[openmeca] 01/05: Import Upstream version 2.2.5

Damien André damien-andre-guest at moszumanska.debian.org
Mon Apr 17 17:35:02 UTC 2017


This is an automated email from the git hooks/post-receive script.

damien-andre-guest pushed a commit to branch master
in repository openmeca.

commit b9f9d0eed2799c3a6be808586f9a54ff2315c32b
Author: Damien Andre <dada at yakuru.fr>
Date:   Mon Apr 17 14:12:21 2017 +0200

    Import Upstream version 2.2.5
---
 LICENSE                                            |   689 +
 Makefile                                           |   155 +
 README.md                                          |    92 +
 SRC/ChronoEngine/ChronoEngine.pro                  |   746 +
 SRC/ChronoEngine/License                           |    10 +
 SRC/ChronoEngine/collision/ChCCollisionInfo.h      |    86 +
 SRC/ChronoEngine/collision/ChCCollisionModel.cpp   |   146 +
 SRC/ChronoEngine/collision/ChCCollisionModel.h     |   325 +
 SRC/ChronoEngine/collision/ChCCollisionPair.h      |   217 +
 SRC/ChronoEngine/collision/ChCCollisionSystem.h    |   208 +
 .../collision/ChCCollisionSystemBullet.cpp         |   256 +
 .../collision/ChCCollisionSystemBullet.h           |   117 +
 SRC/ChronoEngine/collision/ChCCollisionUtils.cpp   |   208 +
 SRC/ChronoEngine/collision/ChCCollisionUtils.h     |    85 +
 SRC/ChronoEngine/collision/ChCModelBullet.cpp      |   723 +
 SRC/ChronoEngine/collision/ChCModelBullet.h        |   209 +
 SRC/ChronoEngine/collision/ChCModelBulletBody.cpp  |    75 +
 SRC/ChronoEngine/collision/ChCModelBulletBody.h    |    85 +
 SRC/ChronoEngine/collision/ChCModelBulletDEM.cpp   |    72 +
 SRC/ChronoEngine/collision/ChCModelBulletDEM.h     |    85 +
 SRC/ChronoEngine/collision/ChCModelBulletNode.cpp  |    98 +
 SRC/ChronoEngine/collision/ChCModelBulletNode.h    |    93 +
 .../collision/ChCModelBulletParticle.cpp           |    82 +
 .../collision/ChCModelBulletParticle.h             |    88 +
 .../collision/ChCModelSphereSetBody.cpp            |    78 +
 SRC/ChronoEngine/collision/ChCModelSphereSetBody.h |    84 +
 .../BroadphaseCollision/btAxisSweep3.cpp           |    38 +
 .../BroadphaseCollision/btAxisSweep3.h             |  1051 +
 .../BroadphaseCollision/btBroadphaseInterface.h    |    82 +
 .../BroadphaseCollision/btBroadphaseProxy.cpp      |    17 +
 .../BroadphaseCollision/btBroadphaseProxy.h        |   271 +
 .../BroadphaseCollision/btCollisionAlgorithm.cpp   |    23 +
 .../BroadphaseCollision/btCollisionAlgorithm.h     |    80 +
 .../BulletCollision/BroadphaseCollision/btDbvt.cpp |  1295 +
 .../BulletCollision/BroadphaseCollision/btDbvt.h   |  1256 +
 .../BroadphaseCollision/btDbvtBroadphase.cpp       |   796 +
 .../BroadphaseCollision/btDbvtBroadphase.h         |   146 +
 .../BroadphaseCollision/btDispatcher.cpp           |    22 +
 .../BroadphaseCollision/btDispatcher.h             |   108 +
 .../BroadphaseCollision/btMultiSapBroadphase.cpp   |   489 +
 .../BroadphaseCollision/btMultiSapBroadphase.h     |   151 +
 .../BroadphaseCollision/btOverlappingPairCache.cpp |   633 +
 .../BroadphaseCollision/btOverlappingPairCache.h   |   469 +
 .../btOverlappingPairCallback.h                    |    40 +
 .../BroadphaseCollision/btQuantizedBvh.cpp         |  1375 +
 .../BroadphaseCollision/btQuantizedBvh.h           |   579 +
 .../BroadphaseCollision/btSimpleBroadphase.cpp     |   349 +
 .../BroadphaseCollision/btSimpleBroadphase.h       |   171 +
 .../CollisionDispatch/SphereTriangleDetector.cpp   |   209 +
 .../CollisionDispatch/SphereTriangleDetector.h     |    51 +
 .../btActivatingCollisionAlgorithm.cpp             |    47 +
 .../btActivatingCollisionAlgorithm.h               |    36 +
 .../btBox2dBox2dCollisionAlgorithm.cpp             |   435 +
 .../btBox2dBox2dCollisionAlgorithm.h               |    66 +
 .../btBoxBoxCollisionAlgorithm.cpp                 |    85 +
 .../CollisionDispatch/btBoxBoxCollisionAlgorithm.h |    66 +
 .../CollisionDispatch/btBoxBoxDetector.cpp         |   718 +
 .../CollisionDispatch/btBoxBoxDetector.h           |    44 +
 .../CollisionDispatch/btCollisionConfiguration.h   |    47 +
 .../CollisionDispatch/btCollisionCreateFunc.h      |    45 +
 .../CollisionDispatch/btCollisionDispatcher.cpp    |   303 +
 .../CollisionDispatch/btCollisionDispatcher.h      |   159 +
 .../CollisionDispatch/btCollisionObject.cpp        |   116 +
 .../CollisionDispatch/btCollisionObject.h          |   524 +
 .../CollisionDispatch/btCollisionWorld.cpp         |  1432 +
 .../CollisionDispatch/btCollisionWorld.h           |   509 +
 .../btCompoundCollisionAlgorithm.cpp               |   353 +
 .../btCompoundCollisionAlgorithm.h                 |    86 +
 .../btConvex2dConvex2dAlgorithm.cpp                |   247 +
 .../btConvex2dConvex2dAlgorithm.h                  |    95 +
 .../btConvexConcaveCollisionAlgorithm.cpp          |   321 +
 .../btConvexConcaveCollisionAlgorithm.h            |   116 +
 .../CollisionDispatch/btConvexConvexAlgorithm.cpp  |   580 +
 .../CollisionDispatch/btConvexConvexAlgorithm.h    |   109 +
 .../btConvexPlaneCollisionAlgorithm.cpp            |   155 +
 .../btConvexPlaneCollisionAlgorithm.h              |    84 +
 .../btDefaultCollisionConfiguration.cpp            |   298 +
 .../btDefaultCollisionConfiguration.h              |   135 +
 .../btEmptyCollisionAlgorithm.cpp                  |    34 +
 .../CollisionDispatch/btEmptyCollisionAlgorithm.h  |    54 +
 .../CollisionDispatch/btGhostObject.cpp            |   171 +
 .../CollisionDispatch/btGhostObject.h              |   175 +
 .../CollisionDispatch/btInternalEdgeUtility.cpp    |   772 +
 .../CollisionDispatch/btInternalEdgeUtility.h      |    46 +
 .../CollisionDispatch/btManifoldResult.cpp         |   134 +
 .../CollisionDispatch/btManifoldResult.h           |   128 +
 .../btSimulationIslandManager.cpp                  |   443 +
 .../CollisionDispatch/btSimulationIslandManager.h  |    81 +
 .../btSphereBoxCollisionAlgorithm.cpp              |   260 +
 .../btSphereBoxCollisionAlgorithm.h                |    75 +
 .../btSphereSphereCollisionAlgorithm.cpp           |   105 +
 .../btSphereSphereCollisionAlgorithm.h             |    66 +
 .../btSphereTriangleCollisionAlgorithm.cpp         |    84 +
 .../btSphereTriangleCollisionAlgorithm.h           |    69 +
 .../CollisionDispatch/btUnionFind.cpp              |    82 +
 .../CollisionDispatch/btUnionFind.h                |   129 +
 .../CollisionShapes/btBarrelShape.cpp              |   131 +
 .../CollisionShapes/btBarrelShape.h                |    71 +
 .../CollisionShapes/btBox2dShape.cpp               |    42 +
 .../BulletCollision/CollisionShapes/btBox2dShape.h |   363 +
 .../BulletCollision/CollisionShapes/btBoxShape.cpp |    41 +
 .../BulletCollision/CollisionShapes/btBoxShape.h   |   318 +
 .../CollisionShapes/btBvhTriangleMeshShape.cpp     |   466 +
 .../CollisionShapes/btBvhTriangleMeshShape.h       |   139 +
 .../CollisionShapes/btCapsuleShape.cpp             |   171 +
 .../CollisionShapes/btCapsuleShape.h               |   173 +
 .../CollisionShapes/btCollisionMargin.h            |    26 +
 .../CollisionShapes/btCollisionShape.cpp           |   123 +
 .../CollisionShapes/btCollisionShape.h             |   150 +
 .../CollisionShapes/btCompoundShape.cpp            |   351 +
 .../CollisionShapes/btCompoundShape.h              |   208 +
 .../CollisionShapes/btConcaveShape.cpp             |    27 +
 .../CollisionShapes/btConcaveShape.h               |    60 +
 .../CollisionShapes/btConeShape.cpp                |   133 +
 .../BulletCollision/CollisionShapes/btConeShape.h  |   100 +
 .../CollisionShapes/btConvex2dShape.cpp            |    92 +
 .../CollisionShapes/btConvex2dShape.h              |    80 +
 .../CollisionShapes/btConvexHullShape.cpp          |   211 +
 .../CollisionShapes/btConvexHullShape.h            |   120 +
 .../CollisionShapes/btConvexInternalShape.cpp      |   151 +
 .../CollisionShapes/btConvexInternalShape.h        |   202 +
 .../CollisionShapes/btConvexPointCloudShape.cpp    |   157 +
 .../CollisionShapes/btConvexPointCloudShape.h      |   105 +
 .../CollisionShapes/btConvexShape.cpp              |   429 +
 .../CollisionShapes/btConvexShape.h                |    82 +
 .../CollisionShapes/btConvexTriangleMeshShape.cpp  |   315 +
 .../CollisionShapes/btConvexTriangleMeshShape.h    |    75 +
 .../CollisionShapes/btCylinderShape.cpp            |   222 +
 .../CollisionShapes/btCylinderShape.h              |   200 +
 .../CollisionShapes/btEmptyShape.cpp               |    50 +
 .../BulletCollision/CollisionShapes/btEmptyShape.h |    70 +
 .../CollisionShapes/btHeightfieldTerrainShape.cpp  |   411 +
 .../CollisionShapes/btHeightfieldTerrainShape.h    |   161 +
 .../BulletCollision/CollisionShapes/btMaterial.h   |    35 +
 .../CollisionShapes/btMinkowskiSumShape.cpp        |    60 +
 .../CollisionShapes/btMinkowskiSumShape.h          |    60 +
 .../CollisionShapes/btMultiSphereShape.cpp         |   167 +
 .../CollisionShapes/btMultiSphereShape.h           |    99 +
 .../btMultimaterialTriangleMeshShape.cpp           |    45 +
 .../btMultimaterialTriangleMeshShape.h             |   121 +
 .../CollisionShapes/btOptimizedBvh.cpp             |   391 +
 .../CollisionShapes/btOptimizedBvh.h               |    65 +
 .../CollisionShapes/btPolyhedralConvexShape.cpp    |   193 +
 .../CollisionShapes/btPolyhedralConvexShape.h      |    98 +
 .../btScaledBvhTriangleMeshShape.cpp               |   121 +
 .../CollisionShapes/btScaledBvhTriangleMeshShape.h |    62 +
 .../CollisionShapes/btShapeHull.cpp                |   170 +
 .../BulletCollision/CollisionShapes/btShapeHull.h  |    59 +
 .../CollisionShapes/btSphereShape.cpp              |    71 +
 .../CollisionShapes/btSphereShape.h                |    73 +
 .../CollisionShapes/btStaticPlaneShape.cpp         |   107 +
 .../CollisionShapes/btStaticPlaneShape.h           |   103 +
 .../CollisionShapes/btStridingMeshInterface.cpp    |   331 +
 .../CollisionShapes/btStridingMeshInterface.h      |   154 +
 .../CollisionShapes/btTetrahedronShape.cpp         |   218 +
 .../CollisionShapes/btTetrahedronShape.h           |    74 +
 .../CollisionShapes/btTriangleBuffer.cpp           |    35 +
 .../CollisionShapes/btTriangleBuffer.h             |    69 +
 .../CollisionShapes/btTriangleCallback.cpp         |    28 +
 .../CollisionShapes/btTriangleCallback.h           |    42 +
 .../CollisionShapes/btTriangleIndexVertexArray.cpp |    95 +
 .../CollisionShapes/btTriangleIndexVertexArray.h   |   131 +
 .../btTriangleIndexVertexMaterialArray.cpp         |    86 +
 .../btTriangleIndexVertexMaterialArray.h           |    84 +
 .../CollisionShapes/btTriangleInfoMap.h            |   238 +
 .../CollisionShapes/btTriangleMesh.cpp             |   140 +
 .../CollisionShapes/btTriangleMesh.h               |    69 +
 .../CollisionShapes/btTriangleMeshShape.cpp        |   211 +
 .../CollisionShapes/btTriangleMeshShape.h          |    89 +
 .../CollisionShapes/btTriangleShape.h              |   182 +
 .../CollisionShapes/btUniformScalingShape.cpp      |   115 +
 .../CollisionShapes/btUniformScalingShape.h        |    87 +
 .../collision/bullet/BulletCollision/Doxyfile      |   746 +
 .../collision/bullet/BulletCollision/Jamfile       |    12 +
 .../btContinuousConvexCollision.cpp                |   236 +
 .../btContinuousConvexCollision.h                  |    52 +
 .../NarrowPhaseCollision/btConvexCast.cpp          |    20 +
 .../NarrowPhaseCollision/btConvexCast.h            |    73 +
 .../btConvexPenetrationDepthSolver.h               |    42 +
 .../btDiscreteCollisionDetectorInterface.h         |    89 +
 .../NarrowPhaseCollision/btGjkConvexCast.cpp       |   176 +
 .../NarrowPhaseCollision/btGjkConvexCast.h         |    50 +
 .../NarrowPhaseCollision/btGjkEpa2.cpp             |   989 +
 .../NarrowPhaseCollision/btGjkEpa2.h               |    73 +
 .../btGjkEpaPenetrationDepthSolver.cpp             |    66 +
 .../btGjkEpaPenetrationDepthSolver.h               |    43 +
 .../NarrowPhaseCollision/btGjkPairDetector.cpp     |   456 +
 .../NarrowPhaseCollision/btGjkPairDetector.h       |   103 +
 .../NarrowPhaseCollision/btManifoldPoint.h         |   157 +
 .../btMinkowskiPenetrationDepthSolver.cpp          |   362 +
 .../btMinkowskiPenetrationDepthSolver.h            |    40 +
 .../NarrowPhaseCollision/btPersistentManifold.cpp  |   261 +
 .../NarrowPhaseCollision/btPersistentManifold.h    |   253 +
 .../NarrowPhaseCollision/btPointCollector.h        |    64 +
 .../NarrowPhaseCollision/btRaycastCallback.cpp     |   175 +
 .../NarrowPhaseCollision/btRaycastCallback.h       |    71 +
 .../btSimplexSolverInterface.h                     |    63 +
 .../btSubSimplexConvexCast.cpp                     |   160 +
 .../NarrowPhaseCollision/btSubSimplexConvexCast.h  |    50 +
 .../btVoronoiSimplexSolver.cpp                     |   609 +
 .../NarrowPhaseCollision/btVoronoiSimplexSolver.h  |   178 +
 .../collision/bullet/BulletFileLoader/bChunk.cpp   |    75 +
 .../collision/bullet/BulletFileLoader/bChunk.h     |    92 +
 .../collision/bullet/BulletFileLoader/bCommon.h    |    39 +
 .../collision/bullet/BulletFileLoader/bDNA.cpp     |   636 +
 .../collision/bullet/BulletFileLoader/bDNA.h       |   110 +
 .../collision/bullet/BulletFileLoader/bDefines.h   |   140 +
 .../collision/bullet/BulletFileLoader/bFile.cpp    |  1354 +
 .../collision/bullet/BulletFileLoader/bFile.h      |   154 +
 .../bullet/BulletFileLoader/btBulletFile.cpp       |   397 +
 .../bullet/BulletFileLoader/btBulletFile.h         |    79 +
 .../BulletWorldImporter/btBulletWorldImporter.cpp  |  1233 +
 .../BulletWorldImporter/btBulletWorldImporter.h    |   188 +
 .../collision/bullet/LinearMath/Jamfile            |    10 +
 .../collision/bullet/LinearMath/btAabbUtil2.h      |   236 +
 .../bullet/LinearMath/btAlignedAllocator.cpp       |   182 +
 .../bullet/LinearMath/btAlignedAllocator.h         |   107 +
 .../bullet/LinearMath/btAlignedObjectArray.h       |   471 +
 .../collision/bullet/LinearMath/btConvexHull.cpp   |  1174 +
 .../collision/bullet/LinearMath/btConvexHull.h     |   241 +
 .../bullet/LinearMath/btDefaultMotionState.h       |    40 +
 .../collision/bullet/LinearMath/btGeometryUtil.cpp |   185 +
 .../collision/bullet/LinearMath/btGeometryUtil.h   |    42 +
 .../collision/bullet/LinearMath/btHashMap.h        |   434 +
 .../collision/bullet/LinearMath/btIDebugDraw.h     |   316 +
 .../collision/bullet/LinearMath/btList.h           |    73 +
 .../collision/bullet/LinearMath/btMatrix3x3.h      |   688 +
 .../collision/bullet/LinearMath/btMinMax.h         |    71 +
 .../collision/bullet/LinearMath/btMotionState.h    |    40 +
 .../collision/bullet/LinearMath/btPoolAllocator.h  |   116 +
 .../collision/bullet/LinearMath/btQuadWord.h       |   180 +
 .../collision/bullet/LinearMath/btQuaternion.h     |   433 +
 .../collision/bullet/LinearMath/btQuickprof.cpp    |   565 +
 .../collision/bullet/LinearMath/btQuickprof.h      |   196 +
 .../collision/bullet/LinearMath/btRandom.h         |    42 +
 .../collision/bullet/LinearMath/btScalar.h         |   524 +
 .../collision/bullet/LinearMath/btSerializer.cpp   |   577 +
 .../collision/bullet/LinearMath/btSerializer.h     |   606 +
 .../collision/bullet/LinearMath/btStackAlloc.h     |   116 +
 .../collision/bullet/LinearMath/btTransform.h      |   307 +
 .../collision/bullet/LinearMath/btTransformUtil.h  |   228 +
 .../collision/bullet/LinearMath/btVector3.h        |   766 +
 .../collision/bullet/btBulletCollisionCommon.h     |    68 +
 SRC/ChronoEngine/collision/edgetempest/ChCAABB.cpp |   245 +
 SRC/ChronoEngine/collision/edgetempest/ChCAABB.h   |   143 +
 .../collision/edgetempest/ChCAABBTree.cpp          |   314 +
 .../collision/edgetempest/ChCAABBTree.h            |    99 +
 .../collision/edgetempest/ChCAABBcollider.cpp      |   195 +
 .../collision/edgetempest/ChCAABBcollider.h        |    95 +
 .../collision/edgetempest/ChCAbsoluteAABB.h        |   124 +
 .../collision/edgetempest/ChCBroadPhaseCollider.h  |    97 +
 .../collision/edgetempest/ChCBruteForce.h          |   145 +
 .../collision/edgetempest/ChCCollisionTree.cpp     |   158 +
 .../collision/edgetempest/ChCCollisionTree.h       |   192 +
 .../collision/edgetempest/ChCCompile.h             |    67 +
 .../collision/edgetempest/ChCGeometryCollider.cpp  |  1434 +
 .../collision/edgetempest/ChCGeometryCollider.h    |   164 +
 .../collision/edgetempest/ChCGetTime.h             |    52 +
 SRC/ChronoEngine/collision/edgetempest/ChCMatVec.h |   889 +
 SRC/ChronoEngine/collision/edgetempest/ChCMates.h  |   106 +
 .../edgetempest/ChCNarrowPhaseCollider.cpp         |   123 +
 .../collision/edgetempest/ChCNarrowPhaseCollider.h |   162 +
 SRC/ChronoEngine/collision/edgetempest/ChCOBB.cpp  |   253 +
 SRC/ChronoEngine/collision/edgetempest/ChCOBB.h    |   123 +
 .../collision/edgetempest/ChCOBBTree.cpp           |   418 +
 .../collision/edgetempest/ChCOBBTree.h             |    95 +
 .../collision/edgetempest/ChCOBBcollider.cpp       |   212 +
 .../collision/edgetempest/ChCOBBcollider.h         |    94 +
 .../collision/edgetempest/ChCSweepAndPrune.h       |   433 +
 .../gimpact/ConvexDecomposition/ConvexBuilder.cpp  |   373 +
 .../gimpact/ConvexDecomposition/ConvexBuilder.h    |   112 +
 .../ConvexDecomposition/ConvexDecomposition.cpp    |   375 +
 .../ConvexDecomposition/ConvexDecomposition.h      |   220 +
 .../collision/gimpact/ConvexDecomposition/Jamfile  |    12 +
 .../gimpact/ConvexDecomposition/bestfit.cpp        |   466 +
 .../gimpact/ConvexDecomposition/bestfit.h          |    65 +
 .../gimpact/ConvexDecomposition/bestfitobb.cpp     |   173 +
 .../gimpact/ConvexDecomposition/bestfitobb.h       |    43 +
 .../gimpact/ConvexDecomposition/cd_hull.cpp        |  3257 ++
 .../gimpact/ConvexDecomposition/cd_hull.h          |   153 +
 .../gimpact/ConvexDecomposition/cd_vector.h        |  1185 +
 .../gimpact/ConvexDecomposition/cd_wavefront.cpp   |   860 +
 .../gimpact/ConvexDecomposition/cd_wavefront.h     |    62 +
 .../gimpact/ConvexDecomposition/concavity.cpp      |   795 +
 .../gimpact/ConvexDecomposition/concavity.h        |    60 +
 .../gimpact/ConvexDecomposition/fitsphere.cpp      |   202 +
 .../gimpact/ConvexDecomposition/fitsphere.h        |    43 +
 .../gimpact/ConvexDecomposition/float_math.cpp     |   257 +
 .../gimpact/ConvexDecomposition/float_math.h       |    72 +
 .../gimpact/ConvexDecomposition/meshvolume.cpp     |   128 +
 .../gimpact/ConvexDecomposition/meshvolume.h       |    45 +
 .../gimpact/ConvexDecomposition/planetri.cpp       |   238 +
 .../gimpact/ConvexDecomposition/planetri.h         |    58 +
 .../gimpact/ConvexDecomposition/raytri.cpp         |   134 +
 .../collision/gimpact/ConvexDecomposition/raytri.h |    45 +
 .../gimpact/ConvexDecomposition/splitplane.cpp     |   306 +
 .../gimpact/ConvexDecomposition/splitplane.h       |    59 +
 .../gimpact/ConvexDecomposition/vlookup.cpp        |   307 +
 .../gimpact/ConvexDecomposition/vlookup.h          |   119 +
 .../gimpact/GIMPACT/Bullet/btBoxCollision.h        |   647 +
 .../gimpact/GIMPACT/Bullet/btClipPolygon.h         |   182 +
 .../gimpact/GIMPACT/Bullet/btContactProcessing.cpp |   181 +
 .../gimpact/GIMPACT/Bullet/btContactProcessing.h   |   145 +
 .../gimpact/GIMPACT/Bullet/btGImpactBvh.cpp        |   498 +
 .../gimpact/GIMPACT/Bullet/btGImpactBvh.h          |   396 +
 .../GIMPACT/Bullet/btGImpactCollisionAlgorithm.cpp |   902 +
 .../GIMPACT/Bullet/btGImpactCollisionAlgorithm.h   |   306 +
 .../gimpact/GIMPACT/Bullet/btGImpactMassUtil.h     |    60 +
 .../GIMPACT/Bullet/btGImpactQuantizedBvh.cpp       |   528 +
 .../gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.h |   372 +
 .../gimpact/GIMPACT/Bullet/btGImpactShape.cpp      |   183 +
 .../gimpact/GIMPACT/Bullet/btGImpactShape.h        |  1124 +
 .../GIMPACT/Bullet/btGenericPoolAllocator.cpp      |   283 +
 .../GIMPACT/Bullet/btGenericPoolAllocator.h        |   163 +
 .../gimpact/GIMPACT/Bullet/btGeometryOperations.h  |   212 +
 .../gimpact/GIMPACT/Bullet/btQuantization.h        |    88 +
 .../gimpact/GIMPACT/Bullet/btTriangleShapeEx.cpp   |   218 +
 .../gimpact/GIMPACT/Bullet/btTriangleShapeEx.h     |   180 +
 .../collision/gimpact/GIMPACT/core/gim_array.h     |   326 +
 .../GIMPACT/core/gim_basic_geometry_operations.h   |   543 +
 .../collision/gimpact/GIMPACT/core/gim_bitset.h    |   123 +
 .../gimpact/GIMPACT/core/gim_box_collision.h       |   590 +
 .../collision/gimpact/GIMPACT/core/gim_box_set.cpp |   182 +
 .../collision/gimpact/GIMPACT/core/gim_box_set.h   |   671 +
 .../gimpact/GIMPACT/core/gim_clip_polygon.h        |   210 +
 .../collision/gimpact/GIMPACT/core/gim_contact.cpp |   146 +
 .../collision/gimpact/GIMPACT/core/gim_contact.h   |   164 +
 .../gimpact/GIMPACT/core/gim_geom_types.h          |    97 +
 .../collision/gimpact/GIMPACT/core/gim_geometry.h  |    42 +
 .../gimpact/GIMPACT/core/gim_hash_table.h          |   902 +
 .../gimpact/GIMPACT/core/gim_linear_math.h         |  1573 +
 .../collision/gimpact/GIMPACT/core/gim_math.h      |   157 +
 .../collision/gimpact/GIMPACT/core/gim_memory.cpp  |   135 +
 .../collision/gimpact/GIMPACT/core/gim_memory.h    |   190 +
 .../collision/gimpact/GIMPACT/core/gim_radixsort.h |   406 +
 .../gimpact/GIMPACT/core/gim_tri_collision.cpp     |   640 +
 .../gimpact/GIMPACT/core/gim_tri_collision.h       |   379 +
 .../btGImpactConvexDecompositionShape.cpp          |   240 +
 .../btGImpactConvexDecompositionShape.h            |    87 +
 SRC/ChronoEngine/core/ChApiCE.h                    |    58 +
 SRC/ChronoEngine/core/ChChrono.h                   |    97 +
 SRC/ChronoEngine/core/ChClassRegister.cpp          |    51 +
 SRC/ChronoEngine/core/ChClassRegister.h            |   240 +
 SRC/ChronoEngine/core/ChCoordsys.cpp               |    59 +
 SRC/ChronoEngine/core/ChCoordsys.h                 |   224 +
 SRC/ChronoEngine/core/ChException.h                |    77 +
 SRC/ChronoEngine/core/ChFrame.h                    |   559 +
 SRC/ChronoEngine/core/ChFrameMoving.h              |   592 +
 SRC/ChronoEngine/core/ChHashFunction.h             |   125 +
 SRC/ChronoEngine/core/ChHashTable.h                |   920 +
 SRC/ChronoEngine/core/ChLinearAlgebra.h            |   944 +
 SRC/ChronoEngine/core/ChLists.h                    |   288 +
 SRC/ChronoEngine/core/ChLog.cpp                    |   110 +
 SRC/ChronoEngine/core/ChLog.h                      |   173 +
 SRC/ChronoEngine/core/ChMath.h                     |    45 +
 SRC/ChronoEngine/core/ChMathematics.cpp            |   132 +
 SRC/ChronoEngine/core/ChMathematics.h              |   131 +
 SRC/ChronoEngine/core/ChMatrix.cpp                 |    69 +
 SRC/ChronoEngine/core/ChMatrix.h                   |  2125 ++
 SRC/ChronoEngine/core/ChMemory.cpp                 |  1757 +
 SRC/ChronoEngine/core/ChMemory.h                   |   207 +
 SRC/ChronoEngine/core/ChMemorynomgr.h              |    65 +
 SRC/ChronoEngine/core/ChPlatform.h                 |    54 +
 SRC/ChronoEngine/core/ChQuaternion.cpp             |   478 +
 SRC/ChronoEngine/core/ChQuaternion.h               |   677 +
 SRC/ChronoEngine/core/ChRealtimeStep.h             |    96 +
 SRC/ChronoEngine/core/ChRunTimeType.h              |   178 +
 SRC/ChronoEngine/core/ChShared.h                   |   136 +
 SRC/ChronoEngine/core/ChSmartpointers.h            |   368 +
 SRC/ChronoEngine/core/ChSpmatrix.cpp               |  1819 +
 SRC/ChronoEngine/core/ChSpmatrix.h                 |   300 +
 SRC/ChronoEngine/core/ChStream.cpp                 |   869 +
 SRC/ChronoEngine/core/ChStream.h                   |   909 +
 SRC/ChronoEngine/core/ChTimer.h                    |   168 +
 SRC/ChronoEngine/core/ChTransform.h                |   175 +
 SRC/ChronoEngine/core/ChTrasform.h                 |   206 +
 SRC/ChronoEngine/core/ChVector.cpp                 |    56 +
 SRC/ChronoEngine/core/ChVector.h                   |   607 +
 SRC/ChronoEngine/core/ChWrapHashmap.h              |    49 +
 SRC/ChronoEngine/geometry/ChCBox.cpp               |   352 +
 SRC/ChronoEngine/geometry/ChCBox.h                 |   193 +
 SRC/ChronoEngine/geometry/ChCCone.cpp              |    68 +
 SRC/ChronoEngine/geometry/ChCCone.h                |   125 +
 SRC/ChronoEngine/geometry/ChCCylinder.cpp          |    69 +
 SRC/ChronoEngine/geometry/ChCCylinder.h            |   164 +
 SRC/ChronoEngine/geometry/ChCEllipsoid.cpp         |    68 +
 SRC/ChronoEngine/geometry/ChCEllipsoid.h           |   156 +
 SRC/ChronoEngine/geometry/ChCGeometry.cpp          |    85 +
 SRC/ChronoEngine/geometry/ChCGeometry.h            |   185 +
 SRC/ChronoEngine/geometry/ChCLine.cpp              |   295 +
 SRC/ChronoEngine/geometry/ChCLine.h                |   161 +
 SRC/ChronoEngine/geometry/ChCLineCam.cpp           |   262 +
 SRC/ChronoEngine/geometry/ChCLineCam.h             |   217 +
 SRC/ChronoEngine/geometry/ChCLinePoly.cpp          |   204 +
 SRC/ChronoEngine/geometry/ChCLinePoly.h            |   155 +
 SRC/ChronoEngine/geometry/ChCSphere.cpp            |    67 +
 SRC/ChronoEngine/geometry/ChCSphere.h              |   156 +
 SRC/ChronoEngine/geometry/ChCTriangle.cpp          |   261 +
 SRC/ChronoEngine/geometry/ChCTriangle.h            |   190 +
 SRC/ChronoEngine/geometry/ChCTriangleMesh.h        |   123 +
 .../geometry/ChCTriangleMeshConnected.cpp          |   980 +
 .../geometry/ChCTriangleMeshConnected.h            |   163 +
 SRC/ChronoEngine/geometry/ChCTriangleMeshSoup.h    |   129 +
 SRC/ChronoEngine/lcp/ChLcpConstraint.cpp           |   125 +
 SRC/ChronoEngine/lcp/ChLcpConstraint.h             |   410 +
 .../lcp/ChLcpConstraintNodeContactN.cpp            |   125 +
 SRC/ChronoEngine/lcp/ChLcpConstraintNodeContactN.h |   178 +
 .../lcp/ChLcpConstraintNodeFrictionT.cpp           |    68 +
 .../lcp/ChLcpConstraintNodeFrictionT.h             |   132 +
 SRC/ChronoEngine/lcp/ChLcpConstraintThree.cpp      |    85 +
 SRC/ChronoEngine/lcp/ChLcpConstraintThree.h        |   157 +
 .../lcp/ChLcpConstraintThreeBBShaft.cpp            |   172 +
 SRC/ChronoEngine/lcp/ChLcpConstraintThreeBBShaft.h |   280 +
 .../lcp/ChLcpConstraintThreeGeneric.cpp            |   289 +
 SRC/ChronoEngine/lcp/ChLcpConstraintThreeGeneric.h |   301 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwo.cpp        |    84 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwo.h          |   148 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.cpp  |   156 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.h    |   270 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.cpp |    66 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.h   |   141 +
 .../lcp/ChLcpConstraintTwoContactN.cpp             |   125 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoContactN.h  |   194 +
 .../lcp/ChLcpConstraintTwoFriction.cpp             |    72 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoFriction.h  |   140 +
 .../lcp/ChLcpConstraintTwoFrictionApprox.cpp       |    94 +
 .../lcp/ChLcpConstraintTwoFrictionApprox.h         |   178 +
 .../lcp/ChLcpConstraintTwoFrictionT.cpp            |    68 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionT.h |   131 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.cpp |   235 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.h   |   278 +
 .../lcp/ChLcpConstraintTwoGenericBoxed.cpp         |    79 +
 .../lcp/ChLcpConstraintTwoGenericBoxed.h           |   173 +
 .../lcp/ChLcpConstraintTwoRollingN.cpp             |   166 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingN.h  |   199 +
 .../lcp/ChLcpConstraintTwoRollingT.cpp             |    68 +
 SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingT.h  |   130 +
 SRC/ChronoEngine/lcp/ChLcpDirectSolver.h           |    82 +
 SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.cpp        |   367 +
 SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.h          |   108 +
 SRC/ChronoEngine/lcp/ChLcpIterativeBB.cpp          |   767 +
 SRC/ChronoEngine/lcp/ChLcpIterativeBB.h            |   128 +
 SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.cpp      |   227 +
 SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.h        |   101 +
 SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.cpp      |   382 +
 SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.h        |   108 +
 SRC/ChronoEngine/lcp/ChLcpIterativePCG.cpp         |   226 +
 SRC/ChronoEngine/lcp/ChLcpIterativePCG.h           |    96 +
 SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.cpp     |   576 +
 SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.h       |   132 +
 SRC/ChronoEngine/lcp/ChLcpIterativeSOR.cpp         |   229 +
 SRC/ChronoEngine/lcp/ChLcpIterativeSOR.h           |   100 +
 .../lcp/ChLcpIterativeSORmultithread.cpp           |   473 +
 .../lcp/ChLcpIterativeSORmultithread.h             |    92 +
 SRC/ChronoEngine/lcp/ChLcpIterativeSolver.h        |   191 +
 SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.cpp     |   337 +
 SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.h       |   107 +
 SRC/ChronoEngine/lcp/ChLcpKstiffness.h             |   126 +
 SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.cpp    |   206 +
 SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.h      |   159 +
 SRC/ChronoEngine/lcp/ChLcpSimplexSolver.cpp        |   217 +
 SRC/ChronoEngine/lcp/ChLcpSimplexSolver.h          |   124 +
 SRC/ChronoEngine/lcp/ChLcpSolver.cpp               |    42 +
 SRC/ChronoEngine/lcp/ChLcpSolver.h                 |   110 +
 SRC/ChronoEngine/lcp/ChLcpSolverDEM.cpp            |   156 +
 SRC/ChronoEngine/lcp/ChLcpSolverDEM.h              |    98 +
 SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.cpp     |   811 +
 SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.h       |   410 +
 SRC/ChronoEngine/lcp/ChLcpVariables.cpp            |    77 +
 SRC/ChronoEngine/lcp/ChLcpVariables.h              |   240 +
 SRC/ChronoEngine/lcp/ChLcpVariablesBody.cpp        |    56 +
 SRC/ChronoEngine/lcp/ChLcpVariablesBody.h          |   112 +
 SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.cpp |    60 +
 SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.h   |   262 +
 .../lcp/ChLcpVariablesBodySharedMass.cpp           |    56 +
 .../lcp/ChLcpVariablesBodySharedMass.h             |   304 +
 SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.cpp     |    80 +
 SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.h       |   211 +
 SRC/ChronoEngine/lcp/ChLcpVariablesNode.cpp        |    57 +
 SRC/ChronoEngine/lcp/ChLcpVariablesNode.h          |   220 +
 SRC/ChronoEngine/lcp/Empty.cpp                     |     8 +
 .../motion_functions/ChFunction_Base.cpp           |   289 +
 .../motion_functions/ChFunction_Base.h             |   213 +
 .../motion_functions/ChFunction_Const.cpp          |    86 +
 .../motion_functions/ChFunction_Const.h            |    96 +
 .../motion_functions/ChFunction_ConstAcc.cpp       |   175 +
 .../motion_functions/ChFunction_ConstAcc.h         |   103 +
 .../motion_functions/ChFunction_Derive.cpp         |   119 +
 .../motion_functions/ChFunction_Derive.h           |    87 +
 .../motion_functions/ChFunction_Fillet3.cpp        |   163 +
 .../motion_functions/ChFunction_Fillet3.h          |    98 +
 .../motion_functions/ChFunction_Integrate.cpp      |   185 +
 .../motion_functions/ChFunction_Integrate.h        |   101 +
 .../motion_functions/ChFunction_Matlab.cpp         |   111 +
 .../motion_functions/ChFunction_Matlab.h           |    80 +
 .../motion_functions/ChFunction_Mirror.cpp         |   120 +
 .../motion_functions/ChFunction_Mirror.h           |    89 +
 .../motion_functions/ChFunction_Mocap.cpp          |   269 +
 .../motion_functions/ChFunction_Mocap.h            |   102 +
 .../motion_functions/ChFunction_Noise.cpp          |   105 +
 .../motion_functions/ChFunction_Noise.h            |    81 +
 .../motion_functions/ChFunction_Operation.cpp      |   176 +
 .../motion_functions/ChFunction_Operation.h        |   104 +
 .../motion_functions/ChFunction_Oscilloscope.cpp   |   168 +
 .../motion_functions/ChFunction_Oscilloscope.h     |   117 +
 .../motion_functions/ChFunction_Poly.cpp           |   170 +
 .../motion_functions/ChFunction_Poly.h             |    85 +
 .../motion_functions/ChFunction_Poly345.cpp        |   119 +
 .../motion_functions/ChFunction_Poly345.h          |    94 +
 .../motion_functions/ChFunction_Ramp.cpp           |    86 +
 .../motion_functions/ChFunction_Ramp.h             |    98 +
 .../motion_functions/ChFunction_Recorder.cpp       |   444 +
 .../motion_functions/ChFunction_Recorder.h         |    96 +
 .../motion_functions/ChFunction_Repeat.cpp         |   119 +
 .../motion_functions/ChFunction_Repeat.h           |    88 +
 .../motion_functions/ChFunction_Sequence.cpp       |   498 +
 .../motion_functions/ChFunction_Sequence.h         |   167 +
 .../motion_functions/ChFunction_Sigma.cpp          |   131 +
 .../motion_functions/ChFunction_Sigma.h            |    93 +
 .../motion_functions/ChFunction_Sine.cpp           |    90 +
 .../motion_functions/ChFunction_Sine.h             |    92 +
 SRC/ChronoEngine/parallel/ChOpenMP.h               |   171 +
 SRC/ChronoEngine/parallel/ChThreads.cpp            |    46 +
 SRC/ChronoEngine/parallel/ChThreads.h              |   107 +
 SRC/ChronoEngine/parallel/ChThreadsFunct.h         |    73 +
 SRC/ChronoEngine/parallel/ChThreadsPOSIX.cpp       |   227 +
 SRC/ChronoEngine/parallel/ChThreadsPOSIX.h         |   123 +
 SRC/ChronoEngine/parallel/ChThreadsSync.h          |   298 +
 SRC/ChronoEngine/parallel/ChThreadsWIN32.cpp       |   223 +
 SRC/ChronoEngine/parallel/ChThreadsWIN32.h         |   119 +
 SRC/ChronoEngine/physics/ChApidll.cpp              |    60 +
 SRC/ChronoEngine/physics/ChApidll.h                |    58 +
 SRC/ChronoEngine/physics/ChAssembly.cpp            |   937 +
 SRC/ChronoEngine/physics/ChAssembly.h              |   383 +
 SRC/ChronoEngine/physics/ChBody.cpp                |  1200 +
 SRC/ChronoEngine/physics/ChBody.h                  |   681 +
 SRC/ChronoEngine/physics/ChBodyAuxRef.cpp          |   185 +
 SRC/ChronoEngine/physics/ChBodyAuxRef.h            |   131 +
 SRC/ChronoEngine/physics/ChBodyDEM.cpp             |   163 +
 SRC/ChronoEngine/physics/ChBodyDEM.h               |   153 +
 SRC/ChronoEngine/physics/ChConstraint.cpp          |   333 +
 SRC/ChronoEngine/physics/ChConstraint.h            |   302 +
 SRC/ChronoEngine/physics/ChContact.cpp             |   341 +
 SRC/ChronoEngine/physics/ChContact.h               |   192 +
 SRC/ChronoEngine/physics/ChContactContainer.cpp    |   508 +
 SRC/ChronoEngine/physics/ChContactContainer.h      |   156 +
 .../physics/ChContactContainerBase.cpp             |    40 +
 SRC/ChronoEngine/physics/ChContactContainerBase.h  |   175 +
 SRC/ChronoEngine/physics/ChContactContainerDEM.cpp |   307 +
 SRC/ChronoEngine/physics/ChContactContainerDEM.h   |   128 +
 .../physics/ChContactContainerNodes.cpp            |   352 +
 SRC/ChronoEngine/physics/ChContactContainerNodes.h |   141 +
 SRC/ChronoEngine/physics/ChContactDEM.cpp          |   203 +
 SRC/ChronoEngine/physics/ChContactDEM.h            |   169 +
 SRC/ChronoEngine/physics/ChContactNode.cpp         |   257 +
 SRC/ChronoEngine/physics/ChContactNode.h           |   185 +
 SRC/ChronoEngine/physics/ChContactRolling.cpp      |   245 +
 SRC/ChronoEngine/physics/ChContactRolling.h        |   149 +
 SRC/ChronoEngine/physics/ChContinuumMaterial.cpp   |   416 +
 SRC/ChronoEngine/physics/ChContinuumMaterial.h     |   408 +
 SRC/ChronoEngine/physics/ChController.cpp          |   120 +
 SRC/ChronoEngine/physics/ChController.h            |    97 +
 SRC/ChronoEngine/physics/ChControls.cpp            |    78 +
 SRC/ChronoEngine/physics/ChControls.h              |    88 +
 SRC/ChronoEngine/physics/ChConveyor.cpp            |   335 +
 SRC/ChronoEngine/physics/ChConveyor.h              |   165 +
 SRC/ChronoEngine/physics/ChEvents.cpp              |   103 +
 SRC/ChronoEngine/physics/ChEvents.h                |   101 +
 SRC/ChronoEngine/physics/ChExternalObject.h        |   158 +
 SRC/ChronoEngine/physics/ChForce.cpp               |   484 +
 SRC/ChronoEngine/physics/ChForce.h                 |   246 +
 SRC/ChronoEngine/physics/ChFunction.cpp            |    34 +
 SRC/ChronoEngine/physics/ChFunction.h              |    31 +
 SRC/ChronoEngine/physics/ChFx.cpp                  |    34 +
 SRC/ChronoEngine/physics/ChFx.h                    |   157 +
 SRC/ChronoEngine/physics/ChGlobal.cpp              |   102 +
 SRC/ChronoEngine/physics/ChGlobal.h                |   118 +
 SRC/ChronoEngine/physics/ChHistory.cpp             |   340 +
 SRC/ChronoEngine/physics/ChHistory.h               |   137 +
 SRC/ChronoEngine/physics/ChIndexedNodes.cpp        |   167 +
 SRC/ChronoEngine/physics/ChIndexedNodes.h          |   235 +
 SRC/ChronoEngine/physics/ChIndexedParticles.cpp    |   134 +
 SRC/ChronoEngine/physics/ChIndexedParticles.h      |   152 +
 SRC/ChronoEngine/physics/ChIntegrator.cpp          |   331 +
 SRC/ChronoEngine/physics/ChIntegrator.h            |    98 +
 SRC/ChronoEngine/physics/ChIterative.cpp           |   388 +
 SRC/ChronoEngine/physics/ChIterative.h             |    92 +
 SRC/ChronoEngine/physics/ChLimit.cpp               |   361 +
 SRC/ChronoEngine/physics/ChLimit.h                 |   150 +
 SRC/ChronoEngine/physics/ChLink.cpp                |   236 +
 SRC/ChronoEngine/physics/ChLink.h                  |   275 +
 SRC/ChronoEngine/physics/ChLinkBrake.cpp           |   231 +
 SRC/ChronoEngine/physics/ChLinkBrake.h             |   105 +
 SRC/ChronoEngine/physics/ChLinkClearance.cpp       |   290 +
 SRC/ChronoEngine/physics/ChLinkClearance.h         |   119 +
 SRC/ChronoEngine/physics/ChLinkContact.cpp         |    84 +
 SRC/ChronoEngine/physics/ChLinkContact.h           |   125 +
 SRC/ChronoEngine/physics/ChLinkDistance.cpp        |   249 +
 SRC/ChronoEngine/physics/ChLinkDistance.h          |   174 +
 SRC/ChronoEngine/physics/ChLinkEngine.cpp          |   841 +
 SRC/ChronoEngine/physics/ChLinkEngine.h            |   232 +
 SRC/ChronoEngine/physics/ChLinkFastContact.cpp     |   315 +
 SRC/ChronoEngine/physics/ChLinkFastContact.h       |   155 +
 SRC/ChronoEngine/physics/ChLinkGear.cpp            |   406 +
 SRC/ChronoEngine/physics/ChLinkGear.h              |   191 +
 SRC/ChronoEngine/physics/ChLinkGeometric.h         |    81 +
 SRC/ChronoEngine/physics/ChLinkLinActuator.cpp     |   295 +
 SRC/ChronoEngine/physics/ChLinkLinActuator.h       |   123 +
 SRC/ChronoEngine/physics/ChLinkLock.cpp            |  1644 +
 SRC/ChronoEngine/physics/ChLinkLock.h              |   401 +
 SRC/ChronoEngine/physics/ChLinkMarkers.cpp         |   619 +
 SRC/ChronoEngine/physics/ChLinkMarkers.h           |   280 +
 SRC/ChronoEngine/physics/ChLinkMask.cpp            |   513 +
 SRC/ChronoEngine/physics/ChLinkMask.h              |   228 +
 SRC/ChronoEngine/physics/ChLinkMasked.cpp          |   682 +
 SRC/ChronoEngine/physics/ChLinkMasked.h            |   322 +
 SRC/ChronoEngine/physics/ChLinkMate.cpp            |  1078 +
 SRC/ChronoEngine/physics/ChLinkMate.h              |   638 +
 SRC/ChronoEngine/physics/ChLinkNumdiff.cpp         |   294 +
 SRC/ChronoEngine/physics/ChLinkNumdiff.h           |   161 +
 .../physics/ChLinkPneumaticActuator.cpp            |   297 +
 SRC/ChronoEngine/physics/ChLinkPneumaticActuator.h |   137 +
 SRC/ChronoEngine/physics/ChLinkPointSpline.cpp     |   217 +
 SRC/ChronoEngine/physics/ChLinkPointSpline.h       |    97 +
 SRC/ChronoEngine/physics/ChLinkPulley.cpp          |   320 +
 SRC/ChronoEngine/physics/ChLinkPulley.h            |   189 +
 SRC/ChronoEngine/physics/ChLinkRackpinion.cpp      |   163 +
 SRC/ChronoEngine/physics/ChLinkRackpinion.h        |   125 +
 SRC/ChronoEngine/physics/ChLinkScrew.cpp           |   201 +
 SRC/ChronoEngine/physics/ChLinkScrew.h             |    89 +
 SRC/ChronoEngine/physics/ChLinkSpring.cpp          |   252 +
 SRC/ChronoEngine/physics/ChLinkSpring.h            |   163 +
 SRC/ChronoEngine/physics/ChLinkTrajectory.cpp      |   205 +
 SRC/ChronoEngine/physics/ChLinkTrajectory.h        |   109 +
 SRC/ChronoEngine/physics/ChLinkWheel.cpp           |   724 +
 SRC/ChronoEngine/physics/ChLinkWheel.h             |   194 +
 SRC/ChronoEngine/physics/ChLinkforce.cpp           |   213 +
 SRC/ChronoEngine/physics/ChLinkforce.h             |   113 +
 SRC/ChronoEngine/physics/ChLinksAll.h              |    52 +
 SRC/ChronoEngine/physics/ChMarker.cpp              |   485 +
 SRC/ChronoEngine/physics/ChMarker.h                |   323 +
 SRC/ChronoEngine/physics/ChMaterialCouple.h        |    70 +
 SRC/ChronoEngine/physics/ChMaterialSurface.h       |   242 +
 SRC/ChronoEngine/physics/ChMatterSPH.cpp           |   617 +
 SRC/ChronoEngine/physics/ChMatterSPH.h             |   353 +
 SRC/ChronoEngine/physics/ChNlsolver.cpp            |   121 +
 SRC/ChronoEngine/physics/ChNlsolver.h              |   101 +
 SRC/ChronoEngine/physics/ChNodeBody.cpp            |   275 +
 SRC/ChronoEngine/physics/ChNodeBody.h              |   182 +
 SRC/ChronoEngine/physics/ChObject.cpp              |   180 +
 SRC/ChronoEngine/physics/ChObject.h                |   229 +
 SRC/ChronoEngine/physics/ChParticlesClones.cpp     |   576 +
 SRC/ChronoEngine/physics/ChParticlesClones.h       |   384 +
 SRC/ChronoEngine/physics/ChPhysicsItem.cpp         |   108 +
 SRC/ChronoEngine/physics/ChPhysicsItem.h           |   306 +
 SRC/ChronoEngine/physics/ChProbe.cpp               |    78 +
 SRC/ChronoEngine/physics/ChProbe.h                 |    73 +
 SRC/ChronoEngine/physics/ChProplist.h              |    58 +
 .../physics/ChProximityContainerBase.cpp           |    40 +
 .../physics/ChProximityContainerBase.h             |   168 +
 .../physics/ChProximityContainerSPH.cpp            |   288 +
 SRC/ChronoEngine/physics/ChProximityContainerSPH.h |   176 +
 SRC/ChronoEngine/physics/ChRef.cpp                 |   157 +
 SRC/ChronoEngine/physics/ChRef.h                   |   164 +
 SRC/ChronoEngine/physics/ChScriptEngine.h          |    84 +
 SRC/ChronoEngine/physics/ChShaft.cpp               |   307 +
 SRC/ChronoEngine/physics/ChShaft.h                 |   279 +
 SRC/ChronoEngine/physics/ChShaftsBody.cpp          |   226 +
 SRC/ChronoEngine/physics/ChShaftsBody.h            |   191 +
 SRC/ChronoEngine/physics/ChShaftsClutch.cpp        |   238 +
 SRC/ChronoEngine/physics/ChShaftsClutch.h          |   201 +
 SRC/ChronoEngine/physics/ChShaftsCouple.h          |   171 +
 SRC/ChronoEngine/physics/ChShaftsGear.cpp          |   218 +
 SRC/ChronoEngine/physics/ChShaftsGear.h            |   174 +
 SRC/ChronoEngine/physics/ChShaftsMotor.cpp         |   249 +
 SRC/ChronoEngine/physics/ChShaftsMotor.h           |   207 +
 SRC/ChronoEngine/physics/ChShaftsPlanetary.cpp     |   243 +
 SRC/ChronoEngine/physics/ChShaftsPlanetary.h       |   226 +
 SRC/ChronoEngine/physics/ChShaftsTorsionSpring.cpp |   131 +
 SRC/ChronoEngine/physics/ChShaftsTorsionSpring.h   |   153 +
 SRC/ChronoEngine/physics/ChSolver.h                |   198 +
 SRC/ChronoEngine/physics/ChSolvmin.cpp             |  2198 ++
 SRC/ChronoEngine/physics/ChSolvmin.h               |   510 +
 SRC/ChronoEngine/physics/ChStack.h                 |   145 +
 SRC/ChronoEngine/physics/ChSystem.cpp              |  3560 ++
 SRC/ChronoEngine/physics/ChSystem.h                |  1174 +
 SRC/ChronoEngine/physics/ChSystemOpenMP.cpp        |   346 +
 SRC/ChronoEngine/physics/ChSystemOpenMP.h          |    93 +
 SRC/ChronoEngine/physics/ChTensors.h               |   196 +
 SRC/ChronoEngine/pneumatica/assepneumatico.cpp     |   206 +
 SRC/ChronoEngine/pneumatica/assepneumatico.h       |   184 +
 SRC/ChronoEngine/pneumatica/pistone.cpp            |   183 +
 SRC/ChronoEngine/pneumatica/pistone.h              |   123 +
 SRC/ChronoEngine/pneumatica/pistone_3_2.cpp        |   130 +
 SRC/ChronoEngine/pneumatica/pistone_3_2.h          |    66 +
 SRC/ChronoEngine/pneumatica/pistone_3_2_prop.cpp   |   109 +
 SRC/ChronoEngine/pneumatica/pistone_3_2_prop.h     |    61 +
 SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.cpp  |   104 +
 SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.h    |    60 +
 .../pneumatica/sis_attuatore_3_2_prop.cpp          |   253 +
 .../pneumatica/sis_attuatore_3_2_prop.h            |    71 +
 SRC/ChronoEngine/pneumatica/sistema.cpp            |   216 +
 SRC/ChronoEngine/pneumatica/sistema.h              |   163 +
 SRC/ChronoEngine/pneumatica/ugello.cpp             |    91 +
 SRC/ChronoEngine/pneumatica/ugello.h               |   103 +
 SRC/ChronoEngine/pneumatica/ugello_controllato.cpp |    66 +
 SRC/ChronoEngine/pneumatica/ugello_controllato.h   |    64 +
 .../pneumatica/ugello_controllato_PA.cpp           |    59 +
 .../pneumatica/ugello_controllato_PA.h             |    59 +
 .../pneumatica/ugello_controllato_RA.cpp           |    57 +
 .../pneumatica/ugello_controllato_RA.h             |    53 +
 SRC/ChronoEngine/pneumatica/valvola_3_2.cpp        |   132 +
 SRC/ChronoEngine/pneumatica/valvola_3_2.h          |    86 +
 SRC/ChronoEngine/pneumatica/valvola_3_2_prop.cpp   |    88 +
 SRC/ChronoEngine/pneumatica/valvola_3_2_prop.h     |    68 +
 SRC/ChronoEngine/pneumatica/volume.h               |    65 +
 SRC/OpenMeca/Core/Action/Action.cpp                |    58 +
 SRC/OpenMeca/Core/Action/Action.hpp                |    62 +
 SRC/OpenMeca/Core/Action/Action.pro                |    36 +
 SRC/OpenMeca/Core/Action/ActionDeleteUserItem.hpp  |   112 +
 .../Core/Action/ActionEditGlobalSetting.hpp        |    79 +
 SRC/OpenMeca/Core/Action/ActionEditItem.hpp        |    86 +
 .../Core/Action/ActionEditSystemSetting.hpp        |    73 +
 SRC/OpenMeca/Core/Action/ActionNewUserItem.hpp     |    85 +
 .../ActionNewUserItemWithAutomaticSelection.hpp    |    99 +
 .../Core/Action/ActionNewUserItemWithSelection.hpp |    84 +
 .../Core/Action/ActionWithSelectedItem.cpp         |    64 +
 .../Core/Action/ActionWithSelectedItem.hpp         |    61 +
 .../Core/Action/ActionWithSelectedItemT.hpp        |   107 +
 .../Core/Action/ActionWithoutSelection.hpp         |    76 +
 SRC/OpenMeca/Core/AutoRegister.hpp                 |    34 +
 SRC/OpenMeca/Core/AutoRegisteredPtr.hpp            |   262 +
 SRC/OpenMeca/Core/CommonProperty.cpp               |   123 +
 SRC/OpenMeca/Core/CommonProperty.hpp               |    77 +
 SRC/OpenMeca/Core/Condition.hpp                    |   117 +
 SRC/OpenMeca/Core/ConfigDirectory.cpp              |    77 +
 SRC/OpenMeca/Core/ConfigDirectory.hpp              |    62 +
 SRC/OpenMeca/Core/ConfigFile.cpp                   |   142 +
 SRC/OpenMeca/Core/ConfigFile.hpp                   |    68 +
 SRC/OpenMeca/Core/Core.pro                         |    70 +
 SRC/OpenMeca/Core/Drawable.cpp                     |    45 +
 SRC/OpenMeca/Core/Drawable.hpp                     |    55 +
 SRC/OpenMeca/Core/DrawableUserItem.cpp             |   126 +
 SRC/OpenMeca/Core/DrawableUserItem.hpp             |   109 +
 SRC/OpenMeca/Core/GlobalSetting.cpp                |    59 +
 SRC/OpenMeca/Core/GlobalSetting.hpp                |    62 +
 SRC/OpenMeca/Core/GlobalSettingCommonProperty.hpp  |    94 +
 SRC/OpenMeca/Core/GlobalSettingT.hpp               |    65 +
 SRC/OpenMeca/Core/HistoricManager.cpp              |   129 +
 SRC/OpenMeca/Core/HistoricManager.hpp              |    68 +
 SRC/OpenMeca/Core/Item.cpp                         |   161 +
 SRC/OpenMeca/Core/Item.hpp                         |   119 +
 SRC/OpenMeca/Core/ItemCommonProperty.hpp           |   133 +
 SRC/OpenMeca/Core/Macro.cpp                        |    97 +
 SRC/OpenMeca/Core/Macro.hpp                        |   104 +
 SRC/OpenMeca/Core/None.hpp                         |    36 +
 SRC/OpenMeca/Core/SelectionManager.cpp             |   101 +
 SRC/OpenMeca/Core/SelectionManager.hpp             |    70 +
 SRC/OpenMeca/Core/SetOf.cpp                        |    30 +
 SRC/OpenMeca/Core/SetOf.hpp                        |   390 +
 SRC/OpenMeca/Core/SetOfBase.cpp                    |    29 +
 SRC/OpenMeca/Core/SetOfBase.hpp                    |   286 +
 SRC/OpenMeca/Core/Singleton.hpp                    |    98 +
 SRC/OpenMeca/Core/Software.cpp                     |   152 +
 SRC/OpenMeca/Core/Software.hpp                     |    72 +
 SRC/OpenMeca/Core/System.cpp                       |   382 +
 SRC/OpenMeca/Core/System.hpp                       |   173 +
 SRC/OpenMeca/Core/SystemSetting.cpp                |   125 +
 SRC/OpenMeca/Core/SystemSetting.hpp                |    77 +
 SRC/OpenMeca/Core/SystemSettingCommonProperty.hpp  |   101 +
 SRC/OpenMeca/Core/SystemSettingT.hpp               |   134 +
 SRC/OpenMeca/Core/UserItem.cpp                     |   283 +
 SRC/OpenMeca/Core/UserItem.hpp                     |   136 +
 SRC/OpenMeca/Core/UserItemCommonProperty.hpp       |   175 +
 SRC/OpenMeca/Core/UserRootItem.cpp                 |    48 +
 SRC/OpenMeca/Core/UserRootItem.hpp                 |    64 +
 SRC/OpenMeca/Core/UserRootItemCommonProperty.hpp   |    87 +
 SRC/OpenMeca/Core/XmlConfigFile.cpp                |   146 +
 SRC/OpenMeca/Core/XmlConfigFile.hpp                |    69 +
 SRC/OpenMeca/Geom/Coordinate.cpp                   |    37 +
 SRC/OpenMeca/Geom/Coordinate.hpp                   |   572 +
 SRC/OpenMeca/Geom/CoordinateSystem.hpp             |    59 +
 SRC/OpenMeca/Geom/Frame.cpp                        |   188 +
 SRC/OpenMeca/Geom/Frame.hpp                        |   344 +
 SRC/OpenMeca/Geom/Geom.pro                         |    39 +
 SRC/OpenMeca/Geom/Matrix.cpp                       |    65 +
 SRC/OpenMeca/Geom/Matrix.hpp                       |   321 +
 SRC/OpenMeca/Geom/Point.cpp                        |    43 +
 SRC/OpenMeca/Geom/Point.hpp                        |   452 +
 SRC/OpenMeca/Geom/Quaternion.cpp                   |   104 +
 SRC/OpenMeca/Geom/Quaternion.hpp                   |   836 +
 SRC/OpenMeca/Geom/SpaceDim.cpp                     |    37 +
 SRC/OpenMeca/Geom/SpaceDim.hpp                     |    52 +
 SRC/OpenMeca/Geom/Vector.cpp                       |   134 +
 SRC/OpenMeca/Geom/Vector.hpp                       |   851 +
 SRC/OpenMeca/Gui/AbstractTreeItem.cpp              |    77 +
 SRC/OpenMeca/Gui/AbstractTreeItem.hpp              |    71 +
 SRC/OpenMeca/Gui/Dialog/Dialog.cpp                 |   132 +
 SRC/OpenMeca/Gui/Dialog/Dialog.hpp                 |    78 +
 SRC/OpenMeca/Gui/Dialog/Dialog.pro                 |    78 +
 SRC/OpenMeca/Gui/Dialog/DialogBody.cpp             |   115 +
 SRC/OpenMeca/Gui/Dialog/DialogBody.hpp             |    78 +
 SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.cpp  |    73 +
 SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.hpp  |    61 +
 SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.ui   |    93 +
 SRC/OpenMeca/Gui/Dialog/DialogGravity.cpp          |    56 +
 SRC/OpenMeca/Gui/Dialog/DialogGravity.hpp          |    54 +
 SRC/OpenMeca/Gui/Dialog/DialogLink.cpp             |   113 +
 SRC/OpenMeca/Gui/Dialog/DialogLink.hpp             |    71 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkGear.cpp         |    94 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkGear.hpp         |    65 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.cpp  |    62 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.hpp  |    60 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.cpp        |    62 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.hpp        |    60 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.cpp       |    75 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.hpp       |    62 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.cpp   |    81 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.hpp   |    63 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.cpp        |    62 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.hpp        |    60 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.cpp       |    85 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.hpp       |    63 +
 SRC/OpenMeca/Gui/Dialog/DialogLinkT.hpp            |   139 +
 SRC/OpenMeca/Gui/Dialog/DialogLoadT.hpp            |   110 +
 SRC/OpenMeca/Gui/Dialog/DialogNone.hpp             |    46 +
 SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.cpp |    86 +
 SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.hpp |    65 +
 SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.cpp     |    84 +
 SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.hpp     |    70 +
 SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.cpp    |    76 +
 SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.hpp    |    66 +
 SRC/OpenMeca/Gui/Dialog/DialogPartUserShapeT.hpp   |   133 +
 SRC/OpenMeca/Gui/Dialog/DialogScales.cpp           |    80 +
 SRC/OpenMeca/Gui/Dialog/DialogScales.hpp           |    56 +
 SRC/OpenMeca/Gui/Dialog/DialogScene.cpp            |    78 +
 SRC/OpenMeca/Gui/Dialog/DialogScene.hpp            |    62 +
 SRC/OpenMeca/Gui/Dialog/DialogSensorT.hpp          |   104 +
 SRC/OpenMeca/Gui/Dialog/DialogSimulation.cpp       |   172 +
 SRC/OpenMeca/Gui/Dialog/DialogSimulation.hpp       |    73 +
 SRC/OpenMeca/Gui/Dialog/DialogSimulation.ui        |    85 +
 SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.cpp    |    72 +
 SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.hpp    |    52 +
 SRC/OpenMeca/Gui/Dialog/DialogSystemSettingT.hpp   |    87 +
 SRC/OpenMeca/Gui/Dialog/DialogUserItem.cpp         |   163 +
 SRC/OpenMeca/Gui/Dialog/DialogUserItem.hpp         |    80 +
 SRC/OpenMeca/Gui/Dialog/DialogUserItem.ui          |   167 +
 SRC/OpenMeca/Gui/Dialog/DialogUserItemT.hpp        |   175 +
 SRC/OpenMeca/Gui/Dialog/DialogVariable.cpp         |   112 +
 SRC/OpenMeca/Gui/Dialog/DialogVariable.hpp         |    68 +
 SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.cpp     |    56 +
 SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.hpp     |    54 +
 .../Gui/Dialog/Physic/DialogMechanicalAction.cpp   |    61 +
 .../Gui/Dialog/Physic/DialogMechanicalAction.hpp   |    60 +
 SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.cpp    |    56 +
 SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.hpp    |    54 +
 SRC/OpenMeca/Gui/Dialog/Physic/Physic.pro          |    27 +
 SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.cpp   |    70 +
 SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.hpp   |    63 +
 SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.cpp     |    52 +
 SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.hpp     |    63 +
 SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.cpp     |    56 +
 SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.hpp     |    64 +
 SRC/OpenMeca/Gui/Dialog/Shape/Shape.pro            |    29 +
 SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.cpp   |    75 +
 SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.hpp   |    64 +
 SRC/OpenMeca/Gui/ExampleAction.cpp                 |    61 +
 SRC/OpenMeca/Gui/ExampleAction.hpp                 |    53 +
 SRC/OpenMeca/Gui/GeneralSetting.cpp                |   101 +
 SRC/OpenMeca/Gui/GeneralSetting.hpp                |    57 +
 SRC/OpenMeca/Gui/GeneralSetting.ui                 |   144 +
 SRC/OpenMeca/Gui/Gui.pro                           |    55 +
 SRC/OpenMeca/Gui/HelpBrowser.cpp                   |    43 +
 SRC/OpenMeca/Gui/HelpBrowser.hpp                   |    45 +
 SRC/OpenMeca/Gui/ImageDialog.cpp                   |    71 +
 SRC/OpenMeca/Gui/ImageDialog.hpp                   |    55 +
 SRC/OpenMeca/Gui/ImageDialog.ui                    |   178 +
 SRC/OpenMeca/Gui/MainPlotWindow.cpp                |   218 +
 SRC/OpenMeca/Gui/MainPlotWindow.hpp                |    74 +
 SRC/OpenMeca/Gui/MainPlotWindow.ui                 |    86 +
 SRC/OpenMeca/Gui/MainTreeItem.cpp                  |    53 +
 SRC/OpenMeca/Gui/MainTreeItem.hpp                  |    60 +
 SRC/OpenMeca/Gui/MainWindow.cpp                    |   727 +
 SRC/OpenMeca/Gui/MainWindow.hpp                    |   114 +
 SRC/OpenMeca/Gui/MainWindow.ui                     |   267 +
 SRC/OpenMeca/Gui/Player.cpp                        |   175 +
 SRC/OpenMeca/Gui/Player.hpp                        |    78 +
 SRC/OpenMeca/Gui/Player.ui                         |   178 +
 SRC/OpenMeca/Gui/Prop/Prop.cpp                     |   135 +
 SRC/OpenMeca/Gui/Prop/Prop.hpp                     |    77 +
 SRC/OpenMeca/Gui/Prop/Prop.pro                     |    55 +
 SRC/OpenMeca/Gui/Prop/PropAttitude.cpp             |   125 +
 SRC/OpenMeca/Gui/Prop/PropAttitude.hpp             |    74 +
 SRC/OpenMeca/Gui/Prop/PropAxis.cpp                 |   121 +
 SRC/OpenMeca/Gui/Prop/PropAxis.hpp                 |    73 +
 SRC/OpenMeca/Gui/Prop/PropBool.cpp                 |    77 +
 SRC/OpenMeca/Gui/Prop/PropBool.hpp                 |    54 +
 SRC/OpenMeca/Gui/Prop/PropColor.cpp                |    88 +
 SRC/OpenMeca/Gui/Prop/PropColor.hpp                |    61 +
 SRC/OpenMeca/Gui/Prop/PropDouble.cpp               |    97 +
 SRC/OpenMeca/Gui/Prop/PropDouble.hpp               |    67 +
 SRC/OpenMeca/Gui/Prop/PropEnumT.hpp                |   109 +
 SRC/OpenMeca/Gui/Prop/PropExpr.cpp                 |    98 +
 SRC/OpenMeca/Gui/Prop/PropExpr.hpp                 |    65 +
 SRC/OpenMeca/Gui/Prop/PropExprAttitude.cpp         |   135 +
 SRC/OpenMeca/Gui/Prop/PropExprAttitude.hpp         |    79 +
 SRC/OpenMeca/Gui/Prop/PropExprPoint.cpp            |   129 +
 SRC/OpenMeca/Gui/Prop/PropExprPoint.hpp            |    80 +
 SRC/OpenMeca/Gui/Prop/PropMatrix.cpp               |   226 +
 SRC/OpenMeca/Gui/Prop/PropMatrix.hpp               |   104 +
 SRC/OpenMeca/Gui/Prop/PropMotionLaw.cpp            |   118 +
 SRC/OpenMeca/Gui/Prop/PropMotionLaw.hpp            |    69 +
 SRC/OpenMeca/Gui/Prop/PropPoint.cpp                |   120 +
 SRC/OpenMeca/Gui/Prop/PropPoint.hpp                |    75 +
 SRC/OpenMeca/Gui/Prop/PropSelectItemT.hpp          |   129 +
 SRC/OpenMeca/Gui/Prop/PropString.cpp               |    86 +
 SRC/OpenMeca/Gui/Prop/PropString.hpp               |    56 +
 SRC/OpenMeca/Gui/Prop/PropT.hpp                    |   155 +
 SRC/OpenMeca/Gui/Prop/PropTree.cpp                 |    71 +
 SRC/OpenMeca/Gui/Prop/PropTree.hpp                 |    53 +
 SRC/OpenMeca/Gui/Prop/PropVector.cpp               |   120 +
 SRC/OpenMeca/Gui/Prop/PropVector.hpp               |    75 +
 SRC/OpenMeca/Gui/RootTreeItemT.hpp                 |    73 +
 SRC/OpenMeca/Gui/SecondaryTreeItem.cpp             |    67 +
 SRC/OpenMeca/Gui/SecondaryTreeItem.hpp             |    59 +
 SRC/OpenMeca/Gui/TreeView.cpp                      |   100 +
 SRC/OpenMeca/Gui/TreeView.hpp                      |    61 +
 SRC/OpenMeca/Gui/Viewer.cpp                        |   203 +
 SRC/OpenMeca/Gui/Viewer.hpp                        |    64 +
 SRC/OpenMeca/Gui/Widget/Widget.pro                 |    40 +
 SRC/OpenMeca/Gui/Widget/WidgetDouble.cpp           |   149 +
 SRC/OpenMeca/Gui/Widget/WidgetDouble.hpp           |    74 +
 SRC/OpenMeca/Gui/Widget/WidgetDouble.ui            |    69 +
 SRC/OpenMeca/Gui/Widget/WidgetEnum.cpp             |    51 +
 SRC/OpenMeca/Gui/Widget/WidgetEnum.hpp             |    44 +
 SRC/OpenMeca/Gui/Widget/WidgetExpr.cpp             |   151 +
 SRC/OpenMeca/Gui/Widget/WidgetExpr.hpp             |    73 +
 SRC/OpenMeca/Gui/Widget/WidgetExpr.ui              |    85 +
 SRC/OpenMeca/Gui/Widget/WidgetScales.cpp           |   112 +
 SRC/OpenMeca/Gui/Widget/WidgetScales.hpp           |    66 +
 SRC/OpenMeca/Gui/Widget/WidgetScales.ui            |    60 +
 SRC/OpenMeca/Gui/Widget/WidgetSelectItem.cpp       |    93 +
 SRC/OpenMeca/Gui/Widget/WidgetSelectItem.hpp       |    62 +
 SRC/OpenMeca/Gui/Widget/WidgetSelectItem.ui        |    55 +
 SRC/OpenMeca/Gui/Widget/WidgetSelectItemT.hpp      |   166 +
 SRC/OpenMeca/Info.txt                              |     6 +
 SRC/OpenMeca/Item/Body.cpp                         |   415 +
 SRC/OpenMeca/Item/Body.hpp                         |   243 +
 SRC/OpenMeca/Item/How/GetAngAcc.cpp                |    72 +
 SRC/OpenMeca/Item/How/GetAngAcc.hpp                |    67 +
 SRC/OpenMeca/Item/How/GetAngPos.cpp                |    70 +
 SRC/OpenMeca/Item/How/GetAngPos.hpp                |    67 +
 SRC/OpenMeca/Item/How/GetAngVel.cpp                |    72 +
 SRC/OpenMeca/Item/How/GetAngVel.hpp                |    67 +
 SRC/OpenMeca/Item/How/GetLinAcc.cpp                |    78 +
 SRC/OpenMeca/Item/How/GetLinAcc.hpp                |    67 +
 SRC/OpenMeca/Item/How/GetLinPos.cpp                |    67 +
 SRC/OpenMeca/Item/How/GetLinPos.hpp                |    67 +
 SRC/OpenMeca/Item/How/GetLinVel.cpp                |    79 +
 SRC/OpenMeca/Item/How/GetLinVel.hpp                |    67 +
 SRC/OpenMeca/Item/How/GetReacForce.cpp             |    69 +
 SRC/OpenMeca/Item/How/GetReacForce.hpp             |    67 +
 SRC/OpenMeca/Item/How/GetReacTorque.cpp            |    69 +
 SRC/OpenMeca/Item/How/GetReacTorque.hpp            |    67 +
 SRC/OpenMeca/Item/How/How.pro                      |    42 +
 SRC/OpenMeca/Item/How/SetForce.cpp                 |    63 +
 SRC/OpenMeca/Item/How/SetForce.hpp                 |    68 +
 SRC/OpenMeca/Item/How/SetTorque.cpp                |    63 +
 SRC/OpenMeca/Item/How/SetTorque.hpp                |    68 +
 SRC/OpenMeca/Item/Item.pro                         |    62 +
 SRC/OpenMeca/Item/Link.cpp                         |   319 +
 SRC/OpenMeca/Item/Link.hpp                         |   218 +
 SRC/OpenMeca/Item/Link/All.hpp                     |    39 +
 SRC/OpenMeca/Item/Link/Cylindrical.cpp             |   114 +
 SRC/OpenMeca/Item/Link/Cylindrical.hpp             |   103 +
 SRC/OpenMeca/Item/Link/Gear.cpp                    |   148 +
 SRC/OpenMeca/Item/Link/Gear.hpp                    |   153 +
 SRC/OpenMeca/Item/Link/LinearMotor.cpp             |   160 +
 SRC/OpenMeca/Item/Link/LinearMotor.hpp             |   115 +
 SRC/OpenMeca/Item/Link/Link.pro                    |    51 +
 SRC/OpenMeca/Item/Link/LinkTypeBase.cpp            |    70 +
 SRC/OpenMeca/Item/Link/LinkTypeBase.hpp            |    86 +
 SRC/OpenMeca/Item/Link/Motor.cpp                   |   144 +
 SRC/OpenMeca/Item/Link/Motor.hpp                   |   119 +
 SRC/OpenMeca/Item/Link/Planar.cpp                  |   119 +
 SRC/OpenMeca/Item/Link/Planar.hpp                  |    96 +
 SRC/OpenMeca/Item/Link/PointLine.cpp               |   106 +
 SRC/OpenMeca/Item/Link/PointLine.hpp               |    96 +
 SRC/OpenMeca/Item/Link/PointPlane.cpp              |   112 +
 SRC/OpenMeca/Item/Link/PointPlane.hpp              |    98 +
 SRC/OpenMeca/Item/Link/Pulley.cpp                  |   227 +
 SRC/OpenMeca/Item/Link/Pulley.hpp                  |   148 +
 SRC/OpenMeca/Item/Link/RackPinion.cpp              |   137 +
 SRC/OpenMeca/Item/Link/RackPinion.hpp              |   139 +
 SRC/OpenMeca/Item/Link/Revolute.cpp                |   122 +
 SRC/OpenMeca/Item/Link/Revolute.hpp                |    96 +
 SRC/OpenMeca/Item/Link/Screw.cpp                   |   149 +
 SRC/OpenMeca/Item/Link/Screw.hpp                   |   106 +
 SRC/OpenMeca/Item/Link/Slider.cpp                  |   141 +
 SRC/OpenMeca/Item/Link/Slider.hpp                  |    98 +
 SRC/OpenMeca/Item/Link/Spherical.cpp               |   117 +
 SRC/OpenMeca/Item/Link/Spherical.hpp               |    97 +
 SRC/OpenMeca/Item/Link/Spring.cpp                  |   133 +
 SRC/OpenMeca/Item/Link/Spring.hpp                  |   149 +
 SRC/OpenMeca/Item/LinkT.cpp                        |   232 +
 SRC/OpenMeca/Item/LinkT.hpp                        |   324 +
 .../Item/Link_CreateAction_SpecializedT.hpp        |    57 +
 SRC/OpenMeca/Item/Load.cpp                         |    79 +
 SRC/OpenMeca/Item/Load.hpp                         |    68 +
 SRC/OpenMeca/Item/LoadT.cpp                        |    33 +
 SRC/OpenMeca/Item/LoadT.hpp                        |   304 +
 SRC/OpenMeca/Item/Part.cpp                         |    93 +
 SRC/OpenMeca/Item/Part.hpp                         |    80 +
 SRC/OpenMeca/Item/PartLinkT.cpp                    |   101 +
 SRC/OpenMeca/Item/PartLinkT.hpp                    |   396 +
 SRC/OpenMeca/Item/PartPoint.cpp                    |   143 +
 SRC/OpenMeca/Item/PartPoint.hpp                    |   121 +
 .../Item/PartPoint_CreateAction_SpecializedT.hpp   |   111 +
 SRC/OpenMeca/Item/PartUser.cpp                     |   147 +
 SRC/OpenMeca/Item/PartUser.hpp                     |   104 +
 SRC/OpenMeca/Item/PartUserJunction.cpp             |   169 +
 SRC/OpenMeca/Item/PartUserJunction.hpp             |   135 +
 SRC/OpenMeca/Item/PartUserPipe.cpp                 |   159 +
 SRC/OpenMeca/Item/PartUserPipe.hpp                 |   141 +
 SRC/OpenMeca/Item/PartUserPoint.cpp                |   102 +
 SRC/OpenMeca/Item/PartUserPoint.hpp                |   134 +
 SRC/OpenMeca/Item/PartUserShape.cpp                |    77 +
 SRC/OpenMeca/Item/PartUserShape.hpp                |    89 +
 SRC/OpenMeca/Item/PartUserShapeT.hpp               |   249 +
 SRC/OpenMeca/Item/Physical.cpp                     |   142 +
 SRC/OpenMeca/Item/Physical.hpp                     |    90 +
 SRC/OpenMeca/Item/Sensor.cpp                       |    86 +
 SRC/OpenMeca/Item/Sensor.hpp                       |    70 +
 SRC/OpenMeca/Item/SensorT.cpp                      |    35 +
 SRC/OpenMeca/Item/SensorT.hpp                      |   293 +
 SRC/OpenMeca/Item/Shape/Box.cpp                    |   100 +
 SRC/OpenMeca/Item/Shape/Box.hpp                    |   111 +
 SRC/OpenMeca/Item/Shape/Cylinder.cpp               |   103 +
 SRC/OpenMeca/Item/Shape/Cylinder.hpp               |   105 +
 SRC/OpenMeca/Item/Shape/Ground.cpp                 |    91 +
 SRC/OpenMeca/Item/Shape/Ground.hpp                 |    93 +
 SRC/OpenMeca/Item/Shape/Shape.pro                  |    31 +
 SRC/OpenMeca/Item/Shape/ShapeBase.cpp              |    49 +
 SRC/OpenMeca/Item/Shape/ShapeBase.hpp              |    74 +
 SRC/OpenMeca/Item/Shape/Sphere.cpp                 |    92 +
 SRC/OpenMeca/Item/Shape/Sphere.hpp                 |    98 +
 SRC/OpenMeca/Item/Variable.cpp                     |    67 +
 SRC/OpenMeca/Item/Variable.hpp                     |   102 +
 SRC/OpenMeca/Main.cpp                              |    62 +
 SRC/OpenMeca/Note.txt                              |   153 +
 SRC/OpenMeca/OpenMeca.pro                          |    83 +
 SRC/OpenMeca/Physic/AngularAcceleration.cpp        |    77 +
 SRC/OpenMeca/Physic/AngularAcceleration.hpp        |    94 +
 SRC/OpenMeca/Physic/AngularPosition.cpp            |    78 +
 SRC/OpenMeca/Physic/AngularPosition.hpp            |    94 +
 SRC/OpenMeca/Physic/AngularVelocity.cpp            |    77 +
 SRC/OpenMeca/Physic/AngularVelocity.hpp            |    94 +
 SRC/OpenMeca/Physic/Double.cpp                     |   128 +
 SRC/OpenMeca/Physic/Double.hpp                     |   115 +
 SRC/OpenMeca/Physic/Enum.hpp                       |    43 +
 SRC/OpenMeca/Physic/Force.cpp                      |    79 +
 SRC/OpenMeca/Physic/Force.hpp                      |   100 +
 SRC/OpenMeca/Physic/LinearAcceleration.cpp         |    77 +
 SRC/OpenMeca/Physic/LinearAcceleration.hpp         |    94 +
 SRC/OpenMeca/Physic/LinearPosition.cpp             |   100 +
 SRC/OpenMeca/Physic/LinearPosition.hpp             |    97 +
 SRC/OpenMeca/Physic/LinearVelocity.cpp             |    77 +
 SRC/OpenMeca/Physic/LinearVelocity.hpp             |    94 +
 SRC/OpenMeca/Physic/MechanicalAction.cpp           |   198 +
 SRC/OpenMeca/Physic/MechanicalAction.hpp           |    98 +
 SRC/OpenMeca/Physic/PhysEnum.hpp                   |    42 +
 SRC/OpenMeca/Physic/Physic.pro                     |    54 +
 SRC/OpenMeca/Physic/Quantity.cpp                   |    98 +
 SRC/OpenMeca/Physic/Quantity.hpp                   |    86 +
 SRC/OpenMeca/Physic/QuantityT.cpp                  |    74 +
 SRC/OpenMeca/Physic/QuantityT.hpp                  |   146 +
 SRC/OpenMeca/Physic/Torque.cpp                     |    78 +
 SRC/OpenMeca/Physic/Torque.hpp                     |   100 +
 SRC/OpenMeca/Physic/Type.cpp                       |    76 +
 SRC/OpenMeca/Physic/Type.hpp                       |    83 +
 SRC/OpenMeca/Physic/TypeT.cpp                      |    39 +
 SRC/OpenMeca/Physic/TypeT.hpp                      |    78 +
 SRC/OpenMeca/Physic/Vector3D.cpp                   |   180 +
 SRC/OpenMeca/Physic/Vector3D.hpp                   |   121 +
 SRC/OpenMeca/Resources.qrc                         |   111 +
 SRC/OpenMeca/Rsc/Example/cranck-shaft.omc          |    46 +
 SRC/OpenMeca/Rsc/Example/gears.omc                 |    43 +
 SRC/OpenMeca/Rsc/Example/gyroscope.omc             |    49 +
 SRC/OpenMeca/Rsc/Example/reprap.omc                |   158 +
 SRC/OpenMeca/Rsc/Example/robot.omc                 |   203 +
 SRC/OpenMeca/Rsc/Example/screw.omc                 |    36 +
 SRC/OpenMeca/Rsc/Example/steering.omc              |   164 +
 SRC/OpenMeca/Rsc/Help/Help.html                    |   168 +
 SRC/OpenMeca/Rsc/Help/Help.qhcp                    |    14 +
 SRC/OpenMeca/Rsc/Help/Help.qhp                     |    27 +
 SRC/OpenMeca/Rsc/Help/img/gui.svg                  |   687 +
 SRC/OpenMeca/Rsc/Img/Body-ground.svg               |   176 +
 SRC/OpenMeca/Rsc/Img/Body.svg                      |   144 +
 SRC/OpenMeca/Rsc/Img/Collision.svg                 |   122 +
 SRC/OpenMeca/Rsc/Img/Cosmetic.svg                  |   130 +
 SRC/OpenMeca/Rsc/Img/Equation.svg                  |    86 +
 SRC/OpenMeca/Rsc/Img/Flower.svg                    |   274 +
 SRC/OpenMeca/Rsc/Img/Frame.svg                     |   113 +
 SRC/OpenMeca/Rsc/Img/Geometry.svg                  |    93 +
 SRC/OpenMeca/Rsc/Img/Link.svg                      |   130 +
 SRC/OpenMeca/Rsc/Img/Link/Cylindrical.svg          |   129 +
 SRC/OpenMeca/Rsc/Img/Link/Gear.svg                 |   140 +
 SRC/OpenMeca/Rsc/Img/Link/LinearMotor.svg          |   127 +
 SRC/OpenMeca/Rsc/Img/Link/Motor.svg                |   133 +
 SRC/OpenMeca/Rsc/Img/Link/Planar.svg               |   125 +
 SRC/OpenMeca/Rsc/Img/Link/PointLine.svg            |   128 +
 SRC/OpenMeca/Rsc/Img/Link/PointPlane.svg           |   128 +
 SRC/OpenMeca/Rsc/Img/Link/Pulley.svg               |   162 +
 SRC/OpenMeca/Rsc/Img/Link/RackPinion.svg           |   136 +
 SRC/OpenMeca/Rsc/Img/Link/Revolute.svg             |   133 +
 SRC/OpenMeca/Rsc/Img/Link/Screw.svg                |   134 +
 SRC/OpenMeca/Rsc/Img/Link/Slider.svg               |   127 +
 SRC/OpenMeca/Rsc/Img/Link/Spherical.svg            |   122 +
 SRC/OpenMeca/Rsc/Img/Link/Spring.svg               |   128 +
 SRC/OpenMeca/Rsc/Img/Load.svg                      |   157 +
 SRC/OpenMeca/Rsc/Img/Load/Force.svg                |   118 +
 SRC/OpenMeca/Rsc/Img/Load/Torque.svg               |   119 +
 SRC/OpenMeca/Rsc/Img/Logo.png                      |   Bin 0 -> 27139 bytes
 SRC/OpenMeca/Rsc/Img/Logo.svg                      |   125 +
 SRC/OpenMeca/Rsc/Img/MainWindow/New.svg            |   474 +
 SRC/OpenMeca/Rsc/Img/MainWindow/Open.svg           |   627 +
 SRC/OpenMeca/Rsc/Img/MainWindow/Preference.svg     |   488 +
 SRC/OpenMeca/Rsc/Img/MainWindow/Quit.svg           |   374 +
 SRC/OpenMeca/Rsc/Img/MainWindow/Redo.svg           |   214 +
 SRC/OpenMeca/Rsc/Img/MainWindow/Save-as.svg        |   737 +
 SRC/OpenMeca/Rsc/Img/MainWindow/Save.svg           |   695 +
 SRC/OpenMeca/Rsc/Img/MainWindow/Undo.svg           |   218 +
 SRC/OpenMeca/Rsc/Img/Mini-Logo.svg                 |   124 +
 SRC/OpenMeca/Rsc/Img/OpenMeca.icns                 |   Bin 0 -> 404731 bytes
 SRC/OpenMeca/Rsc/Img/OpenMeca.png                  |   Bin 0 -> 4225 bytes
 SRC/OpenMeca/Rsc/Img/OpenMeca_1024.png             |   Bin 0 -> 131098 bytes
 SRC/OpenMeca/Rsc/Img/Part/Junction.svg             |   136 +
 SRC/OpenMeca/Rsc/Img/Part/Pipe.svg                 |   131 +
 SRC/OpenMeca/Rsc/Img/Part/Point.svg                |   116 +
 SRC/OpenMeca/Rsc/Img/Player/Play.svg               |   167 +
 SRC/OpenMeca/Rsc/Img/Player/Record.svg             |   501 +
 SRC/OpenMeca/Rsc/Img/Player/Stop.svg               |   250 +
 SRC/OpenMeca/Rsc/Img/Screenshot.png                |   Bin 0 -> 22103 bytes
 SRC/OpenMeca/Rsc/Img/Sensor.svg                    |   146 +
 .../Rsc/Img/Sensor/AngularAcceleration.svg         |    99 +
 SRC/OpenMeca/Rsc/Img/Sensor/AngularPosition.svg    |    86 +
 SRC/OpenMeca/Rsc/Img/Sensor/AngularVelocity.svg    |    99 +
 SRC/OpenMeca/Rsc/Img/Sensor/Force.svg              |   118 +
 SRC/OpenMeca/Rsc/Img/Sensor/LinearAcceleration.svg |    92 +
 SRC/OpenMeca/Rsc/Img/Sensor/LinearPosition.svg     |    80 +
 SRC/OpenMeca/Rsc/Img/Sensor/LinearVelocity.svg     |    91 +
 .../Rsc/Img/Sensor/RotationAcceleration.svg        |   123 +
 SRC/OpenMeca/Rsc/Img/Sensor/RotationAngle.svg      |   109 +
 SRC/OpenMeca/Rsc/Img/Sensor/RotationAxis.svg       |   123 +
 SRC/OpenMeca/Rsc/Img/Sensor/RotationVelocity.svg   |   123 +
 SRC/OpenMeca/Rsc/Img/Sensor/Torque.svg             |   119 +
 SRC/OpenMeca/Rsc/Img/Sensor/save.svg               |   105 +
 SRC/OpenMeca/Rsc/Img/Shape/Box.svg                 |   161 +
 SRC/OpenMeca/Rsc/Img/Shape/Cylinder.svg            |   168 +
 SRC/OpenMeca/Rsc/Img/Shape/Ground.svg              |   176 +
 SRC/OpenMeca/Rsc/Img/Shape/Sphere.svg              |    84 +
 SRC/OpenMeca/Rsc/Img/System.svg                    |   319 +
 SRC/OpenMeca/Rsc/Img/SystemSetting/Gravity.svg     |   166 +
 SRC/OpenMeca/Rsc/Img/SystemSetting/Scales.svg      |    80 +
 SRC/OpenMeca/Rsc/Img/SystemSetting/Scene.svg       |   573 +
 SRC/OpenMeca/Rsc/Img/SystemSetting/Simulation.svg  |    70 +
 SRC/OpenMeca/Rsc/Img/application-openmeca.svg      |   335 +
 SRC/OpenMeca/Rsc/Lang/openmeca_fr.ts               |  1835 +
 SRC/OpenMeca/Rsc/Xml/LangManager.xml               |    28 +
 SRC/OpenMeca/Rsc/Xml/MenuManager.xml               |   331 +
 SRC/OpenMeca/Rsc/Xml/UnitManager.xml               |   102 +
 SRC/OpenMeca/Setting/Gravity.cpp                   |    84 +
 SRC/OpenMeca/Setting/Gravity.hpp                   |    80 +
 SRC/OpenMeca/Setting/LangManager.cpp               |   176 +
 SRC/OpenMeca/Setting/LangManager.hpp               |    75 +
 SRC/OpenMeca/Setting/MenuManager.cpp               |   241 +
 SRC/OpenMeca/Setting/MenuManager.hpp               |    75 +
 SRC/OpenMeca/Setting/Scales.cpp                    |   149 +
 SRC/OpenMeca/Setting/Scales.hpp                    |    84 +
 SRC/OpenMeca/Setting/Scene.cpp                     |   128 +
 SRC/OpenMeca/Setting/Scene.hpp                     |    98 +
 SRC/OpenMeca/Setting/Setting.pro                   |    37 +
 SRC/OpenMeca/Setting/Simulation.cpp                |   275 +
 SRC/OpenMeca/Setting/Simulation.hpp                |   160 +
 SRC/OpenMeca/Setting/UnitManager.cpp               |   152 +
 SRC/OpenMeca/Setting/UnitManager.hpp               |    69 +
 SRC/OpenMeca/Todo.txt                              |     8 +
 SRC/OpenMeca/Util/Color.cpp                        |   161 +
 SRC/OpenMeca/Util/Color.hpp                        |    93 +
 SRC/OpenMeca/Util/CustomChFunction.cpp             |   105 +
 SRC/OpenMeca/Util/CustomChFunction.hpp             |    89 +
 SRC/OpenMeca/Util/Dimension.cpp                    |   159 +
 SRC/OpenMeca/Util/Dimension.hpp                    |    69 +
 SRC/OpenMeca/Util/Draw.cpp                         |   582 +
 SRC/OpenMeca/Util/Draw.hpp                         |    63 +
 SRC/OpenMeca/Util/Enum.cpp                         |    76 +
 SRC/OpenMeca/Util/Enum.hpp                         |    85 +
 SRC/OpenMeca/Util/Expr.cpp                         |   225 +
 SRC/OpenMeca/Util/Expr.hpp                         |   107 +
 SRC/OpenMeca/Util/ExprAttitude.cpp                 |    87 +
 SRC/OpenMeca/Util/ExprAttitude.hpp                 |    82 +
 SRC/OpenMeca/Util/ExprDouble.cpp                   |    89 +
 SRC/OpenMeca/Util/ExprDouble.hpp                   |    82 +
 SRC/OpenMeca/Util/ExprPoint.cpp                    |    88 +
 SRC/OpenMeca/Util/ExprPoint.hpp                    |    83 +
 SRC/OpenMeca/Util/ExprVector.cpp                   |    97 +
 SRC/OpenMeca/Util/ExprVector.hpp                   |    86 +
 SRC/OpenMeca/Util/Icon.cpp                         |    91 +
 SRC/OpenMeca/Util/Icon.hpp                         |    52 +
 SRC/OpenMeca/Util/Lang.cpp                         |    96 +
 SRC/OpenMeca/Util/Lang.hpp                         |    64 +
 SRC/OpenMeca/Util/MotionLaw.cpp                    |    71 +
 SRC/OpenMeca/Util/MotionLaw.hpp                    |    69 +
 SRC/OpenMeca/Util/Unit.cpp                         |    73 +
 SRC/OpenMeca/Util/Unit.hpp                         |    58 +
 SRC/OpenMeca/Util/Util.pro                         |    55 +
 SRC/OpenMeca/Util/Var.cpp                          |   103 +
 SRC/OpenMeca/Util/Var.hpp                          |    93 +
 SRC/OpenMeca/Util/Version.cpp                      |   127 +
 SRC/OpenMeca/Util/Version.hpp                      |    79 +
 SRC/OpenMeca/Util/exprtk.hpp                       | 33740 +++++++++++++++++++
 SRC/OpenMeca/Util/trash/None.hpp                   |    41 +
 SRC/OpenMeca/Util/trash/XmlSerializer.hpp          |   183 +
 SRC/README                                         |    38 +
 SRC/Serialization/Serialization.pro                |    67 +
 SRC/Serialization/access.hpp                       |   147 +
 SRC/Serialization/archive/add_facet.hpp            |    55 +
 SRC/Serialization/archive/archive_exception.hpp    |    97 +
 SRC/Serialization/archive/basic_archive.hpp        |   300 +
 .../archive/basic_binary_iarchive.hpp              |   222 +
 .../archive/basic_binary_iprimitive.hpp            |   190 +
 .../archive/basic_binary_oarchive.hpp              |   180 +
 .../archive/basic_binary_oprimitive.hpp            |   184 +
 .../archive/basic_streambuf_locale_saver.hpp       |    73 +
 SRC/Serialization/archive/basic_text_iarchive.hpp  |    91 +
 .../archive/basic_text_iprimitive.hpp              |   144 +
 SRC/Serialization/archive/basic_text_oarchive.hpp  |   116 +
 .../archive/basic_text_oprimitive.hpp              |   173 +
 SRC/Serialization/archive/basic_xml_archive.hpp    |    67 +
 SRC/Serialization/archive/basic_xml_iarchive.hpp   |   127 +
 SRC/Serialization/archive/basic_xml_oarchive.hpp   |   145 +
 SRC/Serialization/archive/binary_iarchive.hpp      |   103 +
 SRC/Serialization/archive/binary_iarchive_impl.hpp |    96 +
 SRC/Serialization/archive/binary_oarchive.hpp      |    66 +
 SRC/Serialization/archive/binary_oarchive_impl.hpp |    97 +
 SRC/Serialization/archive/binary_wiarchive.hpp     |    93 +
 SRC/Serialization/archive/binary_woarchive.hpp     |    61 +
 SRC/Serialization/archive/codecvt_null.hpp         |   100 +
 SRC/Serialization/archive/detail/abi_prefix.hpp    |    20 +
 SRC/Serialization/archive/detail/abi_suffix.hpp    |    19 +
 .../archive/detail/archive_serializer_map.hpp      |    55 +
 .../archive/detail/auto_link_archive.hpp           |    48 +
 .../archive/detail/auto_link_warchive.hpp          |    47 +
 .../archive/detail/basic_iarchive.hpp              |   110 +
 .../archive/detail/basic_iserializer.hpp           |    95 +
 .../archive/detail/basic_oarchive.hpp              |   106 +
 .../archive/detail/basic_oserializer.hpp           |    93 +
 .../archive/detail/basic_pointer_iserializer.hpp   |    73 +
 .../archive/detail/basic_pointer_oserializer.hpp   |    72 +
 .../archive/detail/basic_serializer.hpp            |    79 +
 .../archive/detail/basic_serializer_map.hpp        |    69 +
 SRC/Serialization/archive/detail/check.hpp         |   169 +
 .../archive/detail/common_iarchive.hpp             |    88 +
 .../archive/detail/common_oarchive.hpp             |    87 +
 SRC/Serialization/archive/detail/decl.hpp          |    79 +
 .../archive/detail/interface_iarchive.hpp          |    77 +
 .../archive/detail/interface_oarchive.hpp          |    84 +
 SRC/Serialization/archive/detail/iserializer.hpp   |   632 +
 SRC/Serialization/archive/detail/oserializer.hpp   |   531 +
 .../archive/detail/polymorphic_iarchive_route.hpp  |   215 +
 .../archive/detail/polymorphic_oarchive_route.hpp  |   205 +
 .../archive/detail/register_archive.hpp            |    91 +
 .../archive/detail/utf8_codecvt_facet.hpp          |    21 +
 SRC/Serialization/archive/dinkumware.hpp           |   224 +
 .../archive/impl/archive_serializer_map.ipp        |    71 +
 .../archive/impl/basic_binary_iarchive.ipp         |   129 +
 .../archive/impl/basic_binary_iprimitive.ipp       |   209 +
 .../archive/impl/basic_binary_oarchive.ipp         |    46 +
 .../archive/impl/basic_binary_oprimitive.ipp       |   160 +
 .../archive/impl/basic_text_iarchive.ipp           |    79 +
 .../archive/impl/basic_text_iprimitive.ipp         |   154 +
 .../archive/impl/basic_text_oarchive.ipp           |    62 +
 .../archive/impl/basic_text_oprimitive.ipp         |   114 +
 .../archive/impl/basic_xml_grammar.hpp             |   178 +
 .../archive/impl/basic_xml_iarchive.ipp            |   114 +
 .../archive/impl/basic_xml_oarchive.ipp            |   275 +
 .../archive/impl/text_iarchive_impl.ipp            |   128 +
 .../archive/impl/text_oarchive_impl.ipp            |   124 +
 .../archive/impl/text_wiarchive_impl.ipp           |   118 +
 .../archive/impl/text_woarchive_impl.ipp           |    85 +
 .../archive/impl/xml_iarchive_impl.ipp             |   204 +
 .../archive/impl/xml_oarchive_impl.ipp             |   117 +
 .../archive/impl/xml_wiarchive_impl.ipp            |   206 +
 .../archive/impl/xml_woarchive_impl.ipp            |   160 +
 .../archive/iterators/base64_from_binary.hpp       |   112 +
 .../archive/iterators/binary_from_base64.hpp       |   120 +
 .../archive/iterators/dataflow_exception.hpp       |    80 +
 SRC/Serialization/archive/iterators/escape.hpp     |   115 +
 .../archive/iterators/insert_linebreaks.hpp        |   101 +
 .../archive/iterators/istream_iterator.hpp         |    95 +
 .../archive/iterators/mb_from_wchar.hpp            |   136 +
 .../archive/iterators/ostream_iterator.hpp         |    83 +
 .../archive/iterators/remove_whitespace.hpp        |   169 +
 .../archive/iterators/transform_width.hpp          |   170 +
 SRC/Serialization/archive/iterators/unescape.hpp   |    91 +
 .../archive/iterators/wchar_from_mb.hpp            |   129 +
 SRC/Serialization/archive/iterators/xml_escape.hpp |   125 +
 .../archive/iterators/xml_unescape.hpp             |   128 +
 .../archive/polymorphic_binary_iarchive.hpp        |    54 +
 .../archive/polymorphic_binary_oarchive.hpp        |    43 +
 SRC/Serialization/archive/polymorphic_iarchive.hpp |   181 +
 SRC/Serialization/archive/polymorphic_oarchive.hpp |   159 +
 .../archive/polymorphic_text_iarchive.hpp          |    54 +
 .../archive/polymorphic_text_oarchive.hpp          |    39 +
 .../archive/polymorphic_text_wiarchive.hpp         |    59 +
 .../archive/polymorphic_text_woarchive.hpp         |    44 +
 .../archive/polymorphic_xml_iarchive.hpp           |    54 +
 .../archive/polymorphic_xml_oarchive.hpp           |    39 +
 .../archive/polymorphic_xml_wiarchive.hpp          |    50 +
 .../archive/polymorphic_xml_woarchive.hpp          |    44 +
 SRC/Serialization/archive/shared_ptr_helper.hpp    |   219 +
 SRC/Serialization/archive/text_iarchive.hpp        |   156 +
 SRC/Serialization/archive/text_oarchive.hpp        |   119 +
 SRC/Serialization/archive/text_wiarchive.hpp       |   152 +
 SRC/Serialization/archive/text_woarchive.hpp       |   145 +
 SRC/Serialization/archive/tmpdir.hpp               |    50 +
 SRC/Serialization/archive/wcslen.hpp               |    56 +
 .../archive/xml_archive_exception.hpp              |    56 +
 SRC/Serialization/archive/xml_iarchive.hpp         |   164 +
 SRC/Serialization/archive/xml_oarchive.hpp         |   133 +
 SRC/Serialization/archive/xml_wiarchive.hpp        |   170 +
 SRC/Serialization/archive/xml_woarchive.hpp        |   140 +
 SRC/Serialization/array.hpp                        |   153 +
 SRC/Serialization/assume_abstract.hpp              |    59 +
 SRC/Serialization/base_object.hpp                  |   112 +
 SRC/Serialization/binary_object.hpp                |    82 +
 SRC/Serialization/bitset.hpp                       |    75 +
 SRC/Serialization/collection_size_type.hpp         |    62 +
 SRC/Serialization/collection_traits.hpp            |    79 +
 SRC/Serialization/collections_load_imp.hpp         |   166 +
 SRC/Serialization/collections_save_imp.hpp         |    72 +
 SRC/Serialization/complex.hpp                      |    81 +
 SRC/Serialization/config.hpp                       |    85 +
 SRC/Serialization/deque.hpp                        |    75 +
 SRC/Serialization/detail/get_data.hpp              |    55 +
 SRC/Serialization/detail/shared_count_132.hpp      |   569 +
 SRC/Serialization/detail/shared_ptr_132.hpp        |   478 +
 SRC/Serialization/detail/shared_ptr_nmt_132.hpp    |   182 +
 SRC/Serialization/detail/stack_constructor.hpp     |    73 +
 SRC/Serialization/ephemeral.hpp                    |    80 +
 SRC/Serialization/export.hpp                       |   234 +
 SRC/Serialization/extended_type_info.hpp           |   108 +
 SRC/Serialization/extended_type_info_no_rtti.hpp   |   182 +
 SRC/Serialization/extended_type_info_typeid.hpp    |   165 +
 SRC/Serialization/factory.hpp                      |   101 +
 SRC/Serialization/force_include.hpp                |    59 +
 SRC/Serialization/hash_collections_load_imp.hpp    |    77 +
 SRC/Serialization/hash_collections_save_imp.hpp    |    97 +
 SRC/Serialization/hash_map.hpp                     |   231 +
 SRC/Serialization/hash_set.hpp                     |   221 +
 SRC/Serialization/is_bitwise_serializable.hpp      |    46 +
 SRC/Serialization/item_version_type.hpp            |    68 +
 SRC/Serialization/level.hpp                        |   125 +
 SRC/Serialization/level_enum.hpp                   |    55 +
 SRC/Serialization/list.hpp                         |    77 +
 SRC/Serialization/map.hpp                          |   118 +
 SRC/Serialization/nvp.hpp                          |   144 +
 SRC/Serialization/optional.hpp                     |   127 +
 SRC/Serialization/pfto.hpp                         |    78 +
 SRC/Serialization/scoped_ptr.hpp                   |    58 +
 SRC/Serialization/serialization.hpp                |   167 +
 SRC/Serialization/set.hpp                          |   120 +
 SRC/Serialization/shared_ptr.hpp                   |   177 +
 SRC/Serialization/shared_ptr_132.hpp               |   222 +
 SRC/Serialization/singleton.hpp                    |   158 +
 SRC/Serialization/slist.hpp                        |   103 +
 SRC/Serialization/smart_cast.hpp                   |   301 +
 SRC/Serialization/split_free.hpp                   |    93 +
 SRC/Serialization/split_member.hpp                 |    86 +
 SRC/Serialization/src/archive_exception.cpp        |   114 +
 SRC/Serialization/src/basic_archive.cpp            |    80 +
 SRC/Serialization/src/basic_iarchive.cpp           |   576 +
 SRC/Serialization/src/basic_iserializer.cpp        |    33 +
 SRC/Serialization/src/basic_oarchive.cpp           |   459 +
 SRC/Serialization/src/basic_oserializer.cpp        |    33 +
 .../src/basic_pointer_iserializer.cpp              |    30 +
 .../src/basic_pointer_oserializer.cpp              |    30 +
 SRC/Serialization/src/basic_serializer_map.cpp     |   111 +
 SRC/Serialization/src/basic_text_iprimitive.cpp    |    28 +
 SRC/Serialization/src/basic_text_oprimitive.cpp    |    28 +
 SRC/Serialization/src/basic_text_wiprimitive.cpp   |    35 +
 SRC/Serialization/src/basic_text_woprimitive.cpp   |    35 +
 SRC/Serialization/src/basic_xml_archive.cpp        |    51 +
 SRC/Serialization/src/basic_xml_grammar.ipp        |   468 +
 SRC/Serialization/src/binary_iarchive.cpp          |    53 +
 SRC/Serialization/src/binary_oarchive.cpp          |    39 +
 SRC/Serialization/src/binary_wiarchive.cpp         |    60 +
 SRC/Serialization/src/binary_woarchive.cpp         |    44 +
 SRC/Serialization/src/codecvt_null.cpp             |    83 +
 SRC/Serialization/src/extended_type_info.cpp       |   188 +
 .../src/extended_type_info_no_rtti.cpp             |    85 +
 .../src/extended_type_info_typeid.cpp              |   161 +
 SRC/Serialization/src/polymorphic_iarchive.cpp     |    29 +
 SRC/Serialization/src/polymorphic_oarchive.cpp     |    29 +
 SRC/Serialization/src/shared_ptr_helper.cpp        |   138 +
 SRC/Serialization/src/stl_port.cpp                 |    43 +
 SRC/Serialization/src/text_iarchive.cpp            |    36 +
 SRC/Serialization/src/text_oarchive.cpp            |    33 +
 SRC/Serialization/src/text_wiarchive.cpp           |    41 +
 SRC/Serialization/src/text_woarchive.cpp           |    35 +
 SRC/Serialization/src/utf8_codecvt_facet.cpp       |    21 +
 SRC/Serialization/src/void_cast.cpp                |   360 +
 SRC/Serialization/src/xml_archive_exception.cpp    |    56 +
 SRC/Serialization/src/xml_grammar.cpp              |    73 +
 SRC/Serialization/src/xml_iarchive.cpp             |    46 +
 SRC/Serialization/src/xml_oarchive.cpp             |    32 +
 SRC/Serialization/src/xml_wgrammar.cpp             |   157 +
 SRC/Serialization/src/xml_wiarchive.cpp            |    53 +
 SRC/Serialization/src/xml_woarchive.cpp            |    35 +
 SRC/Serialization/state_saver.hpp                  |    96 +
 SRC/Serialization/static_warning.hpp               |   108 +
 SRC/Serialization/string.hpp                       |    91 +
 SRC/Serialization/strong_typedef.hpp               |    66 +
 SRC/Serialization/throw_exception.hpp              |    44 +
 SRC/Serialization/tracking.hpp                     |   118 +
 SRC/Serialization/tracking_enum.hpp                |    41 +
 SRC/Serialization/traits.hpp                       |    65 +
 SRC/Serialization/type_info_implementation.hpp     |    86 +
 SRC/Serialization/utility.hpp                      |    56 +
 SRC/Serialization/valarray.hpp                     |    74 +
 SRC/Serialization/variant.hpp                      |   163 +
 SRC/Serialization/vector.hpp                       |   211 +
 SRC/Serialization/vector_135.hpp                   |    26 +
 SRC/Serialization/version.hpp                      |   107 +
 SRC/Serialization/void_cast.hpp                    |   298 +
 SRC/Serialization/void_cast_fwd.hpp                |    37 +
 SRC/Serialization/weak_ptr.hpp                     |    58 +
 SRC/Serialization/wrapper.hpp                      |    60 +
 1438 files changed, 299608 insertions(+)

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..95cbfb9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,689 @@
+Copyright (c) 2008-2017, Damien ANDRE, Cedric HUBERT.
+OpenMeca is distributed under the free GNU-GPLv3 licence (see below). The openmeca
+sources are located under the "SRC/OpenMeca" directory. 
+
+***************
+
+Note that the embeded third party libraries Qwt, Boost, QGLviewer and ChronoEngine
+has their own licences. They are located :
+ - for QWt see the "SRC/Qwt/COPYING" file
+ - for Boost see the "SRC/Qwt/LICENSE_1_0.txt" file
+ - for QGLViewer see the "SRC/QGLViewer/LICENCE" file
+ - for ChronoEngine see the "SR/ChronoEngine/License" file
+ 
+***************
+
+                      GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..233b5fc
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,155 @@
+
+# The install path used when run a 'make install'
+ifndef DESTDIR
+	DESTDIR=/usr/local
+endif
+
+# the bin dir 
+BINDIR=bin
+
+# The qmake utility location (for unix-like systems)
+QMAKE=qmake
+
+
+
+####################################
+# Cross compile from unix to win32 #
+####################################
+# The mxe platform is used. So, you need to specifiy your mxe path. 
+# For example, if you type 'mxe=/home/omc/mxe make', it runs the cross-compilation
+
+# if mxe is used, the mxe path must be exported
+ifdef mxe
+	export PATH := $(mxe)/usr/bin:$(PATH)
+	mxe_bin = $(mxe)/usr/i686-w64-mingw32.static/qt5/bin
+endif
+
+####################################
+# Compile on OS X                  #
+####################################
+OSName := $(shell uname)
+
+####################################
+# Makefile targets                 #
+####################################
+.PHONY: all message boost qglviewer qwt chronoengine openmeca
+
+all: message
+	$(MAKE) serialization
+	$(MAKE) chronoengine
+	$(MAKE) openmeca
+
+message:
+ifdef mxe
+	@echo 'cross compiling for win32...' ;\
+	sleep 1
+endif
+	@echo 'compiling...'
+
+clean:
+	-rm -rf SRC/Serialization/BUILD
+	-rm -rf SRC/Serialization/Makefile
+	-rm -rf SRC/Serialization/Makefile.Debug
+	-rm -rf SRC/Serialization/Makefile.Release
+	-rm -rf SRC/Serialization/.qmake.stash
+	-rm -rf SRC/Serialization/object_script.*
+	-rm -rf SRC/ChronoEngine/BUILD
+	-rm -rf SRC/ChronoEngine/Makefile
+	-rm -rf SRC/ChronoEngine/Makefile.Debug
+	-rm -rf SRC/ChronoEngine/Makefile.Release
+	-rm -rf SRC/ChronoEngine/.qmake.stash
+	-rm -rf SRC/ChronoEngine/object_script.*
+	-rm -rf SRC/OpenMeca/BUILD
+	-rm -rf SRC/OpenMeca/Makefile
+	-rm -rf SRC/OpenMeca/Makefile.Debug
+	-rm -rf SRC/OpenMeca/Makefile.Release
+	-rm -rf SRC/OpenMeca/.qmake.stash
+	-rm -rf SRC/OpenMeca/object_script.*
+	-rm -rf SRC/OpenMeca/Rsc/Help/Help.qch
+	-rm -rf SRC/OpenMeca/Rsc/Help/Help.qhc
+	-rm -rf SRC/OpenMeca/Rsc/Lang/openmeca_fr.qm
+
+
+install: all
+	@echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	echo '@@            Installing openmeca              @@'; \
+	echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	mkdir -p $(DESTDIR)/$(BINDIR)
+	cp -ar ./SRC/OpenMeca/BUILD/openmeca $(DESTDIR)/$(BINDIR)
+	@echo 'The openmeca executable was installed in the $(DESTDIR)/$(BINDIR) directory'
+
+
+uninstall: 
+	@echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	echo '@@           Uninstalling openmeca             @@'; \
+	echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	rm  $(DESTDIR)/$(BINDIR)/openmeca
+	@echo 'The openmeca executable was removed from $(DESTDIR)/$(BINDIR)'
+
+
+purge: uninstall
+	rm -rf $(HOME)/openmeca
+	@echo 'The openmeca config directory $(HOME)/openmeca was removed'
+
+
+serialization: 
+	@echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	echo '@@ making the boost serialization third party library @@'; \
+	echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	sleep 1
+ifdef mxe
+	@echo 'cross compiling qglviewer for win32 !'
+	@cd SRC/Serialization ;\
+	$(mxe_bin)/qmake ; \
+	$(MAKE)
+else
+	@cd SRC/Serialization ; \
+	qtchooser -qt=5 -run-tool=qmake ; \
+	$(MAKE)
+endif
+
+
+chronoengine:
+	@echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	echo '@@ making the chronoengine third party library @@'; \
+	echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	sleep 1
+ifdef mxe
+	@echo 'cross compiling chronoengine for win32 !'
+	@cd SRC/ChronoEngine ;\
+	$(mxe_bin)/qmake ; \
+	$(MAKE)
+else
+	@cd SRC/ChronoEngine ; \
+	qtchooser -qt=5 -run-tool=qmake  ; \
+	$(MAKE)
+endif
+
+
+
+openmeca:
+	@echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	echo '@@              making openmeca                @@'; \
+	echo '@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@'; \
+	sleep 1
+ifdef mxe
+	@echo 'cross compiling openmeca for win32 !'
+	@cd SRC/OpenMeca  ; \
+	lrelease ./OpenMeca.pro  ; \
+	qhelpgenerator ./Rsc/Help/Help.qhp -o ./Rsc/Help/Help.qch  ; \
+	qcollectiongenerator ./Rsc/Help/Help.qhcp -o ./Rsc/Help/Help.qhc ;\
+	$(mxe_bin)/qmake ;\
+	$(MAKE)
+else
+	@cd SRC/OpenMeca  ; \
+	qtchooser -qt=5 -run-tool=lrelease ./OpenMeca.pro  ; \
+	qtchooser -qt=5 -run-tool=qhelpgenerator ./Rsc/Help/Help.qhp -o ./Rsc/Help/Help.qch  ; \
+	qtchooser -qt=5 -run-tool=qcollectiongenerator ./Rsc/Help/Help.qhcp -o ./Rsc/Help/Help.qhc ;\
+	qtchooser -qt=5 -run-tool=qmake  ; \
+	$(MAKE)
+ifeq ($(OSName),Darwin)
+	macdeployqt SRC/OpenMeca/BUILD/openmeca.app
+endif
+endif
+	@echo 'The executable was built in the OpenMeca/BUILD/openmeca directory';
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1cb7c1a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,92 @@
+
+# OpenMeca is a multibody dynamics software designed for human being. 
+
+OpenMeca is based on the [chronoengine](http://chronoengine.info/chronoengine/) library.
+The aim of openmeca is to provide a software for simulating mechanical systems easily.
+openmeca allow us to builds a 3D sketch, where the bonds are represented by symbols and gives a simple way 
+to apply loading and boundary conditions. Thanks to numerical sensors,
+different kind of data (force, torque, displacement, velocity, etc.) 
+could be extracted from the simulation. 
+
+# Example video
+[![Screenshot](http://www.yakuru.fr/~openmeca/yt-screenshot.png)](http://www.youtube.com/watch?v=8iGKT1DO9Jc "Screen cast of epicyclic gearing")
+
+
+# Usage
+A tutorial is available on YouTube [here](https://www.youtube.com/playlist?list=PLjFD44HqZ1diZN45FSLO82NyuIgpu4Lml).
+
+# Installation on Mac OS x
+Simply download the installer [here](http://www.yakuru.fr/~openmeca/openmeca.dmg). 
+To install it, if you are not familiar with .dmg files:
+ - double click on the downloaded .dmg file
+ - in the window that just appeared, drag and drop the OpenMeca onto the link to Applications folder.
+
+To launch OpenMeca, navigate to the Applications folder from the Finder, and double click the OpenMeca icon.
+Note that, the application is not code signed. If you are using a recent version of OS X, you may need to desactivate Gatekeeper in the System Preferences.
+
+# Installation on windows
+Simply download the installer [here](http://www.yakuru.fr/~openmeca/openmeca.exe). 
+
+# Installation on GNU/Linux
+On a Debian based Linux distribution, simply run the following commands.
+```
+sudo apt-get install libboost-dev qtdeclarative5-dev qttools5-dev-tools qtchooserlibqwt-qt5-dev libqglviewer-dev-qt5 libqt5help5 libqt5svg5 libqt5opengl5 libqt5widgets5 libqt5gui5 libqt5xml5 libqt5core5a
+cd /tmp/ && wget http://www.yakuru.fr/~openmeca/openmeca_2.x_amd64.deb 
+sudo dpkg -i openmeca_2.x_amd64.deb
+```
+Now, you can lauch openmeca by typing `openmeca` in a terminal or by clicking the openmeca icon in the *Education* menu. To remove openmeca, simply enter the following command.
+```
+sudo dpkg -r openmeca
+```
+
+
+# The one minute install & compile guide for Linux
+On a Debian based Linux distribution, simply enter the following terminal commands (and take a coffee).
+```
+sudo apt-get install build-essential git qtdeclarative5-dev qt5-default qttools5-dev-tools libqt5svg5-dev libqt5opengl5-dev qttools5-dev qtchooser libqwt-qt5-dev libqglviewer-dev libboost-dev
+git clone https://gitlab.com/damien.andre/openmeca.git
+cd ./openmeca && make 
+./SRC/OpenMeca/BUILD/openmeca
+```
+These commands do the following actions : 
+ * install the required dependencies,
+ * download the openmeca source package,
+ * compile the source files with the `make` command and
+ * run the executable file created by the compilation process.
+
+Note that :
+ * the compilation process can take several minutes.
+ * you can install openmeca by typing `sudo make install`. By default openmeca is installed in the `/usr/local/bin/` directory.
+ * if you want to uninstall openmeca, simply type `sudo make uninstall`.
+
+## Technical information about source code ##
+
+OpenMeca is written in C++ and is based on the [qt5](http://doc.qt.io/qt-5/), [qwt](http://qwt.sourceforge.net/), 
+[qglviewer](http://libqglviewer.com/), [boost](http://www.boost.org/) and the [chronoengine](http://chronoengine.info/chronoengine/) C++ libraries. 
+The graphical front-end is given thanks to the qt5, qglviewer and opengl libraries. 
+The boost library is used to manage serialization (save and load procedures) 
+and some boring stuffs (lexical_cast, bind, etc.). The chronoengine library is the physical engine of OpenMeca.
+
+OpenMeca packages qglviewer, qwt, boost and chronoengine libraries. The chronoengine version used here is a custom version. 
+So, you need to compile them before compiling openmeca. Note that openmeca is statically linked to these libraries. The aim of this design is to make 
+easier the further deployment of openmeca. 
+
+# Configuration files
+The configuration files of openmeca are stored in the `$HOME/openmeca` directory.  
+
+# Compilation
+Simply type `make` in the `SRC` directory.
+
+# License
+OpenMeca is under the GPLv3 license. It is a free software, it means that you may copy, distribute and modify the software as 
+long as you track changes/dates in source files. Any modifications to or software including (via compiler) 
+GPL-licensed code must also be made available under the GPL along with build & install instructions.
+See the LICENSE file for more information.
+
+# Artwork
+Most of the images and icons were extracted and inspired from the [openclipart](https://openclipart.org/) database. 
+
+# Contact & always up-to-date information
+All these information are available [here](https://gitlab.com/damien.andre/openmeca/raw/master/SRC/OpenMeca/Info.txt).
+
+
diff --git a/SRC/ChronoEngine/ChronoEngine.pro b/SRC/ChronoEngine/ChronoEngine.pro
new file mode 100644
index 0000000..c4a5636
--- /dev/null
+++ b/SRC/ChronoEngine/ChronoEngine.pro
@@ -0,0 +1,746 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+CONFIG           += qt     
+CONFIG           += warn_on
+CONFIG           += no_keywords
+CONFIG           += silent
+CONFIG           += release
+CONFIG           += staticlib
+
+TEMPLATE  = lib
+TARGET    = ./BUILD/chronoengine
+DESTDIR   = ./
+
+QMAKE_CXXFLAGS +=-fpermissive -w -D CH_API_COMPILE
+
+OBJECTS_DIR = ./BUILD/obj
+
+INCLUDEPATH = ./ ./collision/bullet ./collision/gimpact
+
+CONFIG += c++11
+
+# Input
+HEADERS += collision/ChCCollisionInfo.h \
+           collision/ChCCollisionModel.h \
+           collision/ChCCollisionPair.h \
+           collision/ChCCollisionSystem.h \
+           collision/ChCCollisionSystemBullet.h \
+           collision/ChCCollisionUtils.h \
+           collision/ChCModelBullet.h \
+           collision/ChCModelBulletBody.h \
+           collision/ChCModelBulletDEM.h \
+           collision/ChCModelBulletNode.h \
+           collision/ChCModelBulletParticle.h \
+           collision/ChCModelSphereSetBody.h \
+           core/ChApiCE.h \
+           core/ChChrono.h \
+           core/ChClassRegister.h \
+           core/ChCoordsys.h \
+           core/ChException.h \
+           core/ChFrame.h \
+           core/ChFrameMoving.h \
+           core/ChHashFunction.h \
+           core/ChHashTable.h \
+           core/ChLinearAlgebra.h \
+           core/ChLists.h \
+           core/ChLog.h \
+           core/ChMath.h \
+           core/ChMathematics.h \
+           core/ChMatrix.h \
+           core/ChMemory.h \
+           core/ChMemorynomgr.h \
+           core/ChPlatform.h \
+           core/ChQuaternion.h \
+           core/ChRealtimeStep.h \
+           core/ChRunTimeType.h \
+           core/ChShared.h \
+           core/ChSmartpointers.h \
+           core/ChSpmatrix.h \
+           core/ChStream.h \
+           core/ChTimer.h \
+           core/ChTransform.h \
+           core/ChTrasform.h \
+           core/ChVector.h \
+           core/ChWrapHashmap.h \
+           geometry/ChCBox.h \
+           geometry/ChCCone.h \
+           geometry/ChCCylinder.h \
+           geometry/ChCEllipsoid.h \
+           geometry/ChCGeometry.h \
+           geometry/ChCLine.h \
+           geometry/ChCLineCam.h \
+           geometry/ChCLinePoly.h \
+           geometry/ChCSphere.h \
+           geometry/ChCTriangle.h \
+           geometry/ChCTriangleMesh.h \
+           geometry/ChCTriangleMeshConnected.h \
+           geometry/ChCTriangleMeshSoup.h \
+           lcp/ChLcpConstraint.h \
+           lcp/ChLcpConstraintNodeContactN.h \
+           lcp/ChLcpConstraintNodeFrictionT.h \
+           lcp/ChLcpConstraintThree.h \
+           lcp/ChLcpConstraintThreeBBShaft.h \
+           lcp/ChLcpConstraintThreeGeneric.h \
+           lcp/ChLcpConstraintTwo.h \
+           lcp/ChLcpConstraintTwoBodies.h \
+           lcp/ChLcpConstraintTwoContact.h \
+           lcp/ChLcpConstraintTwoContactN.h \
+           lcp/ChLcpConstraintTwoFriction.h \
+           lcp/ChLcpConstraintTwoFrictionApprox.h \
+           lcp/ChLcpConstraintTwoFrictionT.h \
+           lcp/ChLcpConstraintTwoGeneric.h \
+           lcp/ChLcpConstraintTwoGenericBoxed.h \
+           lcp/ChLcpConstraintTwoRollingN.h \
+           lcp/ChLcpConstraintTwoRollingT.h \
+           lcp/ChLcpDirectSolver.h \
+           lcp/ChLcpIterativeAPGD.h \
+           lcp/ChLcpIterativeBB.h \
+           lcp/ChLcpIterativeJacobi.h \
+           lcp/ChLcpIterativeMINRES.h \
+           lcp/ChLcpIterativePCG.h \
+           lcp/ChLcpIterativePMINRES.h \
+           lcp/ChLcpIterativeSolver.h \
+           lcp/ChLcpIterativeSOR.h \
+           lcp/ChLcpIterativeSORmultithread.h \
+           lcp/ChLcpIterativeSymmSOR.h \
+           lcp/ChLcpKstiffness.h \
+           lcp/ChLcpKstiffnessGeneric.h \
+           lcp/ChLcpSimplexSolver.h \
+           lcp/ChLcpSolver.h \
+           lcp/ChLcpSolverDEM.h \
+           lcp/ChLcpSystemDescriptor.h \
+           lcp/ChLcpVariables.h \
+           lcp/ChLcpVariablesBody.h \
+           lcp/ChLcpVariablesBodyOwnMass.h \
+           lcp/ChLcpVariablesBodySharedMass.h \
+           lcp/ChLcpVariablesGeneric.h \
+           lcp/ChLcpVariablesNode.h \
+           motion_functions/ChFunction_Base.h \
+           motion_functions/ChFunction_Const.h \
+           motion_functions/ChFunction_ConstAcc.h \
+           motion_functions/ChFunction_Derive.h \
+           motion_functions/ChFunction_Fillet3.h \
+           motion_functions/ChFunction_Integrate.h \
+           motion_functions/ChFunction_Matlab.h \
+           motion_functions/ChFunction_Mirror.h \
+           motion_functions/ChFunction_Mocap.h \
+           motion_functions/ChFunction_Noise.h \
+           motion_functions/ChFunction_Operation.h \
+           motion_functions/ChFunction_Oscilloscope.h \
+           motion_functions/ChFunction_Poly.h \
+           motion_functions/ChFunction_Poly345.h \
+           motion_functions/ChFunction_Ramp.h \
+           motion_functions/ChFunction_Recorder.h \
+           motion_functions/ChFunction_Repeat.h \
+           motion_functions/ChFunction_Sequence.h \
+           motion_functions/ChFunction_Sigma.h \
+           motion_functions/ChFunction_Sine.h \
+           parallel/ChOpenMP.h \
+           parallel/ChThreads.h \
+           parallel/ChThreadsFunct.h \
+           parallel/ChThreadsPOSIX.h \
+           parallel/ChThreadsSync.h \
+           parallel/ChThreadsWIN32.h \
+           physics/ChApidll.h \
+           physics/ChAssembly.h \
+           physics/ChBody.h \
+           physics/ChBodyAuxRef.h \
+           physics/ChBodyDEM.h \
+           physics/ChConstraint.h \
+           physics/ChContact.h \
+           physics/ChContactContainer.h \
+           physics/ChContactContainerBase.h \
+           physics/ChContactContainerDEM.h \
+           physics/ChContactContainerNodes.h \
+           physics/ChContactDEM.h \
+           physics/ChContactNode.h \
+           physics/ChContactRolling.h \
+           physics/ChContinuumMaterial.h \
+           physics/ChController.h \
+           physics/ChControls.h \
+           physics/ChConveyor.h \
+           physics/ChEvents.h \
+           physics/ChExternalObject.h \
+           physics/ChForce.h \
+           physics/ChFunction.h \
+           physics/ChFx.h \
+           physics/ChGlobal.h \
+           physics/ChHistory.h \
+           physics/ChIndexedNodes.h \
+           physics/ChIndexedParticles.h \
+           physics/ChIntegrator.h \
+           physics/ChIterative.h \
+           physics/ChLimit.h \
+           physics/ChLink.h \
+           physics/ChLinkBrake.h \
+           physics/ChLinkClearance.h \
+           physics/ChLinkContact.h \
+           physics/ChLinkDistance.h \
+           physics/ChLinkEngine.h \
+           physics/ChLinkFastContact.h \
+           physics/ChLinkforce.h \
+           physics/ChLinkGear.h \
+           physics/ChLinkGeometric.h \
+           physics/ChLinkLinActuator.h \
+           physics/ChLinkLock.h \
+           physics/ChLinkMarkers.h \
+           physics/ChLinkMask.h \
+           physics/ChLinkMasked.h \
+           physics/ChLinkMate.h \
+           physics/ChLinkNumdiff.h \
+           physics/ChLinkPneumaticActuator.h \
+           physics/ChLinkPointSpline.h \
+           physics/ChLinkPulley.h \
+           physics/ChLinkRackpinion.h \
+           physics/ChLinksAll.h \
+           physics/ChLinkScrew.h \
+           physics/ChLinkSpring.h \
+           physics/ChLinkTrajectory.h \
+           physics/ChLinkWheel.h \
+           physics/ChMarker.h \
+           physics/ChMaterialCouple.h \
+           physics/ChMaterialSurface.h \
+           physics/ChMatterSPH.h \
+           physics/ChNlsolver.h \
+           physics/ChNodeBody.h \
+           physics/ChObject.h \
+           physics/ChParticlesClones.h \
+           physics/ChPhysicsItem.h \
+           physics/ChProbe.h \
+           physics/ChProplist.h \
+           physics/ChProximityContainerBase.h \
+           physics/ChProximityContainerSPH.h \
+           physics/ChRef.h \
+           physics/ChScriptEngine.h \
+           physics/ChShaft.h \
+           physics/ChShaftsBody.h \
+           physics/ChShaftsClutch.h \
+           physics/ChShaftsCouple.h \
+           physics/ChShaftsGear.h \
+           physics/ChShaftsMotor.h \
+           physics/ChShaftsPlanetary.h \
+           physics/ChShaftsTorsionSpring.h \
+           physics/ChSolver.h \
+           physics/ChSolvmin.h \
+           physics/ChStack.h \
+           physics/ChSystem.h \
+           physics/ChSystemOpenMP.h \
+           physics/ChTensors.h \
+           pneumatica/assepneumatico.h \
+           pneumatica/pistone.h \
+           pneumatica/pistone_3_2.h \
+           pneumatica/pistone_3_2_prop.h \
+           pneumatica/sis_attuatore_3_2.h \
+           pneumatica/sis_attuatore_3_2_prop.h \
+           pneumatica/sistema.h \
+           pneumatica/ugello.h \
+           pneumatica/ugello_controllato.h \
+           pneumatica/ugello_controllato_PA.h \
+           pneumatica/ugello_controllato_RA.h \
+           pneumatica/valvola_3_2.h \
+           pneumatica/valvola_3_2_prop.h \
+           pneumatica/volume.h \
+           collision/bullet/btBulletCollisionCommon.h \
+           collision/edgetempest/ChCAABB.h \
+           collision/edgetempest/ChCAABBcollider.h \
+           collision/edgetempest/ChCAABBTree.h \
+           collision/edgetempest/ChCAbsoluteAABB.h \
+           collision/edgetempest/ChCBroadPhaseCollider.h \
+           collision/edgetempest/ChCBruteForce.h \
+           collision/edgetempest/ChCCollisionTree.h \
+           collision/edgetempest/ChCCompile.h \
+           collision/edgetempest/ChCGeometryCollider.h \
+           collision/edgetempest/ChCGetTime.h \
+           collision/edgetempest/ChCMates.h \
+           collision/edgetempest/ChCMatVec.h \
+           collision/edgetempest/ChCNarrowPhaseCollider.h \
+           collision/edgetempest/ChCOBB.h \
+           collision/edgetempest/ChCOBBcollider.h \
+           collision/edgetempest/ChCOBBTree.h \
+           collision/edgetempest/ChCSweepAndPrune.h \
+           collision/bullet/BulletFileLoader/bChunk.h \
+           collision/bullet/BulletFileLoader/bCommon.h \
+           collision/bullet/BulletFileLoader/bDefines.h \
+           collision/bullet/BulletFileLoader/bDNA.h \
+           collision/bullet/BulletFileLoader/bFile.h \
+           collision/bullet/BulletFileLoader/btBulletFile.h \
+           collision/bullet/BulletWorldImporter/btBulletWorldImporter.h \
+           collision/bullet/LinearMath/btAabbUtil2.h \
+           collision/bullet/LinearMath/btAlignedAllocator.h \
+           collision/bullet/LinearMath/btAlignedObjectArray.h \
+           collision/bullet/LinearMath/btConvexHull.h \
+           collision/bullet/LinearMath/btDefaultMotionState.h \
+           collision/bullet/LinearMath/btGeometryUtil.h \
+           collision/bullet/LinearMath/btHashMap.h \
+           collision/bullet/LinearMath/btIDebugDraw.h \
+           collision/bullet/LinearMath/btList.h \
+           collision/bullet/LinearMath/btMatrix3x3.h \
+           collision/bullet/LinearMath/btMinMax.h \
+           collision/bullet/LinearMath/btMotionState.h \
+           collision/bullet/LinearMath/btPoolAllocator.h \
+           collision/bullet/LinearMath/btQuadWord.h \
+           collision/bullet/LinearMath/btQuaternion.h \
+           collision/bullet/LinearMath/btQuickprof.h \
+           collision/bullet/LinearMath/btRandom.h \
+           collision/bullet/LinearMath/btScalar.h \
+           collision/bullet/LinearMath/btSerializer.h \
+           collision/bullet/LinearMath/btStackAlloc.h \
+           collision/bullet/LinearMath/btTransform.h \
+           collision/bullet/LinearMath/btTransformUtil.h \
+           collision/bullet/LinearMath/btVector3.h \
+           collision/gimpact/ConvexDecomposition/bestfit.h \
+           collision/gimpact/ConvexDecomposition/bestfitobb.h \
+           collision/gimpact/ConvexDecomposition/cd_hull.h \
+           collision/gimpact/ConvexDecomposition/cd_vector.h \
+           collision/gimpact/ConvexDecomposition/cd_wavefront.h \
+           collision/gimpact/ConvexDecomposition/concavity.h \
+           collision/gimpact/ConvexDecomposition/ConvexBuilder.h \
+           collision/gimpact/ConvexDecomposition/ConvexDecomposition.h \
+           collision/gimpact/ConvexDecomposition/fitsphere.h \
+           collision/gimpact/ConvexDecomposition/float_math.h \
+           collision/gimpact/ConvexDecomposition/meshvolume.h \
+           collision/gimpact/ConvexDecomposition/planetri.h \
+           collision/gimpact/ConvexDecomposition/raytri.h \
+           collision/gimpact/ConvexDecomposition/splitplane.h \
+           collision/gimpact/ConvexDecomposition/vlookup.h \
+           collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h \
+           collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h \
+           collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.h \
+           collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h \
+           collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btBoxShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h \
+           collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConeShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConvexShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btMaterial.h \
+           collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h \
+           collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btShapeHull.h \
+           collision/bullet/BulletCollision/CollisionShapes/btSphereShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btTriangleShape.h \
+           collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h \
+           collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h \
+           collision/gimpact/GIMPACT/Bullet/btBoxCollision.h \
+           collision/gimpact/GIMPACT/Bullet/btClipPolygon.h \
+           collision/gimpact/GIMPACT/Bullet/btContactProcessing.h \
+           collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.h \
+           collision/gimpact/GIMPACT/Bullet/btGeometryOperations.h \
+           collision/gimpact/GIMPACT/Bullet/btGImpactBvh.h \
+           collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h \
+           collision/gimpact/GIMPACT/Bullet/btGImpactMassUtil.h \
+           collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.h \
+           collision/gimpact/GIMPACT/Bullet/btGImpactShape.h \
+           collision/gimpact/GIMPACT/Bullet/btQuantization.h \
+           collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.h \
+           collision/gimpact/GIMPACT/core/gim_array.h \
+           collision/gimpact/GIMPACT/core/gim_basic_geometry_operations.h \
+           collision/gimpact/GIMPACT/core/gim_bitset.h \
+           collision/gimpact/GIMPACT/core/gim_box_collision.h \
+           collision/gimpact/GIMPACT/core/gim_box_set.h \
+           collision/gimpact/GIMPACT/core/gim_clip_polygon.h \
+           collision/gimpact/GIMPACT/core/gim_contact.h \
+           collision/gimpact/GIMPACT/core/gim_geom_types.h \
+           collision/gimpact/GIMPACT/core/gim_geometry.h \
+           collision/gimpact/GIMPACT/core/gim_hash_table.h \
+           collision/gimpact/GIMPACT/core/gim_linear_math.h \
+           collision/gimpact/GIMPACT/core/gim_math.h \
+           collision/gimpact/GIMPACT/core/gim_memory.h \
+           collision/gimpact/GIMPACT/core/gim_radixsort.h \
+           collision/gimpact/GIMPACT/core/gim_tri_collision.h
+
+SOURCES += collision/ChCCollisionUtils.cpp \
+collision/ChCModelBulletDEM.cpp \
+collision/ChCModelBulletBody.cpp \
+collision/ChCCollisionModel.cpp \
+collision/ChCModelBulletNode.cpp \
+collision/ChCModelBulletParticle.cpp \
+collision/ChCCollisionSystemBullet.cpp \
+collision/ChCModelBullet.cpp \
+collision/bullet/BulletWorldImporter/btBulletWorldImporter.cpp \
+collision/bullet/LinearMath/btAlignedAllocator.cpp \
+collision/bullet/LinearMath/btSerializer.cpp \
+collision/bullet/LinearMath/btConvexHull.cpp \
+collision/bullet/LinearMath/btQuickprof.cpp \
+collision/bullet/LinearMath/btGeometryUtil.cpp \
+collision/bullet/BulletFileLoader/btBulletFile.cpp \
+collision/bullet/BulletFileLoader/bChunk.cpp \
+collision/bullet/BulletFileLoader/bFile.cpp \
+collision/bullet/BulletFileLoader/bDNA.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp \
+collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConeShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp \
+collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp \
+collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp \
+collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp \
+collision/edgetempest/ChCAABB.cpp \
+collision/edgetempest/ChCGeometryCollider.cpp \
+collision/edgetempest/ChCAABBcollider.cpp \
+collision/edgetempest/ChCOBB.cpp \
+collision/edgetempest/ChCAABBTree.cpp \
+collision/edgetempest/ChCNarrowPhaseCollider.cpp \
+collision/edgetempest/ChCCollisionTree.cpp \
+collision/edgetempest/ChCOBBcollider.cpp \
+collision/edgetempest/ChCOBBTree.cpp \
+collision/gimpact/ConvexDecomposition/cd_hull.cpp \
+collision/gimpact/ConvexDecomposition/fitsphere.cpp \
+collision/gimpact/ConvexDecomposition/bestfit.cpp \
+collision/gimpact/ConvexDecomposition/cd_wavefront.cpp \
+collision/gimpact/ConvexDecomposition/raytri.cpp \
+collision/gimpact/ConvexDecomposition/concavity.cpp \
+collision/gimpact/ConvexDecomposition/ConvexDecomposition.cpp \
+collision/gimpact/ConvexDecomposition/meshvolume.cpp \
+collision/gimpact/ConvexDecomposition/planetri.cpp \
+collision/gimpact/ConvexDecomposition/vlookup.cpp \
+collision/gimpact/ConvexDecomposition/float_math.cpp \
+collision/gimpact/ConvexDecomposition/bestfitobb.cpp \
+collision/gimpact/ConvexDecomposition/splitplane.cpp \
+collision/gimpact/ConvexDecomposition/ConvexBuilder.cpp \
+collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp \
+collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.cpp \
+collision/gimpact/GIMPACT/Bullet/btGImpactShape.cpp \
+collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.cpp \
+collision/gimpact/GIMPACT/Bullet/btGImpactBvh.cpp \
+collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.cpp \
+collision/gimpact/GIMPACT/Bullet/btContactProcessing.cpp \
+collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.cpp \
+collision/gimpact/GIMPACT/core/gim_memory.cpp \
+collision/gimpact/GIMPACT/core/gim_contact.cpp \
+collision/gimpact/GIMPACT/core/gim_box_set.cpp \
+collision/gimpact/GIMPACT/core/gim_tri_collision.cpp \
+lcp/ChLcpConstraintThree.cpp \
+lcp/ChLcpIterativeAPGD.cpp \
+lcp/ChLcpVariablesGeneric.cpp \
+lcp/ChLcpIterativePCG.cpp \
+lcp/ChLcpVariablesBody.cpp \
+lcp/ChLcpIterativeSORmultithread.cpp \
+lcp/ChLcpConstraintTwoRollingN.cpp \
+lcp/ChLcpSolver.cpp \
+lcp/ChLcpSolverDEM.cpp \
+lcp/ChLcpConstraintThreeGeneric.cpp \
+lcp/ChLcpKstiffnessGeneric.cpp \
+lcp/ChLcpIterativeBB.cpp \
+lcp/ChLcpConstraintTwoContact.cpp \
+lcp/ChLcpConstraintTwoFrictionT.cpp \
+lcp/ChLcpConstraintNodeFrictionT.cpp \
+lcp/ChLcpVariablesNode.cpp \
+lcp/ChLcpSimplexSolver.cpp \
+lcp/ChLcpConstraintTwoContactN.cpp \
+lcp/ChLcpConstraintTwo.cpp \
+lcp/ChLcpConstraintTwoGenericBoxed.cpp \
+lcp/ChLcpIterativeMINRES.cpp \
+lcp/ChLcpConstraintTwoBodies.cpp \
+lcp/ChLcpSystemDescriptor.cpp \
+lcp/ChLcpConstraint.cpp \
+lcp/ChLcpConstraintTwoGeneric.cpp \
+lcp/ChLcpVariablesBodySharedMass.cpp \
+lcp/ChLcpConstraintThreeBBShaft.cpp \
+lcp/ChLcpConstraintTwoRollingT.cpp \
+lcp/Empty.cpp \
+lcp/ChLcpConstraintTwoFriction.cpp \
+lcp/ChLcpIterativePMINRES.cpp \
+lcp/ChLcpIterativeSOR.cpp \
+lcp/ChLcpConstraintNodeContactN.cpp \
+lcp/ChLcpVariablesBodyOwnMass.cpp \
+lcp/ChLcpIterativeJacobi.cpp \
+lcp/ChLcpConstraintTwoFrictionApprox.cpp \
+lcp/ChLcpVariables.cpp \
+lcp/ChLcpIterativeSymmSOR.cpp \
+geometry/ChCSphere.cpp \
+geometry/ChCGeometry.cpp \
+geometry/ChCLineCam.cpp \
+geometry/ChCLinePoly.cpp \
+geometry/ChCBox.cpp \
+geometry/ChCTriangleMeshConnected.cpp \
+geometry/ChCCone.cpp \
+geometry/ChCCylinder.cpp \
+geometry/ChCLine.cpp \
+geometry/ChCEllipsoid.cpp \
+geometry/ChCTriangle.cpp \
+parallel/ChThreadsPOSIX.cpp \
+parallel/ChThreadsWIN32.cpp \
+parallel/ChThreads.cpp \
+physics/ChContactContainer.cpp \
+physics/ChBody.cpp \
+physics/ChProximityContainerSPH.cpp \
+physics/ChShaftsTorsionSpring.cpp \
+physics/ChAssembly.cpp \
+physics/ChContinuumMaterial.cpp \
+physics/ChIndexedNodes.cpp \
+physics/ChLinkMate.cpp \
+physics/ChParticlesClones.cpp \
+physics/ChLimit.cpp \
+physics/ChContactContainerBase.cpp \
+physics/ChContactContainerNodes.cpp \
+physics/ChForce.cpp \
+physics/ChGlobal.cpp \
+physics/ChLinkBrake.cpp \
+physics/ChBodyAuxRef.cpp \
+physics/ChShaftsGear.cpp \
+physics/ChLinkforce.cpp \
+physics/ChLinkScrew.cpp \
+physics/ChShaftsClutch.cpp \
+physics/ChContact.cpp \
+physics/ChIterative.cpp \
+physics/ChLinkMarkers.cpp \
+physics/ChNodeBody.cpp \
+physics/ChSolvmin.cpp \
+physics/ChLinkLock.cpp \
+physics/ChLinkPulley.cpp \
+physics/ChIndexedParticles.cpp \
+physics/ChLinkClearance.cpp \
+physics/ChShaftsPlanetary.cpp \
+physics/ChLinkLinActuator.cpp \
+physics/ChLinkEngine.cpp \
+physics/ChConstraint.cpp \
+physics/ChLink.cpp \
+physics/ChLinkPneumaticActuator.cpp \
+physics/ChShaftsBody.cpp \
+physics/ChLinkPointSpline.cpp \
+physics/ChProbe.cpp \
+physics/ChLinkSpring.cpp \
+physics/ChSystem.cpp \
+physics/ChLinkDistance.cpp \
+physics/ChApidll.cpp \
+physics/ChContactRolling.cpp \
+physics/ChRef.cpp \
+physics/ChLinkMask.cpp \
+physics/ChContactDEM.cpp \
+physics/ChController.cpp \
+physics/ChFunction.cpp \
+physics/ChLinkContact.cpp \
+physics/ChMatterSPH.cpp \
+physics/ChContactContainerDEM.cpp \
+physics/ChLinkFastContact.cpp \
+physics/ChSystemOpenMP.cpp \
+physics/ChEvents.cpp \
+physics/ChConveyor.cpp \
+physics/ChProximityContainerBase.cpp \
+physics/ChFx.cpp \
+physics/ChNlsolver.cpp \
+physics/ChBodyDEM.cpp \
+physics/ChLinkTrajectory.cpp \
+physics/ChLinkNumdiff.cpp \
+physics/ChPhysicsItem.cpp \
+physics/ChMarker.cpp \
+physics/ChShaft.cpp \
+physics/ChLinkGear.cpp \
+physics/ChLinkRackPinion.cpp \
+physics/ChLinkMasked.cpp \
+physics/ChHistory.cpp \
+physics/ChControls.cpp \
+physics/ChContactNode.cpp \
+physics/ChIntegrator.cpp \
+physics/ChObject.cpp \
+physics/ChLinkWheel.cpp \
+physics/ChShaftsMotor.cpp \
+core/ChQuaternion.cpp \
+core/ChVector.cpp \
+core/ChClassRegister.cpp \
+core/ChMatrix.cpp \
+core/ChLog.cpp \
+core/ChMathematics.cpp \
+core/ChStream.cpp \
+core/ChSpmatrix.cpp \
+core/ChCoordsys.cpp \
+core/ChMemory.cpp \
+motion_functions/ChFunction_Noise.cpp \
+motion_functions/ChFunction_Base.cpp \
+motion_functions/ChFunction_Poly345.cpp \
+motion_functions/ChFunction_Const.cpp \
+motion_functions/ChFunction_Integrate.cpp \
+motion_functions/ChFunction_Ramp.cpp \
+motion_functions/ChFunction_Sine.cpp \
+motion_functions/ChFunction_Oscilloscope.cpp \
+motion_functions/ChFunction_Poly.cpp \
+motion_functions/ChFunction_Sequence.cpp \
+motion_functions/ChFunction_Derive.cpp \
+motion_functions/ChFunction_Operation.cpp \
+motion_functions/ChFunction_Mocap.cpp \
+motion_functions/ChFunction_Sigma.cpp \
+motion_functions/ChFunction_Fillet3.cpp \
+motion_functions/ChFunction_Matlab.cpp \
+motion_functions/ChFunction_Mirror.cpp \
+motion_functions/ChFunction_Repeat.cpp \
+motion_functions/ChFunction_Recorder.cpp \
+motion_functions/ChFunction_ConstAcc.cpp \
+pneumatica/ugello.cpp \
+pneumatica/ugello_controllato.cpp \
+pneumatica/pistone.cpp \
+pneumatica/valvola_3_2_prop.cpp \
+pneumatica/pistone_3_2.cpp \
+pneumatica/valvola_3_2.cpp \
+pneumatica/assepneumatico.cpp \
+pneumatica/sistema.cpp \
+pneumatica/pistone_3_2_prop.cpp \
+pneumatica/ugello_controllato_PA.cpp \
+pneumatica/ugello_controllato_RA.cpp \
+pneumatica/sis_attuatore_3_2_prop.cpp \
+pneumatica/sis_attuatore_3_2.cpp
diff --git a/SRC/ChronoEngine/License b/SRC/ChronoEngine/License
new file mode 100644
index 0000000..8f63273
--- /dev/null
+++ b/SRC/ChronoEngine/License
@@ -0,0 +1,10 @@
+Copyright (c) 2013, Chrono Development Team
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 
+ - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 
+ - Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROF [...]
\ No newline at end of file
diff --git a/SRC/ChronoEngine/collision/ChCCollisionInfo.h b/SRC/ChronoEngine/collision/ChCCollisionInfo.h
new file mode 100644
index 0000000..428409b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionInfo.h
@@ -0,0 +1,86 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCCOLLISIONINFO_H
+#define CHCCOLLISIONINFO_H
+
+///////////////////////////////////////////////////
+//
+//   ChCCollisionInfo.h
+//
+//   Class for passing basic data about contacts
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChVector.h"
+#include "collision/ChCCollisionModel.h"
+
+namespace chrono
+{
+namespace collision 
+{
+
+
+///   Class for passing basic data about contact pairs
+
+class ChCollisionInfo 
+{
+public:
+	ChCollisionModel* modelA; ///<  model A
+	ChCollisionModel* modelB; ///<  model B
+	ChVector<> vpA;			  ///<  coll.point on A, in abs coords
+	ChVector<> vpB;		      ///<  coll.point on B, in abs coords
+	ChVector<> vN; 		      ///<  coll.normal, respect to A, in abs coords
+	double distance;		  ///<  distance (negative for penetration)
+	float* reaction_cache;	  ///<  pointer to some persistent user cache of reactions
+
+
+		/// Basic default constructor
+	ChCollisionInfo()
+		{
+			modelA = modelB = 0;
+			vpA = vpB = VNULL;
+			vN.Set(1,0,0);
+			distance = 0.;
+			reaction_cache=0;
+		}
+
+			/// Swap models, that is modelA becomes modelB and viceversa; 
+			/// normal and so on are updates as well.
+	void SwapModels()
+		{
+			ChCollisionModel* modeltemp;
+			 modeltemp = modelA;
+			 modelA = modelB;
+			 modelB = modeltemp;
+			ChVector<> vtemp;
+			 vtemp = vpA;
+			 vpA = vpB;
+			 vpB = vtemp;
+			vN = Vmul(vN, -1.0);
+		}
+
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCCollisionModel.cpp b/SRC/ChronoEngine/collision/ChCCollisionModel.cpp
new file mode 100644
index 0000000..9914893
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionModel.cpp
@@ -0,0 +1,146 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionModel.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+  
+#include "ChCCollisionModel.h"
+#include "physics/ChBody.h"
+ 
+
+namespace chrono 
+{
+namespace collision 
+{
+ 
+
+static double default_model_envelope = 0.03;
+static double default_safe_margin = 0.01;
+
+
+ChCollisionModel::ChCollisionModel() 
+{
+	model_envelope    = (float)default_model_envelope;//  0.03f;
+	model_safe_margin = (float)default_safe_margin; //0.01f;
+};
+
+
+
+void ChCollisionModel::SetDefaultSuggestedEnvelope(double menv)
+{
+	default_model_envelope = menv;
+}
+
+void ChCollisionModel::SetDefaultSuggestedMargin(double mmargin)
+{
+	default_safe_margin = mmargin;
+}
+
+// static
+double ChCollisionModel::GetDefaultSuggestedEnvelope()
+{
+	return default_model_envelope;
+}
+
+// static
+double ChCollisionModel::GetDefaultSuggestedMargin()
+{
+	return default_safe_margin;
+}
+
+
+bool ChCollisionModel::AddConvexHullsFromFile(ChStreamInAscii& mstream, ChVector<>* pos, ChMatrix33<>* rot)
+{
+	std::vector< ChVector<double> > ptlist; 
+
+	char bufdata[200];
+	int  linechar =0;
+	while(!mstream.End_of_stream())
+	{
+		// read one line
+		linechar = 0;
+		while(!mstream.End_of_stream())
+		{
+			try{
+				mstream >> bufdata[linechar];
+			} catch(ChException mex){};
+			if ((bufdata[linechar]==(char)13) || (bufdata[linechar]==(char)10)) 
+			{ 
+				bufdata[linechar]=0; 
+				break; 
+			}
+			linechar++;
+			if (linechar >=200)
+				throw(ChException("Too long line in parsing"));
+		}
+		bufdata[linechar+1]=0;
+
+		bool parsedline = false;
+		if (bufdata[0]!=*"#")
+		{
+			parsedline = true;
+		}
+		if (strcmp(bufdata,"hull")==0)
+		{
+			if (ptlist.size())
+				this->AddConvexHull(ptlist,pos,rot);
+			ptlist.clear();
+			parsedline = true;
+		}
+		float vx, vy, vz;
+		if (sscanf(bufdata,"%g %g %g", &vx, &vy, &vz)==3)
+		{
+			ptlist.push_back(ChVector<>(vx,vy,vz));
+			parsedline = true;
+		}
+	}
+	if (ptlist.size())
+		this->AddConvexHull(ptlist,pos,rot);
+	ptlist.clear();
+	return true;
+}
+
+
+
+
+void ChCollisionModel::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+	mstream >> this->model_envelope;
+	mstream >> this->model_safe_margin;
+	
+}
+
+		
+void ChCollisionModel::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+	mstream << this->model_envelope;
+	mstream << this->model_safe_margin;
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/ChCCollisionModel.h b/SRC/ChronoEngine/collision/ChCCollisionModel.h
new file mode 100644
index 0000000..a620402
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionModel.h
@@ -0,0 +1,325 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_COLLISIONMODEL_H
+#define CHC_COLLISIONMODEL_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionModel.h
+//
+//   The collision model class. Each body in the
+//   simulation may have a collision model, defining
+//   the shape for collision detection.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <vector>
+#include "core/ChCoordsys.h"
+#include "core/ChMatrix.h"
+#include "core/ChApiCE.h"
+
+#include "geometry/ChCTriangleMesh.h"
+
+
+
+namespace chrono
+{
+
+// forward references
+class ChPhysicsItem;
+class ChBody;
+
+namespace collision
+{
+/// Shape types that can be created. Used so that shape type can be determined without going to bullet
+/// Both GPU and CPU Collision Models use this enum
+enum ShapeType
+{
+	SPHERE,
+	ELLIPSOID,
+	BOX,
+	CYLINDER,
+	CONVEXHULL,
+	TRIANGLEMESH,
+	BARREL,
+	RECT,				//Currently implemented on GPU only
+	DISC,				//Currently implemented on GPU only
+	ELLIPSE,			//Currently implemented on GPU only
+	CAPSULE,			//Currently implemented on GPU only
+	CONE,				//Currently implemented on GPU only
+	COMPOUND			//Currently implemented on GPU only
+};
+
+
+///
+/// Class containing the geometric model ready for collision detection.
+/// Each rigid body will have a ChCollisionModel.
+/// A ChCollisionModel will contain all the geometric description(s) 
+/// of the shape of the rigid body, for collision purposes.
+///
+
+class ChApi ChCollisionModel
+{
+
+
+public:
+
+  ChCollisionModel();
+
+  virtual ~ChCollisionModel() {};
+
+
+		/// Deletes all inserted geometries.
+		/// Also, if you begin the definition of a model, AFTER adding
+		/// the geometric description, remember to call the ClearModel().
+		/// MUST be inherited by child classes! (ex for resetting also BV hierarchies)
+  virtual int ClearModel() = 0;
+
+		/// Builds the BV hierarchy.
+		/// Call this function AFTER adding the geometric description.
+		/// MUST be inherited by child classes! (ex for bulding BV hierarchies)
+  virtual int BuildModel() = 0;
+
+
+	//
+	// GEOMETRY DESCRIPTION
+	//
+	//  The following functions must be called inbetween
+	//  the ClearModel() BuildModel() pair.
+	//  The class must implement automatic deletion of the created
+	//  geometries at class destruction time and at ClearModel()
+	//  Return value is true if the child class implements the
+	//  corresponding type of geometry.
+
+		/// Add a sphere shape to this model, for collision purposes
+  virtual bool AddSphere   (double radius,			///< the radius of the sphere
+							ChVector<>* pos=0		///< the position of the sphere in model coordinates
+							)=0;
+
+  		/// Add an ellipsoid shape to this model, for collision purposes
+  virtual bool AddEllipsoid   (double rx, 			///< the rad on x axis
+							   double ry,			///< the rad on y axis
+							   double rz,			///< the rad on z axis
+							   ChVector<>* pos=0,	///< the position of the ellipsoid
+							   ChMatrix33<>* rot=0	///< the matrix defining rotation (orthogonal)
+							   )=0;
+
+		/// Add a box shape to this model, for collision purposes
+  virtual bool AddBox      (double hx, 				///< the halfsize on x axis
+							double hy,				///< the halfsize on y axis
+							double hz,				///< the halfsize on z axis
+							ChVector<>* pos=0,		///< the position of the box COG
+							ChMatrix33<>* rot=0		///< the rotation of the box - matrix must be orthogonal
+							)=0;
+
+		/// Add a cylinder to this model (default axis on Y direction), for collision purposes
+  virtual bool AddCylinder (double rx, double rz, double hy, ChVector<>* pos=0, ChMatrix33<>* rot=0)=0;
+
+		/// Add a cone to this model (default axis on Y direction), for collision purposes
+  virtual bool AddCone (double rx, double rz, double hy, ChVector<>* pos=0, ChMatrix33<>* rot=0)=0;
+
+		/// Add a convex hull to this model. A convex hull is simply a point cloud that describe
+		/// a convex polytope. Connectivity between the vertexes, as faces/edges in triangle meshes is not necessary.
+		/// Points are passed as a list, that is instantly copied into the model.
+  virtual bool AddConvexHull (std::vector<ChVector<double> >& pointlist, ChVector<>* pos=0, ChMatrix33<>* rot=0)=0;
+
+		/// Add a triangle mesh to this model, passing a triangle mesh (do not delete the triangle mesh
+		/// until the collision model, because depending on the implementation of inherited ChCollisionModel
+		/// classes, maybe the triangle is referenced via a striding interface or just copied)
+		/// Note: if possible, in sake of high performance, avoid triangle meshes and prefer simplified 
+		/// representations as compounds of convex shapes of boxes/spheres/etc.. type. See functions above.
+  virtual bool AddTriangleMesh (const geometry::ChTriangleMesh& trimesh,	///< the triangle mesh
+								bool is_static,			///< true only if model doesn't move (es.a terrain). May improve performance
+								bool is_convex,			///< true if mesh convex hull is used (only for simple mesh). May improve robustness
+								ChVector<>* pos=0, ChMatrix33<>* rot=0 ///< displacement respect to COG (optional)
+								)=0;
+
+  		/// Add a barrel-like shape to this model (main axis on Y direction), for collision purposes.
+		/// The barrel shape is made by lathing an arc of an ellipse around the vertical Y axis.
+		/// The center of the ellipse is on Y=0 level, and it is ofsetted by R_offset from 
+		/// the Y axis in radial direction. The two radii of the ellipse are R_vert (for the 
+		/// vertical direction, i.e. the axis parellel to Y) and R_hor (for the axis that
+		/// is perpendicular to Y). Also, the solid is clamped with two discs on the top and
+		/// the bottom, at levels Y_low and Y_high. 
+  virtual bool AddBarrel (double Y_low, double Y_high, double R_vert, double R_hor, double R_offset, ChVector<>* pos=0, ChMatrix33<>* rot=0)=0;
+
+		/// Add all shapes already contained in another model.
+		/// If possible, child classes implement this so that underlying shapes are 
+		/// shared (not copied) among the models.
+  virtual bool AddCopyOfAnotherModel (ChCollisionModel* another) = 0;
+
+		/// Add a cluster of convex hulls by a '.chulls' file description. The file is an ascii text that contains
+		/// many lines with "[x] [y] [z]" coordinates of the convex hulls. Hulls are separated by lines with "hull".
+		/// Inherited classes should not need to implement/overload this, because this base implementation 
+		/// basically calls AddConvexHull() n times while parsing the file, that is enough.
+  virtual bool AddConvexHullsFromFile(ChStreamInAscii& mstream, ChVector<>* pos=0, ChMatrix33<>* rot=0);
+
+
+  // OTHER FUNCTIONS
+  //
+
+
+  		/// Gets the pointer to the client owner ChPhysicsItem.
+		/// MUST be implemented by child classes!
+  virtual ChPhysicsItem* GetPhysicsItem() = 0;
+
+		/// Sets the position and orientation of the collision
+		/// model as the rigid body current position.
+		/// MUST be implemented by child classes!
+  virtual void SyncPosition()=0;
+
+		/// By default, all collsion objects belong to family n.0, 
+		/// but you can set family in range 0..15. This is used when
+		/// the objects collided with another: the contact is created
+		/// only if the family is within the 'family mask' of the other,
+		/// and viceversa.
+		/// NOTE: these functions have NO effect if used before you add 
+		///  the body to a ChSystem, using AddBody(). Use after AddBody(). 
+		/// MUST be implemented by child classes!
+  virtual void SetFamily(int mfamily)=0;
+  virtual int  GetFamily()=0;
+
+		/// By default, family mask is all turned on, so all families
+		/// can collide with this object, but you can turn on-off some bytes
+		/// of this mask so that some families do not collide.
+		/// When two objects collide, the contact is created
+		/// only if the family is within the 'family mask' of the other,
+		/// and viceversa.
+		/// NOTE: these functions have NO effect if used before you add 
+		///  the body to a ChSystem, using AddBody(). Use after AddBody(). 
+		/// MUST be implemented by child classes!
+  virtual void SetFamilyMaskNoCollisionWithFamily(int mfamily)=0;
+  virtual void SetFamilyMaskDoCollisionWithFamily(int mfamily)=0;
+
+		/// Tells if the family mask of this collision object allows
+		/// for the collision with another collision object belonging to 
+		/// a given family.
+		/// NOTE: this function has NO effect if used before you add 
+		///  the body to a ChSystem, using AddBody(). Use after AddBody(). 
+  virtual bool GetFamilyMaskDoesCollisionWithFamily(int mfamily)=0;
+
+
+	// TOLERANCES, ENVELOPES, THRESHOLDS
+	//
+
+		/// Sets the suggested collision 'inward safe margin' for the 
+		/// shapes to be added from now on, using the AddBox,
+		/// AddCylinder etc (where, if this margin is too high for some
+		/// thin or small shapes, it may be clamped).. 
+		/// If dist<0 and interpenetation occurs (ex.for numerical errors) within 
+		/// this 'safe margin' inward range, collision detection is still fast 
+		/// and reliable (beyond this, for deep penetrations, CD still works, 
+		/// but might be slower and less reliable)
+		/// Side effect: think at the margin as a radius of a 'smoothing' fillet
+		/// on all corners of the shapes - that's why you cannot exceed with this...
+  virtual void SetSafeMargin(double amargin)
+		{
+			model_safe_margin = (float)amargin;
+		}
+		/// Returns the inward safe margin (see SetSafeMargin() )
+  virtual float GetSafeMargin()
+		{
+			return model_safe_margin;
+		}
+
+		/// Sets the suggested collision outward 'envelope' (used from shapes
+		/// added, from now on, to this collision model).  This 'envelope' is a
+		/// surrounding invisible volume which extends outward from the 
+		/// surface, and it is used to detect contacts a bit before shapes
+		/// come into contact, i.e. when dist>0. However contact points will stay
+		/// on the true surface of the geometry, not on the external surface of the 
+		/// envelope.
+		/// Side effect: AABB are 'expanded' outward by this amount, so if you
+		/// exagerate with this value, CD might be slower and too sensible.
+		/// On the other hand, if you set this value to 0, contacts are detected
+		/// only for dist<=0, thus causing unstable simulation.
+  virtual void SetEnvelope(double amargin)
+		{
+			model_envelope = (float)amargin;
+		}
+		/// Returns the outward safe margin (see SetEnvelope() )
+  virtual float GetEnvelope()
+		{
+			return model_envelope;
+		}
+
+		/// Returns the Type of Shape 
+  virtual ShapeType GetShapeType()
+		{
+			return model_type;
+		}
+
+  static void SetDefaultSuggestedEnvelope(double menv);
+  static void SetDefaultSuggestedMargin(double mmargin);
+  static double GetDefaultSuggestedEnvelope();
+  static double GetDefaultSuggestedMargin();
+
+		/// Returns the axis aligned bounding box (AABB) of the collision model,
+		/// i.e. max-min along the x,y,z world axes. Remember that SyncPosition()
+		/// should be invoked before calling this.
+		/// MUST be implemented by child classes! 
+  virtual void GetAABB(ChVector<>& bbmin, ChVector<>& bbmax) const = 0;
+
+  void SetBody(ChBody* mbo) {mbody = mbo;};
+
+			//
+			// STREAMING
+			//
+
+		/// Method to allow deserializing a persistent binary archive (ex: a file)
+		/// into transient data.
+  virtual void StreamIN(ChStreamInBinary& mstream);
+
+		/// Method to allow serializing transient data into a persistent
+		/// binary archive (ex: a file).
+  virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+
+protected:
+
+	virtual float GetSuggestedFullMargin()
+		{
+			return model_envelope + model_safe_margin;
+		}
+				// Maximum envelope: surrounding volume from surface
+				// to the exterior
+	float model_envelope;
+
+				// This is the max.value to be used for fast penetration
+				// contact detection.
+	float model_safe_margin;
+
+				// This is the type of shape used for collision model
+	ShapeType model_type;
+
+	ChBody* mbody;
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCCollisionPair.h b/SRC/ChronoEngine/collision/ChCCollisionPair.h
new file mode 100644
index 0000000..fa99d31
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionPair.h
@@ -0,0 +1,217 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_COLLISIONPAIR_H
+#define CHC_COLLISIONPAIR_H
+
+//////////////////////////////////////////////////
+//
+//   ChCCollisionPair.h
+//
+//   After collision detection has been computed,
+//   some 'collision pairs' are detected and
+//   reported. Class for such 'collision pairs'
+//   objects is defined here.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "geometry/ChCGeometry.h"
+
+
+using namespace chrono::geometry;
+
+namespace chrono
+{
+namespace collision
+{
+
+
+
+
+///
+/// Class for storing information about a collision point.
+///
+
+
+class ChCollisionPair
+{
+public:
+		/// Basic constructor
+	ChCollisionPair()
+		{
+			geo1 = geo2 = 0;
+			p1 = p2 = VNULL;
+			normal.Set(1,0,0);
+			norm_dist = 0.;
+			just_intersection = false;
+			reactions_cache=0;
+		}
+
+		/// Constructor for case of contact point correctly estimated
+	ChCollisionPair(chrono::geometry::ChGeometry* mgeo1,
+					chrono::geometry::ChGeometry* mgeo2,
+					const ChVector<>& mp1,
+					const ChVector<>& mp2,
+					const ChVector<float>& mnormal,
+					float* mreaction_cache=0)
+
+		{
+			this->Set(mgeo1, mgeo2, mp1, mp2, mnormal, mreaction_cache);
+		}
+
+			/// Constructor for case of just intersection
+	ChCollisionPair(chrono::geometry::ChGeometry* mgeo1,
+					chrono::geometry::ChGeometry* mgeo2)
+		{
+			geo1 = mgeo1;
+			geo2 = mgeo2;
+			p1 = p2 = VNULL;
+			normal.Set(1,0,0);
+			norm_dist = 0.;
+			just_intersection = true;
+		}
+
+			/// Set all data at once (better: use the custom constructor)
+	void Set(		chrono::geometry::ChGeometry* mgeo1,
+					chrono::geometry::ChGeometry* mgeo2,
+					const ChVector<>& mp1,
+					const ChVector<>& mp2,
+					const ChVector<float>& mnormal, 
+					float* mreaction_cache=0)
+		{
+			geo1 = mgeo1;
+			geo2 = mgeo2;
+			p1 = mp1;
+			p2 = mp2;
+			normal = mnormal;
+			just_intersection = false;
+			reactions_cache = mreaction_cache;
+
+			norm_dist = Vdot(mnormal,mp2-mp1);
+		}
+
+			/// Swap geometries, that is
+			/// geo1 becomes geo2 and viceversa; normal and so on are updates as well.
+	void SwapGeometries()
+	{
+		chrono::geometry::ChGeometry* gtemp;
+		 gtemp = geo1;
+		 geo1 = geo2;
+		 geo2 = gtemp;
+		ChVector<> vtemp;
+		 vtemp = p1;
+		 p1 = p2;
+		 p2 = vtemp;
+		normal = Vmul(normal, -1.0);
+	}
+
+			/// Fetches normal and U,V impulsive reactions, as previously stored in a 
+			/// persistent contact manifold maintained by the collision engine. If no cache, set as 0,0,0
+	void CacheFetchSpeedSolutionFromManifold(float& mN, float& mU, float& mV)
+	{
+		if (reactions_cache)
+		{
+			mN = reactions_cache[0];
+			mU = reactions_cache[1];
+			mV = reactions_cache[2];
+		}
+	}
+			/// Fetches normal and U,V 'positional' reactions, as previously stored in a 
+			/// persistent contact manifold maintained by the collision engine. If no cache, set as 0,0,0
+	void CacheFetchPositionSolutionFromManifold(float& mN, float& mU, float& mV)
+	{
+		if (reactions_cache)
+		{
+			mN = reactions_cache[3];
+			mU = reactions_cache[4];
+			mV = reactions_cache[5];
+		}
+	}
+			/// Stores normal and U,V reactions into a persistent contact manifold 
+			/// maintained by the collision engine (if any)
+	void CacheStoreSpeedSolutionIntoManifold(const float mN, const float mU, const float mV)
+	{
+		if (reactions_cache)
+		{
+			reactions_cache[0] = mN;
+			reactions_cache[1] = mU;
+			reactions_cache[2] = mV;
+		}
+	}
+			/// Stores normal and U,V 'positional' reactions into a persistent contact manifold 
+			/// maintained by the collision engine (if any)
+	void CacheStorePositionSolutionIntoManifold(const float mN, const float mU, const float mV)
+	{
+		if (reactions_cache)
+		{
+			reactions_cache[3] = mN;
+			reactions_cache[4] = mU;
+			reactions_cache[5] = mV;
+		}
+	}
+
+	// DATA
+
+	chrono::geometry::ChGeometry* geo1;	///< pointer to 1st geometry which generated this collision pair
+	chrono::geometry::ChGeometry* geo2;	///< pointer to 2nd geometry which generated this collision pair
+
+	ChVector<> p1;	///< max penetration point on geo1, after refining, in abs space
+	ChVector<> p2;	///< max penetration point on geo2, after refining, in abs space
+
+	ChVector<float> normal;	///< normal, on surface of master reference (geo1)
+	double norm_dist;	    ///< penetration distance (negative if going inside) after refining
+
+	bool just_intersection;	///< if true, only reports that two geometries are intersection, but no info is reliable about normal, p1 or p2.
+
+	float* reactions_cache; ///< points to an array[3] of N,U,V reactions which might be stored in a persistent contact manifold in the collision engine
+
+};
+
+
+
+
+// codes for tri_type  ***OBSOLETE***
+
+#define CH_TRICOLL_SURFACE			0	// surface type, curved and refinable
+#define CH_TRICOLL_SURFACE_TRIANGLE 7	// surface type, basic triangle
+
+#define CH_TRICOLL_EDGE			1	// edge, curved and refinable
+#define CH_TRICOLL_EDGE_LIMITU0	2	// limiting edge on a patch
+#define CH_TRICOLL_EDGE_LIMITU1	3	// limiting edge on a patch
+#define CH_TRICOLL_EDGE_LIMITV0	4	// limiting edge on a patch
+#define CH_TRICOLL_EDGE_LIMITV1	5	// limiting edge on a patch
+#define CH_TRICOLL_EDGE_TRI_A	8	// edge triangle 1-2
+#define CH_TRICOLL_EDGE_TRI_B	9	// edge triangle 2-3
+#define CH_TRICOLL_EDGE_TRI_C	10  // edge triangle 3-1
+
+#define CH_TRICOLL_VERTEX		6	// vertex type (1st of triangle)
+#define CH_TRICOLL_VERTEX_TRI_A	12	// vertex of triangle
+#define CH_TRICOLL_VERTEX_TRI_B	13	// vertex of triangle
+#define CH_TRICOLL_VERTEX_TRI_C	14	// vertex of triangle
+
+#define CH_TRICOLL_TRIANGLE		11	// has vertex, edge, surface
+
+#define CH_TRICOLL_SPHERE		15	// sphere (1st of triangle is center, 2nd.x is rad);
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCCollisionSystem.h b/SRC/ChronoEngine/collision/ChCCollisionSystem.h
new file mode 100644
index 0000000..50ea165
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionSystem.h
@@ -0,0 +1,208 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_COLLISIONSYSTEM_H
+#define CHC_COLLISIONSYSTEM_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionSystem.h
+//
+//   Header for base class for generic collision 
+//   engine.
+//   Class must be specialized by children classes.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "collision/ChCCollisionInfo.h"
+#include "core/ChFrame.h"
+#include "core/ChApiCE.h"
+
+namespace chrono 
+{
+
+// forward references
+class ChBody; 
+class ChLcpVariablesBody;
+class ChContactContainerBase;
+class ChProximityContainerBase;
+
+
+/// Namespace with classes for collision detection
+namespace collision 
+{
+
+
+
+///
+/// Class to be used as a callback interface for the narrow phase collision 
+/// system. For each contact point found during the Run() execution
+/// of the ChCollisionSystem, the function ChNarrowPhaseCallback() is called.
+/// The user should implement an inherited class and
+/// implement a custom NarrowCallback() function.
+///
+
+class ChApi ChNarrowPhaseCallback
+{
+public:
+			/// Callback, used to report contact points found by default
+			/// narrow phase collision step.
+			/// This must be implemented by a child class of ChNarrowPhaseCallback
+	virtual void NarrowCallback (
+					const ChCollisionInfo& 
+					) 
+	{
+		// do nothing by default - inherit and implement it if you want to use a custom narrow callback
+	};
+};
+
+
+
+///
+/// Class to be used as a callback interface for the broad-phase collision 
+/// system. For each 'near enough' pair of shapes found during the Run() execution
+/// of the ChCollisionSystem, the function ChBroadPhaseCallback() is called.
+/// The user could optionally implement an inherited class and
+/// implement a custom BroadCallback(). 
+///
+
+class ChApi ChBroadPhaseCallback
+{
+public:
+			/// Callback used to report 'near enough' pairs of models.
+			/// This must be implemented by a child class of ChBroadPhaseCallback.
+			/// Return false to skip narrow-phase contact generation for this pair of bodies.
+	bool BroadCallback(
+				ChCollisionModel*  ,	///< pass 1st model
+				ChCollisionModel*  	///< pass 2nd model
+				) 
+	{
+		// do nothing by default - please inherit and implement it!
+		return true;
+	};
+};
+
+
+
+///
+/// Base class for generic collision engine.
+/// Most methods are 'pure virtual': they need to be implemented
+/// by child classes.
+/// 
+
+class ChApi ChCollisionSystem
+{
+  public:
+
+	ChCollisionSystem(unsigned int = 16000, double = 500) 
+				{
+					narrow_callback=0;
+					broad_callback=0;
+				};
+
+	virtual ~ChCollisionSystem() {};
+
+					/// Clears all data instanced by this algorithm
+					/// if any (like persistent contact manifolds)
+    virtual void Clear(void) = 0;
+
+					/// Adds a collision model to the collision
+					/// engine (custom data may be allocated).
+    virtual void Add(ChCollisionModel* model) = 0;
+
+					/// Removes a collision model from the collision
+					/// engine (custom data may be deallocated).
+    virtual void Remove(ChCollisionModel* model) = 0;
+
+					/// Removes all collision models from the collision
+					/// engine (custom data may be deallocated).
+    //virtual void RemoveAll() = 0;
+
+					/// RUN THE ALGORITHM and finds the contacts.
+					/// This is the most important function - it will be called
+					/// at each simulation step.
+					/// Children classes _must_ implement this.
+	virtual void Run() = 0;
+
+					/// After the Run() has completed, you can call this function to
+					/// fill a 'contact container', that is an object inherited from class 
+					/// ChContactContainerBase. For instance ChSystem, after each Run()
+					/// collision detection, calls this method multiple times for all contact containers in the system,
+					/// Children classes _must_ implement this.
+					/// The basic behavior of the implementation should be the following: collision system 
+					/// will call in sequence the functions BeginAddContact(), AddContact() (x n times), 
+					/// EndAddContact() of the contact container.
+					/// In case a specialized implementation (ex. a GPU parallel collision engine)
+					/// finds that the contact container is a specialized one (ex with a GPU buffer) 
+					/// it can call more performant methods to add directly the contacts in batches, for instance
+					/// by recognizing that he can call, say, some special AddAllContactsAsGpuBuffer() instead of many AddContact().
+	virtual void ReportContacts(ChContactContainerBase* mcontactcontainer) = 0;
+
+					/// After the Run() has completed, you can call this function to
+					/// fill a 'proximity container' (container of narrow phase pairs), that is 
+					/// an object inherited from class ChProximityContainerBase. For instance ChSystem, after each Run()
+					/// collision detection, calls this method multiple times for all proximity containers in the system,
+					/// Children classes _must_ implement this.
+					/// The basic behavior of the implementation should be the following: collision system 
+					/// will call in sequence the functions BeginAddProximities(), AddProximity() (x n times), 
+					/// EndAddProximities() of the proximity container.
+					/// In case a specialized implementation (ex. a GPU parallel collision engine)
+					/// finds that the proximity container is a specialized one (ex with a GPU buffer) 
+					/// it can call more performant methods to add directly the proximities in batches, for instance
+					/// by recognizing that he can call, say, some special AddAllProximitiesAsGpuBuffer() instead of many AddProximity().
+	virtual void ReportProximities(ChProximityContainerBase* mproximitycontainer) = 0;
+
+					/// Sets the user ChBroadPhaseCallback to be used
+					/// to tell the near-enough pairs found during the Run()
+					/// execution. It will be executed for near enough pair of bodies.
+	void SetBroadPhaseCallback(ChBroadPhaseCallback* mcallback) {broad_callback = mcallback;} 
+
+					/// Sets the used ChNarrowPhaseCallback to be used
+					/// to report the contacts found during the Run()
+					/// execution. It will be executed for each contact point.
+	void SetNarrowPhaseCallback(ChNarrowPhaseCallback* mcallback) {narrow_callback = mcallback;}
+					
+
+					/// This will be used to recover results from RayHit() raycasting
+	struct ChRayhitResult
+	{
+		bool				hit;			/// if true, there was an hit - look following date for infos
+		ChVector<>			abs_hitPoint;	/// hit point in absolute space coordinates
+		ChVector<>			abs_hitNormal;	/// normal to surface in absolute space coordinates
+		double				dist_factor;	/// from 0 .. 1 means the distance of hit point along the segment
+		ChCollisionModel*	hitModel;		/// pointer to hitten model
+	};
+					/// Perform a ray-hit test with the collision models.
+	virtual bool RayHit(const ChVector<>& from, const ChVector<>& to, ChRayhitResult& mresult) = 0;
+	
+
+protected:
+
+	ChBroadPhaseCallback*  broad_callback;	// user callback for each near-enough pair of shapes 
+	ChNarrowPhaseCallback* narrow_callback;	// user callback for each contact	
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCCollisionSystemBullet.cpp b/SRC/ChronoEngine/collision/ChCCollisionSystemBullet.cpp
new file mode 100644
index 0000000..7d0abea
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionSystemBullet.cpp
@@ -0,0 +1,256 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionSystemBullet.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+   
+ 
+#include "collision/ChCCollisionSystemBullet.h"
+#include "collision/ChCModelBullet.h"
+#include "collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h"
+#include "physics/ChBody.h"
+#include "physics/ChContactContainerBase.h"
+#include "physics/ChProximityContainerBase.h"
+#include "LinearMath/btPoolAllocator.h"
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+/*
+void defaultChronoNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, btDispatcherInfo& dispatchInfo)
+{
+	btCollisionDispatcher::defaultNearCallback(collisionPair, dispatcher, dispatchInfo);
+	if (broad_callback)
+		broad_callback(collisionPair, dispatcher, dispatchInfo);
+}
+*/
+
+ChCollisionSystemBullet::ChCollisionSystemBullet(unsigned int max_objects, double scene_size)
+{
+	// btDefaultCollisionConstructionInfo conf_info(...); ***TODO***
+	bt_collision_configuration = new btDefaultCollisionConfiguration(); 
+	bt_dispatcher = new btCollisionDispatcher(bt_collision_configuration);  
+	
+	  //***OLD***
+	
+	btScalar sscene_size = (btScalar)scene_size;
+	 btVector3	worldAabbMin(-sscene_size,-sscene_size,-sscene_size);
+	 btVector3	worldAabbMax(sscene_size,sscene_size,sscene_size);
+	bt_broadphase = new bt32BitAxisSweep3(worldAabbMin,worldAabbMax, max_objects, 0, true); // true for disabling raycast accelerator
+	
+	  //***NEW***
+	//bt_broadphase = new btDbvtBroadphase();
+
+
+
+	bt_collision_world = new btCollisionWorld(bt_dispatcher, bt_broadphase, bt_collision_configuration);
+
+	// custom collision for sphere-sphere case ***OBSOLETE***
+	//bt_dispatcher->registerCollisionCreateFunc(SPHERE_SHAPE_PROXYTYPE,SPHERE_SHAPE_PROXYTYPE,new btSphereSphereCollisionAlgorithm::CreateFunc);
+
+	// register custom collision for GIMPACT mesh case too
+	btGImpactCollisionAlgorithm::registerAlgorithm(bt_dispatcher);
+}
+
+
+ChCollisionSystemBullet::~ChCollisionSystemBullet()
+{
+	if(bt_collision_world) delete bt_collision_world;
+	if(bt_broadphase) delete bt_broadphase;
+	if(bt_dispatcher) delete bt_dispatcher; 
+	if(bt_collision_configuration) delete bt_collision_configuration;
+}
+
+void ChCollisionSystemBullet::Clear(void)
+{
+	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
+	for (int i=0;i<numManifolds;i++)
+	{
+		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
+		contactManifold->clearManifold();
+	}
+}   
+				
+
+
+void ChCollisionSystemBullet::Add(ChCollisionModel* model)
+{
+	if (((ChModelBullet*)model)->GetBulletModel()->getCollisionShape())
+	{
+		model->SyncPosition();
+		bt_collision_world->addCollisionObject(((ChModelBullet*)model)->GetBulletModel(),
+			((ChModelBullet*)model)->GetFamilyGroup(),
+			((ChModelBullet*)model)->GetFamilyMask());
+	}
+}
+		 		
+void ChCollisionSystemBullet::Remove(ChCollisionModel* model)
+{
+	if (((ChModelBullet*)model)->GetBulletModel()->getCollisionShape())
+	{
+		bt_collision_world->removeCollisionObject(((ChModelBullet*)model)->GetBulletModel());
+	}
+}
+
+
+void ChCollisionSystemBullet::Run()
+{
+	if (bt_collision_world)
+	{
+		bt_collision_world->performDiscreteCollisionDetection(); 
+	}
+}
+
+
+void ChCollisionSystemBullet::ReportContacts(ChContactContainerBase* mcontactcontainer)
+{
+	// This should remove all old contacts (or at least rewind the index)
+	mcontactcontainer->BeginAddContact();
+
+	ChCollisionInfo icontact;
+
+	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
+	for (int i=0;i<numManifolds;i++)
+	{
+		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
+		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
+		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
+		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());
+	 
+		icontact.modelA = (ChCollisionModel*)obA->getUserPointer();
+		icontact.modelB = (ChCollisionModel*)obB->getUserPointer();
+
+		double envelopeA = icontact.modelA->GetEnvelope();
+		double envelopeB = icontact.modelB->GetEnvelope();
+		
+		double marginA = icontact.modelA->GetSafeMargin();
+		double marginB = icontact.modelB->GetSafeMargin();
+
+		// Execute custom broadphase callback, if any
+		bool do_narrow_contactgeneration = true;
+		if (this->broad_callback)
+			do_narrow_contactgeneration = this->broad_callback->BroadCallback(icontact.modelA, icontact.modelB);
+
+		if (do_narrow_contactgeneration)
+		{
+			int numContacts = contactManifold->getNumContacts();
+
+			for (int j=0;j<numContacts;j++)
+			{
+				btManifoldPoint& pt = contactManifold->getContactPoint(j);
+
+				if (pt.getDistance() < marginA+marginB) // to discard "too far" constraints (the Bullet engine also has its threshold)
+				{
+					btVector3 ptA = pt.getPositionWorldOnA();
+					btVector3 ptB = pt.getPositionWorldOnB(); 
+					
+					icontact.vpA.Set(ptA.getX(), ptA.getY(), ptA.getZ());
+					icontact.vpB.Set(ptB.getX(), ptB.getY(), ptB.getZ());
+					
+					icontact.vN.Set( -pt.m_normalWorldOnB.getX(), 
+									 -pt.m_normalWorldOnB.getY(),
+									 -pt.m_normalWorldOnB.getZ());
+					icontact.vN.Normalize(); 
+
+					double ptdist = pt.getDistance();
+
+					icontact.vpA = icontact.vpA - icontact.vN*envelopeA;
+					icontact.vpB = icontact.vpB + icontact.vN*envelopeB;
+					icontact.distance = ptdist + envelopeA + envelopeB;	
+
+					icontact.reaction_cache = pt.reactions_cache;
+
+					// Execute some user custom callback, if any
+					if (this->narrow_callback)
+						this->narrow_callback->NarrowCallback(icontact);
+
+					// Add to contact container
+					mcontactcontainer->AddContact(icontact); 
+				}
+
+			}
+		}
+
+		//you can un-comment out this line, and then all points are removed
+		//contactManifold->clearManifold();	
+	}
+	mcontactcontainer->EndAddContact();
+}
+
+
+void ChCollisionSystemBullet::ReportProximities(ChProximityContainerBase* mproximitycontainer)
+{
+	mproximitycontainer->BeginAddProximities();
+
+	int numManifolds = bt_collision_world->getDispatcher()->getNumManifolds();
+	for (int i=0;i<numManifolds;i++)
+	{
+		btPersistentManifold* contactManifold =  bt_collision_world->getDispatcher()->getManifoldByIndexInternal(i);
+		btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
+		btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
+		contactManifold->refreshContactPoints(obA->getWorldTransform(),obB->getWorldTransform());
+	 
+		ChCollisionModel* modelA = (ChCollisionModel*)obA->getUserPointer();
+		ChCollisionModel* modelB = (ChCollisionModel*)obB->getUserPointer();
+
+		// Add to proximity container
+		mproximitycontainer->AddProximity(modelA, modelB);
+	}
+	mproximitycontainer->EndAddProximities();
+}
+
+
+
+
+bool ChCollisionSystemBullet::RayHit(const ChVector<>& from, const ChVector<>& to, ChRayhitResult& mresult)
+{
+	btVector3 btfrom((btScalar)from.x, (btScalar)from.y, (btScalar)from.z);
+	btVector3 btto  ((btScalar)to.x,   (btScalar)to.y,   (btScalar)to.z);
+
+	btCollisionWorld::ClosestRayResultCallback rayCallback(btfrom,btto);
+
+	this->bt_collision_world->rayTest(btfrom, btto, rayCallback);
+
+	if (rayCallback.hasHit())
+	{
+		mresult.hitModel = (ChCollisionModel*)(rayCallback.m_collisionObject->getUserPointer());
+		if (mresult.hitModel)
+		{
+			mresult.hit = true;
+			mresult.abs_hitPoint.Set(rayCallback.m_hitPointWorld.x(),rayCallback.m_hitPointWorld.y(),rayCallback.m_hitPointWorld.z());
+			mresult.abs_hitNormal.Set(rayCallback.m_hitNormalWorld.x(),rayCallback.m_hitNormalWorld.y(),rayCallback.m_hitNormalWorld.z());
+			mresult.abs_hitNormal.Normalize();
+			mresult.hit = true;
+			mresult.dist_factor = rayCallback.m_closestHitFraction;
+			return true;
+		}
+	}
+	mresult.hit = false;
+	return false;
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/collision/ChCCollisionSystemBullet.h b/SRC/ChronoEngine/collision/ChCCollisionSystemBullet.h
new file mode 100644
index 0000000..ce4a416
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionSystemBullet.h
@@ -0,0 +1,117 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_COLLISIONSYSTEMBULLET_H
+#define CHC_COLLISIONSYSTEMBULLET_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionSystemBullet.h
+//
+//   Header for class for collision engine based on
+//   the 'Bullet' library.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+#include "collision/ChCCollisionSystem.h"
+#include "collision/bullet/btBulletCollisionCommon.h" 
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+///
+/// Class for collision engine based on the 'Bullet' library.
+/// Contains either the broadphase and the narrow phase Bullet
+/// methods.
+/// 
+
+class ChApi ChCollisionSystemBullet : public ChCollisionSystem
+{
+  public:
+
+	ChCollisionSystemBullet(unsigned int max_objects = 16000, double scene_size = 500);
+	virtual ~ChCollisionSystemBullet();
+
+					/// Clears all data instanced by this algorithm
+					/// if any (like persistent contact manifolds)
+    virtual void Clear(void);
+
+					/// Adds a collision model to the collision
+					/// engine (custom data may be allocated).
+    virtual void Add(ChCollisionModel* model);
+
+					/// Removes a collision model from the collision
+					/// engine (custom data may be deallocated).
+    virtual void Remove(ChCollisionModel* model);
+
+					/// Removes all collision models from the collision
+					/// engine (custom data may be deallocated).
+    //virtual void RemoveAll();
+
+					/// Run the algorithm and finds all the contacts.
+					/// (Contacts will be managed by the Bullet persistent contact cache).
+	virtual void Run();
+
+					/// After the Run() has completed, you can call this function to
+					/// fill a 'contact container', that is an object inherited from class 
+					/// ChContactContainerBase. For instance ChSystem, after each Run()
+					/// collision detection, calls this method multiple times for all contact containers in the system,
+					/// The basic behavior of the implementation is the following: collision system 
+					/// will call in sequence the functions BeginAddContact(), AddContact() (x n times), 
+					/// EndAddContact() of the contact container.
+	virtual void ReportContacts(ChContactContainerBase* mcontactcontainer);
+
+					/// After the Run() has completed, you can call this function to
+					/// fill a 'proximity container' (container of narrow phase pairs), that is 
+					/// an object inherited from class ChProximityContainerBase. For instance ChSystem, after each Run()
+					/// collision detection, calls this method multiple times for all proximity containers in the system,
+					/// The basic behavior of the implementation is  the following: collision system 
+					/// will call in sequence the functions BeginAddProximities(), AddProximity() (x n times), 
+					/// EndAddProximities() of the proximity container.
+	virtual void ReportProximities(ChProximityContainerBase* mproximitycontainer);
+
+
+					/// Perform a raycast (ray-hit test with the collision models).
+	virtual bool RayHit(const ChVector<>& from, const ChVector<>& to, ChRayhitResult& mresult);
+
+					// For Bullet related stuff
+	btCollisionWorld* GetBulletCollisionWorld() {return bt_collision_world;}
+
+private:
+	btCollisionConfiguration* bt_collision_configuration;
+	btCollisionDispatcher*  bt_dispatcher;
+	btBroadphaseInterface*	bt_broadphase;
+	btCollisionWorld*		bt_collision_world; 
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCCollisionUtils.cpp b/SRC/ChronoEngine/collision/ChCCollisionUtils.cpp
new file mode 100644
index 0000000..10a5a56
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionUtils.cpp
@@ -0,0 +1,208 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChCCollisionUtils.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+#include "core/ChTrasform.h"
+#include "collision/ChCCollisionUtils.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChSolvmin.h"
+#include "physics/ChNlsolver.h"
+#include "geometry/ChCTriangle.h"
+#include "geometry/ChCSphere.h"
+#include "geometry/ChCBox.h"
+
+
+namespace chrono
+{
+namespace collision 
+{
+
+
+
+//////////////UTILITY
+
+#define EPS 1e-20
+#define EPS_TRIDEGEN 1e-10
+
+//
+// Calculate the line segment PaPb that is the shortest route between
+// two lines P1P2 and P3P4. Calculate also the values of mua and mub where
+//    Pa = P1 + mua (P2 - P1)
+//    Pb = P3 + mub (P4 - P3)
+// Return FALSE if no solution exists.
+
+int ChCollisionUtils::LineLineIntersect(
+   Vector p1, Vector p2,Vector p3,Vector p4,Vector *pa,Vector *pb,
+   double *mua, double *mub)
+{
+   Vector p13,p43,p21;
+   double d1343,d4321,d1321,d4343,d2121;
+   double numer,denom;
+
+   p13.x = p1.x - p3.x;
+   p13.y = p1.y - p3.y;
+   p13.z = p1.z - p3.z;
+   p43.x = p4.x - p3.x;
+   p43.y = p4.y - p3.y;
+   p43.z = p4.z - p3.z;
+   if (fabs(p43.x)  < EPS && fabs(p43.y)  < EPS && fabs(p43.z)  < EPS)
+      return(FALSE);
+   p21.x = p2.x - p1.x;
+   p21.y = p2.y - p1.y;
+   p21.z = p2.z - p1.z;
+   if (fabs(p21.x)  < EPS && fabs(p21.y)  < EPS && fabs(p21.z)  < EPS)
+      return(FALSE);
+
+   d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z;
+   d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z;
+   d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z;
+   d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z;
+   d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z;
+
+   denom = d2121 * d4343 - d4321 * d4321;
+   if (fabs(denom) < EPS)
+      return(FALSE);
+   numer = d1343 * d4321 - d1321 * d4343;
+
+   *mua = numer / denom;
+   *mub = (d1343 + d4321 * (*mua)) / d4343;
+
+   pa->x = p1.x + *mua * p21.x;
+   pa->y = p1.y + *mua * p21.y;
+   pa->z = p1.z + *mua * p21.z;
+   pb->x = p3.x + *mub * p43.x;
+   pb->y = p3.y + *mub * p43.y;
+   pb->z = p3.z + *mub * p43.z;
+
+   return(TRUE);
+}
+
+
+
+/////////////////////////////////////
+
+// Calculate distance between a point p and a line identified
+// with segment dA,dB. Returns distance. Also, the mu value reference
+// tells if the nearest projection of point on line falls into segment (for mu 0...1)
+
+double ChCollisionUtils::PointLineDistance(Vector p, Vector dA, Vector dB, double& mu, int& is_insegment)
+{
+	mu=-1.0;
+	is_insegment = 0;
+	double mdist=10e34;
+
+	Vector vseg = Vsub(dB,dA);
+	Vector vdir = Vnorm(vseg);
+	Vector vray = Vsub(p,dA);
+
+	mdist = Vlenght(Vcross(vray,vdir));
+	mu = Vdot(vray,vdir)/Vlenght(vseg);
+
+	if ((mu>=0) && (mu<=1.0))
+		is_insegment = 1;
+
+	return mdist;
+}
+
+
+
+/////////////////////////////////////
+
+// Calculate distance of a point from a triangle surface.
+// Also computes if projection is inside the triangle.
+//
+
+double ChCollisionUtils::PointTriangleDistance(Vector B, Vector A1, Vector A2, Vector A3,
+							   double& mu, double& mv, int& is_into,
+							   Vector& Bprojected)
+{
+	// defaults
+	is_into = 0;
+	mu=mv=-1;
+	double mdistance = 10e22;
+
+	Vector Dx, Dy, Dz, T1, T1p;
+
+	Dx= Vsub (A2, A1);
+	Dz= Vsub (A3, A1);
+	Dy= Vcross(Dz,Dx);
+
+	double dylen = Vlenght(Dy);
+
+	if(fabs(dylen)<EPS_TRIDEGEN)	// degenere triangle
+		return mdistance;
+
+	Dy= Vmul(Dy,1.0/dylen);
+
+	ChMatrix33<> mA;
+	ChMatrix33<> mAi;
+	mA.Set_A_axis(Dx,Dy,Dz);
+
+	// invert triangle coordinate matrix -if singular matrix, was degenerate triangle-.
+	if (fabs(mA.FastInvert(&mAi)) <0.000001)
+		return mdistance;
+
+	T1 = mAi.Matr_x_Vect( Vsub (B, A1) );
+	T1p = T1;
+	T1p.y=0;
+	mu = T1.x;
+	mv = T1.z;
+	if (mu >=0  &&  mv >=0  &&  mv<=1.0-mu)
+	{
+		is_into = 1;
+		mdistance = fabs(T1.y);
+		Bprojected = Vadd(A1, mA.Matr_x_Vect(T1p));
+	}
+
+	return mdistance;
+}
+
+
+
+/////////////////////////////////////
+
+
+
+ 
+int DegenerateTriangle(Vector Dx, Vector Dy)
+{
+	Vector vcr;
+	vcr = Vcross(Dx,Dy);
+	if (fabs(vcr.x) < EPS_TRIDEGEN && fabs(vcr.y) < EPS_TRIDEGEN && fabs(vcr.z) < EPS_TRIDEGEN )
+		return TRUE;
+	return FALSE;
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+////// end
diff --git a/SRC/ChronoEngine/collision/ChCCollisionUtils.h b/SRC/ChronoEngine/collision/ChCCollisionUtils.h
new file mode 100644
index 0000000..4c22a07
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCCollisionUtils.h
@@ -0,0 +1,85 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCOLLISIONUTILS_H
+#define CHCOLLISIONUTILS_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionUtils.h
+//
+//   Class for collision utilities
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChBody.h"
+
+
+namespace chrono 
+{
+namespace collision
+{
+
+
+
+
+///
+/// Class with some utility functions for collision detection,
+/// as static functions.
+///
+
+class ChApi ChCollisionUtils {
+public:
+
+
+			/// Calculate the line segment PaPb that is the shortest route between
+			/// two lines P1P2 and P3P4. Calculate also the values of mua and mub where
+			///    Pa = P1 + mua (P2 - P1)
+			///    Pb = P3 + mub (P4 - P3)
+			/// Return FALSE if no solution exists.
+	 
+	static int LineLineIntersect(
+	   Vector p1, Vector p2,Vector p3,Vector p4,Vector *pa,Vector *pb,
+	   double *mua, double *mub);
+
+
+
+			/// Calculate distance between a point p and a line identified
+			/// with segment dA,dB. Returns distance. Also, the mu value reference
+			/// tells if the nearest projection of point on line falls into segment (for mu 0...1)
+	 
+	static double PointLineDistance(Vector p, Vector dA, Vector dB, double& mu, int& is_insegment);
+
+
+
+			/// Calculate distance of a point from a triangle surface. 
+			/// Also computes if projection is inside the triangle.
+
+	static double PointTriangleDistance(Vector B, Vector A1, Vector A2, Vector A3, 
+								   double& mu, double& mv, int& is_into,
+								   Vector& Bprojected);
+
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif  
diff --git a/SRC/ChronoEngine/collision/ChCModelBullet.cpp b/SRC/ChronoEngine/collision/ChCModelBullet.cpp
new file mode 100644
index 0000000..945a0ae
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBullet.cpp
@@ -0,0 +1,723 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCModelBullet.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com 
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+ 
+#include "ChCModelBullet.h" 
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChSystem.h"
+#include "collision/bullet/btBulletCollisionCommon.h"
+#include "GIMPACT/Bullet/btGImpactCollisionAlgorithm.h"
+#include "GIMPACTUtils/btGImpactConvexDecompositionShape.h"
+#include "BulletCollision/CollisionShapes/btBarrelShape.h"
+#include "collision/ChCCollisionSystemBullet.h"
+#include "BulletWorldImporter/btBulletWorldImporter.h"
+
+
+namespace chrono 
+{
+
+
+
+namespace collision 
+{
+
+
+
+ChModelBullet::ChModelBullet()
+{
+	bt_collision_object = new btCollisionObject;
+	bt_collision_object->setCollisionShape(0);
+	bt_collision_object->setUserPointer((void*) this);
+
+	this->family_group = 1;
+	this->family_mask  = 0xFF;
+
+	shapes.clear();
+
+
+}
+
+
+ChModelBullet::~ChModelBullet()
+{ 
+	//ClearModel(); not possible, would call GetPhysicsItem() that is pure virtual, enough to use instead..
+	shapes.clear();
+
+	bt_collision_object->setCollisionShape(0);
+
+	if (bt_collision_object) delete bt_collision_object;
+	bt_collision_object=0;
+}
+
+ 
+
+int ChModelBullet::ClearModel()
+{
+
+	// delete previously added shapes, if collision shape(s) used by collision object
+	if(shapes.size()>0)
+	{
+		// deletes shared pointers, so also deletes shapes if uniquely referenced
+		shapes.clear(); 
+
+		// tell to the parent collision system to remove this from collision system,
+		// if still connected to a physical system 
+		if (GetPhysicsItem()->GetSystem())
+		  if (GetPhysicsItem()->GetCollide())
+			GetPhysicsItem()->GetSystem()->GetCollisionSystem()->Remove(this);
+		
+		// at the end, no collision shape
+		bt_collision_object->setCollisionShape(0);
+	}
+
+	return 1;
+} 
+
+
+int ChModelBullet::BuildModel()
+{
+	//assert (GetPhysicsItem());
+	
+	// insert again (we assume it was removed by ClearModel!!!)
+	if (GetPhysicsItem()->GetSystem())
+	  if (GetPhysicsItem()->GetCollide())
+		GetPhysicsItem()->GetSystem()->GetCollisionSystem()->Add(this);
+
+	return 1;
+}
+
+static btVector3 ChVectToBullet(const ChVector<>* pos)
+{
+	return btVector3((btScalar)pos->x,(btScalar)pos->y,(btScalar)pos->z);
+}
+
+static void ChPosMatrToBullet (ChVector<>* pos, ChMatrix33<>* rA, btTransform& mtrasform)
+{
+	btMatrix3x3 basisA( (btScalar)(*rA)(0,0), (btScalar)(*rA)(0,1), (btScalar)(*rA)(0,2),
+						(btScalar)(*rA)(1,0), (btScalar)(*rA)(1,1), (btScalar)(*rA)(1,2),
+						(btScalar)(*rA)(2,0), (btScalar)(*rA)(2,1), (btScalar)(*rA)(2,2));
+	mtrasform.setBasis(basisA);
+	mtrasform.setOrigin(btVector3(
+								(btScalar)pos->x,
+								(btScalar)pos->y,
+								(btScalar)pos->z));
+}
+static void ChCoordsToBullet (ChCoordsys<>& mcoords, btTransform& mtrasform)
+{
+	ChMatrix33<> rA;
+	rA.Set_A_quaternion(mcoords.rot);
+	btMatrix3x3 basisA( (btScalar)rA(0,0), (btScalar)rA(0,1), (btScalar)rA(0,2),
+						(btScalar)rA(1,0), (btScalar)rA(1,1), (btScalar)rA(1,2),
+						(btScalar)rA(2,0), (btScalar)rA(2,1), (btScalar)rA(2,2));
+	mtrasform.setBasis(basisA);
+	mtrasform.setOrigin(btVector3(
+								(btScalar)mcoords.pos.x,
+								(btScalar)mcoords.pos.y,
+								(btScalar)mcoords.pos.z));
+}
+
+void ChModelBullet::_injectShape(ChVector<>* pos, ChMatrix33<>* rot, btCollisionShape* mshape)
+{
+	ChVector<>   defpos = VNULL;
+	ChMatrix33<> defrot;
+	defrot.Set33Identity();
+
+	if (!pos)
+		pos = &defpos;
+	if (!rot)
+		rot = &defrot;
+
+	bool centered = false;
+	if ((*pos==defpos)&&(*rot==defrot))
+		centered = true;
+
+	// start_vector = ||    -- description is still empty
+	if (shapes.size()==0)
+	{
+		if (centered)
+		{
+			 shapes.push_back(ChSmartPtr<btCollisionShape>(mshape)); 
+			bt_collision_object->setCollisionShape(mshape);
+			// end_vector=  | centered shape | 
+			return;
+		}
+		else
+		{
+			btCompoundShape* mcompound = new btCompoundShape(true);
+			 shapes.push_back(ChSmartPtr<btCollisionShape>(mcompound)); 
+			 shapes.push_back(ChSmartPtr<btCollisionShape>(mshape)); 
+			bt_collision_object->setCollisionShape(mcompound);
+			btTransform mtrasform;
+			ChPosMatrToBullet(pos,rot, mtrasform);
+			mcompound->addChildShape(mtrasform, mshape);
+			// vector=  | compound | not centered shape |
+			return;
+		}
+	}
+	// start_vector = | centered shape |    ----just a single centered shape was added
+	if (shapes.size()==1)
+	{
+		btTransform mtrasform;
+		 shapes.push_back(shapes[0]);
+		 shapes.push_back(ChSmartPtr<btCollisionShape>(mshape));
+		btCompoundShape* mcompound = new btCompoundShape(true);
+		 shapes[0] = ChSmartPtr<btCollisionShape>(mcompound); 
+		bt_collision_object->setCollisionShape(mcompound);
+		ChPosMatrToBullet(&defpos, &defrot, mtrasform);
+		mcompound->addChildShape(mtrasform, shapes[1].get_ptr()); 
+		ChPosMatrToBullet(pos,rot, mtrasform);
+		mcompound->addChildShape(mtrasform, shapes[2].get_ptr()); 
+		// vector=  | compound | old centered shape | new shape | ...
+		return;
+	}
+	// vector=  | compound | old | old.. |   ----already working with compounds..
+	if (shapes.size()>1)
+	{
+		btTransform mtrasform;
+		 shapes.push_back(ChSmartPtr<btCollisionShape>(mshape)); 
+		ChPosMatrToBullet(pos,rot, mtrasform);
+		btCollisionShape* mcom = shapes[0].get_ptr(); 
+		((btCompoundShape*)mcom)->addChildShape(mtrasform, mshape); 
+		// vector=  | compound | old | old.. | new shape | ...
+		return;
+	}
+}
+
+bool ChModelBullet::AddSphere(double radius,  ChVector<>* pos)
+{
+	// adjust default inward 'safe' margin (always as radius)
+	this->SetSafeMargin((btScalar)radius);
+
+	btSphereShape* mshape = new btSphereShape((btScalar) (radius + this->GetEnvelope()) );
+
+	mshape->setMargin((btScalar)this->GetSuggestedFullMargin() );
+
+	_injectShape (pos, 0, mshape);
+
+	model_type=SPHERE;
+	return true;
+}
+ 
+bool ChModelBullet::AddEllipsoid(double rx,  double ry,  double rz, ChVector<>* pos, ChMatrix33<>* rot)
+{
+	btScalar rad=1.0;
+	btVector3 spos(0,0,0);
+	double arx = rx + this->GetEnvelope();
+	double ary = ry + this->GetEnvelope();
+	double arz = rz + this->GetEnvelope();
+	double mmargin = GetSuggestedFullMargin();
+	btMultiSphereShape* mshape = new btMultiSphereShape(
+						//btVector3(1,1,1),
+						&spos,&rad,1);
+	mshape->setLocalScaling(btVector3(  (btScalar)arx,
+										(btScalar)ary,
+										(btScalar)arz ));
+
+	mshape->setMargin((btScalar)ChMin(mmargin, 0.9*ChMin(ChMin(arx,ary),arz)));
+
+	_injectShape (	pos, rot, mshape);
+
+	model_type=ELLIPSOID;
+	return true;
+}
+ 
+bool ChModelBullet::AddBox(double hx, double hy, double hz, ChVector<>* pos, ChMatrix33<>* rot)
+{
+	// adjust default inward margin (if object too thin)
+	this->SetSafeMargin((btScalar)ChMin(this->GetSafeMargin(), 0.2*ChMin(ChMin(hx,hy),hz)));
+
+	double ahx = hx + this->GetEnvelope(); 
+	double ahy = hy + this->GetEnvelope();
+	double ahz = hz + this->GetEnvelope();
+	btBoxShape* mshape = new btBoxShape(btVector3(	(btScalar)ahx, 
+													(btScalar)ahy, 
+													(btScalar)ahz));
+
+	mshape->setMargin((btScalar)this->GetSuggestedFullMargin() );
+
+	_injectShape (pos,rot, mshape);
+
+	model_type=BOX;
+	return true;
+}
+ 
+	 /// Add a cylinder to this model (default axis on Y direction), for collision purposes
+bool ChModelBullet::AddCylinder (double rx, double rz, double hy, ChVector<>* pos, ChMatrix33<>* rot)
+{
+		// adjust default inward margin (if object too thin)
+	this->SetSafeMargin((btScalar)ChMin(this->GetSafeMargin(), 0.2*ChMin(ChMin(rx,rz),(hy*0.5) )));
+
+	double arx = rx + this->GetEnvelope();
+	double arz = rz + this->GetEnvelope();
+	double ahy = hy + this->GetEnvelope();
+	
+	btCylinderShape* mshape = new btCylinderShape(btVector3(	
+						(btScalar)(arx), 
+						(btScalar)(ahy), 
+						(btScalar)(arz) ));
+	mshape->setMargin((btScalar)this->GetSuggestedFullMargin() );
+
+	_injectShape (pos,rot, mshape);
+
+	model_type=CYLINDER;
+	return true;
+}
+
+
+bool ChModelBullet::AddBarrel (double Y_low, double Y_high, double R_vert, double R_hor, double R_offset, ChVector<>* pos, ChMatrix33<>* rot)
+{
+		// adjust default inward margin (if object too thin)
+	this->SetSafeMargin((btScalar)ChMin(this->GetSafeMargin(), 0.15*ChMin(ChMin(R_vert,R_hor),(Y_high-Y_low) )));
+
+	btBarrelShape* mshape = new btBarrelShape(
+		(btScalar)(Y_low  - this->model_envelope),  
+		(btScalar)(Y_high + this->model_envelope),  
+		(btScalar)(R_vert + this->model_envelope),  
+		(btScalar)(R_hor  + this->model_envelope),  
+		(btScalar)(R_offset) );
+
+	mshape->setMargin((btScalar)this->GetSuggestedFullMargin() );
+
+	_injectShape (pos,rot, mshape);
+
+	model_type=BARREL;
+	return true;
+}
+
+
+
+bool ChModelBullet::AddConvexHull (std::vector< ChVector<double> >& pointlist, ChVector<>* pos, ChMatrix33<>* rot)
+{
+		// adjust default inward margin (if object too thin)
+	//this->SetSafeMargin((btScalar)ChMin(this->GetSafeMargin(), ... );
+
+	btConvexHullShape* mshape = new btConvexHullShape;
+	
+	mshape->setMargin((btScalar)this->GetSuggestedFullMargin() );
+
+	// ***TO DO*** shrink the convex hull by GetSafeMargin()
+	for (unsigned int i = 0; i < pointlist.size(); i++)
+	{
+		mshape->addPoint( btVector3( 
+			(btScalar)pointlist[i].x,
+			(btScalar)pointlist[i].y,
+			(btScalar)pointlist[i].z) );
+	}
+
+	mshape->setMargin((btScalar)this->GetSuggestedFullMargin() );
+	mshape->recalcLocalAabb();
+	/*
+	btTransform mtr(btQuaternion(0,0,0));
+	btVector3 mmin, mmax;
+	mshape->getAabb(mtr,mmin,mmax);
+
+	GetLog() << "\nAAABB min  " << (double)mmin.getX() << "   "  << (double)mmin.getY() << "   " << (double)mmin.getZ() << "\n" ;
+	GetLog() << "AAABB max  " << (double)mmax.getX() << "   "  << (double)mmax.getY() << "   " << (double)mmax.getZ() << "\n" ;
+	*/
+	_injectShape (pos,rot, mshape);
+
+	model_type=CONVEXHULL;
+	return true;
+}
+
+
+// These classes inherits the Bullet triangle mesh, but adds just a single feature:
+// when this shape is deleted, also the referenced triangle mesh interface is deleted.
+// Hence, when a btBvhTriangleMeshShape_handlemesh is added to the list of shapes of this ChModelBullet,
+// there's no need to remember to delete the mesh interface because it dies with the model, when shapes are deleted.
+// This is just to avoid adding a pointer to a triangle interface in all collision models, when not needed. 
+
+class btBvhTriangleMeshShape_handlemesh : public btBvhTriangleMeshShape
+{
+	btStridingMeshInterface* minterface;
+public:
+	btBvhTriangleMeshShape_handlemesh(btStridingMeshInterface* meshInterface) : 
+			btBvhTriangleMeshShape(meshInterface ,true), 
+			minterface(meshInterface) 
+	{};
+
+	~btBvhTriangleMeshShape_handlemesh()
+	{
+		if (minterface) delete minterface; minterface = 0; // also delete the mesh interface
+	}
+};
+
+class btConvexTriangleMeshShape_handlemesh : public btConvexTriangleMeshShape
+{
+	btStridingMeshInterface* minterface;
+public:
+	btConvexTriangleMeshShape_handlemesh(btStridingMeshInterface* meshInterface) : 
+			btConvexTriangleMeshShape(meshInterface), 
+			minterface(meshInterface) {};
+
+	~btConvexTriangleMeshShape_handlemesh()
+	{
+		if (minterface) delete minterface; minterface = 0; // also delete the mesh interface
+	}
+};
+
+
+class btGImpactConvexDecompositionShape_handlemesh : public btGImpactConvexDecompositionShape 
+{
+	btStridingMeshInterface* minterface;
+public:
+	btGImpactConvexDecompositionShape_handlemesh(btStridingMeshInterface* meshInterface) :  
+	        btGImpactConvexDecompositionShape (meshInterface, btVector3(1.f,1.f,1.f), btScalar(0.01)),
+			minterface(meshInterface) 
+			{
+				//this->setLocalScaling(btVector3(1.f,1.f,1.f));
+			};
+
+	virtual ~btGImpactConvexDecompositionShape_handlemesh()
+	{
+		if (minterface) delete minterface; minterface = 0; // also delete the mesh interface
+	} 
+};
+ 
+class btGImpactMeshShape_handlemesh : public btGImpactMeshShape
+{
+	btStridingMeshInterface* minterface;
+public:
+	btGImpactMeshShape_handlemesh(btStridingMeshInterface* meshInterface) : 
+			btGImpactMeshShape(meshInterface), 
+			minterface(meshInterface) 
+			{
+				//this->setLocalScaling(btVector3(1.f,1.f,1.f));
+			};
+
+	virtual ~btGImpactMeshShape_handlemesh()
+	{
+		if (minterface) delete minterface; minterface = 0; // also delete the mesh interface
+	} 
+};
+
+
+	/// Add a triangle mesh to this model
+bool ChModelBullet::AddTriangleMesh (const  geometry::ChTriangleMesh& trimesh,	bool is_static, bool is_convex,  ChVector<>* pos, ChMatrix33<>* rot)
+{
+	if (!trimesh.getNumTriangles()) 
+		return false;
+
+	btTriangleMesh* bulletMesh = new btTriangleMesh;
+	for (int i=0; i<trimesh.getNumTriangles(); i++)
+	{
+		//bulletMesh->m_weldingThreshold = ...
+		Vector temp1=trimesh.getTriangle(i).p1;
+		Vector temp2=trimesh.getTriangle(i).p2;
+		Vector temp3=trimesh.getTriangle(i).p3;
+		bulletMesh->addTriangle(
+			ChVectToBullet(&temp1),
+			ChVectToBullet(&temp2),
+			ChVectToBullet(&temp3),
+			true); // try to remove duplicate vertices
+	}
+	
+	if (is_static) 
+	{ 
+		// Here a static btBvhTriangleMeshShape should suffice, but looks like that the btGImpactMeshShape works better..
+		 btCollisionShape* pShape = (btBvhTriangleMeshShape*) new btBvhTriangleMeshShape_handlemesh(bulletMesh);
+	     pShape->setMargin((btScalar) this->GetSafeMargin() );
+		// ((btBvhTriangleMeshShape*)pShape)->refitTree();
+		//btCollisionShape* pShape = new btGImpactMeshShape_handlemesh(bulletMesh);
+		//pShape->setMargin((btScalar) this->GetSafeMargin() );
+		//((btGImpactMeshShape_handlemesh*)pShape)->updateBound();
+		_injectShape (pos,rot, pShape);
+	}
+	else
+	{
+		if (is_convex)
+		{
+			btCollisionShape* pShape = (btConvexTriangleMeshShape*) new btConvexTriangleMeshShape_handlemesh(bulletMesh);
+			pShape->setMargin( (btScalar) this->GetEnvelope() );
+			_injectShape (pos,rot, pShape);
+		} 
+		else
+		{
+			// Note: currently there's no 'perfect' convex decomposition method, 
+			// so here the code is a bit experimental...
+
+			/*
+		      // ----- use this? (using GImpact collision method without decomposition) :
+			  this->AddTriangleMeshConcave(trimesh,pos,rot);
+			*/
+	    
+			   
+			  // ----- ..or use this? (using the JR convex decomposition) : 
+
+		}
+	}
+	model_type=TRIANGLEMESH;
+	return true;
+}
+
+
+
+bool ChModelBullet::AddTriangleMeshConcave(const  geometry::ChTriangleMesh& trimesh,	///< the concave triangle mesh
+								ChVector<>* pos, ChMatrix33<>* rot ///< displacement respect to COG (optional)
+								)
+{
+	if (!trimesh.getNumTriangles()) 
+		return false;
+
+	btTriangleMesh* bulletMesh = new btTriangleMesh;
+	for (int i=0; i<trimesh.getNumTriangles(); i++)
+	{
+		//bulletMesh->m_weldingThreshold = ...
+		Vector temp1=trimesh.getTriangle(i).p1;
+		Vector temp2=trimesh.getTriangle(i).p2;
+		Vector temp3=trimesh.getTriangle(i).p3;
+		bulletMesh->addTriangle(
+			ChVectToBullet(&temp1),
+			ChVectToBullet(&temp2),
+			ChVectToBullet(&temp3),
+			true); // try to remove duplicate vertices
+	}
+
+	// Use the GImpact custom mesh-mesh algorithm
+	btCollisionShape* pShape = (btGImpactMeshShape*) new btGImpactMeshShape_handlemesh(bulletMesh);
+	pShape->setMargin( (btScalar) this->GetEnvelope() ); 
+	this->SetSafeMargin(0);
+
+	((btGImpactMeshShape_handlemesh*)pShape)->updateBound();
+	_injectShape (pos,rot, pShape);
+
+	return true;
+}
+
+bool ChModelBullet::AddTriangleMeshConcaveDecomposed(
+							    ChConvexDecomposition& mydecomposition,
+								ChVector<>* pos, ChMatrix33<>* rot ///< displacement respect to COG (optional)
+								)
+{
+  btAssert(0); //Dd.
+}
+
+
+
+bool ChModelBullet::AddCopyOfAnotherModel (ChCollisionModel* another)
+{
+	//this->ClearModel();
+	this->shapes.clear(); // this will also delete owned shapes, if any, thank to shared pointers in 'shapes' vector
+
+	this->SetSafeMargin(another->GetSafeMargin());
+	this->SetEnvelope  (another->GetEnvelope());
+
+	this->bt_collision_object->setCollisionShape(((ChModelBullet*)another)->GetBulletModel()->getCollisionShape());
+	this->shapes = ((ChModelBullet*)another)->shapes;
+
+	return true;
+}
+
+
+
+
+
+void  ChModelBullet::SetFamily(int mfamily)
+{
+	assert(mfamily<16);
+
+	this->family_group = (short int)0x1 << mfamily;
+
+	if (!bt_collision_object->getBroadphaseHandle()) return;
+
+	this->SyncPosition();
+
+	// Trick to avoid troubles if setting mask or family when model is already overlapping to some other model
+	ChCollisionSystem* mcosys =this->GetPhysicsItem()->GetSystem()->GetCollisionSystem();
+	//short int original_mask = bt_collision_object->getBroadphaseHandle()->m_collisionFilterMask;
+	mcosys->Remove(this);
+
+	ChCollisionSystemBullet* mcs = (ChCollisionSystemBullet*) mcosys;
+	mcs->GetBulletCollisionWorld()->addCollisionObject(bt_collision_object, this->family_group , this->family_mask);
+}
+
+int   ChModelBullet::GetFamily()
+{
+	int fam;
+	if (!bt_collision_object->getBroadphaseHandle()) return -1;
+	for (fam = 0; fam < 16; fam++)
+		if (((short int)0x1 << fam) &	bt_collision_object->getBroadphaseHandle()->m_collisionFilterGroup)
+			return fam;
+	return fam;
+}
+
+void  ChModelBullet::SetFamilyMaskNoCollisionWithFamily(int mfamily)
+{
+	assert(mfamily<16);
+
+	short int familyflag = (short int)0x1 << mfamily;
+	this->family_mask = this->family_mask & ~familyflag;
+
+	if (!bt_collision_object->getBroadphaseHandle()) return;
+
+	this->SyncPosition();
+
+	// Trick to avoid troubles if setting mask or family when model is already overlapping to some other model
+	ChCollisionSystem* mcosys =this->GetPhysicsItem()->GetSystem()->GetCollisionSystem();
+	//short int original_family = bt_collision_object->getBroadphaseHandle()->m_collisionFilterGroup;
+	//short int original_mask   = bt_collision_object->getBroadphaseHandle()->m_collisionFilterMask;
+	mcosys->Remove(this);
+
+	ChCollisionSystemBullet* mcs = (ChCollisionSystemBullet*) mcosys;
+	mcs->GetBulletCollisionWorld()->addCollisionObject(bt_collision_object, this->family_group , this->family_mask);
+} 
+
+void  ChModelBullet::SetFamilyMaskDoCollisionWithFamily(int mfamily)
+{
+	assert(mfamily<16);
+
+	short int familyflag = (short int)0x1 << mfamily;
+	this->family_mask = this->family_mask | familyflag;
+
+	if (!bt_collision_object->getBroadphaseHandle()) return;
+
+	this->SyncPosition();
+
+	// Trick to avoid troubles if setting mask or family when model is already overlapping to some other model
+	ChCollisionSystem* mcosys =this->GetPhysicsItem()->GetSystem()->GetCollisionSystem();
+	//short int original_family = bt_collision_object->getBroadphaseHandle()->m_collisionFilterGroup;
+	//short int original_mask   = bt_collision_object->getBroadphaseHandle()->m_collisionFilterMask;
+	mcosys->Remove(this);
+
+	ChCollisionSystemBullet* mcs = (ChCollisionSystemBullet*) mcosys;
+	mcs->GetBulletCollisionWorld()->addCollisionObject(bt_collision_object, this->family_group , this->family_mask);
+}
+
+bool ChModelBullet::GetFamilyMaskDoesCollisionWithFamily(int mfamily)
+{
+	assert(mfamily<16);
+	if (!bt_collision_object->getBroadphaseHandle()) return false;
+	short int familyflag = (short int)0x1 << mfamily;
+	return (bt_collision_object->getBroadphaseHandle()->m_collisionFilterMask & familyflag) != 0;
+}
+
+
+
+
+
+void ChModelBullet::GetAABB(ChVector<>& bbmin, ChVector<>& bbmax) const
+{
+	btVector3 btmin;
+	btVector3 btmax;
+	if (bt_collision_object->getCollisionShape())
+		bt_collision_object->getCollisionShape()->getAabb( bt_collision_object->getWorldTransform(), btmin, btmax);
+	bbmin.Set(btmin.x(), btmin.y(), btmin.z());
+	bbmax.Set(btmax.x(), btmax.y(), btmax.z());
+}
+
+
+void __recurse_add_newcollshapes(btCollisionShape* ashape, std::vector<smartptrshapes>& shapes)
+{
+	if (ashape)
+	{
+		shapes.push_back(ChSmartPtr<btCollisionShape>(ashape));
+
+		if (ashape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+		{
+			btCompoundShape* compoundShape = (btCompoundShape*) ashape;
+			for (int shi = 0; shi < compoundShape->getNumChildShapes(); shi++)
+			{
+				__recurse_add_newcollshapes(compoundShape->getChildShape(shi), shapes);
+			}
+		}
+	}
+}
+
+
+
+void ChModelBullet::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// parent class deserialize
+	ChCollisionModel::StreamIN(mstream);
+
+		// deserialize custom data:
+
+	
+	this->ClearModel(); // remove shape 
+
+	int buffer_len=0;
+
+	mstream >> buffer_len;
+
+	char* mbuffer = new char[buffer_len];
+
+	for (int mpt= 0; mpt <  buffer_len; mpt++)
+		mstream >> mbuffer[mpt];
+
+	btBulletWorldImporter import(0);//don't store info into the world
+	import.setVerboseMode(false);
+
+	if (import.loadFileFromMemory(mbuffer, buffer_len))
+	{
+		int numShape = import.getNumCollisionShapes();
+		if (numShape)
+		{
+			btCollisionShape* mshape = import.getCollisionShapeByIndex(0);
+			if (mshape)
+				bt_collision_object->setCollisionShape(mshape);
+
+			// Update the list of sharedpointers to newly created shapes, so that 
+			// the deletion will be automatic
+			__recurse_add_newcollshapes(mshape, this->shapes);
+		}
+	}
+
+	delete[] mbuffer;
+	
+}
+
+		
+void ChModelBullet::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// parent class serialize
+	ChCollisionModel::StreamOUT(mstream);
+
+		// serialize custom data:
+	
+	int maxSerializeBufferSize = 1024*1024*5;	//***TO DO*** make this more efficient
+	btDefaultSerializer*	serializer = new btDefaultSerializer(maxSerializeBufferSize);
+
+	serializer->startSerialization();
+	
+	this->bt_collision_object->getCollisionShape()->serializeSingleShape(serializer);
+
+	serializer->finishSerialization();
+
+	mstream << serializer->getCurrentBufferSize();
+
+	for (int mpt= 0; mpt <  serializer->getCurrentBufferSize(); mpt++)
+		mstream << (char)(*(serializer->getBufferPointer()+mpt));
+
+	delete serializer;
+
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/ChCModelBullet.h b/SRC/ChronoEngine/collision/ChCModelBullet.h
new file mode 100644
index 0000000..95ca2bc
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBullet.h
@@ -0,0 +1,209 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MODELBULLET_H
+#define CHC_MODELBULLET_H
+ 
+//////////////////////////////////////////////////
+//  
+//   ChCModelBullet.h
+//
+//   A wrapper to use the Bullet collision detection
+//   library
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <vector>
+#include "ChCCollisionModel.h" 
+#include "core/ChSmartpointers.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+
+// forward references
+class btCollisionObject;
+//class btCollisionShape;
+
+namespace chrono 
+{
+
+// forward references
+class ChBody;
+typedef ChSmartPtr<btCollisionShape> smartptrshapes;
+
+namespace collision 
+{
+
+class ChConvexDecomposition;
+
+///  A wrapper to use the Bullet collision detection
+///  library
+
+class ChApi ChModelBullet : public ChCollisionModel
+{
+protected:
+			// The Bullet collision object containing Bullet geometries
+	btCollisionObject* bt_collision_object;
+
+			// Vector of shared pointers to geometric objects.
+    std::vector<smartptrshapes> shapes; 
+
+	short int	family_group;
+	short int	family_mask;
+
+public:
+
+  ChModelBullet();
+  virtual ~ChModelBullet();
+  
+
+		/// Deletes all inserted geometries.
+		/// Also, if you begin the definition of a model, AFTER adding
+		/// the geometric description, remember to call the ClearModel().
+		/// MUST be inherited by child classes! (ex for resetting also BV hierarchies)
+  virtual int ClearModel();
+
+		/// Builds the BV hierarchy.
+		/// Call this function AFTER adding the geometric description.
+		/// MUST be inherited by child classes! (ex for bulding BV hierarchies)
+  virtual int BuildModel();
+
+
+	// 
+	// GEOMETRY DESCRIPTION	
+	//	
+	//  The following functions must be called inbetween 
+	//  the ClearModel() BuildModel() pair.
+
+		/// Add a sphere shape to this model, for collision purposes
+  virtual bool AddSphere   (double radius, ChVector<>* pos=0);
+
+    	/// Add an ellipsoid shape to this model, for collision purposes
+  virtual bool AddEllipsoid   (double rx,  double ry,  double rz,  ChVector<>* pos=0,	ChMatrix33<>* rot=0  );
+
+		/// Add a box shape to this model, for collision purposes
+  virtual bool AddBox      (double hx, double hy, double hz,  ChVector<>* pos=0, ChMatrix33<>* rot=0);
+
+  		/// Add a cylinder to this model (default axis on Y direction), for collision purposes
+  virtual bool AddCylinder (double rx, double rz, double hy,  ChVector<>* pos=0, ChMatrix33<>* rot=0);
+
+  /// Add a cylinder to this model (default axis on Y direction), for collision purposes
+    virtual bool AddCone (double, double, double,  ChVector<>* =0, ChMatrix33<>* =0){return false;}
+
+  		/// Add a convex hull to this model. A convex hull is simply a point cloud that describe
+		/// a convex polytope. Connectivity between the vertexes, as faces/edges in triangle meshes is not necessary.
+		/// Points are passed as a list, that is instantly copied into the model.
+  virtual bool AddConvexHull (std::vector< ChVector<double> >& pointlist, ChVector<>* pos=0, ChMatrix33<>* rot=0);
+
+		/// Add a triangle mesh to this model, passing a triangle mesh (do not delete the triangle mesh
+		/// until the collision model, because depending on the implementation of inherited ChCollisionModel
+		/// classes, maybe the triangle is referenced via a striding interface or just copied)
+		/// Note: if possible, in sake of high performance, avoid triangle meshes and prefer simplified 
+		/// representations as compounds of convex shapes of boxes/spheres/etc.. type. 
+  virtual bool AddTriangleMesh (const  geometry::ChTriangleMesh& trimesh,	///< the triangle mesh
+								bool is_static,			///< true only if model doesn't move (es.a terrain). May improve performance
+								bool is_convex,			///< true if mesh is used as a convex hull(only for simple mesh), otherwise if false, handle as concave
+								ChVector<>* pos=0, ChMatrix33<>* rot=0 ///< displacement respect to COG (optional)
+								);  
+
+		/// CUSTOM for this class only: add a concave triangle mesh that will be managed
+		/// by GImpact mesh-mesh algorithm. Note that, despite this can work with
+		/// arbitrary meshes, there could be issues of robustness and precision, so 
+		/// when possible, prefer simplified representations as compounds of convex 
+		/// shapes of boxes/spheres/etc.. type.
+    virtual bool AddTriangleMeshConcave (const  geometry::ChTriangleMesh& trimesh,	///< the concave triangle mesh
+								ChVector<>* pos=0, ChMatrix33<>* rot=0 ///< displacement respect to COG (optional)
+								); 
+		/// CUSTOM for this class only: add a concave triangle mesh that will be decomposed
+		/// into a compound of convex shapes. Decomposition could be more efficient than 
+		/// AddTriangleMeshConcave(), but preprocessing decomposition might take a while, and
+		/// decomposition result is often approximate. Therefore, despite this can work with
+		/// arbitrary meshes, there could be issues of robustness and precision, so 
+		/// when possible, prefer simplified representations as compounds of convex 
+		/// shapes of boxes/spheres/etc.. type.
+    virtual bool AddTriangleMeshConcaveDecomposed (
+								ChConvexDecomposition& mydecomposition, ///< the concave triangle mesh, already decomposed
+								ChVector<>* pos=0, ChMatrix33<>* rot=0 ///< displacement respect to COG (optional)
+								);
+
+
+   		/// Add a barrel-like shape to this model (main axis on Y direction), for collision purposes.
+		/// The barrel shape is made by lathing an arc of an ellipse around the vertical Y axis.
+		/// The center of the ellipse is on Y=0 level, and it is ofsetted by R_offset from 
+		/// the Y axis in radial direction. The two radii of the ellipse are R_vert (for the 
+		/// vertical direction, i.e. the axis parellel to Y) and R_hor (for the axis that
+		/// is perpendicular to Y). Also, the solid is clamped with two discs on the top and
+		/// the bottom, at levels Y_low and Y_high. 
+  virtual bool AddBarrel (double Y_low, double Y_high, double R_vert, double R_hor, double R_offset, ChVector<>* pos=0, ChMatrix33<>* rot=0);
+
+		/// Add all shapes already contained in another model.
+		/// Thank to the adoption of shared pointers, underlying shapes are 
+		/// shared (not copied) among the models; this will save memory when you must
+		/// simulate thousands of objects with the same collision shape.
+		/// The 'another' model must be of ChModelBullet subclass.
+  virtual bool AddCopyOfAnotherModel (ChCollisionModel* another);
+
+
+  virtual void SetFamily(int mfamily);
+  virtual int  GetFamily();
+  virtual void SetFamilyMaskNoCollisionWithFamily(int mfamily);
+  virtual void SetFamilyMaskDoCollisionWithFamily(int mfamily);
+  virtual bool GetFamilyMaskDoesCollisionWithFamily(int mfamily);
+
+		/// Returns the axis aligned bounding box (AABB) of the collision model,
+		/// i.e. max-min along the x,y,z world axes. Remember that SyncPosition()
+		/// should be invoked before calling this.
+  virtual void GetAABB(ChVector<>& bbmin, ChVector<>& bbmax) const;
+
+	
+			//
+			// STREAMING
+			//
+
+		/// Method to allow deserializing a persistent binary archive (ex: a file)
+		/// into transient data.
+  virtual void StreamIN(ChStreamInBinary& mstream);
+
+		/// Method to allow serializing transient data into a persistent
+		/// binary archive (ex: a file).
+  virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+
+	  //
+	  // CUSTOM BULLET
+	  //
+
+		/// Return the pointer to the Bullet model
+  btCollisionObject* GetBulletModel() {return this->bt_collision_object;}
+	  
+  short int GetFamilyGroup() {return this->family_group;}
+  short int GetFamilyMask() {return this->family_mask;}
+
+private:
+	void _injectShape(ChVector<>* pos, ChMatrix33<>* rot, btCollisionShape* mshape);
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletBody.cpp b/SRC/ChronoEngine/collision/ChCModelBulletBody.cpp
new file mode 100644
index 0000000..7af8ba3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletBody.cpp
@@ -0,0 +1,75 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletBody.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com 
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+ 
+#include "ChCModelBulletBody.h" 
+#include "physics/ChBody.h"
+#include "collision/bullet/btBulletCollisionCommon.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+ChModelBulletBody::ChModelBulletBody()
+{
+	mbody = 0;
+}
+
+
+ChModelBulletBody::~ChModelBulletBody()
+{
+}
+
+void ChModelBulletBody::SyncPosition()
+{
+	ChBody* bpointer = GetBody();
+	assert(bpointer);
+	//assert(bpointer->GetSystem());
+	
+	// To support also the new generic ChBodyAuxRef, the collision
+	// shape is not placed respect to COG csys, but rather REF csys (that are
+	// the same in basic ChBody, anyway)
+	ChFrame<> framepointer = bpointer->GetFrame_REF_to_abs();
+
+	bt_collision_object->getWorldTransform().setOrigin(btVector3(
+								(btScalar)framepointer.GetPos().x,
+								(btScalar)framepointer.GetPos().y,
+								(btScalar)framepointer.GetPos().z));
+	ChMatrix33<>* rA = framepointer.GetA();
+	btMatrix3x3 basisA( (btScalar)(*rA)(0,0), (btScalar)(*rA)(0,1), (btScalar)(*rA)(0,2),
+						(btScalar)(*rA)(1,0), (btScalar)(*rA)(1,1), (btScalar)(*rA)(1,2),
+						(btScalar)(*rA)(2,0), (btScalar)(*rA)(2,1), (btScalar)(*rA)(2,2));
+	bt_collision_object->getWorldTransform().setBasis(basisA);
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletBody.h b/SRC/ChronoEngine/collision/ChCModelBulletBody.h
new file mode 100644
index 0000000..e2d7e78
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletBody.h
@@ -0,0 +1,85 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MODELBULLETBODY_H
+#define CHC_MODELBULLETBODY_H
+ 
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletBody.h
+//
+//   A wrapper to use the Bullet collision detection
+//   library
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "collision/ChCModelBullet.h"
+
+
+namespace chrono 
+{
+
+// forward references
+class ChBody;
+
+namespace collision 
+{
+
+
+/// Class for the collision model to be used in ChIndexedParticles shapes,
+/// that are collections of point-like nodes (each with 3 DOFs)
+/// using features of the Bullet library.
+
+class ChApi ChModelBulletBody : public ChModelBullet
+{
+
+public:
+
+  ChModelBulletBody();
+  virtual ~ChModelBulletBody();
+  
+
+    	/// Gets the pointer to the client owner rigid body. 
+  ChBody* GetBody() const {return mbody;};
+		/// Sets the pointer to the client owner rigid body
+
+  
+	// Overrides and implementations of base members:
+
+		/// Sets the position and orientation of the collision
+		/// model as the current position of the corresponding ChBody
+  virtual void SyncPosition();
+
+  		/// Gets the pointer to the client owner ChPhysicsItem. 
+  virtual ChPhysicsItem* GetPhysicsItem() {return (ChPhysicsItem*)GetBody();};
+
+private:
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletDEM.cpp b/SRC/ChronoEngine/collision/ChCModelBulletDEM.cpp
new file mode 100644
index 0000000..e4309dc
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletDEM.cpp
@@ -0,0 +1,72 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletBody.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com 
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+ 
+#include "ChCModelBulletDEM.h" 
+#include "physics/ChBodyDEM.h"
+#include "collision/bullet/btBulletCollisionCommon.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+ChModelBulletDEM::ChModelBulletDEM()
+{
+	mbody = 0;
+	this->model_envelope=0.0f;
+}
+
+
+ChModelBulletDEM::~ChModelBulletDEM()
+{
+}
+
+void ChModelBulletDEM::SyncPosition()
+{
+	ChBodyDEM* bpointer = GetBody();
+	assert(bpointer);
+	//assert(bpointer->GetSystem());
+
+	bt_collision_object->getWorldTransform().setOrigin(btVector3(
+								(btScalar)bpointer->GetPos().x,
+								(btScalar)bpointer->GetPos().y,
+								(btScalar)bpointer->GetPos().z));
+	ChMatrix33<>* rA = bpointer->GetA();
+	btMatrix3x3 basisA( (btScalar)(*rA)(0,0), (btScalar)(*rA)(0,1), (btScalar)(*rA)(0,2),
+						(btScalar)(*rA)(1,0), (btScalar)(*rA)(1,1), (btScalar)(*rA)(1,2),
+						(btScalar)(*rA)(2,0), (btScalar)(*rA)(2,1), (btScalar)(*rA)(2,2));
+	bt_collision_object->getWorldTransform().setBasis(basisA);
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletDEM.h b/SRC/ChronoEngine/collision/ChCModelBulletDEM.h
new file mode 100644
index 0000000..5dedbde
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletDEM.h
@@ -0,0 +1,85 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MODELBULLETDEM_H
+#define CHC_MODELBULLETDEM_H
+ 
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletDEM.h
+//
+//   A wrapper to use the Bullet collision detection
+//   library
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "collision/ChCModelBullet.h"
+
+
+namespace chrono 
+{
+
+// forward references
+class ChBodyDEM;
+
+namespace collision 
+{
+
+
+/// Class for the collision model to be used in ChIndexedParticles shapes,
+/// that are collections of point-like nodes (each with 3 DOFs)
+/// using features of the Bullet library.
+
+class ChApi ChModelBulletDEM : public ChModelBullet
+{
+
+public:
+
+  ChModelBulletDEM();
+  virtual ~ChModelBulletDEM();
+  
+
+    	/// Gets the pointer to the client owner rigid body. 
+  ChBodyDEM* GetBody() const {return mbody;};
+		/// Sets the pointer to the client owner rigid body
+  void SetBody(ChBodyDEM* mbo) {mbody = mbo;};
+
+  
+	// Overrides and implementations of base members:
+
+		/// Sets the position and orientation of the collision
+		/// model as the current position of the corresponding ChBody
+  virtual void SyncPosition();
+
+  		/// Gets the pointer to the client owner ChPhysicsItem. 
+  virtual ChPhysicsItem* GetPhysicsItem() {return (ChPhysicsItem*)GetBody();};
+
+private:
+	ChBodyDEM* mbody;
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletNode.cpp b/SRC/ChronoEngine/collision/ChCModelBulletNode.cpp
new file mode 100644
index 0000000..d9a29a8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletNode.cpp
@@ -0,0 +1,98 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletNode.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com 
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+ 
+ 
+#include "ChCModelBulletNode.h" 
+#include "physics/ChIndexedNodes.h"
+#include "collision/bullet/btBulletCollisionCommon.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+ChModelBulletNode::ChModelBulletNode()
+{
+	this->nodes = 0;
+	this->node_id = 0;
+}
+
+
+ChModelBulletNode::~ChModelBulletNode()
+{
+}
+
+
+void ChModelBulletNode::SetNode(ChIndexedNodes* mpa, unsigned int id)
+{
+	this->nodes = mpa;
+	this->node_id = id;
+}
+
+
+void ChModelBulletNode::SyncPosition()
+{
+	assert(nodes);
+
+	ChNodeXYZ* ppointer = (ChNodeXYZ*)nodes->GetNode(this->node_id);
+	
+	assert(ppointer);
+	assert(nodes->GetSystem());
+
+	bt_collision_object->getWorldTransform().setOrigin(btVector3(
+								(btScalar)ppointer->GetPos().x,
+								(btScalar)ppointer->GetPos().y,
+								(btScalar)ppointer->GetPos().z));
+
+	btMatrix3x3 basisA( (btScalar)1, (btScalar)0, (btScalar)0,
+						(btScalar)0, (btScalar)1, (btScalar)0,
+						(btScalar)0, (btScalar)0, (btScalar)1); //**rotation does not matter**
+	bt_collision_object->getWorldTransform().setBasis(basisA);
+}
+
+
+
+
+
+bool ChModelBulletNode::SetSphereRadius(double coll_radius, double out_envelope)
+{
+	if (this->shapes.size()!=1) 
+		return false;
+	if ( btSphereShape* mshape = dynamic_cast<btSphereShape*>(this->shapes[0].get_ptr()))
+	{
+		this->SetSafeMargin(coll_radius);
+		this->SetEnvelope(out_envelope);
+		mshape->setUnscaledRadius((btScalar)(coll_radius+out_envelope));
+		//mshape->setMargin((btScalar) (coll_radius+out_envelope));
+	}
+	else 
+		return false;
+	return true;
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletNode.h b/SRC/ChronoEngine/collision/ChCModelBulletNode.h
new file mode 100644
index 0000000..f312092
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletNode.h
@@ -0,0 +1,93 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MODELBULLETNODE_H
+#define CHC_MODELBULLETNODE_H
+ 
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletNode.h
+//
+//   A wrapper to use the Bullet collision detection
+//   library
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "collision/ChCModelBullet.h"
+
+
+namespace chrono 
+{
+
+// forward references
+class ChIndexedNodes;
+
+namespace collision 
+{
+
+
+/// Class for the collision model to be used in ChIndexedNodes shapes,
+/// that are collections of point-like items (each with 3 DOFs). 
+/// Uses features of the Bullet library.
+
+class ChApi ChModelBulletNode : public ChModelBullet
+{
+
+public:
+
+  ChModelBulletNode();
+  virtual ~ChModelBulletNode();
+
+		/// Sets the pointer to the client owner (the ChIndexedNodes container) and the node number.
+  void SetNode(ChIndexedNodes* mpa, unsigned int id);
+
+    	/// Gets the pointer to the client owner, ChIndexedNodes cluster. 
+  ChIndexedNodes* GetNodes() {return nodes;};
+    	/// Gets the number of the node in the  cluster. 
+  unsigned int GetNodeId() {return node_id;};
+
+		/// If the collision shape is a sphere, resize it and return true (if no 
+		/// sphere is found in this collision shape, return false). 
+		/// It can also change the outward envelope; the inward margin is automatically the radius of the sphere. 
+  bool SetSphereRadius(double coll_radius, double out_envelope);
+
+
+	// Overrides and implementations of base members:
+
+		/// Sets the position and orientation of the collision
+		/// model as the current position of the corresponding node
+  virtual void SyncPosition();
+
+  		/// Gets the pointer to the client owner ChPhysicsItem. 
+  virtual ChPhysicsItem* GetPhysicsItem() {return (ChPhysicsItem*)GetNodes();};
+
+private:
+	unsigned int node_id;
+	ChIndexedNodes* nodes;
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletParticle.cpp b/SRC/ChronoEngine/collision/ChCModelBulletParticle.cpp
new file mode 100644
index 0000000..b6c8564
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletParticle.cpp
@@ -0,0 +1,82 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletParticle.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com 
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+ 
+ 
+#include "ChCModelBulletParticle.h" 
+#include "physics/ChIndexedParticles.h"
+#include "collision/bullet/btBulletCollisionCommon.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+ChModelBulletParticle::ChModelBulletParticle()
+{
+	this->particles = 0;
+	this->particle_id = 0;
+}
+
+
+ChModelBulletParticle::~ChModelBulletParticle()
+{
+}
+
+
+void ChModelBulletParticle::SetParticle(ChIndexedParticles* mpa, unsigned int id)
+{
+	this->particles = mpa;
+	this->particle_id = id;
+}
+
+
+void ChModelBulletParticle::SyncPosition()
+{
+	assert(particles);
+
+	ChParticleBase* ppointer = &particles->GetParticle(this->particle_id);
+	
+	assert(ppointer);
+	assert(particles->GetSystem());
+
+	bt_collision_object->getWorldTransform().setOrigin(btVector3(
+								(btScalar)ppointer->GetPos().x,
+								(btScalar)ppointer->GetPos().y,
+								(btScalar)ppointer->GetPos().z));
+	ChMatrix33<>* rA = ppointer->GetA();
+	btMatrix3x3 basisA( (btScalar)(*rA)(0,0), (btScalar)(*rA)(0,1), (btScalar)(*rA)(0,2),
+						(btScalar)(*rA)(1,0), (btScalar)(*rA)(1,1), (btScalar)(*rA)(1,2),
+						(btScalar)(*rA)(2,0), (btScalar)(*rA)(2,1), (btScalar)(*rA)(2,2));
+	bt_collision_object->getWorldTransform().setBasis(basisA);
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/ChCModelBulletParticle.h b/SRC/ChronoEngine/collision/ChCModelBulletParticle.h
new file mode 100644
index 0000000..581a0d7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelBulletParticle.h
@@ -0,0 +1,88 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MODELBULLETPARTICLE_H
+#define CHC_MODELBULLETPARTICLE_H
+ 
+//////////////////////////////////////////////////
+//  
+//   ChCModelBulletParticle.h
+//
+//   A wrapper to use the Bullet collision detection
+//   library
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "collision/ChCModelBullet.h"
+
+
+namespace chrono 
+{
+
+// forward references
+class ChIndexedParticles;
+
+namespace collision 
+{
+
+
+/// Class for the collision model to be used in ChIndexedParticles shapes,
+/// that are collections of frame-like items (each with 6 DOFs). 
+/// Uses features of the Bullet library.
+
+class ChApi ChModelBulletParticle : public ChModelBullet
+{
+
+public:
+
+  ChModelBulletParticle();
+  virtual ~ChModelBulletParticle();
+
+		/// Sets the pointer to the client owner (the ChIndexedParticles cluster) and the particle number.
+  void SetParticle(ChIndexedParticles* mpa, unsigned int id);
+
+    	/// Gets the pointer to the client owner, ChIndexedParticles cluster. 
+  ChIndexedParticles* GetParticles() {return particles;};
+    	/// Gets the number of the particle in the particle cluster. 
+  unsigned int GetParticleId() {return particle_id;};
+
+
+	// Overrides and implementations of base members:
+
+		/// Sets the position and orientation of the collision
+		/// model as the current position of the corresponding item in ChParticles
+  virtual void SyncPosition();
+
+  		/// Gets the pointer to the client owner ChPhysicsItem. 
+  virtual ChPhysicsItem* GetPhysicsItem() {return (ChPhysicsItem*)GetParticles();};
+
+private:
+	unsigned int particle_id;
+	ChIndexedParticles* particles;
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/ChCModelSphereSetBody.cpp b/SRC/ChronoEngine/collision/ChCModelSphereSetBody.cpp
new file mode 100644
index 0000000..faeb665
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelSphereSetBody.cpp
@@ -0,0 +1,78 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCModelSphereSetBody.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com 
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+ 
+#include "ChCModelSphereSetBody.h"
+#include "physics/ChBody.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+ChModelSphereSetBody::ChModelSphereSetBody()
+{
+	mbody = 0;
+}
+
+
+ChModelSphereSetBody::~ChModelSphereSetBody()
+{
+}
+
+void ChModelSphereSetBody::SyncPosition()
+{
+	ChBody* bpointer=GetBody();
+	assert(bpointer);
+
+	ChCoordsys<> bodyCoord=bpointer->GetCoord();
+
+	// Update the bounding box points in global frame
+	//ChVector<> tmin=bodyCoord.TrasformLocalToParent(myBBminLocal);
+	//ChVector<> tmax=bodyCoord.TrasformLocalToParent(myBBmaxLocal);
+	ChVector<> tmin=bpointer->GetPos()+myBBminLocal;
+	ChVector<> tmax=bpointer->GetPos()+myBBmaxLocal;
+	myBBminGlobal.Set(tmin.x,tmin.y,tmin.z);
+	myBBmaxGlobal.Set(tmax.x,tmax.y,tmax.z);
+
+	// Update the sphere positions in global frame
+	thrust::host_vector< ChVector<float> > gPos;
+	gPos.resize(nSpheres);
+	for(uint i=0; i<nSpheres; i++)
+	{
+		gPos[i]=bodyCoord.TrasformLocalToParent(sphPosLocal[i]);
+	}
+
+	sphPosGlobal.swap(gPos);
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/ChCModelSphereSetBody.h b/SRC/ChronoEngine/collision/ChCModelSphereSetBody.h
new file mode 100644
index 0000000..b597ba6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/ChCModelSphereSetBody.h
@@ -0,0 +1,84 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MODELSPHERESETBODY_H
+#define CHC_MODELSPHERESETBODY_H
+ 
+//////////////////////////////////////////////////
+//  
+//   ChCModelSphereSetBody.h
+//
+//   A wrapper to use the Sphere collision detection
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "collision/ChCModelSphereSet.h"
+
+
+namespace chrono 
+{
+
+// forward references
+class ChBody;
+
+namespace collision 
+{
+
+
+/// Class for the collision model to be used in ChIndexedParticles shapes,
+/// that are collections of point-like nodes (each with 3 DOFs)
+/// using features of the Bullet library.
+
+class ChApi ChModelSphereSetBody : public ChModelSphereSet
+{
+
+public:
+
+  ChModelSphereSetBody();
+  virtual ~ChModelSphereSetBody();
+  
+
+    	/// Gets the pointer to the client owner rigid body. 
+  ChBody* GetBody() const {return mbody;};
+		/// Sets the pointer to the client owner rigid body
+  void SetBody(ChBody* mbo) {mbody = mbo;};
+
+  
+	// Overrides and implementations of base members:
+
+		/// Sets the position and orientation of the collision
+		/// model as the current position of the corresponding ChBody
+  virtual void SyncPosition();
+
+  		/// Gets the pointer to the client owner ChPhysicsItem. 
+  virtual ChPhysicsItem* GetPhysicsItem() {return (ChPhysicsItem*)GetBody();};
+
+private:
+	ChBody* mbody;
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
new file mode 100644
index 0000000..49e8b12
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.cpp
@@ -0,0 +1,38 @@
+
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+
+//
+// btAxisSweep3
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+#include "btAxisSweep3.h"
+
+
+btAxisSweep3::btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles, btOverlappingPairCache* pairCache, bool disableRaycastAccelerator)
+:btAxisSweep3Internal<unsigned short int>(worldAabbMin,worldAabbMax,0xfffe,0xffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+	// 1 handle is reserved as sentinel
+	btAssert(maxHandles > 1 && maxHandles < 32767);
+
+}
+
+
+bt32BitAxisSweep3::bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles , btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:btAxisSweep3Internal<unsigned int>(worldAabbMin,worldAabbMax,0xfffffffe,0x7fffffff,maxHandles,pairCache,disableRaycastAccelerator)
+{
+	// 1 handle is reserved as sentinel
+	btAssert(maxHandles > 1 && maxHandles < 2147483647);
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
new file mode 100644
index 0000000..07167af
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btAxisSweep3.h
@@ -0,0 +1,1051 @@
+//Bullet Continuous Collision Detection and Physics Library
+//Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+//
+// btAxisSweep3.h
+//
+// Copyright (c) 2006 Simon Hobbs
+//
+// This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
+//
+// Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+// 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+//
+// 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//
+// 3. This notice may not be removed or altered from any source distribution.
+
+#ifndef AXIS_SWEEP_3_H
+#define AXIS_SWEEP_3_H
+
+#include "LinearMath/btVector3.h"
+#include "btOverlappingPairCache.h"
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+#include "btDbvtBroadphase.h"
+
+//#define DEBUG_BROADPHASE 1
+#define USE_OVERLAP_TEST_ON_REMOVES 1
+
+/// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase.
+/// It uses quantized integers to represent the begin and end points for each of the 3 axis.
+/// Dont use this class directly, use btAxisSweep3 or bt32BitAxisSweep3 instead.
+template <typename BP_FP_INT_TYPE>
+class btAxisSweep3Internal : public btBroadphaseInterface
+{
+protected:
+
+	BP_FP_INT_TYPE	m_bpHandleMask;
+	BP_FP_INT_TYPE	m_handleSentinel;
+
+public:
+	
+ BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	class Edge
+	{
+	public:
+		BP_FP_INT_TYPE m_pos;			// low bit is min/max
+		BP_FP_INT_TYPE m_handle;
+
+		BP_FP_INT_TYPE IsMax() const {return static_cast<BP_FP_INT_TYPE>(m_pos & 1);}
+	};
+
+public:
+	class	Handle : public btBroadphaseProxy
+	{
+	public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+	
+		// indexes into the edge arrays
+		BP_FP_INT_TYPE m_minEdges[3], m_maxEdges[3];		// 6 * 2 = 12
+//		BP_FP_INT_TYPE m_uniqueId;
+		btBroadphaseProxy*	m_dbvtProxy;//for faster raycast
+		//void* m_pOwner; this is now in btBroadphaseProxy.m_clientObject
+	
+		SIMD_FORCE_INLINE void SetNextFree(BP_FP_INT_TYPE next) {m_minEdges[0] = next;}
+		SIMD_FORCE_INLINE BP_FP_INT_TYPE GetNextFree() const {return m_minEdges[0];}
+	};		// 24 bytes + 24 for Edge structures = 44 bytes total per entry
+
+	
+protected:
+	btVector3 m_worldAabbMin;						// overall system bounds
+	btVector3 m_worldAabbMax;						// overall system bounds
+
+	btVector3 m_quantize;						// scaling factor for quantization
+
+	BP_FP_INT_TYPE m_numHandles;						// number of active handles
+	BP_FP_INT_TYPE m_maxHandles;						// max number of handles
+	Handle* m_pHandles;						// handles pool
+	
+	BP_FP_INT_TYPE m_firstFreeHandle;		// free handles list
+
+	Edge* m_pEdges[3];						// edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries)
+	void* m_pEdgesRawPtr[3];
+
+	btOverlappingPairCache* m_pairCache;
+
+	///btOverlappingPairCallback is an additional optional user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+	btOverlappingPairCallback* m_userPairCallback;
+	
+	bool	m_ownsPairCache;
+
+	int	m_invalidPair;
+
+	///additional dynamic aabb structure, used to accelerate ray cast queries.
+	///can be disabled using a optional argument in the constructor
+	btDbvtBroadphase*	m_raycastAccelerator;
+	btOverlappingPairCache*	m_nullPairCache;
+
+
+	// allocation/deallocation
+	BP_FP_INT_TYPE allocHandle();
+	void freeHandle(BP_FP_INT_TYPE handle);
+	
+
+	bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1);
+
+#ifdef DEBUG_BROADPHASE
+	void debugPrintAxis(int axis,bool checkCardinality=true);
+#endif //DEBUG_BROADPHASE
+
+	//Overlap* AddOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+	//void RemoveOverlap(BP_FP_INT_TYPE handleA, BP_FP_INT_TYPE handleB);
+
+	
+
+	void sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+	void sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+	void sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+	void sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps );
+
+public:
+
+	btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel, BP_FP_INT_TYPE maxHandles = 16384, btOverlappingPairCache* pairCache=0,bool disableRaycastAccelerator = false);
+
+	virtual	~btAxisSweep3Internal();
+
+	BP_FP_INT_TYPE getNumHandles() const
+	{
+		return m_numHandles;
+	}
+
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher);
+	
+	BP_FP_INT_TYPE addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+	void removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher);
+	void updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+	SIMD_FORCE_INLINE Handle* getHandle(BP_FP_INT_TYPE index) const {return m_pHandles + index;}
+
+	virtual void resetPool(btDispatcher* dispatcher);
+
+	void	processAllOverlappingPairs(btOverlapCallback* callback);
+
+	//Broadphase Interface
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+	virtual void  getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+	
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+	
+	void quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const;
+	///unQuantize should be conservative: aabbMin/aabbMax should be larger then 'getAabb' result
+	void unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+	
+	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+	btOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_pairCache;
+	}
+	const btOverlappingPairCache*	getOverlappingPairCache() const
+	{
+		return m_pairCache;
+	}
+
+	void	setOverlappingPairUserCallback(btOverlappingPairCallback* pairCallback)
+	{
+		m_userPairCallback = pairCallback;
+	}
+	const btOverlappingPairCallback*	getOverlappingPairUserCallback() const
+	{
+		return m_userPairCallback;
+	}
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		aabbMin = m_worldAabbMin;
+		aabbMax = m_worldAabbMax;
+	}
+
+	virtual void	printStats()
+	{
+/*		printf("btAxisSweep3.h\n");
+		printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+		printf("aabbMin=%f,%f,%f,aabbMax=%f,%f,%f\n",m_worldAabbMin.getX(),m_worldAabbMin.getY(),m_worldAabbMin.getZ(),
+			m_worldAabbMax.getX(),m_worldAabbMax.getY(),m_worldAabbMax.getZ());
+			*/
+
+	}
+
+};
+
+////////////////////////////////////////////////////////////////////
+
+
+
+
+#ifdef DEBUG_BROADPHASE
+#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3<BP_FP_INT_TYPE>::debugPrintAxis(int axis, bool checkCardinality)
+{
+	int numEdges = m_pHandles[0].m_maxEdges[axis];
+	printf("SAP Axis %d, numEdges=%d\n",axis,numEdges);
+
+	int i;
+	for (i=0;i<numEdges+1;i++)
+	{
+		Edge* pEdge = m_pEdges[axis] + i;
+		Handle* pHandlePrev = getHandle(pEdge->m_handle);
+		int handleIndex = pEdge->IsMax()? pHandlePrev->m_maxEdges[axis] : pHandlePrev->m_minEdges[axis];
+		char beginOrEnd;
+		beginOrEnd=pEdge->IsMax()?'E':'B';
+		printf("	[%c,h=%d,p=%x,i=%d]\n",beginOrEnd,pEdge->m_handle,pEdge->m_pos,handleIndex);
+	}
+
+	if (checkCardinality)
+		btAssert(numEdges == m_numHandles*2+1);
+}
+#endif //DEBUG_BROADPHASE
+
+template <typename BP_FP_INT_TYPE>
+btBroadphaseProxy*	btAxisSweep3Internal<BP_FP_INT_TYPE>::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+		(void)shapeType;
+		BP_FP_INT_TYPE handleId = addHandle(aabbMin,aabbMax, userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,multiSapProxy);
+		
+		Handle* handle = getHandle(handleId);
+		
+		if (m_raycastAccelerator)
+		{
+			btBroadphaseProxy* rayProxy = m_raycastAccelerator->createProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,dispatcher,0);
+			handle->m_dbvtProxy = rayProxy;
+		}
+		return handle;
+}
+
+
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+	Handle* handle = static_cast<Handle*>(proxy);
+	if (m_raycastAccelerator)
+		m_raycastAccelerator->destroyProxy(handle->m_dbvtProxy,dispatcher);
+	removeHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), dispatcher);
+}
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+	Handle* handle = static_cast<Handle*>(proxy);
+	handle->m_aabbMin = aabbMin;
+	handle->m_aabbMax = aabbMax;
+	updateHandle(static_cast<BP_FP_INT_TYPE>(handle->m_uniqueId), aabbMin, aabbMax,dispatcher);
+	if (m_raycastAccelerator)
+		m_raycastAccelerator->setAabb(handle->m_dbvtProxy,aabbMin,aabbMax,dispatcher);
+
+}
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	if (m_raycastAccelerator)
+	{
+		m_raycastAccelerator->rayTest(rayFrom,rayTo,rayCallback,aabbMin,aabbMax);
+	} else
+	{
+		//choose axis?
+		BP_FP_INT_TYPE axis = 0;
+		//for each proxy
+		for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+		{
+			if (m_pEdges[axis][i].IsMax())
+			{
+				rayCallback.process(getHandle(m_pEdges[axis][i].m_handle));
+			}
+		}
+	}
+}
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+	if (m_raycastAccelerator)
+	{
+		m_raycastAccelerator->aabbTest(aabbMin,aabbMax,callback);
+	} else
+	{
+		//choose axis?
+		BP_FP_INT_TYPE axis = 0;
+		//for each proxy
+		for (BP_FP_INT_TYPE i=1;i<m_numHandles*2+1;i++)
+		{
+			if (m_pEdges[axis][i].IsMax())
+			{
+				Handle* handle = getHandle(m_pEdges[axis][i].m_handle);
+				if (TestAabbAgainstAabb2(aabbMin,aabbMax,handle->m_aabbMin,handle->m_aabbMax))
+				{
+					callback.process(handle);
+				}
+			}
+		}
+	}
+}
+
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	Handle* pHandle = static_cast<Handle*>(proxy);
+	aabbMin = pHandle->m_aabbMin;
+	aabbMax = pHandle->m_aabbMax;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::unQuantize(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	Handle* pHandle = static_cast<Handle*>(proxy);
+
+	unsigned short vecInMin[3];
+	unsigned short vecInMax[3];
+
+	vecInMin[0] = m_pEdges[0][pHandle->m_minEdges[0]].m_pos ;
+	vecInMax[0] = m_pEdges[0][pHandle->m_maxEdges[0]].m_pos +1 ;
+	vecInMin[1] = m_pEdges[1][pHandle->m_minEdges[1]].m_pos ;
+	vecInMax[1] = m_pEdges[1][pHandle->m_maxEdges[1]].m_pos +1 ;
+	vecInMin[2] = m_pEdges[2][pHandle->m_minEdges[2]].m_pos ;
+	vecInMax[2] = m_pEdges[2][pHandle->m_maxEdges[2]].m_pos +1 ;
+	
+	aabbMin.setValue((btScalar)(vecInMin[0]) / (m_quantize.getX()),(btScalar)(vecInMin[1]) / (m_quantize.getY()),(btScalar)(vecInMin[2]) / (m_quantize.getZ()));
+	aabbMin += m_worldAabbMin;
+	
+	aabbMax.setValue((btScalar)(vecInMax[0]) / (m_quantize.getX()),(btScalar)(vecInMax[1]) / (m_quantize.getY()),(btScalar)(vecInMax[2]) / (m_quantize.getZ()));
+	aabbMax += m_worldAabbMin;
+}
+
+
+
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::btAxisSweep3Internal(const btVector3& worldAabbMin,const btVector3& worldAabbMax, BP_FP_INT_TYPE handleMask, BP_FP_INT_TYPE handleSentinel,BP_FP_INT_TYPE userMaxHandles, btOverlappingPairCache* pairCache , bool disableRaycastAccelerator)
+:m_bpHandleMask(handleMask),
+m_handleSentinel(handleSentinel),
+m_pairCache(pairCache),
+m_userPairCallback(0),
+m_ownsPairCache(false),
+m_invalidPair(0),
+m_raycastAccelerator(0)
+{
+	BP_FP_INT_TYPE maxHandles = static_cast<BP_FP_INT_TYPE>(userMaxHandles+1);//need to add one sentinel handle
+
+	if (!m_pairCache)
+	{
+		void* ptr = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+		m_pairCache = new(ptr) btHashedOverlappingPairCache();
+		m_ownsPairCache = true;
+	}
+
+	if (!disableRaycastAccelerator)
+	{
+		m_nullPairCache = new (btAlignedAlloc(sizeof(btNullPairCache),16)) btNullPairCache();
+		m_raycastAccelerator = new (btAlignedAlloc(sizeof(btDbvtBroadphase),16)) btDbvtBroadphase(m_nullPairCache);//m_pairCache);
+		m_raycastAccelerator->m_deferedcollide = true;//don't add/remove pairs
+	}
+
+	//btAssert(bounds.HasVolume());
+
+	// init bounds
+	m_worldAabbMin = worldAabbMin;
+	m_worldAabbMax = worldAabbMax;
+
+	btVector3 aabbSize = m_worldAabbMax - m_worldAabbMin;
+
+	BP_FP_INT_TYPE	maxInt = m_handleSentinel;
+
+	m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize;
+
+	// allocate handles buffer, using btAlignedAlloc, and put all handles on free list
+	m_pHandles = new Handle[maxHandles];
+	
+	m_maxHandles = maxHandles;
+	m_numHandles = 0;
+
+	// handle 0 is reserved as the null index, and is also used as the sentinel
+	m_firstFreeHandle = 1;
+	{
+		for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < maxHandles; i++)
+			m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
+		m_pHandles[maxHandles - 1].SetNextFree(0);
+	}
+
+	{
+		// allocate edge buffers
+		for (int i = 0; i < 3; i++)
+		{
+			m_pEdgesRawPtr[i] = btAlignedAlloc(sizeof(Edge)*maxHandles*2,16);
+			m_pEdges[i] = new(m_pEdgesRawPtr[i]) Edge[maxHandles * 2];
+		}
+	}
+	//removed overlap management
+
+	// make boundary sentinels
+	
+	m_pHandles[0].m_clientObject = 0;
+
+	for (int axis = 0; axis < 3; axis++)
+	{
+		m_pHandles[0].m_minEdges[axis] = 0;
+		m_pHandles[0].m_maxEdges[axis] = 1;
+
+		m_pEdges[axis][0].m_pos = 0;
+		m_pEdges[axis][0].m_handle = 0;
+		m_pEdges[axis][1].m_pos = m_handleSentinel;
+		m_pEdges[axis][1].m_handle = 0;
+#ifdef DEBUG_BROADPHASE
+		debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+	}
+
+}
+
+template <typename BP_FP_INT_TYPE>
+btAxisSweep3Internal<BP_FP_INT_TYPE>::~btAxisSweep3Internal()
+{
+	if (m_raycastAccelerator)
+	{
+		m_nullPairCache->~btOverlappingPairCache();
+		btAlignedFree(m_nullPairCache);
+		m_raycastAccelerator->~btDbvtBroadphase();
+		btAlignedFree (m_raycastAccelerator);
+	}
+
+	for (int i = 2; i >= 0; i--)
+	{
+		btAlignedFree(m_pEdgesRawPtr[i]);
+	}
+	delete [] m_pHandles;
+
+	if (m_ownsPairCache)
+	{
+		m_pairCache->~btOverlappingPairCache();
+		btAlignedFree(m_pairCache);
+	}
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::quantize(BP_FP_INT_TYPE* out, const btVector3& point, int isMax) const
+{
+#ifdef OLD_CLAMPING_METHOD
+	///problem with this clamping method is that the floating point during quantization might still go outside the range [(0|isMax) .. (m_handleSentinel&m_bpHandleMask]|isMax]
+	///see http://code.google.com/p/bullet/issues/detail?id=87
+	btVector3 clampedPoint(point);
+	clampedPoint.setMax(m_worldAabbMin);
+	clampedPoint.setMin(m_worldAabbMax);
+	btVector3 v = (clampedPoint - m_worldAabbMin) * m_quantize;
+	out[0] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getX() & m_bpHandleMask) | isMax);
+	out[1] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getY() & m_bpHandleMask) | isMax);
+	out[2] = (BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v.getZ() & m_bpHandleMask) | isMax);
+#else
+	btVector3 v = (point - m_worldAabbMin) * m_quantize;
+	out[0]=(v[0]<=0)?(BP_FP_INT_TYPE)isMax:(v[0]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[0]&m_bpHandleMask)|isMax);
+	out[1]=(v[1]<=0)?(BP_FP_INT_TYPE)isMax:(v[1]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[1]&m_bpHandleMask)|isMax);
+	out[2]=(v[2]<=0)?(BP_FP_INT_TYPE)isMax:(v[2]>=m_handleSentinel)?(BP_FP_INT_TYPE)((m_handleSentinel&m_bpHandleMask)|isMax):(BP_FP_INT_TYPE)(((BP_FP_INT_TYPE)v[2]&m_bpHandleMask)|isMax);
+#endif //OLD_CLAMPING_METHOD
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::allocHandle()
+{
+	btAssert(m_firstFreeHandle);
+
+	BP_FP_INT_TYPE handle = m_firstFreeHandle;
+	m_firstFreeHandle = getHandle(handle)->GetNextFree();
+	m_numHandles++;
+
+	return handle;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::freeHandle(BP_FP_INT_TYPE handle)
+{
+	btAssert(handle > 0 && handle < m_maxHandles);
+
+	getHandle(handle)->SetNextFree(m_firstFreeHandle);
+	m_firstFreeHandle = handle;
+
+	m_numHandles--;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+BP_FP_INT_TYPE btAxisSweep3Internal<BP_FP_INT_TYPE>::addHandle(const btVector3& aabbMin,const btVector3& aabbMax, void* pOwner,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy)
+{
+	// quantize the bounds
+	BP_FP_INT_TYPE min[3], max[3];
+	quantize(min, aabbMin, 0);
+	quantize(max, aabbMax, 1);
+
+	// allocate a handle
+	BP_FP_INT_TYPE handle = allocHandle();
+	
+
+	Handle* pHandle = getHandle(handle);
+	
+	pHandle->m_uniqueId = static_cast<int>(handle);
+	//pHandle->m_pOverlaps = 0;
+	pHandle->m_clientObject = pOwner;
+	pHandle->m_collisionFilterGroup = collisionFilterGroup;
+	pHandle->m_collisionFilterMask = collisionFilterMask;
+	pHandle->m_multiSapParentProxy = multiSapProxy;
+
+	// compute current limit of edge arrays
+	BP_FP_INT_TYPE limit = static_cast<BP_FP_INT_TYPE>(m_numHandles * 2);
+
+	
+	// insert new edges just inside the max boundary edge
+	for (BP_FP_INT_TYPE axis = 0; axis < 3; axis++)
+	{
+
+		m_pHandles[0].m_maxEdges[axis] += 2;
+
+		m_pEdges[axis][limit + 1] = m_pEdges[axis][limit - 1];
+
+		m_pEdges[axis][limit - 1].m_pos = min[axis];
+		m_pEdges[axis][limit - 1].m_handle = handle;
+
+		m_pEdges[axis][limit].m_pos = max[axis];
+		m_pEdges[axis][limit].m_handle = handle;
+
+		pHandle->m_minEdges[axis] = static_cast<BP_FP_INT_TYPE>(limit - 1);
+		pHandle->m_maxEdges[axis] = limit;
+	}
+
+	// now sort the new edges to their correct position
+	sortMinDown(0, pHandle->m_minEdges[0], dispatcher,false);
+	sortMaxDown(0, pHandle->m_maxEdges[0], dispatcher,false);
+	sortMinDown(1, pHandle->m_minEdges[1], dispatcher,false);
+	sortMaxDown(1, pHandle->m_maxEdges[1], dispatcher,false);
+	sortMinDown(2, pHandle->m_minEdges[2], dispatcher,true);
+	sortMaxDown(2, pHandle->m_maxEdges[2], dispatcher,true);
+
+
+	return handle;
+}
+
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::removeHandle(BP_FP_INT_TYPE handle,btDispatcher* dispatcher)
+{
+
+	Handle* pHandle = getHandle(handle);
+
+	//explicitly remove the pairs containing the proxy
+	//we could do it also in the sortMinUp (passing true)
+	///@todo: compare performance
+	if (!m_pairCache->hasDeferredRemoval())
+	{
+		m_pairCache->removeOverlappingPairsContainingProxy(pHandle,dispatcher);
+	}
+
+	// compute current limit of edge arrays
+	int limit = static_cast<int>(m_numHandles * 2);
+	
+	int axis;
+
+	for (axis = 0;axis<3;axis++)
+	{
+		m_pHandles[0].m_maxEdges[axis] -= 2;
+	}
+
+	// remove the edges by sorting them up to the end of the list
+	for ( axis = 0; axis < 3; axis++)
+	{
+		Edge* pEdges = m_pEdges[axis];
+		BP_FP_INT_TYPE max = pHandle->m_maxEdges[axis];
+		pEdges[max].m_pos = m_handleSentinel;
+
+		sortMaxUp(axis,max,dispatcher,false);
+
+
+		BP_FP_INT_TYPE i = pHandle->m_minEdges[axis];
+		pEdges[i].m_pos = m_handleSentinel;
+
+
+		sortMinUp(axis,i,dispatcher,false);
+
+		pEdges[limit-1].m_handle = 0;
+		pEdges[limit-1].m_pos = m_handleSentinel;
+		
+#ifdef DEBUG_BROADPHASE
+			debugPrintAxis(axis,false);
+#endif //DEBUG_BROADPHASE
+
+
+	}
+
+
+	// free the handle
+	freeHandle(handle);
+
+	
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::resetPool(btDispatcher* dispatcher)
+{
+	if (m_numHandles == 0)
+	{
+		m_firstFreeHandle = 1;
+		{
+			for (BP_FP_INT_TYPE i = m_firstFreeHandle; i < m_maxHandles; i++)
+				m_pHandles[i].SetNextFree(static_cast<BP_FP_INT_TYPE>(i + 1));
+			m_pHandles[m_maxHandles - 1].SetNextFree(0);
+		}
+	}
+}       
+
+
+extern int gOverlappingPairs;
+//#include <stdio.h>
+
+template <typename BP_FP_INT_TYPE>
+void	btAxisSweep3Internal<BP_FP_INT_TYPE>::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+	if (m_pairCache->hasDeferredRemoval())
+	{
+	
+		btBroadphasePairArray&	overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+
+		
+		int i;
+
+		btBroadphasePair previousPair;
+		previousPair.m_pProxy0 = 0;
+		previousPair.m_pProxy1 = 0;
+		previousPair.m_algorithm = 0;
+		
+		
+		for (i=0;i<overlappingPairArray.size();i++)
+		{
+		
+			btBroadphasePair& pair = overlappingPairArray[i];
+
+			bool isDuplicate = (pair == previousPair);
+
+			previousPair = pair;
+
+			bool needsRemoval = false;
+
+			if (!isDuplicate)
+			{
+				///important to use an AABB test that is consistent with the broadphase
+				bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+				if (hasOverlap)
+				{
+					needsRemoval = false;//callback->processOverlap(pair);
+				} else
+				{
+					needsRemoval = true;
+				}
+			} else
+			{
+				//remove duplicate
+				needsRemoval = true;
+				//should have no algorithm
+				btAssert(!pair.m_algorithm);
+			}
+			
+			if (needsRemoval)
+			{
+				m_pairCache->cleanOverlappingPair(pair,dispatcher);
+
+		//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+		//		m_overlappingPairArray.pop_back();
+				pair.m_pProxy0 = 0;
+				pair.m_pProxy1 = 0;
+				m_invalidPair++;
+				gOverlappingPairs--;
+			} 
+			
+		}
+
+	///if you don't like to skip the invalid pairs in the array, execute following code:
+	#define CLEAN_INVALID_PAIRS 1
+	#ifdef CLEAN_INVALID_PAIRS
+
+		//perform a sort, to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+	#endif//CLEAN_INVALID_PAIRS
+		
+		//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+	}
+
+}
+
+
+template <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	const Handle* pHandleA = static_cast<Handle*>(proxy0);
+	const Handle* pHandleB = static_cast<Handle*>(proxy1);
+	
+	//optimization 1: check the array index (memory address), instead of the m_pos
+
+	for (int axis = 0; axis < 3; axis++)
+	{ 
+		if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || 
+			pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) 
+		{ 
+			return false; 
+		} 
+	} 
+	return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+bool btAxisSweep3Internal<BP_FP_INT_TYPE>::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1)
+{
+	//optimization 1: check the array index (memory address), instead of the m_pos
+
+	if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || 
+		pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] ||
+		pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] ||
+		pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) 
+	{ 
+		return false; 
+	} 
+	return true;
+}
+
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::updateHandle(BP_FP_INT_TYPE handle, const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher)
+{
+//	btAssert(bounds.IsFinite());
+	//btAssert(bounds.HasVolume());
+
+	Handle* pHandle = getHandle(handle);
+
+	// quantize the new bounds
+	BP_FP_INT_TYPE min[3], max[3];
+	quantize(min, aabbMin, 0);
+	quantize(max, aabbMax, 1);
+
+	// update changed edges
+	for (int axis = 0; axis < 3; axis++)
+	{
+		BP_FP_INT_TYPE emin = pHandle->m_minEdges[axis];
+		BP_FP_INT_TYPE emax = pHandle->m_maxEdges[axis];
+
+		int dmin = (int)min[axis] - (int)m_pEdges[axis][emin].m_pos;
+		int dmax = (int)max[axis] - (int)m_pEdges[axis][emax].m_pos;
+
+		m_pEdges[axis][emin].m_pos = min[axis];
+		m_pEdges[axis][emax].m_pos = max[axis];
+
+		// expand (only adds overlaps)
+		if (dmin < 0)
+			sortMinDown(axis, emin,dispatcher,true);
+
+		if (dmax > 0)
+			sortMaxUp(axis, emax,dispatcher,true);
+
+		// shrink (only removes overlaps)
+		if (dmin > 0)
+			sortMinUp(axis, emin,dispatcher,true);
+
+		if (dmax < 0)
+			sortMaxDown(axis, emax,dispatcher,true);
+
+#ifdef DEBUG_BROADPHASE
+	debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+	}
+
+	
+}
+
+
+
+
+// sorting a min edge downwards can only ever *add* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pPrev = pEdge - 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pEdge->m_pos < pPrev->m_pos)
+	{
+		Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+		if (pPrev->IsMax())
+		{
+			// if previous edge is a maximum check the bounds and add an overlap if necessary
+			const int axis1 = (1  << axis) & 3;
+			const int axis2 = (1  << axis1) & 3;
+			if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2))
+			{
+				m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev);
+				if (m_userPairCallback)
+					m_userPairCallback->addOverlappingPair(pHandleEdge,pHandlePrev);
+
+				//AddOverlap(pEdge->m_handle, pPrev->m_handle);
+
+			}
+
+			// update edge reference in other handle
+			pHandlePrev->m_maxEdges[axis]++;
+		}
+		else
+			pHandlePrev->m_minEdges[axis]++;
+
+		pHandleEdge->m_minEdges[axis]--;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pPrev;
+		*pPrev = swap;
+
+		// decrement
+		pEdge--;
+		pPrev--;
+	}
+
+#ifdef DEBUG_BROADPHASE
+	debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a min edge upwards can only ever *remove* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMinUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pNext = pEdge + 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+	{
+		Handle* pHandleNext = getHandle(pNext->m_handle);
+
+		if (pNext->IsMax())
+		{
+			Handle* handle0 = getHandle(pEdge->m_handle);
+			Handle* handle1 = getHandle(pNext->m_handle);
+			const int axis1 = (1  << axis) & 3;
+			const int axis2 = (1  << axis1) & 3;
+			
+			// if next edge is maximum remove any overlap between the two handles
+			if (updateOverlaps 
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+				&& testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+				)
+			{
+				
+
+				m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);	
+				if (m_userPairCallback)
+					m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+				
+			}
+
+
+			// update edge reference in other handle
+			pHandleNext->m_maxEdges[axis]--;
+		}
+		else
+			pHandleNext->m_minEdges[axis]--;
+
+		pHandleEdge->m_minEdges[axis]++;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pNext;
+		*pNext = swap;
+
+		// increment
+		pEdge++;
+		pNext++;
+	}
+
+
+}
+
+// sorting a max edge downwards can only ever *remove* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxDown(int axis, BP_FP_INT_TYPE edge, btDispatcher* dispatcher, bool updateOverlaps)
+{
+
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pPrev = pEdge - 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pEdge->m_pos < pPrev->m_pos)
+	{
+		Handle* pHandlePrev = getHandle(pPrev->m_handle);
+
+		if (!pPrev->IsMax())
+		{
+			// if previous edge was a minimum remove any overlap between the two handles
+			Handle* handle0 = getHandle(pEdge->m_handle);
+			Handle* handle1 = getHandle(pPrev->m_handle);
+			const int axis1 = (1  << axis) & 3;
+			const int axis2 = (1  << axis1) & 3;
+
+			if (updateOverlaps  
+#ifdef USE_OVERLAP_TEST_ON_REMOVES
+				&& testOverlap2D(handle0,handle1,axis1,axis2)
+#endif //USE_OVERLAP_TEST_ON_REMOVES
+				)
+			{
+				//this is done during the overlappingpairarray iteration/narrowphase collision
+
+				
+				m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher);
+				if (m_userPairCallback)
+					m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher);
+			
+
+
+			}
+
+			// update edge reference in other handle
+			pHandlePrev->m_minEdges[axis]++;;
+		}
+		else
+			pHandlePrev->m_maxEdges[axis]++;
+
+		pHandleEdge->m_maxEdges[axis]--;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pPrev;
+		*pPrev = swap;
+
+		// decrement
+		pEdge--;
+		pPrev--;
+	}
+
+	
+#ifdef DEBUG_BROADPHASE
+	debugPrintAxis(axis);
+#endif //DEBUG_BROADPHASE
+
+}
+
+// sorting a max edge upwards can only ever *add* overlaps
+template <typename BP_FP_INT_TYPE>
+void btAxisSweep3Internal<BP_FP_INT_TYPE>::sortMaxUp(int axis, BP_FP_INT_TYPE edge, btDispatcher* /* dispatcher */, bool updateOverlaps)
+{
+	Edge* pEdge = m_pEdges[axis] + edge;
+	Edge* pNext = pEdge + 1;
+	Handle* pHandleEdge = getHandle(pEdge->m_handle);
+
+	while (pNext->m_handle && (pEdge->m_pos >= pNext->m_pos))
+	{
+		Handle* pHandleNext = getHandle(pNext->m_handle);
+
+		const int axis1 = (1  << axis) & 3;
+		const int axis2 = (1  << axis1) & 3;
+
+		if (!pNext->IsMax())
+		{
+			// if next edge is a minimum check the bounds and add an overlap if necessary
+			if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2))
+			{
+				Handle* handle0 = getHandle(pEdge->m_handle);
+				Handle* handle1 = getHandle(pNext->m_handle);
+				m_pairCache->addOverlappingPair(handle0,handle1);
+				if (m_userPairCallback)
+					m_userPairCallback->addOverlappingPair(handle0,handle1);
+			}
+
+			// update edge reference in other handle
+			pHandleNext->m_minEdges[axis]--;
+		}
+		else
+			pHandleNext->m_maxEdges[axis]--;
+
+		pHandleEdge->m_maxEdges[axis]++;
+
+		// swap the edges
+		Edge swap = *pEdge;
+		*pEdge = *pNext;
+		*pNext = swap;
+
+		// increment
+		pEdge++;
+		pNext++;
+	}
+	
+}
+
+
+
+////////////////////////////////////////////////////////////////////
+
+
+/// The btAxisSweep3 is an efficient implementation of the 3d axis sweep and prune broadphase.
+/// It uses arrays rather then lists for storage of the 3 axis. Also it operates using 16 bit integer coordinates instead of floats.
+/// For large worlds and many objects, use bt32BitAxisSweep3 or btDbvtBroadphase instead. bt32BitAxisSweep3 has higher precision and allows more then 16384 objects at the cost of more memory and bit of performance.
+class btAxisSweep3 : public btAxisSweep3Internal<unsigned short int>
+{
+public:
+
+	btAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned short int maxHandles = 16384, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+/// The bt32BitAxisSweep3 allows higher precision quantization and more objects compared to the btAxisSweep3 sweep and prune.
+/// This comes at the cost of more memory per handle, and a bit slower performance.
+/// It uses arrays rather then lists for storage of the 3 axis.
+class bt32BitAxisSweep3 : public btAxisSweep3Internal<unsigned int>
+{
+public:
+
+	bt32BitAxisSweep3(const btVector3& worldAabbMin,const btVector3& worldAabbMax, unsigned int maxHandles = 1500000, btOverlappingPairCache* pairCache = 0, bool disableRaycastAccelerator = false);
+
+};
+
+#endif
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
new file mode 100644
index 0000000..fe414ef
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseInterface.h
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef		BROADPHASE_INTERFACE_H
+#define 	BROADPHASE_INTERFACE_H
+
+
+
+struct btDispatcherInfo;
+class btDispatcher;
+#include "btBroadphaseProxy.h"
+
+class btOverlappingPairCache;
+
+
+
+struct	btBroadphaseAabbCallback
+{
+	virtual ~btBroadphaseAabbCallback() {}
+	virtual bool	process(const btBroadphaseProxy* proxy) = 0;
+};
+
+
+struct	btBroadphaseRayCallback : public btBroadphaseAabbCallback
+{
+	///added some cached data to accelerate ray-AABB tests
+	btVector3		m_rayDirectionInverse;
+	unsigned int	m_signs[3];
+	btScalar		m_lambda_max;
+
+	virtual ~btBroadphaseRayCallback() {}
+};
+
+#include "LinearMath/btVector3.h"
+
+///The btBroadphaseInterface class provides an interface to detect aabb-overlapping object pairs.
+///Some implementations for this broadphase interface include btAxisSweep3, bt32BitAxisSweep3 and btDbvtBroadphase.
+///The actual overlapping pair management, storage, adding and removing of pairs is dealt by the btOverlappingPairCache class.
+class btBroadphaseInterface
+{
+public:
+	virtual ~btBroadphaseInterface() {}
+
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy) =0;
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)=0;
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)=0;
+	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const =0;
+
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0)) = 0;
+
+	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback) = 0;
+
+	///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher)=0;
+
+	virtual	btOverlappingPairCache*	getOverlappingPairCache()=0;
+	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const =0;
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher) { (void) dispatcher; };
+
+	virtual void	printStats() = 0;
+
+};
+
+#endif //BROADPHASE_INTERFACE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
new file mode 100644
index 0000000..f4d7341
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.cpp
@@ -0,0 +1,17 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBroadphaseProxy.h"
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
new file mode 100644
index 0000000..39def06
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h
@@ -0,0 +1,271 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BROADPHASE_PROXY_H
+#define BROADPHASE_PROXY_H
+
+#include "LinearMath/btScalar.h" //for SIMD_FORCE_INLINE
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+/// btDispatcher uses these types
+/// IMPORTANT NOTE:The types are ordered polyhedral, implicit convex and concave
+/// to facilitate type checking
+/// CUSTOM_POLYHEDRAL_SHAPE_TYPE,CUSTOM_CONVEX_SHAPE_TYPE and CUSTOM_CONCAVE_SHAPE_TYPE can be used to extend Bullet without modifying source code
+enum BroadphaseNativeTypes
+{
+	// polyhedral convex shapes
+	BOX_SHAPE_PROXYTYPE,
+	TRIANGLE_SHAPE_PROXYTYPE,
+	TETRAHEDRAL_SHAPE_PROXYTYPE,
+	CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE,
+	CONVEX_HULL_SHAPE_PROXYTYPE,
+	CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE,
+	CUSTOM_POLYHEDRAL_SHAPE_TYPE,
+//implicit convex shapes
+IMPLICIT_CONVEX_SHAPES_START_HERE,
+	SPHERE_SHAPE_PROXYTYPE,
+	MULTI_SPHERE_SHAPE_PROXYTYPE,
+	CAPSULE_SHAPE_PROXYTYPE,
+	CONE_SHAPE_PROXYTYPE,
+	CONVEX_SHAPE_PROXYTYPE,
+	CYLINDER_SHAPE_PROXYTYPE,
+	UNIFORM_SCALING_SHAPE_PROXYTYPE,
+	MINKOWSKI_SUM_SHAPE_PROXYTYPE,
+	MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE,
+	BOX_2D_SHAPE_PROXYTYPE,
+	CONVEX_2D_SHAPE_PROXYTYPE,
+	CUSTOM_CONVEX_SHAPE_TYPE,
+	BARREL_SHAPE_PROXYTYPE,   //***ALEX***
+//concave shapes
+CONCAVE_SHAPES_START_HERE,
+	//keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy!
+	TRIANGLE_MESH_SHAPE_PROXYTYPE,
+	SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE,
+	///used for demo integration FAST/Swift collision library and Bullet
+	FAST_CONCAVE_MESH_PROXYTYPE,
+	//terrain
+	TERRAIN_SHAPE_PROXYTYPE,
+///Used for GIMPACT Trimesh integration
+	GIMPACT_SHAPE_PROXYTYPE,
+///Multimaterial mesh
+    MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE,
+	
+	EMPTY_SHAPE_PROXYTYPE,
+	STATIC_PLANE_PROXYTYPE,
+	CUSTOM_CONCAVE_SHAPE_TYPE,
+CONCAVE_SHAPES_END_HERE,
+
+	COMPOUND_SHAPE_PROXYTYPE,
+
+	SOFTBODY_SHAPE_PROXYTYPE,
+	HFFLUID_SHAPE_PROXYTYPE,
+	HFFLUID_BUOYANT_CONVEX_SHAPE_PROXYTYPE,
+	INVALID_SHAPE_PROXYTYPE,
+
+	MAX_BROADPHASE_COLLISION_TYPES
+	
+};
+
+
+///The btBroadphaseProxy is the main class that can be used with the Bullet broadphases. 
+///It stores collision shape type information, collision filter information and a client object, typically a btCollisionObject or btRigidBody.
+ATTRIBUTE_ALIGNED16(struct) btBroadphaseProxy
+{
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+	
+	///optional filtering to cull potential collisions
+	enum CollisionFilterGroups
+	{
+	        DefaultFilter = 1,
+	        StaticFilter = 2,
+	        KinematicFilter = 4,
+	        DebrisFilter = 8,
+			SensorTrigger = 16,
+			CharacterFilter = 32,
+	        AllFilter = -1 //all bits sets: DefaultFilter | StaticFilter | KinematicFilter | DebrisFilter | SensorTrigger
+	};
+
+	//Usually the client btCollisionObject or Rigidbody class
+	void*	m_clientObject;
+	short int m_collisionFilterGroup;
+	short int m_collisionFilterMask;
+	void*	m_multiSapParentProxy;		
+	int			m_uniqueId;//m_uniqueId is introduced for paircache. could get rid of this, by calculating the address offset etc.
+
+	btVector3	m_aabbMin;
+	btVector3	m_aabbMax;
+
+	SIMD_FORCE_INLINE int getUid() const
+	{
+		return m_uniqueId;
+	}
+
+	//used for memory pools
+	btBroadphaseProxy() :m_clientObject(0),m_multiSapParentProxy(0)
+	{
+	}
+
+	btBroadphaseProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask,void* multiSapParentProxy=0)
+		:m_clientObject(userPtr),
+		m_collisionFilterGroup(collisionFilterGroup),
+		m_collisionFilterMask(collisionFilterMask),
+		m_aabbMin(aabbMin),
+		m_aabbMax(aabbMax)
+	{
+		m_multiSapParentProxy = multiSapParentProxy;
+	}
+
+	
+
+	static SIMD_FORCE_INLINE bool isPolyhedral(int proxyType)
+	{
+		return (proxyType  < IMPLICIT_CONVEX_SHAPES_START_HERE);
+	}
+
+	static SIMD_FORCE_INLINE bool	isConvex(int proxyType)
+	{
+		return (proxyType < CONCAVE_SHAPES_START_HERE);
+	}
+
+	static SIMD_FORCE_INLINE bool	isNonMoving(int proxyType)
+	{
+		return (isConcave(proxyType) && !(proxyType==GIMPACT_SHAPE_PROXYTYPE));
+	}
+
+	static SIMD_FORCE_INLINE bool	isConcave(int proxyType)
+	{
+		return ((proxyType > CONCAVE_SHAPES_START_HERE) &&
+			(proxyType < CONCAVE_SHAPES_END_HERE));
+	}
+	static SIMD_FORCE_INLINE bool	isCompound(int proxyType)
+	{
+		return (proxyType == COMPOUND_SHAPE_PROXYTYPE);
+	}
+
+	static SIMD_FORCE_INLINE bool	isSoftBody(int proxyType)
+	{
+		return (proxyType == SOFTBODY_SHAPE_PROXYTYPE);
+	}
+
+	static SIMD_FORCE_INLINE bool isInfinite(int proxyType)
+	{
+		return (proxyType == STATIC_PLANE_PROXYTYPE);
+	}
+
+	static SIMD_FORCE_INLINE bool isConvex2d(int proxyType)
+	{
+		return (proxyType == BOX_2D_SHAPE_PROXYTYPE) ||	(proxyType == CONVEX_2D_SHAPE_PROXYTYPE);
+	}
+
+	
+}
+;
+
+class btCollisionAlgorithm;
+
+struct btBroadphaseProxy;
+
+
+
+///The btBroadphasePair class contains a pair of aabb-overlapping objects.
+///A btDispatcher can search a btCollisionAlgorithm that performs exact/narrowphase collision detection on the actual collision shapes.
+ATTRIBUTE_ALIGNED16(struct) btBroadphasePair
+{
+	btBroadphasePair ()
+		:
+	m_pProxy0(0),
+		m_pProxy1(0),
+		m_algorithm(0),
+		m_internalInfo1(0)
+	{
+	}
+
+BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btBroadphasePair(const btBroadphasePair& other)
+		:		m_pProxy0(other.m_pProxy0),
+				m_pProxy1(other.m_pProxy1),
+				m_algorithm(other.m_algorithm),
+				m_internalInfo1(other.m_internalInfo1)
+	{
+	}
+	btBroadphasePair(btBroadphaseProxy& proxy0,btBroadphaseProxy& proxy1)
+	{
+
+		//keep them sorted, so the std::set operations work
+		if (proxy0.m_uniqueId < proxy1.m_uniqueId)
+        { 
+            m_pProxy0 = &proxy0; 
+            m_pProxy1 = &proxy1; 
+        }
+        else 
+        { 
+			m_pProxy0 = &proxy1; 
+            m_pProxy1 = &proxy0; 
+        }
+
+		m_algorithm = 0;
+		m_internalInfo1 = 0;
+
+	}
+	
+	btBroadphaseProxy* m_pProxy0;
+	btBroadphaseProxy* m_pProxy1;
+	
+	mutable btCollisionAlgorithm* m_algorithm;
+	union { void* m_internalInfo1; int m_internalTmpValue;};//don't use this data, it will be removed in future version.
+
+};
+
+/*
+//comparison for set operation, see Solid DT_Encounter
+SIMD_FORCE_INLINE bool operator<(const btBroadphasePair& a, const btBroadphasePair& b) 
+{ 
+    return a.m_pProxy0 < b.m_pProxy0 || 
+        (a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 < b.m_pProxy1); 
+}
+*/
+
+
+
+class btBroadphasePairSortPredicate
+{
+	public:
+
+		bool operator() ( const btBroadphasePair& a, const btBroadphasePair& b )
+		{
+			const int uidA0 = a.m_pProxy0 ? a.m_pProxy0->m_uniqueId : -1;
+			const int uidB0 = b.m_pProxy0 ? b.m_pProxy0->m_uniqueId : -1;
+			const int uidA1 = a.m_pProxy1 ? a.m_pProxy1->m_uniqueId : -1;
+			const int uidB1 = b.m_pProxy1 ? b.m_pProxy1->m_uniqueId : -1;
+
+			 return uidA0 > uidB0 || 
+				(a.m_pProxy0 == b.m_pProxy0 && uidA1 > uidB1) ||
+				(a.m_pProxy0 == b.m_pProxy0 && a.m_pProxy1 == b.m_pProxy1 && a.m_algorithm > b.m_algorithm); 
+		}
+};
+
+
+SIMD_FORCE_INLINE bool operator==(const btBroadphasePair& a, const btBroadphasePair& b) 
+{
+	 return (a.m_pProxy0 == b.m_pProxy0) && (a.m_pProxy1 == b.m_pProxy1);
+}
+
+
+#endif //BROADPHASE_PROXY_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
new file mode 100644
index 0000000..c95d1be
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.cpp
@@ -0,0 +1,23 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionAlgorithm.h"
+#include "btDispatcher.h"
+
+btCollisionAlgorithm::btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+{
+	m_dispatcher = ci.m_dispatcher1;
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
new file mode 100644
index 0000000..1618ad9
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COLLISION_ALGORITHM_H
+#define COLLISION_ALGORITHM_H
+
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct btBroadphaseProxy;
+class btDispatcher;
+class btManifoldResult;
+class btCollisionObject;
+struct btDispatcherInfo;
+class	btPersistentManifold;
+
+typedef btAlignedObjectArray<btPersistentManifold*>	btManifoldArray;
+
+struct btCollisionAlgorithmConstructionInfo
+{
+	btCollisionAlgorithmConstructionInfo()
+		:m_dispatcher1(0),
+		m_manifold(0)
+	{
+	}
+	btCollisionAlgorithmConstructionInfo(btDispatcher* dispatcher,int temp)
+		:m_dispatcher1(dispatcher)
+	{
+		(void)temp;
+	}
+
+	btDispatcher*	m_dispatcher1;
+	btPersistentManifold*	m_manifold;
+
+	int	getDispatcherId();
+
+};
+
+
+///btCollisionAlgorithm is an collision interface that is compatible with the Broadphase and btDispatcher.
+///It is persistent over frames
+class btCollisionAlgorithm
+{
+
+protected:
+
+	btDispatcher*	m_dispatcher;
+
+protected:
+	int	getDispatcherId();
+	
+public:
+
+	btCollisionAlgorithm() {};
+
+	btCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+	virtual ~btCollisionAlgorithm() {};
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) = 0;
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray) = 0;
+};
+
+
+#endif //COLLISION_ALGORITHM_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
new file mode 100644
index 0000000..95443af
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.cpp
@@ -0,0 +1,1295 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#include "btDbvt.h"
+
+//
+typedef btAlignedObjectArray<btDbvtNode*>			tNodeArray;
+typedef btAlignedObjectArray<const btDbvtNode*>	tConstNodeArray;
+
+//
+struct btDbvtNodeEnumerator : btDbvt::ICollide
+{
+	tConstNodeArray	nodes;
+	void Process(const btDbvtNode* n) { nodes.push_back(n); }
+};
+
+//
+static DBVT_INLINE int			indexof(const btDbvtNode* node)
+{
+	return(node->parent->childs[1]==node);
+}
+
+//
+static DBVT_INLINE btDbvtVolume	merge(	const btDbvtVolume& a,
+									  const btDbvtVolume& b)
+{
+#if (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)
+	ATTRIBUTE_ALIGNED16(char locals[sizeof(btDbvtAabbMm)]);
+	btDbvtVolume&	res=*(btDbvtVolume*)locals;
+#else
+		btDbvtVolume	res;
+#endif
+	Merge(a,b,res);
+	return(res);
+}
+
+// volume+edge lengths
+static DBVT_INLINE btScalar		size(const btDbvtVolume& a)
+{
+	const btVector3	edges=a.Lengths();
+	return(	edges.x()*edges.y()*edges.z()+
+		edges.x()+edges.y()+edges.z());
+}
+
+//
+static void						getmaxdepth(const btDbvtNode* node,int depth,int& maxdepth)
+{
+	if(node->isinternal())
+	{
+		getmaxdepth(node->childs[0],depth+1,maxdepth);
+		getmaxdepth(node->childs[1],depth+1,maxdepth);
+	} else maxdepth=btMax(maxdepth,depth);
+}
+
+//
+static DBVT_INLINE void			deletenode(	btDbvt* pdbvt,
+										   btDbvtNode* node)
+{
+	btAlignedFree(pdbvt->m_free);
+	pdbvt->m_free=node;
+}
+
+//
+static void						recursedeletenode(	btDbvt* pdbvt,
+												  btDbvtNode* node)
+{
+	if(!node->isleaf())
+	{
+		recursedeletenode(pdbvt,node->childs[0]);
+		recursedeletenode(pdbvt,node->childs[1]);
+	}
+	if(node==pdbvt->m_root) pdbvt->m_root=0;
+	deletenode(pdbvt,node);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
+										   btDbvtNode* parent,
+										   void* data)
+{
+	btDbvtNode*	node;
+	if(pdbvt->m_free)
+	{ node=pdbvt->m_free;pdbvt->m_free=0; }
+	else
+	{ node=new(btAlignedAlloc(sizeof(btDbvtNode),16)) btDbvtNode(); }
+	node->parent	=	parent;
+	node->data		=	data;
+	node->childs[1]	=	0;
+	return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
+										   btDbvtNode* parent,
+										   const btDbvtVolume& volume,
+										   void* data)
+{
+	btDbvtNode*	node=createnode(pdbvt,parent,data);
+	node->volume=volume;
+	return(node);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	createnode(	btDbvt* pdbvt,
+										   btDbvtNode* parent,
+										   const btDbvtVolume& volume0,
+										   const btDbvtVolume& volume1,
+										   void* data)
+{
+	btDbvtNode*	node=createnode(pdbvt,parent,data);
+	Merge(volume0,volume1,node->volume);
+	return(node);
+}
+
+//
+static void						insertleaf(	btDbvt* pdbvt,
+										   btDbvtNode* root,
+										   btDbvtNode* leaf)
+{
+	if(!pdbvt->m_root)
+	{
+		pdbvt->m_root	=	leaf;
+		leaf->parent	=	0;
+	}
+	else
+	{
+		if(!root->isleaf())
+		{
+			do	{
+				root=root->childs[Select(	leaf->volume,
+					root->childs[0]->volume,
+					root->childs[1]->volume)];
+			} while(!root->isleaf());
+		}
+		btDbvtNode*	prev=root->parent;
+		btDbvtNode*	node=createnode(pdbvt,prev,leaf->volume,root->volume,0);
+		if(prev)
+		{
+			prev->childs[indexof(root)]	=	node;
+			node->childs[0]				=	root;root->parent=node;
+			node->childs[1]				=	leaf;leaf->parent=node;
+			do	{
+				if(!prev->volume.Contain(node->volume))
+					Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+				else
+					break;
+				node=prev;
+			} while(0!=(prev=node->parent));
+		}
+		else
+		{
+			node->childs[0]	=	root;root->parent=node;
+			node->childs[1]	=	leaf;leaf->parent=node;
+			pdbvt->m_root	=	node;
+		}
+	}
+}
+
+//
+static btDbvtNode*				removeleaf(	btDbvt* pdbvt,
+										   btDbvtNode* leaf)
+{
+	if(leaf==pdbvt->m_root)
+	{
+		pdbvt->m_root=0;
+		return(0);
+	}
+	else
+	{
+		btDbvtNode*	parent=leaf->parent;
+		btDbvtNode*	prev=parent->parent;
+		btDbvtNode*	sibling=parent->childs[1-indexof(leaf)];			
+		if(prev)
+		{
+			prev->childs[indexof(parent)]=sibling;
+			sibling->parent=prev;
+			deletenode(pdbvt,parent);
+			while(prev)
+			{
+				const btDbvtVolume	pb=prev->volume;
+				Merge(prev->childs[0]->volume,prev->childs[1]->volume,prev->volume);
+				if(NotEqual(pb,prev->volume))
+				{
+					prev=prev->parent;
+				} else break;
+			}
+			return(prev?prev:pdbvt->m_root);
+		}
+		else
+		{								
+			pdbvt->m_root=sibling;
+			sibling->parent=0;
+			deletenode(pdbvt,parent);
+			return(pdbvt->m_root);
+		}			
+	}
+}
+
+//
+static void						fetchleaves(btDbvt* pdbvt,
+											btDbvtNode* root,
+											tNodeArray& leaves,
+											int depth=-1)
+{
+	if(root->isinternal()&&depth)
+	{
+		fetchleaves(pdbvt,root->childs[0],leaves,depth-1);
+		fetchleaves(pdbvt,root->childs[1],leaves,depth-1);
+		deletenode(pdbvt,root);
+	}
+	else
+	{
+		leaves.push_back(root);
+	}
+}
+
+//
+static void						split(	const tNodeArray& leaves,
+									  tNodeArray& left,
+									  tNodeArray& right,
+									  const btVector3& org,
+									  const btVector3& axis)
+{
+	left.resize(0);
+	right.resize(0);
+	for(int i=0,ni=leaves.size();i<ni;++i)
+	{
+		if(btDot(axis,leaves[i]->volume.Center()-org)<0)
+			left.push_back(leaves[i]);
+		else
+			right.push_back(leaves[i]);
+	}
+}
+
+//
+static btDbvtVolume				bounds(	const tNodeArray& leaves)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+	ATTRIBUTE_ALIGNED16(char	locals[sizeof(btDbvtVolume)]);
+	btDbvtVolume&	volume=*(btDbvtVolume*)locals;
+	volume=leaves[0]->volume;
+#else
+	btDbvtVolume volume=leaves[0]->volume;
+#endif
+	for(int i=1,ni=leaves.size();i<ni;++i)
+	{
+		Merge(volume,leaves[i]->volume,volume);
+	}
+	return(volume);
+}
+
+//
+static void						bottomup(	btDbvt* pdbvt,
+										 tNodeArray& leaves)
+{
+	while(leaves.size()>1)
+	{
+		btScalar	minsize=SIMD_INFINITY;
+		int			minidx[2]={-1,-1};
+		for(int i=0;i<leaves.size();++i)
+		{
+			for(int j=i+1;j<leaves.size();++j)
+			{
+				const btScalar	sz=size(merge(leaves[i]->volume,leaves[j]->volume));
+				if(sz<minsize)
+				{
+					minsize		=	sz;
+					minidx[0]	=	i;
+					minidx[1]	=	j;
+				}
+			}
+		}
+		btDbvtNode*	n[]	=	{leaves[minidx[0]],leaves[minidx[1]]};
+		btDbvtNode*	p	=	createnode(pdbvt,0,n[0]->volume,n[1]->volume,0);
+		p->childs[0]		=	n[0];
+		p->childs[1]		=	n[1];
+		n[0]->parent		=	p;
+		n[1]->parent		=	p;
+		leaves[minidx[0]]	=	p;
+		leaves.swap(minidx[1],leaves.size()-1);
+		leaves.pop_back();
+	}
+}
+
+//
+static btDbvtNode*			topdown(btDbvt* pdbvt,
+									tNodeArray& leaves,
+									int bu_treshold)
+{
+	static const btVector3	axis[]={btVector3(1,0,0),
+		btVector3(0,1,0),
+		btVector3(0,0,1)};
+	if(leaves.size()>1)
+	{
+		if(leaves.size()>bu_treshold)
+		{
+			const btDbvtVolume	vol=bounds(leaves);
+			const btVector3			org=vol.Center();
+			tNodeArray				sets[2];
+			int						bestaxis=-1;
+			int						bestmidp=leaves.size();
+			int						splitcount[3][2]={{0,0},{0,0},{0,0}};
+			int i;
+			for( i=0;i<leaves.size();++i)
+			{
+				const btVector3	x=leaves[i]->volume.Center()-org;
+				for(int j=0;j<3;++j)
+				{
+					++splitcount[j][btDot(x,axis[j])>0?1:0];
+				}
+			}
+			for( i=0;i<3;++i)
+			{
+				if((splitcount[i][0]>0)&&(splitcount[i][1]>0))
+				{
+					const int	midp=(int)btFabs(btScalar(splitcount[i][0]-splitcount[i][1]));
+					if(midp<bestmidp)
+					{
+						bestaxis=i;
+						bestmidp=midp;
+					}
+				}
+			}
+			if(bestaxis>=0)
+			{
+				sets[0].reserve(splitcount[bestaxis][0]);
+				sets[1].reserve(splitcount[bestaxis][1]);
+				split(leaves,sets[0],sets[1],org,axis[bestaxis]);
+			}
+			else
+			{
+				sets[0].reserve(leaves.size()/2+1);
+				sets[1].reserve(leaves.size()/2);
+				for(int i=0,ni=leaves.size();i<ni;++i)
+				{
+					sets[i&1].push_back(leaves[i]);
+				}
+			}
+			btDbvtNode*	node=createnode(pdbvt,0,vol,0);
+			node->childs[0]=topdown(pdbvt,sets[0],bu_treshold);
+			node->childs[1]=topdown(pdbvt,sets[1],bu_treshold);
+			node->childs[0]->parent=node;
+			node->childs[1]->parent=node;
+			return(node);
+		}
+		else
+		{
+			bottomup(pdbvt,leaves);
+			return(leaves[0]);
+		}
+	}
+	return(leaves[0]);
+}
+
+//
+static DBVT_INLINE btDbvtNode*	sort(btDbvtNode* n,btDbvtNode*& r)
+{
+	btDbvtNode*	p=n->parent;
+	btAssert(n->isinternal());
+	if(p>n)
+	{
+		const int		i=indexof(n);
+		const int		j=1-i;
+		btDbvtNode*	s=p->childs[j];
+		btDbvtNode*	q=p->parent;
+		btAssert(n==p->childs[i]);
+		if(q) q->childs[indexof(p)]=n; else r=n;
+		s->parent=n;
+		p->parent=n;
+		n->parent=q;
+		p->childs[0]=n->childs[0];
+		p->childs[1]=n->childs[1];
+		n->childs[0]->parent=p;
+		n->childs[1]->parent=p;
+		n->childs[i]=p;
+		n->childs[j]=s;
+		btSwap(p->volume,n->volume);
+		return(p);
+	}
+	return(n);
+}
+
+#if 0
+static DBVT_INLINE btDbvtNode*	walkup(btDbvtNode* n,int count)
+{
+	while(n&&(count--)) n=n->parent;
+	return(n);
+}
+#endif
+
+//
+// Api
+//
+
+//
+btDbvt::btDbvt()
+{
+	m_root		=	0;
+	m_free		=	0;
+	m_lkhd		=	-1;
+	m_leaves	=	0;
+	m_opath		=	0;
+}
+
+//
+btDbvt::~btDbvt()
+{
+	clear();
+}
+
+//
+void			btDbvt::clear()
+{
+	if(m_root)	
+		recursedeletenode(this,m_root);
+	btAlignedFree(m_free);
+	m_free=0;
+	m_lkhd		=	-1;
+	m_stkStack.clear();
+	m_opath		=	0;
+	
+}
+
+//
+void			btDbvt::optimizeBottomUp()
+{
+	if(m_root)
+	{
+		tNodeArray leaves;
+		leaves.reserve(m_leaves);
+		fetchleaves(this,m_root,leaves);
+		bottomup(this,leaves);
+		m_root=leaves[0];
+	}
+}
+
+//
+void			btDbvt::optimizeTopDown(int bu_treshold)
+{
+	if(m_root)
+	{
+		tNodeArray	leaves;
+		leaves.reserve(m_leaves);
+		fetchleaves(this,m_root,leaves);
+		m_root=topdown(this,leaves,bu_treshold);
+	}
+}
+
+//
+void			btDbvt::optimizeIncremental(int passes)
+{
+	if(passes<0) passes=m_leaves;
+	if(m_root&&(passes>0))
+	{
+		do	{
+			btDbvtNode*		node=m_root;
+			unsigned	bit=0;
+			while(node->isinternal())
+			{
+				node=sort(node,m_root)->childs[(m_opath>>bit)&1];
+				bit=(bit+1)&(sizeof(unsigned)*8-1);
+			}
+			update(node);
+			++m_opath;
+		} while(--passes);
+	}
+}
+
+//
+btDbvtNode*	btDbvt::insert(const btDbvtVolume& volume,void* data)
+{
+	btDbvtNode*	leaf=createnode(this,0,volume,data);
+	insertleaf(this,m_root,leaf);
+	++m_leaves;
+	return(leaf);
+}
+
+//
+void			btDbvt::update(btDbvtNode* leaf,int lookahead)
+{
+	btDbvtNode*	root=removeleaf(this,leaf);
+	if(root)
+	{
+		if(lookahead>=0)
+		{
+			for(int i=0;(i<lookahead)&&root->parent;++i)
+			{
+				root=root->parent;
+			}
+		} else root=m_root;
+	}
+	insertleaf(this,root,leaf);
+}
+
+//
+void			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume)
+{
+	btDbvtNode*	root=removeleaf(this,leaf);
+	if(root)
+	{
+		if(m_lkhd>=0)
+		{
+			for(int i=0;(i<m_lkhd)&&root->parent;++i)
+			{
+				root=root->parent;
+			}
+		} else root=m_root;
+	}
+	leaf->volume=volume;
+	insertleaf(this,root,leaf);
+}
+
+//
+bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin)
+{
+	if(leaf->volume.Contain(volume)) return(false);
+	volume.Expand(btVector3(margin,margin,margin));
+	volume.SignedExpand(velocity);
+	update(leaf,volume);
+	return(true);
+}
+
+//
+bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity)
+{
+	if(leaf->volume.Contain(volume)) return(false);
+	volume.SignedExpand(velocity);
+	update(leaf,volume);
+	return(true);
+}
+
+//
+bool			btDbvt::update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin)
+{
+	if(leaf->volume.Contain(volume)) return(false);
+	volume.Expand(btVector3(margin,margin,margin));
+	update(leaf,volume);
+	return(true);
+}
+
+//
+void			btDbvt::remove(btDbvtNode* leaf)
+{
+	removeleaf(this,leaf);
+	deletenode(this,leaf);
+	--m_leaves;
+}
+
+//
+void			btDbvt::write(IWriter* iwriter) const
+{
+	btDbvtNodeEnumerator	nodes;
+	nodes.nodes.reserve(m_leaves*2);
+	enumNodes(m_root,nodes);
+	iwriter->Prepare(m_root,nodes.nodes.size());
+	for(int i=0;i<nodes.nodes.size();++i)
+	{
+		const btDbvtNode* n=nodes.nodes[i];
+		int			p=-1;
+		if(n->parent) p=nodes.nodes.findLinearSearch(n->parent);
+		if(n->isinternal())
+		{
+			const int	c0=nodes.nodes.findLinearSearch(n->childs[0]);
+			const int	c1=nodes.nodes.findLinearSearch(n->childs[1]);
+			iwriter->WriteNode(n,i,p,c0,c1);
+		}
+		else
+		{
+			iwriter->WriteLeaf(n,i,p);
+		}	
+	}
+}
+
+//
+void			btDbvt::clone(btDbvt& dest,IClone* iclone) const
+{
+	dest.clear();
+	if(m_root!=0)
+	{	
+		btAlignedObjectArray<sStkCLN>	stack;
+		stack.reserve(m_leaves);
+		stack.push_back(sStkCLN(m_root,0));
+		do	{
+			const int		i=stack.size()-1;
+			const sStkCLN	e=stack[i];
+			btDbvtNode*			n=createnode(&dest,e.parent,e.node->volume,e.node->data);
+			stack.pop_back();
+			if(e.parent!=0)
+				e.parent->childs[i&1]=n;
+			else
+				dest.m_root=n;
+			if(e.node->isinternal())
+			{
+				stack.push_back(sStkCLN(e.node->childs[0],n));
+				stack.push_back(sStkCLN(e.node->childs[1],n));
+			}
+			else
+			{
+				iclone->CloneLeaf(n);
+			}
+		} while(stack.size()>0);
+	}
+}
+
+//
+int				btDbvt::maxdepth(const btDbvtNode* node)
+{
+	int	depth=0;
+	if(node) getmaxdepth(node,1,depth);
+	return(depth);
+}
+
+//
+int				btDbvt::countLeaves(const btDbvtNode* node)
+{
+	if(node->isinternal())
+		return(countLeaves(node->childs[0])+countLeaves(node->childs[1]));
+	else
+		return(1);
+}
+
+//
+void			btDbvt::extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves)
+{
+	if(node->isinternal())
+	{
+		extractLeaves(node->childs[0],leaves);
+		extractLeaves(node->childs[1],leaves);
+	}
+	else
+	{
+		leaves.push_back(node);
+	}	
+}
+
+//
+#if DBVT_ENABLE_BENCHMARK
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "LinearMath/btQuickProf.h"
+
+/*
+q6600,2.4ghz
+
+/Ox /Ob2 /Oi /Ot /I "." /I "..\.." /I "..\..\src" /D "NDEBUG" /D "_LIB" /D "_WINDOWS" /D "_CRT_SECURE_NO_DEPRECATE" /D "_CRT_NONSTDC_NO_DEPRECATE" /D "WIN32"
+/GF /FD /MT /GS- /Gy /arch:SSE2 /Zc:wchar_t- /Fp"..\..\out\release8\build\libbulletcollision\libbulletcollision.pch"
+/Fo"..\..\out\release8\build\libbulletcollision\\"
+/Fd"..\..\out\release8\build\libbulletcollision\bulletcollision.pdb"
+/W3 /nologo /c /Wp64 /Zi /errorReport:prompt
+
+Benchmarking dbvt...
+World scale: 100.000000
+Extents base: 1.000000
+Extents range: 4.000000
+Leaves: 8192
+sizeof(btDbvtVolume): 32 bytes
+sizeof(btDbvtNode):   44 bytes
+[1] btDbvtVolume intersections: 3499 ms (-1%)
+[2] btDbvtVolume merges: 1934 ms (0%)
+[3] btDbvt::collideTT: 5485 ms (-21%)
+[4] btDbvt::collideTT self: 2814 ms (-20%)
+[5] btDbvt::collideTT xform: 7379 ms (-1%)
+[6] btDbvt::collideTT xform,self: 7270 ms (-2%)
+[7] btDbvt::rayTest: 6314 ms (0%),(332143 r/s)
+[8] insert/remove: 2093 ms (0%),(1001983 ir/s)
+[9] updates (teleport): 1879 ms (-3%),(1116100 u/s)
+[10] updates (jitter): 1244 ms (-4%),(1685813 u/s)
+[11] optimize (incremental): 2514 ms (0%),(1668000 o/s)
+[12] btDbvtVolume notequal: 3659 ms (0%)
+[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s)
+[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s)
+[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s)
+[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s)
+[17] btDbvtVolume select: 3419 ms (0%)
+*/
+
+struct btDbvtBenchmark
+{
+	struct NilPolicy : btDbvt::ICollide
+	{
+		NilPolicy() : m_pcount(0),m_depth(-SIMD_INFINITY),m_checksort(true)		{}
+		void	Process(const btDbvtNode*,const btDbvtNode*)				{ ++m_pcount; }
+		void	Process(const btDbvtNode*)									{ ++m_pcount; }
+		void	Process(const btDbvtNode*,btScalar depth)
+		{
+			++m_pcount;
+			if(m_checksort)
+			{ if(depth>=m_depth) m_depth=depth; else printf("wrong depth: %f (should be >= %f)\r\n",depth,m_depth); }
+		}
+		int			m_pcount;
+		btScalar	m_depth;
+		bool		m_checksort;
+	};
+	struct P14 : btDbvt::ICollide
+	{
+		struct Node
+		{
+			const btDbvtNode*	leaf;
+			btScalar			depth;
+		};
+		void Process(const btDbvtNode* leaf,btScalar depth)
+		{
+			Node	n;
+			n.leaf	=	leaf;
+			n.depth	=	depth;
+		}
+		static int sortfnc(const Node& a,const Node& b)
+		{
+			if(a.depth<b.depth) return(+1);
+			if(a.depth>b.depth) return(-1);
+			return(0);
+		}
+		btAlignedObjectArray<Node>		m_nodes;
+	};
+	struct P15 : btDbvt::ICollide
+	{
+		struct Node
+		{
+			const btDbvtNode*	leaf;
+			btScalar			depth;
+		};
+		void Process(const btDbvtNode* leaf)
+		{
+			Node	n;
+			n.leaf	=	leaf;
+			n.depth	=	dot(leaf->volume.Center(),m_axis);
+		}
+		static int sortfnc(const Node& a,const Node& b)
+		{
+			if(a.depth<b.depth) return(+1);
+			if(a.depth>b.depth) return(-1);
+			return(0);
+		}
+		btAlignedObjectArray<Node>		m_nodes;
+		btVector3						m_axis;
+	};
+	static btScalar			RandUnit()
+	{
+		return(rand()/(btScalar)RAND_MAX);
+	}
+	static btVector3		RandVector3()
+	{
+		return(btVector3(RandUnit(),RandUnit(),RandUnit()));
+	}
+	static btVector3		RandVector3(btScalar cs)
+	{
+		return(RandVector3()*cs-btVector3(cs,cs,cs)/2);
+	}
+	static btDbvtVolume	RandVolume(btScalar cs,btScalar eb,btScalar es)
+	{
+		return(btDbvtVolume::FromCE(RandVector3(cs),btVector3(eb,eb,eb)+RandVector3()*es));
+	}
+	static btTransform		RandTransform(btScalar cs)
+	{
+		btTransform	t;
+		t.setOrigin(RandVector3(cs));
+		t.setRotation(btQuaternion(RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2,RandUnit()*SIMD_PI*2).normalized());
+		return(t);
+	}
+	static void				RandTree(btScalar cs,btScalar eb,btScalar es,int leaves,btDbvt& dbvt)
+	{
+		dbvt.clear();
+		for(int i=0;i<leaves;++i)
+		{
+			dbvt.insert(RandVolume(cs,eb,es),0);
+		}
+	}
+};
+
+void			btDbvt::benchmark()
+{
+	static const btScalar	cfgVolumeCenterScale		=	100;
+	static const btScalar	cfgVolumeExentsBase			=	1;
+	static const btScalar	cfgVolumeExentsScale		=	4;
+	static const int		cfgLeaves					=	8192;
+	static const bool		cfgEnable					=	true;
+
+	//[1] btDbvtVolume intersections
+	bool					cfgBenchmark1_Enable		=	cfgEnable;
+	static const int		cfgBenchmark1_Iterations	=	8;
+	static const int		cfgBenchmark1_Reference		=	3499;
+	//[2] btDbvtVolume merges
+	bool					cfgBenchmark2_Enable		=	cfgEnable;
+	static const int		cfgBenchmark2_Iterations	=	4;
+	static const int		cfgBenchmark2_Reference		=	1945;
+	//[3] btDbvt::collideTT
+	bool					cfgBenchmark3_Enable		=	cfgEnable;
+	static const int		cfgBenchmark3_Iterations	=	512;
+	static const int		cfgBenchmark3_Reference		=	5485;
+	//[4] btDbvt::collideTT self
+	bool					cfgBenchmark4_Enable		=	cfgEnable;
+	static const int		cfgBenchmark4_Iterations	=	512;
+	static const int		cfgBenchmark4_Reference		=	2814;
+	//[5] btDbvt::collideTT xform
+	bool					cfgBenchmark5_Enable		=	cfgEnable;
+	static const int		cfgBenchmark5_Iterations	=	512;
+	static const btScalar	cfgBenchmark5_OffsetScale	=	2;
+	static const int		cfgBenchmark5_Reference		=	7379;
+	//[6] btDbvt::collideTT xform,self
+	bool					cfgBenchmark6_Enable		=	cfgEnable;
+	static const int		cfgBenchmark6_Iterations	=	512;
+	static const btScalar	cfgBenchmark6_OffsetScale	=	2;
+	static const int		cfgBenchmark6_Reference		=	7270;
+	//[7] btDbvt::rayTest
+	bool					cfgBenchmark7_Enable		=	cfgEnable;
+	static const int		cfgBenchmark7_Passes		=	32;
+	static const int		cfgBenchmark7_Iterations	=	65536;
+	static const int		cfgBenchmark7_Reference		=	6307;
+	//[8] insert/remove
+	bool					cfgBenchmark8_Enable		=	cfgEnable;
+	static const int		cfgBenchmark8_Passes		=	32;
+	static const int		cfgBenchmark8_Iterations	=	65536;
+	static const int		cfgBenchmark8_Reference		=	2105;
+	//[9] updates (teleport)
+	bool					cfgBenchmark9_Enable		=	cfgEnable;
+	static const int		cfgBenchmark9_Passes		=	32;
+	static const int		cfgBenchmark9_Iterations	=	65536;
+	static const int		cfgBenchmark9_Reference		=	1879;
+	//[10] updates (jitter)
+	bool					cfgBenchmark10_Enable		=	cfgEnable;
+	static const btScalar	cfgBenchmark10_Scale		=	cfgVolumeCenterScale/10000;
+	static const int		cfgBenchmark10_Passes		=	32;
+	static const int		cfgBenchmark10_Iterations	=	65536;
+	static const int		cfgBenchmark10_Reference	=	1244;
+	//[11] optimize (incremental)
+	bool					cfgBenchmark11_Enable		=	cfgEnable;
+	static const int		cfgBenchmark11_Passes		=	64;
+	static const int		cfgBenchmark11_Iterations	=	65536;
+	static const int		cfgBenchmark11_Reference	=	2510;
+	//[12] btDbvtVolume notequal
+	bool					cfgBenchmark12_Enable		=	cfgEnable;
+	static const int		cfgBenchmark12_Iterations	=	32;
+	static const int		cfgBenchmark12_Reference	=	3677;
+	//[13] culling(OCL+fullsort)
+	bool					cfgBenchmark13_Enable		=	cfgEnable;
+	static const int		cfgBenchmark13_Iterations	=	1024;
+	static const int		cfgBenchmark13_Reference	=	2231;
+	//[14] culling(OCL+qsort)
+	bool					cfgBenchmark14_Enable		=	cfgEnable;
+	static const int		cfgBenchmark14_Iterations	=	8192;
+	static const int		cfgBenchmark14_Reference	=	3500;
+	//[15] culling(KDOP+qsort)
+	bool					cfgBenchmark15_Enable		=	cfgEnable;
+	static const int		cfgBenchmark15_Iterations	=	8192;
+	static const int		cfgBenchmark15_Reference	=	1151;
+	//[16] insert/remove batch
+	bool					cfgBenchmark16_Enable		=	cfgEnable;
+	static const int		cfgBenchmark16_BatchCount	=	256;
+	static const int		cfgBenchmark16_Passes		=	16384;
+	static const int		cfgBenchmark16_Reference	=	5138;
+	//[17] select
+	bool					cfgBenchmark17_Enable		=	cfgEnable;
+	static const int		cfgBenchmark17_Iterations	=	4;
+	static const int		cfgBenchmark17_Reference	=	3390;
+
+	btClock					wallclock;
+	printf("Benchmarking dbvt...\r\n");
+	printf("\tWorld scale: %f\r\n",cfgVolumeCenterScale);
+	printf("\tExtents base: %f\r\n",cfgVolumeExentsBase);
+	printf("\tExtents range: %f\r\n",cfgVolumeExentsScale);
+	printf("\tLeaves: %u\r\n",cfgLeaves);
+	printf("\tsizeof(btDbvtVolume): %u bytes\r\n",sizeof(btDbvtVolume));
+	printf("\tsizeof(btDbvtNode):   %u bytes\r\n",sizeof(btDbvtNode));
+	if(cfgBenchmark1_Enable)
+	{// Benchmark 1	
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<bool>			results;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		printf("[1] btDbvtVolume intersections: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark1_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					results[k]=Intersect(volumes[j],volumes[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark1_Reference)*100/time);
+	}
+	if(cfgBenchmark2_Enable)
+	{// Benchmark 2	
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<btDbvtVolume>	results;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		printf("[2] btDbvtVolume merges: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark2_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					Merge(volumes[j],volumes[k],results[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark2_Reference)*100/time);
+	}
+	if(cfgBenchmark3_Enable)
+	{// Benchmark 3	
+		srand(380843);
+		btDbvt						dbvt[2];
+		btDbvtBenchmark::NilPolicy	policy;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+		dbvt[0].optimizeTopDown();
+		dbvt[1].optimizeTopDown();
+		printf("[3] btDbvt::collideTT: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark3_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,policy);
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark3_Reference)*100/time);
+	}
+	if(cfgBenchmark4_Enable)
+	{// Benchmark 4
+		srand(380843);
+		btDbvt						dbvt;
+		btDbvtBenchmark::NilPolicy	policy;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[4] btDbvt::collideTT self: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark4_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt.m_root,dbvt.m_root,policy);
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark4_Reference)*100/time);
+	}
+	if(cfgBenchmark5_Enable)
+	{// Benchmark 5	
+		srand(380843);
+		btDbvt								dbvt[2];
+		btAlignedObjectArray<btTransform>	transforms;
+		btDbvtBenchmark::NilPolicy			policy;
+		transforms.resize(cfgBenchmark5_Iterations);
+		for(int i=0;i<transforms.size();++i)
+		{
+			transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark5_OffsetScale);
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[0]);
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt[1]);
+		dbvt[0].optimizeTopDown();
+		dbvt[1].optimizeTopDown();
+		printf("[5] btDbvt::collideTT xform: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark5_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt[0].m_root,dbvt[1].m_root,transforms[i],policy);
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark5_Reference)*100/time);
+	}
+	if(cfgBenchmark6_Enable)
+	{// Benchmark 6	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btTransform>	transforms;
+		btDbvtBenchmark::NilPolicy			policy;
+		transforms.resize(cfgBenchmark6_Iterations);
+		for(int i=0;i<transforms.size();++i)
+		{
+			transforms[i]=btDbvtBenchmark::RandTransform(cfgVolumeCenterScale*cfgBenchmark6_OffsetScale);
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[6] btDbvt::collideTT xform,self: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark6_Iterations;++i)
+		{
+			btDbvt::collideTT(dbvt.m_root,dbvt.m_root,transforms[i],policy);		
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark6_Reference)*100/time);
+	}
+	if(cfgBenchmark7_Enable)
+	{// Benchmark 7	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		rayorg;
+		btAlignedObjectArray<btVector3>		raydir;
+		btDbvtBenchmark::NilPolicy			policy;
+		rayorg.resize(cfgBenchmark7_Iterations);
+		raydir.resize(cfgBenchmark7_Iterations);
+		for(int i=0;i<rayorg.size();++i)
+		{
+			rayorg[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+			raydir[i]=btDbvtBenchmark::RandVector3(cfgVolumeCenterScale*2);
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[7] btDbvt::rayTest: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark7_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark7_Iterations;++j)
+			{
+				btDbvt::rayTest(dbvt.m_root,rayorg[j],rayorg[j]+raydir[j],policy);
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		unsigned	rays=cfgBenchmark7_Passes*cfgBenchmark7_Iterations;
+		printf("%u ms (%i%%),(%u r/s)\r\n",time,(time-cfgBenchmark7_Reference)*100/time,(rays*1000)/time);
+	}
+	if(cfgBenchmark8_Enable)
+	{// Benchmark 8	
+		srand(380843);
+		btDbvt								dbvt;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[8] insert/remove: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark8_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark8_Iterations;++j)
+			{
+				dbvt.remove(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	ir=cfgBenchmark8_Passes*cfgBenchmark8_Iterations;
+		printf("%u ms (%i%%),(%u ir/s)\r\n",time,(time-cfgBenchmark8_Reference)*100/time,ir*1000/time);
+	}
+	if(cfgBenchmark9_Enable)
+	{// Benchmark 9	
+		srand(380843);
+		btDbvt										dbvt;
+		btAlignedObjectArray<const btDbvtNode*>	leaves;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		dbvt.extractLeaves(dbvt.m_root,leaves);
+		printf("[9] updates (teleport): ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark9_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark9_Iterations;++j)
+			{
+				dbvt.update(const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]),
+					btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale));
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	up=cfgBenchmark9_Passes*cfgBenchmark9_Iterations;
+		printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark9_Reference)*100/time,up*1000/time);
+	}
+	if(cfgBenchmark10_Enable)
+	{// Benchmark 10	
+		srand(380843);
+		btDbvt										dbvt;
+		btAlignedObjectArray<const btDbvtNode*>	leaves;
+		btAlignedObjectArray<btVector3>				vectors;
+		vectors.resize(cfgBenchmark10_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1))*cfgBenchmark10_Scale;
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		dbvt.extractLeaves(dbvt.m_root,leaves);
+		printf("[10] updates (jitter): ");
+		wallclock.reset();
+
+		for(int i=0;i<cfgBenchmark10_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark10_Iterations;++j)
+			{			
+				const btVector3&	d=vectors[j];
+				btDbvtNode*		l=const_cast<btDbvtNode*>(leaves[rand()%cfgLeaves]);
+				btDbvtVolume		v=btDbvtVolume::FromMM(l->volume.Mins()+d,l->volume.Maxs()+d);
+				dbvt.update(l,v);
+			}
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	up=cfgBenchmark10_Passes*cfgBenchmark10_Iterations;
+		printf("%u ms (%i%%),(%u u/s)\r\n",time,(time-cfgBenchmark10_Reference)*100/time,up*1000/time);
+	}
+	if(cfgBenchmark11_Enable)
+	{// Benchmark 11	
+		srand(380843);
+		btDbvt										dbvt;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[11] optimize (incremental): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark11_Passes;++i)
+		{
+			dbvt.optimizeIncremental(cfgBenchmark11_Iterations);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	op=cfgBenchmark11_Passes*cfgBenchmark11_Iterations;
+		printf("%u ms (%i%%),(%u o/s)\r\n",time,(time-cfgBenchmark11_Reference)*100/time,op/time*1000);
+	}
+	if(cfgBenchmark12_Enable)
+	{// Benchmark 12	
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<bool>				results;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		printf("[12] btDbvtVolume notequal: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark12_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					results[k]=NotEqual(volumes[j],volumes[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark12_Reference)*100/time);
+	}
+	if(cfgBenchmark13_Enable)
+	{// Benchmark 13	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		vectors;
+		btDbvtBenchmark::NilPolicy			policy;
+		vectors.resize(cfgBenchmark13_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		printf("[13] culling(OCL+fullsort): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark13_Iterations;++i)
+		{
+			static const btScalar	offset=0;
+			policy.m_depth=-SIMD_INFINITY;
+			dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	t=cfgBenchmark13_Iterations;
+		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark13_Reference)*100/time,(t*1000)/time);
+	}
+	if(cfgBenchmark14_Enable)
+	{// Benchmark 14	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		vectors;
+		btDbvtBenchmark::P14				policy;
+		vectors.resize(cfgBenchmark14_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		policy.m_nodes.reserve(cfgLeaves);
+		printf("[14] culling(OCL+qsort): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark14_Iterations;++i)
+		{
+			static const btScalar	offset=0;
+			policy.m_nodes.resize(0);
+			dbvt.collideOCL(dbvt.m_root,&vectors[i],&offset,vectors[i],1,policy,false);
+			policy.m_nodes.quickSort(btDbvtBenchmark::P14::sortfnc);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	t=cfgBenchmark14_Iterations;
+		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark14_Reference)*100/time,(t*1000)/time);
+	}
+	if(cfgBenchmark15_Enable)
+	{// Benchmark 15	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btVector3>		vectors;
+		btDbvtBenchmark::P15				policy;
+		vectors.resize(cfgBenchmark15_Iterations);
+		for(int i=0;i<vectors.size();++i)
+		{
+			vectors[i]=(btDbvtBenchmark::RandVector3()*2-btVector3(1,1,1)).normalized();
+		}
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		policy.m_nodes.reserve(cfgLeaves);
+		printf("[15] culling(KDOP+qsort): ");
+		wallclock.reset();	
+		for(int i=0;i<cfgBenchmark15_Iterations;++i)
+		{
+			static const btScalar	offset=0;
+			policy.m_nodes.resize(0);
+			policy.m_axis=vectors[i];
+			dbvt.collideKDOP(dbvt.m_root,&vectors[i],&offset,1,policy);
+			policy.m_nodes.quickSort(btDbvtBenchmark::P15::sortfnc);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	t=cfgBenchmark15_Iterations;
+		printf("%u ms (%i%%),(%u t/s)\r\n",time,(time-cfgBenchmark15_Reference)*100/time,(t*1000)/time);
+	}
+	if(cfgBenchmark16_Enable)
+	{// Benchmark 16	
+		srand(380843);
+		btDbvt								dbvt;
+		btAlignedObjectArray<btDbvtNode*>	batch;
+		btDbvtBenchmark::RandTree(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale,cfgLeaves,dbvt);
+		dbvt.optimizeTopDown();
+		batch.reserve(cfgBenchmark16_BatchCount);
+		printf("[16] insert/remove batch(%u): ",cfgBenchmark16_BatchCount);
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark16_Passes;++i)
+		{
+			for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+			{
+				batch.push_back(dbvt.insert(btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale),0));
+			}
+			for(int j=0;j<cfgBenchmark16_BatchCount;++j)
+			{
+				dbvt.remove(batch[j]);
+			}
+			batch.resize(0);
+		}
+		const int	time=(int)wallclock.getTimeMilliseconds();
+		const int	ir=cfgBenchmark16_Passes*cfgBenchmark16_BatchCount;
+		printf("%u ms (%i%%),(%u bir/s)\r\n",time,(time-cfgBenchmark16_Reference)*100/time,int(ir*1000.0/time));
+	}
+	if(cfgBenchmark17_Enable)
+	{// Benchmark 17
+		srand(380843);
+		btAlignedObjectArray<btDbvtVolume>	volumes;
+		btAlignedObjectArray<int>			results;
+		btAlignedObjectArray<int>			indices;
+		volumes.resize(cfgLeaves);
+		results.resize(cfgLeaves);
+		indices.resize(cfgLeaves);
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			indices[i]=i;
+			volumes[i]=btDbvtBenchmark::RandVolume(cfgVolumeCenterScale,cfgVolumeExentsBase,cfgVolumeExentsScale);
+		}
+		for(int i=0;i<cfgLeaves;++i)
+		{
+			btSwap(indices[i],indices[rand()%cfgLeaves]);
+		}
+		printf("[17] btDbvtVolume select: ");
+		wallclock.reset();
+		for(int i=0;i<cfgBenchmark17_Iterations;++i)
+		{
+			for(int j=0;j<cfgLeaves;++j)
+			{
+				for(int k=0;k<cfgLeaves;++k)
+				{
+					const int idx=indices[k];
+					results[idx]=Select(volumes[idx],volumes[j],volumes[k]);
+				}
+			}
+		}
+		const int time=(int)wallclock.getTimeMilliseconds();
+		printf("%u ms (%i%%)\r\n",time,(time-cfgBenchmark17_Reference)*100/time);
+	}
+	printf("\r\n\r\n");
+}
+#endif
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
new file mode 100644
index 0000000..2bb8ef5
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvt.h
@@ -0,0 +1,1256 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+///btDbvt implementation by Nathanael Presson
+
+#ifndef BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+#define BT_DYNAMIC_BOUNDING_VOLUME_TREE_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAabbUtil2.h"
+
+//
+// Compile time configuration
+//
+
+
+// Implementation profiles
+#define DBVT_IMPL_GENERIC		0	// Generic implementation	
+#define DBVT_IMPL_SSE			1	// SSE
+
+// Template implementation of ICollide
+#ifdef _WIN32
+#if (defined (_MSC_VER) && _MSC_VER >= 1400)
+#define	DBVT_USE_TEMPLATE		1
+#else
+#define	DBVT_USE_TEMPLATE		0
+#endif
+#else
+#define	DBVT_USE_TEMPLATE		0
+#endif
+
+// Use only intrinsics instead of inline asm
+#define DBVT_USE_INTRINSIC_SSE	1
+
+// Using memmov for collideOCL
+#define DBVT_USE_MEMMOVE		1
+
+// Enable benchmarking code
+#define	DBVT_ENABLE_BENCHMARK	0
+
+// Inlining
+#define DBVT_INLINE				SIMD_FORCE_INLINE
+
+// Specific methods implementation
+
+//SSE gives errors on a MSVC 7.1
+#if defined (BT_USE_SSE) && defined (_WIN32)
+#define DBVT_SELECT_IMPL		DBVT_IMPL_SSE
+#define DBVT_MERGE_IMPL			DBVT_IMPL_SSE
+#define DBVT_INT0_IMPL			DBVT_IMPL_SSE
+#else
+#define DBVT_SELECT_IMPL		DBVT_IMPL_GENERIC
+#define DBVT_MERGE_IMPL			DBVT_IMPL_GENERIC
+#define DBVT_INT0_IMPL			DBVT_IMPL_GENERIC
+#endif
+
+#if	(DBVT_SELECT_IMPL==DBVT_IMPL_SSE)||	\
+	(DBVT_MERGE_IMPL==DBVT_IMPL_SSE)||	\
+	(DBVT_INT0_IMPL==DBVT_IMPL_SSE)
+#include <emmintrin.h>
+#endif
+
+//
+// Auto config and checks
+//
+
+#if DBVT_USE_TEMPLATE
+#define	DBVT_VIRTUAL
+#define DBVT_VIRTUAL_DTOR(a)
+#define DBVT_PREFIX					template <typename T>
+#define DBVT_IPOLICY				T& policy
+#define DBVT_CHECKTYPE				static const ICollide&	typechecker=*(T*)1;(void)typechecker;
+#else
+#define	DBVT_VIRTUAL_DTOR(a)		virtual ~a() {}
+#define DBVT_VIRTUAL				virtual
+#define DBVT_PREFIX
+#define DBVT_IPOLICY				ICollide& policy
+#define DBVT_CHECKTYPE
+#endif
+
+#if DBVT_USE_MEMMOVE
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+#endif
+
+#ifndef DBVT_USE_TEMPLATE
+#error "DBVT_USE_TEMPLATE undefined"
+#endif
+
+#ifndef DBVT_USE_MEMMOVE
+#error "DBVT_USE_MEMMOVE undefined"
+#endif
+
+#ifndef DBVT_ENABLE_BENCHMARK
+#error "DBVT_ENABLE_BENCHMARK undefined"
+#endif
+
+#ifndef DBVT_SELECT_IMPL
+#error "DBVT_SELECT_IMPL undefined"
+#endif
+
+#ifndef DBVT_MERGE_IMPL
+#error "DBVT_MERGE_IMPL undefined"
+#endif
+
+#ifndef DBVT_INT0_IMPL
+#error "DBVT_INT0_IMPL undefined"
+#endif
+
+//
+// Defaults volumes
+//
+
+/* btDbvtAabbMm			*/ 
+struct	btDbvtAabbMm
+{
+	DBVT_INLINE btVector3			Center() const	{ return((mi+mx)/2); }
+	DBVT_INLINE btVector3			Lengths() const	{ return(mx-mi); }
+	DBVT_INLINE btVector3			Extents() const	{ return((mx-mi)/2); }
+	DBVT_INLINE const btVector3&	Mins() const	{ return(mi); }
+	DBVT_INLINE const btVector3&	Maxs() const	{ return(mx); }
+	static inline btDbvtAabbMm		FromCE(const btVector3& c,const btVector3& e);
+	static inline btDbvtAabbMm		FromCR(const btVector3& c,btScalar r);
+	static inline btDbvtAabbMm		FromMM(const btVector3& mi,const btVector3& mx);
+	static inline btDbvtAabbMm		FromPoints(const btVector3* pts,int n);
+	static inline btDbvtAabbMm		FromPoints(const btVector3** ppts,int n);
+	DBVT_INLINE void				Expand(const btVector3& e);
+	DBVT_INLINE void				SignedExpand(const btVector3& e);
+	DBVT_INLINE bool				Contain(const btDbvtAabbMm& a) const;
+	DBVT_INLINE int					Classify(const btVector3& n,btScalar o,int s) const;
+	DBVT_INLINE btScalar			ProjectMinimum(const btVector3& v,unsigned signs) const;
+	DBVT_INLINE friend bool			Intersect(	const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+	
+	DBVT_INLINE friend bool			Intersect(	const btDbvtAabbMm& a,
+		const btVector3& b);
+
+	DBVT_INLINE friend btScalar		Proximity(	const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+	DBVT_INLINE friend int			Select(		const btDbvtAabbMm& o,
+		const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+	DBVT_INLINE friend void			Merge(		const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b,
+		btDbvtAabbMm& r);
+	DBVT_INLINE friend bool			NotEqual(	const btDbvtAabbMm& a,
+		const btDbvtAabbMm& b);
+private:
+	DBVT_INLINE void				AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const;
+private:
+	btVector3	mi,mx;
+};
+
+// Types	
+typedef	btDbvtAabbMm	btDbvtVolume;
+
+/* btDbvtNode				*/ 
+struct	btDbvtNode
+{
+	btDbvtVolume	volume;
+	btDbvtNode*		parent;
+	DBVT_INLINE bool	isleaf() const		{ return(childs[1]==0); }
+	DBVT_INLINE bool	isinternal() const	{ return(!isleaf()); }
+	union
+	{
+		btDbvtNode*	childs[2];
+		void*	data;
+		int		dataAsInt;
+	};
+};
+
+///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree).
+///This btDbvt is used for soft body collision detection and for the btDbvtBroadphase. It has a fast insert, remove and update of nodes.
+///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure.
+struct	btDbvt
+{
+	/* Stack element	*/ 
+	struct	sStkNN
+	{
+		const btDbvtNode*	a;
+		const btDbvtNode*	b;
+		sStkNN() {}
+		sStkNN(const btDbvtNode* na,const btDbvtNode* nb) : a(na),b(nb) {}
+	};
+	struct	sStkNP
+	{
+		const btDbvtNode*	node;
+		int			mask;
+		sStkNP(const btDbvtNode* n,unsigned m) : node(n),mask(m) {}
+	};
+	struct	sStkNPS
+	{
+		const btDbvtNode*	node;
+		int			mask;
+		btScalar	value;
+		sStkNPS() {}
+		sStkNPS(const btDbvtNode* n,unsigned m,btScalar v) : node(n),mask(m),value(v) {}
+	};
+	struct	sStkCLN
+	{
+		const btDbvtNode*	node;
+		btDbvtNode*		parent;
+		sStkCLN(const btDbvtNode* n,btDbvtNode* p) : node(n),parent(p) {}
+	};
+	// Policies/Interfaces
+
+	/* ICollide	*/ 
+	struct	ICollide
+	{		
+		DBVT_VIRTUAL_DTOR(ICollide)
+			DBVT_VIRTUAL void	Process(const btDbvtNode*,const btDbvtNode*)		{}
+		DBVT_VIRTUAL void	Process(const btDbvtNode*)					{}
+		DBVT_VIRTUAL void	Process(const btDbvtNode* n,btScalar)			{ Process(n); }
+		DBVT_VIRTUAL bool	Descent(const btDbvtNode*)					{ return(true); }
+		DBVT_VIRTUAL bool	AllLeaves(const btDbvtNode*)					{ return(true); }
+	};
+	/* IWriter	*/ 
+	struct	IWriter
+	{
+		virtual ~IWriter() {}
+		virtual void		Prepare(const btDbvtNode* root,int numnodes)=0;
+		virtual void		WriteNode(const btDbvtNode*,int index,int parent,int child0,int child1)=0;
+		virtual void		WriteLeaf(const btDbvtNode*,int index,int parent)=0;
+	};
+	/* IClone	*/ 
+	struct	IClone
+	{
+		virtual ~IClone()	{}
+		virtual void		CloneLeaf(btDbvtNode*) {}
+	};
+
+	// Constants
+	enum	{
+		SIMPLE_STACKSIZE	=	64,
+		DOUBLE_STACKSIZE	=	SIMPLE_STACKSIZE*2
+	};
+
+	// Fields
+	btDbvtNode*		m_root;
+	btDbvtNode*		m_free;
+	int				m_lkhd;
+	int				m_leaves;
+	unsigned		m_opath;
+
+	
+	btAlignedObjectArray<sStkNN>	m_stkStack;
+
+
+	// Methods
+	btDbvt();
+	~btDbvt();
+	void			clear();
+	bool			empty() const { return(0==m_root); }
+	void			optimizeBottomUp();
+	void			optimizeTopDown(int bu_treshold=128);
+	void			optimizeIncremental(int passes);
+	btDbvtNode*		insert(const btDbvtVolume& box,void* data);
+	void			update(btDbvtNode* leaf,int lookahead=-1);
+	void			update(btDbvtNode* leaf,btDbvtVolume& volume);
+	bool			update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity,btScalar margin);
+	bool			update(btDbvtNode* leaf,btDbvtVolume& volume,const btVector3& velocity);
+	bool			update(btDbvtNode* leaf,btDbvtVolume& volume,btScalar margin);	
+	void			remove(btDbvtNode* leaf);
+	void			write(IWriter* iwriter) const;
+	void			clone(btDbvt& dest,IClone* iclone=0) const;
+	static int		maxdepth(const btDbvtNode* node);
+	static int		countLeaves(const btDbvtNode* node);
+	static void		extractLeaves(const btDbvtNode* node,btAlignedObjectArray<const btDbvtNode*>& leaves);
+#if DBVT_ENABLE_BENCHMARK
+	static void		benchmark();
+#else
+	static void		benchmark(){}
+#endif
+	// DBVT_IPOLICY must support ICollide policy/interface
+	DBVT_PREFIX
+		static void		enumNodes(	const btDbvtNode* root,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		static void		enumLeaves(	const btDbvtNode* root,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		void		collideTT(	const btDbvtNode* root0,
+		const btDbvtNode* root1,
+		DBVT_IPOLICY);
+
+	DBVT_PREFIX
+		void		collideTTpersistentStack(	const btDbvtNode* root0,
+		  const btDbvtNode* root1,
+		  DBVT_IPOLICY);
+#if 0
+	DBVT_PREFIX
+		void		collideTT(	const btDbvtNode* root0,
+		const btDbvtNode* root1,
+		const btTransform& xform,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		void		collideTT(	const btDbvtNode* root0,
+		const btTransform& xform0,
+		const btDbvtNode* root1,
+		const btTransform& xform1,
+		DBVT_IPOLICY);
+#endif
+
+	DBVT_PREFIX
+		void		collideTV(	const btDbvtNode* root,
+		const btDbvtVolume& volume,
+		DBVT_IPOLICY);
+	///rayTest is a re-entrant ray test, and can be called in parallel as long as the btAlignedAlloc is thread-safe (uses locking etc)
+	///rayTest is slower than rayTestInternal, because it builds a local stack, using memory allocations, and it recomputes signs/rayDirectionInverses each time
+	DBVT_PREFIX
+		static void		rayTest(	const btDbvtNode* root,
+		const btVector3& rayFrom,
+		const btVector3& rayTo,
+		DBVT_IPOLICY);
+	///rayTestInternal is faster than rayTest, because it uses a persistent stack (to reduce dynamic memory allocations to a minimum) and it uses precomputed signs/rayInverseDirections
+	///rayTestInternal is used by btDbvtBroadphase to accelerate world ray casts
+	DBVT_PREFIX
+		void		rayTestInternal(	const btDbvtNode* root,
+								const btVector3& rayFrom,
+								const btVector3& rayTo,
+								const btVector3& rayDirectionInverse,
+								unsigned int signs[3],
+								btScalar lambda_max,
+								const btVector3& aabbMin,
+								const btVector3& aabbMax,
+								DBVT_IPOLICY) const;
+
+	DBVT_PREFIX
+		static void		collideKDOP(const btDbvtNode* root,
+		const btVector3* normals,
+		const btScalar* offsets,
+		int count,
+		DBVT_IPOLICY);
+	DBVT_PREFIX
+		static void		collideOCL(	const btDbvtNode* root,
+		const btVector3* normals,
+		const btScalar* offsets,
+		const btVector3& sortaxis,
+		int count,								
+		DBVT_IPOLICY,
+		bool fullsort=true);
+	DBVT_PREFIX
+		static void		collideTU(	const btDbvtNode* root,
+		DBVT_IPOLICY);
+	// Helpers	
+	static DBVT_INLINE int	nearest(const int* i,const btDbvt::sStkNPS* a,btScalar v,int l,int h)
+	{
+		int	m=0;
+		while(l<h)
+		{
+			m=(l+h)>>1;
+			if(a[i[m]].value>=v) l=m+1; else h=m;
+		}
+		return(h);
+	}
+	static DBVT_INLINE int	allocate(	btAlignedObjectArray<int>& ifree,
+		btAlignedObjectArray<sStkNPS>& stock,
+		const sStkNPS& value)
+	{
+		int	i;
+		if(ifree.size()>0)
+		{ i=ifree[ifree.size()-1];ifree.pop_back();stock[i]=value; }
+		else
+		{ i=stock.size();stock.push_back(value); }
+		return(i); 
+	}
+	//
+private:
+	btDbvt(const btDbvt&)	{}	
+};
+
+//
+// Inline's
+//
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromCE(const btVector3& c,const btVector3& e)
+{
+	btDbvtAabbMm box;
+	box.mi=c-e;box.mx=c+e;
+	return(box);
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromCR(const btVector3& c,btScalar r)
+{
+	return(FromCE(c,btVector3(r,r,r)));
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromMM(const btVector3& mi,const btVector3& mx)
+{
+	btDbvtAabbMm box;
+	box.mi=mi;box.mx=mx;
+	return(box);
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromPoints(const btVector3* pts,int n)
+{
+	btDbvtAabbMm box;
+	box.mi=box.mx=pts[0];
+	for(int i=1;i<n;++i)
+	{
+		box.mi.setMin(pts[i]);
+		box.mx.setMax(pts[i]);
+	}
+	return(box);
+}
+
+//
+inline btDbvtAabbMm			btDbvtAabbMm::FromPoints(const btVector3** ppts,int n)
+{
+	btDbvtAabbMm box;
+	box.mi=box.mx=*ppts[0];
+	for(int i=1;i<n;++i)
+	{
+		box.mi.setMin(*ppts[i]);
+		box.mx.setMax(*ppts[i]);
+	}
+	return(box);
+}
+
+//
+DBVT_INLINE void		btDbvtAabbMm::Expand(const btVector3& e)
+{
+	mi-=e;mx+=e;
+}
+
+//
+DBVT_INLINE void		btDbvtAabbMm::SignedExpand(const btVector3& e)
+{
+	if(e.x()>0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]);
+	if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]);
+	if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]);
+}
+
+//
+DBVT_INLINE bool		btDbvtAabbMm::Contain(const btDbvtAabbMm& a) const
+{
+	return(	(mi.x()<=a.mi.x())&&
+		(mi.y()<=a.mi.y())&&
+		(mi.z()<=a.mi.z())&&
+		(mx.x()>=a.mx.x())&&
+		(mx.y()>=a.mx.y())&&
+		(mx.z()>=a.mx.z()));
+}
+
+//
+DBVT_INLINE int		btDbvtAabbMm::Classify(const btVector3& n,btScalar o,int s) const
+{
+	btVector3			pi,px;
+	switch(s)
+	{
+	case	(0+0+0):	px=btVector3(mi.x(),mi.y(),mi.z());
+		pi=btVector3(mx.x(),mx.y(),mx.z());break;
+	case	(1+0+0):	px=btVector3(mx.x(),mi.y(),mi.z());
+		pi=btVector3(mi.x(),mx.y(),mx.z());break;
+	case	(0+2+0):	px=btVector3(mi.x(),mx.y(),mi.z());
+		pi=btVector3(mx.x(),mi.y(),mx.z());break;
+	case	(1+2+0):	px=btVector3(mx.x(),mx.y(),mi.z());
+		pi=btVector3(mi.x(),mi.y(),mx.z());break;
+	case	(0+0+4):	px=btVector3(mi.x(),mi.y(),mx.z());
+		pi=btVector3(mx.x(),mx.y(),mi.z());break;
+	case	(1+0+4):	px=btVector3(mx.x(),mi.y(),mx.z());
+		pi=btVector3(mi.x(),mx.y(),mi.z());break;
+	case	(0+2+4):	px=btVector3(mi.x(),mx.y(),mx.z());
+		pi=btVector3(mx.x(),mi.y(),mi.z());break;
+	case	(1+2+4):	px=btVector3(mx.x(),mx.y(),mx.z());
+		pi=btVector3(mi.x(),mi.y(),mi.z());break;
+	}
+	if((btDot(n,px)+o)<0)		return(-1);
+	if((btDot(n,pi)+o)>=0)	return(+1);
+	return(0);
+}
+
+//
+DBVT_INLINE btScalar	btDbvtAabbMm::ProjectMinimum(const btVector3& v,unsigned signs) const
+{
+	const btVector3*	b[]={&mx,&mi};
+	const btVector3		p(	b[(signs>>0)&1]->x(),
+		b[(signs>>1)&1]->y(),
+		b[(signs>>2)&1]->z());
+	return(btDot(p,v));
+}
+
+//
+DBVT_INLINE void		btDbvtAabbMm::AddSpan(const btVector3& d,btScalar& smi,btScalar& smx) const
+{
+	for(int i=0;i<3;++i)
+	{
+		if(d[i]<0)
+		{ smi+=mx[i]*d[i];smx+=mi[i]*d[i]; }
+		else
+		{ smi+=mi[i]*d[i];smx+=mx[i]*d[i]; }
+	}
+}
+
+//
+DBVT_INLINE bool		Intersect(	const btDbvtAabbMm& a,
+								  const btDbvtAabbMm& b)
+{
+#if	DBVT_INT0_IMPL == DBVT_IMPL_SSE
+	const __m128	rt(_mm_or_ps(	_mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)),
+		_mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi))));
+	const __int32*	pu((const __int32*)&rt);
+	return((pu[0]|pu[1]|pu[2])==0);
+#else
+	return(	(a.mi.x()<=b.mx.x())&&
+		(a.mx.x()>=b.mi.x())&&
+		(a.mi.y()<=b.mx.y())&&
+		(a.mx.y()>=b.mi.y())&&
+		(a.mi.z()<=b.mx.z())&&		
+		(a.mx.z()>=b.mi.z()));
+#endif
+}
+
+
+
+//
+DBVT_INLINE bool		Intersect(	const btDbvtAabbMm& a,
+								  const btVector3& b)
+{
+	return(	(b.x()>=a.mi.x())&&
+		(b.y()>=a.mi.y())&&
+		(b.z()>=a.mi.z())&&
+		(b.x()<=a.mx.x())&&
+		(b.y()<=a.mx.y())&&
+		(b.z()<=a.mx.z()));
+}
+
+
+
+
+
+//////////////////////////////////////
+
+
+//
+DBVT_INLINE btScalar	Proximity(	const btDbvtAabbMm& a,
+								  const btDbvtAabbMm& b)
+{
+	const btVector3	d=(a.mi+a.mx)-(b.mi+b.mx);
+	return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z()));
+}
+
+
+
+//
+DBVT_INLINE int			Select(	const btDbvtAabbMm& o,
+							   const btDbvtAabbMm& a,
+							   const btDbvtAabbMm& b)
+{
+#if	DBVT_SELECT_IMPL == DBVT_IMPL_SSE
+	static ATTRIBUTE_ALIGNED16(const unsigned __int32)	mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff};
+	///@todo: the intrinsic version is 11% slower
+#if DBVT_USE_INTRINSIC_SSE
+
+	union btSSEUnion ///NOTE: if we use more intrinsics, move btSSEUnion into the LinearMath directory
+	{
+	   __m128		ssereg;
+	   float		floats[4];
+	   int			ints[4];
+	};
+
+	__m128	omi(_mm_load_ps(o.mi));
+	omi=_mm_add_ps(omi,_mm_load_ps(o.mx));
+	__m128	ami(_mm_load_ps(a.mi));
+	ami=_mm_add_ps(ami,_mm_load_ps(a.mx));
+	ami=_mm_sub_ps(ami,omi);
+	ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask));
+	__m128	bmi(_mm_load_ps(b.mi));
+	bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx));
+	bmi=_mm_sub_ps(bmi,omi);
+	bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask));
+	__m128	t0(_mm_movehl_ps(ami,ami));
+	ami=_mm_add_ps(ami,t0);
+	ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1));
+	__m128 t1(_mm_movehl_ps(bmi,bmi));
+	bmi=_mm_add_ps(bmi,t1);
+	bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1));
+	
+	btSSEUnion tmp;
+	tmp.ssereg = _mm_cmple_ss(bmi,ami);
+	return tmp.ints[0]&1;
+
+#else
+	ATTRIBUTE_ALIGNED16(__int32	r[1]);
+	__asm
+	{
+		mov		eax,o
+			mov		ecx,a
+			mov		edx,b
+			movaps	xmm0,[eax]
+		movaps	xmm5,mask
+			addps	xmm0,[eax+16]	
+		movaps	xmm1,[ecx]
+		movaps	xmm2,[edx]
+		addps	xmm1,[ecx+16]
+		addps	xmm2,[edx+16]
+		subps	xmm1,xmm0
+			subps	xmm2,xmm0
+			andps	xmm1,xmm5
+			andps	xmm2,xmm5
+			movhlps	xmm3,xmm1
+			movhlps	xmm4,xmm2
+			addps	xmm1,xmm3
+			addps	xmm2,xmm4
+			pshufd	xmm3,xmm1,1
+			pshufd	xmm4,xmm2,1
+			addss	xmm1,xmm3
+			addss	xmm2,xmm4
+			cmpless	xmm2,xmm1
+			movss	r,xmm2
+	}
+	return(r[0]&1);
+#endif
+#else
+	return(Proximity(o,a)<Proximity(o,b)?0:1);
+#endif
+}
+
+//
+DBVT_INLINE void		Merge(	const btDbvtAabbMm& a,
+							  const btDbvtAabbMm& b,
+							  btDbvtAabbMm& r)
+{
+#if DBVT_MERGE_IMPL==DBVT_IMPL_SSE
+	__m128	ami(_mm_load_ps(a.mi));
+	__m128	amx(_mm_load_ps(a.mx));
+	__m128	bmi(_mm_load_ps(b.mi));
+	__m128	bmx(_mm_load_ps(b.mx));
+	ami=_mm_min_ps(ami,bmi);
+	amx=_mm_max_ps(amx,bmx);
+	_mm_store_ps(r.mi,ami);
+	_mm_store_ps(r.mx,amx);
+#else
+	for(int i=0;i<3;++i)
+	{
+		if(a.mi[i]<b.mi[i]) r.mi[i]=a.mi[i]; else r.mi[i]=b.mi[i];
+		if(a.mx[i]>b.mx[i]) r.mx[i]=a.mx[i]; else r.mx[i]=b.mx[i];
+	}
+#endif
+}
+
+//
+DBVT_INLINE bool		NotEqual(	const btDbvtAabbMm& a,
+								 const btDbvtAabbMm& b)
+{
+	return(	(a.mi.x()!=b.mi.x())||
+		(a.mi.y()!=b.mi.y())||
+		(a.mi.z()!=b.mi.z())||
+		(a.mx.x()!=b.mx.x())||
+		(a.mx.y()!=b.mx.y())||
+		(a.mx.z()!=b.mx.z()));
+}
+
+//
+// Inline's
+//
+
+//
+DBVT_PREFIX
+inline void		btDbvt::enumNodes(	const btDbvtNode* root,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		policy.Process(root);
+	if(root->isinternal())
+	{
+		enumNodes(root->childs[0],policy);
+		enumNodes(root->childs[1],policy);
+	}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::enumLeaves(	const btDbvtNode* root,
+								   DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root->isinternal())
+		{
+			enumLeaves(root->childs[0],policy);
+			enumLeaves(root->childs[1],policy);
+		}
+		else
+		{
+			policy.Process(root);
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTT(	const btDbvtNode* root0,
+								  const btDbvtNode* root1,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root0&&root1)
+		{
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-4;
+			btAlignedObjectArray<sStkNN>	stkStack;
+			stkStack.resize(DOUBLE_STACKSIZE);
+			stkStack[0]=sStkNN(root0,root1);
+			do	{		
+				sStkNN	p=stkStack[--depth];
+				if(depth>treshold)
+				{
+					stkStack.resize(stkStack.size()*2);
+					treshold=stkStack.size()-4;
+				}
+				if(p.a==p.b)
+				{
+					if(p.a->isinternal())
+					{
+						stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+						stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+						stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+					}
+				}
+				else if(Intersect(p.a->volume,p.b->volume))
+				{
+					if(p.a->isinternal())
+					{
+						if(p.b->isinternal())
+						{
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+						}
+						else
+						{
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+						}
+					}
+					else
+					{
+						if(p.b->isinternal())
+						{
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+						}
+						else
+						{
+							policy.Process(p.a,p.b);
+						}
+					}
+				}
+			} while(depth);
+		}
+}
+
+
+
+DBVT_PREFIX
+inline void		btDbvt::collideTTpersistentStack(	const btDbvtNode* root0,
+								  const btDbvtNode* root1,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root0&&root1)
+		{
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-4;
+			
+			m_stkStack.resize(DOUBLE_STACKSIZE);
+			m_stkStack[0]=sStkNN(root0,root1);
+			do	{		
+				sStkNN	p=m_stkStack[--depth];
+				if(depth>treshold)
+				{
+					m_stkStack.resize(m_stkStack.size()*2);
+					treshold=m_stkStack.size()-4;
+				}
+				if(p.a==p.b)
+				{
+					if(p.a->isinternal())
+					{
+						m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[0]);
+						m_stkStack[depth++]=sStkNN(p.a->childs[1],p.a->childs[1]);
+						m_stkStack[depth++]=sStkNN(p.a->childs[0],p.a->childs[1]);
+					}
+				}
+				else if(Intersect(p.a->volume,p.b->volume))
+				{
+					if(p.a->isinternal())
+					{
+						if(p.b->isinternal())
+						{
+							m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+							m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+							m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+							m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+						}
+						else
+						{
+							m_stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+							m_stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+						}
+					}
+					else
+					{
+						if(p.b->isinternal())
+						{
+							m_stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+							m_stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+						}
+						else
+						{
+							policy.Process(p.a,p.b);
+						}
+					}
+				}
+			} while(depth);
+		}
+}
+
+#if 0
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTT(	const btDbvtNode* root0,
+								  const btDbvtNode* root1,
+								  const btTransform& xform,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root0&&root1)
+		{
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-4;
+			btAlignedObjectArray<sStkNN>	stkStack;
+			stkStack.resize(DOUBLE_STACKSIZE);
+			stkStack[0]=sStkNN(root0,root1);
+			do	{
+				sStkNN	p=stkStack[--depth];
+				if(Intersect(p.a->volume,p.b->volume,xform))
+				{
+					if(depth>treshold)
+					{
+						stkStack.resize(stkStack.size()*2);
+						treshold=stkStack.size()-4;
+					}
+					if(p.a->isinternal())
+					{
+						if(p.b->isinternal())
+						{					
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b->childs[1]);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b->childs[1]);
+						}
+						else
+						{
+							stkStack[depth++]=sStkNN(p.a->childs[0],p.b);
+							stkStack[depth++]=sStkNN(p.a->childs[1],p.b);
+						}
+					}
+					else
+					{
+						if(p.b->isinternal())
+						{
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[0]);
+							stkStack[depth++]=sStkNN(p.a,p.b->childs[1]);
+						}
+						else
+						{
+							policy.Process(p.a,p.b);
+						}
+					}
+				}
+			} while(depth);
+		}
+}
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTT(	const btDbvtNode* root0,
+								  const btTransform& xform0,
+								  const btDbvtNode* root1,
+								  const btTransform& xform1,
+								  DBVT_IPOLICY)
+{
+	const btTransform	xform=xform0.inverse()*xform1;
+	collideTT(root0,root1,xform,policy);
+}
+#endif 
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTV(	const btDbvtNode* root,
+								  const btDbvtVolume& vol,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			ATTRIBUTE_ALIGNED16(btDbvtVolume)		volume(vol);
+			btAlignedObjectArray<const btDbvtNode*>	stack;
+			stack.resize(0);
+			stack.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(root);
+			do	{
+				const btDbvtNode*	n=stack[stack.size()-1];
+				stack.pop_back();
+				if(Intersect(n->volume,volume))
+				{
+					if(n->isinternal())
+					{
+						stack.push_back(n->childs[0]);
+						stack.push_back(n->childs[1]);
+					}
+					else
+					{
+						policy.Process(n);
+					}
+				}
+			} while(stack.size()>0);
+		}
+}
+
+DBVT_PREFIX
+inline void		btDbvt::rayTestInternal(	const btDbvtNode* root,
+								const btVector3& rayFrom,
+								const btVector3& rayTo,
+								const btVector3& rayDirectionInverse,
+								unsigned int signs[3],
+								btScalar lambda_max,
+								const btVector3& aabbMin,
+								const btVector3& aabbMax,
+								DBVT_IPOLICY) const
+{
+        (void) rayTo;
+	DBVT_CHECKTYPE
+	if(root)
+	{
+		btVector3 resultNormal;
+
+		int								depth=1;
+		int								treshold=DOUBLE_STACKSIZE-2;
+		btAlignedObjectArray<const btDbvtNode*>	stack;
+		stack.resize(DOUBLE_STACKSIZE);
+		stack[0]=root;
+		btVector3 bounds[2];
+		do	
+		{
+			const btDbvtNode*	node=stack[--depth];
+			bounds[0] = node->volume.Mins()-aabbMax;
+			bounds[1] = node->volume.Maxs()-aabbMin;
+			btScalar tmin=1.f,lambda_min=0.f;
+			unsigned int result1=false;
+			result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+			if(result1)
+			{
+				if(node->isinternal())
+				{
+					if(depth>treshold)
+					{
+						stack.resize(stack.size()*2);
+						treshold=stack.size()-2;
+					}
+					stack[depth++]=node->childs[0];
+					stack[depth++]=node->childs[1];
+				}
+				else
+				{
+					policy.Process(node);
+				}
+			}
+		} while(depth);
+	}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::rayTest(	const btDbvtNode* root,
+								const btVector3& rayFrom,
+								const btVector3& rayTo,
+								DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			btVector3 rayDir = (rayTo-rayFrom);
+			rayDir.normalize ();
+
+			///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+			btVector3 rayDirectionInverse;
+			rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+			rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+			rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+			unsigned int signs[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+
+			btScalar lambda_max = rayDir.dot(rayTo-rayFrom);
+
+			btVector3 resultNormal;
+
+			btAlignedObjectArray<const btDbvtNode*>	stack;
+
+			int								depth=1;
+			int								treshold=DOUBLE_STACKSIZE-2;
+
+			stack.resize(DOUBLE_STACKSIZE);
+			stack[0]=root;
+			btVector3 bounds[2];
+			do	{
+				const btDbvtNode*	node=stack[--depth];
+
+				bounds[0] = node->volume.Mins();
+				bounds[1] = node->volume.Maxs();
+				
+				btScalar tmin=1.f,lambda_min=0.f;
+				unsigned int result1 = btRayAabb2(rayFrom,rayDirectionInverse,signs,bounds,tmin,lambda_min,lambda_max);
+
+#ifdef COMPARE_BTRAY_AABB2
+				btScalar param=1.f;
+				bool result2 = btRayAabb(rayFrom,rayTo,node->volume.Mins(),node->volume.Maxs(),param,resultNormal);
+				btAssert(result1 == result2);
+#endif //TEST_BTRAY_AABB2
+
+				if(result1)
+				{
+					if(node->isinternal())
+					{
+						if(depth>treshold)
+						{
+							stack.resize(stack.size()*2);
+							treshold=stack.size()-2;
+						}
+						stack[depth++]=node->childs[0];
+						stack[depth++]=node->childs[1];
+					}
+					else
+					{
+						policy.Process(node);
+					}
+				}
+			} while(depth);
+
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideKDOP(const btDbvtNode* root,
+									const btVector3* normals,
+									const btScalar* offsets,
+									int count,
+									DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			const int						inside=(1<<count)-1;
+			btAlignedObjectArray<sStkNP>	stack;
+			int								signs[sizeof(unsigned)*8];
+			btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+			for(int i=0;i<count;++i)
+			{
+				signs[i]=	((normals[i].x()>=0)?1:0)+
+					((normals[i].y()>=0)?2:0)+
+					((normals[i].z()>=0)?4:0);
+			}
+			stack.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(sStkNP(root,0));
+			do	{
+				sStkNP	se=stack[stack.size()-1];
+				bool	out=false;
+				stack.pop_back();
+				for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+				{
+					if(0==(se.mask&j))
+					{
+						const int	side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+						switch(side)
+						{
+						case	-1:	out=true;break;
+						case	+1:	se.mask|=j;break;
+						}
+					}
+				}
+				if(!out)
+				{
+					if((se.mask!=inside)&&(se.node->isinternal()))
+					{
+						stack.push_back(sStkNP(se.node->childs[0],se.mask));
+						stack.push_back(sStkNP(se.node->childs[1],se.mask));
+					}
+					else
+					{
+						if(policy.AllLeaves(se.node)) enumLeaves(se.node,policy);
+					}
+				}
+			} while(stack.size());
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideOCL(	const btDbvtNode* root,
+								   const btVector3* normals,
+								   const btScalar* offsets,
+								   const btVector3& sortaxis,
+								   int count,
+								   DBVT_IPOLICY,
+								   bool fsort)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			const unsigned					srtsgns=(sortaxis[0]>=0?1:0)+
+				(sortaxis[1]>=0?2:0)+
+				(sortaxis[2]>=0?4:0);
+			const int						inside=(1<<count)-1;
+			btAlignedObjectArray<sStkNPS>	stock;
+			btAlignedObjectArray<int>		ifree;
+			btAlignedObjectArray<int>		stack;
+			int								signs[sizeof(unsigned)*8];
+			btAssert(count<int (sizeof(signs)/sizeof(signs[0])));
+			for(int i=0;i<count;++i)
+			{
+				signs[i]=	((normals[i].x()>=0)?1:0)+
+					((normals[i].y()>=0)?2:0)+
+					((normals[i].z()>=0)?4:0);
+			}
+			stock.reserve(SIMPLE_STACKSIZE);
+			stack.reserve(SIMPLE_STACKSIZE);
+			ifree.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(allocate(ifree,stock,sStkNPS(root,0,root->volume.ProjectMinimum(sortaxis,srtsgns))));
+			do	{
+				const int	id=stack[stack.size()-1];
+				sStkNPS		se=stock[id];
+				stack.pop_back();ifree.push_back(id);
+				if(se.mask!=inside)
+				{
+					bool	out=false;
+					for(int i=0,j=1;(!out)&&(i<count);++i,j<<=1)
+					{
+						if(0==(se.mask&j))
+						{
+							const int	side=se.node->volume.Classify(normals[i],offsets[i],signs[i]);
+							switch(side)
+							{
+							case	-1:	out=true;break;
+							case	+1:	se.mask|=j;break;
+							}
+						}
+					}
+					if(out) continue;
+				}
+				if(policy.Descent(se.node))
+				{
+					if(se.node->isinternal())
+					{
+						const btDbvtNode* pns[]={	se.node->childs[0],se.node->childs[1]};
+						sStkNPS		nes[]={	sStkNPS(pns[0],se.mask,pns[0]->volume.ProjectMinimum(sortaxis,srtsgns)),
+							sStkNPS(pns[1],se.mask,pns[1]->volume.ProjectMinimum(sortaxis,srtsgns))};
+						const int	q=nes[0].value<nes[1].value?1:0;				
+						int			j=stack.size();
+						if(fsort&&(j>0))
+						{
+							/* Insert 0	*/ 
+							j=nearest(&stack[0],&stock[0],nes[q].value,0,stack.size());
+							stack.push_back(0);
+#if DBVT_USE_MEMMOVE
+							memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+							for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+							stack[j]=allocate(ifree,stock,nes[q]);
+							/* Insert 1	*/ 
+							j=nearest(&stack[0],&stock[0],nes[1-q].value,j,stack.size());
+							stack.push_back(0);
+#if DBVT_USE_MEMMOVE
+							memmove(&stack[j+1],&stack[j],sizeof(int)*(stack.size()-j-1));
+#else
+							for(int k=stack.size()-1;k>j;--k) stack[k]=stack[k-1];
+#endif
+							stack[j]=allocate(ifree,stock,nes[1-q]);
+						}
+						else
+						{
+							stack.push_back(allocate(ifree,stock,nes[q]));
+							stack.push_back(allocate(ifree,stock,nes[1-q]));
+						}
+					}
+					else
+					{
+						policy.Process(se.node,se.value);
+					}
+				}
+			} while(stack.size());
+		}
+}
+
+//
+DBVT_PREFIX
+inline void		btDbvt::collideTU(	const btDbvtNode* root,
+								  DBVT_IPOLICY)
+{
+	DBVT_CHECKTYPE
+		if(root)
+		{
+			btAlignedObjectArray<const btDbvtNode*>	stack;
+			stack.reserve(SIMPLE_STACKSIZE);
+			stack.push_back(root);
+			do	{
+				const btDbvtNode*	n=stack[stack.size()-1];
+				stack.pop_back();
+				if(policy.Descent(n))
+				{
+					if(n->isinternal())
+					{ stack.push_back(n->childs[0]);stack.push_back(n->childs[1]); }
+					else
+					{ policy.Process(n); }
+				}
+			} while(stack.size()>0);
+		}
+}
+
+//
+// PP Cleanup
+//
+
+#undef DBVT_USE_MEMMOVE
+#undef DBVT_USE_TEMPLATE
+#undef DBVT_VIRTUAL_DTOR
+#undef DBVT_VIRTUAL
+#undef DBVT_PREFIX
+#undef DBVT_IPOLICY
+#undef DBVT_CHECKTYPE
+#undef DBVT_IMPL_GENERIC
+#undef DBVT_IMPL_SSE
+#undef DBVT_USE_INTRINSIC_SSE
+#undef DBVT_SELECT_IMPL
+#undef DBVT_MERGE_IMPL
+#undef DBVT_INT0_IMPL
+
+#endif
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
new file mode 100644
index 0000000..75cfac6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp
@@ -0,0 +1,796 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+
+#include "btDbvtBroadphase.h"
+
+//
+// Profiling
+//
+
+#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK
+#include <stdio.h>
+#endif
+
+#if DBVT_BP_PROFILE
+struct	ProfileScope
+{
+	__forceinline ProfileScope(btClock& clock,unsigned long& value) :
+	m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds())
+	{
+	}
+	__forceinline ~ProfileScope()
+	{
+		(*m_value)+=m_clock->getTimeMicroseconds()-m_base;
+	}
+	btClock*		m_clock;
+	unsigned long*	m_value;
+	unsigned long	m_base;
+};
+#define	SPC(_value_)	ProfileScope	spc_scope(m_clock,_value_)
+#else
+#define	SPC(_value_)
+#endif
+
+//
+// Helpers
+//
+
+//
+template <typename T>
+static inline void	listappend(T* item,T*& list)
+{
+	item->links[0]=0;
+	item->links[1]=list;
+	if(list) list->links[0]=item;
+	list=item;
+}
+
+//
+template <typename T>
+static inline void	listremove(T* item,T*& list)
+{
+	if(item->links[0]) item->links[0]->links[1]=item->links[1]; else list=item->links[1];
+	if(item->links[1]) item->links[1]->links[0]=item->links[0];
+}
+
+//
+template <typename T>
+static inline int	listcount(T* root)
+{
+	int	n=0;
+	while(root) { ++n;root=root->links[1]; }
+	return(n);
+}
+
+//
+template <typename T>
+static inline void	clear(T& value)
+{
+	static const struct ZeroDummy : T {} zerodummy;
+	value=zerodummy;
+}
+
+//
+// Colliders
+//
+
+/* Tree collider	*/ 
+struct	btDbvtTreeCollider : btDbvt::ICollide
+{
+	btDbvtBroadphase*	pbp;
+	btDbvtProxy*		proxy;
+	btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {}
+	void	Process(const btDbvtNode* na,const btDbvtNode* nb)
+	{
+		if(na!=nb)
+		{
+			btDbvtProxy*	pa=(btDbvtProxy*)na->data;
+			btDbvtProxy*	pb=(btDbvtProxy*)nb->data;
+#if DBVT_BP_SORTPAIRS
+			if(pa->m_uniqueId>pb->m_uniqueId) 
+				btSwap(pa,pb);
+#endif
+			pbp->m_paircache->addOverlappingPair(pa,pb);
+			++pbp->m_newpairs;
+		}
+	}
+	void	Process(const btDbvtNode* n)
+	{
+		Process(n,proxy->leaf);
+	}
+};
+
+//
+// btDbvtBroadphase
+//
+
+//
+btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache)
+{
+	m_deferedcollide	=	false;
+	m_needcleanup		=	true;
+	m_releasepaircache	=	(paircache!=0)?false:true;
+	m_prediction		=	0;
+	m_stageCurrent		=	0;
+	m_fixedleft			=	0;
+	m_fupdates			=	1;
+	m_dupdates			=	0;
+	m_cupdates			=	10;
+	m_newpairs			=	1;
+	m_updates_call		=	0;
+	m_updates_done		=	0;
+	m_updates_ratio		=	0;
+	m_paircache			=	paircache? paircache	: new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+	m_gid				=	0;
+	m_pid				=	0;
+	m_cid				=	0;
+	for(int i=0;i<=STAGECOUNT;++i)
+	{
+		m_stageRoots[i]=0;
+	}
+#if DBVT_BP_PROFILE
+	clear(m_profiling);
+#endif
+}
+
+//
+btDbvtBroadphase::~btDbvtBroadphase()
+{
+	if(m_releasepaircache) 
+	{
+		m_paircache->~btOverlappingPairCache();
+		btAlignedFree(m_paircache);
+	}
+}
+
+//
+btBroadphaseProxy*				btDbvtBroadphase::createProxy(	const btVector3& aabbMin,
+															  const btVector3& aabbMax,
+															  int /*shapeType*/,
+															  void* userPtr,
+															  short int collisionFilterGroup,
+															  short int collisionFilterMask,
+															  btDispatcher* /*dispatcher*/,
+															  void* /*multiSapProxy*/)
+{
+	btDbvtProxy*		proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy(	aabbMin,aabbMax,userPtr,
+		collisionFilterGroup,
+		collisionFilterMask);
+
+	btDbvtAabbMm aabb = btDbvtVolume::FromMM(aabbMin,aabbMax);
+
+	//bproxy->aabb			=	btDbvtVolume::FromMM(aabbMin,aabbMax);
+	proxy->stage		=	m_stageCurrent;
+	proxy->m_uniqueId	=	++m_gid;
+	proxy->leaf			=	m_sets[0].insert(aabb,proxy);
+	listappend(proxy,m_stageRoots[m_stageCurrent]);
+	if(!m_deferedcollide)
+	{
+		btDbvtTreeCollider	collider(this);
+		collider.proxy=proxy;
+		m_sets[0].collideTV(m_sets[0].m_root,aabb,collider);
+		m_sets[1].collideTV(m_sets[1].m_root,aabb,collider);
+	}
+	return(proxy);
+}
+
+//
+void							btDbvtBroadphase::destroyProxy(	btBroadphaseProxy* absproxy,
+															   btDispatcher* dispatcher)
+{
+	btDbvtProxy*	proxy=(btDbvtProxy*)absproxy;
+	if(proxy->stage==STAGECOUNT)
+		m_sets[1].remove(proxy->leaf);
+	else
+		m_sets[0].remove(proxy->leaf);
+	listremove(proxy,m_stageRoots[proxy->stage]);
+	m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher);
+	btAlignedFree(proxy);
+	m_needcleanup=true;
+}
+
+void	btDbvtBroadphase::getAabb(btBroadphaseProxy* absproxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy;
+	aabbMin = proxy->m_aabbMin;
+	aabbMax = proxy->m_aabbMax;
+}
+
+struct	BroadphaseRayTester : btDbvt::ICollide
+{
+	btBroadphaseRayCallback& m_rayCallback;
+	BroadphaseRayTester(btBroadphaseRayCallback& orgCallback)
+		:m_rayCallback(orgCallback)
+	{
+	}
+	void					Process(const btDbvtNode* leaf)
+	{
+		btDbvtProxy*	proxy=(btDbvtProxy*)leaf->data;
+		m_rayCallback.process(proxy);
+	}
+};	
+
+void	btDbvtBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	BroadphaseRayTester callback(rayCallback);
+
+	m_sets[0].rayTestInternal(	m_sets[0].m_root,
+		rayFrom,
+		rayTo,
+		rayCallback.m_rayDirectionInverse,
+		rayCallback.m_signs,
+		rayCallback.m_lambda_max,
+		aabbMin,
+		aabbMax,
+		callback);
+
+	m_sets[1].rayTestInternal(	m_sets[1].m_root,
+		rayFrom,
+		rayTo,
+		rayCallback.m_rayDirectionInverse,
+		rayCallback.m_signs,
+		rayCallback.m_lambda_max,
+		aabbMin,
+		aabbMax,
+		callback);
+
+}
+
+
+struct	BroadphaseAabbTester : btDbvt::ICollide
+{
+	btBroadphaseAabbCallback& m_aabbCallback;
+	BroadphaseAabbTester(btBroadphaseAabbCallback& orgCallback)
+		:m_aabbCallback(orgCallback)
+	{
+	}
+	void					Process(const btDbvtNode* leaf)
+	{
+		btDbvtProxy*	proxy=(btDbvtProxy*)leaf->data;
+		m_aabbCallback.process(proxy);
+	}
+};	
+
+void	btDbvtBroadphase::aabbTest(const btVector3& aabbMin,const btVector3& aabbMax,btBroadphaseAabbCallback& aabbCallback)
+{
+	BroadphaseAabbTester callback(aabbCallback);
+
+	const ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(aabbMin,aabbMax);
+		//process all children, that overlap with  the given AABB bounds
+	m_sets[0].collideTV(m_sets[0].m_root,bounds,callback);
+	m_sets[1].collideTV(m_sets[1].m_root,bounds,callback);
+
+}
+
+
+
+//
+void							btDbvtBroadphase::setAabb(		btBroadphaseProxy* absproxy,
+														  const btVector3& aabbMin,
+														  const btVector3& aabbMax,
+														  btDispatcher* /*dispatcher*/)
+{
+	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy;
+	ATTRIBUTE_ALIGNED16(btDbvtVolume)	aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+#if DBVT_BP_PREVENTFALSEUPDATE
+	if(NotEqual(aabb,proxy->leaf->volume))
+#endif
+	{
+		bool	docollide=false;
+		if(proxy->stage==STAGECOUNT)
+		{/* fixed -> dynamic set	*/ 
+			m_sets[1].remove(proxy->leaf);
+			proxy->leaf=m_sets[0].insert(aabb,proxy);
+			docollide=true;
+		}
+		else
+		{/* dynamic set				*/ 
+			++m_updates_call;
+			if(Intersect(proxy->leaf->volume,aabb))
+			{/* Moving				*/ 
+
+				const btVector3	delta=aabbMin-proxy->m_aabbMin;
+				btVector3		velocity(((proxy->m_aabbMax-proxy->m_aabbMin)/2)*m_prediction);
+				if(delta[0]<0) velocity[0]=-velocity[0];
+				if(delta[1]<0) velocity[1]=-velocity[1];
+				if(delta[2]<0) velocity[2]=-velocity[2];
+				if	(
+#ifdef DBVT_BP_MARGIN				
+					m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN)
+#else
+					m_sets[0].update(proxy->leaf,aabb,velocity)
+#endif
+					)
+				{
+					++m_updates_done;
+					docollide=true;
+				}
+			}
+			else
+			{/* Teleporting			*/ 
+				m_sets[0].update(proxy->leaf,aabb);
+				++m_updates_done;
+				docollide=true;
+			}	
+		}
+		listremove(proxy,m_stageRoots[proxy->stage]);
+		proxy->m_aabbMin = aabbMin;
+		proxy->m_aabbMax = aabbMax;
+		proxy->stage	=	m_stageCurrent;
+		listappend(proxy,m_stageRoots[m_stageCurrent]);
+		if(docollide)
+		{
+			m_needcleanup=true;
+			if(!m_deferedcollide)
+			{
+				btDbvtTreeCollider	collider(this);
+				m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+				m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+			}
+		}	
+	}
+}
+
+
+//
+void							btDbvtBroadphase::setAabbForceUpdate(		btBroadphaseProxy* absproxy,
+														  const btVector3& aabbMin,
+														  const btVector3& aabbMax,
+														  btDispatcher* /*dispatcher*/)
+{
+	btDbvtProxy*						proxy=(btDbvtProxy*)absproxy;
+	ATTRIBUTE_ALIGNED16(btDbvtVolume)	aabb=btDbvtVolume::FromMM(aabbMin,aabbMax);
+	bool	docollide=false;
+	if(proxy->stage==STAGECOUNT)
+	{/* fixed -> dynamic set	*/ 
+		m_sets[1].remove(proxy->leaf);
+		proxy->leaf=m_sets[0].insert(aabb,proxy);
+		docollide=true;
+	}
+	else
+	{/* dynamic set				*/ 
+		++m_updates_call;
+		/* Teleporting			*/ 
+		m_sets[0].update(proxy->leaf,aabb);
+		++m_updates_done;
+		docollide=true;
+	}
+	listremove(proxy,m_stageRoots[proxy->stage]);
+	proxy->m_aabbMin = aabbMin;
+	proxy->m_aabbMax = aabbMax;
+	proxy->stage	=	m_stageCurrent;
+	listappend(proxy,m_stageRoots[m_stageCurrent]);
+	if(docollide)
+	{
+		m_needcleanup=true;
+		if(!m_deferedcollide)
+		{
+			btDbvtTreeCollider	collider(this);
+			m_sets[1].collideTTpersistentStack(m_sets[1].m_root,proxy->leaf,collider);
+			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,proxy->leaf,collider);
+		}
+	}	
+}
+
+//
+void							btDbvtBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+	collide(dispatcher);
+#if DBVT_BP_PROFILE
+	if(0==(m_pid%DBVT_BP_PROFILING_RATE))
+	{	
+		printf("fixed(%u) dynamics(%u) pairs(%u)\r\n",m_sets[1].m_leaves,m_sets[0].m_leaves,m_paircache->getNumOverlappingPairs());
+		unsigned int	total=m_profiling.m_total;
+		if(total<=0) total=1;
+		printf("ddcollide: %u%% (%uus)\r\n",(50+m_profiling.m_ddcollide*100)/total,m_profiling.m_ddcollide/DBVT_BP_PROFILING_RATE);
+		printf("fdcollide: %u%% (%uus)\r\n",(50+m_profiling.m_fdcollide*100)/total,m_profiling.m_fdcollide/DBVT_BP_PROFILING_RATE);
+		printf("cleanup:   %u%% (%uus)\r\n",(50+m_profiling.m_cleanup*100)/total,m_profiling.m_cleanup/DBVT_BP_PROFILING_RATE);
+		printf("total:     %uus\r\n",total/DBVT_BP_PROFILING_RATE);
+		const unsigned long	sum=m_profiling.m_ddcollide+
+			m_profiling.m_fdcollide+
+			m_profiling.m_cleanup;
+		printf("leaked: %u%% (%uus)\r\n",100-((50+sum*100)/total),(total-sum)/DBVT_BP_PROFILING_RATE);
+		printf("job counts: %u%%\r\n",(m_profiling.m_jobcount*100)/((m_sets[0].m_leaves+m_sets[1].m_leaves)*DBVT_BP_PROFILING_RATE));
+		clear(m_profiling);
+		m_clock.reset();
+	}
+#endif
+
+	performDeferredRemoval(dispatcher);
+
+}
+
+void btDbvtBroadphase::performDeferredRemoval(btDispatcher* dispatcher)
+{
+
+	if (m_paircache->hasDeferredRemoval())
+	{
+
+		btBroadphasePairArray&	overlappingPairArray = m_paircache->getOverlappingPairArray();
+
+		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+		int invalidPair = 0;
+
+		
+		int i;
+
+		btBroadphasePair previousPair;
+		previousPair.m_pProxy0 = 0;
+		previousPair.m_pProxy1 = 0;
+		previousPair.m_algorithm = 0;
+		
+		
+		for (i=0;i<overlappingPairArray.size();i++)
+		{
+		
+			btBroadphasePair& pair = overlappingPairArray[i];
+
+			bool isDuplicate = (pair == previousPair);
+
+			previousPair = pair;
+
+			bool needsRemoval = false;
+
+			if (!isDuplicate)
+			{
+				//important to perform AABB check that is consistent with the broadphase
+				btDbvtProxy*		pa=(btDbvtProxy*)pair.m_pProxy0;
+				btDbvtProxy*		pb=(btDbvtProxy*)pair.m_pProxy1;
+				bool hasOverlap = Intersect(pa->leaf->volume,pb->leaf->volume);
+
+				if (hasOverlap)
+				{
+					needsRemoval = false;
+				} else
+				{
+					needsRemoval = true;
+				}
+			} else
+			{
+				//remove duplicate
+				needsRemoval = true;
+				//should have no algorithm
+				btAssert(!pair.m_algorithm);
+			}
+			
+			if (needsRemoval)
+			{
+				m_paircache->cleanOverlappingPair(pair,dispatcher);
+
+				pair.m_pProxy0 = 0;
+				pair.m_pProxy1 = 0;
+				invalidPair++;
+			} 
+			
+		}
+
+		//perform a sort, to sort 'invalid' pairs to the end
+		overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+		overlappingPairArray.resize(overlappingPairArray.size() - invalidPair);
+	}
+}
+
+//
+void							btDbvtBroadphase::collide(btDispatcher* dispatcher)
+{
+	/*printf("---------------------------------------------------------\n");
+	printf("m_sets[0].m_leaves=%d\n",m_sets[0].m_leaves);
+	printf("m_sets[1].m_leaves=%d\n",m_sets[1].m_leaves);
+	printf("numPairs = %d\n",getOverlappingPairCache()->getNumOverlappingPairs());
+	{
+		int i;
+		for (i=0;i<getOverlappingPairCache()->getNumOverlappingPairs();i++)
+		{
+			printf("pair[%d]=(%d,%d),",i,getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy0->getUid(),
+				getOverlappingPairCache()->getOverlappingPairArray()[i].m_pProxy1->getUid());
+		}
+		printf("\n");
+	}
+*/
+
+
+
+	SPC(m_profiling.m_total);
+	/* optimize				*/ 
+	m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100);
+	if(m_fixedleft)
+	{
+		const int count=1+(m_sets[1].m_leaves*m_fupdates)/100;
+		m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100);
+		m_fixedleft=btMax<int>(0,m_fixedleft-count);
+	}
+	/* dynamic -> fixed set	*/ 
+	m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT;
+	btDbvtProxy*	current=m_stageRoots[m_stageCurrent];
+	if(current)
+	{
+		btDbvtTreeCollider	collider(this);
+		do	{
+			btDbvtProxy*	next=current->links[1];
+			listremove(current,m_stageRoots[current->stage]);
+			listappend(current,m_stageRoots[STAGECOUNT]);
+#if DBVT_BP_ACCURATESLEEPING
+			m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher);
+			collider.proxy=current;
+			btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider);
+			btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider);
+#endif
+			m_sets[0].remove(current->leaf);
+			ATTRIBUTE_ALIGNED16(btDbvtVolume)	curAabb=btDbvtVolume::FromMM(current->m_aabbMin,current->m_aabbMax);
+			current->leaf	=	m_sets[1].insert(curAabb,current);
+			current->stage	=	STAGECOUNT;	
+			current			=	next;
+		} while(current);
+		m_fixedleft=m_sets[1].m_leaves;
+		m_needcleanup=true;
+	}
+	/* collide dynamics		*/ 
+	{
+		btDbvtTreeCollider	collider(this);
+		if(m_deferedcollide)
+		{
+			SPC(m_profiling.m_fdcollide);
+			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[1].m_root,collider);
+		}
+		if(m_deferedcollide)
+		{
+			SPC(m_profiling.m_ddcollide);
+			m_sets[0].collideTTpersistentStack(m_sets[0].m_root,m_sets[0].m_root,collider);
+		}
+	}
+	/* clean up				*/ 
+	if(m_needcleanup)
+	{
+		SPC(m_profiling.m_cleanup);
+		btBroadphasePairArray&	pairs=m_paircache->getOverlappingPairArray();
+		if(pairs.size()>0)
+		{
+
+			int			ni=btMin(pairs.size(),btMax<int>(m_newpairs,(pairs.size()*m_cupdates)/100));
+			for(int i=0;i<ni;++i)
+			{
+				btBroadphasePair&	p=pairs[(m_cid+i)%pairs.size()];
+				btDbvtProxy*		pa=(btDbvtProxy*)p.m_pProxy0;
+				btDbvtProxy*		pb=(btDbvtProxy*)p.m_pProxy1;
+				if(!Intersect(pa->leaf->volume,pb->leaf->volume))
+				{
+#if DBVT_BP_SORTPAIRS
+					if(pa->m_uniqueId>pb->m_uniqueId) 
+						btSwap(pa,pb);
+#endif
+					m_paircache->removeOverlappingPair(pa,pb,dispatcher);
+					--ni;--i;
+				}
+			}
+			if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0;
+		}
+	}
+	++m_pid;
+	m_newpairs=1;
+	m_needcleanup=false;
+	if(m_updates_call>0)
+	{ m_updates_ratio=m_updates_done/(btScalar)m_updates_call; }
+	else
+	{ m_updates_ratio=0; }
+	m_updates_done/=2;
+	m_updates_call/=2;
+}
+
+//
+void							btDbvtBroadphase::optimize()
+{
+	m_sets[0].optimizeTopDown();
+	m_sets[1].optimizeTopDown();
+}
+
+//
+btOverlappingPairCache*			btDbvtBroadphase::getOverlappingPairCache()
+{
+	return(m_paircache);
+}
+
+//
+const btOverlappingPairCache*	btDbvtBroadphase::getOverlappingPairCache() const
+{
+	return(m_paircache);
+}
+
+//
+void							btDbvtBroadphase::getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+	ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds;
+
+	if(!m_sets[0].empty())
+		if(!m_sets[1].empty())	Merge(	m_sets[0].m_root->volume,
+			m_sets[1].m_root->volume,bounds);
+		else
+			bounds=m_sets[0].m_root->volume;
+	else if(!m_sets[1].empty())	bounds=m_sets[1].m_root->volume;
+	else
+		bounds=btDbvtVolume::FromCR(btVector3(0,0,0),0);
+	aabbMin=bounds.Mins();
+	aabbMax=bounds.Maxs();
+}
+
+void btDbvtBroadphase::resetPool(btDispatcher* dispatcher)
+{
+	
+	int totalObjects = m_sets[0].m_leaves + m_sets[1].m_leaves;
+	if (!totalObjects)
+	{
+		//reset internal dynamic tree data structures
+		m_sets[0].clear();
+		m_sets[1].clear();
+		
+		m_deferedcollide	=	false;
+		m_needcleanup		=	true;
+		m_stageCurrent		=	0;
+		m_fixedleft			=	0;
+		m_fupdates			=	1;
+		m_dupdates			=	0;
+		m_cupdates			=	10;
+		m_newpairs			=	1;
+		m_updates_call		=	0;
+		m_updates_done		=	0;
+		m_updates_ratio		=	0;
+		
+		m_gid				=	0;
+		m_pid				=	0;
+		m_cid				=	0;
+		for(int i=0;i<=STAGECOUNT;++i)
+		{
+			m_stageRoots[i]=0;
+		}
+	}
+}
+
+//
+void							btDbvtBroadphase::printStats()
+{}
+
+//
+#if DBVT_BP_ENABLE_BENCHMARK
+
+struct	btBroadphaseBenchmark
+{
+	struct	Experiment
+	{
+		const char*			name;
+		int					object_count;
+		int					update_count;
+		int					spawn_count;
+		int					iterations;
+		btScalar			speed;
+		btScalar			amplitude;
+	};
+	struct	Object
+	{
+		btVector3			center;
+		btVector3			extents;
+		btBroadphaseProxy*	proxy;
+		btScalar			time;
+		void				update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi)
+		{
+			time		+=	speed;
+			center[0]	=	btCos(time*(btScalar)2.17)*amplitude+
+				btSin(time)*amplitude/2;
+			center[1]	=	btCos(time*(btScalar)1.38)*amplitude+
+				btSin(time)*amplitude;
+			center[2]	=	btSin(time*(btScalar)0.777)*amplitude;
+			pbi->setAabb(proxy,center-extents,center+extents,0);
+		}
+	};
+	static int		UnsignedRand(int range=RAND_MAX-1)	{ return(rand()%(range+1)); }
+	static btScalar	UnitRand()							{ return(UnsignedRand(16384)/(btScalar)16384); }
+	static void		OutputTime(const char* name,btClock& c,unsigned count=0)
+	{
+		const unsigned long	us=c.getTimeMicroseconds();
+		const unsigned long	ms=(us+500)/1000;
+		const btScalar		sec=us/(btScalar)(1000*1000);
+		if(count>0)
+			printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec);
+		else
+			printf("%s : %u us (%u ms)\r\n",name,us,ms);
+	}
+};
+
+void							btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi)
+{
+	static const btBroadphaseBenchmark::Experiment		experiments[]=
+	{
+		{"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100},
+		/*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100},
+		{"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/
+	};
+	static const int										nexperiments=sizeof(experiments)/sizeof(experiments[0]);
+	btAlignedObjectArray<btBroadphaseBenchmark::Object*>	objects;
+	btClock													wallclock;
+	/* Begin			*/ 
+	for(int iexp=0;iexp<nexperiments;++iexp)
+	{
+		const btBroadphaseBenchmark::Experiment&	experiment=experiments[iexp];
+		const int									object_count=experiment.object_count;
+		const int									update_count=(object_count*experiment.update_count)/100;
+		const int									spawn_count=(object_count*experiment.spawn_count)/100;
+		const btScalar								speed=experiment.speed;	
+		const btScalar								amplitude=experiment.amplitude;
+		printf("Experiment #%u '%s':\r\n",iexp,experiment.name);
+		printf("\tObjects: %u\r\n",object_count);
+		printf("\tUpdate: %u\r\n",update_count);
+		printf("\tSpawn: %u\r\n",spawn_count);
+		printf("\tSpeed: %f\r\n",speed);
+		printf("\tAmplitude: %f\r\n",amplitude);
+		srand(180673);
+		/* Create objects	*/ 
+		wallclock.reset();
+		objects.reserve(object_count);
+		for(int i=0;i<object_count;++i)
+		{
+			btBroadphaseBenchmark::Object*	po=new btBroadphaseBenchmark::Object();
+			po->center[0]=btBroadphaseBenchmark::UnitRand()*50;
+			po->center[1]=btBroadphaseBenchmark::UnitRand()*50;
+			po->center[2]=btBroadphaseBenchmark::UnitRand()*50;
+			po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2;
+			po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2;
+			po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2;
+			po->time=btBroadphaseBenchmark::UnitRand()*2000;
+			po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0);
+			objects.push_back(po);
+		}
+		btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock);
+		/* First update		*/ 
+		wallclock.reset();
+		for(int i=0;i<objects.size();++i)
+		{
+			objects[i]->update(speed,amplitude,pbi);
+		}
+		btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock);
+		/* Updates			*/ 
+		wallclock.reset();
+		for(int i=0;i<experiment.iterations;++i)
+		{
+			for(int j=0;j<update_count;++j)
+			{				
+				objects[j]->update(speed,amplitude,pbi);
+			}
+			pbi->calculateOverlappingPairs(0);
+		}
+		btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations);
+		/* Clean up			*/ 
+		wallclock.reset();
+		for(int i=0;i<objects.size();++i)
+		{
+			pbi->destroyProxy(objects[i]->proxy,0);
+			delete objects[i];
+		}
+		objects.resize(0);
+		btBroadphaseBenchmark::OutputTime("\tRelease",wallclock);
+	}
+
+}
+#else
+void							btDbvtBroadphase::benchmark(btBroadphaseInterface*)
+{}
+#endif
+
+#if DBVT_BP_PROFILE
+#undef	SPC
+#endif
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
new file mode 100644
index 0000000..be2690f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h
@@ -0,0 +1,146 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btDbvtBroadphase implementation by Nathanael Presson
+#ifndef BT_DBVT_BROADPHASE_H
+#define BT_DBVT_BROADPHASE_H
+
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+
+//
+// Compile time config
+//
+
+#define	DBVT_BP_PROFILE					0
+//#define DBVT_BP_SORTPAIRS				1
+#define DBVT_BP_PREVENTFALSEUPDATE		0
+#define DBVT_BP_ACCURATESLEEPING		0
+#define DBVT_BP_ENABLE_BENCHMARK		0
+//#define DBVT_BP_MARGIN				(btScalar)0.05 //***ALEX*** NO MARGIN
+
+#if DBVT_BP_PROFILE
+#define	DBVT_BP_PROFILING_RATE	256
+#include "LinearMath/btQuickprof.h"
+#endif
+
+//
+// btDbvtProxy
+//
+struct btDbvtProxy : btBroadphaseProxy
+{
+	/* Fields		*/ 
+	//btDbvtAabbMm	aabb;
+	btDbvtNode*		leaf;
+	btDbvtProxy*	links[2];
+	int				stage;
+	/* ctor			*/ 
+	btDbvtProxy(const btVector3& aabbMin,const btVector3& aabbMax,void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) :
+	btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask)
+	{
+		links[0]=links[1]=0;
+	}
+};
+
+typedef btAlignedObjectArray<btDbvtProxy*>	btDbvtProxyArray;
+
+///The btDbvtBroadphase implements a broadphase using two dynamic AABB bounding volume hierarchies/trees (see btDbvt).
+///One tree is used for static/non-moving objects, and another tree is used for dynamic objects. Objects can move from one tree to the other.
+///This is a very fast broadphase, especially for very dynamic worlds where many objects are moving. Its insert/add and remove of objects is generally faster than the sweep and prune broadphases btAxisSweep3 and bt32BitAxisSweep3.
+struct	btDbvtBroadphase : btBroadphaseInterface
+{
+	/* Config		*/ 
+	enum	{
+		DYNAMIC_SET			=	0,	/* Dynamic set index	*/ 
+		FIXED_SET			=	1,	/* Fixed set index		*/ 
+		STAGECOUNT			=	2	/* Number of stages		*/ 
+	};
+	/* Fields		*/ 
+	btDbvt					m_sets[2];					// Dbvt sets
+	btDbvtProxy*			m_stageRoots[STAGECOUNT+1];	// Stages list
+	btOverlappingPairCache*	m_paircache;				// Pair cache
+	btScalar				m_prediction;				// Velocity prediction
+	int						m_stageCurrent;				// Current stage
+	int						m_fupdates;					// % of fixed updates per frame
+	int						m_dupdates;					// % of dynamic updates per frame
+	int						m_cupdates;					// % of cleanup updates per frame
+	int						m_newpairs;					// Number of pairs created
+	int						m_fixedleft;				// Fixed optimization left
+	unsigned				m_updates_call;				// Number of updates call
+	unsigned				m_updates_done;				// Number of updates done
+	btScalar				m_updates_ratio;			// m_updates_done/m_updates_call
+	int						m_pid;						// Parse id
+	int						m_cid;						// Cleanup index
+	int						m_gid;						// Gen id
+	bool					m_releasepaircache;			// Release pair cache on delete
+	bool					m_deferedcollide;			// Defere dynamic/static collision to collide call
+	bool					m_needcleanup;				// Need to run cleanup?
+#if DBVT_BP_PROFILE
+	btClock					m_clock;
+	struct	{
+		unsigned long		m_total;
+		unsigned long		m_ddcollide;
+		unsigned long		m_fdcollide;
+		unsigned long		m_cleanup;
+		unsigned long		m_jobcount;
+	}				m_profiling;
+#endif
+	/* Methods		*/ 
+	btDbvtBroadphase(btOverlappingPairCache* paircache=0);
+	~btDbvtBroadphase();
+	void							collide(btDispatcher* dispatcher);
+	void							optimize();
+	
+	/* btBroadphaseInterface Implementation	*/
+	btBroadphaseProxy*				createProxy(const btVector3& aabbMin,const btVector3& aabbMax,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,btDispatcher* dispatcher,void* multiSapProxy);
+	virtual void					destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void					setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* dispatcher);
+	virtual void					rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0), const btVector3& aabbMax = btVector3(0,0,0));
+	virtual void					aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+
+	virtual void					getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+	virtual	void					calculateOverlappingPairs(btDispatcher* dispatcher);
+	virtual	btOverlappingPairCache*	getOverlappingPairCache();
+	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const;
+	virtual	void					getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+	virtual	void					printStats();
+
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher);
+
+	void	performDeferredRemoval(btDispatcher* dispatcher);
+	
+	void	setVelocityPrediction(btScalar prediction)
+	{
+		m_prediction = prediction;
+	}
+	btScalar getVelocityPrediction() const
+	{
+		return m_prediction;
+	}
+
+	///this setAabbForceUpdate is similar to setAabb but always forces the aabb update. 
+	///it is not part of the btBroadphaseInterface but specific to btDbvtBroadphase.
+	///it bypasses certain optimizations that prevent aabb updates (when the aabb shrinks), see
+	///http://code.google.com/p/bullet/issues/detail?id=223
+	void							setAabbForceUpdate(		btBroadphaseProxy* absproxy,const btVector3& aabbMin,const btVector3& aabbMax,btDispatcher* /*dispatcher*/);
+
+	static void						benchmark(btBroadphaseInterface*);
+
+
+};
+
+#endif
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
new file mode 100644
index 0000000..2076822
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.cpp
@@ -0,0 +1,22 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDispatcher.h"
+
+btDispatcher::~btDispatcher()
+{
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
new file mode 100644
index 0000000..8ded000
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btDispatcher.h
@@ -0,0 +1,108 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _DISPATCHER_H
+#define _DISPATCHER_H
+
+#include "LinearMath/btScalar.h"
+
+class btCollisionAlgorithm;
+struct btBroadphaseProxy;
+class btRigidBody;
+class	btCollisionObject;
+class btOverlappingPairCache;
+
+
+class btPersistentManifold;
+class btStackAlloc;
+
+struct btDispatcherInfo
+{
+	enum DispatchFunc
+	{
+		DISPATCH_DISCRETE = 1,
+		DISPATCH_CONTINUOUS
+	};
+	btDispatcherInfo()
+		:m_timeStep(btScalar(0.)),
+		m_stepCount(0),
+		m_dispatchFunc(DISPATCH_DISCRETE),
+		m_timeOfImpact(btScalar(1.)),
+		m_useContinuous(false),
+		m_debugDraw(0),
+		m_enableSatConvex(false),
+		m_enableSPU(true),
+		m_useEpa(true),
+		m_allowedCcdPenetration(btScalar(0.04)),
+		m_useConvexConservativeDistanceUtil(false),
+		m_convexConservativeDistanceThreshold(0.0f),
+		m_convexMaxDistanceUseCPT(false),
+		m_stackAllocator(0)
+	{
+
+	}
+	btScalar	m_timeStep;
+	int			m_stepCount;
+	int			m_dispatchFunc;
+	mutable btScalar	m_timeOfImpact;
+	bool		m_useContinuous;
+	class btIDebugDraw*	m_debugDraw;
+	bool		m_enableSatConvex;
+	bool		m_enableSPU;
+	bool		m_useEpa;
+	btScalar	m_allowedCcdPenetration;
+	bool		m_useConvexConservativeDistanceUtil;
+	btScalar	m_convexConservativeDistanceThreshold;
+	bool		m_convexMaxDistanceUseCPT;
+	btStackAlloc*	m_stackAllocator;
+};
+
+///The btDispatcher interface class can be used in combination with broadphase to dispatch calculations for overlapping pairs.
+///For example for pairwise collision detection, calculating contact points stored in btPersistentManifold or user callbacks (game logic).
+class btDispatcher
+{
+
+
+public:
+	virtual ~btDispatcher() ;
+
+	virtual btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold=0) = 0;
+
+	virtual btPersistentManifold*	getNewManifold(void* body0,void* body1)=0;
+
+	virtual void releaseManifold(btPersistentManifold* manifold)=0;
+
+	virtual void clearManifold(btPersistentManifold* manifold)=0;
+
+	virtual bool	needsCollision(btCollisionObject* body0,btCollisionObject* body1) = 0;
+
+	virtual bool	needsResponse(btCollisionObject* body0,btCollisionObject* body1)=0;
+
+	virtual void	dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher)  =0;
+
+	virtual int getNumManifolds() const = 0;
+
+	virtual btPersistentManifold* getManifoldByIndexInternal(int index) = 0;
+
+	virtual	btPersistentManifold**	getInternalManifoldPointer() = 0;
+
+	virtual	void* allocateCollisionAlgorithm(int size)  = 0;
+
+	virtual	void freeCollisionAlgorithm(void* ptr) = 0;
+
+};
+
+
+#endif //_DISPATCHER_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
new file mode 100644
index 0000000..6712f52
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.cpp
@@ -0,0 +1,489 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMultiSapBroadphase.h"
+
+#include "btSimpleBroadphase.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btQuantizedBvh.h"
+
+///	btSapBroadphaseArray	m_sapBroadphases;
+
+///	btOverlappingPairCache*	m_overlappingPairs;
+extern int gOverlappingPairs;
+
+/*
+class btMultiSapSortedOverlappingPairCache : public btSortedOverlappingPairCache
+{
+public:
+
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+	{
+		return btSortedOverlappingPairCache::addOverlappingPair((btBroadphaseProxy*)proxy0->m_multiSapParentProxy,(btBroadphaseProxy*)proxy1->m_multiSapParentProxy);
+	}
+};
+
+*/
+
+btMultiSapBroadphase::btMultiSapBroadphase(int /*maxProxies*/,btOverlappingPairCache* pairCache)
+:m_overlappingPairs(pairCache),
+m_optimizedAabbTree(0),
+m_ownsPairCache(false),
+m_invalidPair(0)
+{
+	if (!m_overlappingPairs)
+	{
+		m_ownsPairCache = true;
+		void* mem = btAlignedAlloc(sizeof(btSortedOverlappingPairCache),16);
+		m_overlappingPairs = new (mem)btSortedOverlappingPairCache();
+	}
+
+	struct btMultiSapOverlapFilterCallback : public btOverlapFilterCallback
+	{
+		virtual ~btMultiSapOverlapFilterCallback()
+		{}
+		// return true when pairs need collision
+		virtual bool	needBroadphaseCollision(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1) const
+		{
+			btBroadphaseProxy* multiProxy0 = (btBroadphaseProxy*)childProxy0->m_multiSapParentProxy;
+			btBroadphaseProxy* multiProxy1 = (btBroadphaseProxy*)childProxy1->m_multiSapParentProxy;
+			
+			bool collides = (multiProxy0->m_collisionFilterGroup & multiProxy1->m_collisionFilterMask) != 0;
+			collides = collides && (multiProxy1->m_collisionFilterGroup & multiProxy0->m_collisionFilterMask);
+	
+			return collides;
+		}
+	};
+
+	void* mem = btAlignedAlloc(sizeof(btMultiSapOverlapFilterCallback),16);
+	m_filterCallback = new (mem)btMultiSapOverlapFilterCallback();
+
+	m_overlappingPairs->setOverlapFilterCallback(m_filterCallback);
+//	mem = btAlignedAlloc(sizeof(btSimpleBroadphase),16);
+//	m_simpleBroadphase = new (mem) btSimpleBroadphase(maxProxies,m_overlappingPairs);
+}
+
+btMultiSapBroadphase::~btMultiSapBroadphase()
+{
+	if (m_ownsPairCache)
+	{
+		m_overlappingPairs->~btOverlappingPairCache();
+		btAlignedFree(m_overlappingPairs);
+	}
+}
+
+
+void	btMultiSapBroadphase::buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax)
+{
+	m_optimizedAabbTree = new btQuantizedBvh();
+	m_optimizedAabbTree->setQuantizationValues(bvhAabbMin,bvhAabbMax);
+	QuantizedNodeArray&	nodes = m_optimizedAabbTree->getLeafNodeArray();
+	for (int i=0;i<m_sapBroadphases.size();i++)
+	{
+		btQuantizedBvhNode node;
+		btVector3 aabbMin,aabbMax;
+		m_sapBroadphases[i]->getBroadphaseAabb(aabbMin,aabbMax);
+		m_optimizedAabbTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+		m_optimizedAabbTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+		int partId = 0;
+		node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | i;
+		nodes.push_back(node);
+	}
+	m_optimizedAabbTree->buildInternal();
+}
+
+btBroadphaseProxy*	btMultiSapBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* /*ignoreMe*/)
+{
+	//void* ignoreMe -> we could think of recursive multi-sap, if someone is interested
+
+	void* mem = btAlignedAlloc(sizeof(btMultiSapProxy),16);
+	btMultiSapProxy* proxy = new (mem)btMultiSapProxy(aabbMin,  aabbMax,shapeType,userPtr, collisionFilterGroup,collisionFilterMask);
+	m_multiSapProxies.push_back(proxy);
+
+	///this should deal with inserting/removal into child broadphases
+	setAabb(proxy,aabbMin,aabbMax,dispatcher);
+	return proxy;
+}
+
+void	btMultiSapBroadphase::destroyProxy(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+{
+	///not yet
+	btAssert(0);
+
+}
+
+
+void	btMultiSapBroadphase::addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*	childBroadphase)
+{
+	void* mem = btAlignedAlloc(sizeof(btBridgeProxy),16);
+	btBridgeProxy* bridgeProxyRef = new(mem) btBridgeProxy;
+	bridgeProxyRef->m_childProxy = childProxy;
+	bridgeProxyRef->m_childBroadphase = childBroadphase;
+	parentMultiSapProxy->m_bridgeProxies.push_back(bridgeProxyRef);
+}
+
+
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax);
+bool boxIsContainedWithinBox(const btVector3& amin,const btVector3& amax,const btVector3& bmin,const btVector3& bmax)
+{
+return
+amin.getX() >= bmin.getX() && amax.getX() <= bmax.getX() &&
+amin.getY() >= bmin.getY() && amax.getY() <= bmax.getY() &&
+amin.getZ() >= bmin.getZ() && amax.getZ() <= bmax.getZ();
+}
+
+
+
+
+
+
+void	btMultiSapBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
+	aabbMin = multiProxy->m_aabbMin;
+	aabbMax = multiProxy->m_aabbMax;
+}
+
+void	btMultiSapBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	for (int i=0;i<m_multiSapProxies.size();i++)
+	{
+		rayCallback.process(m_multiSapProxies[i]);
+	}
+}
+
+
+//#include <stdio.h>
+
+void	btMultiSapBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher)
+{
+	btMultiSapProxy* multiProxy = static_cast<btMultiSapProxy*>(proxy);
+	multiProxy->m_aabbMin = aabbMin;
+	multiProxy->m_aabbMax = aabbMax;
+	
+	
+//	bool fullyContained = false;
+//	bool alreadyInSimple = false;
+	
+
+
+	
+	struct MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btMultiSapBroadphase*	m_multiSap;
+		btMultiSapProxy*		m_multiProxy;
+		btDispatcher*			m_dispatcher;
+
+		MyNodeOverlapCallback(btMultiSapBroadphase* multiSap,btMultiSapProxy* multiProxy,btDispatcher* dispatcher)
+			:m_multiSap(multiSap),
+			m_multiProxy(multiProxy),
+			m_dispatcher(dispatcher)
+		{
+
+		}
+
+		virtual void processNode(int /*nodeSubPart*/, int broadphaseIndex)
+		{
+			btBroadphaseInterface* childBroadphase = m_multiSap->getBroadphaseArray()[broadphaseIndex];
+
+			int containingBroadphaseIndex = -1;
+			//already found?
+			for (int i=0;i<m_multiProxy->m_bridgeProxies.size();i++)
+			{
+
+				if (m_multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+				{
+					containingBroadphaseIndex = i;
+					break;
+				}
+			}
+			if (containingBroadphaseIndex<0)
+			{
+				//add it
+				btBroadphaseProxy* childProxy = childBroadphase->createProxy(m_multiProxy->m_aabbMin,m_multiProxy->m_aabbMax,m_multiProxy->m_shapeType,m_multiProxy->m_clientObject,m_multiProxy->m_collisionFilterGroup,m_multiProxy->m_collisionFilterMask, m_dispatcher,m_multiProxy);
+				m_multiSap->addToChildBroadphase(m_multiProxy,childProxy,childBroadphase);
+
+			}
+		}
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(this,multiProxy,dispatcher);
+
+
+
+	
+	if (m_optimizedAabbTree)
+		m_optimizedAabbTree->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+
+	int i;
+
+	for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+	{
+		btVector3 worldAabbMin,worldAabbMax;
+		multiProxy->m_bridgeProxies[i]->m_childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+		bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+		if (!overlapsBroadphase)
+		{
+			//remove it now
+			btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[i];
+
+			btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+			bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+			
+			multiProxy->m_bridgeProxies.swap( i,multiProxy->m_bridgeProxies.size()-1);
+			multiProxy->m_bridgeProxies.pop_back();
+
+		}
+	}
+
+
+	/*
+
+	if (1)
+	{
+
+		//find broadphase that contain this multiProxy
+		int numChildBroadphases = getBroadphaseArray().size();
+		for (int i=0;i<numChildBroadphases;i++)
+		{
+			btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+			btVector3 worldAabbMin,worldAabbMax;
+			childBroadphase->getBroadphaseAabb(worldAabbMin,worldAabbMax);
+			bool overlapsBroadphase = TestAabbAgainstAabb2(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+			
+		//	fullyContained = fullyContained || boxIsContainedWithinBox(worldAabbMin,worldAabbMax,multiProxy->m_aabbMin,multiProxy->m_aabbMax);
+			int containingBroadphaseIndex = -1;
+			
+			//if already contains this
+			
+			for (int i=0;i<multiProxy->m_bridgeProxies.size();i++)
+			{
+				if (multiProxy->m_bridgeProxies[i]->m_childBroadphase == childBroadphase)
+				{
+					containingBroadphaseIndex = i;
+				}
+				alreadyInSimple = alreadyInSimple || (multiProxy->m_bridgeProxies[i]->m_childBroadphase == m_simpleBroadphase);
+			}
+
+			if (overlapsBroadphase)
+			{
+				if (containingBroadphaseIndex<0)
+				{
+					btBroadphaseProxy* childProxy = childBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+					childProxy->m_multiSapParentProxy = multiProxy;
+					addToChildBroadphase(multiProxy,childProxy,childBroadphase);
+				}
+			} else
+			{
+				if (containingBroadphaseIndex>=0)
+				{
+					//remove
+					btBridgeProxy* bridgeProxy = multiProxy->m_bridgeProxies[containingBroadphaseIndex];
+
+					btBroadphaseProxy* childProxy = bridgeProxy->m_childProxy;
+					bridgeProxy->m_childBroadphase->destroyProxy(childProxy,dispatcher);
+					
+					multiProxy->m_bridgeProxies.swap( containingBroadphaseIndex,multiProxy->m_bridgeProxies.size()-1);
+					multiProxy->m_bridgeProxies.pop_back();
+				}
+			}
+		}
+
+
+		///If we are in no other child broadphase, stick the proxy in the global 'simple' broadphase (brute force)
+		///hopefully we don't end up with many entries here (can assert/provide feedback on stats)
+		if (0)//!multiProxy->m_bridgeProxies.size())
+		{
+			///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+			///this is needed to be able to calculate the aabb overlap
+			btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+			childProxy->m_multiSapParentProxy = multiProxy;
+			addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+		}
+	}
+
+	if (!multiProxy->m_bridgeProxies.size())
+	{
+		///we don't pass the userPtr but our multisap proxy. We need to patch this, before processing an actual collision
+		///this is needed to be able to calculate the aabb overlap
+		btBroadphaseProxy* childProxy = m_simpleBroadphase->createProxy(aabbMin,aabbMax,multiProxy->m_shapeType,multiProxy->m_clientObject,multiProxy->m_collisionFilterGroup,multiProxy->m_collisionFilterMask, dispatcher);
+		childProxy->m_multiSapParentProxy = multiProxy;
+		addToChildBroadphase(multiProxy,childProxy,m_simpleBroadphase);
+	}
+*/
+
+
+	//update
+	for ( i=0;i<multiProxy->m_bridgeProxies.size();i++)
+	{
+		btBridgeProxy* bridgeProxyRef = multiProxy->m_bridgeProxies[i];
+		bridgeProxyRef->m_childBroadphase->setAabb(bridgeProxyRef->m_childProxy,aabbMin,aabbMax,dispatcher);
+	}
+
+}
+bool stopUpdating=false;
+
+
+
+class btMultiSapBroadphasePairSortPredicate
+{
+	public:
+
+		bool operator() ( const btBroadphasePair& a1, const btBroadphasePair& b1 )
+		{
+				btMultiSapBroadphase::btMultiSapProxy* aProxy0 = a1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy0->m_multiSapParentProxy : 0;
+				btMultiSapBroadphase::btMultiSapProxy* aProxy1 = a1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)a1.m_pProxy1->m_multiSapParentProxy : 0;
+				btMultiSapBroadphase::btMultiSapProxy* bProxy0 = b1.m_pProxy0 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy0->m_multiSapParentProxy : 0;
+				btMultiSapBroadphase::btMultiSapProxy* bProxy1 = b1.m_pProxy1 ? (btMultiSapBroadphase::btMultiSapProxy*)b1.m_pProxy1->m_multiSapParentProxy : 0;
+
+				 return aProxy0 > bProxy0 || 
+					(aProxy0 == bProxy0 && aProxy1 > bProxy1) ||
+					(aProxy0 == bProxy0 && aProxy1 == bProxy1 && a1.m_algorithm > b1.m_algorithm); 
+		}
+};
+
+
+        ///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+void    btMultiSapBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+
+//	m_simpleBroadphase->calculateOverlappingPairs(dispatcher);
+
+	if (!stopUpdating && getOverlappingPairCache()->hasDeferredRemoval())
+	{
+	
+		btBroadphasePairArray&	overlappingPairArray = getOverlappingPairCache()->getOverlappingPairArray();
+
+	//	quicksort(overlappingPairArray,0,overlappingPairArray.size());
+
+		overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+		//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+	//	overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+
+		
+		int i;
+
+		btBroadphasePair previousPair;
+		previousPair.m_pProxy0 = 0;
+		previousPair.m_pProxy1 = 0;
+		previousPair.m_algorithm = 0;
+		
+		
+		for (i=0;i<overlappingPairArray.size();i++)
+		{
+		
+			btBroadphasePair& pair = overlappingPairArray[i];
+
+			btMultiSapProxy* aProxy0 = pair.m_pProxy0 ? (btMultiSapProxy*)pair.m_pProxy0->m_multiSapParentProxy : 0;
+			btMultiSapProxy* aProxy1 = pair.m_pProxy1 ? (btMultiSapProxy*)pair.m_pProxy1->m_multiSapParentProxy : 0;
+			btMultiSapProxy* bProxy0 = previousPair.m_pProxy0 ? (btMultiSapProxy*)previousPair.m_pProxy0->m_multiSapParentProxy : 0;
+			btMultiSapProxy* bProxy1 = previousPair.m_pProxy1 ? (btMultiSapProxy*)previousPair.m_pProxy1->m_multiSapParentProxy : 0;
+
+			bool isDuplicate = (aProxy0 == bProxy0) && (aProxy1 == bProxy1);
+			
+			previousPair = pair;
+
+			bool needsRemoval = false;
+
+			if (!isDuplicate)
+			{
+				bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+				if (hasOverlap)
+				{
+					needsRemoval = false;//callback->processOverlap(pair);
+				} else
+				{
+					needsRemoval = true;
+				}
+			} else
+			{
+				//remove duplicate
+				needsRemoval = true;
+				//should have no algorithm
+				btAssert(!pair.m_algorithm);
+			}
+			
+			if (needsRemoval)
+			{
+				getOverlappingPairCache()->cleanOverlappingPair(pair,dispatcher);
+
+		//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+		//		m_overlappingPairArray.pop_back();
+				pair.m_pProxy0 = 0;
+				pair.m_pProxy1 = 0;
+				m_invalidPair++;
+				gOverlappingPairs--;
+			} 
+			
+		}
+
+	///if you don't like to skip the invalid pairs in the array, execute following code:
+	#define CLEAN_INVALID_PAIRS 1
+	#ifdef CLEAN_INVALID_PAIRS
+
+		//perform a sort, to sort 'invalid' pairs to the end
+		//overlappingPairArray.heapSort(btMultiSapBroadphasePairSortPredicate());
+		overlappingPairArray.quickSort(btMultiSapBroadphasePairSortPredicate());
+
+		overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+		m_invalidPair = 0;
+	#endif//CLEAN_INVALID_PAIRS
+		
+		//printf("overlappingPairArray.size()=%d\n",overlappingPairArray.size());
+	}
+
+
+}
+
+
+bool	btMultiSapBroadphase::testAabbOverlap(btBroadphaseProxy* childProxy0,btBroadphaseProxy* childProxy1)
+{
+	btMultiSapProxy* multiSapProxy0 = (btMultiSapProxy*)childProxy0->m_multiSapParentProxy;
+		btMultiSapProxy* multiSapProxy1 = (btMultiSapProxy*)childProxy1->m_multiSapParentProxy;
+
+		return	TestAabbAgainstAabb2(multiSapProxy0->m_aabbMin,multiSapProxy0->m_aabbMax,
+			multiSapProxy1->m_aabbMin,multiSapProxy1->m_aabbMax);
+		
+}
+
+
+void	btMultiSapBroadphase::printStats()
+{
+/*	printf("---------------------------------\n");
+	
+		printf("btMultiSapBroadphase.h\n");
+		printf("numHandles = %d\n",m_multiSapProxies.size());
+			//find broadphase that contain this multiProxy
+		int numChildBroadphases = getBroadphaseArray().size();
+		for (int i=0;i<numChildBroadphases;i++)
+		{
+
+			btBroadphaseInterface* childBroadphase = getBroadphaseArray()[i];
+			childBroadphase->printStats();
+
+		}
+		*/
+
+}
+
+void btMultiSapBroadphase::resetPool(btDispatcher* dispatcher)
+{
+	// not yet
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
new file mode 100644
index 0000000..7bcfe6b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_MULTI_SAP_BROADPHASE
+#define BT_MULTI_SAP_BROADPHASE
+
+#include "btBroadphaseInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btOverlappingPairCache.h"
+
+
+class btBroadphaseInterface;
+class btSimpleBroadphase;
+
+
+typedef btAlignedObjectArray<btBroadphaseInterface*> btSapBroadphaseArray;
+
+///The btMultiSapBroadphase is a research project, not recommended to use in production. Use btAxisSweep3 or btDbvtBroadphase instead.
+///The btMultiSapBroadphase is a broadphase that contains multiple SAP broadphases.
+///The user can add SAP broadphases that cover the world. A btBroadphaseProxy can be in multiple child broadphases at the same time.
+///A btQuantizedBvh acceleration structures finds overlapping SAPs for each btBroadphaseProxy.
+///See http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=328
+///and http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1329
+class btMultiSapBroadphase :public btBroadphaseInterface
+{
+	btSapBroadphaseArray	m_sapBroadphases;
+	
+	btSimpleBroadphase*		m_simpleBroadphase;
+
+	btOverlappingPairCache*	m_overlappingPairs;
+
+	class btQuantizedBvh*			m_optimizedAabbTree;
+
+
+	bool					m_ownsPairCache;
+	
+	btOverlapFilterCallback*	m_filterCallback;
+
+	int			m_invalidPair;
+
+	struct	btBridgeProxy
+	{
+		btBroadphaseProxy*		m_childProxy;
+		btBroadphaseInterface*	m_childBroadphase;
+	};
+
+
+public:
+
+	struct	btMultiSapProxy	: public btBroadphaseProxy
+	{
+
+		///array with all the entries that this proxy belongs to
+		btAlignedObjectArray<btBridgeProxy*> m_bridgeProxies;
+		btVector3	m_aabbMin;
+		btVector3	m_aabbMax;
+
+		int	m_shapeType;
+
+/*		void*	m_userPtr;
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+*/
+		btMultiSapProxy(const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask)
+			:btBroadphaseProxy(aabbMin,aabbMax,userPtr,collisionFilterGroup,collisionFilterMask),
+			m_aabbMin(aabbMin),
+			m_aabbMax(aabbMax),
+			m_shapeType(shapeType)
+		{
+			m_multiSapParentProxy =this;
+		}
+
+		
+	};
+
+protected:
+
+
+	btAlignedObjectArray<btMultiSapProxy*> m_multiSapProxies;
+
+public:
+
+	btMultiSapBroadphase(int maxProxies = 16384,btOverlappingPairCache* pairCache=0);
+
+
+	btSapBroadphaseArray&	getBroadphaseArray()
+	{
+		return m_sapBroadphases;
+	}
+
+	const btSapBroadphaseArray&	getBroadphaseArray() const
+	{
+		return m_sapBroadphases;
+	}
+
+	virtual ~btMultiSapBroadphase();
+
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr, short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback,const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
+
+	void	addToChildBroadphase(btMultiSapProxy* parentMultiSapProxy, btBroadphaseProxy* childProxy, btBroadphaseInterface*	childBroadphase);
+
+	///calculateOverlappingPairs is optional: incremental algorithms (sweep and prune) might do it during the set aabb
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher);
+
+	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+	virtual	btOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_overlappingPairs;
+	}
+	virtual	const btOverlappingPairCache*	getOverlappingPairCache() const
+	{
+		return m_overlappingPairs;
+	}
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+		aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+	}
+
+	void	buildTree(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax);
+
+	virtual void	printStats();
+
+	void quicksort (btBroadphasePairArray& a, int lo, int hi);
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher);
+
+};
+
+#endif //BT_MULTI_SAP_BROADPHASE
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
new file mode 100644
index 0000000..041bbe0
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.cpp
@@ -0,0 +1,633 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btOverlappingPairCache.h"
+
+#include "btDispatcher.h"
+#include "btCollisionAlgorithm.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <stdio.h>
+
+int	gOverlappingPairs = 0;
+
+int gRemovePairs =0;
+int gAddedPairs =0;
+int gFindPairs =0;
+
+
+
+
+btHashedOverlappingPairCache::btHashedOverlappingPairCache():
+	m_overlapFilterCallback(0),
+	m_blockedForChanges(false),
+	m_ghostPairCallback(0)
+{
+	int initialAllocatedSize= 2;
+	m_overlappingPairArray.reserve(initialAllocatedSize);
+	growTables();
+}
+
+
+
+
+btHashedOverlappingPairCache::~btHashedOverlappingPairCache()
+{
+}
+
+
+
+void	btHashedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+	if (pair.m_algorithm)
+	{
+		{
+			pair.m_algorithm->~btCollisionAlgorithm();
+			dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+			pair.m_algorithm=0;
+		}
+	}
+}
+
+
+
+
+void	btHashedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	CleanPairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_cleanProxy;
+		btOverlappingPairCache*	m_pairCache;
+		btDispatcher* m_dispatcher;
+
+	public:
+		CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+			:m_cleanProxy(cleanProxy),
+			m_pairCache(pairCache),
+			m_dispatcher(dispatcher)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			if ((pair.m_pProxy0 == m_cleanProxy) ||
+				(pair.m_pProxy1 == m_cleanProxy))
+			{
+				m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+			}
+			return false;
+		}
+		
+	};
+
+	CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+	processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+
+
+void	btHashedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	RemovePairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_obsoleteProxy;
+
+	public:
+		RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+			:m_obsoleteProxy(obsoleteProxy)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+				(pair.m_pProxy1 == m_obsoleteProxy));
+		}
+		
+	};
+
+
+	RemovePairCallback removeCallback(proxy);
+
+	processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+
+
+
+
+btBroadphasePair* btHashedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+	gFindPairs++;
+	if(proxy0->m_uniqueId>proxy1->m_uniqueId) 
+		btSwap(proxy0,proxy1);
+	int proxyId1 = proxy0->getUid();
+	int proxyId2 = proxy1->getUid();
+
+	/*if (proxyId1 > proxyId2) 
+		btSwap(proxyId1, proxyId2);*/
+
+	int hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1), static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+	if (hash >= m_hashTable.size())
+	{
+		return NULL;
+	}
+
+	int index = m_hashTable[hash];
+	while (index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+	{
+		index = m_next[index];
+	}
+
+	if (index == BT_NULL_PAIR)
+	{
+		return NULL;
+	}
+
+	btAssert(index < m_overlappingPairArray.size());
+
+	return &m_overlappingPairArray[index];
+}
+
+//#include <stdio.h>
+
+void	btHashedOverlappingPairCache::growTables()
+{
+
+	int newCapacity = m_overlappingPairArray.capacity();
+
+	if (m_hashTable.size() < newCapacity)
+	{
+		//grow hashtable and next table
+		int curHashtableSize = m_hashTable.size();
+
+		m_hashTable.resize(newCapacity);
+		m_next.resize(newCapacity);
+
+
+		int i;
+
+		for (i= 0; i < newCapacity; ++i)
+		{
+			m_hashTable[i] = BT_NULL_PAIR;
+		}
+		for (i = 0; i < newCapacity; ++i)
+		{
+			m_next[i] = BT_NULL_PAIR;
+		}
+
+		for(i=0;i<curHashtableSize;i++)
+		{
+	
+			const btBroadphasePair& pair = m_overlappingPairArray[i];
+			int proxyId1 = pair.m_pProxy0->getUid();
+			int proxyId2 = pair.m_pProxy1->getUid();
+			/*if (proxyId1 > proxyId2) 
+				btSwap(proxyId1, proxyId2);*/
+			int	hashValue = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));	// New hash value with new mask
+			m_next[i] = m_hashTable[hashValue];
+			m_hashTable[hashValue] = i;
+		}
+
+
+	}
+}
+
+btBroadphasePair* btHashedOverlappingPairCache::internalAddPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1)
+{
+	if(proxy0->m_uniqueId>proxy1->m_uniqueId) 
+		btSwap(proxy0,proxy1);
+	int proxyId1 = proxy0->getUid();
+	int proxyId2 = proxy1->getUid();
+
+	/*if (proxyId1 > proxyId2) 
+		btSwap(proxyId1, proxyId2);*/
+
+	int	hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));	// New hash value with new mask
+
+
+	btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+	if (pair != NULL)
+	{
+		return pair;
+	}
+	/*for(int i=0;i<m_overlappingPairArray.size();++i)
+		{
+		if(	(m_overlappingPairArray[i].m_pProxy0==proxy0)&&
+			(m_overlappingPairArray[i].m_pProxy1==proxy1))
+			{
+			printf("Adding duplicated %u<>%u\r\n",proxyId1,proxyId2);
+			internalFindPair(proxy0, proxy1, hash);
+			}
+		}*/
+	int count = m_overlappingPairArray.size();
+	int oldCapacity = m_overlappingPairArray.capacity();
+	void* mem = &m_overlappingPairArray.expandNonInitializing();
+
+	//this is where we add an actual pair, so also call the 'ghost'
+	if (m_ghostPairCallback)
+		m_ghostPairCallback->addOverlappingPair(proxy0,proxy1);
+
+	int newCapacity = m_overlappingPairArray.capacity();
+
+	if (oldCapacity < newCapacity)
+	{
+		growTables();
+		//hash with new capacity
+		hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+	}
+	
+	pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+//	pair->m_pProxy0 = proxy0;
+//	pair->m_pProxy1 = proxy1;
+	pair->m_algorithm = 0;
+	pair->m_internalTmpValue = 0;
+	
+
+	m_next[count] = m_hashTable[hash];
+	m_hashTable[hash] = count;
+
+	return pair;
+}
+
+
+
+void* btHashedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+{
+	gRemovePairs++;
+	if(proxy0->m_uniqueId>proxy1->m_uniqueId) 
+		btSwap(proxy0,proxy1);
+	int proxyId1 = proxy0->getUid();
+	int proxyId2 = proxy1->getUid();
+
+	/*if (proxyId1 > proxyId2) 
+		btSwap(proxyId1, proxyId2);*/
+
+	int	hash = static_cast<int>(getHash(static_cast<unsigned int>(proxyId1),static_cast<unsigned int>(proxyId2)) & (m_overlappingPairArray.capacity()-1));
+
+	btBroadphasePair* pair = internalFindPair(proxy0, proxy1, hash);
+	if (pair == NULL)
+	{
+		return 0;
+	}
+
+	cleanOverlappingPair(*pair,dispatcher);
+
+	void* userData = pair->m_internalInfo1;
+
+	btAssert(pair->m_pProxy0->getUid() == proxyId1);
+	btAssert(pair->m_pProxy1->getUid() == proxyId2);
+
+	int pairIndex = int(pair - &m_overlappingPairArray[0]);
+	btAssert(pairIndex < m_overlappingPairArray.size());
+
+	// Remove the pair from the hash table.
+	int index = m_hashTable[hash];
+	btAssert(index != BT_NULL_PAIR);
+
+	int previous = BT_NULL_PAIR;
+	while (index != pairIndex)
+	{
+		previous = index;
+		index = m_next[index];
+	}
+
+	if (previous != BT_NULL_PAIR)
+	{
+		btAssert(m_next[previous] == pairIndex);
+		m_next[previous] = m_next[pairIndex];
+	}
+	else
+	{
+		m_hashTable[hash] = m_next[pairIndex];
+	}
+
+	// We now move the last pair into spot of the
+	// pair being removed. We need to fix the hash
+	// table indices to support the move.
+
+	int lastPairIndex = m_overlappingPairArray.size() - 1;
+
+	if (m_ghostPairCallback)
+		m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+
+	// If the removed pair is the last pair, we are done.
+	if (lastPairIndex == pairIndex)
+	{
+		m_overlappingPairArray.pop_back();
+		return userData;
+	}
+
+	// Remove the last pair from the hash table.
+	const btBroadphasePair* last = &m_overlappingPairArray[lastPairIndex];
+		/* missing swap here too, Nat. */ 
+	int lastHash = static_cast<int>(getHash(static_cast<unsigned int>(last->m_pProxy0->getUid()), static_cast<unsigned int>(last->m_pProxy1->getUid())) & (m_overlappingPairArray.capacity()-1));
+
+	index = m_hashTable[lastHash];
+	btAssert(index != BT_NULL_PAIR);
+
+	previous = BT_NULL_PAIR;
+	while (index != lastPairIndex)
+	{
+		previous = index;
+		index = m_next[index];
+	}
+
+	if (previous != BT_NULL_PAIR)
+	{
+		btAssert(m_next[previous] == lastPairIndex);
+		m_next[previous] = m_next[lastPairIndex];
+	}
+	else
+	{
+		m_hashTable[lastHash] = m_next[lastPairIndex];
+	}
+
+	// Copy the last pair into the remove pair's spot.
+	m_overlappingPairArray[pairIndex] = m_overlappingPairArray[lastPairIndex];
+
+	// Insert the last pair into the hash table
+	m_next[pairIndex] = m_hashTable[lastHash];
+	m_hashTable[lastHash] = pairIndex;
+
+	m_overlappingPairArray.pop_back();
+
+	return userData;
+}
+//#include <stdio.h>
+
+void	btHashedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+	int i;
+
+//	printf("m_overlappingPairArray.size()=%d\n",m_overlappingPairArray.size());
+	for (i=0;i<m_overlappingPairArray.size();)
+	{
+	
+		btBroadphasePair* pair = &m_overlappingPairArray[i];
+		if (callback->processOverlap(*pair))
+		{
+			removeOverlappingPair(pair->m_pProxy0,pair->m_pProxy1,dispatcher);
+
+			gOverlappingPairs--;
+		} else
+		{
+			i++;
+		}
+	}
+}
+
+void	btHashedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+	///need to keep hashmap in sync with pair address, so rebuild all
+	btBroadphasePairArray tmpPairs;
+	int i;
+	for (i=0;i<m_overlappingPairArray.size();i++)
+	{
+		tmpPairs.push_back(m_overlappingPairArray[i]);
+	}
+
+	for (i=0;i<tmpPairs.size();i++)
+	{
+		removeOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1,dispatcher);
+	}
+	
+	for (i = 0; i < m_next.size(); i++)
+	{
+		m_next[i] = BT_NULL_PAIR;
+	}
+
+	tmpPairs.quickSort(btBroadphasePairSortPredicate());
+
+	for (i=0;i<tmpPairs.size();i++)
+	{
+		addOverlappingPair(tmpPairs[i].m_pProxy0,tmpPairs[i].m_pProxy1);
+	}
+
+	
+}
+
+
+void*	btSortedOverlappingPairCache::removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1, btDispatcher* dispatcher )
+{
+	if (!hasDeferredRemoval())
+	{
+		btBroadphasePair findPair(*proxy0,*proxy1);
+
+		int findIndex = m_overlappingPairArray.findLinearSearch(findPair);
+		if (findIndex < m_overlappingPairArray.size())
+		{
+			gOverlappingPairs--;
+			btBroadphasePair& pair = m_overlappingPairArray[findIndex];
+			void* userData = pair.m_internalInfo1;
+			cleanOverlappingPair(pair,dispatcher);
+			if (m_ghostPairCallback)
+				m_ghostPairCallback->removeOverlappingPair(proxy0, proxy1,dispatcher);
+			
+			m_overlappingPairArray.swap(findIndex,m_overlappingPairArray.capacity()-1);
+			m_overlappingPairArray.pop_back();
+			return userData;
+		}
+	}
+
+	return 0;
+}
+
+
+
+
+
+
+
+
+btBroadphasePair*	btSortedOverlappingPairCache::addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	//don't add overlap with own
+	btAssert(proxy0 != proxy1);
+
+	if (!needsBroadphaseCollision(proxy0,proxy1))
+		return 0;
+	
+	void* mem = &m_overlappingPairArray.expandNonInitializing();
+	btBroadphasePair* pair = new (mem) btBroadphasePair(*proxy0,*proxy1);
+	
+	gOverlappingPairs++;
+	gAddedPairs++;
+	
+	if (m_ghostPairCallback)
+		m_ghostPairCallback->addOverlappingPair(proxy0, proxy1);
+	return pair;
+	
+}
+
+///this findPair becomes really slow. Either sort the list to speedup the query, or
+///use a different solution. It is mainly used for Removing overlapping pairs. Removal could be delayed.
+///we could keep a linked list in each proxy, and store pair in one of the proxies (with lowest memory address)
+///Also we can use a 2D bitmap, which can be useful for a future GPU implementation
+ btBroadphasePair*	btSortedOverlappingPairCache::findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	if (!needsBroadphaseCollision(proxy0,proxy1))
+		return 0;
+
+	btBroadphasePair tmpPair(*proxy0,*proxy1);
+	int findIndex = m_overlappingPairArray.findLinearSearch(tmpPair);
+
+	if (findIndex < m_overlappingPairArray.size())
+	{
+		//btAssert(it != m_overlappingPairSet.end());
+		 btBroadphasePair* pair = &m_overlappingPairArray[findIndex];
+		return pair;
+	}
+	return 0;
+}
+
+
+
+
+
+
+
+
+
+
+//#include <stdio.h>
+
+void	btSortedOverlappingPairCache::processAllOverlappingPairs(btOverlapCallback* callback,btDispatcher* dispatcher)
+{
+
+	int i;
+
+	for (i=0;i<m_overlappingPairArray.size();)
+	{
+	
+		btBroadphasePair* pair = &m_overlappingPairArray[i];
+		if (callback->processOverlap(*pair))
+		{
+			cleanOverlappingPair(*pair,dispatcher);
+			pair->m_pProxy0 = 0;
+			pair->m_pProxy1 = 0;
+			m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+			m_overlappingPairArray.pop_back();
+			gOverlappingPairs--;
+		} else
+		{
+			i++;
+		}
+	}
+}
+
+
+
+
+btSortedOverlappingPairCache::btSortedOverlappingPairCache():
+	m_blockedForChanges(false),
+	m_hasDeferredRemoval(true),
+	m_overlapFilterCallback(0),
+	m_ghostPairCallback(0)
+{
+	int initialAllocatedSize= 2;
+	m_overlappingPairArray.reserve(initialAllocatedSize);
+}
+
+btSortedOverlappingPairCache::~btSortedOverlappingPairCache()
+{
+}
+
+void	btSortedOverlappingPairCache::cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher)
+{
+	if (pair.m_algorithm)
+	{
+		{
+			pair.m_algorithm->~btCollisionAlgorithm();
+			dispatcher->freeCollisionAlgorithm(pair.m_algorithm);
+			pair.m_algorithm=0;
+			gRemovePairs--;
+		}
+	}
+}
+
+
+void	btSortedOverlappingPairCache::cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	CleanPairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_cleanProxy;
+		btOverlappingPairCache*	m_pairCache;
+		btDispatcher* m_dispatcher;
+
+	public:
+		CleanPairCallback(btBroadphaseProxy* cleanProxy,btOverlappingPairCache* pairCache,btDispatcher* dispatcher)
+			:m_cleanProxy(cleanProxy),
+			m_pairCache(pairCache),
+			m_dispatcher(dispatcher)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			if ((pair.m_pProxy0 == m_cleanProxy) ||
+				(pair.m_pProxy1 == m_cleanProxy))
+			{
+				m_pairCache->cleanOverlappingPair(pair,m_dispatcher);
+			}
+			return false;
+		}
+		
+	};
+
+	CleanPairCallback cleanPairs(proxy,this,dispatcher);
+
+	processAllOverlappingPairs(&cleanPairs,dispatcher);
+
+}
+
+
+void	btSortedOverlappingPairCache::removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher)
+{
+
+	class	RemovePairCallback : public btOverlapCallback
+	{
+		btBroadphaseProxy* m_obsoleteProxy;
+
+	public:
+		RemovePairCallback(btBroadphaseProxy* obsoleteProxy)
+			:m_obsoleteProxy(obsoleteProxy)
+		{
+		}
+		virtual	bool	processOverlap(btBroadphasePair& pair)
+		{
+			return ((pair.m_pProxy0 == m_obsoleteProxy) ||
+				(pair.m_pProxy1 == m_obsoleteProxy));
+		}
+		
+	};
+
+	RemovePairCallback removeCallback(proxy);
+
+	processAllOverlappingPairs(&removeCallback,dispatcher);
+}
+
+void	btSortedOverlappingPairCache::sortOverlappingPairs(btDispatcher* dispatcher)
+{
+	//should already be sorted
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
new file mode 100644
index 0000000..3945afb
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCache.h
@@ -0,0 +1,469 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OVERLAPPING_PAIR_CACHE_H
+#define OVERLAPPING_PAIR_CACHE_H
+
+
+#include "btBroadphaseInterface.h"
+#include "btBroadphaseProxy.h"
+#include "btOverlappingPairCallback.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+
+typedef btAlignedObjectArray<btBroadphasePair>	btBroadphasePairArray;
+
+struct	btOverlapCallback
+{
+	virtual ~btOverlapCallback()
+	{}
+	//return true for deletion of the pair
+	virtual bool	processOverlap(btBroadphasePair& pair) = 0;
+
+};
+
+struct btOverlapFilterCallback
+{
+	virtual ~btOverlapFilterCallback()
+	{}
+	// return true when pairs need collision
+	virtual bool	needBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const = 0;
+};
+
+
+
+
+
+
+
+extern int gRemovePairs;
+extern int gAddedPairs;
+extern int gFindPairs;
+
+const int BT_NULL_PAIR=0xffffffff;
+
+///The btOverlappingPairCache provides an interface for overlapping pair management (add, remove, storage), used by the btBroadphaseInterface broadphases.
+///The btHashedOverlappingPairCache and btSortedOverlappingPairCache classes are two implementations.
+class btOverlappingPairCache : public btOverlappingPairCallback
+{
+public:
+	virtual ~btOverlappingPairCache() {} // this is needed so we can get to the derived class destructor
+
+	virtual btBroadphasePair*	getOverlappingPairArrayPtr() = 0;
+	
+	virtual const btBroadphasePair*	getOverlappingPairArrayPtr() const = 0;
+
+	virtual btBroadphasePairArray&	getOverlappingPairArray() = 0;
+
+	virtual	void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher) = 0;
+
+	virtual int getNumOverlappingPairs() const = 0;
+
+	virtual void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher) = 0;
+
+	virtual	void setOverlapFilterCallback(btOverlapFilterCallback* callback) = 0;
+
+	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher) = 0;
+
+	virtual btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1) = 0;
+
+	virtual bool	hasDeferredRemoval() = 0;
+
+	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)=0;
+
+	virtual void	sortOverlappingPairs(btDispatcher* dispatcher) = 0;
+
+
+};
+
+/// Hash-space based Pair Cache, thanks to Erin Catto, Box2D, http://www.box2d.org, and Pierre Terdiman, Codercorner, http://codercorner.com
+class btHashedOverlappingPairCache : public btOverlappingPairCache
+{
+	btBroadphasePairArray	m_overlappingPairArray;
+	btOverlapFilterCallback* m_overlapFilterCallback;
+	bool		m_blockedForChanges;
+
+
+public:
+	btHashedOverlappingPairCache();
+	virtual ~btHashedOverlappingPairCache();
+
+	
+	void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+	
+	SIMD_FORCE_INLINE bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+	{
+		if (m_overlapFilterCallback)
+			return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+		bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+		collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+		
+		return collides;
+	}
+
+	// Add a pair and return the new pair. If the pair already exists,
+	// no new pair is created and the old one is returned.
+	virtual btBroadphasePair* 	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+	{
+		gAddedPairs++;
+
+		if (!needsBroadphaseCollision(proxy0,proxy1))
+			return 0;
+
+		return internalAddPair(proxy0,proxy1);
+	}
+
+	
+
+	void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+	
+	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+	virtual btBroadphasePair*	getOverlappingPairArrayPtr()
+	{
+		return &m_overlappingPairArray[0];
+	}
+
+	const btBroadphasePair*	getOverlappingPairArrayPtr() const
+	{
+		return &m_overlappingPairArray[0];
+	}
+
+	btBroadphasePairArray&	getOverlappingPairArray()
+	{
+		return m_overlappingPairArray;
+	}
+
+	const btBroadphasePairArray&	getOverlappingPairArray() const
+	{
+		return m_overlappingPairArray;
+	}
+
+	void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+
+
+
+	btBroadphasePair* findPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1);
+
+	int GetCount() const { return m_overlappingPairArray.size(); }
+//	btBroadphasePair* GetPairs() { return m_pairs; }
+
+	btOverlapFilterCallback* getOverlapFilterCallback()
+	{
+		return m_overlapFilterCallback;
+	}
+
+	void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+	{
+		m_overlapFilterCallback = callback;
+	}
+
+	int	getNumOverlappingPairs() const
+	{
+		return m_overlappingPairArray.size();
+	}
+private:
+	
+	btBroadphasePair* 	internalAddPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+	void	growTables();
+
+	SIMD_FORCE_INLINE bool equalsPair(const btBroadphasePair& pair, int proxyId1, int proxyId2)
+	{	
+		return pair.m_pProxy0->getUid() == proxyId1 && pair.m_pProxy1->getUid() == proxyId2;
+	}
+
+	/*
+	// Thomas Wang's hash, see: http://www.concentric.net/~Ttwang/tech/inthash.htm
+	// This assumes proxyId1 and proxyId2 are 16-bit.
+	SIMD_FORCE_INLINE int getHash(int proxyId1, int proxyId2)
+	{
+		int key = (proxyId2 << 16) | proxyId1;
+		key = ~key + (key << 15);
+		key = key ^ (key >> 12);
+		key = key + (key << 2);
+		key = key ^ (key >> 4);
+		key = key * 2057;
+		key = key ^ (key >> 16);
+		return key;
+	}
+	*/
+
+
+	
+	SIMD_FORCE_INLINE	unsigned int getHash(unsigned int proxyId1, unsigned int proxyId2)
+	{
+		int key = static_cast<int>(((unsigned int)proxyId1) | (((unsigned int)proxyId2) <<16));
+		// Thomas Wang's hash
+
+		key += ~(key << 15);
+		key ^=  (key >> 10);
+		key +=  (key << 3);
+		key ^=  (key >> 6);
+		key += ~(key << 11);
+		key ^=  (key >> 16);
+		return static_cast<unsigned int>(key);
+	}
+	
+
+
+
+
+	SIMD_FORCE_INLINE btBroadphasePair* internalFindPair(btBroadphaseProxy* proxy0, btBroadphaseProxy* proxy1, int hash)
+	{
+		int proxyId1 = proxy0->getUid();
+		int proxyId2 = proxy1->getUid();
+		#if 0 // wrong, 'equalsPair' use unsorted uids, copy-past devil striked again. Nat.
+		if (proxyId1 > proxyId2) 
+			btSwap(proxyId1, proxyId2);
+		#endif
+
+		int index = m_hashTable[hash];
+		
+		while( index != BT_NULL_PAIR && equalsPair(m_overlappingPairArray[index], proxyId1, proxyId2) == false)
+		{
+			index = m_next[index];
+		}
+
+		if ( index == BT_NULL_PAIR )
+		{
+			return NULL;
+		}
+
+		btAssert(index < m_overlappingPairArray.size());
+
+		return &m_overlappingPairArray[index];
+	}
+
+	virtual bool	hasDeferredRemoval()
+	{
+		return false;
+	}
+
+	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+	{
+		m_ghostPairCallback = ghostPairCallback;
+	}
+
+	virtual void	sortOverlappingPairs(btDispatcher* dispatcher);
+	
+
+protected:
+	
+	btAlignedObjectArray<int>	m_hashTable;
+	btAlignedObjectArray<int>	m_next;
+	btOverlappingPairCallback*	m_ghostPairCallback;
+	
+};
+
+
+
+
+///btSortedOverlappingPairCache maintains the objects with overlapping AABB
+///Typically managed by the Broadphase, Axis3Sweep or btSimpleBroadphase
+class	btSortedOverlappingPairCache : public btOverlappingPairCache
+{
+	protected:
+		//avoid brute-force finding all the time
+		btBroadphasePairArray	m_overlappingPairArray;
+
+		//during the dispatch, check that user doesn't destroy/create proxy
+		bool		m_blockedForChanges;
+
+		///by default, do the removal during the pair traversal
+		bool		m_hasDeferredRemoval;
+		
+		//if set, use the callback instead of the built in filter in needBroadphaseCollision
+		btOverlapFilterCallback* m_overlapFilterCallback;
+
+		btOverlappingPairCallback*	m_ghostPairCallback;
+
+	public:
+			
+		btSortedOverlappingPairCache();	
+		virtual ~btSortedOverlappingPairCache();
+
+		virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* dispatcher);
+
+		void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher);
+
+		void	cleanOverlappingPair(btBroadphasePair& pair,btDispatcher* dispatcher);
+		
+		btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+		btBroadphasePair*	findPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+			
+		
+		void	cleanProxyFromPairs(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+		void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+
+
+		inline bool needsBroadphaseCollision(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) const
+		{
+			if (m_overlapFilterCallback)
+				return m_overlapFilterCallback->needBroadphaseCollision(proxy0,proxy1);
+
+			bool collides = (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) != 0;
+			collides = collides && (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			
+			return collides;
+		}
+		
+		btBroadphasePairArray&	getOverlappingPairArray()
+		{
+			return m_overlappingPairArray;
+		}
+
+		const btBroadphasePairArray&	getOverlappingPairArray() const
+		{
+			return m_overlappingPairArray;
+		}
+
+		
+
+
+		btBroadphasePair*	getOverlappingPairArrayPtr()
+		{
+			return &m_overlappingPairArray[0];
+		}
+
+		const btBroadphasePair*	getOverlappingPairArrayPtr() const
+		{
+			return &m_overlappingPairArray[0];
+		}
+
+		int	getNumOverlappingPairs() const
+		{
+			return m_overlappingPairArray.size();
+		}
+		
+		btOverlapFilterCallback* getOverlapFilterCallback()
+		{
+			return m_overlapFilterCallback;
+		}
+
+		void setOverlapFilterCallback(btOverlapFilterCallback* callback)
+		{
+			m_overlapFilterCallback = callback;
+		}
+
+		virtual bool	hasDeferredRemoval()
+		{
+			return m_hasDeferredRemoval;
+		}
+
+		virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* ghostPairCallback)
+		{
+			m_ghostPairCallback = ghostPairCallback;
+		}
+
+		virtual void	sortOverlappingPairs(btDispatcher* dispatcher);
+		
+
+};
+
+
+
+///btNullPairCache skips add/removal of overlapping pairs. Userful for benchmarking and unit testing.
+class btNullPairCache : public btOverlappingPairCache
+{
+
+	btBroadphasePairArray	m_overlappingPairArray;
+
+public:
+
+	virtual btBroadphasePair*	getOverlappingPairArrayPtr()
+	{
+		return &m_overlappingPairArray[0];
+	}
+	const btBroadphasePair*	getOverlappingPairArrayPtr() const
+	{
+		return &m_overlappingPairArray[0];
+	}
+	btBroadphasePairArray&	getOverlappingPairArray()
+	{
+		return m_overlappingPairArray;
+	}
+	
+	virtual	void	cleanOverlappingPair(btBroadphasePair& /*pair*/,btDispatcher* /*dispatcher*/)
+	{
+
+	}
+
+	virtual int getNumOverlappingPairs() const
+	{
+		return 0;
+	}
+
+	virtual void	cleanProxyFromPairs(btBroadphaseProxy* /*proxy*/,btDispatcher* /*dispatcher*/)
+	{
+
+	}
+
+	virtual	void setOverlapFilterCallback(btOverlapFilterCallback* /*callback*/)
+	{
+	}
+
+	virtual void	processAllOverlappingPairs(btOverlapCallback*,btDispatcher* /*dispatcher*/)
+	{
+	}
+
+	virtual btBroadphasePair* findPair(btBroadphaseProxy* /*proxy0*/, btBroadphaseProxy* /*proxy1*/)
+	{
+		return 0;
+	}
+
+	virtual bool	hasDeferredRemoval()
+	{
+		return true;
+	}
+
+	virtual	void	setInternalGhostPairCallback(btOverlappingPairCallback* /* ghostPairCallback */)
+	{
+
+	}
+
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/)
+	{
+		return 0;
+	}
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* /*proxy0*/,btBroadphaseProxy* /*proxy1*/,btDispatcher* /*dispatcher*/)
+	{
+		return 0;
+	}
+
+	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+	{
+	}
+	
+	virtual void	sortOverlappingPairs(btDispatcher* dispatcher)
+	{
+        (void) dispatcher;
+	}
+
+
+};
+
+
+#endif //OVERLAPPING_PAIR_CACHE_H
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
new file mode 100644
index 0000000..9c7b6f8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h
@@ -0,0 +1,40 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OVERLAPPING_PAIR_CALLBACK_H
+#define OVERLAPPING_PAIR_CALLBACK_H
+
+class btDispatcher;
+struct  btBroadphasePair;
+
+///The btOverlappingPairCallback class is an additional optional broadphase user callback for adding/removing overlapping pairs, similar interface to btOverlappingPairCache.
+class btOverlappingPairCallback
+{
+public:
+	virtual ~btOverlappingPairCallback()
+	{
+
+	}
+	
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1) = 0;
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher) = 0;
+
+	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,btDispatcher* dispatcher) = 0;
+
+};
+
+#endif //OVERLAPPING_PAIR_CALLBACK_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
new file mode 100644
index 0000000..c911435
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.cpp
@@ -0,0 +1,1375 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btQuantizedBvh.h"
+
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+#define RAYAABB2
+
+btQuantizedBvh::btQuantizedBvh() : 
+					m_bulletVersion(BT_BULLET_VERSION),
+					m_useQuantization(false), 
+					//m_traversalMode(TRAVERSAL_STACKLESS_CACHE_FRIENDLY)
+					m_traversalMode(TRAVERSAL_STACKLESS)
+					//m_traversalMode(TRAVERSAL_RECURSIVE)
+					,m_subtreeHeaderCount(0) //PCK: add this line
+{
+	m_bvhAabbMin.setValue(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY);
+	m_bvhAabbMax.setValue(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY);
+}
+
+
+
+
+
+void btQuantizedBvh::buildInternal()
+{
+	///assumes that caller filled in the m_quantizedLeafNodes
+	m_useQuantization = true;
+	int numLeafNodes = 0;
+	
+	if (m_useQuantization)
+	{
+		//now we have an array of leafnodes in m_leafNodes
+		numLeafNodes = m_quantizedLeafNodes.size();
+
+		m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+	}
+
+	m_curNodeIndex = 0;
+
+	buildTree(0,numLeafNodes);
+
+	///if the entire tree is small then subtree size, we need to create a header info for the tree
+	if(m_useQuantization && !m_SubtreeHeaders.size())
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+		subtree.m_rootNodeIndex = 0;
+		subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+	}
+
+	//PCK: update the copy of the size
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+	//PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+	m_quantizedLeafNodes.clear();
+	m_leafNodes.clear();
+}
+
+
+
+///just for debugging, to visualize the individual patches/subtrees
+#ifdef DEBUG_PATCH_COLORS
+btVector3 color[4]=
+{
+	btVector3(1,0,0),
+	btVector3(0,1,0),
+	btVector3(0,0,1),
+	btVector3(0,1,1)
+};
+#endif //DEBUG_PATCH_COLORS
+
+
+
+void	btQuantizedBvh::setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin)
+{
+	//enlarge the AABB to avoid division by zero when initializing the quantization values
+	btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+	m_bvhAabbMin = bvhAabbMin - clampValue;
+	m_bvhAabbMax = bvhAabbMax + clampValue;
+	btVector3 aabbSize = m_bvhAabbMax - m_bvhAabbMin;
+	m_bvhQuantization = btVector3(btScalar(65533.0),btScalar(65533.0),btScalar(65533.0)) / aabbSize;
+	m_useQuantization = true;
+}
+
+
+
+
+btQuantizedBvh::~btQuantizedBvh()
+{
+}
+
+#ifdef DEBUG_TREE_BUILDING
+int gStackDepth = 0;
+int gMaxStackDepth = 0;
+#endif //DEBUG_TREE_BUILDING
+
+void	btQuantizedBvh::buildTree	(int startIndex,int endIndex)
+{
+#ifdef DEBUG_TREE_BUILDING
+	gStackDepth++;
+	if (gStackDepth > gMaxStackDepth)
+		gMaxStackDepth = gStackDepth;
+#endif //DEBUG_TREE_BUILDING
+
+
+	int splitAxis, splitIndex, i;
+	int numIndices =endIndex-startIndex;
+	int curIndex = m_curNodeIndex;
+
+	btAssert(numIndices>0);
+
+	if (numIndices==1)
+	{
+#ifdef DEBUG_TREE_BUILDING
+		gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+		
+		assignInternalNodeFromLeafNode(m_curNodeIndex,startIndex);
+
+		m_curNodeIndex++;
+		return;	
+	}
+	//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+	
+	splitAxis = calcSplittingAxis(startIndex,endIndex);
+
+	splitIndex = sortAndCalcSplittingIndex(startIndex,endIndex,splitAxis);
+
+	int internalNodeIndex = m_curNodeIndex;
+	
+	//set the min aabb to 'inf' or a max value, and set the max aabb to a -inf/minimum value.
+	//the aabb will be expanded during buildTree/mergeInternalNodeAabb with actual node values
+	setInternalNodeAabbMin(m_curNodeIndex,m_bvhAabbMax);//can't use btVector3(SIMD_INFINITY,SIMD_INFINITY,SIMD_INFINITY)) because of quantization
+	setInternalNodeAabbMax(m_curNodeIndex,m_bvhAabbMin);//can't use btVector3(-SIMD_INFINITY,-SIMD_INFINITY,-SIMD_INFINITY)) because of quantization
+	
+	
+	for (i=startIndex;i<endIndex;i++)
+	{
+		mergeInternalNodeAabb(m_curNodeIndex,getAabbMin(i),getAabbMax(i));
+	}
+
+	m_curNodeIndex++;
+	
+
+	//internalNode->m_escapeIndex;
+	
+	int leftChildNodexIndex = m_curNodeIndex;
+
+	//build left child tree
+	buildTree(startIndex,splitIndex);
+
+	int rightChildNodexIndex = m_curNodeIndex;
+	//build right child tree
+	buildTree(splitIndex,endIndex);
+
+#ifdef DEBUG_TREE_BUILDING
+	gStackDepth--;
+#endif //DEBUG_TREE_BUILDING
+
+	int escapeIndex = m_curNodeIndex - curIndex;
+
+	if (m_useQuantization)
+	{
+		//escapeIndex is the number of nodes of this subtree
+		const int sizeQuantizedNode =sizeof(btQuantizedBvhNode);
+		const int treeSizeInBytes = escapeIndex * sizeQuantizedNode;
+		if (treeSizeInBytes > MAX_SUBTREE_SIZE_IN_BYTES)
+		{
+			updateSubtreeHeaders(leftChildNodexIndex,rightChildNodexIndex);
+		}
+	} else
+	{
+
+	}
+
+	setInternalNodeEscapeIndex(internalNodeIndex,escapeIndex);
+
+}
+
+void	btQuantizedBvh::updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex)
+{
+	btAssert(m_useQuantization);
+
+	btQuantizedBvhNode& leftChildNode = m_quantizedContiguousNodes[leftChildNodexIndex];
+	int leftSubTreeSize = leftChildNode.isLeafNode() ? 1 : leftChildNode.getEscapeIndex();
+	int leftSubTreeSizeInBytes =  leftSubTreeSize * static_cast<int>(sizeof(btQuantizedBvhNode));
+	
+	btQuantizedBvhNode& rightChildNode = m_quantizedContiguousNodes[rightChildNodexIndex];
+	int rightSubTreeSize = rightChildNode.isLeafNode() ? 1 : rightChildNode.getEscapeIndex();
+	int rightSubTreeSizeInBytes =  rightSubTreeSize *  static_cast<int>(sizeof(btQuantizedBvhNode));
+
+	if(leftSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(leftChildNode);
+		subtree.m_rootNodeIndex = leftChildNodexIndex;
+		subtree.m_subtreeSize = leftSubTreeSize;
+	}
+
+	if(rightSubTreeSizeInBytes <= MAX_SUBTREE_SIZE_IN_BYTES)
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(rightChildNode);
+		subtree.m_rootNodeIndex = rightChildNodexIndex;
+		subtree.m_subtreeSize = rightSubTreeSize;
+	}
+
+	//PCK: update the copy of the size
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+}
+
+
+int	btQuantizedBvh::sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis)
+{
+	int i;
+	int splitIndex =startIndex;
+	int numIndices = endIndex - startIndex;
+	btScalar splitValue;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+	
+	splitValue = means[splitAxis];
+	
+	//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		if (center[splitAxis] > splitValue)
+		{
+			//swap
+			swapLeafNodes(i,splitIndex);
+			splitIndex++;
+		}
+	}
+
+	//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+	//otherwise the tree-building might fail due to stack-overflows in certain cases.
+	//unbalanced1 is unsafe: it can cause stack overflows
+	//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+	//unbalanced2 should work too: always use center (perfect balanced trees)	
+	//bool unbalanced2 = true;
+
+	//this should be safe too:
+	int rangeBalancedIndices = numIndices/3;
+	bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+	
+	if (unbalanced)
+	{
+		splitIndex = startIndex+ (numIndices>>1);
+	}
+
+	bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex));
+	(void)unbal;
+	btAssert(!unbal);
+
+	return splitIndex;
+}
+
+
+int	btQuantizedBvh::calcSplittingAxis(int startIndex,int endIndex)
+{
+	int i;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+	int numIndices = endIndex-startIndex;
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+		
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(getAabbMax(i)+getAabbMin(i));
+		btVector3 diff2 = center-means;
+		diff2 = diff2 * diff2;
+		variance += diff2;
+	}
+	variance *= (btScalar(1.)/	((btScalar)numIndices-1)	);
+	
+	return variance.maxAxis();
+}
+
+
+
+void	btQuantizedBvh::reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	//either choose recursive traversal (walkTree) or stackless (walkStacklessTree)
+
+	if (m_useQuantization)
+	{
+		///quantize query AABB
+		unsigned short int quantizedQueryAabbMin[3];
+		unsigned short int quantizedQueryAabbMax[3];
+		quantizeWithClamp(quantizedQueryAabbMin,aabbMin,0);
+		quantizeWithClamp(quantizedQueryAabbMax,aabbMax,1);
+
+		switch (m_traversalMode)
+		{
+		case TRAVERSAL_STACKLESS:
+				walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,0,m_curNodeIndex);
+			break;
+		case TRAVERSAL_STACKLESS_CACHE_FRIENDLY:
+				walkStacklessQuantizedTreeCacheFriendly(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+			break;
+		case TRAVERSAL_RECURSIVE:
+			{
+				const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[0];
+				walkRecursiveQuantizedTreeAgainstQueryAabb(rootNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+			}
+			break;
+		default:
+			//unsupported
+			btAssert(0);
+		}
+	} else
+	{
+		walkStacklessTree(nodeCallback,aabbMin,aabbMax);
+	}
+}
+
+
+int maxIterations = 0;
+
+
+void	btQuantizedBvh::walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	btAssert(!m_useQuantization);
+
+	const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+	int escapeIndex, curIndex = 0;
+	int walkIterations = 0;
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap;
+
+	while (curIndex < m_curNodeIndex)
+	{
+		//catch bugs in tree data
+		btAssert (walkIterations < m_curNodeIndex);
+
+		walkIterations++;
+		aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+		isLeafNode = rootNode->m_escapeIndex == -1;
+		
+		//PCK: unsigned instead of bool
+		if (isLeafNode && (aabbOverlap != 0))
+		{
+			nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+		} 
+		
+		//PCK: unsigned instead of bool
+		if ((aabbOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->m_escapeIndex;
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+/*
+///this was the original recursive traversal, before we optimized towards stackless traversal
+void	btQuantizedBvh::walkTree(btOptimizedBvhNode* rootNode,btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	bool isLeafNode, aabbOverlap = TestAabbAgainstAabb2(aabbMin,aabbMax,rootNode->m_aabbMin,rootNode->m_aabbMax);
+	if (aabbOverlap)
+	{
+		isLeafNode = (!rootNode->m_leftChild && !rootNode->m_rightChild);
+		if (isLeafNode)
+		{
+			nodeCallback->processNode(rootNode);
+		} else
+		{
+			walkTree(rootNode->m_leftChild,nodeCallback,aabbMin,aabbMax);
+			walkTree(rootNode->m_rightChild,nodeCallback,aabbMin,aabbMax);
+		}
+	}
+
+}
+*/
+
+void btQuantizedBvh::walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+	btAssert(m_useQuantization);
+	
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap;
+
+	//PCK: unsigned instead of bool
+	aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,currentNode->m_quantizedAabbMin,currentNode->m_quantizedAabbMax);
+	isLeafNode = currentNode->isLeafNode();
+		
+	//PCK: unsigned instead of bool
+	if (aabbOverlap != 0)
+	{
+		if (isLeafNode)
+		{
+			nodeCallback->processNode(currentNode->getPartId(),currentNode->getTriangleIndex());
+		} else
+		{
+			//process left and right children
+			const btQuantizedBvhNode* leftChildNode = currentNode+1;
+			walkRecursiveQuantizedTreeAgainstQueryAabb(leftChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+
+			const btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? leftChildNode+1:leftChildNode+leftChildNode->getEscapeIndex();
+			walkRecursiveQuantizedTreeAgainstQueryAabb(rightChildNode,nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax);
+		}
+	}		
+}
+
+
+
+void	btQuantizedBvh::walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+	btAssert(!m_useQuantization);
+
+	const btOptimizedBvhNode* rootNode = &m_contiguousNodes[0];
+	int escapeIndex, curIndex = 0;
+	int walkIterations = 0;
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap=0;
+	unsigned rayBoxOverlap=0;
+	btScalar lambda_max = 1.0;
+	
+		/* Quick pruning by quantized box */
+	btVector3 rayAabbMin = raySource;
+	btVector3 rayAabbMax = raySource;
+	rayAabbMin.setMin(rayTarget);
+	rayAabbMax.setMax(rayTarget);
+
+	/* Add box cast extents to bounding box */
+	rayAabbMin += aabbMin;
+	rayAabbMax += aabbMax;
+
+#ifdef RAYAABB2
+	btVector3 rayDir = (rayTarget-raySource);
+	rayDir.normalize ();
+	lambda_max = rayDir.dot(rayTarget-raySource);
+	///what about division by zero? --> just set rayDirection[i] to 1.0
+	btVector3 rayDirectionInverse;
+	rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+	rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+	rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+	unsigned int sign[3] = { rayDirectionInverse[0] < 0.0, rayDirectionInverse[1] < 0.0, rayDirectionInverse[2] < 0.0};
+#endif
+
+	btVector3 bounds[2];
+
+	while (curIndex < m_curNodeIndex)
+	{
+		btScalar param = 1.0;
+		//catch bugs in tree data
+		btAssert (walkIterations < m_curNodeIndex);
+
+		walkIterations++;
+
+		bounds[0] = rootNode->m_aabbMinOrg;
+		bounds[1] = rootNode->m_aabbMaxOrg;
+		/* Add box cast extents */
+		bounds[0] -= aabbMax;
+		bounds[1] -= aabbMin;
+
+		aabbOverlap = TestAabbAgainstAabb2(rayAabbMin,rayAabbMax,rootNode->m_aabbMinOrg,rootNode->m_aabbMaxOrg);
+		//perhaps profile if it is worth doing the aabbOverlap test first
+
+#ifdef RAYAABB2
+			///careful with this check: need to check division by zero (above) and fix the unQuantize method
+			///thanks Joerg/hiker for the reproduction case!
+			///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+		rayBoxOverlap = aabbOverlap ? btRayAabb2 (raySource, rayDirectionInverse, sign, bounds, param, 0.0f, lambda_max) : false;
+
+#else
+		btVector3 normal;
+		rayBoxOverlap = btRayAabb(raySource, rayTarget,bounds[0],bounds[1],param, normal);
+#endif
+
+		isLeafNode = rootNode->m_escapeIndex == -1;
+		
+		//PCK: unsigned instead of bool
+		if (isLeafNode && (rayBoxOverlap != 0))
+		{
+			nodeCallback->processNode(rootNode->m_subPart,rootNode->m_triangleIndex);
+		} 
+		
+		//PCK: unsigned instead of bool
+		if ((rayBoxOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->m_escapeIndex;
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+
+
+void	btQuantizedBvh::walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const
+{
+	btAssert(m_useQuantization);
+	
+	int curIndex = startNodeIndex;
+	int walkIterations = 0;
+	int subTreeSize = endNodeIndex - startNodeIndex;
+	(void)subTreeSize;
+
+	const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+	int escapeIndex;
+	
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned boxBoxOverlap = 0;
+	unsigned rayBoxOverlap = 0;
+
+	btScalar lambda_max = 1.0;
+
+#ifdef RAYAABB2
+	btVector3 rayDirection = (rayTarget-raySource);
+	rayDirection.normalize ();
+	lambda_max = rayDirection.dot(rayTarget-raySource);
+	///what about division by zero? --> just set rayDirection[i] to 1.0
+	rayDirection[0] = rayDirection[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[0];
+	rayDirection[1] = rayDirection[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[1];
+	rayDirection[2] = rayDirection[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDirection[2];
+	unsigned int sign[3] = { rayDirection[0] < 0.0, rayDirection[1] < 0.0, rayDirection[2] < 0.0};
+#endif
+
+	/* Quick pruning by quantized box */
+	btVector3 rayAabbMin = raySource;
+	btVector3 rayAabbMax = raySource;
+	rayAabbMin.setMin(rayTarget);
+	rayAabbMax.setMax(rayTarget);
+
+	/* Add box cast extents to bounding box */
+	rayAabbMin += aabbMin;
+	rayAabbMax += aabbMax;
+
+	unsigned short int quantizedQueryAabbMin[3];
+	unsigned short int quantizedQueryAabbMax[3];
+	quantizeWithClamp(quantizedQueryAabbMin,rayAabbMin,0);
+	quantizeWithClamp(quantizedQueryAabbMax,rayAabbMax,1);
+
+	while (curIndex < endNodeIndex)
+	{
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+		//some code snippet to debugDraw aabb, to visually analyze bvh structure
+		static int drawPatch = 0;
+		//need some global access to a debugDrawer
+		extern btIDebugDraw* debugDrawerPtr;
+		if (curIndex==drawPatch)
+		{
+			btVector3 aabbMin,aabbMax;
+			aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+			aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+			btVector3	color(1,0,0);
+			debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+		}
+#endif//VISUALLY_ANALYZE_BVH
+
+		//catch bugs in tree data
+		btAssert (walkIterations < subTreeSize);
+
+		walkIterations++;
+		//PCK: unsigned instead of bool
+		// only interested if this is closer than any previous hit
+		btScalar param = 1.0;
+		rayBoxOverlap = 0;
+		boxBoxOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+		isLeafNode = rootNode->isLeafNode();
+		if (boxBoxOverlap)
+		{
+			btVector3 bounds[2];
+			bounds[0] = unQuantize(rootNode->m_quantizedAabbMin);
+			bounds[1] = unQuantize(rootNode->m_quantizedAabbMax);
+			/* Add box cast extents */
+			bounds[0] -= aabbMax;
+			bounds[1] -= aabbMin;
+			btVector3 normal;
+#if 0
+			bool ra2 = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0, lambda_max);
+			bool ra = btRayAabb (raySource, rayTarget, bounds[0], bounds[1], param, normal);
+			if (ra2 != ra)
+			{
+				printf("functions don't match\n");
+			}
+#endif
+#ifdef RAYAABB2
+			///careful with this check: need to check division by zero (above) and fix the unQuantize method
+			///thanks Joerg/hiker for the reproduction case!
+			///http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=9&t=1858
+
+			//BT_PROFILE("btRayAabb2");
+			rayBoxOverlap = btRayAabb2 (raySource, rayDirection, sign, bounds, param, 0.0f, lambda_max);
+			
+#else
+			rayBoxOverlap = true;//btRayAabb(raySource, rayTarget, bounds[0], bounds[1], param, normal);
+#endif
+		}
+		
+		if (isLeafNode && rayBoxOverlap)
+		{
+			nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+		}
+		
+		//PCK: unsigned instead of bool
+		if ((rayBoxOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->getEscapeIndex();
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+void	btQuantizedBvh::walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const
+{
+	btAssert(m_useQuantization);
+	
+	int curIndex = startNodeIndex;
+	int walkIterations = 0;
+	int subTreeSize = endNodeIndex - startNodeIndex;
+	(void)subTreeSize;
+
+	const btQuantizedBvhNode* rootNode = &m_quantizedContiguousNodes[startNodeIndex];
+	int escapeIndex;
+	
+	bool isLeafNode;
+	//PCK: unsigned instead of bool
+	unsigned aabbOverlap;
+
+	while (curIndex < endNodeIndex)
+	{
+
+//#define VISUALLY_ANALYZE_BVH 1
+#ifdef VISUALLY_ANALYZE_BVH
+		//some code snippet to debugDraw aabb, to visually analyze bvh structure
+		static int drawPatch = 0;
+		//need some global access to a debugDrawer
+		extern btIDebugDraw* debugDrawerPtr;
+		if (curIndex==drawPatch)
+		{
+			btVector3 aabbMin,aabbMax;
+			aabbMin = unQuantize(rootNode->m_quantizedAabbMin);
+			aabbMax = unQuantize(rootNode->m_quantizedAabbMax);
+			btVector3	color(1,0,0);
+			debugDrawerPtr->drawAabb(aabbMin,aabbMax,color);
+		}
+#endif//VISUALLY_ANALYZE_BVH
+
+		//catch bugs in tree data
+		btAssert (walkIterations < subTreeSize);
+
+		walkIterations++;
+		//PCK: unsigned instead of bool
+		aabbOverlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,rootNode->m_quantizedAabbMin,rootNode->m_quantizedAabbMax);
+		isLeafNode = rootNode->isLeafNode();
+		
+		if (isLeafNode && aabbOverlap)
+		{
+			nodeCallback->processNode(rootNode->getPartId(),rootNode->getTriangleIndex());
+		} 
+		
+		//PCK: unsigned instead of bool
+		if ((aabbOverlap != 0) || isLeafNode)
+		{
+			rootNode++;
+			curIndex++;
+		} else
+		{
+			escapeIndex = rootNode->getEscapeIndex();
+			rootNode += escapeIndex;
+			curIndex += escapeIndex;
+		}
+	}
+	if (maxIterations < walkIterations)
+		maxIterations = walkIterations;
+
+}
+
+//This traversal can be called from Playstation 3 SPU
+void	btQuantizedBvh::walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const
+{
+	btAssert(m_useQuantization);
+
+	int i;
+
+
+	for (i=0;i<this->m_SubtreeHeaders.size();i++)
+	{
+		const btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+		//PCK: unsigned instead of bool
+		unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+		if (overlap != 0)
+		{
+			walkStacklessQuantizedTree(nodeCallback,quantizedQueryAabbMin,quantizedQueryAabbMax,
+				subtree.m_rootNodeIndex,
+				subtree.m_rootNodeIndex+subtree.m_subtreeSize);
+		}
+	}
+}
+
+
+void	btQuantizedBvh::reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const
+{
+	reportBoxCastOverlappingNodex(nodeCallback,raySource,rayTarget,btVector3(0,0,0),btVector3(0,0,0));
+}
+
+
+void	btQuantizedBvh::reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	//always use stackless
+
+	if (m_useQuantization)
+	{
+		walkStacklessQuantizedTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+	}
+	else
+	{
+		walkStacklessTreeAgainstRay(nodeCallback, raySource, rayTarget, aabbMin, aabbMax, 0, m_curNodeIndex);
+	}
+	/*
+	{
+		//recursive traversal
+		btVector3 qaabbMin = raySource;
+		btVector3 qaabbMax = raySource;
+		qaabbMin.setMin(rayTarget);
+		qaabbMax.setMax(rayTarget);
+		qaabbMin += aabbMin;
+		qaabbMax += aabbMax;
+		reportAabbOverlappingNodex(nodeCallback,qaabbMin,qaabbMax);
+	}
+	*/
+
+}
+
+
+void	btQuantizedBvh::swapLeafNodes(int i,int splitIndex)
+{
+	if (m_useQuantization)
+	{
+			btQuantizedBvhNode tmp = m_quantizedLeafNodes[i];
+			m_quantizedLeafNodes[i] = m_quantizedLeafNodes[splitIndex];
+			m_quantizedLeafNodes[splitIndex] = tmp;
+	} else
+	{
+			btOptimizedBvhNode tmp = m_leafNodes[i];
+			m_leafNodes[i] = m_leafNodes[splitIndex];
+			m_leafNodes[splitIndex] = tmp;
+	}
+}
+
+void	btQuantizedBvh::assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex)
+{
+	if (m_useQuantization)
+	{
+		m_quantizedContiguousNodes[internalNode] = m_quantizedLeafNodes[leafNodeIndex];
+	} else
+	{
+		m_contiguousNodes[internalNode] = m_leafNodes[leafNodeIndex];
+	}
+}
+
+//PCK: include
+#include <new>
+
+#if 0
+//PCK: consts
+static const unsigned BVH_ALIGNMENT = 16;
+static const unsigned BVH_ALIGNMENT_MASK = BVH_ALIGNMENT-1;
+
+static const unsigned BVH_ALIGNMENT_BLOCKS = 2;
+#endif
+
+
+unsigned int btQuantizedBvh::getAlignmentSerializationPadding()
+{
+	// I changed this to 0 since the extra padding is not needed or used.
+	return 0;//BVH_ALIGNMENT_BLOCKS * BVH_ALIGNMENT;
+}
+
+unsigned btQuantizedBvh::calculateSerializeBufferSize() const
+{
+	unsigned baseSize = sizeof(btQuantizedBvh) + getAlignmentSerializationPadding();
+	baseSize += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+	if (m_useQuantization)
+	{
+		return baseSize + m_curNodeIndex * sizeof(btQuantizedBvhNode);
+	}
+	return baseSize + m_curNodeIndex * sizeof(btOptimizedBvhNode);
+}
+
+bool btQuantizedBvh::serialize(void *o_alignedDataBuffer, unsigned /*i_dataBufferSize */, bool i_swapEndian) const
+{
+	btAssert(m_subtreeHeaderCount == m_SubtreeHeaders.size());
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+/*	if (i_dataBufferSize < calculateSerializeBufferSize() || o_alignedDataBuffer == NULL || (((unsigned)o_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+	{
+		///check alignedment for buffer?
+		btAssert(0);
+		return false;
+	}
+*/
+
+	btQuantizedBvh *targetBvh = (btQuantizedBvh *)o_alignedDataBuffer;
+
+	// construct the class so the virtual function table, etc will be set up
+	// Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+	new (targetBvh) btQuantizedBvh;
+
+	if (i_swapEndian)
+	{
+		targetBvh->m_curNodeIndex = static_cast<int>(btSwapEndian(m_curNodeIndex));
+
+
+		btSwapVector3Endian(m_bvhAabbMin,targetBvh->m_bvhAabbMin);
+		btSwapVector3Endian(m_bvhAabbMax,targetBvh->m_bvhAabbMax);
+		btSwapVector3Endian(m_bvhQuantization,targetBvh->m_bvhQuantization);
+
+		targetBvh->m_traversalMode = (btTraversalMode)btSwapEndian(m_traversalMode);
+		targetBvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(m_subtreeHeaderCount));
+	}
+	else
+	{
+		targetBvh->m_curNodeIndex = m_curNodeIndex;
+		targetBvh->m_bvhAabbMin = m_bvhAabbMin;
+		targetBvh->m_bvhAabbMax = m_bvhAabbMax;
+		targetBvh->m_bvhQuantization = m_bvhQuantization;
+		targetBvh->m_traversalMode = m_traversalMode;
+		targetBvh->m_subtreeHeaderCount = m_subtreeHeaderCount;
+	}
+
+	targetBvh->m_useQuantization = m_useQuantization;
+
+	unsigned char *nodeData = (unsigned char *)targetBvh;
+	nodeData += sizeof(btQuantizedBvh);
+	
+	unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+	
+	int nodeCount = m_curNodeIndex;
+
+	if (m_useQuantization)
+	{
+		targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+			}
+		}
+		else
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+	
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2];
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1];
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2];
+
+				targetBvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex;
+
+
+			}
+		}
+		nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+
+		// this clears the pointer in the member variable it doesn't really do anything to the data
+		// it does call the destructor on the contained objects, but they are all classes with no destructor defined
+		// so the memory (which is not freed) is left alone
+		targetBvh->m_quantizedContiguousNodes.initializeFromBuffer(NULL, 0, 0);
+	}
+	else
+	{
+		targetBvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMinOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+				btSwapVector3Endian(m_contiguousNodes[nodeIndex].m_aabbMaxOrg, targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+
+				targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_escapeIndex));
+				targetBvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_subPart));
+				targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(m_contiguousNodes[nodeIndex].m_triangleIndex));
+			}
+		}
+		else
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				targetBvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg = m_contiguousNodes[nodeIndex].m_aabbMinOrg;
+				targetBvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg = m_contiguousNodes[nodeIndex].m_aabbMaxOrg;
+
+				targetBvh->m_contiguousNodes[nodeIndex].m_escapeIndex = m_contiguousNodes[nodeIndex].m_escapeIndex;
+				targetBvh->m_contiguousNodes[nodeIndex].m_subPart = m_contiguousNodes[nodeIndex].m_subPart;
+				targetBvh->m_contiguousNodes[nodeIndex].m_triangleIndex = m_contiguousNodes[nodeIndex].m_triangleIndex;
+			}
+		}
+		nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+
+		// this clears the pointer in the member variable it doesn't really do anything to the data
+		// it does call the destructor on the contained objects, but they are all classes with no destructor defined
+		// so the memory (which is not freed) is left alone
+		targetBvh->m_contiguousNodes.initializeFromBuffer(NULL, 0, 0);
+	}
+
+	sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+
+	// Now serialize the subtree headers
+	targetBvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, m_subtreeHeaderCount, m_subtreeHeaderCount);
+	if (i_swapEndian)
+	{
+		for (int i = 0; i < m_subtreeHeaderCount; i++)
+		{
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_rootNodeIndex));
+			targetBvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(m_SubtreeHeaders[i].m_subtreeSize));
+		}
+	}
+	else
+	{
+		for (int i = 0; i < m_subtreeHeaderCount; i++)
+		{
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = (m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = (m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = (m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = (m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = (m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+			targetBvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = (m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+			targetBvh->m_SubtreeHeaders[i].m_rootNodeIndex = (m_SubtreeHeaders[i].m_rootNodeIndex);
+			targetBvh->m_SubtreeHeaders[i].m_subtreeSize = (m_SubtreeHeaders[i].m_subtreeSize);
+
+			// need to clear padding in destination buffer
+			targetBvh->m_SubtreeHeaders[i].m_padding[0] = 0;
+			targetBvh->m_SubtreeHeaders[i].m_padding[1] = 0;
+			targetBvh->m_SubtreeHeaders[i].m_padding[2] = 0;
+		}
+	}
+	nodeData += sizeof(btBvhSubtreeInfo) * m_subtreeHeaderCount;
+
+	// this clears the pointer in the member variable it doesn't really do anything to the data
+	// it does call the destructor on the contained objects, but they are all classes with no destructor defined
+	// so the memory (which is not freed) is left alone
+	targetBvh->m_SubtreeHeaders.initializeFromBuffer(NULL, 0, 0);
+
+	// this wipes the virtual function table pointer at the start of the buffer for the class
+	*((void**)o_alignedDataBuffer) = NULL;
+
+	return true;
+}
+
+btQuantizedBvh *btQuantizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+
+	if (i_alignedDataBuffer == NULL)// || (((unsigned)i_alignedDataBuffer & BVH_ALIGNMENT_MASK) != 0))
+	{
+		return NULL;
+	}
+	btQuantizedBvh *bvh = (btQuantizedBvh *)i_alignedDataBuffer;
+
+	if (i_swapEndian)
+	{
+		bvh->m_curNodeIndex = static_cast<int>(btSwapEndian(bvh->m_curNodeIndex));
+
+		btUnSwapVector3Endian(bvh->m_bvhAabbMin);
+		btUnSwapVector3Endian(bvh->m_bvhAabbMax);
+		btUnSwapVector3Endian(bvh->m_bvhQuantization);
+
+		bvh->m_traversalMode = (btTraversalMode)btSwapEndian(bvh->m_traversalMode);
+		bvh->m_subtreeHeaderCount = static_cast<int>(btSwapEndian(bvh->m_subtreeHeaderCount));
+	}
+
+	unsigned int calculatedBufSize = bvh->calculateSerializeBufferSize();
+	btAssert(calculatedBufSize <= i_dataBufferSize);
+
+	if (calculatedBufSize > i_dataBufferSize)
+	{
+		return NULL;
+	}
+
+	unsigned char *nodeData = (unsigned char *)bvh;
+	nodeData += sizeof(btQuantizedBvh);
+	
+	unsigned sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+	
+	int nodeCount = bvh->m_curNodeIndex;
+
+	// Must call placement new to fill in virtual function table, etc, but we don't want to overwrite most data, so call a special version of the constructor
+	// Also, m_leafNodes and m_quantizedLeafNodes will be initialized to default values by the constructor
+	new (bvh) btQuantizedBvh(*bvh, false);
+
+	if (bvh->m_useQuantization)
+	{
+		bvh->m_quantizedContiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[1]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[2]);
+
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[1]);
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[2]);
+
+				bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = static_cast<int>(btSwapEndian(bvh->m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex));
+			}
+		}
+		nodeData += sizeof(btQuantizedBvhNode) * nodeCount;
+	}
+	else
+	{
+		bvh->m_contiguousNodes.initializeFromBuffer(nodeData, nodeCount, nodeCount);
+
+		if (i_swapEndian)
+		{
+			for (int nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++)
+			{
+				btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMinOrg);
+				btUnSwapVector3Endian(bvh->m_contiguousNodes[nodeIndex].m_aabbMaxOrg);
+				
+				bvh->m_contiguousNodes[nodeIndex].m_escapeIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_escapeIndex));
+				bvh->m_contiguousNodes[nodeIndex].m_subPart = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_subPart));
+				bvh->m_contiguousNodes[nodeIndex].m_triangleIndex = static_cast<int>(btSwapEndian(bvh->m_contiguousNodes[nodeIndex].m_triangleIndex));
+			}
+		}
+		nodeData += sizeof(btOptimizedBvhNode) * nodeCount;
+	}
+
+	sizeToAdd = 0;//(BVH_ALIGNMENT-((unsigned)nodeData & BVH_ALIGNMENT_MASK))&BVH_ALIGNMENT_MASK;
+	nodeData += sizeToAdd;
+
+	// Now serialize the subtree headers
+	bvh->m_SubtreeHeaders.initializeFromBuffer(nodeData, bvh->m_subtreeHeaderCount, bvh->m_subtreeHeaderCount);
+	if (i_swapEndian)
+	{
+		for (int i = 0; i < bvh->m_subtreeHeaderCount; i++)
+		{
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[0]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[1]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMin[2]);
+
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[0]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[1]);
+			bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2] = btSwapEndian(bvh->m_SubtreeHeaders[i].m_quantizedAabbMax[2]);
+
+			bvh->m_SubtreeHeaders[i].m_rootNodeIndex = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_rootNodeIndex));
+			bvh->m_SubtreeHeaders[i].m_subtreeSize = static_cast<int>(btSwapEndian(bvh->m_SubtreeHeaders[i].m_subtreeSize));
+		}
+	}
+
+	return bvh;
+}
+
+// Constructor that prevents btVector3's default constructor from being called
+btQuantizedBvh::btQuantizedBvh(btQuantizedBvh &self, bool /* ownsMemory */) :
+m_bvhAabbMin(self.m_bvhAabbMin),
+m_bvhAabbMax(self.m_bvhAabbMax),
+m_bvhQuantization(self.m_bvhQuantization),
+m_bulletVersion(BT_BULLET_VERSION)
+{
+
+}
+
+void btQuantizedBvh::deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData)
+{
+	m_bvhAabbMax.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMax);
+	m_bvhAabbMin.deSerializeFloat(quantizedBvhFloatData.m_bvhAabbMin);
+	m_bvhQuantization.deSerializeFloat(quantizedBvhFloatData.m_bvhQuantization);
+
+	m_curNodeIndex = quantizedBvhFloatData.m_curNodeIndex;
+	m_useQuantization = quantizedBvhFloatData.m_useQuantization!=0;
+	
+	{
+		int numElem = quantizedBvhFloatData.m_numContiguousLeafNodes;
+		m_contiguousNodes.resize(numElem);
+
+		if (numElem)
+		{
+			btOptimizedBvhNodeFloatData* memPtr = quantizedBvhFloatData.m_contiguousNodesPtr;
+
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_contiguousNodes[i].m_aabbMaxOrg.deSerializeFloat(memPtr->m_aabbMaxOrg);
+				m_contiguousNodes[i].m_aabbMinOrg.deSerializeFloat(memPtr->m_aabbMinOrg);
+				m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+				m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+				m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+			}
+		}
+	}
+
+	{
+		int numElem = quantizedBvhFloatData.m_numQuantizedContiguousNodes;
+		m_quantizedContiguousNodes.resize(numElem);
+		
+		if (numElem)
+		{
+			btQuantizedBvhNodeData* memPtr = quantizedBvhFloatData.m_quantizedContiguousNodesPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+			}
+		}
+	}
+
+	m_traversalMode = btTraversalMode(quantizedBvhFloatData.m_traversalMode);
+	
+	{
+		int numElem = quantizedBvhFloatData.m_numSubtreeHeaders;
+		m_SubtreeHeaders.resize(numElem);
+		if (numElem)
+		{
+			btBvhSubtreeInfoData* memPtr = quantizedBvhFloatData.m_subTreeInfoPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+				m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+				m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+				m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+			}
+		}
+	}
+}
+
+void btQuantizedBvh::deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData)
+{
+	m_bvhAabbMax.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMax);
+	m_bvhAabbMin.deSerializeDouble(quantizedBvhDoubleData.m_bvhAabbMin);
+	m_bvhQuantization.deSerializeDouble(quantizedBvhDoubleData.m_bvhQuantization);
+
+	m_curNodeIndex = quantizedBvhDoubleData.m_curNodeIndex;
+	m_useQuantization = quantizedBvhDoubleData.m_useQuantization!=0;
+	
+	{
+		int numElem = quantizedBvhDoubleData.m_numContiguousLeafNodes;
+		m_contiguousNodes.resize(numElem);
+
+		if (numElem)
+		{
+			btOptimizedBvhNodeDoubleData* memPtr = quantizedBvhDoubleData.m_contiguousNodesPtr;
+
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_contiguousNodes[i].m_aabbMaxOrg.deSerializeDouble(memPtr->m_aabbMaxOrg);
+				m_contiguousNodes[i].m_aabbMinOrg.deSerializeDouble(memPtr->m_aabbMinOrg);
+				m_contiguousNodes[i].m_escapeIndex = memPtr->m_escapeIndex;
+				m_contiguousNodes[i].m_subPart = memPtr->m_subPart;
+				m_contiguousNodes[i].m_triangleIndex = memPtr->m_triangleIndex;
+			}
+		}
+	}
+
+	{
+		int numElem = quantizedBvhDoubleData.m_numQuantizedContiguousNodes;
+		m_quantizedContiguousNodes.resize(numElem);
+		
+		if (numElem)
+		{
+			btQuantizedBvhNodeData* memPtr = quantizedBvhDoubleData.m_quantizedContiguousNodesPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex = memPtr->m_escapeIndexOrTriangleIndex;
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_quantizedContiguousNodes[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+			}
+		}
+	}
+
+	m_traversalMode = btTraversalMode(quantizedBvhDoubleData.m_traversalMode);
+	
+	{
+		int numElem = quantizedBvhDoubleData.m_numSubtreeHeaders;
+		m_SubtreeHeaders.resize(numElem);
+		if (numElem)
+		{
+			btBvhSubtreeInfoData* memPtr = quantizedBvhDoubleData.m_subTreeInfoPtr;
+			for (int i=0;i<numElem;i++,memPtr++)
+			{
+				m_SubtreeHeaders[i].m_quantizedAabbMax[0] = memPtr->m_quantizedAabbMax[0] ;
+				m_SubtreeHeaders[i].m_quantizedAabbMax[1] = memPtr->m_quantizedAabbMax[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMax[2] = memPtr->m_quantizedAabbMax[2];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[0] = memPtr->m_quantizedAabbMin[0];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[1] = memPtr->m_quantizedAabbMin[1];
+				m_SubtreeHeaders[i].m_quantizedAabbMin[2] = memPtr->m_quantizedAabbMin[2];
+				m_SubtreeHeaders[i].m_rootNodeIndex = memPtr->m_rootNodeIndex;
+				m_SubtreeHeaders[i].m_subtreeSize = memPtr->m_subtreeSize;
+			}
+		}
+	}
+
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btQuantizedBvh::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btQuantizedBvhData* quantizedData = (btQuantizedBvhData*)dataBuffer;
+	
+	m_bvhAabbMax.serialize(quantizedData->m_bvhAabbMax);
+	m_bvhAabbMin.serialize(quantizedData->m_bvhAabbMin);
+	m_bvhQuantization.serialize(quantizedData->m_bvhQuantization);
+
+	quantizedData->m_curNodeIndex = m_curNodeIndex;
+	quantizedData->m_useQuantization = m_useQuantization;
+	
+	quantizedData->m_numContiguousLeafNodes = m_contiguousNodes.size();
+	quantizedData->m_contiguousNodesPtr = (btOptimizedBvhNodeData*) (m_contiguousNodes.size() ? serializer->getUniquePointer((void*)&m_contiguousNodes[0]) : 0);
+	if (quantizedData->m_contiguousNodesPtr)
+	{
+		int sz = sizeof(btOptimizedBvhNodeData);
+		int numElem = m_contiguousNodes.size();
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btOptimizedBvhNodeData* memPtr = (btOptimizedBvhNodeData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			m_contiguousNodes[i].m_aabbMaxOrg.serialize(memPtr->m_aabbMaxOrg);
+			m_contiguousNodes[i].m_aabbMinOrg.serialize(memPtr->m_aabbMinOrg);
+			memPtr->m_escapeIndex = m_contiguousNodes[i].m_escapeIndex;
+			memPtr->m_subPart = m_contiguousNodes[i].m_subPart;
+			memPtr->m_triangleIndex = m_contiguousNodes[i].m_triangleIndex;
+		}
+		serializer->finalizeChunk(chunk,"btOptimizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_contiguousNodes[0]);
+	}
+
+	quantizedData->m_numQuantizedContiguousNodes = m_quantizedContiguousNodes.size();
+//	printf("quantizedData->m_numQuantizedContiguousNodes=%d\n",quantizedData->m_numQuantizedContiguousNodes);
+	quantizedData->m_quantizedContiguousNodesPtr =(btQuantizedBvhNodeData*) (m_quantizedContiguousNodes.size() ? serializer->getUniquePointer((void*)&m_quantizedContiguousNodes[0]) : 0);
+	if (quantizedData->m_quantizedContiguousNodesPtr)
+	{
+		int sz = sizeof(btQuantizedBvhNodeData);
+		int numElem = m_quantizedContiguousNodes.size();
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btQuantizedBvhNodeData* memPtr = (btQuantizedBvhNodeData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			memPtr->m_escapeIndexOrTriangleIndex = m_quantizedContiguousNodes[i].m_escapeIndexOrTriangleIndex;
+			memPtr->m_quantizedAabbMax[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[0];
+			memPtr->m_quantizedAabbMax[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[1];
+			memPtr->m_quantizedAabbMax[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMax[2];
+			memPtr->m_quantizedAabbMin[0] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[0];
+			memPtr->m_quantizedAabbMin[1] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[1];
+			memPtr->m_quantizedAabbMin[2] = m_quantizedContiguousNodes[i].m_quantizedAabbMin[2];
+		}
+		serializer->finalizeChunk(chunk,"btQuantizedBvhNodeData",BT_ARRAY_CODE,(void*)&m_quantizedContiguousNodes[0]);
+	}
+
+	quantizedData->m_traversalMode = int(m_traversalMode);
+	quantizedData->m_numSubtreeHeaders = m_SubtreeHeaders.size();
+
+	quantizedData->m_subTreeInfoPtr = (btBvhSubtreeInfoData*) (m_SubtreeHeaders.size() ? serializer->getUniquePointer((void*)&m_SubtreeHeaders[0]) : 0);
+	if (quantizedData->m_subTreeInfoPtr)
+	{
+		int sz = sizeof(btBvhSubtreeInfoData);
+		int numElem = m_SubtreeHeaders.size();
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btBvhSubtreeInfoData* memPtr = (btBvhSubtreeInfoData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			memPtr->m_quantizedAabbMax[0] = m_SubtreeHeaders[i].m_quantizedAabbMax[0];
+			memPtr->m_quantizedAabbMax[1] = m_SubtreeHeaders[i].m_quantizedAabbMax[1];
+			memPtr->m_quantizedAabbMax[2] = m_SubtreeHeaders[i].m_quantizedAabbMax[2];
+			memPtr->m_quantizedAabbMin[0] = m_SubtreeHeaders[i].m_quantizedAabbMin[0];
+			memPtr->m_quantizedAabbMin[1] = m_SubtreeHeaders[i].m_quantizedAabbMin[1];
+			memPtr->m_quantizedAabbMin[2] = m_SubtreeHeaders[i].m_quantizedAabbMin[2];
+
+			memPtr->m_rootNodeIndex = m_SubtreeHeaders[i].m_rootNodeIndex;
+			memPtr->m_subtreeSize = m_SubtreeHeaders[i].m_subtreeSize;
+		}
+		serializer->finalizeChunk(chunk,"btBvhSubtreeInfoData",BT_ARRAY_CODE,(void*)&m_SubtreeHeaders[0]);
+	}
+	return btQuantizedBvhDataName;
+}
+
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
new file mode 100644
index 0000000..aa30d43
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btQuantizedBvh.h
@@ -0,0 +1,579 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef QUANTIZED_BVH_H
+#define QUANTIZED_BVH_H
+
+class btSerializer;
+
+//#define DEBUG_CHECK_DEQUANTIZATION 1
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+#ifdef __SPU__
+#define printf spu_printf
+#endif //__SPU__
+
+#include <stdio.h>
+#include <stdlib.h>
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btQuantizedBvhData btQuantizedBvhDoubleData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeDoubleData
+#define btQuantizedBvhDataName "btQuantizedBvhDoubleData"
+#else
+#define btQuantizedBvhData btQuantizedBvhFloatData
+#define btOptimizedBvhNodeData btOptimizedBvhNodeFloatData
+#define btQuantizedBvhDataName "btQuantizedBvhFloatData"
+#endif
+
+
+
+//http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/vclrf__m128.asp
+
+
+//Note: currently we have 16 bytes per quantized node
+#define MAX_SUBTREE_SIZE_IN_BYTES  2048
+
+// 10 gives the potential for 1024 parts, with at most 2^21 (2097152) (minus one
+// actually) triangles each (since the sign bit is reserved
+#define MAX_NUM_PARTS_IN_BITS 10
+
+///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+ATTRIBUTE_ALIGNED16	(struct) btQuantizedBvhNode
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	//12 bytes
+	unsigned short int	m_quantizedAabbMin[3];
+	unsigned short int	m_quantizedAabbMax[3];
+	//4 bytes
+	int	m_escapeIndexOrTriangleIndex;
+
+	bool isLeafNode() const
+	{
+		//skipindex is negative (internal node), triangleindex >=0 (leafnode)
+		return (m_escapeIndexOrTriangleIndex >= 0);
+	}
+	int getEscapeIndex() const
+	{
+		btAssert(!isLeafNode());
+		return -m_escapeIndexOrTriangleIndex;
+	}
+	int	getTriangleIndex() const
+	{
+		btAssert(isLeafNode());
+		// Get only the lower bits where the triangle index is stored
+		return (m_escapeIndexOrTriangleIndex&~((~0)<<(31-MAX_NUM_PARTS_IN_BITS)));
+	}
+	int	getPartId() const
+	{
+		btAssert(isLeafNode());
+		// Get only the highest bits where the part index is stored
+		return (m_escapeIndexOrTriangleIndex>>(31-MAX_NUM_PARTS_IN_BITS));
+	}
+}
+;
+
+/// btOptimizedBvhNode contains both internal and leaf node information.
+/// Total node size is 44 bytes / node. You can use the compressed version of 16 bytes.
+ATTRIBUTE_ALIGNED16 (struct) btOptimizedBvhNode
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	//32 bytes
+	btVector3	m_aabbMinOrg;
+	btVector3	m_aabbMaxOrg;
+
+	//4
+	int	m_escapeIndex;
+
+	//8
+	//for child nodes
+	int	m_subPart;
+	int	m_triangleIndex;
+	int	m_padding[5];//bad, due to alignment
+
+
+};
+
+
+///btBvhSubtreeInfo provides info to gather a subtree of limited size
+ATTRIBUTE_ALIGNED16(class) btBvhSubtreeInfo
+{
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	//12 bytes
+	unsigned short int	m_quantizedAabbMin[3];
+	unsigned short int	m_quantizedAabbMax[3];
+	//4 bytes, points to the root of the subtree
+	int			m_rootNodeIndex;
+	//4 bytes
+	int			m_subtreeSize;
+	int			m_padding[3];
+
+	btBvhSubtreeInfo()
+	{
+		//memset(&m_padding[0], 0, sizeof(m_padding));
+	}
+
+
+	void	setAabbFromQuantizeNode(const btQuantizedBvhNode& quantizedNode)
+	{
+		m_quantizedAabbMin[0] = quantizedNode.m_quantizedAabbMin[0];
+		m_quantizedAabbMin[1] = quantizedNode.m_quantizedAabbMin[1];
+		m_quantizedAabbMin[2] = quantizedNode.m_quantizedAabbMin[2];
+		m_quantizedAabbMax[0] = quantizedNode.m_quantizedAabbMax[0];
+		m_quantizedAabbMax[1] = quantizedNode.m_quantizedAabbMax[1];
+		m_quantizedAabbMax[2] = quantizedNode.m_quantizedAabbMax[2];
+	}
+}
+;
+
+
+class btNodeOverlapCallback
+{
+public:
+	virtual ~btNodeOverlapCallback() {};
+
+	virtual void processNode(int subPart, int triangleIndex) = 0;
+};
+
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+
+///for code readability:
+typedef btAlignedObjectArray<btOptimizedBvhNode>	NodeArray;
+typedef btAlignedObjectArray<btQuantizedBvhNode>	QuantizedNodeArray;
+typedef btAlignedObjectArray<btBvhSubtreeInfo>		BvhSubtreeInfoArray;
+
+
+///The btQuantizedBvh class stores an AABB tree that can be quickly traversed on CPU and Cell SPU.
+///It is used by the btBvhTriangleMeshShape as midphase, and by the btMultiSapBroadphase.
+///It is recommended to use quantization for better performance and lower memory requirements.
+ATTRIBUTE_ALIGNED16(class) btQuantizedBvh
+{
+public:
+	enum btTraversalMode
+	{
+		TRAVERSAL_STACKLESS = 0,
+		TRAVERSAL_STACKLESS_CACHE_FRIENDLY,
+		TRAVERSAL_RECURSIVE
+	};
+
+protected:
+
+
+	btVector3			m_bvhAabbMin;
+	btVector3			m_bvhAabbMax;
+	btVector3			m_bvhQuantization;
+
+	int					m_bulletVersion;	//for serialization versioning. It could also be used to detect endianess.
+
+	int					m_curNodeIndex;
+	//quantization data
+	bool				m_useQuantization;
+
+
+
+	NodeArray			m_leafNodes;
+	NodeArray			m_contiguousNodes;
+	QuantizedNodeArray	m_quantizedLeafNodes;
+	QuantizedNodeArray	m_quantizedContiguousNodes;
+	
+	btTraversalMode	m_traversalMode;
+	BvhSubtreeInfoArray		m_SubtreeHeaders;
+
+	//This is only used for serialization so we don't have to add serialization directly to btAlignedObjectArray
+	mutable int m_subtreeHeaderCount;
+
+	
+
+
+
+	///two versions, one for quantized and normal nodes. This allows code-reuse while maintaining readability (no template/macro!)
+	///this might be refactored into a virtual, it is usually not calculated at run-time
+	void	setInternalNodeAabbMin(int nodeIndex, const btVector3& aabbMin)
+	{
+		if (m_useQuantization)
+		{
+			quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[0] ,aabbMin,0);
+		} else
+		{
+			m_contiguousNodes[nodeIndex].m_aabbMinOrg = aabbMin;
+
+		}
+	}
+	void	setInternalNodeAabbMax(int nodeIndex,const btVector3& aabbMax)
+	{
+		if (m_useQuantization)
+		{
+			quantize(&m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[0],aabbMax,1);
+		} else
+		{
+			m_contiguousNodes[nodeIndex].m_aabbMaxOrg = aabbMax;
+		}
+	}
+
+	btVector3 getAabbMin(int nodeIndex) const
+	{
+		if (m_useQuantization)
+		{
+			return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMin[0]);
+		}
+		//non-quantized
+		return m_leafNodes[nodeIndex].m_aabbMinOrg;
+
+	}
+	btVector3 getAabbMax(int nodeIndex) const
+	{
+		if (m_useQuantization)
+		{
+			return unQuantize(&m_quantizedLeafNodes[nodeIndex].m_quantizedAabbMax[0]);
+		} 
+		//non-quantized
+		return m_leafNodes[nodeIndex].m_aabbMaxOrg;
+		
+	}
+
+	
+	void	setInternalNodeEscapeIndex(int nodeIndex, int escapeIndex)
+	{
+		if (m_useQuantization)
+		{
+			m_quantizedContiguousNodes[nodeIndex].m_escapeIndexOrTriangleIndex = -escapeIndex;
+		} 
+		else
+		{
+			m_contiguousNodes[nodeIndex].m_escapeIndex = escapeIndex;
+		}
+
+	}
+
+	void mergeInternalNodeAabb(int nodeIndex,const btVector3& newAabbMin,const btVector3& newAabbMax) 
+	{
+		if (m_useQuantization)
+		{
+			unsigned short int quantizedAabbMin[3];
+			unsigned short int quantizedAabbMax[3];
+			quantize(quantizedAabbMin,newAabbMin,0);
+			quantize(quantizedAabbMax,newAabbMax,1);
+			for (int i=0;i<3;i++)
+			{
+				if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] > quantizedAabbMin[i])
+					m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMin[i] = quantizedAabbMin[i];
+
+				if (m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] < quantizedAabbMax[i])
+					m_quantizedContiguousNodes[nodeIndex].m_quantizedAabbMax[i] = quantizedAabbMax[i];
+
+			}
+		} else
+		{
+			//non-quantized
+			m_contiguousNodes[nodeIndex].m_aabbMinOrg.setMin(newAabbMin);
+			m_contiguousNodes[nodeIndex].m_aabbMaxOrg.setMax(newAabbMax);		
+		}
+	}
+
+	void	swapLeafNodes(int firstIndex,int secondIndex);
+
+	void	assignInternalNodeFromLeafNode(int internalNode,int leafNodeIndex);
+
+protected:
+
+	
+
+	void	buildTree	(int startIndex,int endIndex);
+
+	int	calcSplittingAxis(int startIndex,int endIndex);
+
+	int	sortAndCalcSplittingIndex(int startIndex,int endIndex,int splitAxis);
+	
+	void	walkStacklessTree(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	void	walkStacklessQuantizedTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+	void	walkStacklessQuantizedTree(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax,int startNodeIndex,int endNodeIndex) const;
+	void	walkStacklessTreeAgainstRay(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax, int startNodeIndex,int endNodeIndex) const;
+
+	///tree traversal designed for small-memory processors like PS3 SPU
+	void	walkStacklessQuantizedTreeCacheFriendly(btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+	///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+	void	walkRecursiveQuantizedTreeAgainstQueryAabb(const btQuantizedBvhNode* currentNode,btNodeOverlapCallback* nodeCallback,unsigned short int* quantizedQueryAabbMin,unsigned short int* quantizedQueryAabbMax) const;
+
+	///use the 16-byte stackless 'skipindex' node tree to do a recursive traversal
+	void	walkRecursiveQuantizedTreeAgainstQuantizedTree(const btQuantizedBvhNode* treeNodeA,const btQuantizedBvhNode* treeNodeB,btNodeOverlapCallback* nodeCallback) const;
+	
+
+
+
+	void	updateSubtreeHeaders(int leftChildNodexIndex,int rightChildNodexIndex);
+
+public:
+	
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btQuantizedBvh();
+
+	virtual ~btQuantizedBvh();
+
+	
+	///***************************************** expert/internal use only *************************
+	void	setQuantizationValues(const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,btScalar quantizationMargin=btScalar(1.0));
+	QuantizedNodeArray&	getLeafNodeArray() {			return	m_quantizedLeafNodes;	}
+	///buildInternal is expert use only: assumes that setQuantizationValues and LeafNodeArray are initialized
+	void	buildInternal();
+	///***************************************** expert/internal use only *************************
+
+	void	reportAabbOverlappingNodex(btNodeOverlapCallback* nodeCallback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+	void	reportRayOverlappingNodex (btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget) const;
+	void	reportBoxCastOverlappingNodex(btNodeOverlapCallback* nodeCallback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+		SIMD_FORCE_INLINE void quantize(unsigned short* out, const btVector3& point,int isMax) const
+	{
+
+		btAssert(m_useQuantization);
+
+		btAssert(point.getX() <= m_bvhAabbMax.getX());
+		btAssert(point.getY() <= m_bvhAabbMax.getY());
+		btAssert(point.getZ() <= m_bvhAabbMax.getZ());
+
+		btAssert(point.getX() >= m_bvhAabbMin.getX());
+		btAssert(point.getY() >= m_bvhAabbMin.getY());
+		btAssert(point.getZ() >= m_bvhAabbMin.getZ());
+
+		btVector3 v = (point - m_bvhAabbMin) * m_bvhQuantization;
+		///Make sure rounding is done in a way that unQuantize(quantizeWithClamp(...)) is conservative
+		///end-points always set the first bit, so that they are sorted properly (so that neighbouring AABBs overlap properly)
+		///@todo: double-check this
+		if (isMax)
+		{
+			out[0] = (unsigned short) (((unsigned short)(v.getX()+btScalar(1.)) | 1));
+			out[1] = (unsigned short) (((unsigned short)(v.getY()+btScalar(1.)) | 1));
+			out[2] = (unsigned short) (((unsigned short)(v.getZ()+btScalar(1.)) | 1));
+		} else
+		{
+			out[0] = (unsigned short) (((unsigned short)(v.getX()) & 0xfffe));
+			out[1] = (unsigned short) (((unsigned short)(v.getY()) & 0xfffe));
+			out[2] = (unsigned short) (((unsigned short)(v.getZ()) & 0xfffe));
+		}
+
+
+#ifdef DEBUG_CHECK_DEQUANTIZATION
+		btVector3 newPoint = unQuantize(out);
+		if (isMax)
+		{
+			if (newPoint.getX() < point.getX())
+			{
+				printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+			}
+			if (newPoint.getY() < point.getY())
+			{
+				printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+			}
+			if (newPoint.getZ() < point.getZ())
+			{
+
+				printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+			}
+		} else
+		{
+			if (newPoint.getX() > point.getX())
+			{
+				printf("unconservative X, diffX = %f, oldX=%f,newX=%f\n",newPoint.getX()-point.getX(), newPoint.getX(),point.getX());
+			}
+			if (newPoint.getY() > point.getY())
+			{
+				printf("unconservative Y, diffY = %f, oldY=%f,newY=%f\n",newPoint.getY()-point.getY(), newPoint.getY(),point.getY());
+			}
+			if (newPoint.getZ() > point.getZ())
+			{
+				printf("unconservative Z, diffZ = %f, oldZ=%f,newZ=%f\n",newPoint.getZ()-point.getZ(), newPoint.getZ(),point.getZ());
+			}
+		}
+#endif //DEBUG_CHECK_DEQUANTIZATION
+
+	}
+
+
+	SIMD_FORCE_INLINE void quantizeWithClamp(unsigned short* out, const btVector3& point2,int isMax) const
+	{
+
+		btAssert(m_useQuantization);
+
+		btVector3 clampedPoint(point2);
+		clampedPoint.setMax(m_bvhAabbMin);
+		clampedPoint.setMin(m_bvhAabbMax);
+
+		quantize(out,clampedPoint,isMax);
+
+	}
+	
+	SIMD_FORCE_INLINE btVector3	unQuantize(const unsigned short* vecIn) const
+	{
+			btVector3	vecOut;
+			vecOut.setValue(
+			(btScalar)(vecIn[0]) / (m_bvhQuantization.getX()),
+			(btScalar)(vecIn[1]) / (m_bvhQuantization.getY()),
+			(btScalar)(vecIn[2]) / (m_bvhQuantization.getZ()));
+			vecOut += m_bvhAabbMin;
+			return vecOut;
+	}
+
+	///setTraversalMode let's you choose between stackless, recursive or stackless cache friendly tree traversal. Note this is only implemented for quantized trees.
+	void	setTraversalMode(btTraversalMode	traversalMode)
+	{
+		m_traversalMode = traversalMode;
+	}
+
+
+	SIMD_FORCE_INLINE QuantizedNodeArray&	getQuantizedNodeArray()
+	{	
+		return	m_quantizedContiguousNodes;
+	}
+
+
+	SIMD_FORCE_INLINE BvhSubtreeInfoArray&	getSubtreeInfoArray()
+	{
+		return m_SubtreeHeaders;
+	}
+
+////////////////////////////////////////////////////////////////////
+
+	/////Calculate space needed to store BVH for serialization
+	unsigned calculateSerializeBufferSize() const;
+
+	/// Data buffer MUST be 16 byte aligned
+	virtual bool serialize(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const;
+
+	///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+	static btQuantizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+	static unsigned int getAlignmentSerializationPadding();
+//////////////////////////////////////////////////////////////////////
+
+	
+	virtual	int	calculateSerializeBufferSizeNew() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	virtual	void deSerializeFloat(struct btQuantizedBvhFloatData& quantizedBvhFloatData);
+
+	virtual	void deSerializeDouble(struct btQuantizedBvhDoubleData& quantizedBvhDoubleData);
+
+
+////////////////////////////////////////////////////////////////////
+
+	SIMD_FORCE_INLINE bool isQuantized()
+	{
+		return m_useQuantization;
+	}
+
+private:
+	// Special "copy" constructor that allows for in-place deserialization
+	// Prevents btVector3's default constructor from being called, but doesn't inialize much else
+	// ownsMemory should most likely be false if deserializing, and if you are not, don't call this (it also changes the function signature, which we need)
+	btQuantizedBvh(btQuantizedBvh &other, bool ownsMemory);
+
+}
+;
+
+
+struct	btBvhSubtreeInfoData
+{
+	int			m_rootNodeIndex;
+	int			m_subtreeSize;
+	unsigned short m_quantizedAabbMin[3];
+	unsigned short m_quantizedAabbMax[3];
+};
+
+struct btOptimizedBvhNodeFloatData
+{
+	btVector3FloatData	m_aabbMinOrg;
+	btVector3FloatData	m_aabbMaxOrg;
+	int	m_escapeIndex;
+	int	m_subPart;
+	int	m_triangleIndex;
+	char m_pad[4];
+};
+
+struct btOptimizedBvhNodeDoubleData
+{
+	btVector3DoubleData	m_aabbMinOrg;
+	btVector3DoubleData	m_aabbMaxOrg;
+	int	m_escapeIndex;
+	int	m_subPart;
+	int	m_triangleIndex;
+	char	m_pad[4];
+};
+
+
+struct btQuantizedBvhNodeData
+{
+	unsigned short m_quantizedAabbMin[3];
+	unsigned short m_quantizedAabbMax[3];
+	int	m_escapeIndexOrTriangleIndex;
+};
+
+struct	btQuantizedBvhFloatData
+{
+	btVector3FloatData			m_bvhAabbMin;
+	btVector3FloatData			m_bvhAabbMax;
+	btVector3FloatData			m_bvhQuantization;
+	int					m_curNodeIndex;
+	int					m_useQuantization;
+	int					m_numContiguousLeafNodes;
+	int					m_numQuantizedContiguousNodes;
+	btOptimizedBvhNodeFloatData	*m_contiguousNodesPtr;
+	btQuantizedBvhNodeData		*m_quantizedContiguousNodesPtr;
+	btBvhSubtreeInfoData	*m_subTreeInfoPtr;
+	int					m_traversalMode;
+	int					m_numSubtreeHeaders;
+	
+};
+
+struct	btQuantizedBvhDoubleData
+{
+	btVector3DoubleData			m_bvhAabbMin;
+	btVector3DoubleData			m_bvhAabbMax;
+	btVector3DoubleData			m_bvhQuantization;
+	int							m_curNodeIndex;
+	int							m_useQuantization;
+	int							m_numContiguousLeafNodes;
+	int							m_numQuantizedContiguousNodes;
+	btOptimizedBvhNodeDoubleData	*m_contiguousNodesPtr;
+	btQuantizedBvhNodeData			*m_quantizedContiguousNodesPtr;
+
+	int							m_traversalMode;
+	int							m_numSubtreeHeaders;
+	btBvhSubtreeInfoData		*m_subTreeInfoPtr;
+};
+
+
+SIMD_FORCE_INLINE	int	btQuantizedBvh::calculateSerializeBufferSizeNew() const
+{
+	return sizeof(btQuantizedBvhData);
+}
+
+
+
+#endif //QUANTIZED_BVH_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
new file mode 100644
index 0000000..752fcd0
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp
@@ -0,0 +1,349 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAabbUtil2.h"
+
+#include <new>
+
+extern int gOverlappingPairs;
+
+void	btSimpleBroadphase::validate()
+{
+	for (int i=0;i<m_numHandles;i++)
+	{
+		for (int j=i+1;j<m_numHandles;j++)
+		{
+			btAssert(&m_pHandles[i] != &m_pHandles[j]);
+		}
+	}
+	
+}
+
+btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* overlappingPairCache)
+	:m_pairCache(overlappingPairCache),
+	m_ownsPairCache(false),
+	m_invalidPair(0)
+{
+
+	if (!overlappingPairCache)
+	{
+		void* mem = btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16);
+		m_pairCache = new (mem)btHashedOverlappingPairCache();
+		m_ownsPairCache = true;
+	}
+
+	// allocate handles buffer and put all handles on free list
+	m_pHandlesRawPtr = btAlignedAlloc(sizeof(btSimpleBroadphaseProxy)*maxProxies,16);
+	m_pHandles = new(m_pHandlesRawPtr) btSimpleBroadphaseProxy[maxProxies];
+	m_maxHandles = maxProxies;
+	m_numHandles = 0;
+	m_firstFreeHandle = 0;
+	m_LastHandleIndex = -1;
+	
+
+	{
+		for (int i = m_firstFreeHandle; i < maxProxies; i++)
+		{
+			m_pHandles[i].SetNextFree(i + 1);
+			m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes
+		}
+		m_pHandles[maxProxies - 1].SetNextFree(0);
+	
+	}
+
+}
+
+btSimpleBroadphase::~btSimpleBroadphase()
+{
+	btAlignedFree(m_pHandlesRawPtr);
+
+	if (m_ownsPairCache)
+	{
+		m_pairCache->~btOverlappingPairCache();
+		btAlignedFree(m_pairCache);
+	}
+}
+
+
+btBroadphaseProxy*	btSimpleBroadphase::createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* /*dispatcher*/,void* multiSapProxy)
+{
+	if (m_numHandles >= m_maxHandles)
+	{
+		btAssert(0);
+		return 0; //should never happen, but don't let the game crash ;-)
+	}
+	btAssert(aabbMin[0]<= aabbMax[0] && aabbMin[1]<= aabbMax[1] && aabbMin[2]<= aabbMax[2]);
+
+	int newHandleIndex = allocHandle();
+	btSimpleBroadphaseProxy* proxy = new (&m_pHandles[newHandleIndex])btSimpleBroadphaseProxy(aabbMin,aabbMax,shapeType,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy);
+
+	return proxy;
+}
+
+class	RemovingOverlapCallback : public btOverlapCallback
+{
+protected:
+	virtual bool	processOverlap(btBroadphasePair& pair)
+	{
+		(void)pair;
+		btAssert(0);
+		return false;
+	}
+};
+
+class RemovePairContainingProxy
+{
+
+	btBroadphaseProxy*	m_targetProxy;
+	public:
+	virtual ~RemovePairContainingProxy()
+	{
+	}
+protected:
+	virtual bool processOverlap(btBroadphasePair& pair)
+	{
+		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0);
+		btSimpleBroadphaseProxy* proxy1 = static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1);
+
+		return ((m_targetProxy == proxy0 || m_targetProxy == proxy1));
+	};
+};
+
+void	btSimpleBroadphase::destroyProxy(btBroadphaseProxy* proxyOrg,btDispatcher* dispatcher)
+{
+		
+		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxyOrg);
+		freeHandle(proxy0);
+
+		m_pairCache->removeOverlappingPairsContainingProxy(proxyOrg,dispatcher);
+
+		//validate();
+		
+}
+
+void	btSimpleBroadphase::getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const
+{
+	const btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+	aabbMin = sbp->m_aabbMin;
+	aabbMax = sbp->m_aabbMax;
+}
+
+void	btSimpleBroadphase::setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* /*dispatcher*/)
+{
+	btSimpleBroadphaseProxy* sbp = getSimpleProxyFromProxy(proxy);
+	sbp->m_aabbMin = aabbMin;
+	sbp->m_aabbMax = aabbMax;
+}
+
+void	btSimpleBroadphase::rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	for (int i=0; i <= m_LastHandleIndex; i++)
+	{
+		btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+		if(!proxy->m_clientObject)
+		{
+			continue;
+		}
+		rayCallback.process(proxy);
+	}
+}
+
+
+void	btSimpleBroadphase::aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback)
+{
+	for (int i=0; i <= m_LastHandleIndex; i++)
+	{
+		btSimpleBroadphaseProxy* proxy = &m_pHandles[i];
+		if(!proxy->m_clientObject)
+		{
+			continue;
+		}
+		if (TestAabbAgainstAabb2(aabbMin,aabbMax,proxy->m_aabbMin,proxy->m_aabbMax))
+		{
+			callback.process(proxy);
+		}
+	}
+}
+
+
+
+	
+
+
+
+bool	btSimpleBroadphase::aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1)
+{
+	return proxy0->m_aabbMin[0] <= proxy1->m_aabbMax[0] && proxy1->m_aabbMin[0] <= proxy0->m_aabbMax[0] && 
+		   proxy0->m_aabbMin[1] <= proxy1->m_aabbMax[1] && proxy1->m_aabbMin[1] <= proxy0->m_aabbMax[1] &&
+		   proxy0->m_aabbMin[2] <= proxy1->m_aabbMax[2] && proxy1->m_aabbMin[2] <= proxy0->m_aabbMax[2];
+
+}
+
+
+
+//then remove non-overlapping ones
+class CheckOverlapCallback : public btOverlapCallback
+{
+public:
+	virtual bool processOverlap(btBroadphasePair& pair)
+	{
+		return (!btSimpleBroadphase::aabbOverlap(static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy0),static_cast<btSimpleBroadphaseProxy*>(pair.m_pProxy1)));
+	}
+};
+
+void	btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher)
+{
+	//first check for new overlapping pairs
+	int i,j;
+	if (m_numHandles >= 0)
+	{
+		int new_largest_index = -1;
+		for (i=0; i <= m_LastHandleIndex; i++)
+		{
+			btSimpleBroadphaseProxy* proxy0 = &m_pHandles[i];
+			if(!proxy0->m_clientObject)
+			{
+				continue;
+			}
+			new_largest_index = i;
+			for (j=i+1; j <= m_LastHandleIndex; j++)
+			{
+				btSimpleBroadphaseProxy* proxy1 = &m_pHandles[j];
+				btAssert(proxy0 != proxy1);
+				if(!proxy1->m_clientObject)
+				{
+					continue;
+				}
+
+				btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+				btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+
+				if (aabbOverlap(p0,p1))
+				{
+					if ( !m_pairCache->findPair(proxy0,proxy1))
+					{
+						m_pairCache->addOverlappingPair(proxy0,proxy1);
+					}
+				} else
+				{
+					if (!m_pairCache->hasDeferredRemoval())
+					{
+						if ( m_pairCache->findPair(proxy0,proxy1))
+						{
+							m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
+						}
+					}
+				}
+			}
+		}
+
+		m_LastHandleIndex = new_largest_index;
+
+		if (m_ownsPairCache && m_pairCache->hasDeferredRemoval())
+		{
+
+			btBroadphasePairArray&	overlappingPairArray = m_pairCache->getOverlappingPairArray();
+
+			//perform a sort, to find duplicates and to sort 'invalid' pairs to the end
+			overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+			overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+			m_invalidPair = 0;
+
+
+			btBroadphasePair previousPair;
+			previousPair.m_pProxy0 = 0;
+			previousPair.m_pProxy1 = 0;
+			previousPair.m_algorithm = 0;
+
+
+			for (i=0;i<overlappingPairArray.size();i++)
+			{
+
+				btBroadphasePair& pair = overlappingPairArray[i];
+
+				bool isDuplicate = (pair == previousPair);
+
+				previousPair = pair;
+
+				bool needsRemoval = false;
+
+				if (!isDuplicate)
+				{
+					bool hasOverlap = testAabbOverlap(pair.m_pProxy0,pair.m_pProxy1);
+
+					if (hasOverlap)
+					{
+						needsRemoval = false;//callback->processOverlap(pair);
+					} else
+					{
+						needsRemoval = true;
+					}
+				} else
+				{
+					//remove duplicate
+					needsRemoval = true;
+					//should have no algorithm
+					btAssert(!pair.m_algorithm);
+				}
+
+				if (needsRemoval)
+				{
+					m_pairCache->cleanOverlappingPair(pair,dispatcher);
+
+					//		m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1);
+					//		m_overlappingPairArray.pop_back();
+					pair.m_pProxy0 = 0;
+					pair.m_pProxy1 = 0;
+					m_invalidPair++;
+					gOverlappingPairs--;
+				} 
+
+			}
+
+			///if you don't like to skip the invalid pairs in the array, execute following code:
+#define CLEAN_INVALID_PAIRS 1
+#ifdef CLEAN_INVALID_PAIRS
+
+			//perform a sort, to sort 'invalid' pairs to the end
+			overlappingPairArray.quickSort(btBroadphasePairSortPredicate());
+
+			overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair);
+			m_invalidPair = 0;
+#endif//CLEAN_INVALID_PAIRS
+
+		}
+	}
+}
+
+
+bool btSimpleBroadphase::testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+{
+	btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0);
+	btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1);
+	return aabbOverlap(p0,p1);
+}
+
+void	btSimpleBroadphase::resetPool(btDispatcher* dispatcher)
+{
+	//not yet
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
new file mode 100644
index 0000000..3e7c7ee
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SIMPLE_BROADPHASE_H
+#define SIMPLE_BROADPHASE_H
+
+
+#include "btOverlappingPairCache.h"
+
+
+struct btSimpleBroadphaseProxy : public btBroadphaseProxy
+{
+	int			m_nextFree;
+	
+//	int			m_handleId;
+
+	
+	btSimpleBroadphaseProxy() {};
+
+	btSimpleBroadphaseProxy(const btVector3& minpt,const btVector3& maxpt,int shapeType,void* userPtr,short int collisionFilterGroup,short int collisionFilterMask,void* multiSapProxy)
+	:btBroadphaseProxy(minpt,maxpt,userPtr,collisionFilterGroup,collisionFilterMask,multiSapProxy)
+	{
+		(void)shapeType;
+	}
+	
+	
+	SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;}
+	SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;}
+
+	
+
+
+};
+
+///The SimpleBroadphase is just a unit-test for btAxisSweep3, bt32BitAxisSweep3, or btDbvtBroadphase, so use those classes instead.
+///It is a brute force aabb culling broadphase based on O(n^2) aabb checks
+class btSimpleBroadphase : public btBroadphaseInterface
+{
+
+protected:
+
+	int		m_numHandles;						// number of active handles
+	int		m_maxHandles;						// max number of handles
+	int		m_LastHandleIndex;							
+	
+	btSimpleBroadphaseProxy* m_pHandles;						// handles pool
+
+	void* m_pHandlesRawPtr;
+	int		m_firstFreeHandle;		// free handles list
+	
+	int allocHandle()
+	{
+		btAssert(m_numHandles < m_maxHandles);
+		int freeHandle = m_firstFreeHandle;
+		m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree();
+		m_numHandles++;
+		if(freeHandle > m_LastHandleIndex)
+		{
+			m_LastHandleIndex = freeHandle;
+		}
+		return freeHandle;
+	}
+
+	void freeHandle(btSimpleBroadphaseProxy* proxy)
+	{
+		int handle = int(proxy-m_pHandles);
+		btAssert(handle >= 0 && handle < m_maxHandles);
+		if(handle == m_LastHandleIndex)
+		{
+			m_LastHandleIndex--;
+		}
+		proxy->SetNextFree(m_firstFreeHandle);
+		m_firstFreeHandle = handle;
+
+		proxy->m_clientObject = 0;
+
+		m_numHandles--;
+	}
+
+	btOverlappingPairCache*	m_pairCache;
+	bool	m_ownsPairCache;
+
+	int	m_invalidPair;
+
+	
+	
+	inline btSimpleBroadphaseProxy*	getSimpleProxyFromProxy(btBroadphaseProxy* proxy)
+	{
+		btSimpleBroadphaseProxy* proxy0 = static_cast<btSimpleBroadphaseProxy*>(proxy);
+		return proxy0;
+	}
+
+	inline const btSimpleBroadphaseProxy*	getSimpleProxyFromProxy(btBroadphaseProxy* proxy) const
+	{
+		const btSimpleBroadphaseProxy* proxy0 = static_cast<const btSimpleBroadphaseProxy*>(proxy);
+		return proxy0;
+	}
+
+	///reset broadphase internal structures, to ensure determinism/reproducability
+	virtual void resetPool(btDispatcher* dispatcher);
+
+
+	void	validate();
+
+protected:
+
+
+	
+
+public:
+	btSimpleBroadphase(int maxProxies=16384,btOverlappingPairCache* overlappingPairCache=0);
+	virtual ~btSimpleBroadphase();
+
+
+		static bool	aabbOverlap(btSimpleBroadphaseProxy* proxy0,btSimpleBroadphaseProxy* proxy1);
+
+
+	virtual btBroadphaseProxy*	createProxy(  const btVector3& aabbMin,  const btVector3& aabbMax,int shapeType,void* userPtr ,short int collisionFilterGroup,short int collisionFilterMask, btDispatcher* dispatcher,void* multiSapProxy);
+
+	virtual void	calculateOverlappingPairs(btDispatcher* dispatcher);
+
+	virtual void	destroyProxy(btBroadphaseProxy* proxy,btDispatcher* dispatcher);
+	virtual void	setAabb(btBroadphaseProxy* proxy,const btVector3& aabbMin,const btVector3& aabbMax, btDispatcher* dispatcher);
+	virtual void	getAabb(btBroadphaseProxy* proxy,btVector3& aabbMin, btVector3& aabbMax ) const;
+
+	virtual void	rayTest(const btVector3& rayFrom,const btVector3& rayTo, btBroadphaseRayCallback& rayCallback, const btVector3& aabbMin=btVector3(0,0,0),const btVector3& aabbMax=btVector3(0,0,0));
+	virtual void	aabbTest(const btVector3& aabbMin, const btVector3& aabbMax, btBroadphaseAabbCallback& callback);
+		
+	btOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_pairCache;
+	}
+	const btOverlappingPairCache*	getOverlappingPairCache() const
+	{
+		return m_pairCache;
+	}
+
+	bool	testAabbOverlap(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1);
+
+
+	///getAabb returns the axis aligned bounding box in the 'global' coordinate frame
+	///will add some transform later
+	virtual void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		aabbMin.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+		aabbMax.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+	}
+
+	virtual void	printStats()
+	{
+//		printf("btSimpleBroadphase.h\n");
+//		printf("numHandles = %d, maxHandles = %d\n",m_numHandles,m_maxHandles);
+	}
+};
+
+
+
+#endif //SIMPLE_BROADPHASE_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
new file mode 100644
index 0000000..f76755f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.cpp
@@ -0,0 +1,209 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btScalar.h"
+#include "SphereTriangleDetector.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+
+SphereTriangleDetector::SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle,btScalar contactBreakingThreshold)
+:m_sphere(sphere),
+m_triangle(triangle),
+m_contactBreakingThreshold(contactBreakingThreshold)
+{
+
+}
+
+void	SphereTriangleDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+{
+
+	(void)debugDraw;
+	const btTransform& transformA = input.m_transformA;
+	const btTransform& transformB = input.m_transformB;
+
+	btVector3 point,normal;
+	btScalar timeOfImpact = btScalar(1.);
+	btScalar depth = btScalar(0.);
+//	output.m_distance = btScalar(BT_LARGE_FLOAT);
+	//move sphere into triangle space
+	btTransform	sphereInTr = transformB.inverseTimes(transformA);
+
+	if (collide(sphereInTr.getOrigin(),point,normal,depth,timeOfImpact,m_contactBreakingThreshold))
+	{
+		if (swapResults)
+		{
+			btVector3 normalOnB = transformB.getBasis()*normal;
+			btVector3 normalOnA = -normalOnB;
+			btVector3 pointOnA = transformB*point+normalOnB*depth;
+			output.addContactPoint(normalOnA,pointOnA,depth);
+		} else
+		{
+			output.addContactPoint(transformB.getBasis()*normal,transformB*point,depth);
+		}
+	}
+
+}
+
+#define MAX_OVERLAP btScalar(0.)
+
+
+
+// See also geometrictools.com
+// Basic idea: D = |p - (lo + t0*lv)| where t0 = lv . (p - lo) / lv . lv
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest);
+
+btScalar SegmentSqrDistance(const btVector3& from, const btVector3& to,const btVector3 &p, btVector3 &nearest) {
+	btVector3 diff = p - from;
+	btVector3 v = to - from;
+	btScalar t = v.dot(diff);
+	
+	if (t > 0) {
+		btScalar dotVV = v.dot(v);
+		if (t < dotVV) {
+			t /= dotVV;
+			diff -= t*v;
+		} else {
+			t = 1;
+			diff -= v;
+		}
+	} else
+		t = 0;
+
+	nearest = from + t*v;
+	return diff.dot(diff);	
+}
+
+bool SphereTriangleDetector::facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal)  {
+	btVector3 lp(p);
+	btVector3 lnormal(normal);
+	
+	return pointInTriangle(vertices, lnormal, &lp);
+}
+
+///combined discrete/continuous sphere-triangle
+bool SphereTriangleDetector::collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar contactBreakingThreshold)
+{
+
+	const btVector3* vertices = &m_triangle->getVertexPtr(0);
+	const btVector3& c = sphereCenter;
+	btScalar r = m_sphere->getRadius();
+
+	btVector3 delta (0,0,0);
+
+	btVector3 normal = (vertices[1]-vertices[0]).cross(vertices[2]-vertices[0]);
+	normal.normalize();
+	btVector3 p1ToCentre = c - vertices[0];
+	btScalar distanceFromPlane = p1ToCentre.dot(normal);
+
+	if (distanceFromPlane < btScalar(0.))
+	{
+		//triangle facing the other way
+	
+		distanceFromPlane *= btScalar(-1.);
+		normal *= btScalar(-1.);
+	}
+
+	btScalar contactMargin = contactBreakingThreshold;
+	bool isInsideContactPlane = distanceFromPlane < r + contactMargin;
+	bool isInsideShellPlane = distanceFromPlane < r;
+	
+	btScalar deltaDotNormal = delta.dot(normal);
+	if (!isInsideShellPlane && deltaDotNormal >= btScalar(0.0))
+		return false;
+
+	// Check for contact / intersection
+	bool hasContact = false;
+	btVector3 contactPoint;
+	if (isInsideContactPlane) {
+		if (facecontains(c,vertices,normal)) {
+			// Inside the contact wedge - touches a point on the shell plane
+			hasContact = true;
+			contactPoint = c - normal*distanceFromPlane;
+		} else {
+			// Could be inside one of the contact capsules
+			btScalar contactCapsuleRadiusSqr = (r + contactMargin) * (r + contactMargin);
+			btVector3 nearestOnEdge;
+			for (int i = 0; i < m_triangle->getNumEdges(); i++) {
+				
+				btVector3 pa;
+				btVector3 pb;
+				
+				m_triangle->getEdge(i,pa,pb);
+
+				btScalar distanceSqr = SegmentSqrDistance(pa,pb,c, nearestOnEdge);
+				if (distanceSqr < contactCapsuleRadiusSqr) {
+					// Yep, we're inside a capsule
+					hasContact = true;
+					contactPoint = nearestOnEdge;
+				}
+				
+			}
+		}
+	}
+
+	if (hasContact) {
+		btVector3 contactToCentre = c - contactPoint;
+		btScalar distanceSqr = contactToCentre.length2();
+		if (distanceSqr < (r - MAX_OVERLAP)*(r - MAX_OVERLAP)) {
+			btScalar distance = btSqrt(distanceSqr);
+			resultNormal = contactToCentre;
+			resultNormal.normalize();
+			point = contactPoint;
+			depth = -(r-distance);
+			return true;
+		}
+
+		if (delta.dot(contactToCentre) >= btScalar(0.0)) 
+			return false;
+		
+		// Moving towards the contact point -> collision
+		point = contactPoint;
+		timeOfImpact = btScalar(0.0);
+		return true;
+	}
+	
+	return false;
+}
+
+
+bool SphereTriangleDetector::pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p )
+{
+	const btVector3* p1 = &vertices[0];
+	const btVector3* p2 = &vertices[1];
+	const btVector3* p3 = &vertices[2];
+
+	btVector3 edge1( *p2 - *p1 );
+	btVector3 edge2( *p3 - *p2 );
+	btVector3 edge3( *p1 - *p3 );
+
+	btVector3 p1_to_p( *p - *p1 );
+	btVector3 p2_to_p( *p - *p2 );
+	btVector3 p3_to_p( *p - *p3 );
+
+	btVector3 edge1_normal( edge1.cross(normal));
+	btVector3 edge2_normal( edge2.cross(normal));
+	btVector3 edge3_normal( edge3.cross(normal));
+	
+	btScalar r1, r2, r3;
+	r1 = edge1_normal.dot( p1_to_p );
+	r2 = edge2_normal.dot( p2_to_p );
+	r3 = edge3_normal.dot( p3_to_p );
+	if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
+	     ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
+		return true;
+	return false;
+
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
new file mode 100644
index 0000000..f656e5c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/SphereTriangleDetector.h
@@ -0,0 +1,51 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SPHERE_TRIANGLE_DETECTOR_H
+#define SPHERE_TRIANGLE_DETECTOR_H
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+
+class btSphereShape;
+class btTriangleShape;
+
+
+
+/// sphere-triangle to match the btDiscreteCollisionDetectorInterface
+struct SphereTriangleDetector : public btDiscreteCollisionDetectorInterface
+{
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+	SphereTriangleDetector(btSphereShape* sphere,btTriangleShape* triangle, btScalar contactBreakingThreshold);
+
+	virtual ~SphereTriangleDetector() {};
+
+	bool collide(const btVector3& sphereCenter,btVector3 &point, btVector3& resultNormal, btScalar& depth, btScalar &timeOfImpact, btScalar	contactBreakingThreshold);
+
+private:
+
+	
+	bool pointInTriangle(const btVector3 vertices[], const btVector3 &normal, btVector3 *p );
+	bool facecontains(const btVector3 &p,const btVector3* vertices,btVector3& normal);
+
+	btSphereShape* m_sphere;
+	btTriangleShape* m_triangle;
+	btScalar	m_contactBreakingThreshold;
+	
+};
+#endif //SPHERE_TRIANGLE_DETECTOR_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
new file mode 100644
index 0000000..7e5da6c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.cpp
@@ -0,0 +1,47 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "btCollisionDispatcher.h"
+#include "btCollisionObject.h"
+
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci)
+:btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+}
+btActivatingCollisionAlgorithm::btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1)
+:btCollisionAlgorithm(ci)
+//,
+//m_colObj0(0),
+//m_colObj1(0)
+{
+//	if (ci.m_dispatcher1->needsCollision(colObj0,colObj1))
+//	{
+//		m_colObj0 = colObj0;
+//		m_colObj1 = colObj1;
+//		
+//		m_colObj0->activate();
+//		m_colObj1->activate();
+//	}
+}
+
+btActivatingCollisionAlgorithm::~btActivatingCollisionAlgorithm()
+{
+//		m_colObj0->activate();
+//		m_colObj1->activate();
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
new file mode 100644
index 0000000..25fe088
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h
@@ -0,0 +1,36 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef __BT_ACTIVATING_COLLISION_ALGORITHM_H
+#define __BT_ACTIVATING_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+///This class is not enabled yet (work-in-progress) to more aggressively activate objects.
+class btActivatingCollisionAlgorithm : public btCollisionAlgorithm
+{
+//	btCollisionObject* m_colObj0;
+//	btCollisionObject* m_colObj1;
+
+public:
+
+	btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci);
+
+	btActivatingCollisionAlgorithm (const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* colObj0,btCollisionObject* colObj1);
+
+	virtual ~btActivatingCollisionAlgorithm();
+
+};
+#endif //__BT_ACTIVATING_COLLISION_ALGORITHM_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
new file mode 100644
index 0000000..2182d0d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.cpp
@@ -0,0 +1,435 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+* The b2CollidePolygons routines are Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btBox2dBox2dCollisionAlgorithm, with modified b2CollidePolygons routines from the Box2D library.
+///The modifications include: switching from b2Vec to btVector3, redefinition of b2Dot, b2Cross
+
+#include "btBox2dBox2dCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBox2dShape.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBox2dBox2dCollisionAlgorithm::btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
+: btActivatingCollisionAlgorithm(ci,obj0,obj1),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+		m_ownManifold = true;
+	}
+}
+
+btBox2dBox2dCollisionAlgorithm::~btBox2dBox2dCollisionAlgorithm()
+{
+	
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+	
+}
+
+
+void b2CollidePolygons(btManifoldResult* manifold,  const btBox2dShape* polyA, const btTransform& xfA, const btBox2dShape* polyB, const btTransform& xfB);
+
+//#include <stdio.h>
+void btBox2dBox2dCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject*	col0 = body0;
+	btCollisionObject*	col1 = body1;
+	btBox2dShape* box0 = (btBox2dShape*)col0->getCollisionShape();
+	btBox2dShape* box1 = (btBox2dShape*)col1->getCollisionShape();
+
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	b2CollidePolygons(resultOut,box0,col0->getWorldTransform(),box1,col1->getWorldTransform());
+
+	//  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+
+}
+
+btScalar btBox2dBox2dCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+	//not yet
+	return 1.f;
+}
+
+
+struct ClipVertex
+{
+	btVector3 v;
+	int id;
+	//b2ContactID id;
+	//b2ContactID id;
+};
+
+#define b2Dot(a,b) (a).dot(b)
+#define b2Mul(a,b) (a)*(b)
+#define b2MulT(a,b) (a).transpose()*(b)
+#define b2Cross(a,b) (a).cross(b)
+#define btCrossS(a,s) btVector3(s * a.getY(), -s * a.getX(),0.f)
+
+int b2_maxManifoldPoints =2;
+
+static int ClipSegmentToLine(ClipVertex vOut[2], ClipVertex vIn[2],
+					  const btVector3& normal, btScalar offset)
+{
+	// Start with no output points
+	int numOut = 0;
+
+	// Calculate the distance of end points to the line
+	btScalar distance0 = b2Dot(normal, vIn[0].v) - offset;
+	btScalar distance1 = b2Dot(normal, vIn[1].v) - offset;
+
+	// If the points are behind the plane
+	if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
+	if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];
+
+	// If the points are on different sides of the plane
+	if (distance0 * distance1 < 0.0f)
+	{
+		// Find intersection point of edge and plane
+		btScalar interp = distance0 / (distance0 - distance1);
+		vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
+		if (distance0 > 0.0f)
+		{
+			vOut[numOut].id = vIn[0].id;
+		}
+		else
+		{
+			vOut[numOut].id = vIn[1].id;
+		}
+		++numOut;
+	}
+
+	return numOut;
+}
+
+// Find the separation between poly1 and poly2 for a give edge normal on poly1.
+static btScalar EdgeSeparation(const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+							  const btBox2dShape* poly2, const btTransform& xf2)
+{
+	const btVector3* vertices1 = poly1->getVertices();
+	const btVector3* normals1 = poly1->getNormals();
+
+	int count2 = poly2->getVertexCount();
+	const btVector3* vertices2 = poly2->getVertices();
+
+	btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+	// Convert normal from poly1's frame into poly2's frame.
+	btVector3 normal1World = b2Mul(xf1.getBasis(), normals1[edge1]);
+	btVector3 normal1 = b2MulT(xf2.getBasis(), normal1World);
+
+	// Find support vertex on poly2 for -normal.
+	int index = 0;
+	btScalar minDot = BT_LARGE_FLOAT;
+
+	for (int i = 0; i < count2; ++i)
+	{
+		btScalar dot = b2Dot(vertices2[i], normal1);
+		if (dot < minDot)
+		{
+			minDot = dot;
+			index = i;
+		}
+	}
+
+	btVector3 v1 = b2Mul(xf1, vertices1[edge1]);
+	btVector3 v2 = b2Mul(xf2, vertices2[index]);
+	btScalar separation = b2Dot(v2 - v1, normal1World);
+	return separation;
+}
+
+// Find the max separation between poly1 and poly2 using edge normals from poly1.
+static btScalar FindMaxSeparation(int* edgeIndex,
+								 const btBox2dShape* poly1, const btTransform& xf1,
+								 const btBox2dShape* poly2, const btTransform& xf2)
+{
+	int count1 = poly1->getVertexCount();
+	const btVector3* normals1 = poly1->getNormals();
+
+	// Vector pointing from the centroid of poly1 to the centroid of poly2.
+	btVector3 d = b2Mul(xf2, poly2->getCentroid()) - b2Mul(xf1, poly1->getCentroid());
+	btVector3 dLocal1 = b2MulT(xf1.getBasis(), d);
+
+	// Find edge normal on poly1 that has the largest projection onto d.
+	int edge = 0;
+	btScalar maxDot = -BT_LARGE_FLOAT;
+	for (int i = 0; i < count1; ++i)
+	{
+		btScalar dot = b2Dot(normals1[i], dLocal1);
+		if (dot > maxDot)
+		{
+			maxDot = dot;
+			edge = i;
+		}
+	}
+
+	// Get the separation for the edge normal.
+	btScalar s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+	if (s > 0.0f)
+	{
+		return s;
+	}
+
+	// Check the separation for the previous edge normal.
+	int prevEdge = edge - 1 >= 0 ? edge - 1 : count1 - 1;
+	btScalar sPrev = EdgeSeparation(poly1, xf1, prevEdge, poly2, xf2);
+	if (sPrev > 0.0f)
+	{
+		return sPrev;
+	}
+
+	// Check the separation for the next edge normal.
+	int nextEdge = edge + 1 < count1 ? edge + 1 : 0;
+	btScalar sNext = EdgeSeparation(poly1, xf1, nextEdge, poly2, xf2);
+	if (sNext > 0.0f)
+	{
+		return sNext;
+	}
+
+	// Find the best edge and the search direction.
+	int bestEdge;
+	btScalar bestSeparation;
+	int increment;
+	if (sPrev > s && sPrev > sNext)
+	{
+		increment = -1;
+		bestEdge = prevEdge;
+		bestSeparation = sPrev;
+	}
+	else if (sNext > s)
+	{
+		increment = 1;
+		bestEdge = nextEdge;
+		bestSeparation = sNext;
+	}
+	else
+	{
+		*edgeIndex = edge;
+		return s;
+	}
+
+	// Perform a local search for the best edge normal.
+	for ( ; ; )
+	{
+		if (increment == -1)
+			edge = bestEdge - 1 >= 0 ? bestEdge - 1 : count1 - 1;
+		else
+			edge = bestEdge + 1 < count1 ? bestEdge + 1 : 0;
+
+		s = EdgeSeparation(poly1, xf1, edge, poly2, xf2);
+		if (s > 0.0f)
+		{
+			return s;
+		}
+
+		if (s > bestSeparation)
+		{
+			bestEdge = edge;
+			bestSeparation = s;
+		}
+		else
+		{
+			break;
+		}
+	}
+
+	*edgeIndex = bestEdge;
+	return bestSeparation;
+}
+
+static void FindIncidentEdge(ClipVertex c[2],
+							 const btBox2dShape* poly1, const btTransform& xf1, int edge1,
+							 const btBox2dShape* poly2, const btTransform& xf2)
+{
+	const btVector3* normals1 = poly1->getNormals();
+
+	int count2 = poly2->getVertexCount();
+	const btVector3* vertices2 = poly2->getVertices();
+	const btVector3* normals2 = poly2->getNormals();
+
+	btAssert(0 <= edge1 && edge1 < poly1->getVertexCount());
+
+	// Get the normal of the reference edge in poly2's frame.
+	btVector3 normal1 = b2MulT(xf2.getBasis(), b2Mul(xf1.getBasis(), normals1[edge1]));
+
+	// Find the incident edge on poly2.
+	int index = 0;
+	btScalar minDot = BT_LARGE_FLOAT;
+	for (int i = 0; i < count2; ++i)
+	{
+		btScalar dot = b2Dot(normal1, normals2[i]);
+		if (dot < minDot)
+		{
+			minDot = dot;
+			index = i;
+		}
+	}
+
+	// Build the clip vertices for the incident edge.
+	int i1 = index;
+	int i2 = i1 + 1 < count2 ? i1 + 1 : 0;
+
+	c[0].v = b2Mul(xf2, vertices2[i1]);
+//	c[0].id.features.referenceEdge = (unsigned char)edge1;
+//	c[0].id.features.incidentEdge = (unsigned char)i1;
+//	c[0].id.features.incidentVertex = 0;
+
+	c[1].v = b2Mul(xf2, vertices2[i2]);
+//	c[1].id.features.referenceEdge = (unsigned char)edge1;
+//	c[1].id.features.incidentEdge = (unsigned char)i2;
+//	c[1].id.features.incidentVertex = 1;
+}
+
+// Find edge normal of max separation on A - return if separating axis is found
+// Find edge normal of max separation on B - return if separation axis is found
+// Choose reference edge as min(minA, minB)
+// Find incident edge
+// Clip
+
+// The normal points from 1 to 2
+void b2CollidePolygons(btManifoldResult* manifold,
+					  const btBox2dShape* polyA, const btTransform& xfA,
+					  const btBox2dShape* polyB, const btTransform& xfB)
+{
+
+	int edgeA = 0;
+	btScalar separationA = FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB);
+	if (separationA > 0.0f)
+		return;
+
+	int edgeB = 0;
+	btScalar separationB = FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA);
+	if (separationB > 0.0f)
+		return;
+
+	const btBox2dShape* poly1;	// reference poly
+	const btBox2dShape* poly2;	// incident poly
+	btTransform xf1, xf2;
+	int edge1;		// reference edge
+	unsigned char flip;
+	const btScalar k_relativeTol = 0.98f;
+	const btScalar k_absoluteTol = 0.001f;
+
+	// TODO_ERIN use "radius" of poly for absolute tolerance.
+	if (separationB > k_relativeTol * separationA + k_absoluteTol)
+	{
+		poly1 = polyB;
+		poly2 = polyA;
+		xf1 = xfB;
+		xf2 = xfA;
+		edge1 = edgeB;
+		flip = 1;
+	}
+	else
+	{
+		poly1 = polyA;
+		poly2 = polyB;
+		xf1 = xfA;
+		xf2 = xfB;
+		edge1 = edgeA;
+		flip = 0;
+	}
+
+	ClipVertex incidentEdge[2];
+	FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2);
+
+	int count1 = poly1->getVertexCount();
+	const btVector3* vertices1 = poly1->getVertices();
+
+	btVector3 v11 = vertices1[edge1];
+	btVector3 v12 = edge1 + 1 < count1 ? vertices1[edge1+1] : vertices1[0];
+
+	btVector3 dv = v12 - v11;
+	btVector3 sideNormal = b2Mul(xf1.getBasis(), v12 - v11);
+	sideNormal.normalize();
+	btVector3 frontNormal = btCrossS(sideNormal, 1.0f);
+	
+	
+	v11 = b2Mul(xf1, v11);
+	v12 = b2Mul(xf1, v12);
+
+	btScalar frontOffset = b2Dot(frontNormal, v11);
+	btScalar sideOffset1 = -b2Dot(sideNormal, v11);
+	btScalar sideOffset2 = b2Dot(sideNormal, v12);
+
+	// Clip incident edge against extruded edge1 side edges.
+	ClipVertex clipPoints1[2];
+	clipPoints1[0].v.setValue(0,0,0);
+	clipPoints1[1].v.setValue(0,0,0);
+
+	ClipVertex clipPoints2[2];
+	clipPoints2[0].v.setValue(0,0,0);
+	clipPoints2[1].v.setValue(0,0,0);
+
+
+	int np;
+
+	// Clip to box side 1
+	np = ClipSegmentToLine(clipPoints1, incidentEdge, -sideNormal, sideOffset1);
+
+	if (np < 2)
+		return;
+
+	// Clip to negative box side 1
+	np = ClipSegmentToLine(clipPoints2, clipPoints1,  sideNormal, sideOffset2);
+
+	if (np < 2)
+	{
+		return;
+	}
+
+	// Now clipPoints2 contains the clipped points.
+	btVector3 manifoldNormal = flip ? -frontNormal : frontNormal;
+
+	int pointCount = 0;
+	for (int i = 0; i < b2_maxManifoldPoints; ++i)
+	{
+		btScalar separation = b2Dot(frontNormal, clipPoints2[i].v) - frontOffset;
+
+		if (separation <= 0.0f)
+		{
+			
+			//b2ManifoldPoint* cp = manifold->points + pointCount;
+			//btScalar separation = separation;
+			//cp->localPoint1 = b2MulT(xfA, clipPoints2[i].v);
+			//cp->localPoint2 = b2MulT(xfB, clipPoints2[i].v);
+
+			manifold->addContactPoint(-manifoldNormal,clipPoints2[i].v,separation);
+
+//			cp->id = clipPoints2[i].id;
+//			cp->id.features.flip = flip;
+			++pointCount;
+		}
+	}
+
+//	manifold->pointCount = pointCount;}
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
new file mode 100644
index 0000000..2134217
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBox2dBox2dCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+#define BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBox2dBox2dCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	
+public:
+	btBox2dBox2dCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btBox2dBox2dCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+	virtual ~btBox2dBox2dCollisionAlgorithm();
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			int bbsize = sizeof(btBox2dBox2dCollisionAlgorithm);
+			void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+			return new(ptr) btBox2dBox2dCollisionAlgorithm(0,ci,body0,body1);
+		}
+	};
+
+};
+
+#endif //BOX_2D_BOX_2D__COLLISION_ALGORITHM_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
new file mode 100644
index 0000000..4962885
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp
@@ -0,0 +1,85 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "btBoxBoxDetector.h"
+
+#define USE_PERSISTENT_CONTACTS 1
+
+btBoxBoxCollisionAlgorithm::btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* obj0,btCollisionObject* obj1)
+: btActivatingCollisionAlgorithm(ci,obj0,obj1),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(obj0,obj1))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(obj0,obj1);
+		m_ownManifold = true;
+	}
+}
+
+btBoxBoxCollisionAlgorithm::~btBoxBoxCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btBoxBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject*	col0 = body0;
+	btCollisionObject*	col1 = body1;
+	btBoxShape* box0 = (btBoxShape*)col0->getCollisionShape();
+	btBoxShape* box1 = (btBoxShape*)col1->getCollisionShape();
+
+
+
+	/// report a contact. internally this will be kept persistent, and contact reduction is done
+	resultOut->setPersistentManifold(m_manifoldPtr);
+#ifndef USE_PERSISTENT_CONTACTS	
+	m_manifoldPtr->clearManifold();
+#endif //USE_PERSISTENT_CONTACTS
+
+	btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+	input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+	input.m_transformA = body0->getWorldTransform();
+	input.m_transformB = body1->getWorldTransform();
+
+	btBoxBoxDetector detector(box0,box1);
+	detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+#ifdef USE_PERSISTENT_CONTACTS
+	//  refreshContactPoints is only necessary when using persistent contact points. otherwise all points are newly added
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+#endif //USE_PERSISTENT_CONTACTS
+
+}
+
+btScalar btBoxBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* /*body0*/,btCollisionObject* /*body1*/,const btDispatcherInfo& /*dispatchInfo*/,btManifoldResult* /*resultOut*/)
+{
+	//not yet
+	return 1.f;
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
new file mode 100644
index 0000000..e7d2cc2
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BOX_BOX__COLLISION_ALGORITHM_H
+#define BOX_BOX__COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+
+class btPersistentManifold;
+
+///box-box collision detection
+class btBoxBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	
+public:
+	btBoxBoxCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btBoxBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+	virtual ~btBoxBoxCollisionAlgorithm();
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			int bbsize = sizeof(btBoxBoxCollisionAlgorithm);
+			void* ptr = ci.m_dispatcher1->allocateCollisionAlgorithm(bbsize);
+			return new(ptr) btBoxBoxCollisionAlgorithm(0,ci,body0,body1);
+		}
+	};
+
+};
+
+#endif //BOX_BOX__COLLISION_ALGORITHM_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
new file mode 100644
index 0000000..a7c8cf1
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp
@@ -0,0 +1,718 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved.  Email: russ at q12.org   Web: www.q12.org
+ Bullet Continuous Collision Detection and Physics Library
+ Bullet is Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///ODE box-box collision detection is adapted to work with Bullet
+
+#include "btBoxBoxDetector.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+
+#include <float.h>
+#include <string.h>
+
+btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
+: m_box1(box1),
+m_box2(box2)
+{
+
+}
+
+
+// given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
+// generate contact points. this returns 0 if there is no contact otherwise
+// it returns the number of contacts generated.
+// `normal' returns the contact normal.
+// `depth' returns the maximum penetration depth along that normal.
+// `return_code' returns a number indicating the type of contact that was
+// detected:
+//        1,2,3 = box 2 intersects with a face of box 1
+//        4,5,6 = box 1 intersects with a face of box 2
+//        7..15 = edge-edge contact
+// `maxc' is the maximum number of contacts allowed to be generated, i.e.
+// the size of the `contact' array.
+// `contact' and `skip' are the contact array information provided to the
+// collision functions. this function only fills in the position and depth
+// fields.
+struct dContactGeom;
+#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
+#define dInfinity FLT_MAX
+
+
+/*PURE_INLINE btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
+PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
+PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
+*/
+static btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
+static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
+static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
+static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
+#define dMULTIPLYOP1_331(A,op,B,C) \
+{\
+  (A)[0] op dDOT41((B),(C)); \
+  (A)[1] op dDOT41((B+1),(C)); \
+  (A)[2] op dDOT41((B+2),(C)); \
+}
+
+#define dMULTIPLYOP0_331(A,op,B,C) \
+{ \
+  (A)[0] op dDOT((B),(C)); \
+  (A)[1] op dDOT((B+4),(C)); \
+  (A)[2] op dDOT((B+8),(C)); \
+} 
+
+#define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
+#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
+
+typedef btScalar dMatrix3[4*3];
+
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+			   const btVector3& pb, const btVector3& ub,
+			   btScalar *alpha, btScalar *beta);
+void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
+			   const btVector3& pb, const btVector3& ub,
+			   btScalar *alpha, btScalar *beta)
+{
+  btVector3 p;
+  p[0] = pb[0] - pa[0];
+  p[1] = pb[1] - pa[1];
+  p[2] = pb[2] - pa[2];
+  btScalar uaub = dDOT(ua,ub);
+  btScalar q1 =  dDOT(ua,p);
+  btScalar q2 = -dDOT(ub,p);
+  btScalar d = 1-uaub*uaub;
+  if (d <= btScalar(0.0001f)) {
+    // @@@ this needs to be made more robust
+    *alpha = 0;
+    *beta  = 0;
+  }
+  else {
+    d = 1.f/d;
+    *alpha = (q1 + uaub*q2)*d;
+    *beta  = (uaub*q1 + q2)*d;
+  }
+}
+
+
+
+// find all the intersection points between the 2D rectangle with vertices
+// at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
+// (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
+//
+// the intersection points are returned as x,y pairs in the 'ret' array.
+// the number of intersection points is returned by the function (this will
+// be in the range 0 to 8).
+
+static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
+{
+  // q (and r) contain nq (and nr) coordinate points for the current (and
+  // chopped) polygons
+  int nq=4,nr=0;
+  btScalar buffer[16];
+  btScalar *q = p;
+  btScalar *r = ret;
+  for (int dir=0; dir <= 1; dir++) {
+    // direction notation: xy[0] = x axis, xy[1] = y axis
+    for (int sign=-1; sign <= 1; sign += 2) {
+      // chop q along the line xy[dir] = sign*h[dir]
+      btScalar *pq = q;
+      btScalar *pr = r;
+      nr = 0;
+      for (int i=nq; i > 0; i--) {
+	// go through all points in q and all lines between adjacent points
+	if (sign*pq[dir] < h[dir]) {
+	  // this point is inside the chopping line
+	  pr[0] = pq[0];
+	  pr[1] = pq[1];
+	  pr += 2;
+	  nr++;
+	  if (nr & 8) {
+	    q = r;
+	    goto done;
+	  }
+	}
+	btScalar *nextq = (i > 1) ? pq+2 : q;
+	if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
+	  // this line crosses the chopping line
+	  pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
+	    (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
+	  pr[dir] = sign*h[dir];
+	  pr += 2;
+	  nr++;
+	  if (nr & 8) {
+	    q = r;
+	    goto done;
+	  }
+	}
+	pq += 2;
+      }
+      q = r;
+      r = (q==ret) ? buffer : ret;
+      nq = nr;
+    }
+  }
+ done:
+  if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
+  return nr;
+}
+
+
+#define M__PI 3.14159265f
+
+// given n points in the plane (array p, of size 2*n), generate m points that
+// best represent the whole set. the definition of 'best' here is not
+// predetermined - the idea is to select points that give good box-box
+// collision detection behavior. the chosen point indexes are returned in the
+// array iret (of size m). 'i0' is always the first entry in the array.
+// n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
+// in the range [0..n-1].
+
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
+void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
+{
+  // compute the centroid of the polygon in cx,cy
+  int i,j;
+  btScalar a,cx,cy,q;
+  if (n==1) {
+    cx = p[0];
+    cy = p[1];
+  }
+  else if (n==2) {
+    cx = btScalar(0.5)*(p[0] + p[2]);
+    cy = btScalar(0.5)*(p[1] + p[3]);
+  }
+  else {
+    a = 0;
+    cx = 0;
+    cy = 0;
+    for (i=0; i<(n-1); i++) {
+      q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
+      a += q;
+      cx += q*(p[i*2]+p[i*2+2]);
+      cy += q*(p[i*2+1]+p[i*2+3]);
+    }
+    q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
+	if (btFabs(a+q) > SIMD_EPSILON)
+	{
+		a = 1.f/(btScalar(3.0)*(a+q));
+	} else
+	{
+		a=BT_LARGE_FLOAT;
+	}
+    cx = a*(cx + q*(p[n*2-2]+p[0]));
+    cy = a*(cy + q*(p[n*2-1]+p[1]));
+  }
+
+  // compute the angle of each point w.r.t. the centroid
+  btScalar A[8];
+  for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
+
+  // search for points that have angles closest to A[i0] + i*(2*pi/m).
+  int avail[8];
+  for (i=0; i<n; i++) avail[i] = 1;
+  avail[i0] = 0;
+  iret[0] = i0;
+  iret++;
+  for (j=1; j<m; j++) {
+    a = btScalar(j)*(2*M__PI/m) + A[i0];
+    if (a > M__PI) a -= 2*M__PI;
+    btScalar maxdiff=1e9,diff;
+
+    *iret = i0;			// iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
+
+    for (i=0; i<n; i++) {
+      if (avail[i]) {
+	diff = btFabs (A[i]-a);
+	if (diff > M__PI) diff = 2*M__PI - diff;
+	if (diff < maxdiff) {
+	  maxdiff = diff;
+	  *iret = i;
+	}
+      }
+    }
+#if defined(DEBUG) || defined (_DEBUG)
+    btAssert (*iret != i0);	// ensure iret got set
+#endif
+    avail[*iret] = 0;
+    iret++;
+  }
+}
+
+
+
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+	     const btVector3& side1, const btVector3& p2,
+	     const dMatrix3 R2, const btVector3& side2,
+	     btVector3& normal, btScalar *depth, int *return_code,
+		 int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
+int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
+	     const btVector3& side1, const btVector3& p2,
+	     const dMatrix3 R2, const btVector3& side2,
+	     btVector3& normal, btScalar *depth, int *return_code,
+		 int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
+{
+  const btScalar fudge_factor = btScalar(1.05);
+  btVector3 p,pp,normalC(0.f,0.f,0.f);
+  const btScalar *normalR = 0;
+  btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
+    Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
+  int i,j,invert_normal,code;
+
+  // get vector from centers of box 1 to box 2, relative to box 1
+  p = p2 - p1;
+  dMULTIPLY1_331 (pp,R1,p);		// get pp = p relative to body 1
+
+  // get side lengths / 2
+  A[0] = side1[0]*btScalar(0.5);
+  A[1] = side1[1]*btScalar(0.5);
+  A[2] = side1[2]*btScalar(0.5);
+  B[0] = side2[0]*btScalar(0.5);
+  B[1] = side2[1]*btScalar(0.5);
+  B[2] = side2[2]*btScalar(0.5);
+
+  // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
+  R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
+  R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
+  R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
+
+  Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
+  Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
+  Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
+
+  // for all 15 possible separating axes:
+  //   * see if the axis separates the boxes. if so, return 0.
+  //   * find the depth of the penetration along the separating axis (s2)
+  //   * if this is the largest depth so far, record it.
+  // the normal vector will be set to the separating axis with the smallest
+  // depth. note: normalR is set to point to a column of R1 or R2 if that is
+  // the smallest depth normal so far. otherwise normalR is 0 and normalC is
+  // set to a vector relative to body 1. invert_normal is 1 if the sign of
+  // the normal should be flipped.
+
+#define TST(expr1,expr2,norm,cc) \
+  s2 = btFabs(expr1) - (expr2); \
+  if (s2 > 0) return 0; \
+  if (s2 > s) { \
+    s = s2; \
+    normalR = norm; \
+    invert_normal = ((expr1) < 0); \
+    code = (cc); \
+  }
+
+  s = -dInfinity;
+  invert_normal = 0;
+  code = 0;
+
+  // separating axis = u1,u2,u3
+  TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
+  TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
+  TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
+
+  // separating axis = v1,v2,v3
+  TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
+  TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
+  TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
+
+  // note: cross product axes need to be scaled when s is computed.
+  // normal (n1,n2,n3) is relative to box 1.
+#undef TST
+#define TST(expr1,expr2,n1,n2,n3,cc) \
+  s2 = btFabs(expr1) - (expr2); \
+  if (s2 > SIMD_EPSILON) return 0; \
+  l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
+  if (l > SIMD_EPSILON) { \
+    s2 /= l; \
+    if (s2*fudge_factor > s) { \
+      s = s2; \
+      normalR = 0; \
+      normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
+      invert_normal = ((expr1) < 0); \
+      code = (cc); \
+    } \
+  }
+
+  btScalar fudge2 (1.0e-5f);
+
+  Q11 += fudge2;
+  Q12 += fudge2;
+  Q13 += fudge2;
+
+  Q21 += fudge2;
+  Q22 += fudge2;
+  Q23 += fudge2;
+
+  Q31 += fudge2;
+  Q32 += fudge2;
+  Q33 += fudge2;
+
+  // separating axis = u1 x (v1,v2,v3)
+  TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
+  TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
+  TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
+
+  // separating axis = u2 x (v1,v2,v3)
+  TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
+  TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
+  TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
+
+  // separating axis = u3 x (v1,v2,v3)
+  TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
+  TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
+  TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
+
+#undef TST
+
+  if (!code) return 0;
+
+  // if we get to this point, the boxes interpenetrate. compute the normal
+  // in global coordinates.
+  if (normalR) {
+    normal[0] = normalR[0];
+    normal[1] = normalR[4];
+    normal[2] = normalR[8];
+  }
+  else {
+    dMULTIPLY0_331 (normal,R1,normalC);
+  }
+  if (invert_normal) {
+    normal[0] = -normal[0];
+    normal[1] = -normal[1];
+    normal[2] = -normal[2];
+  }
+  *depth = -s;
+
+  // compute contact point(s)
+
+  if (code > 6) {
+    // an edge from box 1 touches an edge from box 2.
+    // find a point pa on the intersecting edge of box 1
+    btVector3 pa;
+    btScalar sign;
+    for (i=0; i<3; i++) pa[i] = p1[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
+      for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
+    }
+
+    // find a point pb on the intersecting edge of box 2
+    btVector3 pb;
+    for (i=0; i<3; i++) pb[i] = p2[i];
+    for (j=0; j<3; j++) {
+      sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
+      for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
+    }
+
+    btScalar alpha,beta;
+    btVector3 ua,ub;
+    for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
+    for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
+
+    dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
+    for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
+    for (i=0; i<3; i++) pb[i] += ub[i]*beta;
+
+	{
+		
+		//contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
+		//contact[0].depth = *depth;
+		btVector3 pointInWorld;
+
+#ifdef USE_CENTER_POINT
+	    for (i=0; i<3; i++) 
+			pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
+		output.addContactPoint(-normal,pointInWorld,-*depth);
+#else
+		output.addContactPoint(-normal,pb,-*depth);
+
+#endif //
+		*return_code = code;
+	}
+    return 1;
+  }
+
+  // okay, we have a face-something intersection (because the separating
+  // axis is perpendicular to a face). define face 'a' to be the reference
+  // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
+  // the incident face (the closest face of the other box).
+
+  const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
+  if (code <= 3) {
+    Ra = R1;
+    Rb = R2;
+    pa = p1;
+    pb = p2;
+    Sa = A;
+    Sb = B;
+  }
+  else {
+    Ra = R2;
+    Rb = R1;
+    pa = p2;
+    pb = p1;
+    Sa = B;
+    Sb = A;
+  }
+
+  // nr = normal vector of reference face dotted with axes of incident box.
+  // anr = absolute values of nr.
+  btVector3 normal2,nr,anr;
+  if (code <= 3) {
+    normal2[0] = normal[0];
+    normal2[1] = normal[1];
+    normal2[2] = normal[2];
+  }
+  else {
+    normal2[0] = -normal[0];
+    normal2[1] = -normal[1];
+    normal2[2] = -normal[2];
+  }
+  dMULTIPLY1_331 (nr,Rb,normal2);
+  anr[0] = btFabs (nr[0]);
+  anr[1] = btFabs (nr[1]);
+  anr[2] = btFabs (nr[2]);
+
+  // find the largest compontent of anr: this corresponds to the normal
+  // for the indident face. the other axis numbers of the indicent face
+  // are stored in a1,a2.
+  int lanr,a1,a2;
+  if (anr[1] > anr[0]) {
+    if (anr[1] > anr[2]) {
+      a1 = 0;
+      lanr = 1;
+      a2 = 2;
+    }
+    else {
+      a1 = 0;
+      a2 = 1;
+      lanr = 2;
+    }
+  }
+  else {
+    if (anr[0] > anr[2]) {
+      lanr = 0;
+      a1 = 1;
+      a2 = 2;
+    }
+    else {
+      a1 = 0;
+      a2 = 1;
+      lanr = 2;
+    }
+  }
+
+  // compute center point of incident face, in reference-face coordinates
+  btVector3 center;
+  if (nr[lanr] < 0) {
+    for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
+  }
+  else {
+    for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
+  }
+
+  // find the normal and non-normal axis numbers of the reference box
+  int codeN,code1,code2;
+  if (code <= 3) codeN = code-1; else codeN = code-4;
+  if (codeN==0) {
+    code1 = 1;
+    code2 = 2;
+  }
+  else if (codeN==1) {
+    code1 = 0;
+    code2 = 2;
+  }
+  else {
+    code1 = 0;
+    code2 = 1;
+  }
+
+  // find the four corners of the incident face, in reference-face coordinates
+  btScalar quad[8];	// 2D coordinate of incident face (x,y pairs)
+  btScalar c1,c2,m11,m12,m21,m22;
+  c1 = dDOT14 (center,Ra+code1);
+  c2 = dDOT14 (center,Ra+code2);
+  // optimize this? - we have already computed this data above, but it is not
+  // stored in an easy-to-index format. for now it's quicker just to recompute
+  // the four dot products.
+  m11 = dDOT44 (Ra+code1,Rb+a1);
+  m12 = dDOT44 (Ra+code1,Rb+a2);
+  m21 = dDOT44 (Ra+code2,Rb+a1);
+  m22 = dDOT44 (Ra+code2,Rb+a2);
+  {
+    btScalar k1 = m11*Sb[a1];
+    btScalar k2 = m21*Sb[a1];
+    btScalar k3 = m12*Sb[a2];
+    btScalar k4 = m22*Sb[a2];
+    quad[0] = c1 - k1 - k3;
+    quad[1] = c2 - k2 - k4;
+    quad[2] = c1 - k1 + k3;
+    quad[3] = c2 - k2 + k4;
+    quad[4] = c1 + k1 + k3;
+    quad[5] = c2 + k2 + k4;
+    quad[6] = c1 + k1 - k3;
+    quad[7] = c2 + k2 - k4;
+  }
+
+  // find the size of the reference face
+  btScalar rect[2];
+  rect[0] = Sa[code1];
+  rect[1] = Sa[code2];
+
+  // intersect the incident and reference faces
+  btScalar ret[16];
+  int n = intersectRectQuad2 (rect,quad,ret);
+  if (n < 1) return 0;		// this should never happen
+
+  // convert the intersection points into reference-face coordinates,
+  // and compute the contact position and depth for each point. only keep
+  // those points that have a positive (penetrating) depth. delete points in
+  // the 'ret' array as necessary so that 'point' and 'ret' correspond.
+  btScalar point[3*8];		// penetrating contact points
+  btScalar dep[8];			// depths for those points
+  btScalar det1 = 1.f/(m11*m22 - m12*m21);
+  m11 *= det1;
+  m12 *= det1;
+  m21 *= det1;
+  m22 *= det1;
+  int cnum = 0;			// number of penetrating contact points found
+  for (j=0; j < n; j++) {
+    btScalar k1 =  m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
+    btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
+    for (i=0; i<3; i++) point[cnum*3+i] =
+			  center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
+    dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
+    if (dep[cnum] >= 0) {
+      ret[cnum*2] = ret[j*2];
+      ret[cnum*2+1] = ret[j*2+1];
+      cnum++;
+    }
+  }
+  if (cnum < 1) return 0;	// this should never happen
+
+  // we can't generate more contacts than we actually have
+  if (maxc > cnum) maxc = cnum;
+  if (maxc < 1) maxc = 1;
+
+  if (cnum <= maxc) {
+
+	  if (code<4) 
+	  {
+    // we have less contacts than we need, so we use them all
+    for (j=0; j < cnum; j++) 
+	{
+		btVector3 pointInWorld;
+		for (i=0; i<3; i++) 
+			pointInWorld[i] = point[j*3+i] + pa[i];
+		output.addContactPoint(-normal,pointInWorld,-dep[j]);
+
+    }
+	  } else
+	  {
+		  // we have less contacts than we need, so we use them all
+		for (j=0; j < cnum; j++) 
+		{
+			btVector3 pointInWorld;
+			for (i=0; i<3; i++) 
+				pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j];
+				//pointInWorld[i] = point[j*3+i] + pa[i];
+			output.addContactPoint(-normal,pointInWorld,-dep[j]);
+		}
+	  }
+  }
+  else {
+    // we have more contacts than are wanted, some of them must be culled.
+    // find the deepest point, it is always the first contact.
+    int i1 = 0;
+    btScalar maxdepth = dep[0];
+    for (i=1; i<cnum; i++) {
+      if (dep[i] > maxdepth) {
+	maxdepth = dep[i];
+	i1 = i;
+      }
+    }
+
+    int iret[8];
+    cullPoints2 (cnum,ret,maxc,i1,iret);
+
+    for (j=0; j < maxc; j++) {
+//      dContactGeom *con = CONTACT(contact,skip*j);
+  //    for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
+    //  con->depth = dep[iret[j]];
+
+		btVector3 posInWorld;
+		for (i=0; i<3; i++) 
+			posInWorld[i] = point[iret[j]*3+i] + pa[i];
+		if (code<4) 
+	   {
+			output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
+		} else
+		{
+			output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]);
+		}
+    }
+    cnum = maxc;
+  }
+
+  *return_code = code;
+  return cnum;
+}
+
+void	btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
+{
+	
+	const btTransform& transformA = input.m_transformA;
+	const btTransform& transformB = input.m_transformB;
+	
+	int skip = 0;
+	dContactGeom *contact = 0;
+
+	dMatrix3 R1;
+	dMatrix3 R2;
+
+	for (int j=0;j<3;j++)
+	{
+		R1[0+4*j] = transformA.getBasis()[j].x();
+		R2[0+4*j] = transformB.getBasis()[j].x();
+
+		R1[1+4*j] = transformA.getBasis()[j].y();
+		R2[1+4*j] = transformB.getBasis()[j].y();
+
+
+		R1[2+4*j] = transformA.getBasis()[j].z();
+		R2[2+4*j] = transformB.getBasis()[j].z();
+
+	}
+
+	
+
+	btVector3 normal;
+	btScalar depth;
+	int return_code;
+	int maxc = 4;
+
+
+	dBoxBox2 (transformA.getOrigin(), 
+	R1,
+	2.f*m_box1->getHalfExtentsWithMargin(),
+	transformB.getOrigin(),
+	R2, 
+	2.f*m_box2->getHalfExtentsWithMargin(),
+	normal, &depth, &return_code,
+	maxc, contact, skip,
+	output
+	);
+
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
new file mode 100644
index 0000000..605294d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btBoxBoxDetector.h
@@ -0,0 +1,44 @@
+/*
+ * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
+ * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
+ * All rights reserved.  Email: russ at q12.org   Web: www.q12.org
+
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BOX_BOX_DETECTOR_H
+#define BOX_BOX_DETECTOR_H
+
+
+class btBoxShape;
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+
+/// btBoxBoxDetector wraps the ODE box-box collision detector
+/// re-distributed under the Zlib license with permission from Russell L. Smith
+struct btBoxBoxDetector : public btDiscreteCollisionDetectorInterface
+{
+	btBoxShape* m_box1;
+	btBoxShape* m_box2;
+
+public:
+
+	btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2);
+
+	virtual ~btBoxBoxDetector() {};
+
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+};
+
+#endif //BT_BOX_BOX_DETECTOR_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
new file mode 100644
index 0000000..1db51a3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionConfiguration.h
@@ -0,0 +1,47 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_COLLISION_CONFIGURATION
+#define BT_COLLISION_CONFIGURATION
+struct btCollisionAlgorithmCreateFunc;
+
+class btStackAlloc;
+class btPoolAllocator;
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator size, default collision algorithms and persistent manifold pool size
+///@todo: describe the meaning
+class	btCollisionConfiguration
+{
+
+public:
+
+	virtual ~btCollisionConfiguration()
+	{
+	}
+
+	///memory pools
+	virtual btPoolAllocator* getPersistentManifoldPool() = 0;
+
+	virtual btPoolAllocator* getCollisionAlgorithmPool() = 0;
+
+	virtual btStackAlloc*	getStackAllocator() = 0;
+
+	virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1) =0;
+
+};
+
+#endif //BT_COLLISION_CONFIGURATION
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
new file mode 100644
index 0000000..a6da5f6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionCreateFunc.h
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COLLISION_CREATE_FUNC
+#define COLLISION_CREATE_FUNC
+
+#include "LinearMath/btAlignedObjectArray.h"
+class btCollisionAlgorithm;
+class btCollisionObject;
+
+struct btCollisionAlgorithmConstructionInfo;
+
+///Used by the btCollisionDispatcher to register and create instances for btCollisionAlgorithm
+struct btCollisionAlgorithmCreateFunc
+{
+	bool m_swapped;
+	
+	btCollisionAlgorithmCreateFunc()
+		:m_swapped(false)
+	{
+	}
+	virtual ~btCollisionAlgorithmCreateFunc(){};
+
+	virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& , btCollisionObject* body0,btCollisionObject* body1)
+	{
+		
+		(void)body0;
+		(void)body1;
+		return 0;
+	}
+};
+#endif //COLLISION_CREATE_FUNC
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
new file mode 100644
index 0000000..068a940
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.cpp
@@ -0,0 +1,303 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <stdio.h>
+
+#include "btCollisionDispatcher.h"
+
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btPoolAllocator.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+
+int gNumManifold = 0;
+
+#ifdef BT_DEBUG
+#include <stdio.h>
+#endif
+
+
+btCollisionDispatcher::btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration): 
+m_dispatcherFlags(btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD),
+	m_collisionConfiguration(collisionConfiguration)
+{
+	int i;
+
+	setNearCallback(defaultNearCallback);
+	
+	m_collisionAlgorithmPoolAllocator = collisionConfiguration->getCollisionAlgorithmPool();
+
+	m_persistentManifoldPoolAllocator = collisionConfiguration->getPersistentManifoldPool();
+
+	for (i=0;i<MAX_BROADPHASE_COLLISION_TYPES;i++)
+	{
+		for (int j=0;j<MAX_BROADPHASE_COLLISION_TYPES;j++)
+		{
+			m_doubleDispatch[i][j] = m_collisionConfiguration->getCollisionAlgorithmCreateFunc(i,j);
+			btAssert(m_doubleDispatch[i][j]);
+		}
+	}
+	
+	
+}
+
+
+void btCollisionDispatcher::registerCollisionCreateFunc(int proxyType0, int proxyType1, btCollisionAlgorithmCreateFunc *createFunc)
+{
+	m_doubleDispatch[proxyType0][proxyType1] = createFunc;
+}
+
+btCollisionDispatcher::~btCollisionDispatcher()
+{
+}
+
+btPersistentManifold*	btCollisionDispatcher::getNewManifold(void* b0,void* b1) 
+{ 
+	gNumManifold++;
+	
+	//btAssert(gNumManifold < 65535);
+	
+
+	btCollisionObject* body0 = (btCollisionObject*)b0;
+	btCollisionObject* body1 = (btCollisionObject*)b1;
+
+	//optional relative contact breaking threshold, turned on by default (use setDispatcherFlags to switch off feature for improved performance)
+	
+	btScalar contactBreakingThreshold =  (m_dispatcherFlags & btCollisionDispatcher::CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD) ? 
+		btMin(body0->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold) , body1->getCollisionShape()->getContactBreakingThreshold(gContactBreakingThreshold))
+		: gContactBreakingThreshold ;
+	
+	btScalar contactProcessingThreshold = btMin(body0->getContactProcessingThreshold(),body1->getContactProcessingThreshold());
+
+	void* mem = 0;
+	
+	if (m_persistentManifoldPoolAllocator->getFreeCount())
+	{
+		mem = m_persistentManifoldPoolAllocator->allocate(sizeof(btPersistentManifold));
+	} else
+	{
+		mem = btAlignedAlloc(sizeof(btPersistentManifold),16);
+
+	}
+	btPersistentManifold* manifold = new(mem) btPersistentManifold (body0,body1,0,contactBreakingThreshold,contactProcessingThreshold);
+	manifold->m_index1a = m_manifoldsPtr.size();
+	m_manifoldsPtr.push_back(manifold);
+
+	return manifold;
+}
+
+void btCollisionDispatcher::clearManifold(btPersistentManifold* manifold)
+{
+	manifold->clearManifold();
+}
+
+	
+void btCollisionDispatcher::releaseManifold(btPersistentManifold* manifold)
+{
+	
+	gNumManifold--;
+
+	//printf("releaseManifold: gNumManifold %d\n",gNumManifold);
+	clearManifold(manifold);
+
+	int findIndex = manifold->m_index1a;
+	btAssert(findIndex < m_manifoldsPtr.size());
+	m_manifoldsPtr.swap(findIndex,m_manifoldsPtr.size()-1);
+	m_manifoldsPtr[findIndex]->m_index1a = findIndex;
+	m_manifoldsPtr.pop_back();
+
+	manifold->~btPersistentManifold();
+	if (m_persistentManifoldPoolAllocator->validPtr(manifold))
+	{
+		m_persistentManifoldPoolAllocator->freeMemory(manifold);
+	} else
+	{
+		btAlignedFree(manifold);
+	}
+	
+}
+
+	
+
+btCollisionAlgorithm* btCollisionDispatcher::findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold)
+{
+	
+	btCollisionAlgorithmConstructionInfo ci;
+
+	ci.m_dispatcher1 = this;
+	ci.m_manifold = sharedManifold;
+	btCollisionAlgorithm* algo = m_doubleDispatch[body0->getCollisionShape()->getShapeType()][body1->getCollisionShape()->getShapeType()]->CreateCollisionAlgorithm(ci,body0,body1);
+
+	return algo;
+}
+
+
+
+
+bool	btCollisionDispatcher::needsResponse(btCollisionObject* body0,btCollisionObject* body1)
+{
+	//here you can do filtering
+	bool hasResponse = 
+		(body0->hasContactResponse() && body1->hasContactResponse());
+	//no response between two static/kinematic bodies:
+	hasResponse = hasResponse &&
+		((!body0->isStaticOrKinematicObject()) ||(! body1->isStaticOrKinematicObject()));
+	return hasResponse;
+}
+
+bool	btCollisionDispatcher::needsCollision(btCollisionObject* body0,btCollisionObject* body1)
+{
+	btAssert(body0);
+	btAssert(body1);
+
+	bool needsCollision = true;
+
+#ifdef BT_DEBUG
+	if (!(m_dispatcherFlags & btCollisionDispatcher::CD_STATIC_STATIC_REPORTED))
+	{
+		//broadphase filtering already deals with this
+		if ((body0->isStaticObject() || body0->isKinematicObject()) &&
+			(body1->isStaticObject() || body1->isKinematicObject()))
+		{
+			m_dispatcherFlags |= btCollisionDispatcher::CD_STATIC_STATIC_REPORTED;
+			printf("warning btCollisionDispatcher::needsCollision: static-static collision!\n");
+		}
+	}
+#endif //BT_DEBUG
+
+	if ((!body0->isActive()) && (!body1->isActive()))
+		needsCollision = false;
+	else if (!body0->checkCollideWith(body1))
+		needsCollision = false;
+	
+	return needsCollision ;
+
+}
+
+
+
+///interface for iterating all overlapping collision pairs, no matter how those pairs are stored (array, set, map etc)
+///this is useful for the collision dispatcher.
+class btCollisionPairCallback : public btOverlapCallback
+{
+	const btDispatcherInfo& m_dispatchInfo;
+	btCollisionDispatcher*	m_dispatcher;
+
+public:
+
+	btCollisionPairCallback(const btDispatcherInfo& dispatchInfo,btCollisionDispatcher*	dispatcher)
+	:m_dispatchInfo(dispatchInfo),
+	m_dispatcher(dispatcher)
+	{
+	}
+
+	/*btCollisionPairCallback& operator=(btCollisionPairCallback& other)
+	{
+		m_dispatchInfo = other.m_dispatchInfo;
+		m_dispatcher = other.m_dispatcher;
+		return *this;
+	}
+	*/
+
+
+	virtual ~btCollisionPairCallback() {}
+
+
+	virtual bool	processOverlap(btBroadphasePair& pair)
+	{
+		(*m_dispatcher->getNearCallback())(pair,*m_dispatcher,m_dispatchInfo);
+
+		return false;
+	}
+};
+
+
+
+void	btCollisionDispatcher::dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) 
+{
+	//m_blockedForChanges = true;
+
+	btCollisionPairCallback	collisionCallback(dispatchInfo,this);
+
+	pairCache->processAllOverlappingPairs(&collisionCallback,dispatcher);
+
+	//m_blockedForChanges = false;
+
+}
+
+
+
+
+//by default, Bullet will use this near callback
+void btCollisionDispatcher::defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo)
+{
+		btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+		btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+		if (dispatcher.needsCollision(colObj0,colObj1))
+		{
+			//dispatcher will keep algorithms persistent in the collision pair
+			if (!collisionPair.m_algorithm)
+			{
+				collisionPair.m_algorithm = dispatcher.findAlgorithm(colObj0,colObj1);
+			}
+
+			if (collisionPair.m_algorithm)
+			{
+				btManifoldResult contactPointResult(colObj0,colObj1);
+				
+				if (dispatchInfo.m_dispatchFunc == 		btDispatcherInfo::DISPATCH_DISCRETE)
+				{
+					//discrete collision detection query
+					collisionPair.m_algorithm->processCollision(colObj0,colObj1,dispatchInfo,&contactPointResult);
+				} else
+				{
+					//continuous collision detection query, time of impact (toi)
+					btScalar toi = collisionPair.m_algorithm->calculateTimeOfImpact(colObj0,colObj1,dispatchInfo,&contactPointResult);
+					if (dispatchInfo.m_timeOfImpact > toi)
+						dispatchInfo.m_timeOfImpact = toi;
+
+				}
+			}
+		}
+
+}
+
+
+void* btCollisionDispatcher::allocateCollisionAlgorithm(int size)
+{
+	if (m_collisionAlgorithmPoolAllocator->getFreeCount())
+	{
+		return m_collisionAlgorithmPoolAllocator->allocate(size);
+	}
+	
+	//warn user for overflow?
+	return	btAlignedAlloc(static_cast<size_t>(size), 16);
+}
+
+void btCollisionDispatcher::freeCollisionAlgorithm(void* ptr)
+{
+	if (m_collisionAlgorithmPoolAllocator->validPtr(ptr))
+	{
+		m_collisionAlgorithmPoolAllocator->freeMemory(ptr);
+	} else
+	{
+		btAlignedFree(ptr);
+	}
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
new file mode 100644
index 0000000..51b8ee5
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionDispatcher.h
@@ -0,0 +1,159 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COLLISION__DISPATCHER_H
+#define COLLISION__DISPATCHER_H
+
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+class btIDebugDraw;
+class btOverlappingPairCache;
+class btPoolAllocator;
+class btCollisionConfiguration;
+
+#include "btCollisionCreateFunc.h"
+
+#define USE_DISPATCH_REGISTRY_ARRAY 1
+
+class btCollisionDispatcher;
+///user can override this nearcallback for collision filtering and more finegrained control over collision detection
+typedef void (*btNearCallback)(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+
+///btCollisionDispatcher supports algorithms that handle ConvexConvex and ConvexConcave collision pairs.
+///Time of Impact, Closest Points and Penetration Depth.
+class btCollisionDispatcher : public btDispatcher
+{
+	int		m_dispatcherFlags;
+	
+	btAlignedObjectArray<btPersistentManifold*>	m_manifoldsPtr;
+
+	btManifoldResult	m_defaultManifoldResult;
+
+	btNearCallback		m_nearCallback;
+	
+	btPoolAllocator*	m_collisionAlgorithmPoolAllocator;
+
+	btPoolAllocator*	m_persistentManifoldPoolAllocator;
+
+	btCollisionAlgorithmCreateFunc* m_doubleDispatch[MAX_BROADPHASE_COLLISION_TYPES][MAX_BROADPHASE_COLLISION_TYPES];
+
+	btCollisionConfiguration*	m_collisionConfiguration;
+
+
+public:
+
+	enum DispatcherFlags
+	{
+		CD_STATIC_STATIC_REPORTED = 1,
+		CD_USE_RELATIVE_CONTACT_BREAKING_THRESHOLD = 2
+	};
+
+	int	getDispatcherFlags() const
+	{
+		return m_dispatcherFlags;
+	}
+
+	void	setDispatcherFlags(int flags)
+	{
+        (void) flags;
+		m_dispatcherFlags = 0;
+	}
+
+	///registerCollisionCreateFunc allows registration of custom/alternative collision create functions
+	void	registerCollisionCreateFunc(int proxyType0,int proxyType1, btCollisionAlgorithmCreateFunc* createFunc);
+
+	int	getNumManifolds() const
+	{ 
+		return int( m_manifoldsPtr.size());
+	}
+
+	btPersistentManifold**	getInternalManifoldPointer()
+	{
+		return &m_manifoldsPtr[0];
+	}
+
+	 btPersistentManifold* getManifoldByIndexInternal(int index)
+	{
+		return m_manifoldsPtr[index];
+	}
+
+	 const btPersistentManifold* getManifoldByIndexInternal(int index) const
+	{
+		return m_manifoldsPtr[index];
+	}
+
+	btCollisionDispatcher (btCollisionConfiguration* collisionConfiguration);
+
+	virtual ~btCollisionDispatcher();
+
+	virtual btPersistentManifold*	getNewManifold(void* b0,void* b1);
+	
+	virtual void releaseManifold(btPersistentManifold* manifold);
+
+
+	virtual void clearManifold(btPersistentManifold* manifold);
+
+			
+	btCollisionAlgorithm* findAlgorithm(btCollisionObject* body0,btCollisionObject* body1,btPersistentManifold* sharedManifold = 0);
+		
+	virtual bool	needsCollision(btCollisionObject* body0,btCollisionObject* body1);
+	
+	virtual bool	needsResponse(btCollisionObject* body0,btCollisionObject* body1);
+	
+	virtual void	dispatchAllCollisionPairs(btOverlappingPairCache* pairCache,const btDispatcherInfo& dispatchInfo,btDispatcher* dispatcher) ;
+
+	void	setNearCallback(btNearCallback	nearCallback)
+	{
+		m_nearCallback = nearCallback; 
+	}
+
+	btNearCallback	getNearCallback() const
+	{
+		return m_nearCallback;
+	}
+
+	//by default, Bullet will use this near callback
+	static void  defaultNearCallback(btBroadphasePair& collisionPair, btCollisionDispatcher& dispatcher, const btDispatcherInfo& dispatchInfo);
+
+	virtual	void* allocateCollisionAlgorithm(int size);
+
+	virtual	void freeCollisionAlgorithm(void* ptr);
+
+	btCollisionConfiguration*	getCollisionConfiguration()
+	{
+		return m_collisionConfiguration;
+	}
+
+	const btCollisionConfiguration*	getCollisionConfiguration() const
+	{
+		return m_collisionConfiguration;
+	}
+
+	void	setCollisionConfiguration(btCollisionConfiguration* config)
+	{
+		m_collisionConfiguration = config;
+	}
+
+};
+
+#endif //COLLISION__DISPATCHER_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
new file mode 100644
index 0000000..580ea34
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.cpp
@@ -0,0 +1,116 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btCollisionObject.h"
+#include "LinearMath/btSerializer.h"
+
+btCollisionObject::btCollisionObject()
+	:	m_anisotropicFriction(1.f,1.f,1.f),
+	m_hasAnisotropicFriction(false),
+	m_contactProcessingThreshold(BT_LARGE_FLOAT),
+		m_broadphaseHandle(0),
+		m_collisionShape(0),
+		m_extensionPointer(0),
+		m_rootCollisionShape(0),
+		m_collisionFlags(btCollisionObject::CF_STATIC_OBJECT),
+		m_islandTag1(-1),
+		m_companionId(-1),
+		m_activationState1(1),
+		m_deactivationTime(btScalar(0.)),
+		m_friction(btScalar(0.5)),
+		m_restitution(btScalar(0.)),
+		m_internalType(CO_COLLISION_OBJECT),
+		m_userObjectPointer(0),
+		m_hitFraction(btScalar(1.)),
+		m_ccdSweptSphereRadius(btScalar(0.)),
+		m_ccdMotionThreshold(btScalar(0.)),
+		m_checkCollideWith(false)
+{
+	m_worldTransform.setIdentity();
+}
+
+btCollisionObject::~btCollisionObject()
+{
+}
+
+void btCollisionObject::setActivationState(int newState) 
+{ 
+	if ( (m_activationState1 != DISABLE_DEACTIVATION) && (m_activationState1 != DISABLE_SIMULATION))
+		m_activationState1 = newState;
+}
+
+void btCollisionObject::forceActivationState(int newState)
+{
+	m_activationState1 = newState;
+}
+
+void btCollisionObject::activate(bool forceActivation)
+{
+	if (forceActivation || !(m_collisionFlags & (CF_STATIC_OBJECT|CF_KINEMATIC_OBJECT)))
+	{
+		setActivationState(ACTIVE_TAG);
+		m_deactivationTime = btScalar(0.);
+	}
+}
+
+const char* btCollisionObject::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+	btCollisionObjectData* dataOut = (btCollisionObjectData*)dataBuffer;
+
+	m_worldTransform.serialize(dataOut->m_worldTransform);
+	m_interpolationWorldTransform.serialize(dataOut->m_interpolationWorldTransform);
+	m_interpolationLinearVelocity.serialize(dataOut->m_interpolationLinearVelocity);
+	m_interpolationAngularVelocity.serialize(dataOut->m_interpolationAngularVelocity);
+	m_anisotropicFriction.serialize(dataOut->m_anisotropicFriction);
+	dataOut->m_hasAnisotropicFriction = m_hasAnisotropicFriction;
+	dataOut->m_contactProcessingThreshold = m_contactProcessingThreshold;
+	dataOut->m_broadphaseHandle = 0;
+	dataOut->m_collisionShape = serializer->getUniquePointer(m_collisionShape);
+	dataOut->m_rootCollisionShape = 0;//@todo
+	dataOut->m_collisionFlags = m_collisionFlags;
+	dataOut->m_islandTag1 = m_islandTag1;
+	dataOut->m_companionId = m_companionId;
+	dataOut->m_activationState1 = m_activationState1;
+	dataOut->m_activationState1 = m_activationState1;
+	dataOut->m_deactivationTime = m_deactivationTime;
+	dataOut->m_friction = m_friction;
+	dataOut->m_restitution = m_restitution;
+	dataOut->m_internalType = m_internalType;
+	
+	char* name = (char*) serializer->findNameForPointer(this);
+	dataOut->m_name = (char*)serializer->getUniquePointer(name);
+	if (dataOut->m_name)
+	{
+		serializer->serializeName(name);
+	}
+	dataOut->m_hitFraction = m_hitFraction;
+	dataOut->m_ccdSweptSphereRadius = m_ccdSweptSphereRadius;
+	dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
+	dataOut->m_ccdMotionThreshold = m_ccdMotionThreshold;
+	dataOut->m_checkCollideWith = m_checkCollideWith;
+
+	return btCollisionObjectDataName;
+}
+
+
+void btCollisionObject::serializeSingleObject(class btSerializer* serializer) const
+{
+	int len = calculateSerializeBufferSize();
+	btChunk* chunk = serializer->allocate(len,1);
+	const char* structType = serialize(chunk->m_oldPtr, serializer);
+	serializer->finalizeChunk(chunk,structType,BT_COLLISIONOBJECT_CODE,(void*)this);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
new file mode 100644
index 0000000..5de8298
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionObject.h
@@ -0,0 +1,524 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COLLISION_OBJECT_H
+#define COLLISION_OBJECT_H
+
+#include "LinearMath/btTransform.h"
+
+//island management, m_activationState1
+#define ACTIVE_TAG 1
+#define ISLAND_SLEEPING 2
+#define WANTS_DEACTIVATION 3
+#define DISABLE_DEACTIVATION 4
+#define DISABLE_SIMULATION 5
+
+struct	btBroadphaseProxy;
+class	btCollisionShape;
+struct btCollisionShapeData;
+#include "LinearMath/btMotionState.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<class btCollisionObject*> btCollisionObjectArray;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btCollisionObjectData btCollisionObjectDoubleData
+#define btCollisionObjectDataName "btCollisionObjectDoubleData"
+#else
+#define btCollisionObjectData btCollisionObjectFloatData
+#define btCollisionObjectDataName "btCollisionObjectFloatData"
+#endif
+
+
+/// btCollisionObject can be used to manage collision detection objects. 
+/// btCollisionObject maintains all information that is needed for a collision detection: Shape, Transform and AABB proxy.
+/// They can be added to the btCollisionWorld.
+ATTRIBUTE_ALIGNED16(class)	btCollisionObject
+{
+
+protected:
+
+	btTransform	m_worldTransform;
+
+	///m_interpolationWorldTransform is used for CCD and interpolation
+	///it can be either previous or future (predicted) transform
+	btTransform	m_interpolationWorldTransform;
+	//those two are experimental: just added for bullet time effect, so you can still apply impulses (directly modifying velocities) 
+	//without destroying the continuous interpolated motion (which uses this interpolation velocities)
+	btVector3	m_interpolationLinearVelocity;
+	btVector3	m_interpolationAngularVelocity;
+	
+	btVector3	m_anisotropicFriction;
+	int			m_hasAnisotropicFriction;
+	btScalar	m_contactProcessingThreshold;	
+
+	btBroadphaseProxy*		m_broadphaseHandle;
+	btCollisionShape*		m_collisionShape;
+	///m_extensionPointer is used by some internal low-level Bullet extensions.
+	void*					m_extensionPointer;
+	
+	///m_rootCollisionShape is temporarily used to store the original collision shape
+	///The m_collisionShape might be temporarily replaced by a child collision shape during collision detection purposes
+	///If it is NULL, the m_collisionShape is not temporarily replaced.
+	btCollisionShape*		m_rootCollisionShape;
+
+	int				m_collisionFlags;
+
+	int				m_islandTag1;
+	int				m_companionId;
+
+	int				m_activationState1;
+	btScalar			m_deactivationTime;
+
+	btScalar		m_friction;
+	btScalar		m_restitution;
+
+	///m_internalType is reserved to distinguish Bullet's btCollisionObject, btRigidBody, btSoftBody, btGhostObject etc.
+	///do not assign your own m_internalType unless you write a new dynamics object class.
+	int				m_internalType;
+
+	///users can point to their objects, m_userPointer is not used by Bullet, see setUserPointer/getUserPointer
+	void*			m_userObjectPointer;
+
+	///time of impact calculation
+	btScalar		m_hitFraction; 
+	
+	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+	btScalar		m_ccdSweptSphereRadius;
+
+	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+	btScalar		m_ccdMotionThreshold;
+	
+	/// If some object should have elaborate collision filtering by sub-classes
+	int			m_checkCollideWith;
+
+	virtual bool	checkCollideWithOverride(btCollisionObject* /* co */)
+	{
+		return true;
+	}
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	enum CollisionFlags
+	{
+		CF_STATIC_OBJECT= 1,
+		CF_KINEMATIC_OBJECT= 2,
+		CF_NO_CONTACT_RESPONSE = 4,
+		CF_CUSTOM_MATERIAL_CALLBACK = 8,//this allows per-triangle material (friction/restitution)
+		CF_CHARACTER_OBJECT = 16,
+		CF_DISABLE_VISUALIZE_OBJECT = 32, //disable debug drawing
+		CF_DISABLE_SPU_COLLISION_PROCESSING = 64//disable parallel/SPU processing
+	};
+
+	enum	CollisionObjectTypes
+	{
+		CO_COLLISION_OBJECT =1,
+		CO_RIGID_BODY=2,
+		///CO_GHOST_OBJECT keeps track of all objects overlapping its AABB and that pass its collision filter
+		///It is useful for collision sensors, explosion objects, character controller etc.
+		CO_GHOST_OBJECT=4,
+		CO_SOFT_BODY=8,
+		CO_HF_FLUID=16,
+		CO_USER_TYPE=32
+	};
+
+	SIMD_FORCE_INLINE bool mergesSimulationIslands() const
+	{
+		///static objects, kinematic and object without contact response don't merge islands
+		return  ((m_collisionFlags & (CF_STATIC_OBJECT | CF_KINEMATIC_OBJECT | CF_NO_CONTACT_RESPONSE) )==0);
+	}
+
+	const btVector3& getAnisotropicFriction() const
+	{
+		return m_anisotropicFriction;
+	}
+	void	setAnisotropicFriction(const btVector3& anisotropicFriction)
+	{
+		m_anisotropicFriction = anisotropicFriction;
+		m_hasAnisotropicFriction = (anisotropicFriction[0]!=1.f) || (anisotropicFriction[1]!=1.f) || (anisotropicFriction[2]!=1.f);
+	}
+	bool	hasAnisotropicFriction() const
+	{
+		return m_hasAnisotropicFriction!=0;
+	}
+
+	///the constraint solver can discard solving contacts, if the distance is above this threshold. 0 by default.
+	///Note that using contacts with positive distance can improve stability. It increases, however, the chance of colliding with degerate contacts, such as 'interior' triangle edges
+	void	setContactProcessingThreshold( btScalar contactProcessingThreshold)
+	{
+		m_contactProcessingThreshold = contactProcessingThreshold;
+	}
+	btScalar	getContactProcessingThreshold() const
+	{
+		return m_contactProcessingThreshold;
+	}
+
+	SIMD_FORCE_INLINE bool		isStaticObject() const {
+		return (m_collisionFlags & CF_STATIC_OBJECT) != 0;
+	}
+
+	SIMD_FORCE_INLINE bool		isKinematicObject() const
+	{
+		return (m_collisionFlags & CF_KINEMATIC_OBJECT) != 0;
+	}
+
+	SIMD_FORCE_INLINE bool		isStaticOrKinematicObject() const
+	{
+		return (m_collisionFlags & (CF_KINEMATIC_OBJECT | CF_STATIC_OBJECT)) != 0 ;
+	}
+
+	SIMD_FORCE_INLINE bool		hasContactResponse() const {
+		return (m_collisionFlags & CF_NO_CONTACT_RESPONSE)==0;
+	}
+
+	
+	btCollisionObject();
+
+	virtual ~btCollisionObject();
+
+	virtual void	setCollisionShape(btCollisionShape* collisionShape)
+	{
+		m_collisionShape = collisionShape;
+		m_rootCollisionShape = collisionShape;
+	}
+
+	SIMD_FORCE_INLINE const btCollisionShape*	getCollisionShape() const
+	{
+		return m_collisionShape;
+	}
+
+	SIMD_FORCE_INLINE btCollisionShape*	getCollisionShape()
+	{
+		return m_collisionShape;
+	}
+
+	SIMD_FORCE_INLINE const btCollisionShape*	getRootCollisionShape() const
+	{
+		return m_rootCollisionShape;
+	}
+
+	SIMD_FORCE_INLINE btCollisionShape*	getRootCollisionShape()
+	{
+		return m_rootCollisionShape;
+	}
+
+	///Avoid using this internal API call
+	///internalSetTemporaryCollisionShape is used to temporary replace the actual collision shape by a child collision shape.
+	void	internalSetTemporaryCollisionShape(btCollisionShape* collisionShape)
+	{
+		m_collisionShape = collisionShape;
+	}
+
+	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions. 
+	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+	void*		internalGetExtensionPointer() const
+	{
+		return m_extensionPointer;
+	}
+	///Avoid using this internal API call, the extension pointer is used by some Bullet extensions
+	///If you need to store your own user pointer, use 'setUserPointer/getUserPointer' instead.
+	void	internalSetExtensionPointer(void* pointer)
+	{
+		m_extensionPointer = pointer;
+	}
+
+	SIMD_FORCE_INLINE	int	getActivationState() const { return m_activationState1;}
+	
+	void setActivationState(int newState);
+
+	void	setDeactivationTime(btScalar time)
+	{
+		m_deactivationTime = time;
+	}
+	btScalar	getDeactivationTime() const
+	{
+		return m_deactivationTime;
+	}
+
+	void forceActivationState(int newState);
+
+	void	activate(bool forceActivation = false);
+
+	SIMD_FORCE_INLINE bool isActive() const
+	{
+		return ((getActivationState() != ISLAND_SLEEPING) && (getActivationState() != DISABLE_SIMULATION));
+	}
+
+	void	setRestitution(btScalar rest)
+	{
+		m_restitution = rest;
+	}
+	btScalar	getRestitution() const
+	{
+		return m_restitution;
+	}
+	void	setFriction(btScalar frict)
+	{
+		m_friction = frict;
+	}
+	btScalar	getFriction() const
+	{
+		return m_friction;
+	}
+
+	///reserved for Bullet internal usage
+	int	getInternalType() const
+	{
+		return m_internalType;
+	}
+
+	btTransform&	getWorldTransform()
+	{
+		return m_worldTransform;
+	}
+
+	const btTransform&	getWorldTransform() const
+	{
+		return m_worldTransform;
+	}
+
+	void	setWorldTransform(const btTransform& worldTrans)
+	{
+		m_worldTransform = worldTrans;
+	}
+
+
+	SIMD_FORCE_INLINE btBroadphaseProxy*	getBroadphaseHandle()
+	{
+		return m_broadphaseHandle;
+	}
+
+	SIMD_FORCE_INLINE const btBroadphaseProxy*	getBroadphaseHandle() const
+	{
+		return m_broadphaseHandle;
+	}
+
+	void	setBroadphaseHandle(btBroadphaseProxy* handle)
+	{
+		m_broadphaseHandle = handle;
+	}
+
+
+	const btTransform&	getInterpolationWorldTransform() const
+	{
+		return m_interpolationWorldTransform;
+	}
+
+	btTransform&	getInterpolationWorldTransform()
+	{
+		return m_interpolationWorldTransform;
+	}
+
+	void	setInterpolationWorldTransform(const btTransform&	trans)
+	{
+		m_interpolationWorldTransform = trans;
+	}
+
+	void	setInterpolationLinearVelocity(const btVector3& linvel)
+	{
+		m_interpolationLinearVelocity = linvel;
+	}
+
+	void	setInterpolationAngularVelocity(const btVector3& angvel)
+	{
+		m_interpolationAngularVelocity = angvel;
+	}
+
+	const btVector3&	getInterpolationLinearVelocity() const
+	{
+		return m_interpolationLinearVelocity;
+	}
+
+	const btVector3&	getInterpolationAngularVelocity() const
+	{
+		return m_interpolationAngularVelocity;
+	}
+
+	SIMD_FORCE_INLINE int getIslandTag() const
+	{
+		return	m_islandTag1;
+	}
+
+	void	setIslandTag(int tag)
+	{
+		m_islandTag1 = tag;
+	}
+
+	SIMD_FORCE_INLINE int getCompanionId() const
+	{
+		return	m_companionId;
+	}
+
+	void	setCompanionId(int id)
+	{
+		m_companionId = id;
+	}
+
+	SIMD_FORCE_INLINE btScalar			getHitFraction() const
+	{
+		return m_hitFraction; 
+	}
+
+	void	setHitFraction(btScalar hitFraction)
+	{
+		m_hitFraction = hitFraction;
+	}
+
+	
+	SIMD_FORCE_INLINE int	getCollisionFlags() const
+	{
+		return m_collisionFlags;
+	}
+
+	void	setCollisionFlags(int flags)
+	{
+		m_collisionFlags = flags;
+	}
+	
+	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+	btScalar			getCcdSweptSphereRadius() const
+	{
+		return m_ccdSweptSphereRadius;
+	}
+
+	///Swept sphere radius (0.0 by default), see btConvexConvexAlgorithm::
+	void	setCcdSweptSphereRadius(btScalar radius)
+	{
+		m_ccdSweptSphereRadius = radius;
+	}
+
+	btScalar 	getCcdMotionThreshold() const
+	{
+		return m_ccdMotionThreshold;
+	}
+
+	btScalar 	getCcdSquareMotionThreshold() const
+	{
+		return m_ccdMotionThreshold*m_ccdMotionThreshold;
+	}
+
+
+
+	/// Don't do continuous collision detection if the motion (in one step) is less then m_ccdMotionThreshold
+	void	setCcdMotionThreshold(btScalar ccdMotionThreshold)
+	{
+		m_ccdMotionThreshold = ccdMotionThreshold;
+	}
+
+	///users can point to their objects, userPointer is not used by Bullet
+	void*	getUserPointer() const
+	{
+		return m_userObjectPointer;
+	}
+	
+	///users can point to their objects, userPointer is not used by Bullet
+	void	setUserPointer(void* userPointer)
+	{
+		m_userObjectPointer = userPointer;
+	}
+
+
+	inline bool checkCollideWith(btCollisionObject* co)
+	{
+		if (m_checkCollideWith)
+			return checkCollideWithOverride(co);
+
+		return true;
+	}
+
+	virtual	int	calculateSerializeBufferSize()	const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, class btSerializer* serializer) const;
+
+	virtual void serializeSingleObject(class btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCollisionObjectDoubleData
+{
+	void					*m_broadphaseHandle;
+	void					*m_collisionShape;
+	btCollisionShapeData	*m_rootCollisionShape;
+	char					*m_name;
+
+	btTransformDoubleData	m_worldTransform;
+	btTransformDoubleData	m_interpolationWorldTransform;
+	btVector3DoubleData		m_interpolationLinearVelocity;
+	btVector3DoubleData		m_interpolationAngularVelocity;
+	btVector3DoubleData		m_anisotropicFriction;
+	double					m_contactProcessingThreshold;	
+	double					m_deactivationTime;
+	double					m_friction;
+	double					m_restitution;
+	double					m_hitFraction; 
+	double					m_ccdSweptSphereRadius;
+	double					m_ccdMotionThreshold;
+
+	int						m_hasAnisotropicFriction;
+	int						m_collisionFlags;
+	int						m_islandTag1;
+	int						m_companionId;
+	int						m_activationState1;
+	int						m_internalType;
+	int						m_checkCollideWith;
+
+	char	m_padding[4];
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCollisionObjectFloatData
+{
+	void					*m_broadphaseHandle;
+	void					*m_collisionShape;
+	btCollisionShapeData	*m_rootCollisionShape;
+	char					*m_name;
+
+	btTransformFloatData	m_worldTransform;
+	btTransformFloatData	m_interpolationWorldTransform;
+	btVector3FloatData		m_interpolationLinearVelocity;
+	btVector3FloatData		m_interpolationAngularVelocity;
+	btVector3FloatData		m_anisotropicFriction;
+	float					m_contactProcessingThreshold;	
+	float					m_deactivationTime;
+	float					m_friction;
+	float					m_restitution;
+	float					m_hitFraction; 
+	float					m_ccdSweptSphereRadius;
+	float					m_ccdMotionThreshold;
+
+	int						m_hasAnisotropicFriction;
+	int						m_collisionFlags;
+	int						m_islandTag1;
+	int						m_companionId;
+	int						m_activationState1;
+	int						m_internalType;
+	int						m_checkCollideWith;
+};
+
+
+
+SIMD_FORCE_INLINE	int	btCollisionObject::calculateSerializeBufferSize() const
+{
+	return sizeof(btCollisionObjectData);
+}
+
+
+
+#endif //COLLISION_OBJECT_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
new file mode 100644
index 0000000..653ed96
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.cpp
@@ -0,0 +1,1432 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCollisionWorld.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h" //for raycasting
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" //for raycasting
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btSerializer.h"
+
+//#define USE_BRUTEFORCE_RAYBROADPHASE 1
+//RECALCULATE_AABB is slower, but benefit is that you don't need to call 'stepSimulation'  or 'updateAabbs' before using a rayTest
+//#define RECALCULATE_AABB_RAYCAST 1
+
+//When the user doesn't provide dispatcher or broadphase, create basic versions (and delete them in destructor)
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionDispatch/btCollisionConfiguration.h"
+
+
+///for debug drawing
+
+//for debug rendering
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+
+
+btCollisionWorld::btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache, btCollisionConfiguration* collisionConfiguration)
+:m_dispatcher1(dispatcher),
+m_broadphasePairCache(pairCache),
+m_debugDrawer(0),
+m_forceUpdateAllAabbs(true)
+{
+	m_stackAlloc = collisionConfiguration->getStackAllocator();
+	m_dispatchInfo.m_stackAllocator = m_stackAlloc;
+}
+
+
+btCollisionWorld::~btCollisionWorld()
+{
+
+	//clean up remaining objects
+	int i;
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* collisionObject= m_collisionObjects[i];
+
+		btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
+		if (bp)
+		{
+			//
+			// only clear the cached algorithms
+			//
+			getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+			getBroadphase()->destroyProxy(bp,m_dispatcher1);
+			collisionObject->setBroadphaseHandle(0);
+		}
+	}
+
+
+}
+
+
+
+
+
+
+
+
+
+
+void	btCollisionWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
+{
+
+	btAssert(collisionObject);
+
+	//check that the object isn't already added
+	btAssert( m_collisionObjects.findLinearSearch(collisionObject)  == m_collisionObjects.size());
+
+	m_collisionObjects.push_back(collisionObject);
+
+	//calculate new AABB
+	btTransform trans = collisionObject->getWorldTransform();
+
+	btVector3	minAabb;
+	btVector3	maxAabb;
+	collisionObject->getCollisionShape()->getAabb(trans,minAabb,maxAabb);
+
+	int type = collisionObject->getCollisionShape()->getShapeType();
+	collisionObject->setBroadphaseHandle( getBroadphase()->createProxy(
+		minAabb,
+		maxAabb,
+		type,
+		collisionObject,
+		collisionFilterGroup,
+		collisionFilterMask,
+		m_dispatcher1,0
+		))	;
+
+
+
+
+
+}
+
+
+
+void	btCollisionWorld::updateSingleAabb(btCollisionObject* colObj)
+{
+	btVector3 minAabb,maxAabb;
+	colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+	//need to increase the aabb for contact thresholds
+	btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold);
+	minAabb -= contactThreshold;
+	maxAabb += contactThreshold;
+
+	btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache;
+
+	//moving objects should be moderately sized, probably something wrong if not
+	if ( colObj->isStaticObject() || ((maxAabb-minAabb).length2() < btScalar(1e12)))
+	{
+		bp->setAabb(colObj->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+	} else
+	{
+		//something went wrong, investigate
+		//this assert is unwanted in 3D modelers (danger of loosing work)
+		colObj->setActivationState(DISABLE_SIMULATION);
+
+		static bool reportMe = true;
+		if (reportMe && m_debugDrawer)
+		{
+			reportMe = false;
+			m_debugDrawer->reportErrorWarning("Overflow in AABB, object removed from simulation");
+			m_debugDrawer->reportErrorWarning("If you can reproduce this, please email bugs at continuousphysics.com\n");
+			m_debugDrawer->reportErrorWarning("Please include above information, your Platform, version of OS.\n");
+			m_debugDrawer->reportErrorWarning("Thanks.\n");
+		}
+	}
+}
+
+void	btCollisionWorld::updateAabbs()
+{
+	BT_PROFILE("updateAabbs");
+
+	btTransform predictedTrans;
+	for ( int i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+
+		//only update aabb of active objects
+		if (m_forceUpdateAllAabbs || colObj->isActive())
+		{
+			updateSingleAabb(colObj);
+		}
+	}
+}
+
+
+
+void	btCollisionWorld::performDiscreteCollisionDetection()
+{
+	BT_PROFILE("performDiscreteCollisionDetection");
+
+	btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+	updateAabbs();
+
+	{
+		BT_PROFILE("calculateOverlappingPairs");
+		m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
+	}
+
+
+	btDispatcher* dispatcher = getDispatcher();
+	{
+		BT_PROFILE("dispatchAllCollisionPairs");
+		if (dispatcher)
+			dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+	}
+
+}
+
+
+
+void	btCollisionWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+
+
+	//bool removeFromBroadphase = false;
+
+	{
+
+		btBroadphaseProxy* bp = collisionObject->getBroadphaseHandle();
+		if (bp)
+		{
+			//
+			// only clear the cached algorithms
+			//
+			getBroadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bp,m_dispatcher1);
+			getBroadphase()->destroyProxy(bp,m_dispatcher1);
+			collisionObject->setBroadphaseHandle(0);
+		}
+	}
+
+
+	//swapremove
+	m_collisionObjects.remove(collisionObject);
+
+}
+
+
+
+void	btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+										btCollisionObject* collisionObject,
+										const btCollisionShape* collisionShape,
+										const btTransform& colObjWorldTransform,
+										RayResultCallback& resultCallback)
+{
+	btSphereShape pointShape(btScalar(0.0));
+	pointShape.setMargin(0.f);
+	const btConvexShape* castShape = &pointShape;
+
+	if (collisionShape->isConvex())
+	{
+		//		BT_PROFILE("rayTestConvex");
+		btConvexCast::CastResult castResult;
+		castResult.m_fraction = resultCallback.m_closestHitFraction;
+
+		btConvexShape* convexShape = (btConvexShape*) collisionShape;
+		btVoronoiSimplexSolver	simplexSolver;
+#define USE_SUBSIMPLEX_CONVEX_CAST 1
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+		btSubsimplexConvexCast convexCaster(castShape,convexShape,&simplexSolver);
+#else
+		//btGjkConvexCast	convexCaster(castShape,convexShape,&simplexSolver);
+		//btContinuousConvexCollision convexCaster(castShape,convexShape,&simplexSolver,0);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+
+		if (convexCaster.calcTimeOfImpact(rayFromTrans,rayToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+		{
+			//add hit
+			if (castResult.m_normal.length2() > btScalar(0.0001))
+			{
+				if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+				{
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+					//rotate normal into worldspace
+					castResult.m_normal = rayFromTrans.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+
+					castResult.m_normal.normalize();
+					btCollisionWorld::LocalRayResult localRayResult
+						(
+						collisionObject,
+						0,
+						castResult.m_normal,
+						castResult.m_fraction
+						);
+
+					bool normalInWorldSpace = true;
+					resultCallback.addSingleResult(localRayResult, normalInWorldSpace);
+
+				}
+			}
+		}
+	} else {
+		if (collisionShape->isConcave())
+		{
+			//			BT_PROFILE("rayTestConcave");
+			if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+			{
+				///optimized version for btBvhTriangleMeshShape
+				btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+				btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+				btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+				//ConvexCast::CastResult
+				struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+				{
+					btCollisionWorld::RayResultCallback* m_resultCallback;
+					btCollisionObject*	m_collisionObject;
+					btTriangleMeshShape*	m_triangleMesh;
+
+					btTransform m_colObjWorldTransform;
+
+					BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+						btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape*	triangleMesh,const btTransform& colObjWorldTransform):
+					//@BP Mod
+					btTriangleRaycastCallback(from,to, resultCallback->m_flags),
+						m_resultCallback(resultCallback),
+						m_collisionObject(collisionObject),
+						m_triangleMesh(triangleMesh),
+						m_colObjWorldTransform(colObjWorldTransform)
+					{
+					}
+
+
+					virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+					{
+						btCollisionWorld::LocalShapeInfo	shapeInfo;
+						shapeInfo.m_shapePart = partId;
+						shapeInfo.m_triangleIndex = triangleIndex;
+
+						btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+						btCollisionWorld::LocalRayResult rayResult
+							(m_collisionObject,
+							&shapeInfo,
+							hitNormalWorld,
+							hitFraction);
+
+						bool	normalInWorldSpace = true;
+						return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+					}
+
+				};
+
+				BridgeTriangleRaycastCallback rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,triangleMesh,colObjWorldTransform);
+				rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+				triangleMesh->performRaycast(&rcb,rayFromLocal,rayToLocal);
+			} else
+			{
+				//generic (slower) case
+				btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
+
+				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+
+				btVector3 rayFromLocal = worldTocollisionObject * rayFromTrans.getOrigin();
+				btVector3 rayToLocal = worldTocollisionObject * rayToTrans.getOrigin();
+
+				//ConvexCast::CastResult
+
+				struct BridgeTriangleRaycastCallback : public btTriangleRaycastCallback
+				{
+					btCollisionWorld::RayResultCallback* m_resultCallback;
+					btCollisionObject*	m_collisionObject;
+					btConcaveShape*	m_triangleMesh;
+
+					btTransform m_colObjWorldTransform;
+
+					BridgeTriangleRaycastCallback( const btVector3& from,const btVector3& to,
+						btCollisionWorld::RayResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape*	triangleMesh, const btTransform& colObjWorldTransform):
+					//@BP Mod
+					btTriangleRaycastCallback(from,to, resultCallback->m_flags),
+						m_resultCallback(resultCallback),
+						m_collisionObject(collisionObject),
+						m_triangleMesh(triangleMesh),
+						m_colObjWorldTransform(colObjWorldTransform)
+					{
+					}
+
+
+					virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex )
+					{
+						btCollisionWorld::LocalShapeInfo	shapeInfo;
+						shapeInfo.m_shapePart = partId;
+						shapeInfo.m_triangleIndex = triangleIndex;
+
+						btVector3 hitNormalWorld = m_colObjWorldTransform.getBasis() * hitNormalLocal;
+
+						btCollisionWorld::LocalRayResult rayResult
+							(m_collisionObject,
+							&shapeInfo,
+							hitNormalWorld,
+							hitFraction);
+
+						bool	normalInWorldSpace = true;
+						return m_resultCallback->addSingleResult(rayResult,normalInWorldSpace);
+					}
+
+				};
+
+
+				BridgeTriangleRaycastCallback	rcb(rayFromLocal,rayToLocal,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
+				rcb.m_hitFraction = resultCallback.m_closestHitFraction;
+
+				btVector3 rayAabbMinLocal = rayFromLocal;
+				rayAabbMinLocal.setMin(rayToLocal);
+				btVector3 rayAabbMaxLocal = rayFromLocal;
+				rayAabbMaxLocal.setMax(rayToLocal);
+
+				concaveShape->processAllTriangles(&rcb,rayAabbMinLocal,rayAabbMaxLocal);
+			}
+		} else {
+			//			BT_PROFILE("rayTestCompound");
+			///@todo: use AABB tree or other BVH acceleration structure, see btDbvt
+			if (collisionShape->isCompound())
+			{
+				const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+				int i=0;
+				for (i=0;i<compoundShape->getNumChildShapes();i++)
+				{
+					btTransform childTrans = compoundShape->getChildTransform(i);
+					const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+					btTransform childWorldTrans = colObjWorldTransform * childTrans;
+					// replace collision shape so that callback can determine the triangle
+					btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
+					collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
+                    struct LocalInfoAdder2 : public RayResultCallback {
+						RayResultCallback* m_userCallback;
+						int m_i;
+                        LocalInfoAdder2 (int i, RayResultCallback *user)
+							: m_userCallback(user),
+							m_i(i)
+						{ 
+							m_closestHitFraction = m_userCallback->m_closestHitFraction;
+						}
+						virtual btScalar addSingleResult (btCollisionWorld::LocalRayResult &r, bool b)
+                            {
+                                    btCollisionWorld::LocalShapeInfo	shapeInfo;
+                                    shapeInfo.m_shapePart = -1;
+                                    shapeInfo.m_triangleIndex = m_i;
+                                    if (r.m_localShapeInfo == NULL)
+                                        r.m_localShapeInfo = &shapeInfo;
+
+									const btScalar result = m_userCallback->addSingleResult(r, b);
+									m_closestHitFraction = m_userCallback->m_closestHitFraction;
+									return result;
+                            }
+                    };
+
+                    LocalInfoAdder2 my_cb(i, &resultCallback);
+
+					rayTestSingle(rayFromTrans,rayToTrans,
+						collisionObject,
+						childCollisionShape,
+						childWorldTrans,
+						my_cb);
+					// restore
+					collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
+				}
+			}
+		}
+	}
+}
+
+void	btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const btTransform& convexFromTrans,const btTransform& convexToTrans,
+											btCollisionObject* collisionObject,
+											const btCollisionShape* collisionShape,
+											const btTransform& colObjWorldTransform,
+											ConvexResultCallback& resultCallback, btScalar allowedPenetration)
+{
+	if (collisionShape->isConvex())
+	{
+		//BT_PROFILE("convexSweepConvex");
+		btConvexCast::CastResult castResult;
+		castResult.m_allowedPenetration = allowedPenetration;
+		castResult.m_fraction = resultCallback.m_closestHitFraction;//btScalar(1.);//??
+
+		btConvexShape* convexShape = (btConvexShape*) collisionShape;
+		btVoronoiSimplexSolver	simplexSolver;
+		btGjkEpaPenetrationDepthSolver	gjkEpaPenetrationSolver;
+
+		btContinuousConvexCollision convexCaster1(castShape,convexShape,&simplexSolver,&gjkEpaPenetrationSolver);
+		//btGjkConvexCast convexCaster2(castShape,convexShape,&simplexSolver);
+		//btSubsimplexConvexCast convexCaster3(castShape,convexShape,&simplexSolver);
+
+		btConvexCast* castPtr = &convexCaster1;
+
+
+
+		if (castPtr->calcTimeOfImpact(convexFromTrans,convexToTrans,colObjWorldTransform,colObjWorldTransform,castResult))
+		{
+			//add hit
+			if (castResult.m_normal.length2() > btScalar(0.0001))
+			{
+				if (castResult.m_fraction < resultCallback.m_closestHitFraction)
+				{
+					castResult.m_normal.normalize();
+					btCollisionWorld::LocalConvexResult localConvexResult
+						(
+						collisionObject,
+						0,
+						castResult.m_normal,
+						castResult.m_hitPoint,
+						castResult.m_fraction
+						);
+
+					bool normalInWorldSpace = true;
+					resultCallback.addSingleResult(localConvexResult, normalInWorldSpace);
+
+				}
+			}
+		}
+	} else {
+		if (collisionShape->isConcave())
+		{
+			if (collisionShape->getShapeType()==TRIANGLE_MESH_SHAPE_PROXYTYPE)
+			{
+				//BT_PROFILE("convexSweepbtBvhTriangleMesh");
+				btBvhTriangleMeshShape* triangleMesh = (btBvhTriangleMeshShape*)collisionShape;
+				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+				btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+				btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+				// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+				btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+				//ConvexCast::CastResult
+				struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+				{
+					btCollisionWorld::ConvexResultCallback* m_resultCallback;
+					btCollisionObject*	m_collisionObject;
+					btTriangleMeshShape*	m_triangleMesh;
+
+					BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+						btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btTriangleMeshShape*	triangleMesh, const btTransform& triangleToWorld):
+					btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+						m_resultCallback(resultCallback),
+						m_collisionObject(collisionObject),
+						m_triangleMesh(triangleMesh)
+					{
+					}
+
+
+					virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+					{
+						btCollisionWorld::LocalShapeInfo	shapeInfo;
+						shapeInfo.m_shapePart = partId;
+						shapeInfo.m_triangleIndex = triangleIndex;
+						if (hitFraction <= m_resultCallback->m_closestHitFraction)
+						{
+
+							btCollisionWorld::LocalConvexResult convexResult
+								(m_collisionObject,
+								&shapeInfo,
+								hitNormalLocal,
+								hitPointLocal,
+								hitFraction);
+
+							bool	normalInWorldSpace = true;
+
+
+							return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+						}
+						return hitFraction;
+					}
+
+				};
+
+				BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,triangleMesh, colObjWorldTransform);
+				tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+				btVector3 boxMinLocal, boxMaxLocal;
+				castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+				triangleMesh->performConvexcast(&tccb,convexFromLocal,convexToLocal,boxMinLocal, boxMaxLocal);
+			} else
+			{
+				//BT_PROFILE("convexSweepConcave");
+				btConcaveShape* concaveShape = (btConcaveShape*)collisionShape;
+				btTransform worldTocollisionObject = colObjWorldTransform.inverse();
+				btVector3 convexFromLocal = worldTocollisionObject * convexFromTrans.getOrigin();
+				btVector3 convexToLocal = worldTocollisionObject * convexToTrans.getOrigin();
+				// rotation of box in local mesh space = MeshRotation^-1 * ConvexToRotation
+				btTransform rotationXform = btTransform(worldTocollisionObject.getBasis() * convexToTrans.getBasis());
+
+				//ConvexCast::CastResult
+				struct BridgeTriangleConvexcastCallback : public btTriangleConvexcastCallback
+				{
+					btCollisionWorld::ConvexResultCallback* m_resultCallback;
+					btCollisionObject*	m_collisionObject;
+					btConcaveShape*	m_triangleMesh;
+
+					BridgeTriangleConvexcastCallback(const btConvexShape* castShape, const btTransform& from,const btTransform& to,
+						btCollisionWorld::ConvexResultCallback* resultCallback, btCollisionObject* collisionObject,btConcaveShape*	triangleMesh, const btTransform& triangleToWorld):
+					btTriangleConvexcastCallback(castShape, from,to, triangleToWorld, triangleMesh->getMargin()),
+						m_resultCallback(resultCallback),
+						m_collisionObject(collisionObject),
+						m_triangleMesh(triangleMesh)
+					{
+					}
+
+
+					virtual btScalar reportHit(const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex )
+					{
+						btCollisionWorld::LocalShapeInfo	shapeInfo;
+						shapeInfo.m_shapePart = partId;
+						shapeInfo.m_triangleIndex = triangleIndex;
+						if (hitFraction <= m_resultCallback->m_closestHitFraction)
+						{
+
+							btCollisionWorld::LocalConvexResult convexResult
+								(m_collisionObject,
+								&shapeInfo,
+								hitNormalLocal,
+								hitPointLocal,
+								hitFraction);
+
+							bool	normalInWorldSpace = false;
+
+							return m_resultCallback->addSingleResult(convexResult,normalInWorldSpace);
+						}
+						return hitFraction;
+					}
+
+				};
+
+				BridgeTriangleConvexcastCallback tccb(castShape, convexFromTrans,convexToTrans,&resultCallback,collisionObject,concaveShape, colObjWorldTransform);
+				tccb.m_hitFraction = resultCallback.m_closestHitFraction;
+				btVector3 boxMinLocal, boxMaxLocal;
+				castShape->getAabb(rotationXform, boxMinLocal, boxMaxLocal);
+
+				btVector3 rayAabbMinLocal = convexFromLocal;
+				rayAabbMinLocal.setMin(convexToLocal);
+				btVector3 rayAabbMaxLocal = convexFromLocal;
+				rayAabbMaxLocal.setMax(convexToLocal);
+				rayAabbMinLocal += boxMinLocal;
+				rayAabbMaxLocal += boxMaxLocal;
+				concaveShape->processAllTriangles(&tccb,rayAabbMinLocal,rayAabbMaxLocal);
+			}
+		} else {
+			///@todo : use AABB tree or other BVH acceleration structure!
+			if (collisionShape->isCompound())
+			{
+				BT_PROFILE("convexSweepCompound");
+				const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(collisionShape);
+				int i=0;
+				for (i=0;i<compoundShape->getNumChildShapes();i++)
+				{
+					btTransform childTrans = compoundShape->getChildTransform(i);
+					const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i);
+					btTransform childWorldTrans = colObjWorldTransform * childTrans;
+					// replace collision shape so that callback can determine the triangle
+					btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape();
+					collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape);
+                    struct	LocalInfoAdder : public ConvexResultCallback {
+                            ConvexResultCallback* m_userCallback;
+							int m_i;
+
+                            LocalInfoAdder (int i, ConvexResultCallback *user)
+								: m_userCallback(user), m_i(i)
+							{
+								m_closestHitFraction = m_userCallback->m_closestHitFraction;
+							}
+                            virtual btScalar addSingleResult (btCollisionWorld::LocalConvexResult&	r,	bool b)
+                            {
+                                    btCollisionWorld::LocalShapeInfo	shapeInfo;
+                                    shapeInfo.m_shapePart = -1;
+                                    shapeInfo.m_triangleIndex = m_i;
+                                    if (r.m_localShapeInfo == NULL)
+                                        r.m_localShapeInfo = &shapeInfo;
+									const btScalar result = m_userCallback->addSingleResult(r, b);
+									m_closestHitFraction = m_userCallback->m_closestHitFraction;
+									return result;
+                                    
+                            }
+                    };
+
+                    LocalInfoAdder my_cb(i, &resultCallback);
+					
+
+					objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+						collisionObject,
+						childCollisionShape,
+						childWorldTrans,
+						my_cb, allowedPenetration);
+					// restore
+					collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape);
+				}
+			}
+		}
+	}
+}
+
+
+struct btSingleRayCallback : public btBroadphaseRayCallback
+{
+
+	btVector3	m_rayFromWorld;
+	btVector3	m_rayToWorld;
+	btTransform	m_rayFromTrans;
+	btTransform	m_rayToTrans;
+	btVector3	m_hitNormal;
+
+	const btCollisionWorld*	m_world;
+	btCollisionWorld::RayResultCallback&	m_resultCallback;
+
+	btSingleRayCallback(const btVector3& rayFromWorld,const btVector3& rayToWorld,const btCollisionWorld* world,btCollisionWorld::RayResultCallback& resultCallback)
+		:m_rayFromWorld(rayFromWorld),
+		m_rayToWorld(rayToWorld),
+		m_world(world),
+		m_resultCallback(resultCallback)
+	{
+		m_rayFromTrans.setIdentity();
+		m_rayFromTrans.setOrigin(m_rayFromWorld);
+		m_rayToTrans.setIdentity();
+		m_rayToTrans.setOrigin(m_rayToWorld);
+
+		btVector3 rayDir = (rayToWorld-rayFromWorld);
+
+		rayDir.normalize ();
+		///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+		m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+		m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+		m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+		m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+		m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+		m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+		m_lambda_max = rayDir.dot(m_rayToWorld-m_rayFromWorld);
+
+	}
+
+
+
+	virtual bool	process(const btBroadphaseProxy* proxy)
+	{
+		///terminate further ray tests, once the closestHitFraction reached zero
+		if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+			return false;
+
+		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+		//only perform raycast if filterMask matches
+		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
+		{
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			//btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+#if 0
+#ifdef RECALCULATE_AABB
+			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+#else
+			//getBroadphase()->getAabb(collisionObject->getBroadphaseHandle(),collisionObjectAabbMin,collisionObjectAabbMax);
+			const btVector3& collisionObjectAabbMin = collisionObject->getBroadphaseHandle()->m_aabbMin;
+			const btVector3& collisionObjectAabbMax = collisionObject->getBroadphaseHandle()->m_aabbMax;
+#endif
+#endif
+			//btScalar hitLambda = m_resultCallback.m_closestHitFraction;
+			//culling already done by broadphase
+			//if (btRayAabb(m_rayFromWorld,m_rayToWorld,collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,m_hitNormal))
+			{
+				m_world->rayTestSingle(m_rayFromTrans,m_rayToTrans,
+					collisionObject,
+					collisionObject->getCollisionShape(),
+					collisionObject->getWorldTransform(),
+					m_resultCallback);
+			}
+		}
+		return true;
+	}
+};
+
+void	btCollisionWorld::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const
+{
+	//BT_PROFILE("rayTest");
+	/// use the broadphase to accelerate the search for objects, based on their aabb
+	/// and for each object with ray-aabb overlap, perform an exact ray test
+	btSingleRayCallback rayCB(rayFromWorld,rayToWorld,this,resultCallback);
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+	m_broadphasePairCache->rayTest(rayFromWorld,rayToWorld,rayCB);
+#else
+	for (int i=0;i<this->getNumCollisionObjects();i++)
+	{
+		rayCB.process(m_collisionObjects[i]->getBroadphaseHandle());
+	}	
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+
+}
+
+
+struct btSingleSweepCallback : public btBroadphaseRayCallback
+{
+
+	btTransform	m_convexFromTrans;
+	btTransform	m_convexToTrans;
+	btVector3	m_hitNormal;
+	const btCollisionWorld*	m_world;
+	btCollisionWorld::ConvexResultCallback&	m_resultCallback;
+	btScalar	m_allowedCcdPenetration;
+	const btConvexShape* m_castShape;
+
+
+	btSingleSweepCallback(const btConvexShape* castShape, const btTransform& convexFromTrans,const btTransform& convexToTrans,const btCollisionWorld* world,btCollisionWorld::ConvexResultCallback& resultCallback,btScalar allowedPenetration)
+		:m_convexFromTrans(convexFromTrans),
+		m_convexToTrans(convexToTrans),
+		m_world(world),
+		m_resultCallback(resultCallback),
+		m_allowedCcdPenetration(allowedPenetration),
+		m_castShape(castShape)
+	{
+		btVector3 unnormalizedRayDir = (m_convexToTrans.getOrigin()-m_convexFromTrans.getOrigin());
+		btVector3 rayDir = unnormalizedRayDir.normalized();
+		///what about division by zero? --> just set rayDirection[i] to INF/BT_LARGE_FLOAT
+		m_rayDirectionInverse[0] = rayDir[0] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[0];
+		m_rayDirectionInverse[1] = rayDir[1] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[1];
+		m_rayDirectionInverse[2] = rayDir[2] == btScalar(0.0) ? btScalar(BT_LARGE_FLOAT) : btScalar(1.0) / rayDir[2];
+		m_signs[0] = m_rayDirectionInverse[0] < 0.0;
+		m_signs[1] = m_rayDirectionInverse[1] < 0.0;
+		m_signs[2] = m_rayDirectionInverse[2] < 0.0;
+
+		m_lambda_max = rayDir.dot(unnormalizedRayDir);
+
+	}
+
+	virtual bool	process(const btBroadphaseProxy* proxy)
+	{
+		///terminate further convex sweep tests, once the closestHitFraction reached zero
+		if (m_resultCallback.m_closestHitFraction == btScalar(0.f))
+			return false;
+
+		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
+
+		//only perform raycast if filterMask matches
+		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			m_world->objectQuerySingle(m_castShape, m_convexFromTrans,m_convexToTrans,
+				collisionObject,
+				collisionObject->getCollisionShape(),
+				collisionObject->getWorldTransform(),
+				m_resultCallback,
+				m_allowedCcdPenetration);
+		}
+
+		return true;
+	}
+};
+
+
+
+void	btCollisionWorld::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+{
+
+	BT_PROFILE("convexSweepTest");
+	/// use the broadphase to accelerate the search for objects, based on their aabb
+	/// and for each object with ray-aabb overlap, perform an exact ray test
+	/// unfortunately the implementation for rayTest and convexSweepTest duplicated, albeit practically identical
+
+
+
+	btTransform	convexFromTrans,convexToTrans;
+	convexFromTrans = convexFromWorld;
+	convexToTrans = convexToWorld;
+	btVector3 castShapeAabbMin, castShapeAabbMax;
+	/* Compute AABB that encompasses angular movement */
+	{
+		btVector3 linVel, angVel;
+		btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+		btVector3 zeroLinVel;
+		zeroLinVel.setValue(0,0,0);
+		btTransform R;
+		R.setIdentity ();
+		R.setRotation (convexFromTrans.getRotation());
+		castShape->calculateTemporalAabb (R, zeroLinVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+	}
+
+#ifndef USE_BRUTEFORCE_RAYBROADPHASE
+
+	btSingleSweepCallback	convexCB(castShape,convexFromWorld,convexToWorld,this,resultCallback,allowedCcdPenetration);
+
+	m_broadphasePairCache->rayTest(convexFromTrans.getOrigin(),convexToTrans.getOrigin(),convexCB,castShapeAabbMin,castShapeAabbMax);
+
+#else
+	/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
+	// do a ray-shape query using convexCaster (CCD)
+	int i;
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject*	collisionObject= m_collisionObjects[i];
+		//only perform raycast if filterMask matches
+		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+			AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+			btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+			btVector3 hitNormal;
+			if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+			{
+				objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+					collisionObject,
+					collisionObject->getCollisionShape(),
+					collisionObject->getWorldTransform(),
+					resultCallback,
+					allowedCcdPenetration);
+			}
+		}
+	}
+#endif //USE_BRUTEFORCE_RAYBROADPHASE
+}
+
+
+
+struct btBridgedManifoldResult : public btManifoldResult
+{
+
+	btCollisionWorld::ContactResultCallback&	m_resultCallback;
+
+	btBridgedManifoldResult( btCollisionObject* obj0,btCollisionObject* obj1,btCollisionWorld::ContactResultCallback& resultCallback )
+		:btManifoldResult(obj0,obj1),
+		m_resultCallback(resultCallback)
+	{
+	}
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+	{
+		bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+		btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+		btVector3 localA;
+		btVector3 localB;
+		if (isSwapped)
+		{
+			localA = m_rootTransB.invXform(pointA );
+			localB = m_rootTransA.invXform(pointInWorld);
+		} else
+		{
+			localA = m_rootTransA.invXform(pointA );
+			localB = m_rootTransB.invXform(pointInWorld);
+		}
+		
+		btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+		newPt.m_positionWorldOnA = pointA;
+		newPt.m_positionWorldOnB = pointInWorld;
+		
+	   //BP mod, store contact triangles.
+		if (isSwapped)
+		{
+			newPt.m_partId0 = m_partId1;
+			newPt.m_partId1 = m_partId0;
+			newPt.m_index0  = m_index1;
+			newPt.m_index1  = m_index0;
+		} else
+		{
+			newPt.m_partId0 = m_partId0;
+			newPt.m_partId1 = m_partId1;
+			newPt.m_index0  = m_index0;
+			newPt.m_index1  = m_index1;
+		}
+
+		//experimental feature info, for per-triangle material etc.
+		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
+		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
+		m_resultCallback.addSingleResult(newPt,obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1);
+
+	}
+	
+};
+
+
+
+struct btSingleContactCallback : public btBroadphaseAabbCallback
+{
+
+	btCollisionObject* m_collisionObject;
+	btCollisionWorld*	m_world;
+	btCollisionWorld::ContactResultCallback&	m_resultCallback;
+	
+	
+	btSingleContactCallback(btCollisionObject* collisionObject, btCollisionWorld* world,btCollisionWorld::ContactResultCallback& resultCallback)
+		:m_collisionObject(collisionObject),
+		m_world(world),
+		m_resultCallback(resultCallback)
+	{
+	}
+
+	virtual bool	process(const btBroadphaseProxy* proxy)
+	{
+		btCollisionObject*	collisionObject = (btCollisionObject*)proxy->m_clientObject;
+		if (collisionObject == m_collisionObject)
+			return true;
+
+		//only perform raycast if filterMask matches
+		if(m_resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
+		{
+			btCollisionAlgorithm* algorithm = m_world->getDispatcher()->findAlgorithm(m_collisionObject,collisionObject);
+			if (algorithm)
+			{
+				btBridgedManifoldResult contactPointResult(m_collisionObject,collisionObject, m_resultCallback);
+				//discrete collision detection query
+				algorithm->processCollision(m_collisionObject,collisionObject, m_world->getDispatchInfo(),&contactPointResult);
+
+				algorithm->~btCollisionAlgorithm();
+				m_world->getDispatcher()->freeCollisionAlgorithm(algorithm);
+			}
+		}
+		return true;
+	}
+};
+
+
+///contactTest performs a discrete collision test against all objects in the btCollisionWorld, and calls the resultCallback.
+///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+void	btCollisionWorld::contactTest( btCollisionObject* colObj, ContactResultCallback& resultCallback)
+{
+	btVector3 aabbMin,aabbMax;
+	colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(),aabbMin,aabbMax);
+	btSingleContactCallback	contactCB(colObj,this,resultCallback);
+	
+	m_broadphasePairCache->aabbTest(aabbMin,aabbMax,contactCB);
+}
+
+
+///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+///it reports one or more contact points (including the one with deepest penetration)
+void	btCollisionWorld::contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback)
+{
+	btCollisionAlgorithm* algorithm = getDispatcher()->findAlgorithm(colObjA,colObjB);
+	if (algorithm)
+	{
+		btBridgedManifoldResult contactPointResult(colObjA,colObjB, resultCallback);
+		//discrete collision detection query
+		algorithm->processCollision(colObjA,colObjB, getDispatchInfo(),&contactPointResult);
+
+		algorithm->~btCollisionAlgorithm();
+		getDispatcher()->freeCollisionAlgorithm(algorithm);
+	}
+
+}
+
+
+
+
+class DebugDrawcallback : public btTriangleCallback, public btInternalTriangleIndexCallback
+{
+	btIDebugDraw*	m_debugDrawer;
+	btVector3	m_color;
+	btTransform	m_worldTrans;
+
+public:
+
+	DebugDrawcallback(btIDebugDraw*	debugDrawer,const btTransform& worldTrans,const btVector3& color) :
+	  m_debugDrawer(debugDrawer),
+		  m_color(color),
+		  m_worldTrans(worldTrans)
+	  {
+	  }
+
+	  virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+	  {
+		  processTriangle(triangle,partId,triangleIndex);
+	  }
+
+	  virtual void processTriangle(btVector3* triangle,int partId, int triangleIndex)
+	  {
+		  (void)partId;
+		  (void)triangleIndex;
+
+		  btVector3 wv0,wv1,wv2;
+		  wv0 = m_worldTrans*triangle[0];
+		  wv1 = m_worldTrans*triangle[1];
+		  wv2 = m_worldTrans*triangle[2];
+		  btVector3 center = (wv0+wv1+wv2)*btScalar(1./3.);
+
+		  btVector3 normal = (wv1-wv0).cross(wv2-wv0);
+		  normal.normalize();
+		  btVector3 normalColor(1,1,0);
+		  m_debugDrawer->drawLine(center,center+normal,normalColor);
+
+
+
+		 
+		  m_debugDrawer->drawLine(wv0,wv1,m_color);
+		  m_debugDrawer->drawLine(wv1,wv2,m_color);
+		  m_debugDrawer->drawLine(wv2,wv0,m_color);
+	  }
+};
+
+
+void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color)
+{
+	// Draw a small simplex at the center of the object
+	getDebugDrawer()->drawTransform(worldTransform,1);
+
+	if (shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
+	{
+		const btCompoundShape* compoundShape = static_cast<const btCompoundShape*>(shape);
+		for (int i=compoundShape->getNumChildShapes()-1;i>=0;i--)
+		{
+			btTransform childTrans = compoundShape->getChildTransform(i);
+			const btCollisionShape* colShape = compoundShape->getChildShape(i);
+			debugDrawObject(worldTransform*childTrans,colShape,color);
+		}
+
+	} else
+	{
+		switch (shape->getShapeType())
+		{
+
+		case BOX_SHAPE_PROXYTYPE:
+			{
+				const btBoxShape* boxShape = static_cast<const btBoxShape*>(shape);
+				btVector3 halfExtents = boxShape->getHalfExtentsWithMargin();
+				getDebugDrawer()->drawBox(-halfExtents,halfExtents,worldTransform,color);
+				break;
+			}
+
+		case SPHERE_SHAPE_PROXYTYPE:
+			{
+				const btSphereShape* sphereShape = static_cast<const btSphereShape*>(shape);
+				btScalar radius = sphereShape->getMargin();//radius doesn't include the margin, so draw with margin
+
+				getDebugDrawer()->drawSphere(radius, worldTransform, color);
+				break;
+			}
+		case MULTI_SPHERE_SHAPE_PROXYTYPE:
+			{
+				const btMultiSphereShape* multiSphereShape = static_cast<const btMultiSphereShape*>(shape);
+
+				btTransform childTransform;
+				childTransform.setIdentity();
+
+				for (int i = multiSphereShape->getSphereCount()-1; i>=0;i--)
+				{
+					childTransform.setOrigin(multiSphereShape->getSpherePosition(i));
+					getDebugDrawer()->drawSphere(multiSphereShape->getSphereRadius(i), worldTransform*childTransform, color);
+				}
+
+				break;
+			}
+		case CAPSULE_SHAPE_PROXYTYPE:
+			{
+				const btCapsuleShape* capsuleShape = static_cast<const btCapsuleShape*>(shape);
+
+				btScalar radius = capsuleShape->getRadius();
+				btScalar halfHeight = capsuleShape->getHalfHeight();
+
+				int upAxis = capsuleShape->getUpAxis();
+
+
+				btVector3 capStart(0.f,0.f,0.f);
+				capStart[upAxis] = -halfHeight;
+
+				btVector3 capEnd(0.f,0.f,0.f);
+				capEnd[upAxis] = halfHeight;
+
+				// Draw the ends
+				{
+
+					btTransform childTransform = worldTransform;
+					childTransform.getOrigin() = worldTransform * capStart;
+					getDebugDrawer()->drawSphere(radius, childTransform, color);
+				}
+
+				{
+					btTransform childTransform = worldTransform;
+					childTransform.getOrigin() = worldTransform * capEnd;
+					getDebugDrawer()->drawSphere(radius, childTransform, color);
+				}
+
+				// Draw some additional lines
+				btVector3 start = worldTransform.getOrigin();
+
+
+				capStart[(upAxis+1)%3] = radius;
+				capEnd[(upAxis+1)%3] = radius;
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+				capStart[(upAxis+1)%3] = -radius;
+				capEnd[(upAxis+1)%3] = -radius;
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+
+				capStart[(upAxis+1)%3] = 0.f;
+				capEnd[(upAxis+1)%3] = 0.f;
+
+				capStart[(upAxis+2)%3] = radius;
+				capEnd[(upAxis+2)%3] = radius;
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+				capStart[(upAxis+2)%3] = -radius;
+				capEnd[(upAxis+2)%3] = -radius;
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * capStart,start+worldTransform.getBasis() * capEnd, color);
+
+
+				break;
+			}
+		case CONE_SHAPE_PROXYTYPE:
+			{
+				const btConeShape* coneShape = static_cast<const btConeShape*>(shape);
+				btScalar radius = coneShape->getRadius();//+coneShape->getMargin();
+				btScalar height = coneShape->getHeight();//+coneShape->getMargin();
+				btVector3 start = worldTransform.getOrigin();
+
+				int upAxis= coneShape->getConeUpIndex();
+
+
+				btVector3	offsetHeight(0,0,0);
+				offsetHeight[upAxis] = height * btScalar(0.5);
+				btVector3	offsetRadius(0,0,0);
+				offsetRadius[(upAxis+1)%3] = radius;
+				btVector3	offset2Radius(0,0,0);
+				offset2Radius[(upAxis+2)%3] = radius;
+
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color);
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color);
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight+offset2Radius),color);
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight),start+worldTransform.getBasis() * (-offsetHeight-offset2Radius),color);
+
+				// Drawing the base of the cone
+				btVector3 yaxis(0,0,0);
+				yaxis[upAxis] = btScalar(1.0);
+				btVector3 xaxis(0,0,0);
+				xaxis[(upAxis+1)%3] = btScalar(1.0);
+				getDebugDrawer()->drawArc(start-worldTransform.getBasis()*(offsetHeight),worldTransform.getBasis()*yaxis,worldTransform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,10.0);
+		break;
+
+			}
+		case CYLINDER_SHAPE_PROXYTYPE:
+			{
+				const btCylinderShape* cylinder = static_cast<const btCylinderShape*>(shape);
+				int upAxis = cylinder->getUpAxis();
+				btScalar radius = cylinder->getRadius();
+				btScalar halfHeight = cylinder->getHalfExtentsWithMargin()[upAxis];
+				btVector3 start = worldTransform.getOrigin();
+				btVector3	offsetHeight(0,0,0);
+				offsetHeight[upAxis] = halfHeight;
+				btVector3	offsetRadius(0,0,0);
+				offsetRadius[(upAxis+1)%3] = radius;
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight+offsetRadius),start+worldTransform.getBasis() * (-offsetHeight+offsetRadius),color);
+				getDebugDrawer()->drawLine(start+worldTransform.getBasis() * (offsetHeight-offsetRadius),start+worldTransform.getBasis() * (-offsetHeight-offsetRadius),color);
+
+				// Drawing top and bottom caps of the cylinder
+				btVector3 yaxis(0,0,0);
+				yaxis[upAxis] = btScalar(1.0);
+				btVector3 xaxis(0,0,0);
+				xaxis[(upAxis+1)%3] = btScalar(1.0);
+				getDebugDrawer()->drawArc(start-worldTransform.getBasis()*(offsetHeight),worldTransform.getBasis()*yaxis,worldTransform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
+				getDebugDrawer()->drawArc(start+worldTransform.getBasis()*(offsetHeight),worldTransform.getBasis()*yaxis,worldTransform.getBasis()*xaxis,radius,radius,0,SIMD_2_PI,color,false,btScalar(10.0));
+				break;
+			}
+
+		case STATIC_PLANE_PROXYTYPE:
+			{
+				const btStaticPlaneShape* staticPlaneShape = static_cast<const btStaticPlaneShape*>(shape);
+				btScalar planeConst = staticPlaneShape->getPlaneConstant();
+				const btVector3& planeNormal = staticPlaneShape->getPlaneNormal();
+				btVector3 planeOrigin = planeNormal * planeConst;
+				btVector3 vec0,vec1;
+				btPlaneSpace1(planeNormal,vec0,vec1);
+				btScalar vecLen = 100.f;
+				btVector3 pt0 = planeOrigin + vec0*vecLen;
+				btVector3 pt1 = planeOrigin - vec0*vecLen;
+				btVector3 pt2 = planeOrigin + vec1*vecLen;
+				btVector3 pt3 = planeOrigin - vec1*vecLen;
+				getDebugDrawer()->drawLine(worldTransform*pt0,worldTransform*pt1,color);
+				getDebugDrawer()->drawLine(worldTransform*pt2,worldTransform*pt3,color);
+				break;
+
+			}
+		default:
+			{
+
+				if (shape->isConcave())
+				{
+					btConcaveShape* concaveMesh = (btConcaveShape*) shape;
+
+					///@todo pass camera, for some culling? no -> we are not a graphics lib
+					btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+					btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+
+					DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+					concaveMesh->processAllTriangles(&drawCallback,aabbMin,aabbMax);
+
+				}
+
+				if (shape->getShapeType() == CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE)
+				{
+					btConvexTriangleMeshShape* convexMesh = (btConvexTriangleMeshShape*) shape;
+					//todo: pass camera for some culling			
+					btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+					btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+					//DebugDrawcallback drawCallback;
+					DebugDrawcallback drawCallback(getDebugDrawer(),worldTransform,color);
+					convexMesh->getMeshInterface()->InternalProcessAllTriangles(&drawCallback,aabbMin,aabbMax);
+				}
+
+
+				/// for polyhedral shapes
+				if (shape->isPolyhedral())
+				{
+					btPolyhedralConvexShape* polyshape = (btPolyhedralConvexShape*) shape;
+
+					int i;
+					for (i=0;i<polyshape->getNumEdges();i++)
+					{
+						btVector3 a,b;
+						polyshape->getEdge(i,a,b);
+						btVector3 wa = worldTransform * a;
+						btVector3 wb = worldTransform * b;
+						getDebugDrawer()->drawLine(wa,wb,color);
+
+					}
+
+
+				}
+			}
+		}
+	}
+}
+
+
+void	btCollisionWorld::debugDrawWorld()
+{
+	if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)
+	{
+		int numManifolds = getDispatcher()->getNumManifolds();
+		btVector3 color(0,0,0);
+		for (int i=0;i<numManifolds;i++)
+		{
+			btPersistentManifold* contactManifold = getDispatcher()->getManifoldByIndexInternal(i);
+			//btCollisionObject* obA = static_cast<btCollisionObject*>(contactManifold->getBody0());
+			//btCollisionObject* obB = static_cast<btCollisionObject*>(contactManifold->getBody1());
+
+			int numContacts = contactManifold->getNumContacts();
+			for (int j=0;j<numContacts;j++)
+			{
+				btManifoldPoint& cp = contactManifold->getContactPoint(j);
+				getDebugDrawer()->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color);
+			}
+		}
+	}
+
+	if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))
+	{
+		int i;
+
+		for (  i=0;i<m_collisionObjects.size();i++)
+		{
+			btCollisionObject* colObj = m_collisionObjects[i];
+			if ((colObj->getCollisionFlags() & btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT)==0)
+			{
+				if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawWireframe)
+				{
+					btVector3 color(btScalar(1.),btScalar(1.),btScalar(1.));
+					switch(colObj->getActivationState())
+					{
+					case  ACTIVE_TAG:
+						color = btVector3(btScalar(1.),btScalar(1.),btScalar(1.)); break;
+					case ISLAND_SLEEPING:
+						color =  btVector3(btScalar(0.),btScalar(1.),btScalar(0.));break;
+					case WANTS_DEACTIVATION:
+						color = btVector3(btScalar(0.),btScalar(1.),btScalar(1.));break;
+					case DISABLE_DEACTIVATION:
+						color = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));break;
+					case DISABLE_SIMULATION:
+						color = btVector3(btScalar(1.),btScalar(1.),btScalar(0.));break;
+					default:
+						{
+							color = btVector3(btScalar(1),btScalar(0.),btScalar(0.));
+						}
+					};
+
+					debugDrawObject(colObj->getWorldTransform(),colObj->getCollisionShape(),color);
+				}
+				if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+				{
+					btVector3 minAabb,maxAabb;
+					btVector3 colorvec(1,0,0);
+					colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+					m_debugDrawer->drawAabb(minAabb,maxAabb,colorvec);
+				}
+			}
+
+		}
+	}
+}
+
+
+void	btCollisionWorld::serializeCollisionObjects(btSerializer* serializer)
+{
+	int i;
+	//serialize all collision objects
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		if (colObj->getInternalType() == btCollisionObject::CO_COLLISION_OBJECT)
+		{
+			colObj->serializeSingleObject(serializer);
+		}
+	}
+
+	///keep track of shapes already serialized
+	btHashMap<btHashPtr,btCollisionShape*>	serializedShapes;
+
+	for (i=0;i<m_collisionObjects.size();i++)
+	{
+		btCollisionObject* colObj = m_collisionObjects[i];
+		btCollisionShape* shape = colObj->getCollisionShape();
+
+		if (!serializedShapes.find(shape))
+		{
+			serializedShapes.insert(shape,shape);
+			shape->serializeSingleShape(serializer);
+		}
+	}
+
+}
+
+
+void	btCollisionWorld::serialize(btSerializer* serializer)
+{
+
+	serializer->startSerialization();
+	
+	serializeCollisionObjects(serializer);
+	
+	serializer->finishSerialization();
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
new file mode 100644
index 0000000..b42e2c4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCollisionWorld.h
@@ -0,0 +1,509 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://bulletphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+/**
+ * @mainpage Bullet Documentation
+ *
+ * @section intro_sec Introduction
+ * Bullet Collision Detection & Physics SDK
+ *
+ * Bullet is a Collision Detection and Rigid Body Dynamics Library. The Library is Open Source and free for commercial use, under the ZLib license ( http://opensource.org/licenses/zlib-license.php ).
+ *
+ * The main documentation is Bullet_User_Manual.pdf, included in the source code distribution.
+ * There is the Physics Forum for feedback and general Collision Detection and Physics discussions.
+ * Please visit http://www.bulletphysics.com
+ *
+ * @section install_sec Installation
+ *
+ * @subsection step1 Step 1: Download
+ * You can download the Bullet Physics Library from the Google Code repository: http://code.google.com/p/bullet/downloads/list
+ *
+ * @subsection step2 Step 2: Building
+ * Bullet main build system for all platforms is cmake, you can download http://www.cmake.org
+ * cmake can autogenerate projectfiles for Microsoft Visual Studio, Apple Xcode, KDevelop and Unix Makefiles.
+ * The easiest is to run the CMake cmake-gui graphical user interface and choose the options and generate projectfiles.
+ * You can also use cmake in the command-line. Here are some examples for various platforms:
+ * cmake . -G "Visual Studio 9 2008"
+ * cmake . -G Xcode
+ * cmake . -G "Unix Makefiles"
+ * Although cmake is recommended, you can also use autotools for UNIX: ./autogen.sh ./configure to create a Makefile and then run make.
+ * 
+ * @subsection step3 Step 3: Testing demos
+ * Try to run and experiment with BasicDemo executable as a starting point.
+ * Bullet can be used in several ways, as Full Rigid Body simulation, as Collision Detector Library or Low Level / Snippets like the GJK Closest Point calculation.
+ * The Dependencies can be seen in this documentation under Directories
+ * 
+ * @subsection step4 Step 4: Integrating in your application, full Rigid Body and Soft Body simulation
+ * Check out BasicDemo how to create a btDynamicsWorld, btRigidBody and btCollisionShape, Stepping the simulation and synchronizing your graphics object transform.
+ * Check out SoftDemo how to use soft body dynamics, using btSoftRigidDynamicsWorld.
+ * @subsection step5 Step 5 : Integrate the Collision Detection Library (without Dynamics and other Extras)
+ * Bullet Collision Detection can also be used without the Dynamics/Extras.
+ * Check out btCollisionWorld and btCollisionObject, and the CollisionInterfaceDemo.
+ * @subsection step6 Step 6 : Use Snippets like the GJK Closest Point calculation.
+ * Bullet has been designed in a modular way keeping dependencies to a minimum. The ConvexHullDistance demo demonstrates direct use of btGjkPairDetector.
+ *
+ * @section copyright Copyright
+ * For up-to-data information and copyright and contributors list check out the Bullet_User_Manual.pdf
+ * 
+ */
+ 
+ 
+
+#ifndef COLLISION_WORLD_H
+#define COLLISION_WORLD_H
+
+class btStackAlloc;
+class btCollisionShape;
+class btConvexShape;
+class btBroadphaseInterface;
+class btSerializer;
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btCollisionObject.h"
+#include "btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///CollisionWorld is interface and container for the collision detection
+class btCollisionWorld
+{
+
+	
+protected:
+
+	btAlignedObjectArray<btCollisionObject*>	m_collisionObjects;
+	
+	btDispatcher*	m_dispatcher1;
+
+	btDispatcherInfo	m_dispatchInfo;
+
+	btStackAlloc*	m_stackAlloc;
+
+	btBroadphaseInterface*	m_broadphasePairCache;
+
+	btIDebugDraw*	m_debugDrawer;
+
+	///m_forceUpdateAllAabbs can be set to false as an optimization to only update active object AABBs
+	///it is true by default, because it is error-prone (setting the position of static objects wouldn't update their AABB)
+	bool m_forceUpdateAllAabbs;
+
+	void	serializeCollisionObjects(btSerializer* serializer);
+
+public:
+
+	//this constructor doesn't own the dispatcher and paircache/broadphase
+	btCollisionWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphasePairCache, btCollisionConfiguration* collisionConfiguration);
+
+	virtual ~btCollisionWorld();
+
+	void	setBroadphase(btBroadphaseInterface*	pairCache)
+	{
+		m_broadphasePairCache = pairCache;
+	}
+
+	const btBroadphaseInterface*	getBroadphase() const
+	{
+		return m_broadphasePairCache;
+	}
+
+	btBroadphaseInterface*	getBroadphase()
+	{
+		return m_broadphasePairCache;
+	}
+
+	btOverlappingPairCache*	getPairCache()
+	{
+		return m_broadphasePairCache->getOverlappingPairCache();
+	}
+
+
+	btDispatcher*	getDispatcher()
+	{
+		return m_dispatcher1;
+	}
+
+	const btDispatcher*	getDispatcher() const
+	{
+		return m_dispatcher1;
+	}
+
+	void	updateSingleAabb(btCollisionObject* colObj);
+
+	virtual void	updateAabbs();
+	
+	virtual void	setDebugDrawer(btIDebugDraw*	debugDrawer)
+	{
+			m_debugDrawer = debugDrawer;
+	}
+
+	virtual btIDebugDraw*	getDebugDrawer()
+	{
+		return m_debugDrawer;
+	}
+
+	virtual void	debugDrawWorld();
+
+	virtual void debugDrawObject(const btTransform& worldTransform, const btCollisionShape* shape, const btVector3& color);
+
+
+	///LocalShapeInfo gives extra information for complex shapes
+	///Currently, only btTriangleMeshShape is available, so it just contains triangleIndex and subpart
+	struct	LocalShapeInfo
+	{
+		int	m_shapePart;
+		int	m_triangleIndex;
+		
+		//const btCollisionShape*	m_shapeTemp;
+		//const btTransform*	m_shapeLocalTransform;
+	};
+
+	struct	LocalRayResult
+	{
+		LocalRayResult(btCollisionObject*	collisionObject, 
+			LocalShapeInfo*	localShapeInfo,
+			const btVector3&		hitNormalLocal,
+			btScalar hitFraction)
+		:m_collisionObject(collisionObject),
+		m_localShapeInfo(localShapeInfo),
+		m_hitNormalLocal(hitNormalLocal),
+		m_hitFraction(hitFraction)
+		{
+		}
+
+		btCollisionObject*		m_collisionObject;
+		LocalShapeInfo*			m_localShapeInfo;
+		btVector3				m_hitNormalLocal;
+		btScalar				m_hitFraction;
+
+	};
+
+	///RayResultCallback is used to report new raycast results
+	struct	RayResultCallback
+	{
+		btScalar	m_closestHitFraction;
+		btCollisionObject*		m_collisionObject;
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+      //@BP Mod - Custom flags, currently used to enable backface culling on tri-meshes, see btRaycastCallback
+      unsigned int m_flags;
+
+		virtual ~RayResultCallback()
+		{
+		}
+		bool	hasHit() const
+		{
+			return (m_collisionObject != 0);
+		}
+
+		RayResultCallback()
+			:m_closestHitFraction(btScalar(1.)),
+			m_collisionObject(0),
+			m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+			m_collisionFilterMask(btBroadphaseProxy::AllFilter),
+         //@BP Mod
+         m_flags(0)
+		{
+		}
+
+		virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+		{
+			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			return collides;
+		}
+
+
+		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace) = 0;
+	};
+
+	struct	ClosestRayResultCallback : public RayResultCallback
+	{
+		ClosestRayResultCallback(const btVector3&	rayFromWorld,const btVector3&	rayToWorld)
+		:m_rayFromWorld(rayFromWorld),
+		m_rayToWorld(rayToWorld)
+		{
+		}
+
+		btVector3	m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
+		btVector3	m_rayToWorld;
+
+		btVector3	m_hitNormalWorld;
+		btVector3	m_hitPointWorld;
+			
+		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+		{
+			//caller already does the filter on the m_closestHitFraction
+			btAssert(rayResult.m_hitFraction <= m_closestHitFraction);
+			
+			m_closestHitFraction = rayResult.m_hitFraction;
+			m_collisionObject = rayResult.m_collisionObject;
+			if (normalInWorldSpace)
+			{
+				m_hitNormalWorld = rayResult.m_hitNormalLocal;
+			} else
+			{
+				///need to transform normal into worldspace
+				m_hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+			}
+			m_hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+			return rayResult.m_hitFraction;
+		}
+	};
+
+	struct	AllHitsRayResultCallback : public RayResultCallback
+	{
+		AllHitsRayResultCallback(const btVector3&	rayFromWorld,const btVector3&	rayToWorld)
+		:m_rayFromWorld(rayFromWorld),
+		m_rayToWorld(rayToWorld)
+		{
+		}
+
+		btAlignedObjectArray<btCollisionObject*>		m_collisionObjects;
+
+		btVector3	m_rayFromWorld;//used to calculate hitPointWorld from hitFraction
+		btVector3	m_rayToWorld;
+
+		btAlignedObjectArray<btVector3>	m_hitNormalWorld;
+		btAlignedObjectArray<btVector3>	m_hitPointWorld;
+		btAlignedObjectArray<btScalar> m_hitFractions;
+			
+		virtual	btScalar	addSingleResult(LocalRayResult& rayResult,bool normalInWorldSpace)
+		{
+			m_collisionObject = rayResult.m_collisionObject;
+			m_collisionObjects.push_back(rayResult.m_collisionObject);
+			btVector3 hitNormalWorld;
+			if (normalInWorldSpace)
+			{
+				hitNormalWorld = rayResult.m_hitNormalLocal;
+			} else
+			{
+				///need to transform normal into worldspace
+				hitNormalWorld = m_collisionObject->getWorldTransform().getBasis()*rayResult.m_hitNormalLocal;
+			}
+			m_hitNormalWorld.push_back(hitNormalWorld);
+			btVector3 hitPointWorld;
+			hitPointWorld.setInterpolate3(m_rayFromWorld,m_rayToWorld,rayResult.m_hitFraction);
+			m_hitPointWorld.push_back(hitPointWorld);
+			m_hitFractions.push_back(rayResult.m_hitFraction);
+			return m_closestHitFraction;
+		}
+	};
+
+
+	struct LocalConvexResult
+	{
+		LocalConvexResult(btCollisionObject*	hitCollisionObject, 
+			LocalShapeInfo*	localShapeInfo,
+			const btVector3&		hitNormalLocal,
+			const btVector3&		hitPointLocal,
+			btScalar hitFraction
+			)
+		:m_hitCollisionObject(hitCollisionObject),
+		m_localShapeInfo(localShapeInfo),
+		m_hitNormalLocal(hitNormalLocal),
+		m_hitPointLocal(hitPointLocal),
+		m_hitFraction(hitFraction)
+		{
+		}
+
+		btCollisionObject*		m_hitCollisionObject;
+		LocalShapeInfo*			m_localShapeInfo;
+		btVector3				m_hitNormalLocal;
+		btVector3				m_hitPointLocal;
+		btScalar				m_hitFraction;
+	};
+
+	///RayResultCallback is used to report new raycast results
+	struct	ConvexResultCallback
+	{
+		btScalar	m_closestHitFraction;
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+		
+		ConvexResultCallback()
+			:m_closestHitFraction(btScalar(1.)),
+			m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+			m_collisionFilterMask(btBroadphaseProxy::AllFilter)
+		{
+		}
+
+		virtual ~ConvexResultCallback()
+		{
+		}
+		
+		bool	hasHit() const
+		{
+			return (m_closestHitFraction < btScalar(1.));
+		}
+
+		
+
+		virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+		{
+			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			return collides;
+		}
+
+		virtual	btScalar	addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace) = 0;
+	};
+
+	struct	ClosestConvexResultCallback : public ConvexResultCallback
+	{
+		ClosestConvexResultCallback(const btVector3&	convexFromWorld,const btVector3&	convexToWorld)
+		:m_convexFromWorld(convexFromWorld),
+		m_convexToWorld(convexToWorld),
+		m_hitCollisionObject(0)
+		{
+		}
+
+		btVector3	m_convexFromWorld;//used to calculate hitPointWorld from hitFraction
+		btVector3	m_convexToWorld;
+
+		btVector3	m_hitNormalWorld;
+		btVector3	m_hitPointWorld;
+		btCollisionObject*	m_hitCollisionObject;
+		
+		virtual	btScalar	addSingleResult(LocalConvexResult& convexResult,bool normalInWorldSpace)
+		{
+//caller already does the filter on the m_closestHitFraction
+			btAssert(convexResult.m_hitFraction <= m_closestHitFraction);
+						
+			m_closestHitFraction = convexResult.m_hitFraction;
+			m_hitCollisionObject = convexResult.m_hitCollisionObject;
+			if (normalInWorldSpace)
+			{
+				m_hitNormalWorld = convexResult.m_hitNormalLocal;
+			} else
+			{
+				///need to transform normal into worldspace
+				m_hitNormalWorld = m_hitCollisionObject->getWorldTransform().getBasis()*convexResult.m_hitNormalLocal;
+			}
+			m_hitPointWorld = convexResult.m_hitPointLocal;
+			return convexResult.m_hitFraction;
+		}
+	};
+
+	///ContactResultCallback is used to report contact points
+	struct	ContactResultCallback
+	{
+		short int	m_collisionFilterGroup;
+		short int	m_collisionFilterMask;
+		
+		ContactResultCallback()
+			:m_collisionFilterGroup(btBroadphaseProxy::DefaultFilter),
+			m_collisionFilterMask(btBroadphaseProxy::AllFilter)
+		{
+		}
+
+		virtual ~ContactResultCallback()
+		{
+		}
+		
+		virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+		{
+			bool collides = (proxy0->m_collisionFilterGroup & m_collisionFilterMask) != 0;
+			collides = collides && (m_collisionFilterGroup & proxy0->m_collisionFilterMask);
+			return collides;
+		}
+
+		virtual	btScalar	addSingleResult(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1) = 0;
+	};
+
+
+
+	int	getNumCollisionObjects() const
+	{
+		return int(m_collisionObjects.size());
+	}
+
+	/// rayTest performs a raycast on all objects in the btCollisionWorld, and calls the resultCallback
+	/// This allows for several queries: first hit, all hits, any hit, dependent on the value returned by the callback.
+	virtual void rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, RayResultCallback& resultCallback) const; 
+
+	/// convexTest performs a swept convex cast on all objects in the btCollisionWorld, and calls the resultCallback
+	/// This allows for several queries: first hit, all hits, any hit, dependent on the value return by the callback.
+	void    convexSweepTest (const btConvexShape* castShape, const btTransform& from, const btTransform& to, ConvexResultCallback& resultCallback,  btScalar allowedCcdPenetration = btScalar(0.)) const;
+
+	///contactTest performs a discrete collision test between colObj against all objects in the btCollisionWorld, and calls the resultCallback.
+	///it reports one or more contact points for every overlapping object (including the one with deepest penetration)
+	void	contactTest(btCollisionObject* colObj, ContactResultCallback& resultCallback);
+
+	///contactTest performs a discrete collision test between two collision objects and calls the resultCallback if overlap if detected.
+	///it reports one or more contact points (including the one with deepest penetration)
+	void	contactPairTest(btCollisionObject* colObjA, btCollisionObject* colObjB, ContactResultCallback& resultCallback);
+
+
+	/// rayTestSingle performs a raycast call and calls the resultCallback. It is used internally by rayTest.
+	/// In a future implementation, we consider moving the ray test as a virtual method in btCollisionShape.
+	/// This allows more customization.
+	static void	rayTestSingle(const btTransform& rayFromTrans,const btTransform& rayToTrans,
+					  btCollisionObject* collisionObject,
+					  const btCollisionShape* collisionShape,
+					  const btTransform& colObjWorldTransform,
+					  RayResultCallback& resultCallback);
+
+	/// objectQuerySingle performs a collision detection query and calls the resultCallback. It is used internally by rayTest.
+	static void	objectQuerySingle(const btConvexShape* castShape, const btTransform& rayFromTrans,const btTransform& rayToTrans,
+					  btCollisionObject* collisionObject,
+					  const btCollisionShape* collisionShape,
+					  const btTransform& colObjWorldTransform,
+					  ConvexResultCallback& resultCallback, btScalar	allowedPenetration);
+
+	virtual void	addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::DefaultFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter);
+
+	btCollisionObjectArray& getCollisionObjectArray()
+	{
+		return m_collisionObjects;
+	}
+
+	const btCollisionObjectArray& getCollisionObjectArray() const
+	{
+		return m_collisionObjects;
+	}
+
+
+	virtual void	removeCollisionObject(btCollisionObject* collisionObject);
+
+	virtual void	performDiscreteCollisionDetection();
+
+	btDispatcherInfo& getDispatchInfo()
+	{
+		return m_dispatchInfo;
+	}
+
+	const btDispatcherInfo& getDispatchInfo() const
+	{
+		return m_dispatchInfo;
+	}
+	
+	bool	getForceUpdateAllAabbs() const
+	{
+		return m_forceUpdateAllAabbs;
+	}
+	void setForceUpdateAllAabbs( bool forceUpdateAllAabbs)
+	{
+		m_forceUpdateAllAabbs = forceUpdateAllAabbs;
+	}
+
+	///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (Bullet/Demos/SerializeDemo)
+	virtual	void	serialize(btSerializer* serializer);
+
+};
+
+
+#endif //COLLISION_WORLD_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
new file mode 100644
index 0000000..1262eef
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp
@@ -0,0 +1,353 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "btManifoldResult.h"
+
+btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
+:btActivatingCollisionAlgorithm(ci,body0,body1),
+m_isSwapped(isSwapped),
+m_sharedManifold(ci.m_manifold)
+{
+	m_ownsManifold = false;
+
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btAssert (colObj->getCollisionShape()->isCompound());
+	
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+	m_compoundShapeRevision = compoundShape->getUpdateRevision();
+	
+	preallocateChildAlgorithms(body0,body1);
+}
+
+void	btCompoundCollisionAlgorithm::preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1)
+{
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+	btAssert (colObj->getCollisionShape()->isCompound());
+	
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+	int numChildren = compoundShape->getNumChildShapes();
+	int i;
+	
+	m_childCollisionAlgorithms.resize(numChildren);
+	for (i=0;i<numChildren;i++)
+	{
+		if (compoundShape->getDynamicAabbTree())
+		{
+			m_childCollisionAlgorithms[i] = 0;
+		} else
+		{
+			btCollisionShape* tmpShape = colObj->getCollisionShape();
+			btCollisionShape* childShape = compoundShape->getChildShape(i);
+			colObj->internalSetTemporaryCollisionShape( childShape );
+			m_childCollisionAlgorithms[i] = m_dispatcher->findAlgorithm(colObj,otherObj,m_sharedManifold);
+			colObj->internalSetTemporaryCollisionShape( tmpShape );
+		}
+	}
+}
+
+void	btCompoundCollisionAlgorithm::removeChildAlgorithms()
+{
+	int numChildren = m_childCollisionAlgorithms.size();
+	int i;
+	for (i=0;i<numChildren;i++)
+	{
+		if (m_childCollisionAlgorithms[i])
+		{
+			m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+			m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+		}
+	}
+}
+
+btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm()
+{
+	removeChildAlgorithms();
+}
+
+
+
+
+struct	btCompoundLeafCallback : btDbvt::ICollide
+{
+
+public:
+
+	btCollisionObject* m_compoundColObj;
+	btCollisionObject* m_otherObj;
+	btDispatcher* m_dispatcher;
+	const btDispatcherInfo& m_dispatchInfo;
+	btManifoldResult*	m_resultOut;
+	btCollisionAlgorithm**	m_childCollisionAlgorithms;
+	btPersistentManifold*	m_sharedManifold;
+
+
+
+
+	btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult*	resultOut,btCollisionAlgorithm**	childCollisionAlgorithms,btPersistentManifold*	sharedManifold)
+		:m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut),
+		m_childCollisionAlgorithms(childCollisionAlgorithms),
+		m_sharedManifold(sharedManifold)
+	{
+
+	}
+
+
+	void	ProcessChildShape(btCollisionShape* childShape,int index)
+	{
+		btAssert(index>=0);
+		btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
+		btAssert(index<compoundShape->getNumChildShapes());
+
+
+		//backup
+		btTransform	orgTrans = m_compoundColObj->getWorldTransform();
+		btTransform	orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform();
+		const btTransform& childTrans = compoundShape->getChildTransform(index);
+		btTransform	newChildWorldTrans = orgTrans*childTrans ;
+
+		//perform an AABB check first
+		btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;
+		childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
+		m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1);
+
+		if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+		{
+
+			m_compoundColObj->setWorldTransform( newChildWorldTrans);
+			m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans);
+
+			//the contactpoint is still projected back using the original inverted worldtrans
+			btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape();
+			m_compoundColObj->internalSetTemporaryCollisionShape( childShape );
+
+			if (!m_childCollisionAlgorithms[index])
+				m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold);
+
+			///detect swapping case
+			if (m_resultOut->getBody0Internal() == m_compoundColObj)
+			{
+				m_resultOut->setShapeIdentifiersA(-1,index);
+			} else
+			{
+				m_resultOut->setShapeIdentifiersB(-1,index);
+			}
+
+			m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut);
+			if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+			{
+				btVector3 worldAabbMin,worldAabbMax;
+				m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1));
+				m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1));
+			}
+			
+			//revert back transform
+			m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape);
+			m_compoundColObj->setWorldTransform(  orgTrans );
+			m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans);
+		}
+	}
+	void		Process(const btDbvtNode* leaf)
+	{
+		int index = leaf->dataAsInt;
+
+		btCompoundShape* compoundShape = static_cast<btCompoundShape*>(m_compoundColObj->getCollisionShape());
+		btCollisionShape* childShape = compoundShape->getChildShape(index);
+		if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb))
+		{
+			btVector3 worldAabbMin,worldAabbMax;
+			btTransform	orgTrans = m_compoundColObj->getWorldTransform();
+			btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax);
+			m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0));
+		}
+		ProcessChildShape(childShape,index);
+
+	}
+};
+
+
+
+
+
+
+void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+
+	
+
+	btAssert (colObj->getCollisionShape()->isCompound());
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+	///btCompoundShape might have changed:
+	////make sure the internal child collision algorithm caches are still valid
+	if (compoundShape->getUpdateRevision() != m_compoundShapeRevision)
+	{
+		///clear and update all
+		removeChildAlgorithms();
+		
+		preallocateChildAlgorithms(body0,body1);
+	}
+
+
+	btDbvt* tree = compoundShape->getDynamicAabbTree();
+	//use a dynamic aabb tree to cull potential child-overlaps
+	btCompoundLeafCallback  callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold);
+
+	///we need to refresh all contact manifolds
+	///note that we should actually recursively traverse all children, btCompoundShape can nested more then 1 level deep
+	///so we should add a 'refreshManifolds' in the btCollisionAlgorithm
+	{
+		int i;
+		btManifoldArray manifoldArray;
+		for (i=0;i<m_childCollisionAlgorithms.size();i++)
+		{
+			if (m_childCollisionAlgorithms[i])
+			{
+				m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+				for (int m=0;m<manifoldArray.size();m++)
+				{
+					if (manifoldArray[m]->getNumContacts())
+					{
+						resultOut->setPersistentManifold(manifoldArray[m]);
+						resultOut->refreshContactPoints();
+						resultOut->setPersistentManifold(0);//??necessary?
+					}
+				}
+				manifoldArray.clear();
+			}
+		}
+	}
+
+	if (tree)
+	{
+
+		btVector3 localAabbMin,localAabbMax;
+		btTransform otherInCompoundSpace;
+		otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform();
+		otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax);
+
+		const ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+		//process all children, that overlap with  the given AABB bounds
+		tree->collideTV(tree->m_root,bounds,callback);
+
+	} else
+	{
+		//iterate over all children, perform an AABB check inside ProcessChildShape
+		int numChildren = m_childCollisionAlgorithms.size();
+		int i;
+		for (i=0;i<numChildren;i++)
+		{
+			callback.ProcessChildShape(compoundShape->getChildShape(i),i);
+		}
+	}
+
+	{
+				//iterate over all children, perform an AABB check inside ProcessChildShape
+		int numChildren = m_childCollisionAlgorithms.size();
+		int i;
+		btManifoldArray	manifoldArray;
+        btCollisionShape* childShape = 0;
+        btTransform	orgTrans;
+        btTransform	orgInterpolationTrans;
+        btTransform	newChildWorldTrans;
+        btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1;        
+        
+		for (i=0;i<numChildren;i++)
+		{
+			if (m_childCollisionAlgorithms[i])
+			{
+				childShape = compoundShape->getChildShape(i);
+			//if not longer overlapping, remove the algorithm
+                orgTrans = colObj->getWorldTransform();
+                orgInterpolationTrans = colObj->getInterpolationWorldTransform();
+				const btTransform& childTrans = compoundShape->getChildTransform(i);
+                newChildWorldTrans = orgTrans*childTrans ;
+
+				//perform an AABB check first
+				childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0);
+				otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1);
+
+				if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1))
+				{
+					m_childCollisionAlgorithms[i]->~btCollisionAlgorithm();
+					m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]);
+					m_childCollisionAlgorithms[i] = 0;
+				}
+			}
+		}
+	}
+}
+
+btScalar	btCompoundCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+	btCollisionObject* colObj = m_isSwapped? body1 : body0;
+	btCollisionObject* otherObj = m_isSwapped? body0 : body1;
+
+	btAssert (colObj->getCollisionShape()->isCompound());
+	
+	btCompoundShape* compoundShape = static_cast<btCompoundShape*>(colObj->getCollisionShape());
+
+	//We will use the OptimizedBVH, AABB tree to cull potential child-overlaps
+	//If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals
+	//given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means:
+	//determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1
+	//then use each overlapping node AABB against Tree0
+	//and vise versa.
+
+	btScalar hitFraction = btScalar(1.);
+
+	int numChildren = m_childCollisionAlgorithms.size();
+	int i;
+    btTransform	orgTrans;
+    btScalar frac;
+	for (i=0;i<numChildren;i++)
+	{
+		//temporarily exchange parent btCollisionShape with childShape, and recurse
+		btCollisionShape* childShape = compoundShape->getChildShape(i);
+
+		//backup
+        orgTrans = colObj->getWorldTransform();
+	
+		const btTransform& childTrans = compoundShape->getChildTransform(i);
+		//btTransform	newChildWorldTrans = orgTrans*childTrans ;
+		colObj->setWorldTransform( orgTrans*childTrans );
+
+		btCollisionShape* tmpShape = colObj->getCollisionShape();
+		colObj->internalSetTemporaryCollisionShape( childShape );
+        frac = m_childCollisionAlgorithms[i]->calculateTimeOfImpact(colObj,otherObj,dispatchInfo,resultOut);
+		if (frac<hitFraction)
+		{
+			hitFraction = frac;
+		}
+		//revert back
+		colObj->internalSetTemporaryCollisionShape( tmpShape);
+		colObj->setWorldTransform( orgTrans);
+	}
+	return hitFraction;
+
+}
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
new file mode 100644
index 0000000..255e0af
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COMPOUND_COLLISION_ALGORITHM_H
+#define COMPOUND_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+class btDispatcher;
+class btCollisionObject;
+
+/// btCompoundCollisionAlgorithm  supports collision between CompoundCollisionShapes and other collision shapes
+class btCompoundCollisionAlgorithm  : public btActivatingCollisionAlgorithm
+{
+	btAlignedObjectArray<btCollisionAlgorithm*> m_childCollisionAlgorithms;
+	bool m_isSwapped;
+
+	class btPersistentManifold*	m_sharedManifold;
+	bool					m_ownsManifold;
+
+	int	m_compoundShapeRevision;//to keep track of changes, so that childAlgorithm array can be updated
+	
+	void	removeChildAlgorithms();
+	
+	void	preallocateChildAlgorithms(btCollisionObject* body0,btCollisionObject* body1);
+
+public:
+
+	btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+	virtual ~btCompoundCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btScalar	calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		int i;
+		for (i=0;i<m_childCollisionAlgorithms.size();i++)
+		{
+			if (m_childCollisionAlgorithms[i])
+				m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray);
+		}
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+			return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,false);
+		}
+	};
+
+	struct SwappedCreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btCompoundCollisionAlgorithm));
+			return new(mem) btCompoundCollisionAlgorithm(ci,body0,body1,true);
+		}
+	};
+
+};
+
+#endif //COMPOUND_COLLISION_ALGORITHM_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
new file mode 100644
index 0000000..db7f884
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.cpp
@@ -0,0 +1,247 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvex2dConvex2dAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+
+
+btConvex2dConvex2dAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
+{
+	m_numPerturbationIterations = 0;
+	m_minimumPointsPerturbationThreshold = 3;
+	m_simplexSolver = simplexSolver;
+	m_pdSolver = pdSolver;
+}
+
+btConvex2dConvex2dAlgorithm::CreateFunc::~CreateFunc() 
+{ 
+}
+
+btConvex2dConvex2dAlgorithm::btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+: btActivatingCollisionAlgorithm(ci,body0,body1),
+m_simplexSolver(simplexSolver),
+m_pdSolver(pdSolver),
+m_ownManifold (false),
+m_manifoldPtr(mf),
+m_lowLevelOfDetail(false),
+ m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+	(void)body0;
+	(void)body1;
+}
+
+
+
+
+btConvex2dConvex2dAlgorithm::~btConvex2dConvex2dAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void	btConvex2dConvex2dAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+	m_lowLevelOfDetail = useLowLevel;
+}
+
+
+
+extern btScalar gContactBreakingThreshold;
+
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvex2dConvex2dAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+	if (!m_manifoldPtr)
+	{
+		//swapped?
+		m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+		m_ownManifold = true;
+	}
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	//comment-out next line to test multi-contact generation
+	//resultOut->getPersistentManifold()->clearManifold();
+
+
+	btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
+	btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
+
+	btVector3  normalOnB;
+	btVector3  pointOnBWorld;
+
+	{
+
+
+		btGjkPairDetector::ClosestPointInput input;
+
+		btGjkPairDetector	gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
+		//TODO: if (dispatchInfo.m_useContinuous)
+		gjkPairDetector.setMinkowskiA(min0);
+		gjkPairDetector.setMinkowskiB(min1);
+
+		{
+			input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
+			input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
+		}
+
+		input.m_stackAlloc = dispatchInfo.m_stackAllocator;
+		input.m_transformA = body0->getWorldTransform();
+		input.m_transformB = body1->getWorldTransform();
+
+		gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+		btVector3 v0,v1;
+		btVector3 sepNormalWorldSpace;
+
+	}
+
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+
+}
+
+
+
+
+btScalar	btConvex2dConvex2dAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+
+	///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+	///col0->m_worldTransform,
+	btScalar resultFraction = btScalar(1.);
+
+
+	btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+	btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+
+	if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+		squareMot1 < col1->getCcdSquareMotionThreshold())
+		return resultFraction;
+
+
+	//An adhoc way of testing the Continuous Collision Detection algorithms
+	//One object is approximated as a sphere, to simplify things
+	//Starting in penetration should report no time of impact
+	//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+	//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+
+	/// Convex0 against sphere for Convex1
+	{
+		btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+		btSphereShape	sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+
+			//store result.m_fraction in both bodies
+
+			if (col0->getHitFraction()> result.m_fraction)
+				col0->setHitFraction( result.m_fraction );
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+
+
+
+
+	}
+
+	/// Sphere (for convex0) against Convex1
+	{
+		btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+		btSphereShape	sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+
+			//store result.m_fraction in both bodies
+
+			if (col0->getHitFraction()	> result.m_fraction)
+				col0->setHitFraction( result.m_fraction);
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+	}
+
+	return resultFraction;
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
new file mode 100644
index 0000000..5738401
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvex2dConvex2dAlgorithm.h
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONVEX_2D_CONVEX_2D_ALGORITHM_H
+#define CONVEX_2D_CONVEX_2D_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+
+class btConvexPenetrationDepthSolver;
+
+
+///The convex2dConvex2dAlgorithm collision algorithm support 2d collision detection for btConvex2dShape
+///Currently it requires the btMinkowskiPenetrationDepthSolver, it has support for 2d penetration depth computation
+class btConvex2dConvex2dAlgorithm : public btActivatingCollisionAlgorithm
+{
+	btSimplexSolverInterface*		m_simplexSolver;
+	btConvexPenetrationDepthSolver* m_pdSolver;
+
+	
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool			m_lowLevelOfDetail;
+	
+	int m_numPerturbationIterations;
+	int m_minimumPointsPerturbationThreshold;
+
+public:
+
+	btConvex2dConvex2dAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+
+	virtual ~btConvex2dConvex2dAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		///should we use m_ownManifold to avoid adding duplicates?
+		if (m_manifoldPtr && m_ownManifold)
+			manifoldArray.push_back(m_manifoldPtr);
+	}
+
+
+	void	setLowLevelOfDetail(bool useLowLevel);
+
+
+	const btPersistentManifold*	getManifold()
+	{
+		return m_manifoldPtr;
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+
+		btConvexPenetrationDepthSolver*		m_pdSolver;
+		btSimplexSolverInterface*			m_simplexSolver;
+		int m_numPerturbationIterations;
+		int m_minimumPointsPerturbationThreshold;
+
+		CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
+		
+		virtual ~CreateFunc();
+
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvex2dConvex2dAlgorithm));
+			return new(mem) btConvex2dConvex2dAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+		}
+	};
+
+
+};
+
+#endif //CONVEX_2D_CONVEX_2D_ALGORITHM_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
new file mode 100644
index 0000000..268ec4b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp
@@ -0,0 +1,321 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btConvexConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+
+btConvexConcaveCollisionAlgorithm::btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1,bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,body0,body1),
+m_isSwapped(isSwapped),
+m_btConvexTriangleCallback(ci.m_dispatcher1,body0,body1,isSwapped)
+{
+}
+
+btConvexConcaveCollisionAlgorithm::~btConvexConcaveCollisionAlgorithm()
+{
+}
+
+void	btConvexConcaveCollisionAlgorithm::getAllContactManifolds(btManifoldArray&	manifoldArray)
+{
+	if (m_btConvexTriangleCallback.m_manifoldPtr)
+	{
+		manifoldArray.push_back(m_btConvexTriangleCallback.m_manifoldPtr);
+	}
+}
+
+
+btConvexTriangleCallback::btConvexTriangleCallback(btDispatcher*  dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped):
+	  m_dispatcher(dispatcher),
+	m_dispatchInfoPtr(0)
+{
+	m_convexBody = isSwapped? body1:body0;
+	m_triBody = isSwapped? body0:body1;
+	
+	  //
+	  // create the manifold from the dispatcher 'manifold pool'
+	  //
+	  m_manifoldPtr = m_dispatcher->getNewManifold(m_convexBody,m_triBody);
+
+  	  clearCache();
+}
+
+btConvexTriangleCallback::~btConvexTriangleCallback()
+{
+	clearCache();
+	m_dispatcher->releaseManifold( m_manifoldPtr );
+  
+}
+  
+
+void	btConvexTriangleCallback::clearCache()
+{
+	m_dispatcher->clearManifold(m_manifoldPtr);
+}
+
+
+
+void btConvexTriangleCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+{
+ 
+	//just for debugging purposes
+	//printf("triangle %d",m_triangleCount++);
+
+
+	//aabb filter is already applied!	
+
+	btCollisionAlgorithmConstructionInfo ci;
+	ci.m_dispatcher1 = m_dispatcher;
+
+	btCollisionObject* ob = static_cast<btCollisionObject*>(m_triBody);
+
+
+	
+	///debug drawing of the overlapping triangles
+	if (m_dispatchInfoPtr && m_dispatchInfoPtr->m_debugDraw && (m_dispatchInfoPtr->m_debugDraw->getDebugMode() &btIDebugDraw::DBG_DrawWireframe ))
+	{
+		btVector3 color(1,1,0);
+		btTransform& tr = ob->getWorldTransform();
+		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(triangle[1]),color);
+		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(triangle[2]),color);
+		m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(triangle[0]),color);
+
+		//btVector3 center = triangle[0] + triangle[1]+triangle[2];
+		//center *= btScalar(0.333333);
+		//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[0]),tr(center),color);
+		//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[1]),tr(center),color);
+		//m_dispatchInfoPtr->m_debugDraw->drawLine(tr(triangle[2]),tr(center),color);
+
+	}
+
+
+	//btCollisionObject* colObj = static_cast<btCollisionObject*>(m_convexProxy->m_clientObject);
+	
+	if (m_convexBody->getCollisionShape()->isConvex())
+	{
+		btTriangleShape tm(triangle[0],triangle[1],triangle[2]);	
+		tm.setMargin(m_collisionMarginTriangle);
+		
+		btCollisionShape* tmpShape = ob->getCollisionShape();
+		ob->internalSetTemporaryCollisionShape( &tm );
+		
+		btCollisionAlgorithm* colAlgo = ci.m_dispatcher1->findAlgorithm(m_convexBody,m_triBody,m_manifoldPtr);
+
+		if (m_resultOut->getBody0Internal() == m_triBody)
+		{
+			m_resultOut->setShapeIdentifiersA(partId,triangleIndex);
+		}
+		else
+		{
+			m_resultOut->setShapeIdentifiersB(partId,triangleIndex);
+		}
+	
+		colAlgo->processCollision(m_convexBody,m_triBody,*m_dispatchInfoPtr,m_resultOut);
+		colAlgo->~btCollisionAlgorithm();
+		ci.m_dispatcher1->freeCollisionAlgorithm(colAlgo);
+		ob->internalSetTemporaryCollisionShape( tmpShape);
+	}
+
+
+}
+
+
+
+void	btConvexTriangleCallback::setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	m_dispatchInfoPtr = &dispatchInfo;
+	m_collisionMarginTriangle = collisionMarginTriangle;
+	m_resultOut = resultOut;
+
+	//recalc aabbs
+	btTransform convexInTriangleSpace;
+	convexInTriangleSpace = m_triBody->getWorldTransform().inverse() * m_convexBody->getWorldTransform();
+	btCollisionShape* convexShape = static_cast<btCollisionShape*>(m_convexBody->getCollisionShape());
+	//CollisionShape* triangleShape = static_cast<btCollisionShape*>(triBody->m_collisionShape);
+	convexShape->getAabb(convexInTriangleSpace,m_aabbMin,m_aabbMax);
+	btScalar extraMargin = collisionMarginTriangle;
+	btVector3 extra(extraMargin,extraMargin,extraMargin);
+
+	m_aabbMax += extra;
+	m_aabbMin -= extra;
+	
+}
+
+void btConvexConcaveCollisionAlgorithm::clearCache()
+{
+	m_btConvexTriangleCallback.clearCache();
+
+}
+
+void btConvexConcaveCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	
+	
+	btCollisionObject* convexBody = m_isSwapped ? body1 : body0;
+	btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+
+	if (triBody->getCollisionShape()->isConcave())
+	{
+
+
+		btCollisionObject*	triOb = triBody;
+		btConcaveShape* concaveShape = static_cast<btConcaveShape*>( triOb->getCollisionShape());
+		
+		if (convexBody->getCollisionShape()->isConvex())
+		{
+			btScalar collisionMarginTriangle = concaveShape->getMargin();
+					
+			resultOut->setPersistentManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+			m_btConvexTriangleCallback.setTimeStepAndCounters(collisionMarginTriangle,dispatchInfo,resultOut);
+
+			//Disable persistency. previously, some older algorithm calculated all contacts in one go, so you can clear it here.
+			//m_dispatcher->clearManifold(m_btConvexTriangleCallback.m_manifoldPtr);
+
+			m_btConvexTriangleCallback.m_manifoldPtr->setBodies(convexBody,triBody);
+
+			concaveShape->processAllTriangles( &m_btConvexTriangleCallback,m_btConvexTriangleCallback.getAabbMin(),m_btConvexTriangleCallback.getAabbMax());
+			
+			resultOut->refreshContactPoints();
+	
+		}
+	
+	}
+
+}
+
+
+btScalar btConvexConcaveCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	btCollisionObject* convexbody = m_isSwapped ? body1 : body0;
+	btCollisionObject* triBody = m_isSwapped ? body0 : body1;
+
+
+	//quick approximation using raycast, todo: hook up to the continuous collision detection (one of the btConvexCast)
+
+	//only perform CCD above a certain threshold, this prevents blocking on the long run
+	//because object in a blocked ccd state (hitfraction<1) get their linear velocity halved each frame...
+	btScalar squareMot0 = (convexbody->getInterpolationWorldTransform().getOrigin() - convexbody->getWorldTransform().getOrigin()).length2();
+	if (squareMot0 < convexbody->getCcdSquareMotionThreshold())
+	{
+		return btScalar(1.);
+	}
+
+	//const btVector3& from = convexbody->m_worldTransform.getOrigin();
+	//btVector3 to = convexbody->m_interpolationWorldTransform.getOrigin();
+	//todo: only do if the motion exceeds the 'radius'
+
+	btTransform triInv = triBody->getWorldTransform().inverse();
+	btTransform convexFromLocal = triInv * convexbody->getWorldTransform();
+	btTransform convexToLocal = triInv * convexbody->getInterpolationWorldTransform();
+
+	struct LocalTriangleSphereCastCallback	: public btTriangleCallback
+	{
+		btTransform m_ccdSphereFromTrans;
+		btTransform m_ccdSphereToTrans;
+		btTransform	m_meshTransform;
+
+		btScalar	m_ccdSphereRadius;
+		btScalar	m_hitFraction;
+	
+
+		LocalTriangleSphereCastCallback(const btTransform& from,const btTransform& to,btScalar ccdSphereRadius,btScalar hitFraction)
+			:m_ccdSphereFromTrans(from),
+			m_ccdSphereToTrans(to),
+			m_ccdSphereRadius(ccdSphereRadius),
+			m_hitFraction(hitFraction)
+		{			
+		}
+		
+		
+		virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+		{
+			(void)partId;
+			(void)triangleIndex;
+			//do a swept sphere for now
+			btTransform ident;
+			ident.setIdentity();
+			btConvexCast::CastResult castResult;
+			castResult.m_fraction = m_hitFraction;
+			btSphereShape	pointShape(m_ccdSphereRadius);
+			btTriangleShape	triShape(triangle[0],triangle[1],triangle[2]);
+			btVoronoiSimplexSolver	simplexSolver;
+			btSubsimplexConvexCast convexCaster(&pointShape,&triShape,&simplexSolver);
+			//GjkConvexCast	convexCaster(&pointShape,convexShape,&simplexSolver);
+			//ContinuousConvexCollision convexCaster(&pointShape,convexShape,&simplexSolver,0);
+			//local space?
+
+			if (convexCaster.calcTimeOfImpact(m_ccdSphereFromTrans,m_ccdSphereToTrans,
+				ident,ident,castResult))
+			{
+				if (m_hitFraction > castResult.m_fraction)
+					m_hitFraction = castResult.m_fraction;
+			}
+
+		}
+
+	};
+
+
+	
+
+	
+	if (triBody->getCollisionShape()->isConcave())
+	{
+		btVector3 rayAabbMin = convexFromLocal.getOrigin();
+		rayAabbMin.setMin(convexToLocal.getOrigin());
+		btVector3 rayAabbMax = convexFromLocal.getOrigin();
+		rayAabbMax.setMax(convexToLocal.getOrigin());
+		btScalar ccdRadius0 = convexbody->getCcdSweptSphereRadius();
+		rayAabbMin -= btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+		rayAabbMax += btVector3(ccdRadius0,ccdRadius0,ccdRadius0);
+
+		btScalar curHitFraction = btScalar(1.); //is this available?
+		LocalTriangleSphereCastCallback raycastCallback(convexFromLocal,convexToLocal,
+			convexbody->getCcdSweptSphereRadius(),curHitFraction);
+
+		raycastCallback.m_hitFraction = convexbody->getHitFraction();
+
+		btCollisionObject* concavebody = triBody;
+
+		btConcaveShape* triangleMesh = (btConcaveShape*) concavebody->getCollisionShape();
+		
+		if (triangleMesh)
+		{
+			triangleMesh->processAllTriangles(&raycastCallback,rayAabbMin,rayAabbMax);
+		}
+	
+
+
+		if (raycastCallback.m_hitFraction < convexbody->getHitFraction())
+		{
+			convexbody->setHitFraction( raycastCallback.m_hitFraction);
+			return raycastCallback.m_hitFraction;
+		}
+	}
+
+	return btScalar(1.);
+
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
new file mode 100644
index 0000000..984a4c3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h
@@ -0,0 +1,116 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+#define CONVEX_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "btCollisionCreateFunc.h"
+
+///For each triangle in the concave mesh that overlaps with the AABB of a convex (m_convexProxy), processTriangle is called.
+class btConvexTriangleCallback : public btTriangleCallback
+{
+	btCollisionObject* m_convexBody;
+	btCollisionObject* m_triBody;
+
+	btVector3	m_aabbMin;
+	btVector3	m_aabbMax ;
+
+
+	btManifoldResult* m_resultOut;
+	btDispatcher*	m_dispatcher;
+	const btDispatcherInfo* m_dispatchInfoPtr;
+	btScalar m_collisionMarginTriangle;
+	
+public:
+int	m_triangleCount;
+	
+	btPersistentManifold*	m_manifoldPtr;
+
+	btConvexTriangleCallback(btDispatcher* dispatcher,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+	void	setTimeStepAndCounters(btScalar collisionMarginTriangle,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual ~btConvexTriangleCallback();
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+	
+	void clearCache();
+
+	SIMD_FORCE_INLINE const btVector3& getAabbMin() const
+	{
+		return m_aabbMin;
+	}
+	SIMD_FORCE_INLINE const btVector3& getAabbMax() const
+	{
+		return m_aabbMax;
+	}
+
+};
+
+
+
+
+/// btConvexConcaveCollisionAlgorithm  supports collision between convex shapes and (concave) trianges meshes.
+class btConvexConcaveCollisionAlgorithm  : public btActivatingCollisionAlgorithm
+{
+
+	bool	m_isSwapped;
+
+	btConvexTriangleCallback m_btConvexTriangleCallback;
+
+
+
+public:
+
+	btConvexConcaveCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped);
+
+	virtual ~btConvexConcaveCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btScalar	calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray);
+	
+	void	clearCache();
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+			return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,false);
+		}
+	};
+
+	struct SwappedCreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConcaveCollisionAlgorithm));
+			return new(mem) btConvexConcaveCollisionAlgorithm(ci,body0,body1,true);
+		}
+	};
+
+};
+
+#endif //CONVEX_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
new file mode 100644
index 0000000..ede1afb
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.cpp
@@ -0,0 +1,580 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Specialized capsule-capsule collision algorithm has been added for Bullet 2.75 release to increase ragdoll performance
+///If you experience problems with capsule-capsule collision, try to define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER and report it in the Bullet forums
+///with reproduction case
+//define BT_DISABLE_CAPSULE_CAPSULE_COLLIDER 1
+
+#include "btConvexConvexAlgorithm.h"
+
+//#include <stdio.h>
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+
+
+
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+
+
+
+///////////
+
+
+
+static SIMD_FORCE_INLINE void segmentsClosestPoints(
+	btVector3& ptsVector,
+	btVector3& offsetA,
+	btVector3& offsetB,
+	btScalar& tA, btScalar& tB,
+	const btVector3& translation,
+	const btVector3& dirA, btScalar hlenA,
+	const btVector3& dirB, btScalar hlenB )
+{
+	// compute the parameters of the closest points on each line segment
+
+	btScalar dirA_dot_dirB = btDot(dirA,dirB);
+	btScalar dirA_dot_trans = btDot(dirA,translation);
+	btScalar dirB_dot_trans = btDot(dirB,translation);
+
+	btScalar denom = 1.0f - dirA_dot_dirB * dirA_dot_dirB;
+
+	if ( denom == 0.0f ) {
+		tA = 0.0f;
+	} else {
+		tA = ( dirA_dot_trans - dirB_dot_trans * dirA_dot_dirB ) / denom;
+		if ( tA < -hlenA )
+			tA = -hlenA;
+		else if ( tA > hlenA )
+			tA = hlenA;
+	}
+
+	tB = tA * dirA_dot_dirB - dirB_dot_trans;
+
+	if ( tB < -hlenB ) {
+		tB = -hlenB;
+		tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+		if ( tA < -hlenA )
+			tA = -hlenA;
+		else if ( tA > hlenA )
+			tA = hlenA;
+	} else if ( tB > hlenB ) {
+		tB = hlenB;
+		tA = tB * dirA_dot_dirB + dirA_dot_trans;
+
+		if ( tA < -hlenA )
+			tA = -hlenA;
+		else if ( tA > hlenA )
+			tA = hlenA;
+	}
+
+	// compute the closest points relative to segment centers.
+
+	offsetA = dirA * tA;
+	offsetB = dirB * tB;
+
+	ptsVector = translation - offsetA + offsetB;
+}
+
+
+static SIMD_FORCE_INLINE btScalar capsuleCapsuleDistance(
+	btVector3& normalOnB,
+	btVector3& pointOnB,
+	btScalar capsuleLengthA,
+	btScalar	capsuleRadiusA,
+	btScalar capsuleLengthB,
+	btScalar	capsuleRadiusB,
+	int capsuleAxisA,
+	int capsuleAxisB,
+	const btTransform& transformA,
+	const btTransform& transformB,
+	btScalar distanceThreshold )
+{
+	btVector3 directionA = transformA.getBasis().getColumn(capsuleAxisA);
+	btVector3 translationA = transformA.getOrigin();
+	btVector3 directionB = transformB.getBasis().getColumn(capsuleAxisB);
+	btVector3 translationB = transformB.getOrigin();
+
+	// translation between centers
+
+	btVector3 translation = translationB - translationA;
+
+	// compute the closest points of the capsule line segments
+
+	btVector3 ptsVector;           // the vector between the closest points
+	
+	btVector3 offsetA, offsetB;    // offsets from segment centers to their closest points
+	btScalar tA, tB;              // parameters on line segment
+
+	segmentsClosestPoints( ptsVector, offsetA, offsetB, tA, tB, translation,
+						   directionA, capsuleLengthA, directionB, capsuleLengthB );
+
+	btScalar distance = ptsVector.length() - capsuleRadiusA - capsuleRadiusB;
+
+	if ( distance > distanceThreshold )
+		return distance;
+
+	btScalar lenSqr = ptsVector.length2();
+	if (lenSqr<= (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		//degenerate case where 2 capsules are likely at the same location: take a vector tangential to 'directionA'
+		btVector3 q;
+		btPlaneSpace1(directionA,normalOnB,q);
+	} else
+	{
+		// compute the contact normal
+		normalOnB = ptsVector*-btRecipSqrt(lenSqr);
+	}
+	pointOnB = transformB.getOrigin()+offsetB + normalOnB * capsuleRadiusB;
+
+	return distance;
+}
+
+
+
+
+
+
+
+//////////
+
+
+
+
+
+btConvexConvexAlgorithm::CreateFunc::CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver)
+{
+	m_numPerturbationIterations = 0;
+	m_minimumPointsPerturbationThreshold = 3;
+	m_simplexSolver = simplexSolver;
+	m_pdSolver = pdSolver;
+}
+
+btConvexConvexAlgorithm::CreateFunc::~CreateFunc() 
+{ 
+}
+
+btConvexConvexAlgorithm::btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver,int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+: btActivatingCollisionAlgorithm(ci,body0,body1),
+m_simplexSolver(simplexSolver),
+m_pdSolver(pdSolver),
+m_ownManifold (false),
+m_manifoldPtr(mf),
+m_lowLevelOfDetail(false),
+#ifdef USE_SEPDISTANCE_UTIL2
+m_sepDistance((static_cast<btConvexShape*>(body0->getCollisionShape()))->getAngularMotionDisc(),
+			  (static_cast<btConvexShape*>(body1->getCollisionShape()))->getAngularMotionDisc()),
+#endif
+m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+	(void)body0;
+	(void)body1;
+}
+
+
+
+
+btConvexConvexAlgorithm::~btConvexConvexAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void	btConvexConvexAlgorithm ::setLowLevelOfDetail(bool useLowLevel)
+{
+	m_lowLevelOfDetail = useLowLevel;
+}
+
+
+struct btPerturbedContactResult : public btManifoldResult
+{
+	btManifoldResult* m_originalManifoldResult;
+	btTransform m_transformA;
+	btTransform m_transformB;
+	btTransform	m_unPerturbedTransform;
+	bool	m_perturbA;
+	btIDebugDraw*	m_debugDrawer;
+
+
+	btPerturbedContactResult(btManifoldResult* originalResult,const btTransform& transformA,const btTransform& transformB,const btTransform& unPerturbedTransform,bool perturbA,btIDebugDraw* debugDrawer)
+		:m_originalManifoldResult(originalResult),
+		m_transformA(transformA),
+		m_transformB(transformB),
+		m_unPerturbedTransform(unPerturbedTransform),
+		m_perturbA(perturbA),
+		m_debugDrawer(debugDrawer)
+	{
+	}
+	virtual ~ btPerturbedContactResult()
+	{
+	}
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar orgDepth)
+	{
+		btVector3 endPt,startPt;
+		btScalar newDepth;
+		btVector3 newNormal;
+
+		if (m_perturbA)
+		{
+			btVector3 endPtOrg = pointInWorld + normalOnBInWorld*orgDepth;
+			endPt = (m_unPerturbedTransform*m_transformA.inverse())(endPtOrg);
+			newDepth = (endPt -  pointInWorld).dot(normalOnBInWorld);
+			startPt = endPt+normalOnBInWorld*newDepth;
+		} else
+		{
+			endPt = pointInWorld + normalOnBInWorld*orgDepth;
+			startPt = (m_unPerturbedTransform*m_transformB.inverse())(pointInWorld);
+			newDepth = (endPt -  startPt).dot(normalOnBInWorld);
+			
+		}
+
+//#define DEBUG_CONTACTS 1
+#ifdef DEBUG_CONTACTS
+		m_debugDrawer->drawLine(startPt,endPt,btVector3(1,0,0));
+		m_debugDrawer->drawSphere(startPt,0.05,btVector3(0,1,0));
+		m_debugDrawer->drawSphere(endPt,0.05,btVector3(0,0,1));
+#endif //DEBUG_CONTACTS
+
+		
+		m_originalManifoldResult->addContactPoint(normalOnBInWorld,startPt,newDepth);
+	}
+
+};
+
+extern btScalar gContactBreakingThreshold;
+
+
+//
+// Convex-Convex collision algorithm
+//
+void btConvexConvexAlgorithm ::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+
+	if (!m_manifoldPtr)
+	{
+		//swapped?
+		m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+		m_ownManifold = true;
+	}
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	//comment-out next line to test multi-contact generation
+	//resultOut->getPersistentManifold()->clearManifold();
+	
+
+	btConvexShape* min0 = static_cast<btConvexShape*>(body0->getCollisionShape());
+	btConvexShape* min1 = static_cast<btConvexShape*>(body1->getCollisionShape());
+
+	btVector3  normalOnB;
+		btVector3  pointOnBWorld;
+#ifndef BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+	if ((min0->getShapeType() == CAPSULE_SHAPE_PROXYTYPE) && (min1->getShapeType() == CAPSULE_SHAPE_PROXYTYPE))
+	{
+		btCapsuleShape* capsuleA = (btCapsuleShape*) min0;
+		btCapsuleShape* capsuleB = (btCapsuleShape*) min1;
+		btVector3 localScalingA = capsuleA->getLocalScaling();
+		btVector3 localScalingB = capsuleB->getLocalScaling();
+		
+		btScalar threshold = m_manifoldPtr->getContactBreakingThreshold();
+
+		btScalar dist = capsuleCapsuleDistance(normalOnB,	pointOnBWorld,capsuleA->getHalfHeight(),capsuleA->getRadius(),
+			capsuleB->getHalfHeight(),capsuleB->getRadius(),capsuleA->getUpAxis(),capsuleB->getUpAxis(),
+			body0->getWorldTransform(),body1->getWorldTransform(),threshold);
+
+		if (dist<threshold)
+		{
+			btAssert(normalOnB.length2()>=(SIMD_EPSILON*SIMD_EPSILON));
+			resultOut->addContactPoint(normalOnB,pointOnBWorld,dist);	
+		}
+		resultOut->refreshContactPoints();
+		return;
+	}
+#endif //BT_DISABLE_CAPSULE_CAPSULE_COLLIDER
+
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+	{
+		m_sepDistance.updateSeparatingDistance(body0->getWorldTransform(),body1->getWorldTransform());
+	}
+
+	if (!dispatchInfo.m_useConvexConservativeDistanceUtil || m_sepDistance.getConservativeSeparatingDistance()<=0.f)
+#endif //USE_SEPDISTANCE_UTIL2
+
+	{
+
+	
+	btGjkPairDetector::ClosestPointInput input;
+
+	btGjkPairDetector	gjkPairDetector(min0,min1,m_simplexSolver,m_pdSolver);
+	//TODO: if (dispatchInfo.m_useContinuous)
+	gjkPairDetector.setMinkowskiA(min0);
+	gjkPairDetector.setMinkowskiB(min1);
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+	{
+		input.m_maximumDistanceSquared = BT_LARGE_FLOAT;
+	} else
+#endif //USE_SEPDISTANCE_UTIL2
+	{
+		if (dispatchInfo.m_convexMaxDistanceUseCPT)
+		{
+			input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactProcessingThreshold();
+		} else
+		{
+			input.m_maximumDistanceSquared = min0->getMargin() + min1->getMargin() + m_manifoldPtr->getContactBreakingThreshold();
+		}
+		input.m_maximumDistanceSquared*= input.m_maximumDistanceSquared;
+	}
+
+	input.m_stackAlloc = dispatchInfo.m_stackAllocator;
+	input.m_transformA = body0->getWorldTransform();
+	input.m_transformB = body1->getWorldTransform();
+
+	gjkPairDetector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw);
+
+	
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	btScalar sepDist = 0.f;
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil)
+	{
+		sepDist = gjkPairDetector.getCachedSeparatingDistance();
+		if (sepDist>SIMD_EPSILON)
+		{
+			sepDist += dispatchInfo.m_convexConservativeDistanceThreshold;
+			//now perturbe directions to get multiple contact points
+			
+		}
+	}
+#endif //USE_SEPDISTANCE_UTIL2
+
+	//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+	
+	//perform perturbation when more then 'm_minimumPointsPerturbationThreshold' points
+	if (m_numPerturbationIterations && resultOut->getPersistentManifold()->getNumContacts() < m_minimumPointsPerturbationThreshold)
+	{
+		
+		int i;
+		btVector3 v0,v1;
+		btVector3 sepNormalWorldSpace;
+	
+		sepNormalWorldSpace = gjkPairDetector.getCachedSeparatingAxis().normalized();
+		btPlaneSpace1(sepNormalWorldSpace,v0,v1);
+
+
+		bool perturbeA = true;
+		const btScalar angleLimit = 0.125f * SIMD_PI;
+		btScalar perturbeAngle;
+		btScalar radiusA = min0->getAngularMotionDisc();
+		btScalar radiusB = min1->getAngularMotionDisc();
+		if (radiusA < radiusB)
+		{
+			perturbeAngle = gContactBreakingThreshold /radiusA;
+			perturbeA = true;
+		} else
+		{
+			perturbeAngle = gContactBreakingThreshold / radiusB;
+			perturbeA = false;
+		}
+		if ( perturbeAngle > angleLimit ) 
+				perturbeAngle = angleLimit;
+
+		btTransform unPerturbedTransform;
+		if (perturbeA)
+		{
+			unPerturbedTransform = input.m_transformA;
+		} else
+		{
+			unPerturbedTransform = input.m_transformB;
+		}
+		
+		for ( i=0;i<m_numPerturbationIterations;i++)
+		{
+			if (v0.length2()>SIMD_EPSILON)
+			{
+			btQuaternion perturbeRot(v0,perturbeAngle);
+			btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
+			btQuaternion rotq(sepNormalWorldSpace,iterationAngle);
+			
+			
+			if (perturbeA)
+			{
+				input.m_transformA.setBasis(  btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body0->getWorldTransform().getBasis());
+				input.m_transformB = body1->getWorldTransform();
+#ifdef DEBUG_CONTACTS
+				dispatchInfo.m_debugDraw->drawTransform(input.m_transformA,10.0);
+#endif //DEBUG_CONTACTS
+			} else
+			{
+				input.m_transformA = body0->getWorldTransform();
+				input.m_transformB.setBasis( btMatrix3x3(rotq.inverse()*perturbeRot*rotq)*body1->getWorldTransform().getBasis());
+#ifdef DEBUG_CONTACTS
+				dispatchInfo.m_debugDraw->drawTransform(input.m_transformB,10.0);
+#endif
+			}
+			
+			btPerturbedContactResult perturbedResultOut(resultOut,input.m_transformA,input.m_transformB,unPerturbedTransform,perturbeA,dispatchInfo.m_debugDraw);
+			gjkPairDetector.getClosestPoints(input,perturbedResultOut,dispatchInfo.m_debugDraw);
+			}
+			
+		}
+	}
+
+	
+
+#ifdef USE_SEPDISTANCE_UTIL2
+	if (dispatchInfo.m_useConvexConservativeDistanceUtil && (sepDist>SIMD_EPSILON))
+	{
+		m_sepDistance.initSeparatingDistance(gjkPairDetector.getCachedSeparatingAxis(),sepDist,body0->getWorldTransform(),body1->getWorldTransform());
+	}
+#endif //USE_SEPDISTANCE_UTIL2
+
+
+	}
+
+	if (m_ownManifold)
+	{
+		resultOut->refreshContactPoints();
+	}
+
+}
+
+
+
+bool disableCcd = false;
+btScalar	btConvexConvexAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	///Rather then checking ALL pairs, only calculate TOI when motion exceeds threshold
+    
+	///Linear motion for one of objects needs to exceed m_ccdSquareMotionThreshold
+	///col0->m_worldTransform,
+	btScalar resultFraction = btScalar(1.);
+
+
+	btScalar squareMot0 = (col0->getInterpolationWorldTransform().getOrigin() - col0->getWorldTransform().getOrigin()).length2();
+	btScalar squareMot1 = (col1->getInterpolationWorldTransform().getOrigin() - col1->getWorldTransform().getOrigin()).length2();
+    
+	if (squareMot0 < col0->getCcdSquareMotionThreshold() &&
+		squareMot1 < col1->getCcdSquareMotionThreshold())
+		return resultFraction;
+
+	if (disableCcd)
+		return btScalar(1.);
+
+
+	//An adhoc way of testing the Continuous Collision Detection algorithms
+	//One object is approximated as a sphere, to simplify things
+	//Starting in penetration should report no time of impact
+	//For proper CCD, better accuracy and handling of 'allowed' penetration should be added
+	//also the mainloop of the physics should have a kind of toi queue (something like Brian Mirtich's application of Timewarp for Rigidbodies)
+
+		
+	/// Convex0 against sphere for Convex1
+	{
+		btConvexShape* convex0 = static_cast<btConvexShape*>(col0->getCollisionShape());
+
+		btSphereShape	sphere1(col1->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1( convex0 ,&sphere1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+		
+			//store result.m_fraction in both bodies
+		
+			if (col0->getHitFraction()> result.m_fraction)
+				col0->setHitFraction( result.m_fraction );
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+		
+		
+
+
+	}
+
+	/// Sphere (for convex0) against Convex1
+	{
+		btConvexShape* convex1 = static_cast<btConvexShape*>(col1->getCollisionShape());
+
+		btSphereShape	sphere0(col0->getCcdSweptSphereRadius()); //todo: allow non-zero sphere sizes, for better approximation
+		btConvexCast::CastResult result;
+		btVoronoiSimplexSolver voronoiSimplex;
+		//SubsimplexConvexCast ccd0(&sphere,min0,&voronoiSimplex);
+		///Simplification, one object is simplified as a sphere
+		btGjkConvexCast ccd1(&sphere0,convex1,&voronoiSimplex);
+		//ContinuousConvexCollision ccd(min0,min1,&voronoiSimplex,0);
+		if (ccd1.calcTimeOfImpact(col0->getWorldTransform(),col0->getInterpolationWorldTransform(),
+			col1->getWorldTransform(),col1->getInterpolationWorldTransform(),result))
+		{
+		
+			//store result.m_fraction in both bodies
+		
+			if (col0->getHitFraction()	> result.m_fraction)
+				col0->setHitFraction( result.m_fraction);
+
+			if (col1->getHitFraction() > result.m_fraction)
+				col1->setHitFraction( result.m_fraction);
+
+			if (resultFraction > result.m_fraction)
+				resultFraction = result.m_fraction;
+
+		}
+	}
+	
+	return resultFraction;
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
new file mode 100644
index 0000000..d38aff6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h
@@ -0,0 +1,109 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONVEX_CONVEX_ALGORITHM_H
+#define CONVEX_CONVEX_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+#include "LinearMath/btTransformUtil.h" //for btConvexSeparatingDistanceUtil
+
+class btConvexPenetrationDepthSolver;
+
+///Enabling USE_SEPDISTANCE_UTIL2 requires 100% reliable distance computation. However, when using large size ratios GJK can be imprecise
+///so the distance is not conservative. In that case, enabling this USE_SEPDISTANCE_UTIL2 would result in failing/missing collisions.
+///Either improve GJK for large size ratios (testing a 100 units versus a 0.1 unit object) or only enable the util
+///for certain pairs that have a small size ratio
+
+//#define USE_SEPDISTANCE_UTIL2 1
+
+///The convexConvexAlgorithm collision algorithm implements time of impact, convex closest points and penetration depth calculations between two convex objects.
+///Multiple contact points are calculated by perturbing the orientation of the smallest object orthogonal to the separating normal.
+///This idea was described by Gino van den Bergen in this forum topic http://www.bulletphysics.com/Bullet/phpBB3/viewtopic.php?f=4&t=288&p=888#p888
+class btConvexConvexAlgorithm : public btActivatingCollisionAlgorithm
+{
+#ifdef USE_SEPDISTANCE_UTIL2
+	btConvexSeparatingDistanceUtil	m_sepDistance;
+#endif
+	btSimplexSolverInterface*		m_simplexSolver;
+	btConvexPenetrationDepthSolver* m_pdSolver;
+
+	
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool			m_lowLevelOfDetail;
+	
+	int m_numPerturbationIterations;
+	int m_minimumPointsPerturbationThreshold;
+
+
+	///cache separating vector to speedup collision detection
+	
+
+public:
+
+	btConvexConvexAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1, btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* pdSolver, int numPerturbationIterations, int minimumPointsPerturbationThreshold);
+
+
+	virtual ~btConvexConvexAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		///should we use m_ownManifold to avoid adding duplicates?
+		if (m_manifoldPtr && m_ownManifold)
+			manifoldArray.push_back(m_manifoldPtr);
+	}
+
+
+	void	setLowLevelOfDetail(bool useLowLevel);
+
+
+	const btPersistentManifold*	getManifold()
+	{
+		return m_manifoldPtr;
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+
+		btConvexPenetrationDepthSolver*		m_pdSolver;
+		btSimplexSolverInterface*			m_simplexSolver;
+		int m_numPerturbationIterations;
+		int m_minimumPointsPerturbationThreshold;
+
+		CreateFunc(btSimplexSolverInterface*			simplexSolver, btConvexPenetrationDepthSolver* pdSolver);
+		
+		virtual ~CreateFunc();
+
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexConvexAlgorithm));
+			return new(mem) btConvexConvexAlgorithm(ci.m_manifold,ci,body0,body1,m_simplexSolver,m_pdSolver,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+		}
+	};
+
+
+};
+
+#endif //CONVEX_CONVEX_ALGORITHM_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
new file mode 100644
index 0000000..dda85dc
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp
@@ -0,0 +1,155 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexPlaneCollisionAlgorithm.h"
+
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+
+//#include <stdio.h>
+
+btConvexPlaneCollisionAlgorithm::btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold)
+: btCollisionAlgorithm(ci),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped),
+m_numPerturbationIterations(numPerturbationIterations),
+m_minimumPointsPerturbationThreshold(minimumPointsPerturbationThreshold)
+{
+	btCollisionObject* convexObj = m_isSwapped? col1 : col0;
+	btCollisionObject* planeObj = m_isSwapped? col0 : col1;
+
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(convexObj,planeObj))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(convexObj,planeObj);
+		m_ownManifold = true;
+	}
+}
+
+
+btConvexPlaneCollisionAlgorithm::~btConvexPlaneCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btConvexPlaneCollisionAlgorithm::collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+    btCollisionObject* convexObj = m_isSwapped? body1 : body0;
+	btCollisionObject* planeObj = m_isSwapped? body0: body1;
+
+	btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
+	btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+
+    bool hasCollision = false;
+	const btVector3& planeNormal = planeShape->getPlaneNormal();
+	const btScalar& planeConstant = planeShape->getPlaneConstant();
+	
+	btTransform convexWorldTransform = convexObj->getWorldTransform();
+	btTransform convexInPlaneTrans;
+	convexInPlaneTrans= planeObj->getWorldTransform().inverse() * convexWorldTransform;
+	//now perturbe the convex-world transform
+	convexWorldTransform.getBasis()*=btMatrix3x3(perturbeRot);
+	btTransform planeInConvex;
+	planeInConvex= convexWorldTransform.inverse() * planeObj->getWorldTransform();
+	
+	btVector3 vtx = convexShape->localGetSupportingVertex(planeInConvex.getBasis()*-planeNormal);
+
+	btVector3 vtxInPlane = convexInPlaneTrans(vtx);
+	btScalar distance = (planeNormal.dot(vtxInPlane) - planeConstant);
+
+	btVector3 vtxInPlaneProjected = vtxInPlane - distance*planeNormal;
+	btVector3 vtxInPlaneWorld = planeObj->getWorldTransform() * vtxInPlaneProjected;
+
+	hasCollision = distance < m_manifoldPtr->getContactBreakingThreshold();
+	resultOut->setPersistentManifold(m_manifoldPtr);
+	if (hasCollision)
+	{
+		/// report a contact. internally this will be kept persistent, and contact reduction is done
+		btVector3 normalOnSurfaceB = planeObj->getWorldTransform().getBasis() * planeNormal;
+		btVector3 pOnB = vtxInPlaneWorld;
+		resultOut->addContactPoint(normalOnSurfaceB,pOnB,distance);
+	}
+}
+
+
+void btConvexPlaneCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)dispatchInfo;
+	if (!m_manifoldPtr)
+		return;
+
+    btCollisionObject* convexObj = m_isSwapped? body1 : body0;
+	btCollisionObject* planeObj = m_isSwapped? body0: body1;
+
+	btConvexShape* convexShape = (btConvexShape*) convexObj->getCollisionShape();
+	btStaticPlaneShape* planeShape = (btStaticPlaneShape*) planeObj->getCollisionShape();
+
+    
+	const btVector3& planeNormal = planeShape->getPlaneNormal();
+	//const btScalar& planeConstant = planeShape->getPlaneConstant();
+
+	//first perform a collision query with the non-perturbated collision objects
+	{
+		btQuaternion rotq(0,0,0,1);
+		collideSingleContact(rotq,body0,body1,dispatchInfo,resultOut);
+	}
+
+	if (resultOut->getPersistentManifold()->getNumContacts()<m_minimumPointsPerturbationThreshold)
+	{
+		btVector3 v0,v1;
+		btPlaneSpace1(planeNormal,v0,v1);
+		//now perform 'm_numPerturbationIterations' collision queries with the perturbated collision objects
+
+		const btScalar angleLimit = 0.125f * SIMD_PI;
+		btScalar perturbeAngle;
+		btScalar radius = convexShape->getAngularMotionDisc();
+		perturbeAngle = gContactBreakingThreshold / radius;
+		if ( perturbeAngle > angleLimit ) 
+				perturbeAngle = angleLimit;
+
+		btQuaternion perturbeRot(v0,perturbeAngle);
+		for (int i=0;i<m_numPerturbationIterations;i++)
+		{
+			btScalar iterationAngle = i*(SIMD_2_PI/btScalar(m_numPerturbationIterations));
+			btQuaternion rotq(planeNormal,iterationAngle);
+			collideSingleContact(rotq.inverse()*perturbeRot*rotq,body0,body1,dispatchInfo,resultOut);
+		}
+	}
+
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr->getNumContacts())
+		{
+			resultOut->refreshContactPoints();
+		}
+	}
+}
+
+btScalar btConvexPlaneCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	(void)col0;
+	(void)col1;
+
+	//not yet
+	return btScalar(1.);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
new file mode 100644
index 0000000..f49ac45
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONVEX_PLANE_COLLISION_ALGORITHM_H
+#define CONVEX_PLANE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btConvexPlaneCollisionAlgorithm : public btCollisionAlgorithm
+{
+	bool		m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool		m_isSwapped;
+	int			m_numPerturbationIterations;
+	int			m_minimumPointsPerturbationThreshold;
+
+public:
+
+	btConvexPlaneCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped, int numPerturbationIterations,int minimumPointsPerturbationThreshold);
+
+	virtual ~btConvexPlaneCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	void collideSingleContact (const btQuaternion& perturbeRot, btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		int	m_numPerturbationIterations;
+		int m_minimumPointsPerturbationThreshold;
+			
+		CreateFunc() 
+			: m_numPerturbationIterations(1),
+			m_minimumPointsPerturbationThreshold(1)
+		{
+		}
+		
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btConvexPlaneCollisionAlgorithm));
+			if (!m_swapped)
+			{
+				return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,false,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+			} else
+			{
+				return new(mem) btConvexPlaneCollisionAlgorithm(0,ci,body0,body1,true,m_numPerturbationIterations,m_minimumPointsPerturbationThreshold);
+			}
+		}
+	};
+
+};
+
+#endif //CONVEX_PLANE_COLLISION_ALGORITHM_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
new file mode 100644
index 0000000..c27d8ce
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp
@@ -0,0 +1,298 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btDefaultCollisionConfiguration.h"
+
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexConcaveCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+#include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+
+
+
+#include "LinearMath/btStackAlloc.h"
+#include "LinearMath/btPoolAllocator.h"
+
+
+
+
+
+btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo)
+//btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(btStackAlloc*	stackAlloc,btPoolAllocator*	persistentManifoldPool,btPoolAllocator*	collisionAlgorithmPool)
+{
+
+	void* mem = btAlignedAlloc(sizeof(btVoronoiSimplexSolver),16);
+	m_simplexSolver = new (mem)btVoronoiSimplexSolver();
+
+	if (constructionInfo.m_useEpaPenetrationAlgorithm)
+	{
+		mem = btAlignedAlloc(sizeof(btGjkEpaPenetrationDepthSolver),16);
+		m_pdSolver = new (mem)btGjkEpaPenetrationDepthSolver;
+	}else
+	{
+		mem = btAlignedAlloc(sizeof(btMinkowskiPenetrationDepthSolver),16);
+		m_pdSolver = new (mem)btMinkowskiPenetrationDepthSolver;
+	}
+	
+	//default CreationFunctions, filling the m_doubleDispatch table
+	mem = btAlignedAlloc(sizeof(btConvexConvexAlgorithm::CreateFunc),16);
+	m_convexConvexCreateFunc = new(mem) btConvexConvexAlgorithm::CreateFunc(m_simplexSolver,m_pdSolver);
+	mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+	m_convexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btConvexConcaveCollisionAlgorithm::CreateFunc),16);
+	m_swappedConvexConcaveCreateFunc = new (mem)btConvexConcaveCollisionAlgorithm::SwappedCreateFunc;
+	mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::CreateFunc),16);
+	m_compoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btCompoundCollisionAlgorithm::SwappedCreateFunc),16);
+	m_swappedCompoundCreateFunc = new (mem)btCompoundCollisionAlgorithm::SwappedCreateFunc;
+	mem = btAlignedAlloc(sizeof(btEmptyAlgorithm::CreateFunc),16);
+	m_emptyCreateFunc = new(mem) btEmptyAlgorithm::CreateFunc;
+	
+	mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16);
+	m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+	m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16);
+	m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc;
+	m_boxSphereCF->m_swapped = true;
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+	mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+	m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16);
+	m_triangleSphereCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc;
+	m_triangleSphereCF->m_swapped = true;
+	
+	mem = btAlignedAlloc(sizeof(btBoxBoxCollisionAlgorithm::CreateFunc),16);
+	m_boxBoxCF = new(mem)btBoxBoxCollisionAlgorithm::CreateFunc;
+
+	//convex versus plane
+	mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+	m_convexPlaneCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+	mem = btAlignedAlloc (sizeof(btConvexPlaneCollisionAlgorithm::CreateFunc),16);
+	m_planeConvexCF = new (mem) btConvexPlaneCollisionAlgorithm::CreateFunc;
+	m_planeConvexCF->m_swapped = true;
+	
+	///calculate maximum element size, big enough to fit any collision algorithm in the memory pool
+	int maxSize = sizeof(btConvexConvexAlgorithm);
+	int maxSize2 = sizeof(btConvexConcaveCollisionAlgorithm);
+	int maxSize3 = sizeof(btCompoundCollisionAlgorithm);
+	int sl = sizeof(btConvexSeparatingDistanceUtil);
+	sl = sizeof(btGjkPairDetector);
+	int	collisionAlgorithmMaxElementSize = btMax(maxSize,constructionInfo.m_customCollisionAlgorithmMaxElementSize);
+	collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize2);
+	collisionAlgorithmMaxElementSize = btMax(collisionAlgorithmMaxElementSize,maxSize3);
+
+	if (constructionInfo.m_stackAlloc)
+	{
+		m_ownsStackAllocator = false;
+		this->m_stackAlloc = constructionInfo.m_stackAlloc;
+	} else
+	{
+		m_ownsStackAllocator = true;
+		void* mem = btAlignedAlloc(sizeof(btStackAlloc),16);
+		m_stackAlloc = new(mem)btStackAlloc(constructionInfo.m_defaultStackAllocatorSize);
+	}
+		
+	if (constructionInfo.m_persistentManifoldPool)
+	{
+		m_ownsPersistentManifoldPool = false;
+		m_persistentManifoldPool = constructionInfo.m_persistentManifoldPool;
+	} else
+	{
+		m_ownsPersistentManifoldPool = true;
+		void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+		m_persistentManifoldPool = new (mem) btPoolAllocator(sizeof(btPersistentManifold),constructionInfo.m_defaultMaxPersistentManifoldPoolSize);
+	}
+	
+	if (constructionInfo.m_collisionAlgorithmPool)
+	{
+		m_ownsCollisionAlgorithmPool = false;
+		m_collisionAlgorithmPool = constructionInfo.m_collisionAlgorithmPool;
+	} else
+	{
+		m_ownsCollisionAlgorithmPool = true;
+		void* mem = btAlignedAlloc(sizeof(btPoolAllocator),16);
+		m_collisionAlgorithmPool = new(mem) btPoolAllocator(collisionAlgorithmMaxElementSize,constructionInfo.m_defaultMaxCollisionAlgorithmPoolSize);
+	}
+
+
+}
+
+btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration()
+{
+	if (m_ownsStackAllocator)
+	{
+		m_stackAlloc->destroy();
+		m_stackAlloc->~btStackAlloc();
+		btAlignedFree(m_stackAlloc);
+	}
+	if (m_ownsCollisionAlgorithmPool)
+	{
+		m_collisionAlgorithmPool->~btPoolAllocator();
+		btAlignedFree(m_collisionAlgorithmPool);
+	}
+	if (m_ownsPersistentManifoldPool)
+	{
+		m_persistentManifoldPool->~btPoolAllocator();
+		btAlignedFree(m_persistentManifoldPool);
+	}
+
+	m_convexConvexCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree(	m_convexConvexCreateFunc);
+
+	m_convexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_convexConcaveCreateFunc);
+	m_swappedConvexConcaveCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_swappedConvexConcaveCreateFunc);
+
+	m_compoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_compoundCreateFunc);
+
+	m_swappedCompoundCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_swappedCompoundCreateFunc);
+
+	m_emptyCreateFunc->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_emptyCreateFunc);
+
+	m_sphereSphereCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_sphereSphereCF);
+
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	m_sphereBoxCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_sphereBoxCF);
+	m_boxSphereCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_boxSphereCF);
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+	m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_sphereTriangleCF);
+	m_triangleSphereCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_triangleSphereCF);
+	m_boxBoxCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_boxBoxCF);
+
+	m_convexPlaneCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_convexPlaneCF);
+	m_planeConvexCF->~btCollisionAlgorithmCreateFunc();
+	btAlignedFree( m_planeConvexCF);
+
+	m_simplexSolver->~btVoronoiSimplexSolver();
+	btAlignedFree(m_simplexSolver);
+
+	m_pdSolver->~btConvexPenetrationDepthSolver();
+	
+	btAlignedFree(m_pdSolver);
+
+
+}
+
+
+btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1)
+{
+
+
+
+	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+	{
+		return	m_sphereSphereCF;
+	}
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE))
+	{
+		return	m_sphereBoxCF;
+	}
+
+	if ((proxyType0 == BOX_SHAPE_PROXYTYPE ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+	{
+		return	m_boxSphereCF;
+	}
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+
+	if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE))
+	{
+		return	m_sphereTriangleCF;
+	}
+
+	if ((proxyType0 == TRIANGLE_SHAPE_PROXYTYPE  ) && (proxyType1==SPHERE_SHAPE_PROXYTYPE))
+	{
+		return	m_triangleSphereCF;
+	} 
+
+	if ((proxyType0 == BOX_SHAPE_PROXYTYPE) && (proxyType1 == BOX_SHAPE_PROXYTYPE))
+	{
+		return m_boxBoxCF;
+	}
+	
+	if (btBroadphaseProxy::isConvex(proxyType0) && (proxyType1 == STATIC_PLANE_PROXYTYPE))
+	{
+		return m_convexPlaneCF;
+	}
+
+	if (btBroadphaseProxy::isConvex(proxyType1) && (proxyType0 == STATIC_PLANE_PROXYTYPE))
+	{
+		return m_planeConvexCF;
+	}
+	
+
+
+	if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConvex(proxyType1))
+	{
+		return m_convexConvexCreateFunc;
+	}
+
+	if (btBroadphaseProxy::isConvex(proxyType0) && btBroadphaseProxy::isConcave(proxyType1))
+	{
+		return m_convexConcaveCreateFunc;
+	}
+
+	if (btBroadphaseProxy::isConvex(proxyType1) && btBroadphaseProxy::isConcave(proxyType0))
+	{
+		return m_swappedConvexConcaveCreateFunc;
+	}
+
+	if (btBroadphaseProxy::isCompound(proxyType0))
+	{
+		return m_compoundCreateFunc;
+	} else
+	{
+		if (btBroadphaseProxy::isCompound(proxyType1))
+		{
+			return m_swappedCompoundCreateFunc;
+		}
+	}
+
+	//failed to find an algorithm
+	return m_emptyCreateFunc;
+}
+
+void btDefaultCollisionConfiguration::setConvexConvexMultipointIterations(int numPerturbationIterations, int minimumPointsPerturbationThreshold)
+{
+	btConvexConvexAlgorithm::CreateFunc* convexConvex = (btConvexConvexAlgorithm::CreateFunc*) m_convexConvexCreateFunc;
+	convexConvex->m_numPerturbationIterations = numPerturbationIterations;
+	convexConvex->m_minimumPointsPerturbationThreshold = minimumPointsPerturbationThreshold;
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
new file mode 100644
index 0000000..6aa0d8c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h
@@ -0,0 +1,135 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_DEFAULT_COLLISION_CONFIGURATION
+#define BT_DEFAULT_COLLISION_CONFIGURATION
+
+#include "btCollisionConfiguration.h"
+class btVoronoiSimplexSolver;
+class btConvexPenetrationDepthSolver;
+
+struct	btDefaultCollisionConstructionInfo
+{
+	btStackAlloc*		m_stackAlloc;
+	btPoolAllocator*	m_persistentManifoldPool;
+	btPoolAllocator*	m_collisionAlgorithmPool;
+	int					m_defaultMaxPersistentManifoldPoolSize;
+	int					m_defaultMaxCollisionAlgorithmPoolSize;
+	int					m_customCollisionAlgorithmMaxElementSize;
+	int					m_defaultStackAllocatorSize;
+	int					m_useEpaPenetrationAlgorithm;
+
+	btDefaultCollisionConstructionInfo()
+		:m_stackAlloc(0),
+		m_persistentManifoldPool(0),
+		m_collisionAlgorithmPool(0),
+		m_defaultMaxPersistentManifoldPoolSize(4096),
+		m_defaultMaxCollisionAlgorithmPoolSize(4096),
+		m_customCollisionAlgorithmMaxElementSize(0),
+		m_defaultStackAllocatorSize(0),
+		m_useEpaPenetrationAlgorithm(true)
+	{
+	}
+};
+
+
+
+///btCollisionConfiguration allows to configure Bullet collision detection
+///stack allocator, pool memory allocators
+///@todo: describe the meaning
+class	btDefaultCollisionConfiguration : public btCollisionConfiguration
+{
+
+protected:
+
+	int	m_persistentManifoldPoolSize;
+	
+	btStackAlloc*	m_stackAlloc;
+	bool	m_ownsStackAllocator;
+
+	btPoolAllocator*	m_persistentManifoldPool;
+	bool	m_ownsPersistentManifoldPool;
+
+
+	btPoolAllocator*	m_collisionAlgorithmPool;
+	bool	m_ownsCollisionAlgorithmPool;
+
+	//default simplex/penetration depth solvers
+	btVoronoiSimplexSolver*	m_simplexSolver;
+	btConvexPenetrationDepthSolver*	m_pdSolver;
+	
+	//default CreationFunctions, filling the m_doubleDispatch table
+	btCollisionAlgorithmCreateFunc*	m_convexConvexCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_convexConcaveCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_swappedConvexConcaveCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_compoundCreateFunc;
+	btCollisionAlgorithmCreateFunc*	m_swappedCompoundCreateFunc;
+	btCollisionAlgorithmCreateFunc* m_emptyCreateFunc;
+	btCollisionAlgorithmCreateFunc* m_sphereSphereCF;
+#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM
+	btCollisionAlgorithmCreateFunc* m_sphereBoxCF;
+	btCollisionAlgorithmCreateFunc* m_boxSphereCF;
+#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM
+
+	btCollisionAlgorithmCreateFunc* m_boxBoxCF;
+	btCollisionAlgorithmCreateFunc*	m_sphereTriangleCF;
+	btCollisionAlgorithmCreateFunc*	m_triangleSphereCF;
+	btCollisionAlgorithmCreateFunc*	m_planeConvexCF;
+	btCollisionAlgorithmCreateFunc*	m_convexPlaneCF;
+	
+public:
+
+
+	btDefaultCollisionConfiguration(const btDefaultCollisionConstructionInfo& constructionInfo = btDefaultCollisionConstructionInfo());
+
+	virtual ~btDefaultCollisionConfiguration();
+
+		///memory pools
+	virtual btPoolAllocator* getPersistentManifoldPool()
+	{
+		return m_persistentManifoldPool;
+	}
+
+	virtual btPoolAllocator* getCollisionAlgorithmPool()
+	{
+		return m_collisionAlgorithmPool;
+	}
+
+	virtual btStackAlloc*	getStackAllocator()
+	{
+		return m_stackAlloc;
+	}
+
+	virtual	btVoronoiSimplexSolver*	getSimplexSolver()
+	{
+		return m_simplexSolver;
+	}
+
+
+	virtual btCollisionAlgorithmCreateFunc* getCollisionAlgorithmCreateFunc(int proxyType0,int proxyType1);
+
+	///Use this method to allow to generate multiple contact points between at once, between two objects using the generic convex-convex algorithm.
+	///By default, this feature is disabled for best performance.
+	///@param numPerturbationIterations controls the number of collision queries. Set it to zero to disable the feature.
+	///@param minimumPointsPerturbationThreshold is the minimum number of points in the contact cache, above which the feature is disabled
+	///3 is a good value for both params, if you want to enable the feature. This is because the default contact cache contains a maximum of 4 points, and one collision query at the unperturbed orientation is performed first.
+	///See Bullet/Demos/CollisionDemo for an example how this feature gathers multiple points.
+	///@todo we could add a per-object setting of those parameters, for level-of-detail collision detection.
+	void	setConvexConvexMultipointIterations(int numPerturbationIterations=3, int minimumPointsPerturbationThreshold = 3);
+
+};
+
+#endif //BT_DEFAULT_COLLISION_CONFIGURATION
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
new file mode 100644
index 0000000..9360543
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.cpp
@@ -0,0 +1,34 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btEmptyCollisionAlgorithm.h"
+
+
+
+btEmptyAlgorithm::btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+	: btCollisionAlgorithm(ci)
+{
+}
+
+void btEmptyAlgorithm::processCollision (btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
+{
+}
+
+btScalar btEmptyAlgorithm::calculateTimeOfImpact(btCollisionObject* ,btCollisionObject* ,const btDispatcherInfo& ,btManifoldResult* )
+{
+	return btScalar(1.);
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
new file mode 100644
index 0000000..e54721d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btEmptyCollisionAlgorithm.h
@@ -0,0 +1,54 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef EMPTY_ALGORITH
+#define EMPTY_ALGORITH
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+#define ATTRIBUTE_ALIGNED(a)
+
+///EmptyAlgorithm is a stub for unsupported collision pairs.
+///The dispatcher can dispatch a persistent btEmptyAlgorithm to avoid a search every frame.
+class btEmptyAlgorithm : public btCollisionAlgorithm
+{
+
+public:
+	
+	btEmptyAlgorithm(const btCollisionAlgorithmConstructionInfo& ci);
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+	}
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			(void)body0;
+			(void)body1;
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btEmptyAlgorithm));
+			return new(mem) btEmptyAlgorithm(ci);
+		}
+	};
+
+} ATTRIBUTE_ALIGNED(16);
+
+#endif //EMPTY_ALGORITH
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
new file mode 100644
index 0000000..86141fa
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.cpp
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGhostObject.h"
+#include "btCollisionWorld.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+btGhostObject::btGhostObject()
+{
+	m_internalType = CO_GHOST_OBJECT;
+}
+
+btGhostObject::~btGhostObject()
+{
+	///btGhostObject should have been removed from the world, so no overlapping objects
+	btAssert(!m_overlappingObjects.size());
+}
+
+
+void btGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+{
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btAssert(otherObject);
+	///if this linearSearch becomes too slow (too many overlapping objects) we should add a more appropriate data structure
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index==m_overlappingObjects.size())
+	{
+		//not found
+		m_overlappingObjects.push_back(otherObject);
+	}
+}
+
+void btGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy)
+{
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btAssert(otherObject);
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index<m_overlappingObjects.size())
+	{
+		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+		m_overlappingObjects.pop_back();
+	}
+}
+
+
+btPairCachingGhostObject::btPairCachingGhostObject()
+{
+	m_hashPairCache = new (btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache();
+}
+
+btPairCachingGhostObject::~btPairCachingGhostObject()
+{
+	m_hashPairCache->~btHashedOverlappingPairCache();
+	btAlignedFree( m_hashPairCache );
+}
+
+void btPairCachingGhostObject::addOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btBroadphaseProxy* thisProxy)
+{
+	btBroadphaseProxy*actualThisProxy = thisProxy ? thisProxy : getBroadphaseHandle();
+	btAssert(actualThisProxy);
+
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btAssert(otherObject);
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index==m_overlappingObjects.size())
+	{
+		m_overlappingObjects.push_back(otherObject);
+		m_hashPairCache->addOverlappingPair(actualThisProxy,otherProxy);
+	}
+}
+
+void btPairCachingGhostObject::removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy1)
+{
+	btCollisionObject* otherObject = (btCollisionObject*)otherProxy->m_clientObject;
+	btBroadphaseProxy* actualThisProxy = thisProxy1 ? thisProxy1 : getBroadphaseHandle();
+	btAssert(actualThisProxy);
+
+	btAssert(otherObject);
+	int index = m_overlappingObjects.findLinearSearch(otherObject);
+	if (index<m_overlappingObjects.size())
+	{
+		m_overlappingObjects[index] = m_overlappingObjects[m_overlappingObjects.size()-1];
+		m_overlappingObjects.pop_back();
+		m_hashPairCache->removeOverlappingPair(actualThisProxy,otherProxy,dispatcher);
+	}
+}
+
+
+void	btGhostObject::convexSweepTest(const btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration) const
+{
+	btTransform	convexFromTrans,convexToTrans;
+	convexFromTrans = convexFromWorld;
+	convexToTrans = convexToWorld;
+	btVector3 castShapeAabbMin, castShapeAabbMax;
+	/* Compute AABB that encompasses angular movement */
+	{
+		btVector3 linVel, angVel;
+		btTransformUtil::calculateVelocity (convexFromTrans, convexToTrans, 1.0, linVel, angVel);
+		btTransform R;
+		R.setIdentity ();
+		R.setRotation (convexFromTrans.getRotation());
+		castShape->calculateTemporalAabb (R, linVel, angVel, 1.0, castShapeAabbMin, castShapeAabbMax);
+	}
+
+	/// go over all objects, and if the ray intersects their aabb + cast shape aabb,
+	// do a ray-shape query using convexCaster (CCD)
+	int i;
+	for (i=0;i<m_overlappingObjects.size();i++)
+	{
+		btCollisionObject*	collisionObject= m_overlappingObjects[i];
+		//only perform raycast if filterMask matches
+		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) {
+			//RigidcollisionObject* collisionObject = ctrl->GetRigidcollisionObject();
+			btVector3 collisionObjectAabbMin,collisionObjectAabbMax;
+			collisionObject->getCollisionShape()->getAabb(collisionObject->getWorldTransform(),collisionObjectAabbMin,collisionObjectAabbMax);
+			AabbExpand (collisionObjectAabbMin, collisionObjectAabbMax, castShapeAabbMin, castShapeAabbMax);
+			btScalar hitLambda = btScalar(1.); //could use resultCallback.m_closestHitFraction, but needs testing
+			btVector3 hitNormal;
+			if (btRayAabb(convexFromWorld.getOrigin(),convexToWorld.getOrigin(),collisionObjectAabbMin,collisionObjectAabbMax,hitLambda,hitNormal))
+			{
+				btCollisionWorld::objectQuerySingle(castShape, convexFromTrans,convexToTrans,
+					collisionObject,
+						collisionObject->getCollisionShape(),
+						collisionObject->getWorldTransform(),
+						resultCallback,
+						allowedCcdPenetration);
+			}
+		}
+	}
+
+}
+
+void	btGhostObject::rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const
+{
+	btTransform rayFromTrans;
+	rayFromTrans.setIdentity();
+	rayFromTrans.setOrigin(rayFromWorld);
+	btTransform  rayToTrans;
+	rayToTrans.setIdentity();
+	rayToTrans.setOrigin(rayToWorld);
+
+
+	int i;
+	for (i=0;i<m_overlappingObjects.size();i++)
+	{
+		btCollisionObject*	collisionObject= m_overlappingObjects[i];
+		//only perform raycast if filterMask matches
+		if(resultCallback.needsCollision(collisionObject->getBroadphaseHandle())) 
+		{
+			btCollisionWorld::rayTestSingle(rayFromTrans,rayToTrans,
+							collisionObject,
+								collisionObject->getCollisionShape(),
+								collisionObject->getWorldTransform(),
+								resultCallback);
+		}
+	}
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
new file mode 100644
index 0000000..8ec8613
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btGhostObject.h
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://bulletphysics.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_GHOST_OBJECT_H
+#define BT_GHOST_OBJECT_H
+
+
+#include "btCollisionObject.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCallback.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "BulletCollision/BroadphaseCollision/btOverlappingPairCache.h"
+#include "btCollisionWorld.h"
+
+class btConvexShape;
+
+class btDispatcher;
+
+///The btGhostObject can keep track of all objects that are overlapping
+///By default, this overlap is based on the AABB
+///This is useful for creating a character controller, collision sensors/triggers, explosions etc.
+///We plan on adding rayTest and other queries for the btGhostObject
+ATTRIBUTE_ALIGNED16(class) btGhostObject : public btCollisionObject
+{
+protected:
+
+	btAlignedObjectArray<btCollisionObject*> m_overlappingObjects;
+
+public:
+
+	btGhostObject();
+
+	virtual ~btGhostObject();
+
+	void	convexSweepTest(const class btConvexShape* castShape, const btTransform& convexFromWorld, const btTransform& convexToWorld, btCollisionWorld::ConvexResultCallback& resultCallback, btScalar allowedCcdPenetration = 0.f) const;
+
+	void	rayTest(const btVector3& rayFromWorld, const btVector3& rayToWorld, btCollisionWorld::RayResultCallback& resultCallback) const; 
+
+	///this method is mainly for expert/internal use only.
+	virtual void	addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+	///this method is mainly for expert/internal use only.
+	virtual void	removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+
+	int	getNumOverlappingObjects() const
+	{
+		return m_overlappingObjects.size();
+	}
+
+	btCollisionObject*	getOverlappingObject(int index)
+	{
+		return m_overlappingObjects[index];
+	}
+
+	const btCollisionObject*	getOverlappingObject(int index) const
+	{
+		return m_overlappingObjects[index];
+	}
+
+	btAlignedObjectArray<btCollisionObject*>&	getOverlappingPairs()
+	{
+		return m_overlappingObjects;
+	}
+
+	const btAlignedObjectArray<btCollisionObject*>	getOverlappingPairs() const
+	{
+		return m_overlappingObjects;
+	}
+
+	//
+	// internal cast
+	//
+
+	static const btGhostObject*	upcast(const btCollisionObject* colObj)
+	{
+		if (colObj->getInternalType()==CO_GHOST_OBJECT)
+			return (const btGhostObject*)colObj;
+		return 0;
+	}
+	static btGhostObject*			upcast(btCollisionObject* colObj)
+	{
+		if (colObj->getInternalType()==CO_GHOST_OBJECT)
+			return (btGhostObject*)colObj;
+		return 0;
+	}
+
+};
+
+class	btPairCachingGhostObject : public btGhostObject
+{
+	btHashedOverlappingPairCache*	m_hashPairCache;
+
+public:
+
+	btPairCachingGhostObject();
+
+	virtual ~btPairCachingGhostObject();
+
+	///this method is mainly for expert/internal use only.
+	virtual void	addOverlappingObjectInternal(btBroadphaseProxy* otherProxy, btBroadphaseProxy* thisProxy=0);
+
+	virtual void	removeOverlappingObjectInternal(btBroadphaseProxy* otherProxy,btDispatcher* dispatcher,btBroadphaseProxy* thisProxy=0);
+
+	btHashedOverlappingPairCache*	getOverlappingPairCache()
+	{
+		return m_hashPairCache;
+	}
+
+};
+
+
+
+///The btGhostPairCallback interfaces and forwards adding and removal of overlapping pairs from the btBroadphaseInterface to btGhostObject.
+class btGhostPairCallback : public btOverlappingPairCallback
+{
+	
+public:
+	btGhostPairCallback()
+	{
+	}
+
+	virtual ~btGhostPairCallback()
+	{
+		
+	}
+
+	virtual btBroadphasePair*	addOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1)
+	{
+		btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
+		btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
+		btGhostObject* ghost0 = 		btGhostObject::upcast(colObj0);
+		btGhostObject* ghost1 = 		btGhostObject::upcast(colObj1);
+		if (ghost0)
+			ghost0->addOverlappingObjectInternal(proxy1, proxy0);
+		if (ghost1)
+			ghost1->addOverlappingObjectInternal(proxy0, proxy1);
+		return 0;
+	}
+
+	virtual void*	removeOverlappingPair(btBroadphaseProxy* proxy0,btBroadphaseProxy* proxy1,btDispatcher* dispatcher)
+	{
+		btCollisionObject* colObj0 = (btCollisionObject*) proxy0->m_clientObject;
+		btCollisionObject* colObj1 = (btCollisionObject*) proxy1->m_clientObject;
+		btGhostObject* ghost0 = 		btGhostObject::upcast(colObj0);
+		btGhostObject* ghost1 = 		btGhostObject::upcast(colObj1);
+		if (ghost0)
+			ghost0->removeOverlappingObjectInternal(proxy1,dispatcher,proxy0);
+		if (ghost1)
+			ghost1->removeOverlappingObjectInternal(proxy0,dispatcher,proxy1);
+		return 0;
+	}
+
+	virtual void	removeOverlappingPairsContainingProxy(btBroadphaseProxy* /*proxy0*/,btDispatcher* /*dispatcher*/)
+	{
+		btAssert(0);
+		//need to keep track of all ghost objects and call them here
+		//m_hashPairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
+	}
+
+	
+
+};
+
+#endif
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
new file mode 100644
index 0000000..5cceb04
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.cpp
@@ -0,0 +1,772 @@
+#include "btInternalEdgeUtility.h"
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/NarrowPhaseCollision/btManifoldPoint.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+//#define DEBUG_INTERNAL_EDGE
+
+
+#ifdef DEBUG_INTERNAL_EDGE
+#include <stdio.h>
+#endif //DEBUG_INTERNAL_EDGE
+
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+static btIDebugDraw* gDebugDrawer = 0;
+
+void	btSetDebugDrawer(btIDebugDraw* debugDrawer)
+{
+	gDebugDrawer = debugDrawer;
+}
+
+static void    btDebugDrawLine(const btVector3& from,const btVector3& to, const btVector3& color)
+{
+	if (gDebugDrawer)
+		gDebugDrawer->drawLine(from,to,color);
+}
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+static int	btGetHash(int partId, int triangleIndex)
+{
+	int hash = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+	return hash;
+}
+
+
+
+static btScalar btGetAngle(const btVector3& edgeA, const btVector3& normalA,const btVector3& normalB)
+{
+	const btVector3 refAxis0  = edgeA;
+	const btVector3 refAxis1  = normalA;
+	const btVector3 swingAxis = normalB;
+	btScalar angle = btAtan2(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1));
+	return  angle;
+}
+
+
+struct btConnectivityProcessor : public btTriangleCallback
+{
+	int				m_partIdA;
+	int				m_triangleIndexA;
+	btVector3*		m_triangleVerticesA;
+	btTriangleInfoMap*	m_triangleInfoMap;
+
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+	{
+		//skip self-collisions
+		if ((m_partIdA == partId) && (m_triangleIndexA == triangleIndex))
+			return;
+
+		//skip duplicates (disabled for now)
+		//if ((m_partIdA <= partId) && (m_triangleIndexA <= triangleIndex))
+		//	return;
+
+		//search for shared vertices and edges
+		int numshared = 0;
+		int sharedVertsA[3]={-1,-1,-1};
+		int sharedVertsB[3]={-1,-1,-1};
+
+		///skip degenerate triangles
+		btScalar crossBSqr = ((triangle[1]-triangle[0]).cross(triangle[2]-triangle[0])).length2();
+		if (crossBSqr < m_triangleInfoMap->m_equalVertexThreshold)
+			return;
+
+
+		btScalar crossASqr = ((m_triangleVerticesA[1]-m_triangleVerticesA[0]).cross(m_triangleVerticesA[2]-m_triangleVerticesA[0])).length2();
+		///skip degenerate triangles
+		if (crossASqr< m_triangleInfoMap->m_equalVertexThreshold)
+			return;
+
+#if 0
+		printf("triangle A[0]	=	(%f,%f,%f)\ntriangle A[1]	=	(%f,%f,%f)\ntriangle A[2]	=	(%f,%f,%f)\n",
+			m_triangleVerticesA[0].getX(),m_triangleVerticesA[0].getY(),m_triangleVerticesA[0].getZ(),
+			m_triangleVerticesA[1].getX(),m_triangleVerticesA[1].getY(),m_triangleVerticesA[1].getZ(),
+			m_triangleVerticesA[2].getX(),m_triangleVerticesA[2].getY(),m_triangleVerticesA[2].getZ());
+
+		printf("partId=%d, triangleIndex=%d\n",partId,triangleIndex);
+		printf("triangle B[0]	=	(%f,%f,%f)\ntriangle B[1]	=	(%f,%f,%f)\ntriangle B[2]	=	(%f,%f,%f)\n",
+			triangle[0].getX(),triangle[0].getY(),triangle[0].getZ(),
+			triangle[1].getX(),triangle[1].getY(),triangle[1].getZ(),
+			triangle[2].getX(),triangle[2].getY(),triangle[2].getZ());
+#endif
+
+		for (int i=0;i<3;i++)
+		{
+			for (int j=0;j<3;j++)
+			{
+				if ( (m_triangleVerticesA[i]-triangle[j]).length2() < m_triangleInfoMap->m_equalVertexThreshold)
+				{
+					sharedVertsA[numshared] = i;
+					sharedVertsB[numshared] = j;
+					numshared++;
+					///degenerate case
+					if(numshared >= 3)
+						return;
+				}
+			}
+			///degenerate case
+			if(numshared >= 3)
+				return;
+		}
+		switch (numshared)
+		{
+		case 0:
+			{
+				break;
+			}
+		case 1:
+			{
+				//shared vertex
+				break;
+			}
+		case 2:
+			{
+				//shared edge
+				//we need to make sure the edge is in the order V2V0 and not V0V2 so that the signs are correct
+				if (sharedVertsA[0] == 0 && sharedVertsA[1] == 2)
+				{
+					sharedVertsA[0] = 2;
+					sharedVertsA[1] = 0;
+					int tmp = sharedVertsB[1];
+					sharedVertsB[1] = sharedVertsB[0];
+					sharedVertsB[0] = tmp;
+				}
+
+				int hash = btGetHash(m_partIdA,m_triangleIndexA);
+
+				btTriangleInfo* info = m_triangleInfoMap->find(hash);
+				if (!info)
+				{
+					btTriangleInfo tmp;
+					m_triangleInfoMap->insert(hash,tmp);
+					info = m_triangleInfoMap->find(hash);
+				}
+
+				int sumvertsA = sharedVertsA[0]+sharedVertsA[1];
+				int otherIndexA = 3-sumvertsA;
+
+				
+				btVector3 edge(m_triangleVerticesA[sharedVertsA[1]]-m_triangleVerticesA[sharedVertsA[0]]);
+
+				btTriangleShape tA(m_triangleVerticesA[0],m_triangleVerticesA[1],m_triangleVerticesA[2]);
+				int otherIndexB = 3-(sharedVertsB[0]+sharedVertsB[1]);
+
+				btTriangleShape tB(triangle[sharedVertsB[1]],triangle[sharedVertsB[0]],triangle[otherIndexB]);
+				//btTriangleShape tB(triangle[0],triangle[1],triangle[2]);
+
+				btVector3 normalA;
+				btVector3 normalB;
+				tA.calcNormal(normalA);
+				tB.calcNormal(normalB);
+				edge.normalize();
+				btVector3 edgeCrossA = edge.cross(normalA).normalize();
+
+				{
+					btVector3 tmp = m_triangleVerticesA[otherIndexA]-m_triangleVerticesA[sharedVertsA[0]];
+					if (edgeCrossA.dot(tmp) < 0)
+					{
+						edgeCrossA*=-1;
+					}
+				}
+
+				btVector3 edgeCrossB = edge.cross(normalB).normalize();
+
+				{
+					btVector3 tmp = triangle[otherIndexB]-triangle[sharedVertsB[0]];
+					if (edgeCrossB.dot(tmp) < 0)
+					{
+						edgeCrossB*=-1;
+					}
+				}
+
+				btScalar	angle2 = 0;
+				btScalar	ang4 = 0.f;
+
+
+				btVector3 calculatedEdge = edgeCrossA.cross(edgeCrossB);
+				btScalar len2 = calculatedEdge.length2();
+
+				btScalar correctedAngle(0);
+				btVector3 calculatedNormalB = normalA;
+				bool isConvex = false;
+
+				if (len2<m_triangleInfoMap->m_planarEpsilon)
+				{
+					angle2 = 0.f;
+					ang4 = 0.f;
+				} else
+				{
+
+					calculatedEdge.normalize();
+					btVector3 calculatedNormalA = calculatedEdge.cross(edgeCrossA);
+					calculatedNormalA.normalize();
+					angle2 = btGetAngle(calculatedNormalA,edgeCrossA,edgeCrossB);
+					ang4 = SIMD_PI-angle2;
+					btScalar dotA = normalA.dot(edgeCrossB);
+					///@todo: check if we need some epsilon, due to floating point imprecision
+					isConvex = (dotA<0.);
+
+					correctedAngle = isConvex ? ang4 : -ang4;
+					btQuaternion orn2(calculatedEdge,-correctedAngle);
+					calculatedNormalB = btMatrix3x3(orn2)*normalA;
+
+
+				}
+
+				
+
+				
+							
+				//alternatively use 
+				//btVector3 calculatedNormalB2 = quatRotate(orn,normalA);
+
+
+				switch (sumvertsA)
+				{
+				case 1:
+					{
+						btVector3 edge = m_triangleVerticesA[0]-m_triangleVerticesA[1];
+						btQuaternion orn(edge,-correctedAngle);
+						btVector3 computedNormalB = quatRotate(orn,normalA);
+						btScalar bla = computedNormalB.dot(normalB);
+						if (bla<0)
+						{
+							computedNormalB*=-1;
+							info->m_flags |= TRI_INFO_V0V1_SWAP_NORMALB;
+						}
+#ifdef DEBUG_INTERNAL_EDGE
+						if ((computedNormalB-normalB).length()>0.0001)
+						{
+							printf("warning: normals not identical\n");
+						}
+#endif//DEBUG_INTERNAL_EDGE
+
+						info->m_edgeV0V1Angle = -correctedAngle;
+
+						if (isConvex)
+							info->m_flags |= TRI_INFO_V0V1_CONVEX;
+						break;
+					}
+				case 2:
+					{
+						btVector3 edge = m_triangleVerticesA[2]-m_triangleVerticesA[0];
+						btQuaternion orn(edge,-correctedAngle);
+						btVector3 computedNormalB = quatRotate(orn,normalA);
+						if (computedNormalB.dot(normalB)<0)
+						{
+							computedNormalB*=-1;
+							info->m_flags |= TRI_INFO_V2V0_SWAP_NORMALB;
+						}
+
+#ifdef DEBUG_INTERNAL_EDGE
+						if ((computedNormalB-normalB).length()>0.0001)
+						{
+							printf("warning: normals not identical\n");
+						}
+#endif //DEBUG_INTERNAL_EDGE
+						info->m_edgeV2V0Angle = -correctedAngle;
+						if (isConvex)
+							info->m_flags |= TRI_INFO_V2V0_CONVEX;
+						break;	
+					}
+				case 3:
+					{
+						btVector3 edge = m_triangleVerticesA[1]-m_triangleVerticesA[2];
+						btQuaternion orn(edge,-correctedAngle);
+						btVector3 computedNormalB = quatRotate(orn,normalA);
+						if (computedNormalB.dot(normalB)<0)
+						{
+							info->m_flags |= TRI_INFO_V1V2_SWAP_NORMALB;
+							computedNormalB*=-1;
+						}
+#ifdef DEBUG_INTERNAL_EDGE
+						if ((computedNormalB-normalB).length()>0.0001)
+						{
+							printf("warning: normals not identical\n");
+						}
+#endif //DEBUG_INTERNAL_EDGE
+						info->m_edgeV1V2Angle = -correctedAngle;
+
+						if (isConvex)
+							info->m_flags |= TRI_INFO_V1V2_CONVEX;
+						break;
+					}
+				}
+
+				break;
+			}
+		default:
+			{
+				//				printf("warning: duplicate triangle\n");
+			}
+
+		}
+	}
+};
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+
+void btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap)
+{
+	//the user pointer shouldn't already be used for other purposes, we intend to store connectivity info there!
+	if (trimeshShape->getTriangleInfoMap())
+		return;
+
+	trimeshShape->setTriangleInfoMap(triangleInfoMap);
+
+	btStridingMeshInterface* meshInterface = trimeshShape->getMeshInterface();
+	const btVector3& meshScaling = meshInterface->getScaling();
+
+	for (int partId = 0; partId< meshInterface->getNumSubParts();partId++)
+	{
+		const unsigned char *vertexbase = 0;
+		int numverts = 0;
+		PHY_ScalarType type = PHY_INTEGER;
+		int stride = 0;
+		const unsigned char *indexbase = 0;
+		int indexstride = 0;
+		int numfaces = 0;
+		PHY_ScalarType indicestype = PHY_INTEGER;
+		//PHY_ScalarType indexType=0;
+
+		btVector3 triangleVerts[3];
+		meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,	type,stride,&indexbase,indexstride,numfaces,indicestype,partId);
+		btVector3 aabbMin,aabbMax;
+
+		for (int triangleIndex = 0 ; triangleIndex < numfaces;triangleIndex++)
+		{
+			unsigned int* gfxbase = (unsigned int*)(indexbase+triangleIndex*indexstride);
+
+			for (int j=2;j>=0;j--)
+			{
+
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+					triangleVerts[j] = btVector3(
+						graphicsbase[0]*meshScaling.getX(),
+						graphicsbase[1]*meshScaling.getY(),
+						graphicsbase[2]*meshScaling.getZ());
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+					triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
+				}
+			}
+			aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+			aabbMin.setMin(triangleVerts[0]);
+			aabbMax.setMax(triangleVerts[0]);
+			aabbMin.setMin(triangleVerts[1]);
+			aabbMax.setMax(triangleVerts[1]);
+			aabbMin.setMin(triangleVerts[2]);
+			aabbMax.setMax(triangleVerts[2]);
+
+			btConnectivityProcessor connectivityProcessor;
+			connectivityProcessor.m_partIdA = partId;
+			connectivityProcessor.m_triangleIndexA = triangleIndex;
+			connectivityProcessor.m_triangleVerticesA = &triangleVerts[0];
+			connectivityProcessor.m_triangleInfoMap  = triangleInfoMap;
+
+			trimeshShape->processAllTriangles(&connectivityProcessor,aabbMin,aabbMax);
+		}
+
+	}
+
+}
+
+
+
+
+// Given a point and a line segment (defined by two points), compute the closest point
+// in the line.  Cap the point at the endpoints of the line segment.
+void btNearestPointInLineSegment(const btVector3 &point, const btVector3& line0, const btVector3& line1, btVector3& nearestPoint)
+{
+	btVector3 lineDelta     = line1 - line0;
+
+	// Handle degenerate lines
+	if ( lineDelta.fuzzyZero())
+	{
+		nearestPoint = line0;
+	}
+	else
+	{
+		btScalar delta = (point-line0).dot(lineDelta) / (lineDelta).dot(lineDelta);
+
+		// Clamp the point to conform to the segment's endpoints
+		if ( delta < 0 )
+			delta = 0;
+		else if ( delta > 1 )
+			delta = 1;
+
+		nearestPoint = line0 + lineDelta*delta;
+	}
+}
+
+
+
+
+bool	btClampNormal(const btVector3& edge,const btVector3& tri_normal_org,const btVector3& localContactNormalOnB, btScalar correctedEdgeAngle, btVector3 & clampedLocalNormal)
+{
+	btVector3 tri_normal = tri_normal_org;
+	//we only have a local triangle normal, not a local contact normal -> only normal in world space...
+	//either compute the current angle all in local space, or all in world space
+
+	btVector3 edgeCross = edge.cross(tri_normal).normalize();
+	btScalar curAngle = btGetAngle(edgeCross,tri_normal,localContactNormalOnB);
+
+	if (correctedEdgeAngle<0)
+	{
+		if (curAngle < correctedEdgeAngle)
+		{
+			btScalar diffAngle = correctedEdgeAngle-curAngle;
+			btQuaternion rotation(edge,diffAngle );
+			clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+			return true;
+		}
+	}
+
+	if (correctedEdgeAngle>=0)
+	{
+		if (curAngle > correctedEdgeAngle)
+		{
+			btScalar diffAngle = correctedEdgeAngle-curAngle;
+			btQuaternion rotation(edge,diffAngle );
+			clampedLocalNormal = btMatrix3x3(rotation)*localContactNormalOnB;
+			return true;
+		}
+	}
+	return false;
+}
+
+
+
+/// Changes a btManifoldPoint collision normal to the normal from the mesh.
+void btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* colObj0,const btCollisionObject* colObj1, int partId0, int index0, int normalAdjustFlags)
+{
+	//btAssert(colObj0->getCollisionShape()->getShapeType() == TRIANGLE_SHAPE_PROXYTYPE);
+	if (colObj0->getCollisionShape()->getShapeType() != TRIANGLE_SHAPE_PROXYTYPE)
+		return;
+
+	btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)colObj0->getRootCollisionShape();
+	btTriangleInfoMap* triangleInfoMapPtr = (btTriangleInfoMap*) trimesh->getTriangleInfoMap();
+	if (!triangleInfoMapPtr)
+		return;
+
+	int hash = btGetHash(partId0,index0);
+
+
+	btTriangleInfo* info = triangleInfoMapPtr->find(hash);
+	if (!info)
+		return;
+
+	btScalar frontFacing = (normalAdjustFlags & BT_TRIANGLE_CONVEX_BACKFACE_MODE)==0? 1.f : -1.f;
+	
+	const btTriangleShape* tri_shape = static_cast<const btTriangleShape*>(colObj0->getCollisionShape());
+	btVector3 v0,v1,v2;
+	tri_shape->getVertex(0,v0);
+	tri_shape->getVertex(1,v1);
+	tri_shape->getVertex(2,v2);
+
+	btVector3 center = (v0+v1+v2)*btScalar(1./3.);
+
+	btVector3 red(1,0,0), green(0,1,0),blue(0,0,1),white(1,1,1),black(0,0,0);
+	btVector3 tri_normal;
+	tri_shape->calcNormal(tri_normal);
+
+	//btScalar dot = tri_normal.dot(cp.m_normalWorldOnB);
+	btVector3 nearest;
+	btNearestPointInLineSegment(cp.m_localPointB,v0,v1,nearest);
+
+	btVector3 contact = cp.m_localPointB;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+	const btTransform& tr = colObj0->getWorldTransform();
+	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,red);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+
+	bool isNearEdge = false;
+
+	int numConcaveEdgeHits = 0;
+	int numConvexEdgeHits = 0;
+
+	btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+	localContactNormalOnB.normalize();//is this necessary?
+
+	if ((info->m_edgeV0V1Angle)< SIMD_2_PI)
+	{
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif
+		btScalar len = (contact-nearest).length();
+		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+		{
+			btVector3 edge(v0-v1);
+			isNearEdge = true;
+
+			if (info->m_edgeV0V1Angle==btScalar(0))
+			{
+				numConcaveEdgeHits++;
+			} else
+			{
+
+				bool isEdgeConvex = (info->m_flags & TRI_INFO_V0V1_CONVEX);
+				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+				btVector3 nA = swapFactor * tri_normal;
+
+				btQuaternion orn(edge,info->m_edgeV0V1Angle);
+				btVector3 computedNormalB = quatRotate(orn,tri_normal);
+				if (info->m_flags & TRI_INFO_V0V1_SWAP_NORMALB)
+					computedNormalB*=-1;
+				btVector3 nB = swapFactor*computedNormalB;
+
+				btScalar	NdotA = localContactNormalOnB.dot(nA);
+				btScalar	NdotB = localContactNormalOnB.dot(nB);
+				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+#ifdef DEBUG_INTERNAL_EDGE
+				{
+					
+					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+				}
+#endif //DEBUG_INTERNAL_EDGE
+
+
+				if (backFacingNormal)
+				{
+					numConcaveEdgeHits++;
+				}
+				else
+				{
+					numConvexEdgeHits++;
+					btVector3 clampedLocalNormal;
+					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV0V1Angle,clampedLocalNormal);
+					if (isClamped)
+					{
+						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+						{
+							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+							cp.m_normalWorldOnB = newNormal;
+							// Reproject collision point along normal. (what about cp.m_distance1?)
+							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+							
+						}
+					}
+				}
+			}
+		}
+	}
+
+	btNearestPointInLineSegment(contact,v1,v2,nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,green);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+	if ((info->m_edgeV1V2Angle)< SIMD_2_PI)
+	{
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+
+		btScalar len = (contact-nearest).length();
+		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+		{
+			isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+			btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+			btVector3 edge(v1-v2);
+
+			isNearEdge = true;
+
+			if (info->m_edgeV1V2Angle == btScalar(0))
+			{
+				numConcaveEdgeHits++;
+			} else
+			{
+				bool isEdgeConvex = (info->m_flags & TRI_INFO_V1V2_CONVEX)!=0;
+				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+				btVector3 nA = swapFactor * tri_normal;
+				
+				btQuaternion orn(edge,info->m_edgeV1V2Angle);
+				btVector3 computedNormalB = quatRotate(orn,tri_normal);
+				if (info->m_flags & TRI_INFO_V1V2_SWAP_NORMALB)
+					computedNormalB*=-1;
+				btVector3 nB = swapFactor*computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+				{
+					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+				}
+#endif //DEBUG_INTERNAL_EDGE
+
+
+				btScalar	NdotA = localContactNormalOnB.dot(nA);
+				btScalar	NdotB = localContactNormalOnB.dot(nB);
+				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+				if (backFacingNormal)
+				{
+					numConcaveEdgeHits++;
+				}
+				else
+				{
+					numConvexEdgeHits++;
+					btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+					btVector3 clampedLocalNormal;
+					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB, info->m_edgeV1V2Angle,clampedLocalNormal);
+					if (isClamped)
+					{
+						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+						{
+							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+							cp.m_normalWorldOnB = newNormal;
+							// Reproject collision point along normal.
+							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+						}
+					}
+				}
+			}
+		}
+	}
+
+	btNearestPointInLineSegment(contact,v2,v0,nearest);
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+	btDebugDrawLine(tr*nearest,tr*cp.m_localPointB,blue);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+	if ((info->m_edgeV2V0Angle)< SIMD_2_PI)
+	{
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+		btDebugDrawLine(tr*contact,tr*(contact+cp.m_normalWorldOnB*10),black);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+		btScalar len = (contact-nearest).length();
+		if(len<triangleInfoMapPtr->m_edgeDistanceThreshold)
+		{
+			isNearEdge = true;
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+			btDebugDrawLine(tr*nearest,tr*(nearest+tri_normal*10),white);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+			btVector3 edge(v2-v0);
+
+			if (info->m_edgeV2V0Angle==btScalar(0))
+			{
+				numConcaveEdgeHits++;
+			} else
+			{
+
+				bool isEdgeConvex = (info->m_flags & TRI_INFO_V2V0_CONVEX)!=0;
+				btScalar swapFactor = isEdgeConvex ? btScalar(1) : btScalar(-1);
+	#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+				btDebugDrawLine(tr*nearest,tr*(nearest+swapFactor*tri_normal*10),white);
+	#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+				btVector3 nA = swapFactor * tri_normal;
+				btQuaternion orn(edge,info->m_edgeV2V0Angle);
+				btVector3 computedNormalB = quatRotate(orn,tri_normal);
+				if (info->m_flags & TRI_INFO_V2V0_SWAP_NORMALB)
+					computedNormalB*=-1;
+				btVector3 nB = swapFactor*computedNormalB;
+
+#ifdef DEBUG_INTERNAL_EDGE
+				{
+					btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+tr.getBasis()*(nB*20),red);
+				}
+#endif //DEBUG_INTERNAL_EDGE
+
+				btScalar	NdotA = localContactNormalOnB.dot(nA);
+				btScalar	NdotB = localContactNormalOnB.dot(nB);
+				bool backFacingNormal = (NdotA< triangleInfoMapPtr->m_convexEpsilon) && (NdotB<triangleInfoMapPtr->m_convexEpsilon);
+
+				if (backFacingNormal)
+				{
+					numConcaveEdgeHits++;
+				}
+				else
+				{
+					numConvexEdgeHits++;
+					//				printf("hitting convex edge\n");
+
+
+					btVector3 localContactNormalOnB = colObj0->getWorldTransform().getBasis().transpose() * cp.m_normalWorldOnB;
+					btVector3 clampedLocalNormal;
+					bool isClamped = btClampNormal(edge,swapFactor*tri_normal,localContactNormalOnB,info->m_edgeV2V0Angle,clampedLocalNormal);
+					if (isClamped)
+					{
+						if (((normalAdjustFlags & BT_TRIANGLE_CONVEX_DOUBLE_SIDED)!=0) || (clampedLocalNormal.dot(frontFacing*tri_normal)>0))
+						{
+							btVector3 newNormal = colObj0->getWorldTransform().getBasis() * clampedLocalNormal;
+							//					cp.m_distance1 = cp.m_distance1 * newNormal.dot(cp.m_normalWorldOnB);
+							cp.m_normalWorldOnB = newNormal;
+							// Reproject collision point along normal.
+							cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+							cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+						}
+					}
+				} 
+			}
+			
+
+		}
+	}
+
+#ifdef DEBUG_INTERNAL_EDGE
+	{
+		btVector3 color(0,1,1);
+		btDebugDrawLine(cp.getPositionWorldOnB(),cp.getPositionWorldOnB()+cp.m_normalWorldOnB*10,color);
+	}
+#endif //DEBUG_INTERNAL_EDGE
+
+	if (isNearEdge)
+	{
+
+		if (numConcaveEdgeHits>0)
+		{
+			if ((normalAdjustFlags & BT_TRIANGLE_CONCAVE_DOUBLE_SIDED)!=0)
+			{
+				//fix tri_normal so it pointing the same direction as the current local contact normal
+				if (tri_normal.dot(localContactNormalOnB) < 0)
+				{
+					tri_normal *= -1;
+				}
+				cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis()*tri_normal;
+			} else
+			{
+				//modify the normal to be the triangle normal (or backfacing normal)
+				cp.m_normalWorldOnB = colObj0->getWorldTransform().getBasis() *(tri_normal *frontFacing);
+			}
+			
+			
+			// Reproject collision point along normal.
+			cp.m_positionWorldOnB = cp.m_positionWorldOnA - cp.m_normalWorldOnB * cp.m_distance1;
+			cp.m_localPointB = colObj0->getWorldTransform().invXform(cp.m_positionWorldOnB);
+		}
+	}
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
new file mode 100644
index 0000000..9efb012
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btInternalEdgeUtility.h
@@ -0,0 +1,46 @@
+
+#ifndef BT_INTERNAL_EDGE_UTILITY_H
+#define BT_INTERNAL_EDGE_UTILITY_H
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btVector3.h"
+
+#include "BulletCollision/CollisionShapes/btTriangleInfoMap.h"
+
+///The btInternalEdgeUtility helps to avoid or reduce artifacts due to wrong collision normals caused by internal edges.
+///See also http://code.google.com/p/bullet/issues/detail?id=27
+
+class btBvhTriangleMeshShape;
+class btCollisionObject;
+class btManifoldPoint;
+class btIDebugDraw;
+
+
+
+enum btInternalEdgeAdjustFlags
+{
+	BT_TRIANGLE_CONVEX_BACKFACE_MODE = 1,
+	BT_TRIANGLE_CONCAVE_DOUBLE_SIDED = 2, //double sided options are experimental, single sided is recommended
+	BT_TRIANGLE_CONVEX_DOUBLE_SIDED = 4
+};
+
+
+///Call btGenerateInternalEdgeInfo to create triangle info, store in the shape 'userInfo'
+void	btGenerateInternalEdgeInfo (btBvhTriangleMeshShape*trimeshShape, btTriangleInfoMap* triangleInfoMap);
+
+
+///Call the btFixMeshNormal to adjust the collision normal, using the triangle info map (generated using btGenerateInternalEdgeInfo)
+///If this info map is missing, or the triangle is not store in this map, nothing will be done
+void	btAdjustInternalEdgeContacts(btManifoldPoint& cp, const btCollisionObject* trimeshColObj0,const btCollisionObject* otherColObj1, int partId0, int index0, int normalAdjustFlags = 0);
+
+///Enable the BT_INTERNAL_EDGE_DEBUG_DRAW define and call btSetDebugDrawer, to get visual info to see if the internal edge utility works properly.
+///If the utility doesn't work properly, you might have to adjust the threshold values in btTriangleInfoMap
+//#define BT_INTERNAL_EDGE_DEBUG_DRAW
+
+#ifdef BT_INTERNAL_EDGE_DEBUG_DRAW
+void	btSetDebugDrawer(btIDebugDraw* debugDrawer);
+#endif //BT_INTERNAL_EDGE_DEBUG_DRAW
+
+
+#endif //BT_INTERNAL_EDGE_UTILITY_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
new file mode 100644
index 0000000..e607bdb
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.cpp
@@ -0,0 +1,134 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btManifoldResult.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+
+///This is to allow MaterialCombiner/Custom Friction/Restitution values
+ContactAddedCallback		gContactAddedCallback=0;
+
+///User can override this material combiner by implementing gContactAddedCallback and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback;
+inline btScalar	calculateCombinedFriction(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+	btScalar friction = body0->getFriction() * body1->getFriction();
+
+	const btScalar MAX_FRICTION  = btScalar(10.);
+	if (friction < -MAX_FRICTION)
+		friction = -MAX_FRICTION;
+	if (friction > MAX_FRICTION)
+		friction = MAX_FRICTION;
+	return friction;
+
+}
+
+inline btScalar	calculateCombinedRestitution(const btCollisionObject* body0,const btCollisionObject* body1)
+{
+	return body0->getRestitution() * body1->getRestitution();
+}
+
+
+
+btManifoldResult::btManifoldResult(btCollisionObject* body0,btCollisionObject* body1)
+		:m_manifoldPtr(0),
+		m_body0(body0),
+		m_body1(body1)
+#ifdef DEBUG_PART_INDEX
+		,m_partId0(-1),
+	m_partId1(-1),
+	m_index0(-1),
+	m_index1(-1)
+#endif //DEBUG_PART_INDEX
+{
+	m_rootTransA = body0->getWorldTransform();
+	m_rootTransB = body1->getWorldTransform();
+}
+
+
+void btManifoldResult::addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+{
+	btAssert(m_manifoldPtr);
+	//order in manifold needs to match
+	
+	if (depth > m_manifoldPtr->getContactBreakingThreshold())
+		return;
+
+	bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+
+	btVector3 pointA = pointInWorld + normalOnBInWorld * depth;
+
+	btVector3 localA;
+	btVector3 localB;
+	
+	if (isSwapped)
+	{
+		localA = m_rootTransB.invXform(pointA );
+		localB = m_rootTransA.invXform(pointInWorld);
+	} else
+	{
+		localA = m_rootTransA.invXform(pointA );
+		localB = m_rootTransB.invXform(pointInWorld);
+	}
+
+	btManifoldPoint newPt(localA,localB,normalOnBInWorld,depth);
+	newPt.m_positionWorldOnA = pointA;
+	newPt.m_positionWorldOnB = pointInWorld;
+	
+	int insertIndex = m_manifoldPtr->getCacheEntry(newPt);
+
+	newPt.m_combinedFriction = calculateCombinedFriction(m_body0,m_body1);
+	newPt.m_combinedRestitution = calculateCombinedRestitution(m_body0,m_body1);
+
+   //BP mod, store contact triangles.
+	if (isSwapped)
+	{
+		newPt.m_partId0 = m_partId1;
+		newPt.m_partId1 = m_partId0;
+		newPt.m_index0  = m_index1;
+		newPt.m_index1  = m_index0;
+	} else
+	{
+		newPt.m_partId0 = m_partId0;
+		newPt.m_partId1 = m_partId1;
+		newPt.m_index0  = m_index0;
+		newPt.m_index1  = m_index1;
+	}
+	//printf("depth=%f\n",depth);
+	///@todo, check this for any side effects
+	if (insertIndex >= 0)
+	{
+		//const btManifoldPoint& oldPoint = m_manifoldPtr->getContactPoint(insertIndex);
+		m_manifoldPtr->replaceContactPoint(newPt,insertIndex);
+	} else
+	{
+		insertIndex = m_manifoldPtr->addManifoldPoint(newPt);
+	}
+	
+	//User can override friction and/or restitution
+	if (gContactAddedCallback &&
+		//and if either of the two bodies requires custom material
+		 ((m_body0->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK) ||
+		   (m_body1->getCollisionFlags() & btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK)))
+	{
+		//experimental feature info, for per-triangle material etc.
+		btCollisionObject* obj0 = isSwapped? m_body1 : m_body0;
+		btCollisionObject* obj1 = isSwapped? m_body0 : m_body1;
+		(*gContactAddedCallback)(m_manifoldPtr->getContactPoint(insertIndex),obj0,newPt.m_partId0,newPt.m_index0,obj1,newPt.m_partId1,newPt.m_index1);
+	}
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
new file mode 100644
index 0000000..927e2bc
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btManifoldResult.h
@@ -0,0 +1,128 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef MANIFOLD_RESULT_H
+#define MANIFOLD_RESULT_H
+
+class btCollisionObject;
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btManifoldPoint;
+
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+
+#include "LinearMath/btTransform.h"
+
+typedef bool (*ContactAddedCallback)(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1);
+extern ContactAddedCallback		gContactAddedCallback;
+
+//#define DEBUG_PART_INDEX 1
+
+
+///btManifoldResult is a helper class to manage  contact results.
+class btManifoldResult : public btDiscreteCollisionDetectorInterface::Result
+{
+protected:
+
+	btPersistentManifold* m_manifoldPtr;
+
+	//we need this for compounds
+	btTransform	m_rootTransA;
+	btTransform	m_rootTransB;
+
+	btCollisionObject* m_body0;
+	btCollisionObject* m_body1;
+	int	m_partId0;
+	int m_partId1;
+	int m_index0;
+	int m_index1;
+	
+
+public:
+
+	btManifoldResult()
+#ifdef DEBUG_PART_INDEX
+		:
+	m_partId0(-1),
+	m_partId1(-1),
+	m_index0(-1),
+	m_index1(-1)
+#endif //DEBUG_PART_INDEX
+	{
+	}
+
+	btManifoldResult(btCollisionObject* body0,btCollisionObject* body1);
+
+	virtual ~btManifoldResult() {};
+
+	void	setPersistentManifold(btPersistentManifold* manifoldPtr)
+	{
+		m_manifoldPtr = manifoldPtr;
+	}
+
+	const btPersistentManifold*	getPersistentManifold() const
+	{
+		return m_manifoldPtr;
+	}
+	btPersistentManifold*	getPersistentManifold()
+	{
+		return m_manifoldPtr;
+	}
+
+	virtual void setShapeIdentifiersA(int partId0,int index0)
+	{
+		m_partId0=partId0;
+		m_index0=index0;
+	}
+
+	virtual void setShapeIdentifiersB(	int partId1,int index1)
+	{
+		m_partId1=partId1;
+		m_index1=index1;
+	}
+
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth);
+
+	SIMD_FORCE_INLINE	void refreshContactPoints()
+	{
+		btAssert(m_manifoldPtr);
+		if (!m_manifoldPtr->getNumContacts())
+			return;
+
+		bool isSwapped = m_manifoldPtr->getBody0() != m_body0;
+
+		if (isSwapped)
+		{
+			m_manifoldPtr->refreshContactPoints(m_rootTransB,m_rootTransA);
+		} else
+		{
+			m_manifoldPtr->refreshContactPoints(m_rootTransA,m_rootTransB);
+		}
+	}
+
+	const btCollisionObject* getBody0Internal() const
+	{
+		return m_body0;
+	}
+
+	const btCollisionObject* getBody1Internal() const
+	{
+		return m_body1;
+	}
+	
+};
+
+#endif //MANIFOLD_RESULT_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
new file mode 100644
index 0000000..44e7628
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp
@@ -0,0 +1,443 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "LinearMath/btScalar.h"
+#include "btSimulationIslandManager.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+
+//#include <stdio.h>
+#include "LinearMath/btQuickprof.h"
+
+btSimulationIslandManager::btSimulationIslandManager():
+m_splitIslands(true)
+{
+}
+
+btSimulationIslandManager::~btSimulationIslandManager()
+{
+}
+
+
+void btSimulationIslandManager::initUnionFind(int n)
+{
+		m_unionFind.reset(n);
+}
+		
+
+void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btCollisionWorld* colWorld)
+{
+	
+	{
+		btOverlappingPairCache* pairCachePtr = colWorld->getPairCache();
+		const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs();
+		btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr();
+		
+		for (int i=0;i<numOverlappingPairs;i++)
+		{
+			const btBroadphasePair& collisionPair = pairPtr[i];
+			btCollisionObject* colObj0 = (btCollisionObject*)collisionPair.m_pProxy0->m_clientObject;
+			btCollisionObject* colObj1 = (btCollisionObject*)collisionPair.m_pProxy1->m_clientObject;
+
+			if (((colObj0) && ((colObj0)->mergesSimulationIslands())) &&
+				((colObj1) && ((colObj1)->mergesSimulationIslands())))
+			{
+
+				m_unionFind.unite((colObj0)->getIslandTag(),
+					(colObj1)->getIslandTag());
+			}
+		}
+	}
+}
+
+#ifdef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void   btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+{
+
+	// put the index into m_controllers into m_tag   
+	int index = 0;
+	{
+
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+		{
+			btCollisionObject*   collisionObject= colWorld->getCollisionObjectArray()[i];
+			//Adding filtering here
+			if (!collisionObject->isStaticOrKinematicObject())
+			{
+				collisionObject->setIslandTag(index++);
+			}
+			collisionObject->setCompanionId(-1);
+			collisionObject->setHitFraction(btScalar(1.));
+		}
+	}
+	// do the union find
+
+	initUnionFind( index );
+
+	findUnions(dispatcher,colWorld);
+}
+
+void   btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+	// put the islandId ('find' value) into m_tag   
+	{
+		int index = 0;
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+		{
+			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+			if (!collisionObject->isStaticOrKinematicObject())
+			{
+				collisionObject->setIslandTag( m_unionFind.find(index) );
+				//Set the correct object offset in Collision Object Array
+				m_unionFind.getElement(index).m_sz = i;
+				collisionObject->setCompanionId(-1);
+				index++;
+			} else
+			{
+				collisionObject->setIslandTag(-1);
+				collisionObject->setCompanionId(-2);
+			}
+		}
+	}
+}
+
+
+#else //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+void	btSimulationIslandManager::updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher)
+{
+
+	initUnionFind( int (colWorld->getCollisionObjectArray().size()));
+
+	// put the index into m_controllers into m_tag	
+	{
+
+		int index = 0;
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size(); i++)
+		{
+			btCollisionObject*	collisionObject= colWorld->getCollisionObjectArray()[i];
+			collisionObject->setIslandTag(index);
+			collisionObject->setCompanionId(-1);
+			collisionObject->setHitFraction(btScalar(1.));
+			index++;
+
+		}
+	}
+	// do the union find
+
+	findUnions(dispatcher,colWorld);
+}
+
+void	btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* colWorld)
+{
+	// put the islandId ('find' value) into m_tag	
+	{
+
+
+		int index = 0;
+		int i;
+		for (i=0;i<colWorld->getCollisionObjectArray().size();i++)
+		{
+			btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i];
+			if (!collisionObject->isStaticOrKinematicObject())
+			{
+				collisionObject->setIslandTag( m_unionFind.find(index) );
+				collisionObject->setCompanionId(-1);
+			} else
+			{
+				collisionObject->setIslandTag(-1);
+				collisionObject->setCompanionId(-2);
+			}
+			index++;
+		}
+	}
+}
+
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+
+inline	int	getIslandId(const btPersistentManifold* lhs)
+{
+	int islandId;
+	const btCollisionObject* rcolObj0 = static_cast<const btCollisionObject*>(lhs->getBody0());
+	const btCollisionObject* rcolObj1 = static_cast<const btCollisionObject*>(lhs->getBody1());
+	islandId= rcolObj0->getIslandTag()>=0?rcolObj0->getIslandTag():rcolObj1->getIslandTag();
+	return islandId;
+
+}
+
+
+
+/// function object that routes calls to operator<
+class btPersistentManifoldSortPredicate
+{
+	public:
+
+		SIMD_FORCE_INLINE bool operator() ( const btPersistentManifold* lhs, const btPersistentManifold* rhs )
+		{
+			return getIslandId(lhs) < getIslandId(rhs);
+		}
+};
+
+
+void btSimulationIslandManager::buildIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld)
+{
+
+	BT_PROFILE("islandUnionFindAndQuickSort");
+	
+	btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+	m_islandmanifold.resize(0);
+
+	//we are going to sort the unionfind array, and store the element id in the size
+	//afterwards, we clean unionfind, to make sure no-one uses it anymore
+	
+	getUnionFind().sortIslands();
+	int numElem = getUnionFind().getNumElements();
+
+	int endIslandIndex=1;
+	int startIslandIndex;
+
+
+	//update the sleeping state for bodies, if all are sleeping
+	for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+	{
+		int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+		for (endIslandIndex = startIslandIndex+1;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+		{
+		}
+
+		//int numSleeping = 0;
+
+		bool allSleeping = true;
+
+		int idx;
+		for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+		{
+			int i = getUnionFind().getElement(idx).m_sz;
+
+			btCollisionObject* colObj0 = collisionObjects[i];
+			if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+			{
+//				printf("error in island management\n");
+			}
+
+			btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+			if (colObj0->getIslandTag() == islandId)
+			{
+				if (colObj0->getActivationState()== ACTIVE_TAG)
+				{
+					allSleeping = false;
+				}
+				if (colObj0->getActivationState()== DISABLE_DEACTIVATION)
+				{
+					allSleeping = false;
+				}
+			}
+		}
+			
+
+		if (allSleeping)
+		{
+			int idx;
+			for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+			{
+				int i = getUnionFind().getElement(idx).m_sz;
+				btCollisionObject* colObj0 = collisionObjects[i];
+				if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+				{
+//					printf("error in island management\n");
+				}
+
+				btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+				if (colObj0->getIslandTag() == islandId)
+				{
+					colObj0->setActivationState( ISLAND_SLEEPING );
+				}
+			}
+		} else
+		{
+
+			int idx;
+			for (idx=startIslandIndex;idx<endIslandIndex;idx++)
+			{
+				int i = getUnionFind().getElement(idx).m_sz;
+
+				btCollisionObject* colObj0 = collisionObjects[i];
+				if ((colObj0->getIslandTag() != islandId) && (colObj0->getIslandTag() != -1))
+				{
+//					printf("error in island management\n");
+				}
+
+				btAssert((colObj0->getIslandTag() == islandId) || (colObj0->getIslandTag() == -1));
+
+				if (colObj0->getIslandTag() == islandId)
+				{
+					if ( colObj0->getActivationState() == ISLAND_SLEEPING)
+					{
+						colObj0->setActivationState( WANTS_DEACTIVATION);
+						colObj0->setDeactivationTime(0.f);
+					}
+				}
+			}
+		}
+	}
+
+	
+	int i;
+	int maxNumManifolds = dispatcher->getNumManifolds();
+
+//#define SPLIT_ISLANDS 1
+//#ifdef SPLIT_ISLANDS
+
+	
+//#endif //SPLIT_ISLANDS
+
+	
+	for (i=0;i<maxNumManifolds ;i++)
+	{
+		 btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i);
+		 
+		 btCollisionObject* colObj0 = static_cast<btCollisionObject*>(manifold->getBody0());
+		 btCollisionObject* colObj1 = static_cast<btCollisionObject*>(manifold->getBody1());
+		
+		 ///@todo: check sleeping conditions!
+		 if (((colObj0) && colObj0->getActivationState() != ISLAND_SLEEPING) ||
+			((colObj1) && colObj1->getActivationState() != ISLAND_SLEEPING))
+		{
+		
+			//kinematic objects don't merge islands, but wake up all connected objects
+			if (colObj0->isKinematicObject() && colObj0->getActivationState() != ISLAND_SLEEPING)
+			{
+				colObj1->activate();
+			}
+			if (colObj1->isKinematicObject() && colObj1->getActivationState() != ISLAND_SLEEPING)
+			{
+				colObj0->activate();
+			}
+			if(m_splitIslands)
+			{ 
+				//filtering for response
+				if (dispatcher->needsResponse(colObj0,colObj1))
+					m_islandmanifold.push_back(manifold);
+			}
+		}
+	}
+}
+
+
+
+///@todo: this is random access, it can be walked 'cache friendly'!
+void btSimulationIslandManager::buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback)
+{
+	btCollisionObjectArray& collisionObjects = collisionWorld->getCollisionObjectArray();
+
+	buildIslands(dispatcher,collisionWorld);
+
+	int endIslandIndex=1;
+	int startIslandIndex;
+	int numElem = getUnionFind().getNumElements();
+
+	BT_PROFILE("processIslands");
+
+	if(!m_splitIslands)
+	{
+		btPersistentManifold** manifold = dispatcher->getInternalManifoldPointer();
+		int maxNumManifolds = dispatcher->getNumManifolds();
+		callback->ProcessIsland(&collisionObjects[0],collisionObjects.size(),manifold,maxNumManifolds, -1);
+	}
+	else
+	{
+		// Sort manifolds, based on islands
+		// Sort the vector using predicate and std::sort
+		//std::sort(islandmanifold.begin(), islandmanifold.end(), btPersistentManifoldSortPredicate);
+
+		int numManifolds = int (m_islandmanifold.size());
+
+		//we should do radix sort, it it much faster (O(n) instead of O (n log2(n))
+		m_islandmanifold.quickSort(btPersistentManifoldSortPredicate());
+
+		//now process all active islands (sets of manifolds for now)
+
+		int startManifoldIndex = 0;
+		int endManifoldIndex = 1;
+
+		//int islandId;
+
+		
+
+	//	printf("Start Islands\n");
+
+		//traverse the simulation islands, and call the solver, unless all objects are sleeping/deactivated
+		for ( startIslandIndex=0;startIslandIndex<numElem;startIslandIndex = endIslandIndex)
+		{
+			int islandId = getUnionFind().getElement(startIslandIndex).m_id;
+
+
+			   bool islandSleeping = false;
+	                
+					for (endIslandIndex = startIslandIndex;(endIslandIndex<numElem) && (getUnionFind().getElement(endIslandIndex).m_id == islandId);endIslandIndex++)
+					{
+							int i = getUnionFind().getElement(endIslandIndex).m_sz;
+							btCollisionObject* colObj0 = collisionObjects[i];
+							m_islandBodies.push_back(colObj0);
+							if (!colObj0->isActive())
+									islandSleeping = true;
+					}
+	                
+
+			//find the accompanying contact manifold for this islandId
+			int numIslandManifolds = 0;
+			btPersistentManifold** startManifold = 0;
+
+			if (startManifoldIndex<numManifolds)
+			{
+				int curIslandId = getIslandId(m_islandmanifold[startManifoldIndex]);
+				if (curIslandId == islandId)
+				{
+					startManifold = &m_islandmanifold[startManifoldIndex];
+				
+					for (endManifoldIndex = startManifoldIndex+1;(endManifoldIndex<numManifolds) && (islandId == getIslandId(m_islandmanifold[endManifoldIndex]));endManifoldIndex++)
+					{
+
+					}
+					/// Process the actual simulation, only if not sleeping/deactivated
+					numIslandManifolds = endManifoldIndex-startManifoldIndex;
+				}
+
+			}
+
+			if (!islandSleeping)
+			{
+				callback->ProcessIsland(&m_islandBodies[0],m_islandBodies.size(),startManifold,numIslandManifolds, islandId);
+	//			printf("Island callback of size:%d bodies, %d manifolds\n",islandBodies.size(),numIslandManifolds);
+			}
+			
+			if (numIslandManifolds)
+			{
+				startManifoldIndex = endManifoldIndex;
+			}
+
+			m_islandBodies.resize(0);
+		}
+	} // else if(!splitIslands) 
+
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
new file mode 100644
index 0000000..d059f5d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSimulationIslandManager.h
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SIMULATION_ISLAND_MANAGER_H
+#define SIMULATION_ISLAND_MANAGER_H
+
+#include "BulletCollision/CollisionDispatch/btUnionFind.h"
+#include "btCollisionCreateFunc.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btCollisionObject.h"
+
+class btCollisionObject;
+class btCollisionWorld;
+class btDispatcher;
+class btPersistentManifold;
+
+
+///SimulationIslandManager creates and handles simulation islands, using btUnionFind
+class btSimulationIslandManager
+{
+	btUnionFind m_unionFind;
+
+	btAlignedObjectArray<btPersistentManifold*>  m_islandmanifold;
+	btAlignedObjectArray<btCollisionObject* >  m_islandBodies;
+	
+	bool m_splitIslands;
+	
+public:
+	btSimulationIslandManager();
+	virtual ~btSimulationIslandManager();
+
+
+	void initUnionFind(int n);	
+	
+		
+	btUnionFind& getUnionFind() { return m_unionFind;}
+
+	virtual	void	updateActivationState(btCollisionWorld* colWorld,btDispatcher* dispatcher);
+	virtual	void	storeIslandActivationState(btCollisionWorld* world);
+
+
+	void	findUnions(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+
+	
+
+	struct	IslandCallback
+	{
+		virtual ~IslandCallback() {};
+
+		virtual	void	ProcessIsland(btCollisionObject** bodies,int numBodies,class btPersistentManifold**	manifolds,int numManifolds, int islandId) = 0;
+	};
+
+	void	buildAndProcessIslands(btDispatcher* dispatcher,btCollisionWorld* collisionWorld, IslandCallback* callback);
+
+	void buildIslands(btDispatcher* dispatcher,btCollisionWorld* colWorld);
+
+	bool getSplitIslands()
+	{
+		return m_splitIslands;
+	}
+	void setSplitIslands(bool doSplitIslands)
+	{
+		m_splitIslands = doSplitIslands;
+	}
+
+};
+
+#endif //SIMULATION_ISLAND_MANAGER_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
new file mode 100644
index 0000000..8df8769
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp
@@ -0,0 +1,260 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+//#include <stdio.h>
+
+btSphereBoxCollisionAlgorithm::btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped)
+: btActivatingCollisionAlgorithm(ci,col0,col1),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_isSwapped(isSwapped)
+{
+	btCollisionObject* sphereObj = m_isSwapped? col1 : col0;
+	btCollisionObject* boxObj = m_isSwapped? col0 : col1;
+	
+	if (!m_manifoldPtr && m_dispatcher->needsCollision(sphereObj,boxObj))
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(sphereObj,boxObj);
+		m_ownManifold = true;
+	}
+}
+
+
+btSphereBoxCollisionAlgorithm::~btSphereBoxCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+
+
+void btSphereBoxCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)dispatchInfo;
+	(void)resultOut;
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject* sphereObj = m_isSwapped? body1 : body0;
+	btCollisionObject* boxObj = m_isSwapped? body0 : body1;
+
+
+	btSphereShape* sphere0 = (btSphereShape*)sphereObj->getCollisionShape();
+
+	btVector3 normalOnSurfaceB;
+	btVector3 pOnBox,pOnSphere;
+	btVector3 sphereCenter = sphereObj->getWorldTransform().getOrigin();
+	btScalar radius = sphere0->getRadius();
+	
+	btScalar dist = getSphereDistance(boxObj,pOnBox,pOnSphere,sphereCenter,radius);
+
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	if (dist < SIMD_EPSILON)
+	{
+		btVector3 normalOnSurfaceB = (pOnBox- pOnSphere).normalize();
+
+		/// report a contact. internally this will be kept persistent, and contact reduction is done
+
+		resultOut->addContactPoint(normalOnSurfaceB,pOnBox,dist);
+		
+	}
+
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr->getNumContacts())
+		{
+			resultOut->refreshContactPoints();
+		}
+	}
+
+}
+
+btScalar btSphereBoxCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	(void)col0;
+	(void)col1;
+
+	//not yet
+	return btScalar(1.);
+}
+
+
+btScalar btSphereBoxCollisionAlgorithm::getSphereDistance(btCollisionObject* boxObj, btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius ) 
+{
+
+	btScalar margins;
+	btVector3 bounds[2];
+	btBoxShape* boxShape= (btBoxShape*)boxObj->getCollisionShape();
+	
+	bounds[0] = -boxShape->getHalfExtentsWithoutMargin();
+	bounds[1] = boxShape->getHalfExtentsWithoutMargin();
+
+	margins = boxShape->getMargin();//also add sphereShape margin?
+
+	const btTransform&	m44T = boxObj->getWorldTransform();
+
+	btVector3	boundsVec[2];
+	btScalar	fPenetration;
+
+	boundsVec[0] = bounds[0];
+	boundsVec[1] = bounds[1];
+
+	btVector3	marginsVec( margins, margins, margins );
+
+	// add margins
+	bounds[0] += marginsVec;
+	bounds[1] -= marginsVec;
+
+	/////////////////////////////////////////////////
+
+	btVector3	tmp, prel, n[6], normal, v3P;
+	btScalar   fSep = btScalar(10000000.0), fSepThis;
+
+	n[0].setValue( btScalar(-1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[1].setValue(  btScalar(0.0), btScalar(-1.0),  btScalar(0.0) );
+	n[2].setValue(  btScalar(0.0),  btScalar(0.0), btScalar(-1.0) );
+	n[3].setValue(  btScalar(1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[4].setValue(  btScalar(0.0),  btScalar(1.0),  btScalar(0.0) );
+	n[5].setValue(  btScalar(0.0),  btScalar(0.0),  btScalar(1.0) );
+
+	// convert  point in local space
+	prel = m44T.invXform( sphereCenter);
+	
+	bool	bFound = false;
+
+	v3P = prel;
+
+	for (int i=0;i<6;i++)
+	{
+		int j = i<3? 0:1;
+		if ( (fSepThis = ((v3P-bounds[j]) .dot(n[i]))) > btScalar(0.0) )
+		{
+			v3P = v3P - n[i]*fSepThis;		
+			bFound = true;
+		}
+	}
+	
+	//
+
+	if ( bFound )
+	{
+		bounds[0] = boundsVec[0];
+		bounds[1] = boundsVec[1];
+
+		normal = (prel - v3P).normalize();
+		pointOnBox = v3P + normal*margins;
+		v3PointOnSphere = prel - normal*fRadius;
+
+		if ( ((v3PointOnSphere - pointOnBox) .dot (normal)) > btScalar(0.0) )
+		{
+			return btScalar(1.0);
+		}
+
+		// transform back in world space
+		tmp = m44T( pointOnBox);
+		pointOnBox    = tmp;
+		tmp  = m44T( v3PointOnSphere);		
+		v3PointOnSphere = tmp;
+		btScalar fSeps2 = (pointOnBox-v3PointOnSphere).length2();
+		
+		//if this fails, fallback into deeper penetration case, below
+		if (fSeps2 > SIMD_EPSILON)
+		{
+			fSep = - btSqrt(fSeps2);
+			normal = (pointOnBox-v3PointOnSphere);
+			normal *= btScalar(1.)/fSep;
+		}
+
+		return fSep;
+	}
+
+	//////////////////////////////////////////////////
+	// Deep penetration case
+
+	fPenetration = getSpherePenetration( boxObj,pointOnBox, v3PointOnSphere, sphereCenter, fRadius,bounds[0],bounds[1] );
+
+	bounds[0] = boundsVec[0];
+	bounds[1] = boundsVec[1];
+
+	if ( fPenetration <= btScalar(0.0) )
+		return (fPenetration-margins);
+	else
+		return btScalar(1.0);
+}
+
+btScalar btSphereBoxCollisionAlgorithm::getSpherePenetration( btCollisionObject* boxObj,btVector3& pointOnBox, btVector3& v3PointOnSphere, const btVector3& sphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax) 
+{
+
+	btVector3 bounds[2];
+
+	bounds[0] = aabbMin;
+	bounds[1] = aabbMax;
+
+	btVector3	p0, tmp, prel, n[6], normal;
+	btScalar   fSep = btScalar(-10000000.0), fSepThis;
+
+	// set p0 and normal to a default value to shup up GCC
+	p0.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+	normal.setValue(btScalar(0.), btScalar(0.), btScalar(0.));
+
+	n[0].setValue( btScalar(-1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[1].setValue(  btScalar(0.0), btScalar(-1.0),  btScalar(0.0) );
+	n[2].setValue(  btScalar(0.0),  btScalar(0.0), btScalar(-1.0) );
+	n[3].setValue(  btScalar(1.0),  btScalar(0.0),  btScalar(0.0) );
+	n[4].setValue(  btScalar(0.0),  btScalar(1.0),  btScalar(0.0) );
+	n[5].setValue(  btScalar(0.0),  btScalar(0.0),  btScalar(1.0) );
+
+	const btTransform&	m44T = boxObj->getWorldTransform();
+
+	// convert  point in local space
+	prel = m44T.invXform( sphereCenter);
+
+	///////////
+
+	for (int i=0;i<6;i++)
+	{
+		int j = i<3 ? 0:1;
+		if ( (fSepThis = ((prel-bounds[j]) .dot( n[i]))-fRadius) > btScalar(0.0) )	return btScalar(1.0);
+		if ( fSepThis > fSep )
+		{
+			p0 = bounds[j];	normal = (btVector3&)n[i];
+			fSep = fSepThis;
+		}
+	}
+
+	pointOnBox = prel - normal*(normal.dot((prel-p0)));
+	v3PointOnSphere = pointOnBox + normal*fSep;
+
+	// transform back in world space
+	tmp  = m44T( pointOnBox);		
+	pointOnBox    = tmp;
+	tmp  = m44T( v3PointOnSphere);		v3PointOnSphere = tmp;
+	normal = (pointOnBox-v3PointOnSphere).normalize();
+
+	return fSep;
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
new file mode 100644
index 0000000..47111d1
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SPHERE_BOX_COLLISION_ALGORITHM_H
+#define SPHERE_BOX_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+#include "LinearMath/btVector3.h"
+
+/// btSphereBoxCollisionAlgorithm  provides sphere-box collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+class btSphereBoxCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool	m_isSwapped;
+	
+public:
+
+	btSphereBoxCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1, bool isSwapped);
+
+	virtual ~btSphereBoxCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+
+	btScalar getSphereDistance( btCollisionObject* boxObj,btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius );
+
+	btScalar getSpherePenetration( btCollisionObject* boxObj, btVector3& v3PointOnBox, btVector3& v3PointOnSphere, const btVector3& v3SphereCenter, btScalar fRadius, const btVector3& aabbMin, const btVector3& aabbMax);
+	
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereBoxCollisionAlgorithm));
+			if (!m_swapped)
+			{
+				return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,false);
+			} else
+			{
+				return new(mem) btSphereBoxCollisionAlgorithm(0,ci,body0,body1,true);
+			}
+		}
+	};
+
+};
+
+#endif //SPHERE_BOX_COLLISION_ALGORITHM_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
new file mode 100644
index 0000000..5c4e78f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereSphereCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+btSphereSphereCollisionAlgorithm::btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1)
+: btActivatingCollisionAlgorithm(ci,col0,col1),
+m_ownManifold(false),
+m_manifoldPtr(mf)
+{
+	if (!m_manifoldPtr)
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
+		m_ownManifold = true;
+	}
+}
+
+btSphereSphereCollisionAlgorithm::~btSphereSphereCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btSphereSphereCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)dispatchInfo;
+
+	if (!m_manifoldPtr)
+		return;
+
+	resultOut->setPersistentManifold(m_manifoldPtr);
+
+	btSphereShape* sphere0 = (btSphereShape*)col0->getCollisionShape();
+	btSphereShape* sphere1 = (btSphereShape*)col1->getCollisionShape();
+
+	btVector3 diff = col0->getWorldTransform().getOrigin()-  col1->getWorldTransform().getOrigin();
+	btScalar len = diff.length();
+	btScalar radius0 = sphere0->getRadius();
+	btScalar radius1 = sphere1->getRadius();
+
+#ifdef CLEAR_MANIFOLD
+	m_manifoldPtr->clearManifold(); //don't do this, it disables warmstarting
+#endif
+
+	///iff distance positive, don't generate a new contact
+	if ( len > (radius0+radius1))
+	{
+#ifndef CLEAR_MANIFOLD
+		resultOut->refreshContactPoints();
+#endif //CLEAR_MANIFOLD
+		return;
+	}
+	///distance (negative means penetration)
+	btScalar dist = len - (radius0+radius1);
+
+	btVector3 normalOnSurfaceB(1,0,0);
+	if (len > SIMD_EPSILON)
+	{
+		normalOnSurfaceB = diff / len;
+	}
+
+	///point on A (worldspace)
+	///btVector3 pos0 = col0->getWorldTransform().getOrigin() - radius0 * normalOnSurfaceB;
+	///point on B (worldspace)
+	btVector3 pos1 = col1->getWorldTransform().getOrigin() + radius1* normalOnSurfaceB;
+
+	/// report a contact. internally this will be kept persistent, and contact reduction is done
+	
+	
+	resultOut->addContactPoint(normalOnSurfaceB,pos1,dist);
+
+#ifndef CLEAR_MANIFOLD
+	resultOut->refreshContactPoints();
+#endif //CLEAR_MANIFOLD
+
+}
+
+btScalar btSphereSphereCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)col0;
+	(void)col1;
+	(void)dispatchInfo;
+	(void)resultOut;
+
+	//not yet
+	return btScalar(1.);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
new file mode 100644
index 0000000..7d07512
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SPHERE_SPHERE_COLLISION_ALGORITHM_H
+#define SPHERE_SPHERE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "btCollisionDispatcher.h"
+
+class btPersistentManifold;
+
+/// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereSphereCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	
+public:
+	btSphereSphereCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+	btSphereSphereCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+	
+	virtual ~btSphereSphereCollisionAlgorithm();
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereSphereCollisionAlgorithm));
+			return new(mem) btSphereSphereCollisionAlgorithm(0,ci,body0,body1);
+		}
+	};
+
+};
+
+#endif //SPHERE_SPHERE_COLLISION_ALGORITHM_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
new file mode 100644
index 0000000..c327c3f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSphereTriangleCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "SphereTriangleDetector.h"
+
+
+btSphereTriangleCollisionAlgorithm::btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* col0,btCollisionObject* col1,bool swapped)
+: btActivatingCollisionAlgorithm(ci,col0,col1),
+m_ownManifold(false),
+m_manifoldPtr(mf),
+m_swapped(swapped)
+{
+	if (!m_manifoldPtr)
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(col0,col1);
+		m_ownManifold = true;
+	}
+}
+
+btSphereTriangleCollisionAlgorithm::~btSphereTriangleCollisionAlgorithm()
+{
+	if (m_ownManifold)
+	{
+		if (m_manifoldPtr)
+			m_dispatcher->releaseManifold(m_manifoldPtr);
+	}
+}
+
+void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	if (!m_manifoldPtr)
+		return;
+
+	btCollisionObject* sphereObj = m_swapped? col1 : col0;
+	btCollisionObject* triObj = m_swapped? col0 : col1;
+
+	btSphereShape* sphere = (btSphereShape*)sphereObj->getCollisionShape();
+	btTriangleShape* triangle = (btTriangleShape*)triObj->getCollisionShape();
+	
+	/// report a contact. internally this will be kept persistent, and contact reduction is done
+	resultOut->setPersistentManifold(m_manifoldPtr);
+	SphereTriangleDetector detector(sphere,triangle, m_manifoldPtr->getContactBreakingThreshold());
+	
+	btDiscreteCollisionDetectorInterface::ClosestPointInput input;
+	input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);///@todo: tighter bounds
+	input.m_transformA = sphereObj->getWorldTransform();
+	input.m_transformB = triObj->getWorldTransform();
+
+	bool swapResults = m_swapped;
+
+	detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults);
+
+	if (m_ownManifold)
+		resultOut->refreshContactPoints();
+	
+}
+
+btScalar btSphereTriangleCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* col0,btCollisionObject* col1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	(void)resultOut;
+	(void)dispatchInfo;
+	(void)col0;
+	(void)col1;
+
+	//not yet
+	return btScalar(1.);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
new file mode 100644
index 0000000..606c363
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+#define SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+
+#include "btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+class btPersistentManifold;
+#include "btCollisionDispatcher.h"
+
+/// btSphereSphereCollisionAlgorithm  provides sphere-sphere collision detection.
+/// Other features are frame-coherency (persistent data) and collision response.
+/// Also provides the most basic sample for custom/user btCollisionAlgorithm
+class btSphereTriangleCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+	bool	m_ownManifold;
+	btPersistentManifold*	m_manifoldPtr;
+	bool	m_swapped;
+	
+public:
+	btSphereTriangleCollisionAlgorithm(btPersistentManifold* mf,const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool swapped);
+
+	btSphereTriangleCollisionAlgorithm(const btCollisionAlgorithmConstructionInfo& ci)
+		: btActivatingCollisionAlgorithm(ci) {}
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr && m_ownManifold)
+		{
+			manifoldArray.push_back(m_manifoldPtr);
+		}
+	}
+	
+	virtual ~btSphereTriangleCollisionAlgorithm();
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btSphereTriangleCollisionAlgorithm));
+
+			return new(mem) btSphereTriangleCollisionAlgorithm(ci.m_manifold,ci,body0,body1,m_swapped);
+		}
+	};
+
+};
+
+#endif //SPHERE_TRIANGLE_COLLISION_ALGORITHM_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
new file mode 100644
index 0000000..4c4f58d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.cpp
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btUnionFind.h"
+
+
+
+btUnionFind::~btUnionFind()
+{
+	Free();
+
+}
+
+btUnionFind::btUnionFind()
+{ 
+
+}
+
+void	btUnionFind::allocate(int N)
+{
+	m_elements.resize(N);
+}
+void	btUnionFind::Free()
+{
+	m_elements.clear();
+}
+
+
+void	btUnionFind::reset(int N)
+{
+	allocate(N);
+
+	for (int i = 0; i < N; i++) 
+	{ 
+		m_elements[i].m_id = i; m_elements[i].m_sz = 1; 
+	} 
+}
+
+
+class btUnionFindElementSortPredicate
+{
+	public:
+
+		bool operator() ( const btElement& lhs, const btElement& rhs )
+		{
+			return lhs.m_id < rhs.m_id;
+		}
+};
+
+///this is a special operation, destroying the content of btUnionFind.
+///it sorts the elements, based on island id, in order to make it easy to iterate over islands
+void	btUnionFind::sortIslands()
+{
+
+	//first store the original body index, and islandId
+	int numElements = m_elements.size();
+	
+	for (int i=0;i<numElements;i++)
+	{
+		m_elements[i].m_id = find(i);
+#ifndef STATIC_SIMULATION_ISLAND_OPTIMIZATION
+		m_elements[i].m_sz = i;
+#endif //STATIC_SIMULATION_ISLAND_OPTIMIZATION
+	}
+	
+	 // Sort the vector using predicate and std::sort
+	  //std::sort(m_elements.begin(), m_elements.end(), btUnionFindElementSortPredicate);
+	  m_elements.quickSort(btUnionFindElementSortPredicate());
+
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
new file mode 100644
index 0000000..2cce335
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionDispatch/btUnionFind.h
@@ -0,0 +1,129 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef UNION_FIND_H
+#define UNION_FIND_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#define USE_PATH_COMPRESSION 1
+
+///see for discussion of static island optimizations by Vroonsh here: http://code.google.com/p/bullet/issues/detail?id=406
+#define STATIC_SIMULATION_ISLAND_OPTIMIZATION 1
+
+struct	btElement
+{
+	int	m_id;
+	int	m_sz;
+};
+
+///UnionFind calculates connected subsets
+// Implements weighted Quick Union with path compression
+// optimization: could use short ints instead of ints (halving memory, would limit the number of rigid bodies to 64k, sounds reasonable)
+class btUnionFind
+  {
+    private:
+		btAlignedObjectArray<btElement>	m_elements;
+
+    public:
+	  
+		btUnionFind();
+		~btUnionFind();
+
+	
+		//this is a special operation, destroying the content of btUnionFind.
+		//it sorts the elements, based on island id, in order to make it easy to iterate over islands
+		void	sortIslands();
+
+	  void	reset(int N);
+
+	  SIMD_FORCE_INLINE int	getNumElements() const
+	  {
+		  return int(m_elements.size());
+	  }
+	  SIMD_FORCE_INLINE bool  isRoot(int x) const
+	  {
+		  return (x == m_elements[x].m_id);
+	  }
+
+	  btElement&	getElement(int index)
+	  {
+		  return m_elements[index];
+	  }
+	  const btElement& getElement(int index) const
+	  {
+		  return m_elements[index];
+	  }
+   
+	  void	allocate(int N);
+	  void	Free();
+
+
+
+
+	  int find(int p, int q)
+		{ 
+			return (find(p) == find(q)); 
+		}
+
+		void unite(int p, int q)
+		{
+			int i = find(p), j = find(q);
+			if (i == j) 
+				return;
+
+#ifndef USE_PATH_COMPRESSION
+			//weighted quick union, this keeps the 'trees' balanced, and keeps performance of unite O( log(n) )
+			if (m_elements[i].m_sz < m_elements[j].m_sz)
+			{ 
+				m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; 
+			}
+			else 
+			{ 
+				m_elements[j].m_id = i; m_elements[i].m_sz += m_elements[j].m_sz; 
+			}
+#else
+			m_elements[i].m_id = j; m_elements[j].m_sz += m_elements[i].m_sz; 
+#endif //USE_PATH_COMPRESSION
+		}
+
+		int find(int x)
+		{ 
+			//btAssert(x < m_N);
+			//btAssert(x >= 0);
+
+			while (x != m_elements[x].m_id) 
+			{
+		//not really a reason not to use path compression, and it flattens the trees/improves find performance dramatically
+	
+		#ifdef USE_PATH_COMPRESSION
+				const btElement* elementPtr = &m_elements[m_elements[x].m_id];
+				m_elements[x].m_id = elementPtr->m_id;
+				x = elementPtr->m_id;			
+		#else//
+				x = m_elements[x].m_id;
+		#endif		
+				//btAssert(x < m_N);
+				//btAssert(x >= 0);
+
+			}
+			return x; 
+		}
+
+
+  };
+
+
+#endif //UNION_FIND_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.cpp
new file mode 100644
index 0000000..9f1899e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.cpp
@@ -0,0 +1,131 @@
+/*
+*** ALEX ***
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btBarrelShape.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "LinearMath/btQuaternion.h"
+
+btBarrelShape::btBarrelShape(btScalar sY_low, btScalar sY_high, btScalar sR_vert, btScalar sR_hor, btScalar sR_offset )
+{
+	Y_low = sY_low;
+	Y_high = sY_high; 
+	R_vert = sR_vert; 
+	R_hor  = sR_hor; 
+	R_offset = sR_offset;
+	m_shapeType = BARREL_SHAPE_PROXYTYPE;
+}
+
+#include <stdio.h>
+ btVector3	btBarrelShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+	btVector3 supVec(0,0,0);
+	btVector3 supVecD;
+
+	// suppport point on the lathed ellipse?
+	btScalar pY = vec0.y();
+	btScalar pR = sqrt (vec0.z()*vec0.z() + vec0.x()*vec0.x() );
+	btScalar pH = pR;
+	btScalar dX = vec0.x()/pR;
+	btScalar dZ = vec0.z()/pR;
+	btScalar tpar = atan((pY*R_vert)/(pH*R_hor));
+	btScalar sY = R_vert * sin(tpar);
+	btScalar sH = R_hor  * cos(tpar);
+	btScalar sR = sH + R_offset;
+	btScalar sX = dX * sR;
+	btScalar sZ = dZ * sR;
+	supVec.setValue(sX,sY,sZ);
+	btScalar len = supVec.length();
+
+	// support point on the top disc?
+	if ((fabs(Y_high) < R_vert)&(supVec.y()>Y_high))
+	{
+		btScalar R_high_ellips = R_hor * sqrt( 1- pow( Y_high/R_vert ,2) );
+		btScalar R_high = R_high_ellips + R_offset;
+		btScalar rad_ratio = pR/R_high;
+		supVecD.setValue(vec0.x()/rad_ratio, Y_high, vec0.z()/rad_ratio);
+		supVec = supVecD;
+	}
+	// support point on the bottom disc?
+	if ((fabs(Y_low) < R_vert)&(supVec.y()<Y_low))
+	{
+		btScalar R_low_ellips = R_hor * sqrt( 1- pow( Y_low/R_vert ,2) );
+		btScalar R_low = R_low_ellips + R_offset;
+		btScalar rad_ratio = pR/R_low;
+		supVecD.setValue(vec0.x()/rad_ratio, Y_low, vec0.z()/rad_ratio);
+		supVec = supVecD;
+	}
+
+	return supVec;
+}
+
+ void	btBarrelShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	printf("NOT SUPPORTED!! \n");
+}
+
+
+void	btBarrelShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//***TO DO***
+	//as an approximation, take the inertia of the box that bounds the barrell
+
+	btTransform ident;
+	ident.setIdentity();
+
+	btVector3 halfExtents;
+
+	halfExtents.setValue((R_hor+R_offset), 
+						 (R_vert),
+						 (R_hor+R_offset));
+
+	btScalar margin = CONVEX_DISTANCE_MARGIN;
+
+	btScalar lx=btScalar(2.)*(halfExtents[0]+margin);
+	btScalar ly=btScalar(2.)*(halfExtents[1]+margin);
+	btScalar lz=btScalar(2.)*(halfExtents[2]+margin);
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(.08333333);
+
+	inertia[0] = scaledmass * (y2+z2);
+	inertia[1] = scaledmass * (x2+z2);
+	inertia[2] = scaledmass * (x2+y2);
+}
+
+
+void btBarrelShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 halfExtents; 
+	halfExtents.setValue((R_hor+R_offset), 
+						 (R_vert),
+						 (R_hor+R_offset));
+
+	btMatrix3x3 abs_b = t.getBasis().absolute();  
+	btVector3 center = t.getOrigin();
+	btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
+		   abs_b[1].dot(halfExtents),
+		  abs_b[2].dot(halfExtents));
+	extent += btVector3(getMargin(),getMargin(),getMargin());
+
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.h
new file mode 100644
index 0000000..9371bbf
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBarrelShape.h
@@ -0,0 +1,71 @@
+/*
+*** ALEX ***
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BARREL_SHAPE_H
+#define BT_BARREL_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+
+///btBarrelShape represents a barrel-like shape (with vertical axis)
+///made by lathing an arc of an ellipse around the vertical Y axis.
+///The center of the ellipse is on Y=0 level, and it is ofsetted by R_offset from 
+///the Y axis in radial direction. The two radii of the ellipse are R_vert (for the 
+///vertical direction, i.e. the axis parellel to Y) and R_hor (for the axis that
+///is perpendicular to Y). Also, the solid is clamped with two discs on the top and
+///the bottom, at levels Y_low and Y_high.
+class btBarrelShape : public btConvexInternalShape
+{
+private:
+	btScalar Y_low;
+	btScalar Y_high; 
+	btScalar R_vert; 
+	btScalar R_hor; 
+	btScalar R_offset;
+
+public:
+	btBarrelShape(btScalar sY_low, btScalar sY_high, btScalar sR_vert, btScalar sR_hor, btScalar sR_offset );
+
+	///CollisionShape Interface
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	/// btConvexShape Interface
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	//virtual int	getShapeType() const { return BARREL_SHAPE_PROXYTYPE; }
+
+	virtual const char*	getName()const 
+	{
+		return "BarrelShape";
+	}
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	btScalar	getY_low() const {return Y_low;}
+	btScalar	getY_high() const {return Y_high;}
+	btScalar	getR_vert() const {return R_vert;}
+	btScalar	getR_hor() const {return R_hor;}
+	btScalar	getR_offset() const {return R_offset;}
+
+
+};
+
+
+
+#endif //BT_CAPSULE_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
new file mode 100644
index 0000000..ecce028
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.cpp
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBox2dShape.h"
+
+
+//{ 
+
+
+void btBox2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+
+void	btBox2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//btScalar margin = btScalar(0.);
+	btVector3 halfExtents = getHalfExtentsWithMargin();
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
new file mode 100644
index 0000000..fc03206
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBox2dShape.h
@@ -0,0 +1,363 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OBB_BOX_2D_SHAPE_H
+#define OBB_BOX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///The btBox2dShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
+class btBox2dShape: public btPolyhedralConvexShape
+{
+
+	//btVector3	m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+	btVector3 m_centroid;
+	btVector3 m_vertices[4];
+	btVector3 m_normals[4];
+
+public:
+
+	btVector3 getHalfExtentsWithMargin() const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		return halfExtents;
+	}
+	
+	const btVector3& getHalfExtentsWithoutMargin() const
+	{
+		return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+	}
+	
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	SIMD_FORCE_INLINE  btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+	
+		for (int i=0;i<numVectors;i++)
+		{
+			const btVector3& vec = vectors[i];
+			supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+				btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+				btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); 
+		}
+
+	}
+
+
+	btBox2dShape( const btVector3& boxHalfExtents) 
+		: btPolyhedralConvexShape(),
+		m_centroid(0,0,0)
+	{
+		m_vertices[0].setValue(-boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
+		m_vertices[1].setValue(boxHalfExtents.getX(),-boxHalfExtents.getY(),0);
+		m_vertices[2].setValue(boxHalfExtents.getX(),boxHalfExtents.getY(),0);
+		m_vertices[3].setValue(-boxHalfExtents.getX(),boxHalfExtents.getY(),0);
+
+		m_normals[0].setValue(0,-1,0);
+		m_normals[1].setValue(1,0,0);
+		m_normals[2].setValue(0,1,0);
+		m_normals[3].setValue(-1,0,0);
+
+		m_shapeType = BOX_2D_SHAPE_PROXYTYPE;
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+	};
+
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+
+
+
+	int	getVertexCount() const
+	{
+		return 4;
+	}
+
+	virtual int getNumVertices()const
+	{
+		return 4;
+	}
+
+	const btVector3* getVertices() const
+	{
+		return &m_vertices[0];
+	}
+
+	const btVector3* getNormals() const
+	{
+		return &m_normals[0];
+	}
+
+
+
+
+
+
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+	{
+		//this plane might not be aligned...
+		btVector4 plane ;
+		getPlaneEquation(plane,i);
+		planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+		planeSupport = localGetSupportingVertex(-planeNormal);
+	}
+
+
+	const btVector3& getCentroid() const
+	{
+		return m_centroid;
+	}
+	
+	virtual int getNumPlanes() const
+	{
+		return 6;
+	}	
+	
+	
+
+	virtual int getNumEdges() const
+	{
+		return 12;
+	}
+
+
+	virtual void getVertex(int i,btVector3& vtx) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		vtx = btVector3(
+				halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
+				halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
+				halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+	}
+	
+
+	virtual void	getPlaneEquation(btVector4& plane,int i) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		switch (i)
+		{
+		case 0:
+			plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 1:
+			plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 2:
+			plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 3:
+			plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 4:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
+			break;
+		case 5:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+	
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+	//virtual void getEdge(int i,Edge& edge) const
+	{
+		int edgeVert0 = 0;
+		int edgeVert1 = 0;
+
+		switch (i)
+		{
+		case 0:
+				edgeVert0 = 0;
+				edgeVert1 = 1;
+			break;
+		case 1:
+				edgeVert0 = 0;
+				edgeVert1 = 2;
+			break;
+		case 2:
+			edgeVert0 = 1;
+			edgeVert1 = 3;
+
+			break;
+		case 3:
+			edgeVert0 = 2;
+			edgeVert1 = 3;
+			break;
+		case 4:
+			edgeVert0 = 0;
+			edgeVert1 = 4;
+			break;
+		case 5:
+			edgeVert0 = 1;
+			edgeVert1 = 5;
+
+			break;
+		case 6:
+			edgeVert0 = 2;
+			edgeVert1 = 6;
+			break;
+		case 7:
+			edgeVert0 = 3;
+			edgeVert1 = 7;
+			break;
+		case 8:
+			edgeVert0 = 4;
+			edgeVert1 = 5;
+			break;
+		case 9:
+			edgeVert0 = 4;
+			edgeVert1 = 6;
+			break;
+		case 10:
+			edgeVert0 = 5;
+			edgeVert1 = 7;
+			break;
+		case 11:
+			edgeVert0 = 6;
+			edgeVert1 = 7;
+			break;
+		default:
+			btAssert(0);
+
+		}
+
+		getVertex(edgeVert0,pa );
+		getVertex(edgeVert1,pb );
+	}
+
+
+
+
+	
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		//btScalar minDist = 2*tolerance;
+		
+		bool result =	(pt.x() <= (halfExtents.x()+tolerance)) &&
+						(pt.x() >= (-halfExtents.x()-tolerance)) &&
+						(pt.y() <= (halfExtents.y()+tolerance)) &&
+						(pt.y() >= (-halfExtents.y()-tolerance)) &&
+						(pt.z() <= (halfExtents.z()+tolerance)) &&
+						(pt.z() >= (-halfExtents.z()-tolerance));
+		
+		return result;
+	}
+
+
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "Box2d";
+	}
+
+	virtual int		getNumPreferredPenetrationDirections() const
+	{
+		return 6;
+	}
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+	{
+		switch (index)
+		{
+		case 0:
+			penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
+			break;
+		case 1:
+			penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
+			break;
+		case 2:
+			penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
+			break;
+		case 3:
+			penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
+			break;
+		case 4:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
+			break;
+		case 5:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+};
+
+#endif //OBB_BOX_2D_SHAPE_H
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
new file mode 100644
index 0000000..c6644ef
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBoxShape.cpp
@@ -0,0 +1,41 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "btBoxShape.h"
+
+
+//{ 
+
+
+void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+
+void	btBoxShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//btScalar margin = btScalar(0.);
+	btVector3 halfExtents = getHalfExtentsWithMargin();
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBoxShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBoxShape.h
new file mode 100644
index 0000000..b405efc
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBoxShape.h
@@ -0,0 +1,318 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OBB_BOX_MINKOWSKI_H
+#define OBB_BOX_MINKOWSKI_H
+
+#include "btPolyhedralConvexShape.h"
+#include "btCollisionMargin.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMinMax.h"
+
+///The btBoxShape is a box primitive around the origin, its sides axis aligned with length specified by half extents, in local shape coordinates. When used as part of a btCollisionObject or btRigidBody it will be an oriented box in world space.
+class btBoxShape: public btPolyhedralConvexShape
+{
+
+	//btVector3	m_boxHalfExtents1; //use m_implicitShapeDimensions instead
+
+
+public:
+
+	btVector3 getHalfExtentsWithMargin() const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		return halfExtents;
+	}
+	
+	const btVector3& getHalfExtentsWithoutMargin() const
+	{
+		return m_implicitShapeDimensions;//scaling is included, margin is not
+	}
+	
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	SIMD_FORCE_INLINE  btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+		
+		return btVector3(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(vec.z(), halfExtents.z(), -halfExtents.z()));
+	}
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+	{
+		const btVector3& halfExtents = getHalfExtentsWithoutMargin();
+	
+		for (int i=0;i<numVectors;i++)
+		{
+			const btVector3& vec = vectors[i];
+			supportVerticesOut[i].setValue(btFsels(vec.x(), halfExtents.x(), -halfExtents.x()),
+				btFsels(vec.y(), halfExtents.y(), -halfExtents.y()),
+				btFsels(vec.z(), halfExtents.z(), -halfExtents.z())); 
+		}
+
+	}
+
+
+	btBoxShape( const btVector3& boxHalfExtents) 
+		: btPolyhedralConvexShape()
+	{
+		m_shapeType = BOX_SHAPE_PROXYTYPE;
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = (boxHalfExtents * m_localScaling) - margin;
+	};
+
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const
+	{
+		//this plane might not be aligned...
+		btVector4 plane ;
+		getPlaneEquation(plane,i);
+		planeNormal = btVector3(plane.getX(),plane.getY(),plane.getZ());
+		planeSupport = localGetSupportingVertex(-planeNormal);
+	}
+
+	
+	virtual int getNumPlanes() const
+	{
+		return 6;
+	}	
+	
+	virtual int	getNumVertices() const 
+	{
+		return 8;
+	}
+
+	virtual int getNumEdges() const
+	{
+		return 12;
+	}
+
+
+	virtual void getVertex(int i,btVector3& vtx) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		vtx = btVector3(
+				halfExtents.x() * (1-(i&1)) - halfExtents.x() * (i&1),
+				halfExtents.y() * (1-((i&2)>>1)) - halfExtents.y() * ((i&2)>>1),
+				halfExtents.z() * (1-((i&4)>>2)) - halfExtents.z() * ((i&4)>>2));
+	}
+	
+
+	virtual void	getPlaneEquation(btVector4& plane,int i) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		switch (i)
+		{
+		case 0:
+			plane.setValue(btScalar(1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 1:
+			plane.setValue(btScalar(-1.),btScalar(0.),btScalar(0.),-halfExtents.x());
+			break;
+		case 2:
+			plane.setValue(btScalar(0.),btScalar(1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 3:
+			plane.setValue(btScalar(0.),btScalar(-1.),btScalar(0.),-halfExtents.y());
+			break;
+		case 4:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(1.),-halfExtents.z());
+			break;
+		case 5:
+			plane.setValue(btScalar(0.),btScalar(0.),btScalar(-1.),-halfExtents.z());
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+	
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+	//virtual void getEdge(int i,Edge& edge) const
+	{
+		int edgeVert0 = 0;
+		int edgeVert1 = 0;
+
+		switch (i)
+		{
+		case 0:
+				edgeVert0 = 0;
+				edgeVert1 = 1;
+			break;
+		case 1:
+				edgeVert0 = 0;
+				edgeVert1 = 2;
+			break;
+		case 2:
+			edgeVert0 = 1;
+			edgeVert1 = 3;
+
+			break;
+		case 3:
+			edgeVert0 = 2;
+			edgeVert1 = 3;
+			break;
+		case 4:
+			edgeVert0 = 0;
+			edgeVert1 = 4;
+			break;
+		case 5:
+			edgeVert0 = 1;
+			edgeVert1 = 5;
+
+			break;
+		case 6:
+			edgeVert0 = 2;
+			edgeVert1 = 6;
+			break;
+		case 7:
+			edgeVert0 = 3;
+			edgeVert1 = 7;
+			break;
+		case 8:
+			edgeVert0 = 4;
+			edgeVert1 = 5;
+			break;
+		case 9:
+			edgeVert0 = 4;
+			edgeVert1 = 6;
+			break;
+		case 10:
+			edgeVert0 = 5;
+			edgeVert1 = 7;
+			break;
+		case 11:
+			edgeVert0 = 6;
+			edgeVert1 = 7;
+			break;
+		default:
+			btAssert(0);
+
+		}
+
+		getVertex(edgeVert0,pa );
+		getVertex(edgeVert1,pb );
+	}
+
+
+
+
+	
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+
+		//btScalar minDist = 2*tolerance;
+		
+		bool result =	(pt.x() <= (halfExtents.x()+tolerance)) &&
+						(pt.x() >= (-halfExtents.x()-tolerance)) &&
+						(pt.y() <= (halfExtents.y()+tolerance)) &&
+						(pt.y() >= (-halfExtents.y()-tolerance)) &&
+						(pt.z() <= (halfExtents.z()+tolerance)) &&
+						(pt.z() >= (-halfExtents.z()-tolerance));
+		
+		return result;
+	}
+
+
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "Box";
+	}
+
+	virtual int		getNumPreferredPenetrationDirections() const
+	{
+		return 6;
+	}
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+	{
+		switch (index)
+		{
+		case 0:
+			penetrationVector.setValue(btScalar(1.),btScalar(0.),btScalar(0.));
+			break;
+		case 1:
+			penetrationVector.setValue(btScalar(-1.),btScalar(0.),btScalar(0.));
+			break;
+		case 2:
+			penetrationVector.setValue(btScalar(0.),btScalar(1.),btScalar(0.));
+			break;
+		case 3:
+			penetrationVector.setValue(btScalar(0.),btScalar(-1.),btScalar(0.));
+			break;
+		case 4:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(1.));
+			break;
+		case 5:
+			penetrationVector.setValue(btScalar(0.),btScalar(0.),btScalar(-1.));
+			break;
+		default:
+			btAssert(0);
+		}
+	}
+
+};
+
+
+#endif //OBB_BOX_MINKOWSKI_H
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
new file mode 100644
index 0000000..b71ee03
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.cpp
@@ -0,0 +1,466 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#define DISABLE_BVH
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+#include "LinearMath/btSerializer.h"
+
+///Bvh Concave triangle mesh is a static-triangle mesh shape with Bounding Volume Hierarchy optimization.
+///Uses an interface to access the triangles to allow for sharing graphics/physics triangles.
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_triangleInfoMap(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
+{
+	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+	//construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+	if (buildBvh)
+	{
+		buildOptimizedBvh();
+	}
+
+#endif //DISABLE_BVH
+
+}
+
+btBvhTriangleMeshShape::btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax,bool buildBvh)
+:btTriangleMeshShape(meshInterface),
+m_bvh(0),
+m_triangleInfoMap(0),
+m_useQuantizedAabbCompression(useQuantizedAabbCompression),
+m_ownsBvh(false)
+{
+	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+	//construct bvh from meshInterface
+#ifndef DISABLE_BVH
+
+	if (buildBvh)
+	{
+		void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+		m_bvh = new (mem) btOptimizedBvh();
+		
+		m_bvh->build(meshInterface,m_useQuantizedAabbCompression,bvhAabbMin,bvhAabbMax);
+		m_ownsBvh = true;
+	}
+
+#endif //DISABLE_BVH
+
+}
+
+void	btBvhTriangleMeshShape::partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	m_bvh->refitPartial( m_meshInterface,aabbMin,aabbMax );
+	
+	m_localAabbMin.setMin(aabbMin);
+	m_localAabbMax.setMax(aabbMax);
+}
+
+
+void	btBvhTriangleMeshShape::refitTree(const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	m_bvh->refit( m_meshInterface, aabbMin,aabbMax );
+	
+	recalcLocalAabb();
+}
+
+btBvhTriangleMeshShape::~btBvhTriangleMeshShape()
+{
+	if (m_ownsBvh)
+	{
+		m_bvh->~btOptimizedBvh();
+		btAlignedFree(m_bvh);
+	}
+}
+
+void	btBvhTriangleMeshShape::performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget)
+{
+	struct	MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btStridingMeshInterface*	m_meshInterface;
+		btTriangleCallback* m_callback;
+
+		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+			:m_meshInterface(meshInterface),
+			m_callback(callback)
+		{
+		}
+				
+		virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+		{
+			btVector3 m_triangle[3];
+			const unsigned char *vertexbase;
+			int numverts;
+			PHY_ScalarType type;
+			int stride;
+			const unsigned char *indexbase;
+			int indexstride;
+			int numfaces;
+			PHY_ScalarType indicestype;
+
+			m_meshInterface->getLockedReadOnlyVertexIndexBase(
+				&vertexbase,
+				numverts,
+				type,
+				stride,
+				&indexbase,
+				indexstride,
+				numfaces,
+				indicestype,
+				nodeSubPart);
+
+			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+	
+			const btVector3& meshScaling = m_meshInterface->getScaling();
+			for (int j=2;j>=0;j--)
+			{
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+				
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());		
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());		
+				}
+			}
+
+			/* Perform ray vs. triangle collision here */
+			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+		}
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface);
+
+	m_bvh->reportRayOverlappingNodex(&myNodeCallback,raySource,rayTarget);
+}
+
+void	btBvhTriangleMeshShape::performConvexcast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget, const btVector3& aabbMin, const btVector3& aabbMax)
+{
+	struct	MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btStridingMeshInterface*	m_meshInterface;
+		btTriangleCallback* m_callback;
+
+		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+			:m_meshInterface(meshInterface),
+			m_callback(callback)
+		{
+		}
+				
+		virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+		{
+			btVector3 m_triangle[3];
+			const unsigned char *vertexbase;
+			int numverts;
+			PHY_ScalarType type;
+			int stride;
+			const unsigned char *indexbase;
+			int indexstride;
+			int numfaces;
+			PHY_ScalarType indicestype;
+
+			m_meshInterface->getLockedReadOnlyVertexIndexBase(
+				&vertexbase,
+				numverts,
+				type,
+				stride,
+				&indexbase,
+				indexstride,
+				numfaces,
+				indicestype,
+				nodeSubPart);
+
+			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+	
+			const btVector3& meshScaling = m_meshInterface->getScaling();
+			for (int j=2;j>=0;j--)
+			{
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+
+					m_triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());		
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(btScalar(graphicsbase[0])*meshScaling.getX(),btScalar(graphicsbase[1])*meshScaling.getY(),btScalar(graphicsbase[2])*meshScaling.getZ());		
+				}
+			}
+
+			/* Perform ray vs. triangle collision here */
+			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+		}
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface);
+
+	m_bvh->reportBoxCastOverlappingNodex (&myNodeCallback, raySource, rayTarget, aabbMin, aabbMax);
+}
+
+//perform bvh tree traversal and report overlapping triangles to 'callback'
+void	btBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+
+#ifdef DISABLE_BVH
+	//brute force traverse all triangles
+	btTriangleMeshShape::processAllTriangles(callback,aabbMin,aabbMax);
+#else
+
+	//first get all the nodes
+
+	
+	struct	MyNodeOverlapCallback : public btNodeOverlapCallback
+	{
+		btStridingMeshInterface*	m_meshInterface;
+		btTriangleCallback*		m_callback;
+		btVector3				m_triangle[3];
+
+
+		MyNodeOverlapCallback(btTriangleCallback* callback,btStridingMeshInterface* meshInterface)
+			:m_meshInterface(meshInterface),
+			m_callback(callback)
+		{
+		}
+				
+		virtual void processNode(int nodeSubPart, int nodeTriangleIndex)
+		{
+			const unsigned char *vertexbase;
+			int numverts;
+			PHY_ScalarType type;
+			int stride;
+			const unsigned char *indexbase;
+			int indexstride;
+			int numfaces;
+			PHY_ScalarType indicestype;
+			
+
+			m_meshInterface->getLockedReadOnlyVertexIndexBase(
+				&vertexbase,
+				numverts,
+				type,
+				stride,
+				&indexbase,
+				indexstride,
+				numfaces,
+				indicestype,
+				nodeSubPart);
+
+			unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+			btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+	
+			const btVector3& meshScaling = m_meshInterface->getScaling();
+			for (int j=2;j>=0;j--)
+			{
+				
+				int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+
+
+#ifdef DEBUG_TRIANGLE_MESH
+				printf("%d ,",graphicsindex);
+#endif //DEBUG_TRIANGLE_MESH
+				if (type == PHY_FLOAT)
+				{
+					float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+					
+					m_triangle[j] = btVector3(
+																		graphicsbase[0]*meshScaling.getX(),
+																		graphicsbase[1]*meshScaling.getY(),
+																		graphicsbase[2]*meshScaling.getZ());
+				}
+				else
+				{
+					double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+
+					m_triangle[j] = btVector3(
+						btScalar(graphicsbase[0])*meshScaling.getX(),
+						btScalar(graphicsbase[1])*meshScaling.getY(),
+						btScalar(graphicsbase[2])*meshScaling.getZ());
+				}
+#ifdef DEBUG_TRIANGLE_MESH
+				printf("triangle vertices:%f,%f,%f\n",triangle[j].x(),triangle[j].y(),triangle[j].z());
+#endif //DEBUG_TRIANGLE_MESH
+			}
+
+			m_callback->processTriangle(m_triangle,nodeSubPart,nodeTriangleIndex);
+			m_meshInterface->unLockReadOnlyVertexBase(nodeSubPart);
+		}
+
+	};
+
+	MyNodeOverlapCallback	myNodeCallback(callback,m_meshInterface);
+
+	m_bvh->reportAabbOverlappingNodex(&myNodeCallback,aabbMin,aabbMax);
+
+
+#endif//DISABLE_BVH
+
+
+}
+
+void   btBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+   if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
+   {
+      btTriangleMeshShape::setLocalScaling(scaling);
+	  buildOptimizedBvh();
+   }
+}
+
+void   btBvhTriangleMeshShape::buildOptimizedBvh()
+{
+	if (m_ownsBvh)
+	{
+		m_bvh->~btOptimizedBvh();
+		btAlignedFree(m_bvh);
+	}
+	///m_localAabbMin/m_localAabbMax is already re-calculated in btTriangleMeshShape. We could just scale aabb, but this needs some more work
+	void* mem = btAlignedAlloc(sizeof(btOptimizedBvh),16);
+	m_bvh = new(mem) btOptimizedBvh();
+	//rebuild the bvh...
+	m_bvh->build(m_meshInterface,m_useQuantizedAabbCompression,m_localAabbMin,m_localAabbMax);
+	m_ownsBvh = true;
+}
+
+void   btBvhTriangleMeshShape::setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& scaling)
+{
+   btAssert(!m_bvh);
+   btAssert(!m_ownsBvh);
+
+   m_bvh = bvh;
+   m_ownsBvh = false;
+   // update the scaling without rebuilding the bvh
+   if ((getLocalScaling() -scaling).length2() > SIMD_EPSILON)
+   {
+      btTriangleMeshShape::setLocalScaling(scaling);
+   }
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btBvhTriangleMeshShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btTriangleMeshShapeData* trimeshData = (btTriangleMeshShapeData*) dataBuffer;
+
+	btCollisionShape::serialize(&trimeshData->m_collisionShapeData,serializer);
+
+	m_meshInterface->serialize(&trimeshData->m_meshInterface, serializer);
+
+	trimeshData->m_collisionMargin = float(m_collisionMargin);
+
+	
+
+	if (m_bvh && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_BVH))
+	{
+		void* chunk = serializer->findPointer(m_bvh);
+		if (chunk)
+		{
+#ifdef BT_USE_DOUBLE_PRECISION
+			trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)chunk;
+			trimeshData->m_quantizedFloatBvh = 0;
+#else
+			trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)chunk;
+			trimeshData->m_quantizedDoubleBvh= 0;
+#endif //BT_USE_DOUBLE_PRECISION
+		} else
+		{
+
+#ifdef BT_USE_DOUBLE_PRECISION
+			trimeshData->m_quantizedDoubleBvh = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+			trimeshData->m_quantizedFloatBvh = 0;
+#else
+			trimeshData->m_quantizedFloatBvh  = (btQuantizedBvhData*)serializer->getUniquePointer(m_bvh);
+			trimeshData->m_quantizedDoubleBvh= 0;
+#endif //BT_USE_DOUBLE_PRECISION
+	
+			int sz = m_bvh->calculateSerializeBufferSizeNew();
+			btChunk* chunk = serializer->allocate(sz,1);
+			const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+			serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,m_bvh);
+		}
+	} else
+	{
+		trimeshData->m_quantizedFloatBvh = 0;
+		trimeshData->m_quantizedDoubleBvh = 0;
+	}
+
+	
+
+	if (m_triangleInfoMap && !(serializer->getSerializationFlags()&BT_SERIALIZE_NO_TRIANGLEINFOMAP))
+	{
+		void* chunk = serializer->findPointer(m_triangleInfoMap);
+		if (chunk)
+		{
+			trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)chunk;
+		} else
+		{
+			trimeshData->m_triangleInfoMap = (btTriangleInfoMapData*)serializer->getUniquePointer(m_triangleInfoMap);
+			int sz = m_triangleInfoMap->calculateSerializeBufferSize();
+			btChunk* chunk = serializer->allocate(sz,1);
+			const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+			serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,m_triangleInfoMap);
+		}
+	} else
+	{
+		trimeshData->m_triangleInfoMap = 0;
+	}
+
+	return "btTriangleMeshShapeData";
+}
+
+void	btBvhTriangleMeshShape::serializeSingleBvh(btSerializer* serializer) const
+{
+	if (m_bvh)
+	{
+		int len = m_bvh->calculateSerializeBufferSizeNew(); //make sure not to use calculateSerializeBufferSize because it is used for in-place
+		btChunk* chunk = serializer->allocate(len,1);
+		const char* structType = m_bvh->serialize(chunk->m_oldPtr, serializer);
+		serializer->finalizeChunk(chunk,structType,BT_QUANTIZED_BVH_CODE,(void*)m_bvh);
+	}
+}
+
+void	btBvhTriangleMeshShape::serializeSingleTriangleInfoMap(btSerializer* serializer) const
+{
+	if (m_triangleInfoMap)
+	{
+		int len = m_triangleInfoMap->calculateSerializeBufferSize();
+		btChunk* chunk = serializer->allocate(len,1);
+		const char* structType = m_triangleInfoMap->serialize(chunk->m_oldPtr, serializer);
+		serializer->finalizeChunk(chunk,structType,BT_TRIANLGE_INFO_MAP,(void*)m_triangleInfoMap);
+	}
+}
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
new file mode 100644
index 0000000..e4d4386
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h
@@ -0,0 +1,139 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BVH_TRIANGLE_MESH_SHAPE_H
+#define BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "btTriangleMeshShape.h"
+#include "btOptimizedBvh.h"
+#include "LinearMath/btAlignedAllocator.h"
+#include "btTriangleInfoMap.h"
+
+///The btBvhTriangleMeshShape is a static-triangle mesh shape with several optimizations, such as bounding volume hierarchy and cache friendly traversal for PlayStation 3 Cell SPU. It is recommended to enable useQuantizedAabbCompression for better memory usage.
+///It takes a triangle mesh as input, for example a btTriangleMesh or btTriangleIndexVertexArray. The btBvhTriangleMeshShape class allows for triangle mesh deformations by a refit or partialRefit method.
+///Instead of building the bounding volume hierarchy acceleration structure, it is also possible to serialize (save) and deserialize (load) the structure from disk.
+///See Demos\ConcaveDemo\ConcavePhysicsDemo.cpp for an example.
+ATTRIBUTE_ALIGNED16(class) btBvhTriangleMeshShape : public btTriangleMeshShape
+{
+
+	btOptimizedBvh*	m_bvh;
+	btTriangleInfoMap*	m_triangleInfoMap;
+
+	bool m_useQuantizedAabbCompression;
+	bool m_ownsBvh;
+	bool m_pad[11];////need padding due to alignment
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btBvhTriangleMeshShape() : btTriangleMeshShape(0),m_bvh(0),m_triangleInfoMap(0),m_ownsBvh(false) {m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;};
+	btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true);
+
+	///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+	btBvhTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true);
+	
+	virtual ~btBvhTriangleMeshShape();
+
+	bool getOwnsBvh () const
+	{
+		return m_ownsBvh;
+	}
+
+
+	
+	void performRaycast (btTriangleCallback* callback, const btVector3& raySource, const btVector3& rayTarget);
+	void performConvexcast (btTriangleCallback* callback, const btVector3& boxSource, const btVector3& boxTarget, const btVector3& boxMin, const btVector3& boxMax);
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	void	refitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+
+	///for a fast incremental refit of parts of the tree. Note: the entire AABB of the tree will become more conservative, it never shrinks
+	void	partialRefitTree(const btVector3& aabbMin,const btVector3& aabbMax);
+
+	//debugging
+	virtual const char*	getName()const {return "BVHTRIANGLEMESH";}
+
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	
+	btOptimizedBvh*	getOptimizedBvh()
+	{
+		return m_bvh;
+	}
+
+	void	setOptimizedBvh(btOptimizedBvh* bvh, const btVector3& localScaling=btVector3(1,1,1));
+
+	void    buildOptimizedBvh();
+
+	bool	usesQuantizedAabbCompression() const
+	{
+		return	m_useQuantizedAabbCompression;
+	}
+
+	void	setTriangleInfoMap(btTriangleInfoMap* triangleInfoMap)
+	{
+		m_triangleInfoMap = triangleInfoMap;
+	}
+
+	const btTriangleInfoMap*	getTriangleInfoMap() const
+	{
+		return m_triangleInfoMap;
+	}
+	
+	btTriangleInfoMap*	getTriangleInfoMap()
+	{
+		return m_triangleInfoMap;
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	virtual void	serializeSingleBvh(btSerializer* serializer) const;
+
+	virtual void	serializeSingleTriangleInfoMap(btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btTriangleMeshShapeData
+{
+	btCollisionShapeData	m_collisionShapeData;
+
+	btStridingMeshInterfaceData m_meshInterface;
+
+	btQuantizedBvhFloatData		*m_quantizedFloatBvh;
+	btQuantizedBvhDoubleData	*m_quantizedDoubleBvh;
+
+	btTriangleInfoMapData	*m_triangleInfoMap;
+	
+	float	m_collisionMargin;
+
+	char m_pad3[4];
+	
+};
+
+
+SIMD_FORCE_INLINE	int	btBvhTriangleMeshShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btTriangleMeshShapeData);
+}
+
+
+
+#endif //BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
new file mode 100644
index 0000000..2faa11d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.cpp
@@ -0,0 +1,171 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btCapsuleShape.h"
+
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "LinearMath/btQuaternion.h"
+
+btCapsuleShape::btCapsuleShape(btScalar radius, btScalar height) : btConvexInternalShape ()
+{
+	m_shapeType = CAPSULE_SHAPE_PROXYTYPE;
+	m_upAxis = 1;
+	m_implicitShapeDimensions.setValue(radius,0.5f*height,radius);
+}
+
+ 
+ btVector3	btCapsuleShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+
+	btVector3 supVec(0,0,0);
+
+	btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	btVector3 vtx;
+	btScalar newDot;
+	
+	btScalar radius = getRadius();
+
+
+	{
+		btVector3 pos(0,0,0);
+		pos[getUpAxis()] = getHalfHeight();
+
+		vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+	{
+		btVector3 pos(0,0,0);
+		pos[getUpAxis()] = -getHalfHeight();
+
+		vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+
+	return supVec;
+
+}
+
+ void	btCapsuleShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+
+	
+	btScalar radius = getRadius();
+
+	for (int j=0;j<numVectors;j++)
+	{
+		btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+		const btVector3& vec = vectors[j];
+
+		btVector3 vtx;
+		btScalar newDot;
+		{
+			btVector3 pos(0,0,0);
+			pos[getUpAxis()] = getHalfHeight();
+			vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supportVerticesOut[j] = vtx;
+			}
+		}
+		{
+			btVector3 pos(0,0,0);
+			pos[getUpAxis()] = -getHalfHeight();
+			vtx = pos +vec*m_localScaling*(radius) - vec * getMargin();
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supportVerticesOut[j] = vtx;
+			}
+		}
+		
+	}
+}
+
+
+void	btCapsuleShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//as an approximation, take the inertia of the box that bounds the spheres
+
+	btTransform ident;
+	ident.setIdentity();
+
+	
+	btScalar radius = getRadius();
+
+	btVector3 halfExtents(radius,radius,radius);
+	halfExtents[getUpAxis()]+=getHalfHeight();
+
+	btScalar margin = CONVEX_DISTANCE_MARGIN;
+
+	btScalar lx=btScalar(2.)*(halfExtents[0]+margin);
+	btScalar ly=btScalar(2.)*(halfExtents[1]+margin);
+	btScalar lz=btScalar(2.)*(halfExtents[2]+margin);
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(.08333333);
+
+	inertia[0] = scaledmass * (y2+z2);
+	inertia[1] = scaledmass * (x2+z2);
+	inertia[2] = scaledmass * (x2+y2);
+
+}
+
+btCapsuleShapeX::btCapsuleShapeX(btScalar radius,btScalar height)
+{
+	m_upAxis = 0;
+	m_implicitShapeDimensions.setValue(0.5f*height, radius,radius);
+}
+
+
+
+
+
+
+btCapsuleShapeZ::btCapsuleShapeZ(btScalar radius,btScalar height)
+{
+	m_upAxis = 2;
+	m_implicitShapeDimensions.setValue(radius,radius,0.5f*height);
+}
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
new file mode 100644
index 0000000..ab763ab
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCapsuleShape.h
@@ -0,0 +1,173 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CAPSULE_SHAPE_H
+#define BT_CAPSULE_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+
+///The btCapsuleShape represents a capsule around the Y axis, there is also the btCapsuleShapeX aligned around the X axis and btCapsuleShapeZ around the Z axis.
+///The total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+///The btCapsuleShape is a convex hull of two spheres. The btMultiSphereShape is a more general collision shape that takes the convex hull of multiple sphere, so it can also represent a capsule when just using two spheres.
+class btCapsuleShape : public btConvexInternalShape
+{
+protected:
+	int	m_upAxis;
+
+protected:
+	///only used for btCapsuleShapeZ and btCapsuleShapeX subclasses.
+	btCapsuleShape() : btConvexInternalShape() {m_shapeType = CAPSULE_SHAPE_PROXYTYPE;};
+
+public:
+	btCapsuleShape(btScalar radius,btScalar height);
+
+	///CollisionShape Interface
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	/// btConvexShape Interface
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+
+	virtual void getAabb (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+	{
+			btVector3 halfExtents(getRadius(),getRadius(),getRadius());
+			halfExtents[m_upAxis] = getRadius() + getHalfHeight();
+			halfExtents += btVector3(getMargin(),getMargin(),getMargin());
+			btMatrix3x3 abs_b = t.getBasis().absolute();  
+			btVector3 center = t.getOrigin();
+			btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));		  
+			
+			aabbMin = center - extent;
+			aabbMax = center + extent;
+	}
+
+	virtual const char*	getName()const 
+	{
+		return "CapsuleShape";
+	}
+
+	int	getUpAxis() const
+	{
+		return m_upAxis;
+	}
+
+	btScalar	getRadius() const
+	{
+		int radiusAxis = (m_upAxis+2)%3;
+		return m_implicitShapeDimensions[radiusAxis];
+	}
+
+	btScalar	getHalfHeight() const
+	{
+		return m_implicitShapeDimensions[m_upAxis];
+	}
+
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///btCapsuleShapeX represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeX : public btCapsuleShape
+{
+public:
+
+	btCapsuleShapeX(btScalar radius,btScalar height);
+		
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "CapsuleX";
+	}
+
+	
+
+};
+
+///btCapsuleShapeZ represents a capsule around the Z axis
+///the total height is height+2*radius, so the height is just the height between the center of each 'sphere' of the capsule caps.
+class btCapsuleShapeZ : public btCapsuleShape
+{
+public:
+	btCapsuleShapeZ(btScalar radius,btScalar height);
+
+		//debugging
+	virtual const char*	getName()const
+	{
+		return "CapsuleZ";
+	}
+
+	
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCapsuleShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	int	m_upAxis;
+
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btCapsuleShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCapsuleShapeData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btCapsuleShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btCapsuleShapeData* shapeData = (btCapsuleShapeData*) dataBuffer;
+	
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+
+	shapeData->m_upAxis = m_upAxis;
+	
+	return "btCapsuleShapeData";
+}
+
+#endif //BT_CAPSULE_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
new file mode 100644
index 0000000..18fd026
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionMargin.h
@@ -0,0 +1,26 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COLLISION_MARGIN_H
+#define COLLISION_MARGIN_H
+
+//used by Gjk and some other algorithms
+
+#define CONVEX_DISTANCE_MARGIN btScalar(0.04)// btScalar(0.1)//;//btScalar(0.01)
+
+
+
+#endif //COLLISION_MARGIN_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
new file mode 100644
index 0000000..26f0bd8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.cpp
@@ -0,0 +1,123 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "LinearMath/btSerializer.h"
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C" 
+{
+void btBulletCollisionProbe ();
+
+void btBulletCollisionProbe () {}
+}
+
+
+
+void	btCollisionShape::getBoundingSphere(btVector3& center,btScalar& radius) const
+{
+	btTransform tr;
+	tr.setIdentity();
+	btVector3 aabbMin,aabbMax;
+
+	getAabb(tr,aabbMin,aabbMax);
+
+	radius = (aabbMax-aabbMin).length()*btScalar(0.5);
+	center = (aabbMin+aabbMax)*btScalar(0.5);
+}
+
+
+btScalar	btCollisionShape::getContactBreakingThreshold(btScalar defaultContactThreshold) const
+{
+	// return getAngularMotionDisc() * defaultContactThreshold; // <-- original!
+	//return 0.001; // <-- ***ALEX***TEST: fixed and small, for small objects
+	//return getAngularMotionDisc() * getMargin()*0.2; //***ALEX*** modified because defaultContactThreshold is zero in C::E, with inward breaking threshold
+	//return 0.001+ getAngularMotionDisc() * getMargin()*0.2; //***ALEX*** hybryd!
+	return 0.3*getMargin(); //***ALEX*** fixed to be comparable to margin
+}
+
+btScalar	btCollisionShape::getAngularMotionDisc() const
+{
+	///@todo cache this value, to improve performance
+	btVector3	center;
+	btScalar disc;
+	getBoundingSphere(center,disc);
+	disc += (center).length();
+	return disc;
+}
+
+void btCollisionShape::calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const
+{
+	//start with static aabb
+	getAabb(curTrans,temporalAabbMin,temporalAabbMax);
+
+	btScalar temporalAabbMaxx = temporalAabbMax.getX();
+	btScalar temporalAabbMaxy = temporalAabbMax.getY();
+	btScalar temporalAabbMaxz = temporalAabbMax.getZ();
+	btScalar temporalAabbMinx = temporalAabbMin.getX();
+	btScalar temporalAabbMiny = temporalAabbMin.getY();
+	btScalar temporalAabbMinz = temporalAabbMin.getZ();
+
+	// add linear motion
+	btVector3 linMotion = linvel*timeStep;
+	///@todo: simd would have a vector max/min operation, instead of per-element access
+	if (linMotion.x() > btScalar(0.))
+		temporalAabbMaxx += linMotion.x(); 
+	else
+		temporalAabbMinx += linMotion.x();
+	if (linMotion.y() > btScalar(0.))
+		temporalAabbMaxy += linMotion.y(); 
+	else
+		temporalAabbMiny += linMotion.y();
+	if (linMotion.z() > btScalar(0.))
+		temporalAabbMaxz += linMotion.z(); 
+	else
+		temporalAabbMinz += linMotion.z();
+
+	//add conservative angular motion
+	btScalar angularMotion = angvel.length() * getAngularMotionDisc() * timeStep;
+	btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
+	temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
+	temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
+
+	temporalAabbMin -= angularMotion3d;
+	temporalAabbMax += angularMotion3d;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btCollisionShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btCollisionShapeData* shapeData = (btCollisionShapeData*) dataBuffer;
+	char* name = (char*) serializer->findNameForPointer(this);
+	shapeData->m_name = (char*)serializer->getUniquePointer(name);
+	if (shapeData->m_name)
+	{
+		serializer->serializeName(name);
+	}
+	shapeData->m_shapeType = m_shapeType;
+	//shapeData->m_padding//??
+	return "btCollisionShapeData";
+}
+
+void	btCollisionShape::serializeSingleShape(btSerializer* serializer) const
+{
+	int len = calculateSerializeBufferSize();
+	btChunk* chunk = serializer->allocate(len,1);
+	const char* structType = serialize(chunk->m_oldPtr, serializer);
+	serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,(void*)this);
+}
\ No newline at end of file
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
new file mode 100644
index 0000000..f32bd73
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCollisionShape.h
@@ -0,0 +1,150 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COLLISION_SHAPE_H
+#define COLLISION_SHAPE_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" //for the shape types
+class btSerializer;
+
+
+///The btCollisionShape class provides an interface for collision shapes that can be shared among btCollisionObjects.
+class btCollisionShape
+{
+protected:
+	int m_shapeType;
+	void* m_userPointer;
+
+public:
+
+	btCollisionShape() : m_shapeType (INVALID_SHAPE_PROXYTYPE), m_userPointer(0)
+	{
+	}
+
+	virtual ~btCollisionShape()
+	{
+	}
+
+	///getAabb returns the axis aligned bounding box in the coordinate frame of the given transform t.
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	virtual void	getBoundingSphere(btVector3& center,btScalar& radius) const;
+
+	///getAngularMotionDisc returns the maximus radius needed for Conservative Advancement to handle time-of-impact with rotations.
+	virtual btScalar	getAngularMotionDisc() const;
+
+	virtual btScalar	getContactBreakingThreshold(btScalar defaultContactThresholdFactor) const;
+
+
+	///calculateTemporalAabb calculates the enclosing aabb for the moving object over interval [0..timeStep)
+	///result is conservative
+	void calculateTemporalAabb(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep, btVector3& temporalAabbMin,btVector3& temporalAabbMax) const;
+
+
+
+	SIMD_FORCE_INLINE bool	isPolyhedral() const
+	{
+		return btBroadphaseProxy::isPolyhedral(getShapeType());
+	}
+
+	SIMD_FORCE_INLINE bool	isConvex2d() const
+	{
+		return btBroadphaseProxy::isConvex2d(getShapeType());
+	}
+
+	SIMD_FORCE_INLINE bool	isConvex() const
+	{
+		return btBroadphaseProxy::isConvex(getShapeType());
+	}
+	SIMD_FORCE_INLINE bool	isNonMoving() const
+	{
+		return btBroadphaseProxy::isNonMoving(getShapeType());
+	}
+	SIMD_FORCE_INLINE bool	isConcave() const
+	{
+		return btBroadphaseProxy::isConcave(getShapeType());
+	}
+	SIMD_FORCE_INLINE bool	isCompound() const
+	{
+		return btBroadphaseProxy::isCompound(getShapeType());
+	}
+
+	SIMD_FORCE_INLINE bool	isSoftBody() const
+	{
+		return btBroadphaseProxy::isSoftBody(getShapeType());
+	}
+
+	///isInfinite is used to catch simulation error (aabb check)
+	SIMD_FORCE_INLINE bool isInfinite() const
+	{
+		return btBroadphaseProxy::isInfinite(getShapeType());
+	}
+
+#ifndef __SPU__
+	virtual void	setLocalScaling(const btVector3& scaling) =0;
+	virtual const btVector3& getLocalScaling() const =0;
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const = 0;
+
+
+//debugging support
+	virtual const char*	getName()const =0 ;
+#endif //__SPU__
+
+	
+	int		getShapeType() const { return m_shapeType; }
+	virtual void	setMargin(btScalar margin) = 0;
+	virtual btScalar	getMargin() const = 0;
+
+	
+	///optional user data pointer
+	void	setUserPointer(void*  userPtr)
+	{
+		m_userPointer = userPtr;
+	}
+
+	void*	getUserPointer() const
+	{
+		return m_userPointer;
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	virtual void	serializeSingleShape(btSerializer* serializer) const;
+
+};	
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCollisionShapeData
+{
+	char	*m_name;
+	int		m_shapeType;
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btCollisionShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCollisionShapeData);
+}
+
+
+
+#endif //COLLISION_SHAPE_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
new file mode 100644
index 0000000..c4f3dff
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.cpp
@@ -0,0 +1,351 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCompoundShape.h"
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btDbvt.h"
+#include "LinearMath/btSerializer.h"
+
+btCompoundShape::btCompoundShape(bool enableDynamicAabbTree)
+: m_localAabbMin(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT)),
+m_localAabbMax(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)),
+m_dynamicAabbTree(0),
+m_updateRevision(1),
+m_collisionMargin(btScalar(0.)),
+m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.))
+{
+	m_shapeType = COMPOUND_SHAPE_PROXYTYPE;
+
+	if (enableDynamicAabbTree)
+	{
+		void* mem = btAlignedAlloc(sizeof(btDbvt),16);
+		m_dynamicAabbTree = new(mem) btDbvt();
+		btAssert(mem==m_dynamicAabbTree);
+	}
+}
+
+
+btCompoundShape::~btCompoundShape()
+{
+	if (m_dynamicAabbTree)
+	{
+		m_dynamicAabbTree->~btDbvt();
+		btAlignedFree(m_dynamicAabbTree);
+	}
+}
+
+void	btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape)
+{
+	m_updateRevision++;
+	//m_childTransforms.push_back(localTransform);
+	//m_childShapes.push_back(shape);
+	btCompoundShapeChild child;
+	child.m_node = 0;
+	child.m_transform = localTransform;
+	child.m_childShape = shape;
+	child.m_childShapeType = shape->getShapeType();
+	child.m_childMargin = shape->getMargin();
+
+	
+	//extend the local aabbMin/aabbMax
+	btVector3 localAabbMin,localAabbMax;
+	shape->getAabb(localTransform,localAabbMin,localAabbMax);
+	for (int i=0;i<3;i++)
+	{
+		if (m_localAabbMin[i] > localAabbMin[i])
+		{
+			m_localAabbMin[i] = localAabbMin[i];
+		}
+		if (m_localAabbMax[i] < localAabbMax[i])
+		{
+			m_localAabbMax[i] = localAabbMax[i];
+		}
+
+	}
+	if (m_dynamicAabbTree)
+	{
+		const btDbvtVolume	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+		int index = m_children.size();
+		child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
+	}
+
+	m_children.push_back(child);
+
+}
+
+void	btCompoundShape::updateChildTransform(int childIndex, const btTransform& newChildTransform)
+{
+	m_children[childIndex].m_transform = newChildTransform;
+
+	if (m_dynamicAabbTree)
+	{
+		///update the dynamic aabb tree
+		btVector3 localAabbMin,localAabbMax;
+		m_children[childIndex].m_childShape->getAabb(newChildTransform,localAabbMin,localAabbMax);
+		ATTRIBUTE_ALIGNED16(btDbvtVolume)	bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+		//int index = m_children.size()-1;
+		m_dynamicAabbTree->update(m_children[childIndex].m_node,bounds);
+	}
+
+	recalculateLocalAabb();
+}
+
+void btCompoundShape::removeChildShapeByIndex(int childShapeIndex)
+{
+	m_updateRevision++;
+	btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size());
+	if (m_dynamicAabbTree)
+	{
+		m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node);
+	}
+	m_children.swap(childShapeIndex,m_children.size()-1);
+    if (m_dynamicAabbTree) 
+		m_children[childShapeIndex].m_node->dataAsInt = childShapeIndex;
+	m_children.pop_back();
+
+}
+
+
+
+void btCompoundShape::removeChildShape(btCollisionShape* shape)
+{
+	m_updateRevision++;
+	// Find the children containing the shape specified, and remove those children.
+	//note: there might be multiple children using the same shape!
+	for(int i = m_children.size()-1; i >= 0 ; i--)
+	{
+		if(m_children[i].m_childShape == shape)
+		{
+			removeChildShapeByIndex(i);
+		}
+	}
+
+
+
+	recalculateLocalAabb();
+}
+
+void btCompoundShape::recalculateLocalAabb()
+{
+	// Recalculate the local aabb
+	// Brute force, it iterates over all the shapes left.
+
+	m_localAabbMin = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	m_localAabbMax = btVector3(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+
+	//extend the local aabbMin/aabbMax
+	for (int j = 0; j < m_children.size(); j++)
+	{
+		btVector3 localAabbMin,localAabbMax;
+		m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax);
+		for (int i=0;i<3;i++)
+		{
+			if (m_localAabbMin[i] > localAabbMin[i])
+				m_localAabbMin[i] = localAabbMin[i];
+			if (m_localAabbMax[i] < localAabbMax[i])
+				m_localAabbMax[i] = localAabbMax[i];
+		}
+	}
+}
+
+///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
+	btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
+	
+	//avoid an illegal AABB when there are no children
+	if (!m_children.size())
+	{
+		localHalfExtents.setValue(0,0,0);
+		localCenter.setValue(0,0,0);
+	}
+	localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
+		
+
+	btMatrix3x3 abs_b = trans.getBasis().absolute();  
+
+	btVector3 center = trans(localCenter);
+
+	btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+		abs_b[1].dot(localHalfExtents),
+		abs_b[2].dot(localHalfExtents));
+	aabbMin = center-extent;
+	aabbMax = center+extent;
+	
+}
+
+void	btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//approximation: take the inertia from the aabb for now
+	btTransform ident;
+	ident.setIdentity();
+	btVector3 aabbMin,aabbMax;
+	getAabb(ident,aabbMin,aabbMax);
+
+	btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia[0] = mass/(btScalar(12.0)) * (ly*ly + lz*lz);
+	inertia[1] = mass/(btScalar(12.0)) * (lx*lx + lz*lz);
+	inertia[2] = mass/(btScalar(12.0)) * (lx*lx + ly*ly);
+
+}
+
+
+
+
+void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const
+{
+	int n = m_children.size();
+
+	btScalar totalMass = 0;
+	btVector3 center(0, 0, 0);
+	int k;
+
+	for (k = 0; k < n; k++)
+	{
+		btAssert(masses[k]>0);
+		center += m_children[k].m_transform.getOrigin() * masses[k];
+		totalMass += masses[k];
+	}
+
+	btAssert(totalMass>0);
+
+	center /= totalMass;
+	principal.setOrigin(center);
+
+	btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0);
+	for ( k = 0; k < n; k++)
+	{
+		btVector3 i;
+		m_children[k].m_childShape->calculateLocalInertia(masses[k], i);
+
+		const btTransform& t = m_children[k].m_transform;
+		btVector3 o = t.getOrigin() - center;
+
+		//compute inertia tensor in coordinate system of compound shape
+		btMatrix3x3 j = t.getBasis().transpose();
+		j[0] *= i[0];
+		j[1] *= i[1];
+		j[2] *= i[2];
+		j = t.getBasis() * j;
+
+		//add inertia tensor
+		tensor[0] += j[0];
+		tensor[1] += j[1];
+		tensor[2] += j[2];
+
+		//compute inertia tensor of pointmass at o
+		btScalar o2 = o.length2();
+		j[0].setValue(o2, 0, 0);
+		j[1].setValue(0, o2, 0);
+		j[2].setValue(0, 0, o2);
+		j[0] += o * -o.x(); 
+		j[1] += o * -o.y(); 
+		j[2] += o * -o.z();
+
+		//add inertia tensor of pointmass
+		tensor[0] += masses[k] * j[0];
+		tensor[1] += masses[k] * j[1];
+		tensor[2] += masses[k] * j[2];
+	}
+
+	tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+	inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]);
+}
+
+
+
+void btCompoundShape::setLocalScaling(const btVector3& scaling)
+{
+
+	for(int i = 0; i < m_children.size(); i++)
+	{
+		btTransform childTrans = getChildTransform(i);
+		btVector3 childScale = m_children[i].m_childShape->getLocalScaling();
+//		childScale = childScale * (childTrans.getBasis() * scaling);
+		childScale = childScale * scaling / m_localScaling;
+		m_children[i].m_childShape->setLocalScaling(childScale);
+		childTrans.setOrigin((childTrans.getOrigin())*scaling);
+		updateChildTransform(i, childTrans);
+		recalculateLocalAabb();
+	}
+	m_localScaling = scaling;
+}
+
+
+void btCompoundShape::createAabbTreeFromChildren()
+{
+    if ( !m_dynamicAabbTree )
+    {
+        void* mem = btAlignedAlloc(sizeof(btDbvt),16);
+        m_dynamicAabbTree = new(mem) btDbvt();
+        btAssert(mem==m_dynamicAabbTree);
+
+        for ( int index = 0; index < m_children.size(); index++ )
+        {
+            btCompoundShapeChild &child = m_children[index];
+
+            //extend the local aabbMin/aabbMax
+            btVector3 localAabbMin,localAabbMax;
+            child.m_childShape->getAabb(child.m_transform,localAabbMin,localAabbMax);
+
+            const btDbvtVolume  bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax);
+            child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index);
+        }
+    }
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btCompoundShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+
+	btCompoundShapeData* shapeData = (btCompoundShapeData*) dataBuffer;
+	btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+	shapeData->m_collisionMargin = float(m_collisionMargin);
+	shapeData->m_numChildShapes = m_children.size();
+	shapeData->m_childShapePtr = 0;
+	if (shapeData->m_numChildShapes)
+	{
+		btChunk* chunk = serializer->allocate(sizeof(btCompoundShapeChildData),shapeData->m_numChildShapes);
+		btCompoundShapeChildData* memPtr = (btCompoundShapeChildData*)chunk->m_oldPtr;
+		shapeData->m_childShapePtr = (btCompoundShapeChildData*)serializer->getUniquePointer(memPtr);
+
+		for (int i=0;i<shapeData->m_numChildShapes;i++,memPtr++)
+		{
+			memPtr->m_childMargin = float(m_children[i].m_childMargin);
+			memPtr->m_childShape = (btCollisionShapeData*)serializer->getUniquePointer(m_children[i].m_childShape);
+			//don't serialize shapes that already have been serialized
+			if (!serializer->findPointer(m_children[i].m_childShape))
+			{
+				btChunk* chunk = serializer->allocate(m_children[i].m_childShape->calculateSerializeBufferSize(),1);
+				const char* structType = m_children[i].m_childShape->serialize(chunk->m_oldPtr,serializer);
+				serializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,m_children[i].m_childShape);
+			} 
+
+			memPtr->m_childShapeType = m_children[i].m_childShapeType;
+			m_children[i].m_transform.serializeFloat(memPtr->m_transform);
+		}
+		serializer->finalizeChunk(chunk,"btCompoundShapeChildData",BT_ARRAY_CODE,chunk->m_oldPtr);
+	}
+	return "btCompoundShapeData";
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
new file mode 100644
index 0000000..95fc5a0
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCompoundShape.h
@@ -0,0 +1,208 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef COMPOUND_SHAPE_H
+#define COMPOUND_SHAPE_H
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+//class btOptimizedBvh;
+struct btDbvt;
+
+ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btTransform			m_transform;
+	btCollisionShape*	m_childShape;
+	int					m_childShapeType;
+	btScalar			m_childMargin;
+	struct btDbvtNode*	m_node;
+};
+
+SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2)
+{
+	return  ( c1.m_transform      == c2.m_transform &&
+		c1.m_childShape     == c2.m_childShape &&
+		c1.m_childShapeType == c2.m_childShapeType &&
+		c1.m_childMargin    == c2.m_childMargin );
+}
+
+/// The btCompoundShape allows to store multiple other btCollisionShapes
+/// This allows for moving concave collision objects. This is more general then the static concave btBvhTriangleMeshShape.
+/// It has an (optional) dynamic aabb tree to accelerate early rejection tests. 
+/// @todo: This aabb tree can also be use to speed up ray tests on btCompoundShape, see http://code.google.com/p/bullet/issues/detail?id=25
+/// Currently, removal of child shapes is only supported when disabling the aabb tree (pass 'false' in the constructor of btCompoundShape)
+ATTRIBUTE_ALIGNED16(class) btCompoundShape	: public btCollisionShape
+{
+	btAlignedObjectArray<btCompoundShapeChild> m_children;
+	btVector3						m_localAabbMin;
+	btVector3						m_localAabbMax;
+
+	btDbvt*							m_dynamicAabbTree;
+
+	///increment m_updateRevision when adding/removing/replacing child shapes, so that some caches can be updated
+	int								m_updateRevision;
+
+	btScalar	m_collisionMargin;
+
+protected:
+	btVector3	m_localScaling;
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btCompoundShape(bool enableDynamicAabbTree = true);
+
+	virtual ~btCompoundShape();
+
+	void	addChildShape(const btTransform& localTransform,btCollisionShape* shape);
+
+	/// Remove all children shapes that contain the specified shape
+	virtual void removeChildShape(btCollisionShape* shape);
+
+	void removeChildShapeByIndex(int childShapeindex);
+
+
+	int		getNumChildShapes() const
+	{
+		return int (m_children.size());
+	}
+
+	btCollisionShape* getChildShape(int index)
+	{
+		return m_children[index].m_childShape;
+	}
+	const btCollisionShape* getChildShape(int index) const
+	{
+		return m_children[index].m_childShape;
+	}
+
+	btTransform&	getChildTransform(int index)
+	{
+		return m_children[index].m_transform;
+	}
+	const btTransform&	getChildTransform(int index) const
+	{
+		return m_children[index].m_transform;
+	}
+
+	///set a new transform for a child, and update internal data structures (local aabb and dynamic tree)
+	void	updateChildTransform(int childIndex, const btTransform& newChildTransform);
+
+
+	btCompoundShapeChild* getChildList()
+	{
+		return &m_children[0];
+	}
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	virtual	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	/** Re-calculate the local Aabb. Is called at the end of removeChildShapes. 
+	Use this yourself if you modify the children or their transforms. */
+	virtual void recalculateLocalAabb(); 
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual const btVector3& getLocalScaling() const 
+	{
+		return m_localScaling;
+	}
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setMargin(btScalar margin)
+	{
+		m_collisionMargin = margin;
+	}
+	virtual btScalar	getMargin() const
+	{
+		return m_collisionMargin;
+	}
+	virtual const char*	getName()const
+	{
+		return "Compound";
+	}
+
+
+	btDbvt*							getDynamicAabbTree()
+	{
+		return m_dynamicAabbTree;
+	}
+
+	void createAabbTreeFromChildren();
+
+	///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+	///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform
+	///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound
+	///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+	///of the collision object by the principal transform.
+	void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const;
+
+	int	getUpdateRevision() const
+	{
+		return m_updateRevision;
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btCompoundShapeChildData
+{
+	btTransformFloatData	m_transform;
+	btCollisionShapeData	*m_childShape;
+	int						m_childShapeType;
+	float					m_childMargin;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCompoundShapeData
+{
+	btCollisionShapeData		m_collisionShapeData;
+
+	btCompoundShapeChildData	*m_childShapePtr;
+
+	int							m_numChildShapes;
+
+	float	m_collisionMargin;
+
+};
+
+
+SIMD_FORCE_INLINE	int	btCompoundShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCompoundShapeData);
+}
+
+
+
+
+
+
+
+#endif //COMPOUND_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
new file mode 100644
index 0000000..58ff84a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.cpp
@@ -0,0 +1,27 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btConcaveShape.h"
+
+btConcaveShape::btConcaveShape() : m_collisionMargin(btScalar(0.))
+{
+
+}
+
+btConcaveShape::~btConcaveShape()
+{
+
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
new file mode 100644
index 0000000..2a370a4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConcaveShape.h
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONCAVE_SHAPE_H
+#define CONCAVE_SHAPE_H
+
+#include "btCollisionShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "btTriangleCallback.h"
+
+/// PHY_ScalarType enumerates possible scalar types.
+/// See the btStridingMeshInterface or btHeightfieldTerrainShape for its use
+typedef enum PHY_ScalarType {
+	PHY_FLOAT,
+	PHY_DOUBLE,
+	PHY_INTEGER,
+	PHY_SHORT,
+	PHY_FIXEDPOINT88,
+	PHY_UCHAR
+} PHY_ScalarType;
+
+///The btConcaveShape class provides an interface for non-moving (static) concave shapes.
+///It has been implemented by the btStaticPlaneShape, btBvhTriangleMeshShape and btHeightfieldTerrainShape.
+class btConcaveShape : public btCollisionShape
+{
+protected:
+	btScalar m_collisionMargin;
+
+public:
+	btConcaveShape();
+
+	virtual ~btConcaveShape();
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const = 0;
+
+	virtual btScalar getMargin() const {
+		return m_collisionMargin;
+	}
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		m_collisionMargin = collisionMargin;
+	}
+
+
+
+};
+
+#endif //CONCAVE_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConeShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
new file mode 100644
index 0000000..dfa3f94
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConeShape.cpp
@@ -0,0 +1,133 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConeShape.h"
+
+
+
+btConeShape::btConeShape (btScalar radius,btScalar height): btConvexInternalShape (),
+m_radius (radius),
+m_height(height)
+{
+	m_shapeType = CONE_SHAPE_PROXYTYPE;
+	setConeUpIndex(1);
+	btVector3 halfExtents;
+	m_sinAngle = (m_radius / btSqrt(m_radius * m_radius + m_height * m_height));
+}
+
+btConeShapeZ::btConeShapeZ (btScalar radius,btScalar height):
+btConeShape(radius,height)
+{
+	setConeUpIndex(2);
+}
+
+btConeShapeX::btConeShapeX (btScalar radius,btScalar height):
+btConeShape(radius,height)
+{
+	setConeUpIndex(0);
+}
+
+///choose upAxis index
+void	btConeShape::setConeUpIndex(int upIndex)
+{
+	switch (upIndex)
+	{
+	case 0:
+			m_coneIndices[0] = 1;
+			m_coneIndices[1] = 0;
+			m_coneIndices[2] = 2;
+		break;
+	case 1:
+			m_coneIndices[0] = 0;
+			m_coneIndices[1] = 1;
+			m_coneIndices[2] = 2;
+		break;
+	case 2:
+			m_coneIndices[0] = 0;
+			m_coneIndices[1] = 2;
+			m_coneIndices[2] = 1;
+		break;
+	default:
+		btAssert(0);
+	};
+}
+
+btVector3 btConeShape::coneLocalSupport(const btVector3& v) const
+{
+	
+	btScalar halfHeight = m_height * btScalar(0.5);
+
+ if (v[m_coneIndices[1]] > v.length() * m_sinAngle)
+ {
+	btVector3 tmp;
+
+	tmp[m_coneIndices[0]] = btScalar(0.);
+	tmp[m_coneIndices[1]] = halfHeight;
+	tmp[m_coneIndices[2]] = btScalar(0.);
+	return tmp;
+ }
+  else {
+    btScalar s = btSqrt(v[m_coneIndices[0]] * v[m_coneIndices[0]] + v[m_coneIndices[2]] * v[m_coneIndices[2]]);
+    if (s > SIMD_EPSILON) {
+      btScalar d = m_radius / s;
+	  btVector3 tmp;
+	  tmp[m_coneIndices[0]] = v[m_coneIndices[0]] * d;
+	  tmp[m_coneIndices[1]] = -halfHeight;
+	  tmp[m_coneIndices[2]] = v[m_coneIndices[2]] * d;
+	  return tmp;
+    }
+    else  {
+		btVector3 tmp;
+		tmp[m_coneIndices[0]] = btScalar(0.);
+		tmp[m_coneIndices[1]] = -halfHeight;
+		tmp[m_coneIndices[2]] = btScalar(0.);
+		return tmp;
+	}
+  }
+
+}
+
+btVector3	btConeShape::localGetSupportingVertexWithoutMargin(const btVector3& vec) const
+{
+		return coneLocalSupport(vec);
+}
+
+void	btConeShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		const btVector3& vec = vectors[i];
+		supportVerticesOut[i] = coneLocalSupport(vec);
+	}
+}
+
+
+btVector3	btConeShape::localGetSupportingVertex(const btVector3& vec)  const
+{
+	btVector3 supVertex = coneLocalSupport(vec);
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConeShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConeShape.h
new file mode 100644
index 0000000..9766c7e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConeShape.h
@@ -0,0 +1,100 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONE_MINKOWSKI_H
+#define CONE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btConeShape implements a cone shape primitive, centered around the origin and aligned with the Y axis. The btConeShapeX is aligned around the X axis and btConeShapeZ around the Z axis.
+class btConeShape : public btConvexInternalShape
+
+{
+
+	btScalar m_sinAngle;
+	btScalar m_radius;
+	btScalar m_height;
+	int		m_coneIndices[3];
+	btVector3 coneLocalSupport(const btVector3& v) const;
+
+
+public:
+	btConeShape (btScalar radius,btScalar height);
+	
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec) const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	btScalar getRadius() const { return m_radius;}
+	btScalar getHeight() const { return m_height;}
+
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const
+	{
+		btTransform identity;
+		identity.setIdentity();
+		btVector3 aabbMin,aabbMax;
+		getAabb(identity,aabbMin,aabbMax);
+
+		btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+		btScalar margin = getMargin();
+
+		btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
+		btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
+		btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+		const btScalar x2 = lx*lx;
+		const btScalar y2 = ly*ly;
+		const btScalar z2 = lz*lz;
+		const btScalar scaledmass = mass * btScalar(0.08333333);
+
+		inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+//		inertia.x() = scaledmass * (y2+z2);
+//		inertia.y() = scaledmass * (x2+z2);
+//		inertia.z() = scaledmass * (x2+y2);
+	}
+
+
+		virtual const char*	getName()const 
+		{
+			return "Cone";
+		}
+		
+		///choose upAxis index
+		void	setConeUpIndex(int upIndex);
+		
+		int	getConeUpIndex() const
+		{
+			return m_coneIndices[1];
+		}
+};
+
+///btConeShape implements a Cone shape, around the X axis
+class btConeShapeX : public btConeShape
+{
+	public:
+		btConeShapeX(btScalar radius,btScalar height);
+};
+
+///btConeShapeZ implements a Cone shape, around the Z axis
+class btConeShapeZ : public btConeShape
+{
+	public:
+		btConeShapeZ(btScalar radius,btScalar height);
+};
+#endif //CONE_MINKOWSKI_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
new file mode 100644
index 0000000..10ea3e9
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.cpp
@@ -0,0 +1,92 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvex2dShape.h"
+
+btConvex2dShape::btConvex2dShape(	btConvexShape* convexChildShape):
+btConvexShape (), m_childConvexShape(convexChildShape)
+{
+	m_shapeType = CONVEX_2D_SHAPE_PROXYTYPE;
+}
+	
+btConvex2dShape::~btConvex2dShape()
+{
+}
+
+	
+
+btVector3	btConvex2dShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
+}
+
+void	btConvex2dShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+}
+
+
+btVector3	btConvex2dShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	return m_childConvexShape->localGetSupportingVertex(vec);
+}
+
+
+void	btConvex2dShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	///this linear upscaling is not realistic, but we don't deal with large mass ratios...
+	m_childConvexShape->calculateLocalInertia(mass,inertia);
+}
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btConvex2dShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	m_childConvexShape->getAabb(t,aabbMin,aabbMax);
+}
+
+void btConvex2dShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax);
+}
+
+void	btConvex2dShape::setLocalScaling(const btVector3& scaling) 
+{
+	m_childConvexShape->setLocalScaling(scaling);
+}
+
+const btVector3& btConvex2dShape::getLocalScaling() const
+{
+	return m_childConvexShape->getLocalScaling();
+}
+
+void	btConvex2dShape::setMargin(btScalar margin)
+{
+	m_childConvexShape->setMargin(margin);
+}
+btScalar	btConvex2dShape::getMargin() const
+{
+	return m_childConvexShape->getMargin();
+}
+
+int		btConvex2dShape::getNumPreferredPenetrationDirections() const
+{
+	return m_childConvexShape->getNumPreferredPenetrationDirections();
+}
+	
+void	btConvex2dShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+{
+	m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
new file mode 100644
index 0000000..58166c8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvex2dShape.h
@@ -0,0 +1,80 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_2D_SHAPE_H
+#define BT_CONVEX_2D_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btConvex2dShape allows to use arbitrary convex shapes are 2d convex shapes, with the Z component assumed to be 0.
+///For 2d boxes, the btBox2dShape is recommended.
+class btConvex2dShape : public btConvexShape
+{
+	btConvexShape*	m_childConvexShape;
+
+	public:
+	
+	btConvex2dShape(	btConvexShape* convexChildShape);
+	
+	virtual ~btConvex2dShape();
+	
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	btConvexShape*	getChildShape() 
+	{
+		return m_childConvexShape;
+	}
+
+	const btConvexShape*	getChildShape() const
+	{
+		return m_childConvexShape;
+	}
+
+	virtual const char*	getName()const 
+	{
+		return "Convex2dShape";
+	}
+	
+
+
+	///////////////////////////
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling) ;
+	virtual const btVector3& getLocalScaling() const ;
+
+	virtual void	setMargin(btScalar margin);
+	virtual btScalar	getMargin() const;
+
+	virtual int		getNumPreferredPenetrationDirections() const;
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+
+
+};
+
+#endif //BT_CONVEX_2D_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
new file mode 100644
index 0000000..69bc67c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.cpp
@@ -0,0 +1,211 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+
+btConvexHullShape ::btConvexHullShape (const btScalar* points,int numPoints,int stride) : btPolyhedralConvexAabbCachingShape ()
+{
+	m_shapeType = CONVEX_HULL_SHAPE_PROXYTYPE;
+	m_unscaledPoints.resize(numPoints);
+
+	unsigned char* pointsAddress = (unsigned char*)points;
+
+	for (int i=0;i<numPoints;i++)
+	{
+		btScalar* point = (btScalar*)pointsAddress;
+		m_unscaledPoints[i] = btVector3(point[0], point[1], point[2]);
+		pointsAddress += stride;
+	}
+
+	recalcLocalAabb();
+
+}
+
+
+
+void btConvexHullShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+	recalcLocalAabb();
+}
+
+void btConvexHullShape::addPoint(const btVector3& point)
+{
+	m_unscaledPoints.push_back(point);
+	recalcLocalAabb();
+
+}
+
+btVector3	btConvexHullShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+
+	for (int i=0;i<m_unscaledPoints.size();i++)
+	{
+		btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
+
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+	return supVec;
+}
+
+void	btConvexHullShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	btScalar newDot;
+	//use 'w' component of supportVerticesOut?
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+		}
+	}
+	for (int i=0;i<m_unscaledPoints.size();i++)
+	{
+		btVector3 vtx = getScaledPoint(i);
+
+		for (int j=0;j<numVectors;j++)
+		{
+			const btVector3& vec = vectors[j];
+			
+			newDot = vec.dot(vtx);
+			if (newDot > supportVerticesOut[j][3])
+			{
+				//WARNING: don't swap next lines, the w component would get overwritten!
+				supportVerticesOut[j] = vtx;
+				supportVerticesOut[j][3] = newDot;
+			}
+		}
+	}
+
+
+
+}
+	
+
+
+btVector3	btConvexHullShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
+
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int	btConvexHullShape::getNumVertices() const
+{
+	return m_unscaledPoints.size();
+}
+
+int btConvexHullShape::getNumEdges() const
+{
+	return m_unscaledPoints.size();
+}
+
+void btConvexHullShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+
+	int index0 = i%m_unscaledPoints.size();
+	int index1 = (i+1)%m_unscaledPoints.size();
+	pa = getScaledPoint(index0);
+	pb = getScaledPoint(index1);
+}
+
+void btConvexHullShape::getVertex(int i,btVector3& vtx) const
+{
+	vtx = getScaledPoint(i);
+}
+
+int	btConvexHullShape::getNumPlanes() const
+{
+	return 0;
+}
+
+void btConvexHullShape::getPlane(btVector3& ,btVector3& ,int ) const
+{
+
+	btAssert(0);
+}
+
+//not yet
+bool btConvexHullShape::isInside(const btVector3& ,btScalar ) const
+{
+	btAssert(0);
+	return false;
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btConvexHullShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	//int szc = sizeof(btConvexHullShapeData);
+	btConvexHullShapeData* shapeData = (btConvexHullShapeData*) dataBuffer;
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+	int numElem = m_unscaledPoints.size();
+	shapeData->m_numUnscaledPoints = numElem;
+#ifdef BT_USE_DOUBLE_PRECISION
+	shapeData->m_unscaledPointsFloatPtr = 0;
+	shapeData->m_unscaledPointsDoublePtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]):  0;
+#else
+	shapeData->m_unscaledPointsFloatPtr = numElem ? (btVector3Data*)serializer->getUniquePointer((void*)&m_unscaledPoints[0]):  0;
+	shapeData->m_unscaledPointsDoublePtr = 0;
+#endif
+	
+	if (numElem)
+	{
+		int sz = sizeof(btVector3Data);
+	//	int sz2 = sizeof(btVector3DoubleData);
+	//	int sz3 = sizeof(btVector3FloatData);
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btVector3Data* memPtr = (btVector3Data*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			m_unscaledPoints[i].serialize(*memPtr);
+		}
+		serializer->finalizeChunk(chunk,btVector3DataName,BT_ARRAY_CODE,(void*)&m_unscaledPoints[0]);
+	}
+	
+	return "btConvexHullShapeData";
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
new file mode 100644
index 0000000..bf960f4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexHullShape.h
@@ -0,0 +1,120 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONVEX_HULL_SHAPE_H
+#define CONVEX_HULL_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+///The btConvexHullShape implements an implicit convex hull of an array of vertices.
+///Bullet provides a general and fast collision detector for convex shapes based on GJK and EPA using localGetSupportingVertex.
+ATTRIBUTE_ALIGNED16(class) btConvexHullShape : public btPolyhedralConvexAabbCachingShape
+{
+	btAlignedObjectArray<btVector3>	m_unscaledPoints;
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	
+	///this constructor optionally takes in a pointer to points. Each point is assumed to be 3 consecutive btScalar (x,y,z), the striding defines the number of bytes between each point, in memory.
+	///It is easier to not pass any points in the constructor, and just add one point at a time, using addPoint.
+	///btConvexHullShape make an internal copy of the points.
+	btConvexHullShape(const btScalar* points=0,int numPoints=0, int stride=sizeof(btVector3));
+
+	void addPoint(const btVector3& point);
+
+	
+	btVector3* getUnscaledPoints()
+	{
+		return &m_unscaledPoints[0];
+	}
+
+	const btVector3* getUnscaledPoints() const
+	{
+		return &m_unscaledPoints[0];
+	}
+
+	///getPoints is obsolete, please use getUnscaledPoints
+	const btVector3* getPoints() const
+	{
+		return getUnscaledPoints();
+	}
+
+	
+
+
+	SIMD_FORCE_INLINE	btVector3 getScaledPoint(int i) const
+	{
+		return m_unscaledPoints[i] * m_localScaling;
+	}
+
+	SIMD_FORCE_INLINE	int getNumPoints() const 
+	{
+		return m_unscaledPoints.size();
+	}
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+
+
+	//debugging
+	virtual const char*	getName()const {return "Convex";}
+
+	
+	virtual int	getNumVertices() const;
+	virtual int getNumEdges() const;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	virtual void getVertex(int i,btVector3& vtx) const;
+	virtual int	getNumPlanes() const;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+	///in case we receive negative scaling
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btConvexHullShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	btVector3FloatData	*m_unscaledPointsFloatPtr;
+	btVector3DoubleData	*m_unscaledPointsDoublePtr;
+
+	int		m_numUnscaledPoints;
+	char m_padding3[4];
+
+};
+
+
+SIMD_FORCE_INLINE	int	btConvexHullShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btConvexHullShapeData);
+}
+
+
+#endif //CONVEX_HULL_SHAPE_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
new file mode 100644
index 0000000..083d60b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.cpp
@@ -0,0 +1,151 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btConvexInternalShape.h"
+
+
+
+btConvexInternalShape::btConvexInternalShape()
+: m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)),
+m_collisionMargin(CONVEX_DISTANCE_MARGIN)
+{
+}
+
+
+void	btConvexInternalShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling.absolute();
+}
+
+
+
+void	btConvexInternalShape::getAabbSlow(const btTransform& trans,btVector3&minAabb,btVector3&maxAabb) const
+{
+#ifndef __SPU__
+	//use localGetSupportingVertexWithoutMargin?
+	btScalar margin = getMargin();
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+
+		btVector3 sv = localGetSupportingVertex(vec*trans.getBasis());
+
+		btVector3 tmp = trans(sv);
+		maxAabb[i] = tmp[i]+margin;
+		vec[i] = btScalar(-1.);
+		tmp = trans(localGetSupportingVertex(vec*trans.getBasis()));
+		minAabb[i] = tmp[i]-margin;
+	}
+#endif
+}
+
+
+
+btVector3	btConvexInternalShape::localGetSupportingVertex(const btVector3& vec)const
+{
+#ifndef __SPU__
+
+	 btVector3	supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+
+#else
+	btAssert(0);
+	return btVector3(0,0,0);
+#endif //__SPU__
+
+ }
+
+
+btConvexInternalAabbCachingShape::btConvexInternalAabbCachingShape()
+	:	btConvexInternalShape(),
+m_localAabbMin(1,1,1),
+m_localAabbMax(-1,-1,-1),
+m_isLocalAabbValid(false)
+{
+}
+
+
+void btConvexInternalAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+}
+
+void	btConvexInternalAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+	btConvexInternalShape::setLocalScaling(scaling);
+	recalcLocalAabb();
+}
+
+
+void	btConvexInternalAabbCachingShape::recalcLocalAabb()
+{
+	m_isLocalAabbValid = true;
+	
+	#if 1
+	static const btVector3 _directions[] =
+	{
+		btVector3( 1.,  0.,  0.),
+		btVector3( 0.,  1.,  0.),
+		btVector3( 0.,  0.,  1.),
+		btVector3( -1., 0.,  0.),
+		btVector3( 0., -1.,  0.),
+		btVector3( 0.,  0., -1.)
+	};
+	
+	btVector3 _supporting[] =
+	{
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.)
+	};
+	
+	batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+	
+	for ( int i = 0; i < 3; ++i )
+	{
+		m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
+		m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+	}
+	
+	#else
+
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+		btVector3 tmp = localGetSupportingVertex(vec);
+		m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+		vec[i] = btScalar(-1.);
+		tmp = localGetSupportingVertex(vec);
+		m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+	}
+	#endif
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
new file mode 100644
index 0000000..1252773
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexInternalShape.h
@@ -0,0 +1,202 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_INTERNAL_SHAPE_H
+#define BT_CONVEX_INTERNAL_SHAPE_H
+
+#include "btConvexShape.h"
+#include "LinearMath/btAabbUtil2.h"
+
+
+///The btConvexInternalShape is an internal base class, shared by most convex shape implementations.
+class btConvexInternalShape : public btConvexShape
+{
+
+	protected:
+
+	//local scaling. collisionMargin is not scaled !
+	btVector3	m_localScaling;
+
+	btVector3	m_implicitShapeDimensions;
+	
+	btScalar	m_collisionMargin;
+
+	btScalar	m_padding;
+
+	btConvexInternalShape();
+
+public:
+
+	
+
+	virtual ~btConvexInternalShape()
+	{
+
+	}
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+
+	const btVector3& getImplicitShapeDimensions() const
+	{
+		return m_implicitShapeDimensions;
+	}
+
+	///warning: use setImplicitShapeDimensions with care
+	///changing a collision shape while the body is in the world is not recommended,
+	///it is best to remove the body from the world, then make the change, and re-add it
+	///alternatively flush the contact points, see documentation for 'cleanProxyFromPairs'
+	void	setImplicitShapeDimensions(const btVector3& dimensions)
+	{
+		m_implicitShapeDimensions = dimensions;
+	}
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+	{
+		getAabbSlow(t,aabbMin,aabbMax);
+	}
+
+
+	
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const 
+	{
+		return m_localScaling;
+	}
+
+	const btVector3& getLocalScalingNV() const 
+	{
+		return m_localScaling;
+	}
+
+	virtual void	setMargin(btScalar margin)
+	{
+		m_collisionMargin = margin;
+	}
+	virtual btScalar	getMargin() const
+	{
+		return m_collisionMargin;
+	}
+
+	btScalar	getMarginNV() const
+	{
+		return m_collisionMargin;
+	}
+
+	virtual int		getNumPreferredPenetrationDirections() const
+	{
+		return 0;
+	}
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+	{
+		(void)penetrationVector;
+		(void)index;
+		btAssert(0);
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btConvexInternalShapeData
+{
+	btCollisionShapeData	m_collisionShapeData;
+
+	btVector3FloatData	m_localScaling;
+
+	btVector3FloatData	m_implicitShapeDimensions;
+	
+	float			m_collisionMargin;
+
+	int	m_padding;
+
+};
+
+
+
+SIMD_FORCE_INLINE	int	btConvexInternalShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btConvexInternalShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btConvexInternalShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btConvexInternalShapeData* shapeData = (btConvexInternalShapeData*) dataBuffer;
+	btCollisionShape::serialize(&shapeData->m_collisionShapeData, serializer);
+
+	m_implicitShapeDimensions.serializeFloat(shapeData->m_implicitShapeDimensions);
+	m_localScaling.serializeFloat(shapeData->m_localScaling);
+	shapeData->m_collisionMargin = float(m_collisionMargin);
+
+	return "btConvexInternalShapeData";
+}
+
+
+
+
+///btConvexInternalAabbCachingShape adds local aabb caching for convex shapes, to avoid expensive bounding box calculations
+class btConvexInternalAabbCachingShape : public btConvexInternalShape
+{
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	bool		m_isLocalAabbValid;
+	
+protected:
+					
+	btConvexInternalAabbCachingShape();
+	
+	void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+	{
+		m_isLocalAabbValid = true;
+		m_localAabbMin = aabbMin;
+		m_localAabbMax = aabbMax;
+	}
+
+	inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+	{
+		btAssert(m_isLocalAabbValid);
+		aabbMin = m_localAabbMin;
+		aabbMax = m_localAabbMax;
+	}
+
+	inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+	{
+
+		//lazy evaluation of local aabb
+		btAssert(m_isLocalAabbValid);
+		btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+	}
+		
+public:
+		
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	void	recalcLocalAabb();
+
+};
+
+#endif //BT_CONVEX_INTERNAL_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
new file mode 100644
index 0000000..c1b155a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.cpp
@@ -0,0 +1,157 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexPointCloudShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+void btConvexPointCloudShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+	recalcLocalAabb();
+}
+
+#ifndef __SPU__
+btVector3	btConvexPointCloudShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+
+	for (int i=0;i<m_numPoints;i++)
+	{
+		btVector3 vtx = getScaledPoint(i);
+
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+	return supVec;
+}
+
+void	btConvexPointCloudShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	btScalar newDot;
+	//use 'w' component of supportVerticesOut?
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+		}
+	}
+	for (int i=0;i<m_numPoints;i++)
+	{
+		btVector3 vtx = getScaledPoint(i);
+
+		for (int j=0;j<numVectors;j++)
+		{
+			const btVector3& vec = vectors[j];
+			
+			newDot = vec.dot(vtx);
+			if (newDot > supportVerticesOut[j][3])
+			{
+				//WARNING: don't swap next lines, the w component would get overwritten!
+				supportVerticesOut[j] = vtx;
+				supportVerticesOut[j][3] = newDot;
+			}
+		}
+	}
+
+
+
+}
+	
+
+
+btVector3	btConvexPointCloudShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
+#endif
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexHullShape with the Raytracer Demo
+int	btConvexPointCloudShape::getNumVertices() const
+{
+	return m_numPoints;
+}
+
+int btConvexPointCloudShape::getNumEdges() const
+{
+	return 0;
+}
+
+void btConvexPointCloudShape::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+	btAssert (0);
+}
+
+void btConvexPointCloudShape::getVertex(int i,btVector3& vtx) const
+{
+	vtx = m_unscaledPoints[i]*m_localScaling;
+}
+
+int	btConvexPointCloudShape::getNumPlanes() const
+{
+	return 0;
+}
+
+void btConvexPointCloudShape::getPlane(btVector3& ,btVector3& ,int ) const
+{
+
+	btAssert(0);
+}
+
+//not yet
+bool btConvexPointCloudShape::isInside(const btVector3& ,btScalar ) const
+{
+	btAssert(0);
+	return false;
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
new file mode 100644
index 0000000..54b5afa
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexPointCloudShape.h
@@ -0,0 +1,105 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_CONVEX_POINT_CLOUD_SHAPE_H
+#define BT_CONVEX_POINT_CLOUD_SHAPE_H
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btConvexPointCloudShape implements an implicit convex hull of an array of vertices.
+ATTRIBUTE_ALIGNED16(class) btConvexPointCloudShape : public btPolyhedralConvexAabbCachingShape
+{
+	btVector3* m_unscaledPoints;
+	int m_numPoints;
+
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btConvexPointCloudShape()
+	{
+		m_localScaling.setValue(1.f,1.f,1.f);
+		m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+		m_unscaledPoints = 0;
+		m_numPoints = 0;
+	}
+
+	btConvexPointCloudShape(btVector3* points,int numPoints, const btVector3& localScaling,bool computeAabb = true)
+	{
+		m_localScaling = localScaling;
+		m_shapeType = CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE;
+		m_unscaledPoints = points;
+		m_numPoints = numPoints;
+
+		if (computeAabb)
+			recalcLocalAabb();
+	}
+
+	void setPoints (btVector3* points, int numPoints, bool computeAabb = true,const btVector3& localScaling=btVector3(1.f,1.f,1.f))
+	{
+		m_unscaledPoints = points;
+		m_numPoints = numPoints;
+		m_localScaling = localScaling;
+
+		if (computeAabb)
+			recalcLocalAabb();
+	}
+
+	SIMD_FORCE_INLINE	btVector3* getUnscaledPoints()
+	{
+		return m_unscaledPoints;
+	}
+
+	SIMD_FORCE_INLINE	const btVector3* getUnscaledPoints() const
+	{
+		return m_unscaledPoints;
+	}
+
+	SIMD_FORCE_INLINE	int getNumPoints() const 
+	{
+		return m_numPoints;
+	}
+
+	SIMD_FORCE_INLINE	btVector3	getScaledPoint( int index) const
+	{
+		return m_unscaledPoints[index] * m_localScaling;
+	}
+
+#ifndef __SPU__
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+#endif
+
+
+	//debugging
+	virtual const char*	getName()const {return "ConvexPointCloud";}
+
+	virtual int	getNumVertices() const;
+	virtual int getNumEdges() const;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	virtual void getVertex(int i,btVector3& vtx) const;
+	virtual int	getNumPlanes() const;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+	///in case we receive negative scaling
+	virtual void	setLocalScaling(const btVector3& scaling);
+};
+
+
+#endif //BT_CONVEX_POINT_CLOUD_SHAPE_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
new file mode 100644
index 0000000..f5f3aa5
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexShape.cpp
@@ -0,0 +1,429 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexShape.h"
+#include "btTriangleShape.h"
+#include "btSphereShape.h"
+#include "btCylinderShape.h"
+#include "btCapsuleShape.h"
+#include "btConvexHullShape.h"
+#include "btConvexPointCloudShape.h"
+
+///not supported on IBM SDK, until we fix the alignment of btVector3
+#if defined (__CELLOS_LV2__) && defined (__SPU__)
+#include <spu_intrinsics.h>
+static inline vec_float4 vec_dot3( vec_float4 vec0, vec_float4 vec1 )
+{
+    vec_float4 result;
+    result = spu_mul( vec0, vec1 );
+    result = spu_madd( spu_rlqwbyte( vec0, 4 ), spu_rlqwbyte( vec1, 4 ), result );
+    return spu_madd( spu_rlqwbyte( vec0, 8 ), spu_rlqwbyte( vec1, 8 ), result );
+}
+#endif //__SPU__
+
+btConvexShape::btConvexShape ()
+{
+}
+
+btConvexShape::~btConvexShape()
+{
+
+}
+
+
+
+static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
+{	
+
+	btVector3 vec = localDirOrg * localScaling;
+
+#if defined (__CELLOS_LV2__) && defined (__SPU__)
+
+	btVector3 localDir = vec;
+
+	vec_float4 v_distMax = {-FLT_MAX,0,0,0};
+	vec_int4 v_idxMax = {-999,0,0,0};
+	int v=0;
+	int numverts = numPoints;
+
+	for(;v<(int)numverts-4;v+=4) {
+		vec_float4 p0 = vec_dot3(points[v  ].get128(),localDir.get128());
+		vec_float4 p1 = vec_dot3(points[v+1].get128(),localDir.get128());
+		vec_float4 p2 = vec_dot3(points[v+2].get128(),localDir.get128());
+		vec_float4 p3 = vec_dot3(points[v+3].get128(),localDir.get128());
+		const vec_int4 i0 = {v  ,0,0,0};
+		const vec_int4 i1 = {v+1,0,0,0};
+		const vec_int4 i2 = {v+2,0,0,0};
+		const vec_int4 i3 = {v+3,0,0,0};
+		vec_uint4  retGt01 = spu_cmpgt(p0,p1);
+		vec_float4 pmax01 = spu_sel(p1,p0,retGt01);
+		vec_int4   imax01 = spu_sel(i1,i0,retGt01);
+		vec_uint4  retGt23 = spu_cmpgt(p2,p3);
+		vec_float4 pmax23 = spu_sel(p3,p2,retGt23);
+		vec_int4   imax23 = spu_sel(i3,i2,retGt23);
+		vec_uint4  retGt0123 = spu_cmpgt(pmax01,pmax23);
+		vec_float4 pmax0123 = spu_sel(pmax23,pmax01,retGt0123);
+		vec_int4   imax0123 = spu_sel(imax23,imax01,retGt0123);
+		vec_uint4  retGtMax = spu_cmpgt(v_distMax,pmax0123);
+		v_distMax = spu_sel(pmax0123,v_distMax,retGtMax);
+		v_idxMax = spu_sel(imax0123,v_idxMax,retGtMax);
+	}
+	for(;v<(int)numverts;v++) {
+		vec_float4 p = vec_dot3(points[v].get128(),localDir.get128());
+		const vec_int4 i = {v,0,0,0};
+		vec_uint4  retGtMax = spu_cmpgt(v_distMax,p);
+		v_distMax = spu_sel(p,v_distMax,retGtMax);
+		v_idxMax = spu_sel(i,v_idxMax,retGtMax);
+	}
+	int ptIndex = spu_extract(v_idxMax,0);
+	const btVector3& supVec= points[ptIndex] * localScaling;
+	return supVec;
+#else
+
+	btScalar newDot,maxDot = btScalar(-BT_LARGE_FLOAT);
+	int ptIndex = -1;
+
+	for (int i=0;i<numPoints;i++)
+	{
+
+		newDot = vec.dot(points[i]);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			ptIndex = i;
+		}
+	}
+	btAssert(ptIndex >= 0);
+	btVector3 supVec = points[ptIndex] * localScaling;
+	return supVec;
+#endif //__SPU__
+}
+
+btVector3 btConvexShape::localGetSupportVertexWithoutMarginNonVirtual (const btVector3& localDir) const
+{
+	switch (m_shapeType)
+	{
+    case SPHERE_SHAPE_PROXYTYPE:
+	{
+		return btVector3(0,0,0);
+    }
+	case BOX_SHAPE_PROXYTYPE:
+	{
+		btBoxShape* convexShape = (btBoxShape*)this;
+		const btVector3& halfExtents = convexShape->getImplicitShapeDimensions();
+
+		return btVector3(btFsels(localDir.x(), halfExtents.x(), -halfExtents.x()),
+			btFsels(localDir.y(), halfExtents.y(), -halfExtents.y()),
+			btFsels(localDir.z(), halfExtents.z(), -halfExtents.z()));
+	}
+	case TRIANGLE_SHAPE_PROXYTYPE:
+	{
+		btTriangleShape* triangleShape = (btTriangleShape*)this;
+		btVector3 dir(localDir.getX(),localDir.getY(),localDir.getZ());
+		btVector3* vertices = &triangleShape->m_vertices1[0];
+		btVector3 dots(dir.dot(vertices[0]), dir.dot(vertices[1]), dir.dot(vertices[2]));
+		btVector3 sup = vertices[dots.maxAxis()];
+		return btVector3(sup.getX(),sup.getY(),sup.getZ());
+	}
+	case CYLINDER_SHAPE_PROXYTYPE:
+	{
+		btCylinderShape* cylShape = (btCylinderShape*)this;
+		//mapping of halfextents/dimension onto radius/height depends on how cylinder local orientation is (upAxis)
+
+		btVector3 halfExtents = cylShape->getImplicitShapeDimensions();
+		btVector3 v(localDir.getX(),localDir.getY(),localDir.getZ());
+		int cylinderUpAxis = cylShape->getUpAxis();
+		int XX(1),YY(0),ZZ(2);
+
+		switch (cylinderUpAxis)
+		{
+		case 0:
+		{
+			XX = 1;
+			YY = 0;
+			ZZ = 2;
+		}
+		break;
+		case 1:
+		{
+			XX = 0;
+			YY = 1;
+			ZZ = 2;	
+		}
+		break;
+		case 2:
+		{
+			XX = 0;
+			YY = 2;
+			ZZ = 1;
+			
+		}
+		break;
+		default:
+			btAssert(0);
+		break;
+		};
+
+		btScalar radius = halfExtents[XX];
+		btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+		btVector3 tmp;
+		btScalar d ;
+
+		btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+		if (s != btScalar(0.0))
+		{
+			d = radius / s;  
+			tmp[XX] = v[XX] * d;
+			tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+			tmp[ZZ] = v[ZZ] * d;
+			return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
+		} else {
+			tmp[XX] = radius;
+			tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+			tmp[ZZ] = btScalar(0.0);
+			return btVector3(tmp.getX(),tmp.getY(),tmp.getZ());
+		}
+	}
+	case CAPSULE_SHAPE_PROXYTYPE:
+	{
+		btVector3 vec0(localDir.getX(),localDir.getY(),localDir.getZ());
+
+		btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+		btScalar halfHeight = capsuleShape->getHalfHeight();
+		int capsuleUpAxis = capsuleShape->getUpAxis();
+
+		btScalar radius = capsuleShape->getRadius();
+		btVector3 supVec(0,0,0);
+
+		btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+		btVector3 vec = vec0;
+		btScalar lenSqr = vec.length2();
+		if (lenSqr < btScalar(0.0001))
+		{
+			vec.setValue(1,0,0);
+		} else
+		{
+			btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+			vec *= rlen;
+		}
+		btVector3 vtx;
+		btScalar newDot;
+		{
+			btVector3 pos(0,0,0);
+			pos[capsuleUpAxis] = halfHeight;
+
+			//vtx = pos +vec*(radius);
+			vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV();
+			newDot = vec.dot(vtx);
+			
+
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supVec = vtx;
+			}
+		}
+		{
+			btVector3 pos(0,0,0);
+			pos[capsuleUpAxis] = -halfHeight;
+
+			//vtx = pos +vec*(radius);
+			vtx = pos +vec*capsuleShape->getLocalScalingNV()*(radius) - vec * capsuleShape->getMarginNV();
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supVec = vtx;
+			}
+		}
+		return btVector3(supVec.getX(),supVec.getY(),supVec.getZ());	
+	}
+	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+	{
+		btConvexPointCloudShape* convexPointCloudShape = (btConvexPointCloudShape*)this;
+		btVector3* points = convexPointCloudShape->getUnscaledPoints ();
+		int numPoints = convexPointCloudShape->getNumPoints ();
+		return convexHullSupport (localDir, points, numPoints,convexPointCloudShape->getLocalScalingNV());
+	}
+	case CONVEX_HULL_SHAPE_PROXYTYPE:
+	{
+		btConvexHullShape* convexHullShape = (btConvexHullShape*)this;
+		btVector3* points = convexHullShape->getUnscaledPoints();
+		int numPoints = convexHullShape->getNumPoints ();
+		return convexHullSupport (localDir, points, numPoints,convexHullShape->getLocalScalingNV());
+	}
+    default:
+#ifndef __SPU__
+		return this->localGetSupportingVertexWithoutMargin (localDir);
+#else
+		btAssert (0);
+#endif
+	}
+
+	// should never reach here
+	btAssert (0);
+	return btVector3 (btScalar(0.0f), btScalar(0.0f), btScalar(0.0f));
+}
+
+btVector3 btConvexShape::localGetSupportVertexNonVirtual (const btVector3& localDir) const
+{
+	btVector3 localDirNorm = localDir;
+	if (localDirNorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		localDirNorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+	}
+	localDirNorm.normalize ();
+
+	return localGetSupportVertexWithoutMarginNonVirtual(localDirNorm)+ getMarginNonVirtual() * localDirNorm;
+}
+
+/* TODO: This should be bumped up to btCollisionShape () */
+btScalar btConvexShape::getMarginNonVirtual () const
+{
+	switch (m_shapeType)
+	{
+    case SPHERE_SHAPE_PROXYTYPE:
+	{
+		btSphereShape* sphereShape = (btSphereShape*)this;
+		return sphereShape->getRadius ();
+	}
+	case BOX_SHAPE_PROXYTYPE:
+	{
+		btBoxShape* convexShape = (btBoxShape*)this;
+		return convexShape->getMarginNV ();
+	}
+	case TRIANGLE_SHAPE_PROXYTYPE:
+	{
+		btTriangleShape* triangleShape = (btTriangleShape*)this;
+		return triangleShape->getMarginNV ();
+	}
+	case CYLINDER_SHAPE_PROXYTYPE:
+	{
+		btCylinderShape* cylShape = (btCylinderShape*)this;
+		return cylShape->getMarginNV();
+	}
+	case CAPSULE_SHAPE_PROXYTYPE:
+	{
+		btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+		return capsuleShape->getMarginNV();
+	}
+	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+	/* fall through */
+	case CONVEX_HULL_SHAPE_PROXYTYPE:
+	{
+		btPolyhedralConvexShape* convexHullShape = (btPolyhedralConvexShape*)this;
+		return convexHullShape->getMarginNV();
+	}
+    default:
+#ifndef __SPU__
+		return this->getMargin ();
+#else
+		btAssert (0);
+#endif
+	}
+
+	// should never reach here
+	btAssert (0);
+	return btScalar(0.0f);
+}
+#ifndef __SPU__
+void btConvexShape::getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
+{
+	switch (m_shapeType)
+	{
+    case SPHERE_SHAPE_PROXYTYPE:
+	{
+		btSphereShape* sphereShape = (btSphereShape*)this;
+		btScalar radius = sphereShape->getImplicitShapeDimensions().getX();// * convexShape->getLocalScaling().getX();
+		btScalar margin = radius + sphereShape->getMarginNonVirtual();
+		const btVector3& center = t.getOrigin();
+		btVector3 extent(margin,margin,margin);
+		aabbMin = center - extent;
+		aabbMax = center + extent;
+    }
+	break;
+	case CYLINDER_SHAPE_PROXYTYPE:
+	/* fall through */
+	case BOX_SHAPE_PROXYTYPE:
+	{
+		btBoxShape* convexShape = (btBoxShape*)this;
+		btScalar margin=convexShape->getMarginNonVirtual();
+		btVector3 halfExtents = convexShape->getImplicitShapeDimensions();
+		halfExtents += btVector3(margin,margin,margin);
+		btMatrix3x3 abs_b = t.getBasis().absolute();  
+		btVector3 center = t.getOrigin();
+		btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));
+		
+		aabbMin = center - extent;
+		aabbMax = center + extent;
+		break;
+	}
+	case TRIANGLE_SHAPE_PROXYTYPE:
+	{
+		btTriangleShape* triangleShape = (btTriangleShape*)this;
+		btScalar margin = triangleShape->getMarginNonVirtual();
+		for (int i=0;i<3;i++)
+		{
+			btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+			vec[i] = btScalar(1.);
+
+			btVector3 sv = localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis());
+
+			btVector3 tmp = t(sv);
+			aabbMax[i] = tmp[i]+margin;
+			vec[i] = btScalar(-1.);
+			tmp = t(localGetSupportVertexWithoutMarginNonVirtual(vec*t.getBasis()));
+			aabbMin[i] = tmp[i]-margin;
+		}	
+	}
+	break;
+	case CAPSULE_SHAPE_PROXYTYPE:
+	{
+		btCapsuleShape* capsuleShape = (btCapsuleShape*)this;
+		btVector3 halfExtents(capsuleShape->getRadius(),capsuleShape->getRadius(),capsuleShape->getRadius());
+		int m_upAxis = capsuleShape->getUpAxis();
+		halfExtents[m_upAxis] = capsuleShape->getRadius() + capsuleShape->getHalfHeight();
+		halfExtents += btVector3(capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual(),capsuleShape->getMarginNonVirtual());
+		btMatrix3x3 abs_b = t.getBasis().absolute();  
+		btVector3 center = t.getOrigin();
+		btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents));		  	
+		aabbMin = center - extent;
+		aabbMax = center + extent;
+	}
+	break;
+	case CONVEX_POINT_CLOUD_SHAPE_PROXYTYPE:
+	case CONVEX_HULL_SHAPE_PROXYTYPE:
+	{
+		btPolyhedralConvexAabbCachingShape* convexHullShape = (btPolyhedralConvexAabbCachingShape*)this;
+		btScalar margin = convexHullShape->getMarginNonVirtual();
+		convexHullShape->getNonvirtualAabb (t, aabbMin, aabbMax, margin);
+	}
+	break;
+    default:
+#ifndef __SPU__
+		this->getAabb (t, aabbMin, aabbMax);
+#else
+		btAssert (0);
+#endif
+	break;
+	}
+
+	// should never reach here
+	btAssert (0);
+}
+
+#endif //__SPU__
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexShape.h
new file mode 100644
index 0000000..9c15825
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexShape.h
@@ -0,0 +1,82 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CONVEX_SHAPE_INTERFACE1
+#define CONVEX_SHAPE_INTERFACE1
+
+#include "btCollisionShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+#define MAX_PREFERRED_PENETRATION_DIRECTIONS 10
+
+/// The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape, btConvexHullShape etc.
+/// It describes general convex shapes using the localGetSupportingVertex interface, used by collision detectors such as btGjkPairDetector.
+ATTRIBUTE_ALIGNED16(class) btConvexShape : public btCollisionShape
+{
+
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btConvexShape ();
+
+	virtual ~btConvexShape();
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const = 0;
+
+	////////
+	#ifndef __SPU__
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec) const=0;
+	#endif //#ifndef __SPU__
+
+	btVector3 localGetSupportVertexWithoutMarginNonVirtual (const btVector3& vec) const;
+	btVector3 localGetSupportVertexNonVirtual (const btVector3& vec) const;
+	btScalar getMarginNonVirtual () const;
+	void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
+
+	
+	//notice that the vectors should be unit length
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const =0;
+
+	virtual void	setLocalScaling(const btVector3& scaling) =0;
+	virtual const btVector3& getLocalScaling() const =0;
+
+	virtual void	setMargin(btScalar margin)=0;
+
+	virtual btScalar	getMargin() const=0;
+
+	virtual int		getNumPreferredPenetrationDirections() const=0;
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const=0;
+
+
+	
+	
+};
+
+
+
+#endif //CONVEX_SHAPE_INTERFACE1
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
new file mode 100644
index 0000000..0f9ced5
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp
@@ -0,0 +1,315 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
+
+
+btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
+: btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
+{
+	m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
+	if ( calcAabb )
+		recalcLocalAabb();
+}
+
+
+
+
+///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
+///but then we are duplicating
+class LocalSupportVertexCallback: public btInternalTriangleIndexCallback
+{
+
+	btVector3 m_supportVertexLocal;
+public:
+
+	btScalar m_maxDot;
+	btVector3 m_supportVecLocal;
+
+	LocalSupportVertexCallback(const btVector3& supportVecLocal)
+		: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)),
+		m_maxDot(btScalar(-BT_LARGE_FLOAT)),
+                m_supportVecLocal(supportVecLocal)
+	{
+	}
+
+	virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+	{
+		(void)triangleIndex;
+		(void)partId;
+
+		for (int i=0;i<3;i++)
+		{
+			btScalar dot = m_supportVecLocal.dot(triangle[i]);
+			if (dot > m_maxDot)
+			{
+				m_maxDot = dot;
+				m_supportVertexLocal = triangle[i];
+			}
+		}
+	}
+	
+	btVector3	GetSupportVertexLocal()
+	{
+		return m_supportVertexLocal;
+	}
+
+};
+
+
+
+
+
+btVector3	btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	LocalSupportVertexCallback	supportCallback(vec);
+	btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+	supVec = supportCallback.GetSupportVertexLocal();
+
+	return supVec;
+}
+
+void	btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	//use 'w' component of supportVerticesOut?
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+		}
+	}
+	
+	///@todo: could do the batch inside the callback!
+
+
+	for (int j=0;j<numVectors;j++)
+	{
+		const btVector3& vec = vectors[j];
+		LocalSupportVertexCallback	supportCallback(vec);
+		btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+		m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
+		supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
+	}
+	
+}
+	
+
+
+btVector3	btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	if ( getMargin()!=btScalar(0.) )
+	{
+		btVector3 vecnorm = vec;
+		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+		{
+			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+		} 
+		vecnorm.normalize();
+		supVertex+= getMargin() * vecnorm;
+	}
+	return supVertex;
+}
+
+
+
+
+
+
+
+
+
+//currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
+//Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
+int	btConvexTriangleMeshShape::getNumVertices() const
+{
+	//cache this?
+	return 0;
+	
+}
+
+int btConvexTriangleMeshShape::getNumEdges() const
+{
+	return 0;
+}
+
+void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const
+{
+	btAssert(0);	
+}
+
+void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const
+{
+	btAssert(0);
+}
+
+int	btConvexTriangleMeshShape::getNumPlanes() const
+{
+	return 0;
+}
+
+void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int  ) const
+{
+	btAssert(0);
+}
+
+//not yet
+bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const
+{
+	btAssert(0);
+	return false;
+}
+
+
+
+void	btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+	m_stridingMesh->setScaling(scaling);
+	
+	recalcLocalAabb();
+	
+}
+
+
+const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
+{
+	return m_stridingMesh->getScaling();
+}
+
+void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
+{
+   class CenterCallback: public btInternalTriangleIndexCallback
+   {
+      bool first;
+      btVector3 ref;
+      btVector3 sum;
+      btScalar volume;
+
+   public:
+
+      CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
+      {
+      }
+
+      virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+      {
+         (void) triangleIndex;
+         (void) partId;
+         if (first)
+         {
+            ref = triangle[0];
+            first = false;
+         }
+         else
+         {
+            btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
+            sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
+            volume += vol;
+         }
+      }
+      
+      btVector3 getCenter()
+      {
+         return (volume > 0) ? sum / volume : ref;
+      }
+
+      btScalar getVolume()
+      {
+         return volume * btScalar(1. / 6);
+      }
+
+   };
+
+   class InertiaCallback: public btInternalTriangleIndexCallback
+   {
+      btMatrix3x3 sum;
+      btVector3 center;
+
+   public:
+
+      InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
+      {
+      }
+
+      virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
+      {
+         (void) triangleIndex;
+         (void) partId;
+         btMatrix3x3 i;
+         btVector3 a = triangle[0] - center;
+         btVector3 b = triangle[1] - center;
+         btVector3 c = triangle[2] - center;
+         btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
+         for (int j = 0; j < 3; j++)
+         {
+            for (int k = 0; k <= j; k++)
+            {
+               i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
+                  + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
+            }
+         }
+         btScalar i00 = -i[0][0];
+         btScalar i11 = -i[1][1];
+         btScalar i22 = -i[2][2];
+         i[0][0] = i11 + i22; 
+         i[1][1] = i22 + i00; 
+         i[2][2] = i00 + i11;
+         sum[0] += i[0];
+         sum[1] += i[1];
+         sum[2] += i[2];
+      }
+      
+      btMatrix3x3& getInertia()
+      {
+         return sum;
+      }
+
+   };
+
+   CenterCallback centerCallback;
+   btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+   m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
+   btVector3 center = centerCallback.getCenter();
+   principal.setOrigin(center);
+   volume = centerCallback.getVolume();
+
+   InertiaCallback inertiaCallback(center);
+   m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
+
+   btMatrix3x3& i = inertiaCallback.getInertia();
+   i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
+   inertia.setValue(i[0][0], i[1][1], i[2][2]);
+   inertia /= volume;
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
new file mode 100644
index 0000000..f5167e7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h
@@ -0,0 +1,75 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef CONVEX_TRIANGLEMESH_SHAPE_H
+#define CONVEX_TRIANGLEMESH_SHAPE_H
+
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+
+/// The btConvexTriangleMeshShape is a convex hull of a triangle mesh, but the performance is not as good as btConvexHullShape.
+/// A small benefit of this class is that it uses the btStridingMeshInterface, so you can avoid the duplication of the triangle mesh data. Nevertheless, most users should use the much better performing btConvexHullShape instead.
+class btConvexTriangleMeshShape : public btPolyhedralConvexAabbCachingShape
+{
+
+	class btStridingMeshInterface*	m_stridingMesh;
+
+public:
+	btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb = true);
+
+	class btStridingMeshInterface*	getMeshInterface()
+	{
+		return m_stridingMesh;
+	}
+	const class btStridingMeshInterface* getMeshInterface() const
+	{
+		return m_stridingMesh;
+	}
+	
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	//debugging
+	virtual const char*	getName()const {return "ConvexTrimesh";}
+	
+	virtual int	getNumVertices() const;
+	virtual int getNumEdges() const;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	virtual void getVertex(int i,btVector3& vtx) const;
+	virtual int	getNumPlanes() const;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const;
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+	
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+
+	///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia
+	///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia"
+	///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the
+	///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform
+	///of the collision object by the principal transform. This method also computes the volume of the convex mesh.
+	void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const;
+
+};
+
+
+
+#endif //CONVEX_TRIANGLEMESH_SHAPE_H
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
new file mode 100644
index 0000000..2688093
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.cpp
@@ -0,0 +1,222 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btCylinderShape.h"
+
+btCylinderShape::btCylinderShape (const btVector3& halfExtents)
+:btConvexInternalShape(),
+m_upAxis(1)
+{
+	btVector3 margin(getMargin(),getMargin(),getMargin());
+	m_implicitShapeDimensions = (halfExtents * m_localScaling) - margin;
+	m_shapeType = CYLINDER_SHAPE_PROXYTYPE;
+}
+
+
+btCylinderShapeX::btCylinderShapeX (const btVector3& halfExtents)
+:btCylinderShape(halfExtents)
+{
+	m_upAxis = 0;
+
+}
+
+
+btCylinderShapeZ::btCylinderShapeZ (const btVector3& halfExtents)
+:btCylinderShape(halfExtents)
+{
+	m_upAxis = 2;
+
+}
+
+void btCylinderShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax);
+}
+
+void	btCylinderShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//approximation of box shape, todo: implement cylinder shape inertia before people notice ;-)
+	btVector3 halfExtents = getHalfExtentsWithMargin();
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
+
+SIMD_FORCE_INLINE btVector3 CylinderLocalSupportX(const btVector3& halfExtents,const btVector3& v) 
+{
+const int cylinderUpAxis = 0;
+const int XX = 1;
+const int YY = 0;
+const int ZZ = 2;
+
+	//mapping depends on how cylinder local orientation is
+	// extents of the cylinder is: X,Y is for radius, and Z for height
+
+
+	btScalar radius = halfExtents[XX];
+	btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+    btVector3 tmp;
+	btScalar d ;
+
+    btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+    if (s != btScalar(0.0))
+	{
+        d = radius / s;  
+		tmp[XX] = v[XX] * d;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = v[ZZ] * d;
+		return tmp;
+	}
+    else
+	{
+	    tmp[XX] = radius;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = btScalar(0.0);
+		return tmp;
+    }
+
+
+}
+
+
+
+
+
+
+inline  btVector3 CylinderLocalSupportY(const btVector3& halfExtents,const btVector3& v) 
+{
+
+const int cylinderUpAxis = 1;
+const int XX = 0;
+const int YY = 1;
+const int ZZ = 2;
+
+
+	btScalar radius = halfExtents[XX];
+	btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+    btVector3 tmp;
+	btScalar d ;
+
+    btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+    if (s != btScalar(0.0))
+	{
+        d = radius / s;  
+		tmp[XX] = v[XX] * d;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = v[ZZ] * d;
+		return tmp;
+	}
+    else
+	{
+	    tmp[XX] = radius;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = btScalar(0.0);
+		return tmp;
+    }
+
+}
+
+inline btVector3 CylinderLocalSupportZ(const btVector3& halfExtents,const btVector3& v) 
+{
+const int cylinderUpAxis = 2;
+const int XX = 0;
+const int YY = 2;
+const int ZZ = 1;
+
+	//mapping depends on how cylinder local orientation is
+	// extents of the cylinder is: X,Y is for radius, and Z for height
+
+
+	btScalar radius = halfExtents[XX];
+	btScalar halfHeight = halfExtents[cylinderUpAxis];
+
+
+    btVector3 tmp;
+	btScalar d ;
+
+    btScalar s = btSqrt(v[XX] * v[XX] + v[ZZ] * v[ZZ]);
+    if (s != btScalar(0.0))
+	{
+        d = radius / s;  
+		tmp[XX] = v[XX] * d;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = v[ZZ] * d;
+		return tmp;
+	}
+    else
+	{
+	    tmp[XX] = radius;
+		tmp[YY] = v[YY] < 0.0 ? -halfHeight : halfHeight;
+		tmp[ZZ] = btScalar(0.0);
+		return tmp;
+    }
+
+
+}
+
+btVector3	btCylinderShapeX::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vec);
+}
+
+
+btVector3	btCylinderShapeZ::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vec);
+}
+btVector3	btCylinderShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	return CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vec);
+}
+
+void	btCylinderShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = CylinderLocalSupportY(getHalfExtentsWithoutMargin(),vectors[i]);
+	}
+}
+
+void	btCylinderShapeZ::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = CylinderLocalSupportZ(getHalfExtentsWithoutMargin(),vectors[i]);
+	}
+}
+
+
+
+
+void	btCylinderShapeX::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = CylinderLocalSupportX(getHalfExtentsWithoutMargin(),vectors[i]);
+	}
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
new file mode 100644
index 0000000..f789926
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btCylinderShape.h
@@ -0,0 +1,200 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef CYLINDER_MINKOWSKI_H
+#define CYLINDER_MINKOWSKI_H
+
+#include "btBoxShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btVector3.h"
+
+/// The btCylinderShape class implements a cylinder shape primitive, centered around the origin. Its central axis aligned with the Y axis. btCylinderShapeX is aligned with the X axis and btCylinderShapeZ around the Z axis.
+class btCylinderShape : public btConvexInternalShape
+
+{
+
+protected:
+
+	int	m_upAxis;
+
+public:
+
+	btVector3 getHalfExtentsWithMargin() const
+	{
+		btVector3 halfExtents = getHalfExtentsWithoutMargin();
+		btVector3 margin(getMargin(),getMargin(),getMargin());
+		halfExtents += margin;
+		return halfExtents;
+	}
+	
+	const btVector3& getHalfExtentsWithoutMargin() const
+	{
+		return m_implicitShapeDimensions;//changed in Bullet 2.63: assume the scaling and margin are included
+	}
+
+	btCylinderShape (const btVector3& halfExtents);
+	
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	virtual void setMargin(btScalar collisionMargin)
+	{
+		//correct the m_implicitShapeDimensions for the margin
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		
+		btConvexInternalShape::setMargin(collisionMargin);
+		btVector3 newMargin(getMargin(),getMargin(),getMargin());
+		m_implicitShapeDimensions = implicitShapeDimensionsWithMargin - newMargin;
+
+	}
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec) const
+	{
+
+		btVector3 supVertex;
+		supVertex = localGetSupportingVertexWithoutMargin(vec);
+		
+		if ( getMargin()!=btScalar(0.) )
+		{
+			btVector3 vecnorm = vec;
+			if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+			{
+				vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+			} 
+			vecnorm.normalize();
+			supVertex+= getMargin() * vecnorm;
+		}
+		return supVertex;
+	}
+
+
+	//use box inertia
+	//	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+	int	getUpAxis() const
+	{
+		return m_upAxis;
+	}
+
+	virtual btScalar getRadius() const
+	{
+		return getHalfExtentsWithMargin().getX();
+	}
+
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		btVector3 oldMargin(getMargin(),getMargin(),getMargin());
+		btVector3 implicitShapeDimensionsWithMargin = m_implicitShapeDimensions+oldMargin;
+		btVector3 unScaledImplicitShapeDimensionsWithMargin = implicitShapeDimensionsWithMargin / m_localScaling;
+
+		btConvexInternalShape::setLocalScaling(scaling);
+
+		m_implicitShapeDimensions = (unScaledImplicitShapeDimensionsWithMargin * m_localScaling) - oldMargin;
+
+	}
+
+	//debugging
+	virtual const char*	getName()const
+	{
+		return "CylinderY";
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+};
+
+class btCylinderShapeX : public btCylinderShape
+{
+public:
+	btCylinderShapeX (const btVector3& halfExtents);
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+		//debugging
+	virtual const char*	getName()const
+	{
+		return "CylinderX";
+	}
+
+	virtual btScalar getRadius() const
+	{
+		return getHalfExtentsWithMargin().getY();
+	}
+
+};
+
+class btCylinderShapeZ : public btCylinderShape
+{
+public:
+	btCylinderShapeZ (const btVector3& halfExtents);
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+		//debugging
+	virtual const char*	getName()const
+	{
+		return "CylinderZ";
+	}
+
+	virtual btScalar getRadius() const
+	{
+		return getHalfExtentsWithMargin().getX();
+	}
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btCylinderShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	int	m_upAxis;
+
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btCylinderShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btCylinderShapeData);
+}
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btCylinderShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btCylinderShapeData* shapeData = (btCylinderShapeData*) dataBuffer;
+	
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData,serializer);
+
+	shapeData->m_upAxis = m_upAxis;
+	
+	return "btCylinderShapeData";
+}
+
+
+
+#endif //CYLINDER_MINKOWSKI_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
new file mode 100644
index 0000000..a9e6df5
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.cpp
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btEmptyShape.h"
+
+
+#include "btCollisionShape.h"
+
+
+btEmptyShape::btEmptyShape() : btConcaveShape ()
+{
+	m_shapeType = EMPTY_SHAPE_PROXYTYPE;
+}
+
+
+btEmptyShape::~btEmptyShape()
+{
+}
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btEmptyShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 margin(getMargin(),getMargin(),getMargin());
+
+	aabbMin = t.getOrigin() - margin;
+
+	aabbMax = t.getOrigin() + margin;
+
+}
+
+void	btEmptyShape::calculateLocalInertia(btScalar ,btVector3& ) const
+{
+	btAssert(0);
+}
+
+	
+	
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
new file mode 100644
index 0000000..9f6b443
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btEmptyShape.h
@@ -0,0 +1,70 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef EMPTY_SHAPE_H
+#define EMPTY_SHAPE_H
+
+#include "btConcaveShape.h"
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "btCollisionMargin.h"
+
+
+
+
+/// The btEmptyShape is a collision shape without actual collision detection shape, so most users should ignore this class.
+/// It can be replaced by another shape during runtime, but the inertia tensor should be recomputed.
+class btEmptyShape	: public btConcaveShape
+{
+public:
+	btEmptyShape();
+
+	virtual ~btEmptyShape();
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		m_localScaling = scaling;
+	}
+	virtual const btVector3& getLocalScaling() const 
+	{
+		return m_localScaling;
+	}
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+	
+	virtual const char*	getName()const
+	{
+		return "Empty";
+	}
+
+	virtual void processAllTriangles(btTriangleCallback* ,const btVector3& ,const btVector3& ) const
+	{
+	}
+
+protected:
+	btVector3	m_localScaling;
+
+};
+
+
+
+#endif //EMPTY_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
new file mode 100644
index 0000000..3a1e6f4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp
@@ -0,0 +1,411 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btHeightfieldTerrainShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape
+(
+int heightStickWidth, int heightStickLength, void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight,int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
+{
+	initialize(heightStickWidth, heightStickLength, heightfieldData,
+	           heightScale, minHeight, maxHeight, upAxis, hdt,
+	           flipQuadEdges);
+}
+
+
+
+btHeightfieldTerrainShape::btHeightfieldTerrainShape(int heightStickWidth, int heightStickLength,void* heightfieldData,btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges)
+{
+	// legacy constructor: support only float or unsigned char,
+	// 	and min height is zero
+	PHY_ScalarType hdt = (useFloatData) ? PHY_FLOAT : PHY_UCHAR;
+	btScalar minHeight = 0.0;
+
+	// previously, height = uchar * maxHeight / 65535.
+	// So to preserve legacy behavior, heightScale = maxHeight / 65535
+	btScalar heightScale = maxHeight / 65535;
+
+	initialize(heightStickWidth, heightStickLength, heightfieldData,
+	           heightScale, minHeight, maxHeight, upAxis, hdt,
+	           flipQuadEdges);
+}
+
+
+
+void btHeightfieldTerrainShape::initialize
+(
+int heightStickWidth, int heightStickLength, void* heightfieldData,
+btScalar heightScale, btScalar minHeight, btScalar maxHeight, int upAxis,
+PHY_ScalarType hdt, bool flipQuadEdges
+)
+{
+	// validation
+	btAssert(heightStickWidth > 1 && "bad width");
+	btAssert(heightStickLength > 1 && "bad length");
+	btAssert(heightfieldData && "null heightfield data");
+	// btAssert(heightScale) -- do we care?  Trust caller here
+	btAssert(minHeight <= maxHeight && "bad min/max height");
+	btAssert(upAxis >= 0 && upAxis < 3 &&
+	    "bad upAxis--should be in range [0,2]");
+	btAssert(hdt != PHY_UCHAR || hdt != PHY_FLOAT || hdt != PHY_SHORT &&
+	    "Bad height data type enum");
+
+	// initialize member variables
+	m_shapeType = TERRAIN_SHAPE_PROXYTYPE;
+	m_heightStickWidth = heightStickWidth;
+	m_heightStickLength = heightStickLength;
+	m_minHeight = minHeight;
+	m_maxHeight = maxHeight;
+	m_width = (btScalar) (heightStickWidth - 1);
+	m_length = (btScalar) (heightStickLength - 1);
+	m_heightScale = heightScale;
+	m_heightfieldDataUnknown = heightfieldData;
+	m_heightDataType = hdt;
+	m_flipQuadEdges = flipQuadEdges;
+	m_useDiamondSubdivision = false;
+	m_upAxis = upAxis;
+	m_localScaling.setValue(btScalar(1.), btScalar(1.), btScalar(1.));
+
+	// determine min/max axis-aligned bounding box (aabb) values
+	switch (m_upAxis)
+	{
+	case 0:
+		{
+			m_localAabbMin.setValue(m_minHeight, 0, 0);
+			m_localAabbMax.setValue(m_maxHeight, m_width, m_length);
+			break;
+		}
+	case 1:
+		{
+			m_localAabbMin.setValue(0, m_minHeight, 0);
+			m_localAabbMax.setValue(m_width, m_maxHeight, m_length);
+			break;
+		};
+	case 2:
+		{
+			m_localAabbMin.setValue(0, 0, m_minHeight);
+			m_localAabbMax.setValue(m_width, m_length, m_maxHeight);
+			break;
+		}
+	default:
+		{
+			//need to get valid m_upAxis
+			btAssert(0 && "Bad m_upAxis");
+		}
+	}
+
+	// remember origin (defined as exact middle of aabb)
+	m_localOrigin = btScalar(0.5) * (m_localAabbMin + m_localAabbMax);
+}
+
+
+
+btHeightfieldTerrainShape::~btHeightfieldTerrainShape()
+{
+}
+
+
+
+void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5);
+
+	btVector3 localOrigin(0, 0, 0);
+	localOrigin[m_upAxis] = (m_minHeight + m_maxHeight) * btScalar(0.5);
+	localOrigin *= m_localScaling;
+
+	btMatrix3x3 abs_b = t.getBasis().absolute();  
+	btVector3 center = t.getOrigin();
+	btVector3 extent = btVector3(abs_b[0].dot(halfExtents),
+		   abs_b[1].dot(halfExtents),
+		  abs_b[2].dot(halfExtents));
+	extent += btVector3(getMargin(),getMargin(),getMargin());
+
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+}
+
+
+/// This returns the "raw" (user's initial) height, not the actual height.
+/// The actual height needs to be adjusted to be relative to the center
+///   of the heightfield's AABB.
+btScalar
+btHeightfieldTerrainShape::getRawHeightFieldValue(int x,int y) const
+{
+	btScalar val = 0.f;
+	switch (m_heightDataType)
+	{
+	case PHY_FLOAT:
+		{
+			val = m_heightfieldDataFloat[(y*m_heightStickWidth)+x];
+			break;
+		}
+
+	case PHY_UCHAR:
+		{
+			unsigned char heightFieldValue = m_heightfieldDataUnsignedChar[(y*m_heightStickWidth)+x];
+			val = heightFieldValue * m_heightScale;
+			break;
+		}
+
+	case PHY_SHORT:
+		{
+			short hfValue = m_heightfieldDataShort[(y * m_heightStickWidth) + x];
+			val = hfValue * m_heightScale;
+			break;
+		}
+
+	default:
+		{
+			btAssert(!"Bad m_heightDataType");
+		}
+	}
+
+	return val;
+}
+
+
+
+
+/// this returns the vertex in bullet-local coordinates
+void	btHeightfieldTerrainShape::getVertex(int x,int y,btVector3& vertex) const
+{
+	btAssert(x>=0);
+	btAssert(y>=0);
+	btAssert(x<m_heightStickWidth);
+	btAssert(y<m_heightStickLength);
+
+	btScalar	height = getRawHeightFieldValue(x,y);
+
+	switch (m_upAxis)
+	{
+	case 0:
+		{
+		vertex.setValue(
+			height - m_localOrigin.getX(),
+			(-m_width/btScalar(2.0)) + x,
+			(-m_length/btScalar(2.0) ) + y
+			);
+			break;
+		}
+	case 1:
+		{
+			vertex.setValue(
+			(-m_width/btScalar(2.0)) + x,
+			height - m_localOrigin.getY(),
+			(-m_length/btScalar(2.0)) + y
+			);
+			break;
+		};
+	case 2:
+		{
+			vertex.setValue(
+			(-m_width/btScalar(2.0)) + x,
+			(-m_length/btScalar(2.0)) + y,
+			height - m_localOrigin.getZ()
+			);
+			break;
+		}
+	default:
+		{
+			//need to get valid m_upAxis
+			btAssert(0);
+		}
+	}
+
+	vertex*=m_localScaling;
+}
+
+
+
+static inline int
+getQuantized
+(
+btScalar x
+)
+{
+	if (x < 0.0) {
+		return (int) (x - 0.5);
+	}
+	return (int) (x + 0.5);
+}
+
+
+
+/// given input vector, return quantized version
+/**
+  This routine is basically determining the gridpoint indices for a given
+  input vector, answering the question: "which gridpoint is closest to the
+  provided point?".
+
+  "with clamp" means that we restrict the point to be in the heightfield's
+  axis-aligned bounding box.
+ */
+void btHeightfieldTerrainShape::quantizeWithClamp(int* out, const btVector3& point,int /*isMax*/) const
+{
+	btVector3 clampedPoint(point);
+	clampedPoint.setMax(m_localAabbMin);
+	clampedPoint.setMin(m_localAabbMax);
+
+	out[0] = getQuantized(clampedPoint.getX());
+	out[1] = getQuantized(clampedPoint.getY());
+	out[2] = getQuantized(clampedPoint.getZ());
+		
+}
+
+
+
+/// process all triangles within the provided axis-aligned bounding box
+/**
+  basic algorithm:
+    - convert input aabb to local coordinates (scale down and shift for local origin)
+    - convert input aabb to a range of heightfield grid points (quantize)
+    - iterate over all triangles in that subset of the grid
+ */
+void	btHeightfieldTerrainShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	// scale down the input aabb's so they are in local (non-scaled) coordinates
+	btVector3	localAabbMin = aabbMin*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+	btVector3	localAabbMax = aabbMax*btVector3(1.f/m_localScaling[0],1.f/m_localScaling[1],1.f/m_localScaling[2]);
+
+	// account for local origin
+	localAabbMin += m_localOrigin;
+	localAabbMax += m_localOrigin;
+
+	//quantize the aabbMin and aabbMax, and adjust the start/end ranges
+	int	quantizedAabbMin[3];
+	int	quantizedAabbMax[3];
+	quantizeWithClamp(quantizedAabbMin, localAabbMin,0);
+	quantizeWithClamp(quantizedAabbMax, localAabbMax,1);
+	
+	// expand the min/max quantized values
+	// this is to catch the case where the input aabb falls between grid points!
+	for (int i = 0; i < 3; ++i) {
+		quantizedAabbMin[i]--;
+		quantizedAabbMax[i]++;
+	}	
+
+	int startX=0;
+	int endX=m_heightStickWidth-1;
+	int startJ=0;
+	int endJ=m_heightStickLength-1;
+
+	switch (m_upAxis)
+	{
+	case 0:
+		{
+			if (quantizedAabbMin[1]>startX)
+				startX = quantizedAabbMin[1];
+			if (quantizedAabbMax[1]<endX)
+				endX = quantizedAabbMax[1];
+			if (quantizedAabbMin[2]>startJ)
+				startJ = quantizedAabbMin[2];
+			if (quantizedAabbMax[2]<endJ)
+				endJ = quantizedAabbMax[2];
+			break;
+		}
+	case 1:
+		{
+			if (quantizedAabbMin[0]>startX)
+				startX = quantizedAabbMin[0];
+			if (quantizedAabbMax[0]<endX)
+				endX = quantizedAabbMax[0];
+			if (quantizedAabbMin[2]>startJ)
+				startJ = quantizedAabbMin[2];
+			if (quantizedAabbMax[2]<endJ)
+				endJ = quantizedAabbMax[2];
+			break;
+		};
+	case 2:
+		{
+			if (quantizedAabbMin[0]>startX)
+				startX = quantizedAabbMin[0];
+			if (quantizedAabbMax[0]<endX)
+				endX = quantizedAabbMax[0];
+			if (quantizedAabbMin[1]>startJ)
+				startJ = quantizedAabbMin[1];
+			if (quantizedAabbMax[1]<endJ)
+				endJ = quantizedAabbMax[1];
+			break;
+		}
+	default:
+		{
+			//need to get valid m_upAxis
+			btAssert(0);
+		}
+	}
+
+	
+  
+
+	for(int j=startJ; j<endJ; j++)
+	{
+		for(int x=startX; x<endX; x++)
+		{
+			btVector3 vertices[3];
+			if (m_flipQuadEdges || (m_useDiamondSubdivision && !((j+x) & 1)))
+			{
+        //first triangle
+        getVertex(x,j,vertices[0]);
+        getVertex(x+1,j,vertices[1]);
+        getVertex(x+1,j+1,vertices[2]);
+        callback->processTriangle(vertices,x,j);
+        //second triangle
+        getVertex(x,j,vertices[0]);
+        getVertex(x+1,j+1,vertices[1]);
+        getVertex(x,j+1,vertices[2]);
+        callback->processTriangle(vertices,x,j);				
+			} else
+			{
+        //first triangle
+        getVertex(x,j,vertices[0]);
+        getVertex(x,j+1,vertices[1]);
+        getVertex(x+1,j,vertices[2]);
+        callback->processTriangle(vertices,x,j);
+        //second triangle
+        getVertex(x+1,j,vertices[0]);
+        getVertex(x,j+1,vertices[1]);
+        getVertex(x+1,j+1,vertices[2]);
+        callback->processTriangle(vertices,x,j);
+			}
+		}
+	}
+
+	
+
+}
+
+void	btHeightfieldTerrainShape::calculateLocalInertia(btScalar ,btVector3& inertia) const
+{
+	//moving concave objects not supported
+	
+	inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void	btHeightfieldTerrainShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+}
+const btVector3& btHeightfieldTerrainShape::getLocalScaling() const
+{
+	return m_localScaling;
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
new file mode 100644
index 0000000..4f5d1e3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h
@@ -0,0 +1,161 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef HEIGHTFIELD_TERRAIN_SHAPE_H
+#define HEIGHTFIELD_TERRAIN_SHAPE_H
+
+#include "btConcaveShape.h"
+
+///btHeightfieldTerrainShape simulates a 2D heightfield terrain
+/**
+  The caller is responsible for maintaining the heightfield array; this
+  class does not make a copy.
+
+  The heightfield can be dynamic so long as the min/max height values
+  capture the extremes (heights must always be in that range).
+
+  The local origin of the heightfield is assumed to be the exact
+  center (as determined by width and length and height, with each
+  axis multiplied by the localScaling).
+
+  \b NOTE: be careful with coordinates.  If you have a heightfield with a local
+  min height of -100m, and a max height of +500m, you may be tempted to place it
+  at the origin (0,0) and expect the heights in world coordinates to be
+  -100 to +500 meters.
+  Actually, the heights will be -300 to +300m, because bullet will re-center
+  the heightfield based on its AABB (which is determined by the min/max
+  heights).  So keep in mind that once you create a btHeightfieldTerrainShape
+  object, the heights will be adjusted relative to the center of the AABB.  This
+  is different to the behavior of many rendering engines, but is useful for
+  physics engines.
+
+  Most (but not all) rendering and heightfield libraries assume upAxis = 1
+  (that is, the y-axis is "up").  This class allows any of the 3 coordinates
+  to be "up".  Make sure your choice of axis is consistent with your rendering
+  system.
+
+  The heightfield heights are determined from the data type used for the
+  heightfieldData array.  
+
+   - PHY_UCHAR: height at a point is the uchar value at the
+       grid point, multipled by heightScale.  uchar isn't recommended
+       because of its inability to deal with negative values, and
+       low resolution (8-bit).
+
+   - PHY_SHORT: height at a point is the short int value at that grid
+       point, multipled by heightScale.
+
+   - PHY_FLOAT: height at a point is the float value at that grid
+       point.  heightScale is ignored when using the float heightfield
+       data type.
+
+  Whatever the caller specifies as minHeight and maxHeight will be honored.
+  The class will not inspect the heightfield to discover the actual minimum
+  or maximum heights.  These values are used to determine the heightfield's
+  axis-aligned bounding box, multiplied by localScaling.
+
+  For usage and testing see the TerrainDemo.
+ */
+class btHeightfieldTerrainShape : public btConcaveShape
+{
+protected:
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	btVector3	m_localOrigin;
+
+	///terrain data
+	int	m_heightStickWidth;
+	int m_heightStickLength;
+	btScalar	m_minHeight;
+	btScalar	m_maxHeight;
+	btScalar m_width;
+	btScalar m_length;
+	btScalar m_heightScale;
+	union
+	{
+		unsigned char*	m_heightfieldDataUnsignedChar;
+		short*		m_heightfieldDataShort;
+		btScalar*			m_heightfieldDataFloat;
+		void*			m_heightfieldDataUnknown;
+	};
+
+	PHY_ScalarType	m_heightDataType;	
+	bool	m_flipQuadEdges;
+  bool  m_useDiamondSubdivision;
+
+	int	m_upAxis;
+	
+	btVector3	m_localScaling;
+
+	virtual btScalar	getRawHeightFieldValue(int x,int y) const;
+	void		quantizeWithClamp(int* out, const btVector3& point,int isMax) const;
+	void		getVertex(int x,int y,btVector3& vertex) const;
+
+
+
+	/// protected initialization
+	/**
+	  Handles the work of constructors so that public constructors can be
+	  backwards-compatible without a lot of copy/paste.
+	 */
+	void initialize(int heightStickWidth, int heightStickLength,
+	                void* heightfieldData, btScalar heightScale,
+	                btScalar minHeight, btScalar maxHeight, int upAxis,
+	                PHY_ScalarType heightDataType, bool flipQuadEdges);
+
+public:
+	/// preferred constructor
+	/**
+	  This constructor supports a range of heightfield
+	  data types, and allows for a non-zero minimum height value.
+	  heightScale is needed for any integer-based heightfield data types.
+	 */
+	btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,
+	                          void* heightfieldData, btScalar heightScale,
+	                          btScalar minHeight, btScalar maxHeight,
+	                          int upAxis, PHY_ScalarType heightDataType,
+	                          bool flipQuadEdges);
+
+	/// legacy constructor
+	/**
+	  The legacy constructor assumes the heightfield has a minimum height
+	  of zero.  Only unsigned char or floats are supported.  For legacy
+	  compatibility reasons, heightScale is calculated as maxHeight / 65535 
+	  (and is only used when useFloatData = false).
+ 	 */
+	btHeightfieldTerrainShape(int heightStickWidth,int heightStickLength,void* heightfieldData, btScalar maxHeight,int upAxis,bool useFloatData,bool flipQuadEdges);
+
+	virtual ~btHeightfieldTerrainShape();
+
+
+	void setUseDiamondSubdivision(bool useDiamondSubdivision=true) { m_useDiamondSubdivision = useDiamondSubdivision;}
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	
+	virtual const btVector3& getLocalScaling() const;
+	
+	//debugging
+	virtual const char*	getName()const {return "HEIGHTFIELD";}
+
+};
+
+#endif //HEIGHTFIELD_TERRAIN_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMaterial.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMaterial.h
new file mode 100644
index 0000000..030e167
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMaterial.h
@@ -0,0 +1,35 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef MATERIAL_H
+#define MATERIAL_H
+
+// Material class to be used by btMultimaterialTriangleMeshShape to store triangle properties
+class btMaterial
+{
+    // public members so that materials can change due to world events
+public:
+    btScalar m_friction;
+    btScalar m_restitution;
+    int pad[2];
+
+    btMaterial(){}
+    btMaterial(btScalar fric, btScalar rest) { m_friction = fric; m_restitution = rest; }
+};
+
+#endif // MATERIAL_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
new file mode 100644
index 0000000..06707e2
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.cpp
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btMinkowskiSumShape.h"
+
+
+btMinkowskiSumShape::btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB)
+: btConvexInternalShape (),
+m_shapeA(shapeA),
+m_shapeB(shapeB)
+{
+	m_shapeType = MINKOWSKI_DIFFERENCE_SHAPE_PROXYTYPE;
+	m_transA.setIdentity();
+	m_transB.setIdentity();
+}
+
+btVector3 btMinkowskiSumShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	btVector3 supVertexA = m_transA(m_shapeA->localGetSupportingVertexWithoutMargin(vec*m_transA.getBasis()));
+	btVector3 supVertexB = m_transB(m_shapeB->localGetSupportingVertexWithoutMargin(-vec*m_transB.getBasis()));
+	return  supVertexA - supVertexB;
+}
+
+void	btMinkowskiSumShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	///@todo: could make recursive use of batching. probably this shape is not used frequently.
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = localGetSupportingVertexWithoutMargin(vectors[i]);
+	}
+
+}
+
+
+
+btScalar	btMinkowskiSumShape::getMargin() const
+{
+	return m_shapeA->getMargin() + m_shapeB->getMargin();
+}
+
+
+void	btMinkowskiSumShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	(void)mass;
+	btAssert(0);
+	inertia.setValue(0,0,0);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
new file mode 100644
index 0000000..d6fd040
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMinkowskiSumShape.h
@@ -0,0 +1,60 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef MINKOWSKI_SUM_SHAPE_H
+#define MINKOWSKI_SUM_SHAPE_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+/// The btMinkowskiSumShape is only for advanced users. This shape represents implicit based minkowski sum of two convex implicit shapes.
+class btMinkowskiSumShape : public btConvexInternalShape
+{
+
+	btTransform	m_transA;
+	btTransform	m_transB;
+	const btConvexShape*	m_shapeA;
+	const btConvexShape*	m_shapeB;
+
+public:
+
+	btMinkowskiSumShape(const btConvexShape* shapeA,const btConvexShape* shapeB);
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	void	setTransformA(const btTransform&	transA) { m_transA = transA;}
+	void	setTransformB(const btTransform&	transB) { m_transB = transB;}
+
+	const btTransform& getTransformA()const  { return m_transA;}
+	const btTransform& GetTransformB()const  { return m_transB;}
+
+
+	virtual btScalar	getMargin() const;
+
+	const btConvexShape*	getShapeA() const { return m_shapeA;}
+	const btConvexShape*	getShapeB() const { return m_shapeB;}
+
+	virtual const char*	getName()const 
+	{
+		return "MinkowskiSum";
+	}
+};
+
+#endif //MINKOWSKI_SUM_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
new file mode 100644
index 0000000..c996bfc
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.cpp
@@ -0,0 +1,167 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btSerializer.h"
+
+btMultiSphereShape::btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres)
+:btConvexInternalAabbCachingShape ()
+{
+	m_shapeType = MULTI_SPHERE_SHAPE_PROXYTYPE;
+	//btScalar startMargin = btScalar(BT_LARGE_FLOAT);
+
+	m_localPositionArray.resize(numSpheres);
+	m_radiArray.resize(numSpheres);
+	for (int i=0;i<numSpheres;i++)
+	{
+		m_localPositionArray[i] = positions[i];
+		m_radiArray[i] = radi[i];
+		
+	}
+
+	recalcLocalAabb();
+
+}
+
+ 
+ btVector3	btMultiSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+	int i;
+	btVector3 supVec(0,0,0);
+
+	btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	btVector3 vtx;
+	btScalar newDot;
+
+	const btVector3* pos = &m_localPositionArray[0];
+	const btScalar* rad = &m_radiArray[0];
+	int numSpheres = m_localPositionArray.size();
+
+	for (i=0;i<numSpheres;i++)
+	{
+		vtx = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
+		pos++;
+		rad++;
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+
+	return supVec;
+
+}
+
+ void	btMultiSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+
+	for (int j=0;j<numVectors;j++)
+	{
+		btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+		const btVector3& vec = vectors[j];
+
+		btVector3 vtx;
+		btScalar newDot;
+
+		const btVector3* pos = &m_localPositionArray[0];
+		const btScalar* rad = &m_radiArray[0];
+		int numSpheres = m_localPositionArray.size();
+		for (int i=0;i<numSpheres;i++)
+		{
+			vtx = (*pos) +vec*m_localScaling*(*rad) - vec * getMargin();
+			pos++;
+			rad++;
+			newDot = vec.dot(vtx);
+			if (newDot > maxDot)
+			{
+				maxDot = newDot;
+				supportVerticesOut[j] = vtx;
+			}
+		}
+	}
+}
+
+
+
+
+
+
+
+
+void	btMultiSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	//as an approximation, take the inertia of the box that bounds the spheres
+
+	btVector3 localAabbMin,localAabbMax;
+	getCachedLocalAabb(localAabbMin,localAabbMax);
+	btVector3 halfExtents = (localAabbMax-localAabbMin)*btScalar(0.5);
+
+	btScalar lx=btScalar(2.)*(halfExtents.x());
+	btScalar ly=btScalar(2.)*(halfExtents.y());
+	btScalar lz=btScalar(2.)*(halfExtents.z());
+
+	inertia.setValue(mass/(btScalar(12.0)) * (ly*ly + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + lz*lz),
+					mass/(btScalar(12.0)) * (lx*lx + ly*ly));
+
+}
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btMultiSphereShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btMultiSphereShapeData* shapeData = (btMultiSphereShapeData*) dataBuffer;
+	btConvexInternalShape::serialize(&shapeData->m_convexInternalShapeData, serializer);
+
+	int numElem = m_localPositionArray.size();
+	shapeData->m_localPositionArrayPtr = numElem ? (btPositionAndRadius*)serializer->getUniquePointer((void*)&m_localPositionArray[0]):  0;
+	
+	shapeData->m_localPositionArraySize = numElem;
+	if (numElem)
+	{
+		btChunk* chunk = serializer->allocate(sizeof(btPositionAndRadius),numElem);
+		btPositionAndRadius* memPtr = (btPositionAndRadius*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			m_localPositionArray[i].serializeFloat(memPtr->m_pos);
+			memPtr->m_radius = float(m_radiArray[i]);
+		}
+		serializer->finalizeChunk(chunk,"btPositionAndRadius",BT_ARRAY_CODE,(void*)&m_localPositionArray[0]);
+	}
+	
+	return "btMultiSphereShapeData";
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
new file mode 100644
index 0000000..3db7e32
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultiSphereShape.h
@@ -0,0 +1,99 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef MULTI_SPHERE_MINKOWSKI_H
+#define MULTI_SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btAabbUtil2.h"
+
+
+
+///The btMultiSphereShape represents the convex hull of a collection of spheres. You can create special capsules or other smooth volumes.
+///It is possible to animate the spheres for deformation, but call 'recalcLocalAabb' after changing any sphere position/radius
+class btMultiSphereShape : public btConvexInternalAabbCachingShape
+{
+	
+	btAlignedObjectArray<btVector3> m_localPositionArray;
+	btAlignedObjectArray<btScalar>  m_radiArray;
+	
+public:
+	btMultiSphereShape (const btVector3* positions,const btScalar* radi,int numSpheres);
+
+	///CollisionShape Interface
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	/// btConvexShape Interface
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	int	getSphereCount() const
+	{
+		return m_localPositionArray.size();
+	}
+
+	const btVector3&	getSpherePosition(int index) const
+	{
+		return m_localPositionArray[index];
+	}
+
+	btScalar	getSphereRadius(int index) const
+	{
+		return m_radiArray[index];
+	}
+
+
+	virtual const char*	getName()const 
+	{
+		return "MultiSphere";
+	}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+
+struct	btPositionAndRadius
+{
+	btVector3FloatData	m_pos;
+	float		m_radius;
+};
+
+struct	btMultiSphereShapeData
+{
+	btConvexInternalShapeData	m_convexInternalShapeData;
+
+	btPositionAndRadius	*m_localPositionArrayPtr;
+	int				m_localPositionArraySize;
+	char	m_padding[4];
+};
+
+
+
+SIMD_FORCE_INLINE	int	btMultiSphereShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btMultiSphereShapeData);
+}
+
+
+
+#endif //MULTI_SPHERE_MINKOWSKI_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
new file mode 100644
index 0000000..58799ac
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.cpp
@@ -0,0 +1,45 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#include "BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h"
+//#include "BulletCollision/CollisionShapes/btOptimizedBvh.h"
+
+
+///Obtains the material for a specific triangle
+const btMaterial * btMultimaterialTriangleMeshShape::getMaterialProperties(int partID, int triIndex)
+{
+    const unsigned char * materialBase = 0;
+    int numMaterials;
+    PHY_ScalarType materialType;
+    int materialStride;
+    const unsigned char * triangleMaterialBase = 0;
+    int numTriangles;
+    int triangleMaterialStride;
+    PHY_ScalarType triangleType;
+
+    ((btTriangleIndexVertexMaterialArray*)m_meshInterface)->getLockedReadOnlyMaterialBase(&materialBase, numMaterials, materialType, materialStride,
+        &triangleMaterialBase, numTriangles, triangleMaterialStride, triangleType, partID);
+
+    // return the pointer to the place with the friction for the triangle
+    // TODO: This depends on whether it's a moving mesh or not
+    // BUG IN GIMPACT
+    //return (btScalar*)(&materialBase[triangleMaterialBase[(triIndex-1) * triangleMaterialStride] * materialStride]);
+    int * matInd = (int *)(&(triangleMaterialBase[(triIndex * triangleMaterialStride)]));
+    btMaterial *matVal = (btMaterial *)(&(materialBase[*matInd * materialStride]));
+    return (matVal);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
new file mode 100644
index 0000000..d42ba11
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btMultimaterialTriangleMeshShape.h
@@ -0,0 +1,121 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/// This file was created by Alex Silverman
+
+#ifndef BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+#define BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
+
+#include "btBvhTriangleMeshShape.h"
+#include "btMaterial.h"
+
+///The BvhTriangleMaterialMeshShape extends the btBvhTriangleMeshShape. Its main contribution is the interface into a material array, which allows per-triangle friction and restitution.
+ATTRIBUTE_ALIGNED16(class) btMultimaterialTriangleMeshShape : public btBvhTriangleMeshShape
+{
+    btAlignedObjectArray <btMaterial*> m_materialList;
+    int ** m_triangleMaterials;
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+    btMultimaterialTriangleMeshShape(): btBvhTriangleMeshShape() {m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;}
+    btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression, bool buildBvh = true):
+        btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, buildBvh)
+        {
+            m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+            const unsigned char *vertexbase;
+            int numverts;
+            PHY_ScalarType type;
+            int stride;
+            const unsigned char *indexbase;
+            int indexstride;
+            int numfaces;
+            PHY_ScalarType indicestype;
+
+            //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+            for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+            {
+                m_meshInterface->getLockedReadOnlyVertexIndexBase(
+                    &vertexbase,
+                    numverts,
+                    type,
+                    stride,
+                    &indexbase,
+                    indexstride,
+                    numfaces,
+                    indicestype,
+                    i);
+                //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces, 16));
+            }
+        }
+
+	///optionally pass in a larger bvh aabb, used for quantization. This allows for deformations within this aabb
+	btMultimaterialTriangleMeshShape(btStridingMeshInterface* meshInterface, bool useQuantizedAabbCompression,const btVector3& bvhAabbMin,const btVector3& bvhAabbMax, bool buildBvh = true):
+        btBvhTriangleMeshShape(meshInterface, useQuantizedAabbCompression, bvhAabbMin, bvhAabbMax, buildBvh)
+        {
+            m_shapeType = MULTIMATERIAL_TRIANGLE_MESH_PROXYTYPE;
+
+            const unsigned char *vertexbase;
+            int numverts;
+            PHY_ScalarType type;
+            int stride;
+            const unsigned char *indexbase;
+            int indexstride;
+            int numfaces;
+            PHY_ScalarType indicestype;
+
+            //m_materialLookup = (int**)(btAlignedAlloc(sizeof(int*) * meshInterface->getNumSubParts(), 16));
+
+            for(int i = 0; i < meshInterface->getNumSubParts(); i++)
+            {
+                m_meshInterface->getLockedReadOnlyVertexIndexBase(
+                    &vertexbase,
+                    numverts,
+                    type,
+                    stride,
+                    &indexbase,
+                    indexstride,
+                    numfaces,
+                    indicestype,
+                    i);
+                //m_materialLookup[i] = (int*)(btAlignedAlloc(sizeof(int) * numfaces * 2, 16));
+            }
+        }
+	
+    virtual ~btMultimaterialTriangleMeshShape()
+    {
+/*
+        for(int i = 0; i < m_meshInterface->getNumSubParts(); i++)
+        {
+            btAlignedFree(m_materialValues[i]);
+            m_materialLookup[i] = NULL;
+        }
+        btAlignedFree(m_materialValues);
+        m_materialLookup = NULL;
+*/
+    }
+	//debugging
+	virtual const char*	getName()const {return "MULTIMATERIALTRIANGLEMESH";}
+
+    ///Obtains the material for a specific triangle
+    const btMaterial * getMaterialProperties(int partID, int triIndex);
+
+}
+;
+
+#endif //BVH_TRIANGLE_MATERIAL_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
new file mode 100644
index 0000000..981b8a2
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.cpp
@@ -0,0 +1,391 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btOptimizedBvh.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+btOptimizedBvh::btOptimizedBvh()
+{ 
+}
+
+btOptimizedBvh::~btOptimizedBvh()
+{
+}
+
+
+void btOptimizedBvh::build(btStridingMeshInterface* triangles, bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax)
+{
+	m_useQuantization = useQuantizedAabbCompression;
+
+
+	// NodeArray	triangleNodes;
+
+	struct	NodeTriangleCallback : public btInternalTriangleIndexCallback
+	{
+
+		NodeArray&	m_triangleNodes;
+
+		NodeTriangleCallback& operator=(NodeTriangleCallback& other)
+		{
+			m_triangleNodes = other.m_triangleNodes;
+			return *this;
+		}
+		
+		NodeTriangleCallback(NodeArray&	triangleNodes)
+			:m_triangleNodes(triangleNodes)
+		{
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+		{
+			btOptimizedBvhNode node;
+			btVector3	aabbMin,aabbMax;
+			aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+			aabbMin.setMin(triangle[0]);
+			aabbMax.setMax(triangle[0]);
+			aabbMin.setMin(triangle[1]);
+			aabbMax.setMax(triangle[1]);
+			aabbMin.setMin(triangle[2]);
+			aabbMax.setMax(triangle[2]);
+
+			//with quantization?
+			node.m_aabbMinOrg = aabbMin;
+			node.m_aabbMaxOrg = aabbMax;
+
+			node.m_escapeIndex = -1;
+	
+			//for child nodes
+			node.m_subPart = partId;
+			node.m_triangleIndex = triangleIndex;
+			m_triangleNodes.push_back(node);
+		}
+	};
+	struct	QuantizedNodeTriangleCallback : public btInternalTriangleIndexCallback
+	{
+		QuantizedNodeArray&	m_triangleNodes;
+		const btQuantizedBvh* m_optimizedTree; // for quantization
+
+		QuantizedNodeTriangleCallback& operator=(QuantizedNodeTriangleCallback& other)
+		{
+			m_triangleNodes = other.m_triangleNodes;
+			m_optimizedTree = other.m_optimizedTree;
+			return *this;
+		}
+
+		QuantizedNodeTriangleCallback(QuantizedNodeArray&	triangleNodes,const btQuantizedBvh* tree)
+			:m_triangleNodes(triangleNodes),m_optimizedTree(tree)
+		{
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+		{
+			// The partId and triangle index must fit in the same (positive) integer
+			btAssert(partId < (1<<MAX_NUM_PARTS_IN_BITS));
+			btAssert(triangleIndex < (1<<(31-MAX_NUM_PARTS_IN_BITS)));
+			//negative indices are reserved for escapeIndex
+			btAssert(triangleIndex>=0);
+
+			btQuantizedBvhNode node;
+			btVector3	aabbMin,aabbMax;
+			aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+			aabbMin.setMin(triangle[0]);
+			aabbMax.setMax(triangle[0]);
+			aabbMin.setMin(triangle[1]);
+			aabbMax.setMax(triangle[1]);
+			aabbMin.setMin(triangle[2]);
+			aabbMax.setMax(triangle[2]);
+
+			//PCK: add these checks for zero dimensions of aabb
+			const btScalar MIN_AABB_DIMENSION = btScalar(0.002);
+			const btScalar MIN_AABB_HALF_DIMENSION = btScalar(0.001);
+			if (aabbMax.x() - aabbMin.x() < MIN_AABB_DIMENSION)
+			{
+				aabbMax.setX(aabbMax.x() + MIN_AABB_HALF_DIMENSION);
+				aabbMin.setX(aabbMin.x() - MIN_AABB_HALF_DIMENSION);
+			}
+			if (aabbMax.y() - aabbMin.y() < MIN_AABB_DIMENSION)
+			{
+				aabbMax.setY(aabbMax.y() + MIN_AABB_HALF_DIMENSION);
+				aabbMin.setY(aabbMin.y() - MIN_AABB_HALF_DIMENSION);
+			}
+			if (aabbMax.z() - aabbMin.z() < MIN_AABB_DIMENSION)
+			{
+				aabbMax.setZ(aabbMax.z() + MIN_AABB_HALF_DIMENSION);
+				aabbMin.setZ(aabbMin.z() - MIN_AABB_HALF_DIMENSION);
+			}
+
+			m_optimizedTree->quantize(&node.m_quantizedAabbMin[0],aabbMin,0);
+			m_optimizedTree->quantize(&node.m_quantizedAabbMax[0],aabbMax,1);
+
+			node.m_escapeIndexOrTriangleIndex = (partId<<(31-MAX_NUM_PARTS_IN_BITS)) | triangleIndex;
+
+			m_triangleNodes.push_back(node);
+		}
+	};
+	
+
+
+	int numLeafNodes = 0;
+
+	
+	if (m_useQuantization)
+	{
+
+		//initialize quantization values
+		setQuantizationValues(bvhAabbMin,bvhAabbMax);
+
+		QuantizedNodeTriangleCallback	callback(m_quantizedLeafNodes,this);
+
+	
+		triangles->InternalProcessAllTriangles(&callback,m_bvhAabbMin,m_bvhAabbMax);
+
+		//now we have an array of leafnodes in m_leafNodes
+		numLeafNodes = m_quantizedLeafNodes.size();
+
+
+		m_quantizedContiguousNodes.resize(2*numLeafNodes);
+
+
+	} else
+	{
+		NodeTriangleCallback	callback(m_leafNodes);
+
+		btVector3 aabbMin(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+		btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+		triangles->InternalProcessAllTriangles(&callback,aabbMin,aabbMax);
+
+		//now we have an array of leafnodes in m_leafNodes
+		numLeafNodes = m_leafNodes.size();
+
+		m_contiguousNodes.resize(2*numLeafNodes);
+	}
+
+	m_curNodeIndex = 0;
+
+	buildTree(0,numLeafNodes);
+
+	///if the entire tree is small then subtree size, we need to create a header info for the tree
+	if(m_useQuantization && !m_SubtreeHeaders.size())
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders.expand();
+		subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[0]);
+		subtree.m_rootNodeIndex = 0;
+		subtree.m_subtreeSize = m_quantizedContiguousNodes[0].isLeafNode() ? 1 : m_quantizedContiguousNodes[0].getEscapeIndex();
+	}
+
+	//PCK: update the copy of the size
+	m_subtreeHeaderCount = m_SubtreeHeaders.size();
+
+	//PCK: clear m_quantizedLeafNodes and m_leafNodes, they are temporary
+	m_quantizedLeafNodes.clear();
+	m_leafNodes.clear();
+}
+
+
+
+
+void	btOptimizedBvh::refit(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	if (m_useQuantization)
+	{
+
+		setQuantizationValues(aabbMin,aabbMax);
+
+		updateBvhNodes(meshInterface,0,m_curNodeIndex,0);
+
+		///now update all subtree headers
+
+		int i;
+		for (i=0;i<m_SubtreeHeaders.size();i++)
+		{
+			btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+			subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+		}
+
+	} else
+	{
+
+	}
+}
+
+
+
+
+void	btOptimizedBvh::refitPartial(btStridingMeshInterface* meshInterface,const btVector3& aabbMin,const btVector3& aabbMax)
+{
+	//incrementally initialize quantization values
+	btAssert(m_useQuantization);
+
+	btAssert(aabbMin.getX() > m_bvhAabbMin.getX());
+	btAssert(aabbMin.getY() > m_bvhAabbMin.getY());
+	btAssert(aabbMin.getZ() > m_bvhAabbMin.getZ());
+
+	btAssert(aabbMax.getX() < m_bvhAabbMax.getX());
+	btAssert(aabbMax.getY() < m_bvhAabbMax.getY());
+	btAssert(aabbMax.getZ() < m_bvhAabbMax.getZ());
+
+	///we should update all quantization values, using updateBvhNodes(meshInterface);
+	///but we only update chunks that overlap the given aabb
+	
+	unsigned short	quantizedQueryAabbMin[3];
+	unsigned short	quantizedQueryAabbMax[3];
+
+	quantize(&quantizedQueryAabbMin[0],aabbMin,0);
+	quantize(&quantizedQueryAabbMax[0],aabbMax,1);
+
+	int i;
+	for (i=0;i<this->m_SubtreeHeaders.size();i++)
+	{
+		btBvhSubtreeInfo& subtree = m_SubtreeHeaders[i];
+
+		//PCK: unsigned instead of bool
+		unsigned overlap = testQuantizedAabbAgainstQuantizedAabb(quantizedQueryAabbMin,quantizedQueryAabbMax,subtree.m_quantizedAabbMin,subtree.m_quantizedAabbMax);
+		if (overlap != 0)
+		{
+			updateBvhNodes(meshInterface,subtree.m_rootNodeIndex,subtree.m_rootNodeIndex+subtree.m_subtreeSize,i);
+
+			subtree.setAabbFromQuantizeNode(m_quantizedContiguousNodes[subtree.m_rootNodeIndex]);
+		}
+	}
+	
+}
+
+void	btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index)
+{
+	(void)index;
+
+	btAssert(m_useQuantization);
+
+	int curNodeSubPart=-1;
+
+	//get access info to trianglemesh data
+		const unsigned char *vertexbase = 0;
+		int numverts = 0;
+		PHY_ScalarType type = PHY_INTEGER;
+		int stride = 0;
+		const unsigned char *indexbase = 0;
+		int indexstride = 0;
+		int numfaces = 0;
+		PHY_ScalarType indicestype = PHY_INTEGER;
+
+		btVector3	triangleVerts[3];
+		btVector3	aabbMin,aabbMax;
+		const btVector3& meshScaling = meshInterface->getScaling();
+		
+		int i;
+		for (i=endNode-1;i>=firstNode;i--)
+		{
+
+
+			btQuantizedBvhNode& curNode = m_quantizedContiguousNodes[i];
+			if (curNode.isLeafNode())
+			{
+				//recalc aabb from triangle data
+				int nodeSubPart = curNode.getPartId();
+				int nodeTriangleIndex = curNode.getTriangleIndex();
+				if (nodeSubPart != curNodeSubPart)
+				{
+					if (curNodeSubPart >= 0)
+						meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+					meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,	type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart);
+
+					curNodeSubPart = nodeSubPart;
+					btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT);
+				}
+				//triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts,
+
+				unsigned int* gfxbase = (unsigned int*)(indexbase+nodeTriangleIndex*indexstride);
+				
+				
+				for (int j=2;j>=0;j--)
+				{
+					
+					int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j];
+					if (type == PHY_FLOAT)
+					{
+						float* graphicsbase = (float*)(vertexbase+graphicsindex*stride);
+						triangleVerts[j] = btVector3(
+							graphicsbase[0]*meshScaling.getX(),
+							graphicsbase[1]*meshScaling.getY(),
+							graphicsbase[2]*meshScaling.getZ());
+					}
+					else
+					{
+						double* graphicsbase = (double*)(vertexbase+graphicsindex*stride);
+						triangleVerts[j] = btVector3( btScalar(graphicsbase[0]*meshScaling.getX()), btScalar(graphicsbase[1]*meshScaling.getY()), btScalar(graphicsbase[2]*meshScaling.getZ()));
+					}
+				}
+
+
+				
+				aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+				aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT)); 
+				aabbMin.setMin(triangleVerts[0]);
+				aabbMax.setMax(triangleVerts[0]);
+				aabbMin.setMin(triangleVerts[1]);
+				aabbMax.setMax(triangleVerts[1]);
+				aabbMin.setMin(triangleVerts[2]);
+				aabbMax.setMax(triangleVerts[2]);
+
+				quantize(&curNode.m_quantizedAabbMin[0],aabbMin,0);
+				quantize(&curNode.m_quantizedAabbMax[0],aabbMax,1);
+				
+			} else
+			{
+				//combine aabb from both children
+
+				btQuantizedBvhNode* leftChildNode = &m_quantizedContiguousNodes[i+1];
+				
+				btQuantizedBvhNode* rightChildNode = leftChildNode->isLeafNode() ? &m_quantizedContiguousNodes[i+2] :
+					&m_quantizedContiguousNodes[i+1+leftChildNode->getEscapeIndex()];
+				
+
+				{
+					for (int i=0;i<3;i++)
+					{
+						curNode.m_quantizedAabbMin[i] = leftChildNode->m_quantizedAabbMin[i];
+						if (curNode.m_quantizedAabbMin[i]>rightChildNode->m_quantizedAabbMin[i])
+							curNode.m_quantizedAabbMin[i]=rightChildNode->m_quantizedAabbMin[i];
+
+						curNode.m_quantizedAabbMax[i] = leftChildNode->m_quantizedAabbMax[i];
+						if (curNode.m_quantizedAabbMax[i] < rightChildNode->m_quantizedAabbMax[i])
+							curNode.m_quantizedAabbMax[i] = rightChildNode->m_quantizedAabbMax[i];
+					}
+				}
+			}
+
+		}
+
+		if (curNodeSubPart >= 0)
+			meshInterface->unLockReadOnlyVertexBase(curNodeSubPart);
+
+		
+}
+
+///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+btOptimizedBvh* btOptimizedBvh::deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian)
+{
+	btQuantizedBvh* bvh = btQuantizedBvh::deSerializeInPlace(i_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+	
+	//we don't add additional data so just do a static upcast
+	return static_cast<btOptimizedBvh*>(bvh);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
new file mode 100644
index 0000000..749fe60
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btOptimizedBvh.h
@@ -0,0 +1,65 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///Contains contributions from Disney Studio's
+
+#ifndef OPTIMIZED_BVH_H
+#define OPTIMIZED_BVH_H
+
+#include "BulletCollision/BroadphaseCollision/btQuantizedBvh.h"
+
+class btStridingMeshInterface;
+
+
+///The btOptimizedBvh extends the btQuantizedBvh to create AABB tree for triangle meshes, through the btStridingMeshInterface.
+ATTRIBUTE_ALIGNED16(class) btOptimizedBvh : public btQuantizedBvh
+{
+	
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+protected:
+
+public:
+
+	btOptimizedBvh();
+
+	virtual ~btOptimizedBvh();
+
+	void	build(btStridingMeshInterface* triangles,bool useQuantizedAabbCompression, const btVector3& bvhAabbMin, const btVector3& bvhAabbMax);
+
+	void	refit(btStridingMeshInterface* triangles,const btVector3& aabbMin,const btVector3& aabbMax);
+
+	void	refitPartial(btStridingMeshInterface* triangles,const btVector3& aabbMin, const btVector3& aabbMax);
+
+	void	updateBvhNodes(btStridingMeshInterface* meshInterface,int firstNode,int endNode,int index);
+
+	/// Data buffer MUST be 16 byte aligned
+	virtual bool serializeInPlace(void *o_alignedDataBuffer, unsigned i_dataBufferSize, bool i_swapEndian) const
+	{
+		return btQuantizedBvh::serialize(o_alignedDataBuffer,i_dataBufferSize,i_swapEndian);
+
+	}
+
+	///deSerializeInPlace loads and initializes a BVH from a buffer in memory 'in place'
+	static btOptimizedBvh *deSerializeInPlace(void *i_alignedDataBuffer, unsigned int i_dataBufferSize, bool i_swapEndian);
+
+
+};
+
+
+#endif //OPTIMIZED_BVH_H
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
new file mode 100644
index 0000000..b1ecb3e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp
@@ -0,0 +1,193 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionShapes/btPolyhedralConvexShape.h"
+
+btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape()
+{
+
+}
+
+
+btVector3	btPolyhedralConvexShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
+{
+
+
+	btVector3 supVec(0,0,0);
+#ifndef __SPU__
+	int i;
+	btScalar maxDot(btScalar(-BT_LARGE_FLOAT));
+
+	btVector3 vec = vec0;
+	btScalar lenSqr = vec.length2();
+	if (lenSqr < btScalar(0.0001))
+	{
+		vec.setValue(1,0,0);
+	} else
+	{
+		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+		vec *= rlen;
+	}
+
+	btVector3 vtx;
+	btScalar newDot;
+
+	for (i=0;i<getNumVertices();i++)
+	{
+		getVertex(i,vtx);
+		newDot = vec.dot(vtx);
+		if (newDot > maxDot)
+		{
+			maxDot = newDot;
+			supVec = vtx;
+		}
+	}
+
+	
+#endif //__SPU__
+	return supVec;
+}
+
+
+
+void	btPolyhedralConvexShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+#ifndef __SPU__
+	int i;
+
+	btVector3 vtx;
+	btScalar newDot;
+
+	for (i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
+	}
+
+	for (int j=0;j<numVectors;j++)
+	{
+	
+		const btVector3& vec = vectors[j];
+
+		for (i=0;i<getNumVertices();i++)
+		{
+			getVertex(i,vtx);
+			newDot = vec.dot(vtx);
+			if (newDot > supportVerticesOut[j][3])
+			{
+				//WARNING: don't swap next lines, the w component would get overwritten!
+				supportVerticesOut[j] = vtx;
+				supportVerticesOut[j][3] = newDot;
+			}
+		}
+	}
+#endif //__SPU__
+}
+
+
+
+void	btPolyhedralConvexShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+#ifndef __SPU__
+	//not yet, return box inertia
+
+	btScalar margin = getMargin();
+
+	btTransform ident;
+	ident.setIdentity();
+	btVector3 aabbMin,aabbMax;
+	getAabb(ident,aabbMin,aabbMax);
+	btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5);
+
+	btScalar lx=btScalar(2.)*(halfExtents.x()+margin);
+	btScalar ly=btScalar(2.)*(halfExtents.y()+margin);
+	btScalar lz=btScalar(2.)*(halfExtents.z()+margin);
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(0.08333333);
+
+	inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+#endif //__SPU__
+}
+
+
+
+void	btPolyhedralConvexAabbCachingShape::setLocalScaling(const btVector3& scaling)
+{
+	btConvexInternalShape::setLocalScaling(scaling);
+	recalcLocalAabb();
+}
+
+btPolyhedralConvexAabbCachingShape::btPolyhedralConvexAabbCachingShape()
+:btPolyhedralConvexShape(),
+m_localAabbMin(1,1,1),
+m_localAabbMax(-1,-1,-1),
+m_isLocalAabbValid(false)
+{
+}
+
+void btPolyhedralConvexAabbCachingShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	getNonvirtualAabb(trans,aabbMin,aabbMax,getMargin());
+}
+
+void	btPolyhedralConvexAabbCachingShape::recalcLocalAabb()
+{
+	m_isLocalAabbValid = true;
+	
+	#if 1
+	static const btVector3 _directions[] =
+	{
+		btVector3( 1.,  0.,  0.),
+		btVector3( 0.,  1.,  0.),
+		btVector3( 0.,  0.,  1.),
+		btVector3( -1., 0.,  0.),
+		btVector3( 0., -1.,  0.),
+		btVector3( 0.,  0., -1.)
+	};
+	
+	btVector3 _supporting[] =
+	{
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.),
+		btVector3( 0., 0., 0.)
+	};
+	
+	batchedUnitVectorGetSupportingVertexWithoutMargin(_directions, _supporting, 6);
+	
+	for ( int i = 0; i < 3; ++i )
+	{
+		m_localAabbMax[i] = _supporting[i][i] + m_collisionMargin;
+		m_localAabbMin[i] = _supporting[i + 3][i] - m_collisionMargin;
+	}
+	
+	#else
+
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+		btVector3 tmp = localGetSupportingVertex(vec);
+		m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+		vec[i] = btScalar(-1.);
+		tmp = localGetSupportingVertex(vec);
+		m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+	}
+	#endif
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
new file mode 100644
index 0000000..2c691b9
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h
@@ -0,0 +1,98 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BU_SHAPE
+#define BU_SHAPE
+
+#include "LinearMath/btMatrix3x3.h"
+#include "btConvexInternalShape.h"
+
+
+///The btPolyhedralConvexShape is an internal interface class for polyhedral convex shapes.
+class btPolyhedralConvexShape : public btConvexInternalShape
+{
+
+protected:
+	
+public:
+
+	btPolyhedralConvexShape();
+
+	//brute force implementations
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+	
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+	
+	
+	virtual int	getNumVertices() const = 0 ;
+	virtual int getNumEdges() const = 0;
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const = 0;
+	virtual void getVertex(int i,btVector3& vtx) const = 0;
+	virtual int	getNumPlanes() const = 0;
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i ) const = 0;
+//	virtual int getIndex(int i) const = 0 ; 
+
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const = 0;
+	
+};
+
+
+///The btPolyhedralConvexAabbCachingShape adds aabb caching to the btPolyhedralConvexShape
+class btPolyhedralConvexAabbCachingShape : public btPolyhedralConvexShape
+{
+
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	bool		m_isLocalAabbValid;
+		
+protected:
+
+	void setCachedLocalAabb (const btVector3& aabbMin, const btVector3& aabbMax)
+	{
+		m_isLocalAabbValid = true;
+		m_localAabbMin = aabbMin;
+		m_localAabbMax = aabbMax;
+	}
+
+	inline void getCachedLocalAabb (btVector3& aabbMin, btVector3& aabbMax) const
+	{
+		btAssert(m_isLocalAabbValid);
+		aabbMin = m_localAabbMin;
+		aabbMax = m_localAabbMax;
+	}
+
+public:
+
+	btPolyhedralConvexAabbCachingShape();
+	
+	inline void getNonvirtualAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax, btScalar margin) const
+	{
+
+		//lazy evaluation of local aabb
+		btAssert(m_isLocalAabbValid);
+		btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax);
+	}
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	void	recalcLocalAabb();
+
+};
+
+#endif //BU_SHAPE
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
new file mode 100644
index 0000000..d964e1e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp
@@ -0,0 +1,121 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btScaledBvhTriangleMeshShape.h"
+
+btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling)
+:m_localScaling(localScaling),m_bvhTriMeshShape(childShape)
+{
+	m_shapeType = SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE;
+}
+
+btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape()
+{
+}
+
+
+class btScaledTriangleCallback : public btTriangleCallback
+{
+	btTriangleCallback* m_originalCallback;
+
+	btVector3	m_localScaling;
+
+public:
+
+	btScaledTriangleCallback(btTriangleCallback* originalCallback,const btVector3& localScaling)
+		:m_originalCallback(originalCallback),
+		m_localScaling(localScaling)
+	{
+	}
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+	{
+		btVector3 newTriangle[3];
+		newTriangle[0] = triangle[0]*m_localScaling;
+		newTriangle[1] = triangle[1]*m_localScaling;
+		newTriangle[2] = triangle[2]*m_localScaling;
+		m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex);
+	}
+};
+
+void	btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	btScaledTriangleCallback scaledCallback(callback,m_localScaling);
+	
+	btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ());
+	btVector3 scaledAabbMin,scaledAabbMax;
+
+	///support negative scaling
+	scaledAabbMin[0] = m_localScaling.getX() >= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+	scaledAabbMin[1] = m_localScaling.getY() >= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+	scaledAabbMin[2] = m_localScaling.getZ() >= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+	
+	scaledAabbMax[0] = m_localScaling.getX() <= 0. ? aabbMin[0] * invLocalScaling[0] : aabbMax[0] * invLocalScaling[0];
+	scaledAabbMax[1] = m_localScaling.getY() <= 0. ? aabbMin[1] * invLocalScaling[1] : aabbMax[1] * invLocalScaling[1];
+	scaledAabbMax[2] = m_localScaling.getZ() <= 0. ? aabbMin[2] * invLocalScaling[2] : aabbMax[2] * invLocalScaling[2];
+	
+	
+	m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax);
+}
+
+
+void	btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin();
+	btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax();
+
+	btVector3 tmpLocalAabbMin = localAabbMin * m_localScaling;
+	btVector3 tmpLocalAabbMax = localAabbMax * m_localScaling;
+
+	localAabbMin[0] = (m_localScaling.getX() >= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+	localAabbMin[1] = (m_localScaling.getY() >= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+	localAabbMin[2] = (m_localScaling.getZ() >= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+	localAabbMax[0] = (m_localScaling.getX() <= 0.) ? tmpLocalAabbMin[0] : tmpLocalAabbMax[0];
+	localAabbMax[1] = (m_localScaling.getY() <= 0.) ? tmpLocalAabbMin[1] : tmpLocalAabbMax[1];
+	localAabbMax[2] = (m_localScaling.getZ() <= 0.) ? tmpLocalAabbMin[2] : tmpLocalAabbMax[2];
+
+	btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+	btScalar margin = m_bvhTriMeshShape->getMargin();
+	localHalfExtents += btVector3(margin,margin,margin);
+	btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+	
+	btMatrix3x3 abs_b = trans.getBasis().absolute();  
+
+	btVector3 center = trans(localCenter);
+
+	btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+		   abs_b[1].dot(localHalfExtents),
+		  abs_b[2].dot(localHalfExtents));
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+
+}
+
+void	btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+}
+
+const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const
+{
+	return m_localScaling;
+}
+
+void	btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	///don't make this a movable object!
+//	btAssert(0);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
new file mode 100644
index 0000000..d720b1b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h
@@ -0,0 +1,62 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+
+
+///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape.
+///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling'
+ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape
+{
+	
+	
+	btVector3	m_localScaling;
+
+	btBvhTriangleMeshShape*	m_bvhTriMeshShape;
+
+public:
+
+
+	btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,const btVector3& localScaling);
+
+	virtual ~btScaledBvhTriangleMeshShape();
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	btBvhTriangleMeshShape*	getChildShape()
+	{
+		return m_bvhTriMeshShape;
+	}
+
+	const btBvhTriangleMeshShape*	getChildShape() const
+	{
+		return m_bvhTriMeshShape;
+	}
+
+	//debugging
+	virtual const char*	getName()const {return "SCALEDBVHTRIANGLEMESH";}
+
+};
+
+#endif //BVH_TRIANGLE_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
new file mode 100644
index 0000000..3beaf86
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btShapeHull.cpp
@@ -0,0 +1,170 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//btShapeHull was implemented by John McCutchan.
+
+
+#include "btShapeHull.h"
+#include "LinearMath/btConvexHull.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+btShapeHull::btShapeHull (const btConvexShape* shape)
+{
+	m_shape = shape;
+	m_vertices.clear ();
+	m_indices.clear();
+	m_numIndices = 0;
+}
+
+btShapeHull::~btShapeHull ()
+{
+	m_indices.clear();	
+	m_vertices.clear ();
+}
+
+bool
+btShapeHull::buildHull (btScalar /*margin*/)
+{
+	int numSampleDirections = NUM_UNITSPHERE_POINTS;
+	{
+		int numPDA = m_shape->getNumPreferredPenetrationDirections();
+		if (numPDA)
+		{
+			for (int i=0;i<numPDA;i++)
+			{
+				btVector3 norm;
+				m_shape->getPreferredPenetrationDirection(i,norm);
+				getUnitSpherePoints()[numSampleDirections] = norm;
+				numSampleDirections++;
+			}
+		}
+	}
+
+	btVector3 supportPoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	int i;
+	for (i = 0; i < numSampleDirections; i++)
+	{
+		supportPoints[i] = m_shape->localGetSupportingVertex(getUnitSpherePoints()[i]);
+	}
+
+	HullDesc hd;
+	hd.mFlags = QF_TRIANGLES;
+	hd.mVcount = static_cast<unsigned int>(numSampleDirections);
+
+#ifdef BT_USE_DOUBLE_PRECISION
+	hd.mVertices = &supportPoints[0];
+	hd.mVertexStride = sizeof(btVector3);
+#else
+	hd.mVertices = &supportPoints[0];
+	hd.mVertexStride = sizeof (btVector3);
+#endif
+
+	HullLibrary hl;
+	HullResult hr;
+	if (hl.CreateConvexHull (hd, hr) == QE_FAIL)
+	{
+		return false;
+	}
+
+	m_vertices.resize (static_cast<int>(hr.mNumOutputVertices));
+
+
+	for (i = 0; i < static_cast<int>(hr.mNumOutputVertices); i++)
+	{
+		m_vertices[i] = hr.m_OutputVertices[i];
+	}
+	m_numIndices = hr.mNumIndices;
+	m_indices.resize(static_cast<int>(m_numIndices));
+	for (i = 0; i < static_cast<int>(m_numIndices); i++)
+	{
+		m_indices[i] = hr.m_Indices[i];
+	}
+
+	// free temporary hull result that we just copied
+	hl.ReleaseResult (hr);
+
+	return true;
+}
+
+int
+btShapeHull::numTriangles () const
+{
+	return static_cast<int>(m_numIndices / 3);
+}
+
+int
+btShapeHull::numVertices () const
+{
+	return m_vertices.size ();
+}
+
+int
+btShapeHull::numIndices () const
+{
+	return static_cast<int>(m_numIndices);
+}
+
+
+btVector3* btShapeHull::getUnitSpherePoints()
+{
+	static btVector3 sUnitSpherePoints[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = 
+	{
+		btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
+		btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
+		btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
+		btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
+		btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
+		btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
+		btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
+		btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
+		btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
+		btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
+		btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
+		btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
+		btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
+		btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
+		btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
+		btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
+		btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
+		btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
+		btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
+		btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
+		btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
+		btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
+		btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
+		btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
+		btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+		btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
+		btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+		btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
+		btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
+		btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+		btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
+		btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+		btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
+		btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
+		btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
+		btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
+		btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
+		btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
+		btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
+		btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
+		btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
+		btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
+	};
+	return sUnitSpherePoints;
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btShapeHull.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btShapeHull.h
new file mode 100644
index 0000000..07b3500
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btShapeHull.h
@@ -0,0 +1,59 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///btShapeHull implemented by John McCutchan.
+
+#ifndef _SHAPE_HULL_H
+#define _SHAPE_HULL_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+
+///The btShapeHull class takes a btConvexShape, builds a simplified convex hull using btConvexHull and provides triangle indices and vertices.
+///It can be useful for to simplify a complex convex object and for visualization of a non-polyhedral convex object.
+///It approximates the convex hull using the supporting vertex of 42 directions.
+class btShapeHull
+{
+protected:
+
+	btAlignedObjectArray<btVector3> m_vertices;
+	btAlignedObjectArray<unsigned int> m_indices;
+	unsigned int m_numIndices;
+	const btConvexShape* m_shape;
+
+	static btVector3* getUnitSpherePoints();
+
+public:
+	btShapeHull (const btConvexShape* shape);
+	~btShapeHull ();
+
+	bool buildHull (btScalar margin);
+
+	int numTriangles () const;
+	int numVertices () const;
+	int numIndices () const;
+
+	const btVector3* getVertexPointer() const
+	{
+		return &m_vertices[0];
+	}
+	const unsigned int* getIndexPointer() const
+	{
+		return &m_indices[0];
+	}
+};
+
+#endif //_SHAPE_HULL_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
new file mode 100644
index 0000000..b9a736c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btSphereShape.cpp
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btQuaternion.h"
+
+btVector3	btSphereShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	(void)vec;
+	return btVector3(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void	btSphereShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	(void)vectors;
+
+	for (int i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i].setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	}
+}
+
+
+btVector3	btSphereShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 supVertex;
+	supVertex = localGetSupportingVertexWithoutMargin(vec);
+
+	btVector3 vecnorm = vec;
+	if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
+	{
+		vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
+	} 
+	vecnorm.normalize();
+	supVertex+= getMargin() * vecnorm;
+	return supVertex;
+}
+
+
+//broken due to scaling
+void btSphereShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	const btVector3& center = t.getOrigin();
+	btVector3 extent(getMargin(),getMargin(),getMargin());
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+}
+
+
+
+void	btSphereShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	btScalar elem = btScalar(0.4) * mass * getMargin()*getMargin();
+	inertia.setValue(elem,elem,elem);
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btSphereShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btSphereShape.h
new file mode 100644
index 0000000..f983724
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btSphereShape.h
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef SPHERE_MINKOWSKI_H
+#define SPHERE_MINKOWSKI_H
+
+#include "btConvexInternalShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btSphereShape implements an implicit sphere, centered around a local origin with radius.
+ATTRIBUTE_ALIGNED16(class) btSphereShape : public btConvexInternalShape
+
+{
+	
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btSphereShape (btScalar radius) : btConvexInternalShape ()
+	{
+		m_shapeType = SPHERE_SHAPE_PROXYTYPE;
+		m_implicitShapeDimensions.setX(radius);
+		m_collisionMargin = radius;
+	}
+	
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+	//notice that the vectors should be unit length
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+	btScalar	getRadius() const { return m_implicitShapeDimensions.getX() * m_localScaling.getX();}
+
+	void	setUnscaledRadius(btScalar	radius)
+	{
+		m_implicitShapeDimensions.setX(radius);
+		btConvexInternalShape::setMargin(radius);
+	}
+
+	//debugging
+	virtual const char*	getName()const {return "SPHERE";}
+
+	virtual void	setMargin(btScalar margin)
+	{
+		btConvexInternalShape::setMargin(margin);
+	}
+	virtual btScalar	getMargin() const
+	{
+		//to improve gjk behaviour, use radius+margin as the full margin, so never get into the penetration case
+		//this means, non-uniform scaling is not supported anymore
+		return getRadius();
+	}
+
+
+};
+
+
+#endif //SPHERE_MINKOWSKI_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
new file mode 100644
index 0000000..38ef8f0
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.cpp
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btStaticPlaneShape.h"
+
+#include "LinearMath/btTransformUtil.h"
+
+
+btStaticPlaneShape::btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
+: btConcaveShape (), m_planeNormal(planeNormal.normalized()),
+m_planeConstant(planeConstant),
+m_localScaling(btScalar(0.),btScalar(0.),btScalar(0.))
+{
+	m_shapeType = STATIC_PLANE_PROXYTYPE;
+	//	btAssert( btFuzzyZero(m_planeNormal.length() - btScalar(1.)) );
+}
+
+
+btStaticPlaneShape::~btStaticPlaneShape()
+{
+}
+
+
+
+void btStaticPlaneShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	(void)t;
+	/*
+	btVector3 infvec (btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+	btVector3 center = m_planeNormal*m_planeConstant;
+	aabbMin = center + infvec*m_planeNormal;
+	aabbMax = aabbMin;
+	aabbMin.setMin(center - infvec*m_planeNormal);
+	aabbMax.setMax(center - infvec*m_planeNormal); 
+	*/
+
+	aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+	aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+
+}
+
+
+
+
+void	btStaticPlaneShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+
+	btVector3 halfExtents = (aabbMax - aabbMin) * btScalar(0.5);
+	btScalar radius = halfExtents.length();
+	btVector3 center = (aabbMax + aabbMin) * btScalar(0.5);
+	
+	//this is where the triangles are generated, given AABB and plane equation (normal/constant)
+
+	btVector3 tangentDir0,tangentDir1;
+
+	//tangentDir0/tangentDir1 can be precalculated
+	btPlaneSpace1(m_planeNormal,tangentDir0,tangentDir1);
+
+	btVector3 supVertex0,supVertex1;
+
+	btVector3 projectedCenter = center - (m_planeNormal.dot(center) - m_planeConstant)*m_planeNormal;
+	
+	btVector3 triangle[3];
+	triangle[0] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
+	triangle[1] = projectedCenter + tangentDir0*radius - tangentDir1*radius;
+	triangle[2] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
+
+	callback->processTriangle(triangle,0,0);
+
+	triangle[0] = projectedCenter - tangentDir0*radius - tangentDir1*radius;
+	triangle[1] = projectedCenter - tangentDir0*radius + tangentDir1*radius;
+	triangle[2] = projectedCenter + tangentDir0*radius + tangentDir1*radius;
+
+	callback->processTriangle(triangle,0,1);
+
+}
+
+void	btStaticPlaneShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	(void)mass;
+
+	//moving concave objects not supported
+	
+	inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+void	btStaticPlaneShape::setLocalScaling(const btVector3& scaling)
+{
+	m_localScaling = scaling;
+}
+const btVector3& btStaticPlaneShape::getLocalScaling() const
+{
+	return m_localScaling;
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
new file mode 100644
index 0000000..beb53ef
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStaticPlaneShape.h
@@ -0,0 +1,103 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef STATIC_PLANE_SHAPE_H
+#define STATIC_PLANE_SHAPE_H
+
+#include "btConcaveShape.h"
+
+
+///The btStaticPlaneShape simulates an infinite non-moving (static) collision plane.
+ATTRIBUTE_ALIGNED16(class) btStaticPlaneShape : public btConcaveShape
+{
+protected:
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	
+	btVector3	m_planeNormal;
+	btScalar      m_planeConstant;
+	btVector3	m_localScaling;
+
+public:
+	btStaticPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
+
+	virtual ~btStaticPlaneShape();
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+	
+	const btVector3&	getPlaneNormal() const
+	{
+		return	m_planeNormal;
+	}
+
+	const btScalar&	getPlaneConstant() const
+	{
+		return	m_planeConstant;
+	}
+
+	//debugging
+	virtual const char*	getName()const {return "STATICPLANE";}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btStaticPlaneShapeData
+{
+	btCollisionShapeData	m_collisionShapeData;
+
+	btVector3FloatData	m_localScaling;
+	btVector3FloatData	m_planeNormal;
+	float			m_planeConstant;
+	char	m_pad[4];
+};
+
+
+SIMD_FORCE_INLINE	int	btStaticPlaneShape::calculateSerializeBufferSize() const
+{
+	return sizeof(btStaticPlaneShapeData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btStaticPlaneShape::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*) dataBuffer;
+	btCollisionShape::serialize(&planeData->m_collisionShapeData,serializer);
+
+	m_localScaling.serializeFloat(planeData->m_localScaling);
+	m_planeNormal.serializeFloat(planeData->m_planeNormal);
+	planeData->m_planeConstant = float(m_planeConstant);
+		
+	return "btStaticPlaneShapeData";
+}
+
+
+#endif //STATIC_PLANE_SHAPE_H
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
new file mode 100644
index 0000000..8624531
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.cpp
@@ -0,0 +1,331 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btSerializer.h"
+
+btStridingMeshInterface::~btStridingMeshInterface()
+{
+
+}
+
+
+void	btStridingMeshInterface::InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	(void)aabbMin;
+	(void)aabbMax;
+	int numtotalphysicsverts = 0;
+	int part,graphicssubparts = getNumSubParts();
+	const unsigned char * vertexbase;
+	const unsigned char * indexbase;
+	int indexstride;
+	PHY_ScalarType type;
+	PHY_ScalarType gfxindextype;
+	int stride,numverts,numtriangles;
+	int gfxindex;
+	btVector3 triangle[3];
+
+	btVector3 meshScaling = getScaling();
+
+	///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+	for (part=0;part<graphicssubparts ;part++)
+	{
+		getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
+		numtotalphysicsverts+=numtriangles*3; //upper bound
+
+		///unlike that developers want to pass in double-precision meshes in single-precision Bullet build
+		///so disable this feature by default
+		///see patch http://code.google.com/p/bullet/issues/detail?id=213
+
+		switch (type)
+		{
+		case PHY_FLOAT:
+		 {
+
+			 float* graphicsbase;
+
+			 switch (gfxindextype)
+			 {
+			 case PHY_INTEGER:
+				 {
+					 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+					 {
+						 unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+						 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+						 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+						 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+						 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+					 }
+					 break;
+				 }
+			 case PHY_SHORT:
+				 {
+					 for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+					 {
+						 unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+						 graphicsbase = (float*)(vertexbase+tri_indices[0]*stride);
+						 triangle[0].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[1]*stride);
+						 triangle[1].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 graphicsbase = (float*)(vertexbase+tri_indices[2]*stride);
+						 triangle[2].setValue(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),	graphicsbase[2]*meshScaling.getZ());
+						 callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+					 }
+					 break;
+				 }
+			 default:
+				 btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+			 }
+			 break;
+		 }
+
+		case PHY_DOUBLE:
+			{
+				double* graphicsbase;
+
+				switch (gfxindextype)
+				{
+				case PHY_INTEGER:
+					{
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+							graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+							triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+							triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+							triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+						}
+						break;
+					}
+				case PHY_SHORT:
+					{
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+							graphicsbase = (double*)(vertexbase+tri_indices[0]*stride);
+							triangle[0].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),(btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[1]*stride);
+							triangle[1].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							graphicsbase = (double*)(vertexbase+tri_indices[2]*stride);
+							triangle[2].setValue((btScalar)graphicsbase[0]*meshScaling.getX(),(btScalar)graphicsbase[1]*meshScaling.getY(),  (btScalar)graphicsbase[2]*meshScaling.getZ());
+							callback->internalProcessTriangleIndex(triangle,part,gfxindex);
+						}
+						break;
+					}
+				default:
+					btAssert((gfxindextype == PHY_INTEGER) || (gfxindextype == PHY_SHORT));
+				}
+				break;
+			}
+		default:
+			btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+		}
+
+		unLockReadOnlyVertexBase(part);
+	}
+}
+
+void	btStridingMeshInterface::calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax)
+{
+
+	struct	AabbCalculationCallback : public btInternalTriangleIndexCallback
+	{
+		btVector3	m_aabbMin;
+		btVector3	m_aabbMax;
+
+		AabbCalculationCallback()
+		{
+			m_aabbMin.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+			m_aabbMax.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
+		{
+			(void)partId;
+			(void)triangleIndex;
+
+			m_aabbMin.setMin(triangle[0]);
+			m_aabbMax.setMax(triangle[0]);
+			m_aabbMin.setMin(triangle[1]);
+			m_aabbMax.setMax(triangle[1]);
+			m_aabbMin.setMin(triangle[2]);
+			m_aabbMax.setMax(triangle[2]);
+		}
+	};
+
+	//first calculate the total aabb for all triangles
+	AabbCalculationCallback	aabbCallback;
+	aabbMin.setValue(btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT),btScalar(-BT_LARGE_FLOAT));
+	aabbMax.setValue(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	InternalProcessAllTriangles(&aabbCallback,aabbMin,aabbMax);
+
+	aabbMin = aabbCallback.m_aabbMin;
+	aabbMax = aabbCallback.m_aabbMax;
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char*	btStridingMeshInterface::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btStridingMeshInterfaceData* trimeshData = (btStridingMeshInterfaceData*) dataBuffer;
+
+	trimeshData->m_numMeshParts = getNumSubParts();
+
+	//void* uniquePtr = 0;
+
+	trimeshData->m_meshPartsPtr = 0;
+
+	if (trimeshData->m_numMeshParts)
+	{
+		btChunk* chunk = serializer->allocate(sizeof(btMeshPartData),trimeshData->m_numMeshParts);
+		btMeshPartData* memPtr = (btMeshPartData*)chunk->m_oldPtr;
+		trimeshData->m_meshPartsPtr = (btMeshPartData *)serializer->getUniquePointer(memPtr);
+
+
+	//	int numtotalphysicsverts = 0;
+		int part,graphicssubparts = getNumSubParts();
+		const unsigned char * vertexbase;
+		const unsigned char * indexbase;
+		int indexstride;
+		PHY_ScalarType type;
+		PHY_ScalarType gfxindextype;
+		int stride,numverts,numtriangles;
+		int gfxindex;
+	//	btVector3 triangle[3];
+
+		btVector3 meshScaling = getScaling();
+
+		///if the number of parts is big, the performance might drop due to the innerloop switch on indextype
+		for (part=0;part<graphicssubparts ;part++,memPtr++)
+		{
+			getLockedReadOnlyVertexIndexBase(&vertexbase,numverts,type,stride,&indexbase,indexstride,numtriangles,gfxindextype,part);
+			memPtr->m_numTriangles = numtriangles;//indices = 3*numtriangles
+			memPtr->m_numVertices = numverts;
+			memPtr->m_indices16 = 0;
+			memPtr->m_indices32 = 0;
+			memPtr->m_3indices16 = 0;
+			memPtr->m_vertices3f = 0;
+			memPtr->m_vertices3d = 0;
+
+			switch (gfxindextype)
+			{
+			case PHY_INTEGER:
+				{
+					int numindices = numtriangles*3;
+				
+					if (numindices)
+					{
+						btChunk* chunk = serializer->allocate(sizeof(btIntIndexData),numindices);
+						btIntIndexData* tmpIndices = (btIntIndexData*)chunk->m_oldPtr;
+						memPtr->m_indices32 = (btIntIndexData*)serializer->getUniquePointer(tmpIndices);
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned int* tri_indices= (unsigned int*)(indexbase+gfxindex*indexstride);
+							tmpIndices[gfxindex*3].m_value = tri_indices[0];
+							tmpIndices[gfxindex*3+1].m_value = tri_indices[1];
+							tmpIndices[gfxindex*3+2].m_value = tri_indices[2];
+						}
+						serializer->finalizeChunk(chunk,"btIntIndexData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+					}
+					break;
+				}
+			case PHY_SHORT:
+				{
+					if (numtriangles)
+					{
+						btChunk* chunk = serializer->allocate(sizeof(btShortIntIndexTripletData),numtriangles);
+						btShortIntIndexTripletData* tmpIndices = (btShortIntIndexTripletData*)chunk->m_oldPtr;
+						memPtr->m_3indices16 = (btShortIntIndexTripletData*) serializer->getUniquePointer(tmpIndices);
+						for (gfxindex=0;gfxindex<numtriangles;gfxindex++)
+						{
+							unsigned short int* tri_indices= (unsigned short int*)(indexbase+gfxindex*indexstride);
+							tmpIndices[gfxindex].m_values[0] = tri_indices[0];
+							tmpIndices[gfxindex].m_values[1] = tri_indices[1];
+							tmpIndices[gfxindex].m_values[2] = tri_indices[2];
+						}
+						serializer->finalizeChunk(chunk,"btShortIntIndexTripletData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+					}
+					break;
+				}
+			default:
+				{
+					btAssert(0);
+					//unknown index type
+				}
+			}
+
+			switch (type)
+			{
+			case PHY_FLOAT:
+			 {
+				 float* graphicsbase;
+
+				 if (numverts)
+				 {
+					 btChunk* chunk = serializer->allocate(sizeof(btVector3FloatData),numverts);
+					 btVector3FloatData* tmpVertices = (btVector3FloatData*) chunk->m_oldPtr;
+					 memPtr->m_vertices3f = (btVector3FloatData *)serializer->getUniquePointer(tmpVertices);
+					 for (int i=0;i<numverts;i++)
+					 {
+						 graphicsbase = (float*)(vertexbase+i*stride);
+						 tmpVertices[i].m_floats[0] = graphicsbase[0];
+						 tmpVertices[i].m_floats[1] = graphicsbase[1];
+						 tmpVertices[i].m_floats[2] = graphicsbase[2];
+					 }
+					 serializer->finalizeChunk(chunk,"btVector3FloatData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+				 }
+				 break;
+				}
+
+			case PHY_DOUBLE:
+				{
+					if (numverts)
+					{
+						btChunk* chunk = serializer->allocate(sizeof(btVector3DoubleData),numverts);
+						btVector3DoubleData* tmpVertices = (btVector3DoubleData*) chunk->m_oldPtr;
+						memPtr->m_vertices3d = (btVector3DoubleData *) serializer->getUniquePointer(tmpVertices);
+						for (int i=0;i<numverts;i++)
+					 {
+						 double* graphicsbase = (double*)(vertexbase+i*stride);//for now convert to float, might leave it at double
+						 tmpVertices[i].m_floats[0] = graphicsbase[0];
+						 tmpVertices[i].m_floats[1] = graphicsbase[1];
+						 tmpVertices[i].m_floats[2] = graphicsbase[2];
+					 }
+						serializer->finalizeChunk(chunk,"btVector3DoubleData",BT_ARRAY_CODE,(void*)chunk->m_oldPtr);
+					}
+					break;
+				}
+
+			default:
+				btAssert((type == PHY_FLOAT) || (type == PHY_DOUBLE));
+			}
+
+			unLockReadOnlyVertexBase(part);
+		}
+
+		serializer->finalizeChunk(chunk,"btMeshPartData",BT_ARRAY_CODE,chunk->m_oldPtr);
+	}
+
+
+	m_scaling.serializeFloat(trimeshData->m_scaling);
+	return "btStridingMeshInterfaceData";
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
new file mode 100644
index 0000000..e0c1b54
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btStridingMeshInterface.h
@@ -0,0 +1,154 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef STRIDING_MESHINTERFACE_H
+#define STRIDING_MESHINTERFACE_H
+
+#include "LinearMath/btVector3.h"
+#include "btTriangleCallback.h"
+#include "btConcaveShape.h"
+
+
+
+
+
+///	The btStridingMeshInterface is the interface class for high performance generic access to triangle meshes, used in combination with btBvhTriangleMeshShape and some other collision shapes.
+/// Using index striding of 3*sizeof(integer) it can use triangle arrays, using index striding of 1*sizeof(integer) it can handle triangle strips.
+/// It allows for sharing graphics and collision meshes. Also it provides locking/unlocking of graphics meshes that are in gpu memory.
+class  btStridingMeshInterface
+{
+	protected:
+	
+		btVector3 m_scaling;
+
+	public:
+		btStridingMeshInterface() :m_scaling(btScalar(1.),btScalar(1.),btScalar(1.))
+		{
+
+		}
+
+		virtual ~btStridingMeshInterface();
+
+
+
+		virtual void	InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+		///brute force method to calculate aabb
+		void	calculateAabbBruteForce(btVector3& aabbMin,btVector3& aabbMax);
+
+		/// get read and write access to a subpart of a triangle mesh
+		/// this subpart has a continuous array of vertices and indices
+		/// in this way the mesh can be handled as chunks of memory with striding
+		/// very similar to OpenGL vertexarray support
+		/// make a call to unLockVertexBase when the read and write access is finished	
+		virtual void	getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0)=0;
+		
+		virtual void	getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& stride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const=0;
+	
+		/// unLockVertexBase finishes the access to a subpart of the triangle mesh
+		/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+		virtual void	unLockVertexBase(int subpart)=0;
+
+		virtual void	unLockReadOnlyVertexBase(int subpart) const=0;
+
+
+		/// getNumSubParts returns the number of seperate subparts
+		/// each subpart has a continuous array of vertices and indices
+		virtual int		getNumSubParts() const=0;
+
+		virtual void	preallocateVertices(int numverts)=0;
+		virtual void	preallocateIndices(int numindices)=0;
+
+		virtual bool	hasPremadeAabb() const { return false; }
+		virtual void	setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
+                {
+                        (void) aabbMin;
+                        (void) aabbMax;
+                }
+		virtual void	getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+        {
+            (void) aabbMin;
+            (void) aabbMax;
+        }
+
+		const btVector3&	getScaling() const {
+			return m_scaling;
+		}
+		void	setScaling(const btVector3& scaling)
+		{
+			m_scaling = scaling;
+		}
+
+		virtual	int	calculateSerializeBufferSize() const;
+
+		///fills the dataBuffer and returns the struct name (and 0 on failure)
+		virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+
+};
+
+struct	btIntIndexData
+{
+	int	m_value;
+};
+
+struct	btShortIntIndexData
+{
+	short m_value;
+	char m_pad[2];
+};
+
+struct	btShortIntIndexTripletData
+{
+	short	m_values[3];
+	char	m_pad[2];
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btMeshPartData
+{
+	btVector3FloatData			*m_vertices3f;
+	btVector3DoubleData			*m_vertices3d;
+
+	btIntIndexData				*m_indices32;
+	btShortIntIndexTripletData	*m_3indices16;
+
+	btShortIntIndexData			*m_indices16;//backwards compatibility
+
+	int                     m_numTriangles;//length of m_indices = m_numTriangles
+	int                     m_numVertices;
+};
+
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct	btStridingMeshInterfaceData
+{
+	btMeshPartData	*m_meshPartsPtr;
+	btVector3FloatData	m_scaling;
+	int	m_numMeshParts;
+	char m_padding[4];
+};
+
+
+
+
+SIMD_FORCE_INLINE	int	btStridingMeshInterface::calculateSerializeBufferSize() const
+{
+	return sizeof(btStridingMeshInterfaceData);
+}
+
+
+
+#endif //STRIDING_MESHINTERFACE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
new file mode 100644
index 0000000..52f346b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.cpp
@@ -0,0 +1,218 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTetrahedronShape.h"
+#include "LinearMath/btMatrix3x3.h"
+
+btBU_Simplex1to4::btBU_Simplex1to4() : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+	addVertex(pt1);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+	addVertex(pt1);
+	addVertex(pt2);
+}
+
+btBU_Simplex1to4::btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3) : btPolyhedralConvexAabbCachingShape (),
+m_numVertices(0)
+{
+	m_shapeType = TETRAHEDRAL_SHAPE_PROXYTYPE;
+	addVertex(pt0);
+	addVertex(pt1);
+	addVertex(pt2);
+	addVertex(pt3);
+}
+
+
+void btBU_Simplex1to4::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+#if 1
+	btPolyhedralConvexAabbCachingShape::getAabb(t,aabbMin,aabbMax);
+#else
+	aabbMin.setValue(BT_LARGE_FLOAT,BT_LARGE_FLOAT,BT_LARGE_FLOAT);
+	aabbMax.setValue(-BT_LARGE_FLOAT,-BT_LARGE_FLOAT,-BT_LARGE_FLOAT);
+
+	//just transform the vertices in worldspace, and take their AABB
+	for (int i=0;i<m_numVertices;i++)
+	{
+		btVector3 worldVertex = t(m_vertices[i]);
+		aabbMin.setMin(worldVertex);
+		aabbMax.setMax(worldVertex);
+	}
+#endif
+}
+
+
+
+
+
+void btBU_Simplex1to4::addVertex(const btVector3& pt)
+{
+	m_vertices[m_numVertices++] = pt;
+	recalcLocalAabb();
+}
+
+
+int	btBU_Simplex1to4::getNumVertices() const
+{
+	return m_numVertices;
+}
+
+int btBU_Simplex1to4::getNumEdges() const
+{
+	//euler formula, F-E+V = 2, so E = F+V-2
+
+	switch (m_numVertices)
+	{
+	case 0:
+		return 0;
+	case 1: return 0;
+	case 2: return 1;
+	case 3: return 3;
+	case 4: return 6;
+
+
+	}
+
+	return 0;
+}
+
+void btBU_Simplex1to4::getEdge(int i,btVector3& pa,btVector3& pb) const
+{
+	
+    switch (m_numVertices)
+	{
+
+	case 2: 
+		pa = m_vertices[0];
+		pb = m_vertices[1];
+		break;
+	case 3:  
+		switch (i)
+		{
+		case 0:
+			pa = m_vertices[0];
+			pb = m_vertices[1];
+			break;
+		case 1:
+			pa = m_vertices[1];
+			pb = m_vertices[2];
+			break;
+		case 2:
+			pa = m_vertices[2];
+			pb = m_vertices[0];
+			break;
+
+		}
+		break;
+	case 4: 
+		switch (i)
+		{
+		case 0:
+			pa = m_vertices[0];
+			pb = m_vertices[1];
+			break;
+		case 1:
+			pa = m_vertices[1];
+			pb = m_vertices[2];
+			break;
+		case 2:
+			pa = m_vertices[2];
+			pb = m_vertices[0];
+			break;
+		case 3:
+			pa = m_vertices[0];
+			pb = m_vertices[3];
+			break;
+		case 4:
+			pa = m_vertices[1];
+			pb = m_vertices[3];
+			break;
+		case 5:
+			pa = m_vertices[2];
+			pb = m_vertices[3];
+			break;
+		}
+
+	}
+
+
+
+
+}
+
+void btBU_Simplex1to4::getVertex(int i,btVector3& vtx) const
+{
+	vtx = m_vertices[i];
+}
+
+int	btBU_Simplex1to4::getNumPlanes() const
+{
+	switch (m_numVertices)
+	{
+	case 0:
+			return 0;
+	case 1:
+			return 0;
+	case 2:
+			return 0;
+	case 3:
+			return 2;
+	case 4:
+			return 4;
+	default:
+		{
+		}
+	}
+	return 0;
+}
+
+
+void btBU_Simplex1to4::getPlane(btVector3&, btVector3& ,int ) const
+{
+	
+}
+
+int btBU_Simplex1to4::getIndex(int ) const
+{
+	return 0;
+}
+
+bool btBU_Simplex1to4::isInside(const btVector3& ,btScalar ) const
+{
+	return false;
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
new file mode 100644
index 0000000..72e9f23
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTetrahedronShape.h
@@ -0,0 +1,74 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BU_SIMPLEX_1TO4_SHAPE
+#define BU_SIMPLEX_1TO4_SHAPE
+
+
+#include "btPolyhedralConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+
+
+///The btBU_Simplex1to4 implements tetrahedron, triangle, line, vertex collision shapes. In most cases it is better to use btConvexHullShape instead.
+class btBU_Simplex1to4 : public btPolyhedralConvexAabbCachingShape
+{
+protected:
+
+	int	m_numVertices;
+	btVector3	m_vertices[4];
+
+public:
+	btBU_Simplex1to4();
+
+	btBU_Simplex1to4(const btVector3& pt0);
+	btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1);
+	btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2);
+	btBU_Simplex1to4(const btVector3& pt0,const btVector3& pt1,const btVector3& pt2,const btVector3& pt3);
+
+    
+	void	reset()
+	{
+		m_numVertices = 0;
+	}
+	
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	void addVertex(const btVector3& pt);
+
+	//PolyhedralConvexShape interface
+
+	virtual int	getNumVertices() const;
+
+	virtual int getNumEdges() const;
+
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const;
+	
+	virtual void getVertex(int i,btVector3& vtx) const;
+
+	virtual int	getNumPlanes() const;
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const;
+
+	virtual int getIndex(int i) const;
+
+	virtual	bool isInside(const btVector3& pt,btScalar tolerance) const;
+
+
+	///getName is for debugging
+	virtual const char*	getName()const { return "btBU_Simplex1to4";}
+
+};
+
+#endif //BU_SIMPLEX_1TO4_SHAPE
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
new file mode 100644
index 0000000..3027e65
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.cpp
@@ -0,0 +1,35 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleBuffer.h"
+
+
+
+
+
+
+
+void btTriangleBuffer::processTriangle(btVector3* triangle,int partId,int  triangleIndex)
+{
+		btTriangle	tri;
+		tri.m_vertex0 = triangle[0];
+		tri.m_vertex1 = triangle[1];
+		tri.m_vertex2 = triangle[2];
+		tri.m_partId = partId;
+		tri.m_triangleIndex = triangleIndex;
+			
+		m_triangleBuffer.push_back(tri);
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
new file mode 100644
index 0000000..b71fc8b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleBuffer.h
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_BUFFER_H
+#define BT_TRIANGLE_BUFFER_H
+
+#include "btTriangleCallback.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+struct	btTriangle
+{
+	btVector3	m_vertex0;
+	btVector3	m_vertex1;
+	btVector3	m_vertex2;
+	int	m_partId;
+	int	m_triangleIndex;
+};
+
+///The btTriangleBuffer callback can be useful to collect and store overlapping triangles between AABB and concave objects that support 'processAllTriangles'
+///Example usage of this class:
+///			btTriangleBuffer	triBuf;
+///			concaveShape->processAllTriangles(&triBuf,aabbMin, aabbMax);
+///			for (int i=0;i<triBuf.getNumTriangles();i++)
+///			{
+///				const btTriangle& tri = triBuf.getTriangle(i);
+///				//do something useful here with the triangle
+///			}
+class btTriangleBuffer : public btTriangleCallback
+{
+
+	btAlignedObjectArray<btTriangle>	m_triangleBuffer;
+	
+public:
+
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+	
+	int	getNumTriangles() const
+	{
+		return int(m_triangleBuffer.size());
+	}
+	
+	const btTriangle&	getTriangle(int index) const
+	{
+		return m_triangleBuffer[index];
+	}
+
+	void	clearBuffer()
+	{
+		m_triangleBuffer.clear();
+	}
+	
+};
+
+
+#endif //BT_TRIANGLE_BUFFER_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
new file mode 100644
index 0000000..f558bf6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.cpp
@@ -0,0 +1,28 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleCallback.h"
+
+btTriangleCallback::~btTriangleCallback()
+{
+
+}
+
+
+btInternalTriangleIndexCallback::~btInternalTriangleIndexCallback()
+{
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
new file mode 100644
index 0000000..0499702
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleCallback.h
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef TRIANGLE_CALLBACK_H
+#define TRIANGLE_CALLBACK_H
+
+#include "LinearMath/btVector3.h"
+
+
+///The btTriangleCallback provides a callback for each overlapping triangle when calling processAllTriangles.
+///This callback is called by processAllTriangles for all btConcaveShape derived class, such as  btBvhTriangleMeshShape, btStaticPlaneShape and btHeightfieldTerrainShape.
+class btTriangleCallback
+{
+public:
+
+	virtual ~btTriangleCallback();
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) = 0;
+};
+
+class btInternalTriangleIndexCallback
+{
+public:
+
+	virtual ~btInternalTriangleIndexCallback();
+	virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex) = 0;
+};
+
+
+
+#endif //TRIANGLE_CALLBACK_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
new file mode 100644
index 0000000..a665024
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.cpp
@@ -0,0 +1,95 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleIndexVertexArray.h"
+
+btTriangleIndexVertexArray::btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride)
+: m_hasAabb(0)
+{
+	btIndexedMesh mesh;
+
+	mesh.m_numTriangles = numTriangles;
+	mesh.m_triangleIndexBase = (const unsigned char *)triangleIndexBase;
+	mesh.m_triangleIndexStride = triangleIndexStride;
+	mesh.m_numVertices = numVertices;
+	mesh.m_vertexBase = (const unsigned char *)vertexBase;
+	mesh.m_vertexStride = vertexStride;
+
+	addIndexedMesh(mesh);
+
+}
+
+btTriangleIndexVertexArray::~btTriangleIndexVertexArray()
+{
+
+}
+
+void	btTriangleIndexVertexArray::getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart)
+{
+	btAssert(subpart< getNumSubParts() );
+
+	btIndexedMesh& mesh = m_indexedMeshes[subpart];
+
+	numverts = mesh.m_numVertices;
+	(*vertexbase) = (unsigned char *) mesh.m_vertexBase;
+
+   type = mesh.m_vertexType;
+
+	vertexStride = mesh.m_vertexStride;
+
+	numfaces = mesh.m_numTriangles;
+
+	(*indexbase) = (unsigned char *)mesh.m_triangleIndexBase;
+	indexstride = mesh.m_triangleIndexStride;
+	indicestype = mesh.m_indexType;
+}
+
+void	btTriangleIndexVertexArray::getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart) const
+{
+	const btIndexedMesh& mesh = m_indexedMeshes[subpart];
+
+	numverts = mesh.m_numVertices;
+	(*vertexbase) = (const unsigned char *)mesh.m_vertexBase;
+
+   type = mesh.m_vertexType;
+   
+	vertexStride = mesh.m_vertexStride;
+
+	numfaces = mesh.m_numTriangles;
+	(*indexbase) = (const unsigned char *)mesh.m_triangleIndexBase;
+	indexstride = mesh.m_triangleIndexStride;
+	indicestype = mesh.m_indexType;
+}
+
+bool	btTriangleIndexVertexArray::hasPremadeAabb() const
+{
+	return (m_hasAabb == 1);
+}
+
+
+void	btTriangleIndexVertexArray::setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const
+{
+	m_aabbMin = aabbMin;
+	m_aabbMax = aabbMax;
+	m_hasAabb = 1; // this is intentionally an int see notes in header
+}
+
+void	btTriangleIndexVertexArray::getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const
+{
+	*aabbMin = m_aabbMin;
+	*aabbMax = m_aabbMax;
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
new file mode 100644
index 0000000..c64ea6e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h
@@ -0,0 +1,131 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btScalar.h"
+
+
+///The btIndexedMesh indexes a single vertex and index array. Multiple btIndexedMesh objects can be passed into a btTriangleIndexVertexArray using addIndexedMesh.
+///Instead of the number of indices, we pass the number of triangles.
+ATTRIBUTE_ALIGNED16( struct)	btIndexedMesh
+{
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+   int                     m_numTriangles;
+   const unsigned char *   m_triangleIndexBase;
+   int                     m_triangleIndexStride;
+   int                     m_numVertices;
+   const unsigned char *   m_vertexBase;
+   int                     m_vertexStride;
+
+   // The index type is set when adding an indexed mesh to the
+   // btTriangleIndexVertexArray, do not set it manually
+   PHY_ScalarType m_indexType;
+
+   // The vertex type has a default type similar to Bullet's precision mode (float or double)
+   // but can be set manually if you for example run Bullet with double precision but have
+   // mesh data in single precision..
+   PHY_ScalarType m_vertexType;
+
+
+   btIndexedMesh()
+	   :m_indexType(PHY_INTEGER),
+#ifdef BT_USE_DOUBLE_PRECISION
+      m_vertexType(PHY_DOUBLE)
+#else // BT_USE_DOUBLE_PRECISION
+      m_vertexType(PHY_FLOAT)
+#endif // BT_USE_DOUBLE_PRECISION
+      {
+      }
+}
+;
+
+
+typedef btAlignedObjectArray<btIndexedMesh>	IndexedMeshArray;
+
+///The btTriangleIndexVertexArray allows to access multiple triangle meshes, by indexing into existing triangle/index arrays.
+///Additional meshes can be added using addIndexedMesh
+///No duplcate is made of the vertex/index data, it only indexes into external vertex/index arrays.
+///So keep those arrays around during the lifetime of this btTriangleIndexVertexArray.
+ATTRIBUTE_ALIGNED16( class) btTriangleIndexVertexArray : public btStridingMeshInterface
+{
+protected:
+	IndexedMeshArray	m_indexedMeshes;
+	int m_pad[2];
+	mutable int m_hasAabb; // using int instead of bool to maintain alignment
+	mutable btVector3 m_aabbMin;
+	mutable btVector3 m_aabbMax;
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	btTriangleIndexVertexArray() : m_hasAabb(0)
+	{
+	}
+
+	virtual ~btTriangleIndexVertexArray();
+
+	//just to be backwards compatible
+	btTriangleIndexVertexArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,int numVertices,btScalar* vertexBase,int vertexStride);
+	
+	void	addIndexedMesh(const btIndexedMesh& mesh, PHY_ScalarType indexType = PHY_INTEGER)
+	{
+		m_indexedMeshes.push_back(mesh);
+		m_indexedMeshes[m_indexedMeshes.size()-1].m_indexType = indexType;
+	}
+	
+	
+	virtual void	getLockedVertexIndexBase(unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0);
+
+	virtual void	getLockedReadOnlyVertexIndexBase(const unsigned char **vertexbase, int& numverts,PHY_ScalarType& type, int& vertexStride,const unsigned char **indexbase,int & indexstride,int& numfaces,PHY_ScalarType& indicestype,int subpart=0) const;
+
+	/// unLockVertexBase finishes the access to a subpart of the triangle mesh
+	/// make a call to unLockVertexBase when the read and write access (using getLockedVertexIndexBase) is finished
+	virtual void	unLockVertexBase(int subpart) {(void)subpart;}
+
+	virtual void	unLockReadOnlyVertexBase(int subpart) const {(void)subpart;}
+
+	/// getNumSubParts returns the number of seperate subparts
+	/// each subpart has a continuous array of vertices and indices
+	virtual int		getNumSubParts() const { 
+		return (int)m_indexedMeshes.size();
+	}
+
+	IndexedMeshArray&	getIndexedMeshArray()
+	{
+		return m_indexedMeshes;
+	}
+
+	const IndexedMeshArray&	getIndexedMeshArray() const
+	{
+		return m_indexedMeshes;
+	}
+
+	virtual void	preallocateVertices(int numverts){(void) numverts;}
+	virtual void	preallocateIndices(int numindices){(void) numindices;}
+
+	virtual bool	hasPremadeAabb() const;
+	virtual void	setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const;
+	virtual void	getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const;
+
+}
+;
+
+#endif //BT_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
new file mode 100644
index 0000000..dc56294
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.cpp
@@ -0,0 +1,86 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///This file was created by Alex Silverman
+
+#include "btTriangleIndexVertexMaterialArray.h"
+
+btTriangleIndexVertexMaterialArray::btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+                                   int numVertices,btScalar* vertexBase,int vertexStride,
+                                   int numMaterials, unsigned char* materialBase, int materialStride,
+                                   int* triangleMaterialsBase, int materialIndexStride) :
+btTriangleIndexVertexArray(numTriangles, triangleIndexBase, triangleIndexStride, numVertices, vertexBase, vertexStride)
+{
+    btMaterialProperties mat;
+
+    mat.m_numMaterials = numMaterials;
+    mat.m_materialBase = materialBase;
+    mat.m_materialStride = materialStride;
+#ifdef BT_USE_DOUBLE_PRECISION
+    mat.m_materialType = PHY_DOUBLE;
+#else
+    mat.m_materialType = PHY_FLOAT;
+#endif
+
+    mat.m_numTriangles = numTriangles;
+    mat.m_triangleMaterialsBase = (unsigned char *)triangleMaterialsBase;
+    mat.m_triangleMaterialStride = materialIndexStride;
+    mat.m_triangleType = PHY_INTEGER;
+
+    addMaterialProperties(mat);
+}
+
+
+void btTriangleIndexVertexMaterialArray::getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+                                   unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+    btAssert(subpart< getNumSubParts() );
+
+    btMaterialProperties& mats = m_materials[subpart];
+
+    numMaterials = mats.m_numMaterials;
+    (*materialBase) = (unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+    materialType = PHY_DOUBLE;
+#else
+    materialType = PHY_FLOAT;
+#endif
+    materialStride = mats.m_materialStride;
+
+    numTriangles = mats.m_numTriangles;
+    (*triangleMaterialBase) = (unsigned char *)mats.m_triangleMaterialsBase;
+    triangleMaterialStride = mats.m_triangleMaterialStride;
+    triangleType = mats.m_triangleType;
+}
+
+void btTriangleIndexVertexMaterialArray::getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+                                           const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart)
+{
+    btMaterialProperties& mats = m_materials[subpart];
+
+    numMaterials = mats.m_numMaterials;
+    (*materialBase) = (const unsigned char *) mats.m_materialBase;
+#ifdef BT_USE_DOUBLE_PRECISION
+    materialType = PHY_DOUBLE;
+#else
+    materialType = PHY_FLOAT;
+#endif
+    materialStride = mats.m_materialStride;
+
+    numTriangles = mats.m_numTriangles;
+    (*triangleMaterialBase) = (const unsigned char *)mats.m_triangleMaterialsBase;
+    triangleMaterialStride = mats.m_triangleMaterialStride;
+    triangleType = mats.m_triangleType;
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
new file mode 100644
index 0000000..ba4f7b4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleIndexVertexMaterialArray.h
@@ -0,0 +1,84 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///This file was created by Alex Silverman
+
+#ifndef BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+#define BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
+
+#include "btTriangleIndexVertexArray.h"
+
+
+ATTRIBUTE_ALIGNED16( struct)	btMaterialProperties
+{
+    ///m_materialBase ==========> 2 btScalar values make up one material, friction then restitution
+    int m_numMaterials;
+    const unsigned char * m_materialBase;
+    int m_materialStride;
+    PHY_ScalarType m_materialType;
+    ///m_numTriangles <=========== This exists in the btIndexedMesh object for the same subpart, but since we're
+    ///                           padding the structure, it can be reproduced at no real cost
+    ///m_triangleMaterials =====> 1 integer value makes up one entry
+    ///                           eg: m_triangleMaterials[1] = 5; // This will set triangle 2 to use material 5
+    int m_numTriangles; 
+    const unsigned char * m_triangleMaterialsBase;
+    int m_triangleMaterialStride;
+    ///m_triangleType <========== Automatically set in addMaterialProperties
+    PHY_ScalarType m_triangleType;
+};
+
+typedef btAlignedObjectArray<btMaterialProperties>	MaterialArray;
+
+///Teh btTriangleIndexVertexMaterialArray is built on TriangleIndexVertexArray
+///The addition of a material array allows for the utilization of the partID and
+///triangleIndex that are returned in the ContactAddedCallback.  As with
+///TriangleIndexVertexArray, no duplicate is made of the material data, so it
+///is the users responsibility to maintain the array during the lifetime of the
+///TriangleIndexVertexMaterialArray.
+ATTRIBUTE_ALIGNED16(class) btTriangleIndexVertexMaterialArray : public btTriangleIndexVertexArray
+{
+protected:
+    MaterialArray       m_materials;
+		
+public:
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+    btTriangleIndexVertexMaterialArray()
+	{
+	}
+
+    btTriangleIndexVertexMaterialArray(int numTriangles,int* triangleIndexBase,int triangleIndexStride,
+        int numVertices,btScalar* vertexBase,int vertexStride,
+        int numMaterials, unsigned char* materialBase, int materialStride,
+        int* triangleMaterialsBase, int materialIndexStride);
+
+    virtual ~btTriangleIndexVertexMaterialArray() {}
+
+    void	addMaterialProperties(const btMaterialProperties& mat, PHY_ScalarType triangleType = PHY_INTEGER)
+    {
+        m_materials.push_back(mat);
+        m_materials[m_materials.size()-1].m_triangleType = triangleType;
+    }
+
+    virtual void getLockedMaterialBase(unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+        unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType ,int subpart = 0);
+
+    virtual void getLockedReadOnlyMaterialBase(const unsigned char **materialBase, int& numMaterials, PHY_ScalarType& materialType, int& materialStride,
+        const unsigned char ** triangleMaterialBase, int& numTriangles, int& triangleMaterialStride, PHY_ScalarType& triangleType, int subpart = 0);
+
+}
+;
+
+#endif //BT_MULTIMATERIAL_TRIANGLE_INDEX_VERTEX_ARRAY_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
new file mode 100644
index 0000000..282a770
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleInfoMap.h
@@ -0,0 +1,238 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2010 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _BT_TRIANGLE_INFO_MAP_H
+#define _BT_TRIANGLE_INFO_MAP_H
+
+
+#include "LinearMath/btHashMap.h"
+#include "LinearMath/btSerializer.h"
+
+
+///for btTriangleInfo m_flags
+#define TRI_INFO_V0V1_CONVEX 1
+#define TRI_INFO_V1V2_CONVEX 2
+#define TRI_INFO_V2V0_CONVEX 4
+
+#define TRI_INFO_V0V1_SWAP_NORMALB 8
+#define TRI_INFO_V1V2_SWAP_NORMALB 16
+#define TRI_INFO_V2V0_SWAP_NORMALB 32
+
+
+///The btTriangleInfo structure stores information to adjust collision normals to avoid collisions against internal edges
+///it can be generated using 
+struct	btTriangleInfo
+{
+	btTriangleInfo()
+	{
+		m_edgeV0V1Angle = SIMD_2_PI;
+		m_edgeV1V2Angle = SIMD_2_PI;
+		m_edgeV2V0Angle = SIMD_2_PI;
+		m_flags=0;
+	}
+
+	int			m_flags;
+
+	btScalar	m_edgeV0V1Angle;
+	btScalar	m_edgeV1V2Angle;
+	btScalar	m_edgeV2V0Angle;
+
+};
+
+typedef btHashMap<btHashInt,btTriangleInfo> btInternalTriangleInfoMap;
+
+
+///The btTriangleInfoMap stores edge angle information for some triangles. You can compute this information yourself or using btGenerateInternalEdgeInfo.
+struct	btTriangleInfoMap : public btInternalTriangleInfoMap
+{
+	btScalar	m_convexEpsilon;///used to determine if an edge or contact normal is convex, using the dot product
+	btScalar	m_planarEpsilon; ///used to determine if a triangle edge is planar with zero angle
+	btScalar	m_equalVertexThreshold; ///used to compute connectivity: if the distance between two vertices is smaller than m_equalVertexThreshold, they are considered to be 'shared'
+	btScalar	m_edgeDistanceThreshold; ///used to determine edge contacts: if the closest distance between a contact point and an edge is smaller than this distance threshold it is considered to "hit the edge"
+	btScalar	m_zeroAreaThreshold; ///used to determine if a triangle is degenerate (length squared of cross product of 2 triangle edges < threshold)
+	
+	
+	btTriangleInfoMap()
+	{
+		m_convexEpsilon = 0.00f;
+		m_planarEpsilon = 0.0001f;
+		m_equalVertexThreshold = btScalar(0.0001)*btScalar(0.0001);
+		m_edgeDistanceThreshold = btScalar(0.1);
+		m_zeroAreaThreshold = btScalar(0.0001)*btScalar(0.0001);
+	}
+	virtual ~btTriangleInfoMap() {}
+
+	virtual	int	calculateSerializeBufferSize() const;
+
+	///fills the dataBuffer and returns the struct name (and 0 on failure)
+	virtual	const char*	serialize(void* dataBuffer, btSerializer* serializer) const;
+
+	void	deSerialize(struct btTriangleInfoMapData& data);
+
+};
+
+struct	btTriangleInfoData
+{
+	int			m_flags;
+	float	m_edgeV0V1Angle;
+	float	m_edgeV1V2Angle;
+	float	m_edgeV2V0Angle;
+};
+
+struct	btTriangleInfoMapData
+{
+	int					*m_hashTablePtr;
+	int					*m_nextPtr;
+	btTriangleInfoData	*m_valueArrayPtr;
+	int					*m_keyArrayPtr;
+
+	float	m_convexEpsilon;
+	float	m_planarEpsilon;
+	float	m_equalVertexThreshold; 
+	float	m_edgeDistanceThreshold;
+	float	m_zeroAreaThreshold;
+
+	int		m_nextSize;
+	int		m_hashTableSize;
+	int		m_numValues;
+	int		m_numKeys;
+	char	m_padding[4];
+};
+
+SIMD_FORCE_INLINE	int	btTriangleInfoMap::calculateSerializeBufferSize() const
+{
+	return sizeof(btTriangleInfoMapData);
+}
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	const char*	btTriangleInfoMap::serialize(void* dataBuffer, btSerializer* serializer) const
+{
+	btTriangleInfoMapData* tmapData = (btTriangleInfoMapData*) dataBuffer;
+	tmapData->m_convexEpsilon = m_convexEpsilon;
+	tmapData->m_planarEpsilon = m_planarEpsilon;
+	tmapData->m_equalVertexThreshold = m_equalVertexThreshold;
+	tmapData->m_edgeDistanceThreshold = m_edgeDistanceThreshold;
+	tmapData->m_zeroAreaThreshold = m_zeroAreaThreshold;
+	
+	tmapData->m_hashTableSize = m_hashTable.size();
+
+	tmapData->m_hashTablePtr = tmapData->m_hashTableSize ? (int*)serializer->getUniquePointer((void*)&m_hashTable[0]) : 0;
+	if (tmapData->m_hashTablePtr)
+	{ 
+		//serialize an int buffer
+		int sz = sizeof(int);
+		int numElem = tmapData->m_hashTableSize;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		int* memPtr = (int*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			*memPtr = m_hashTable[i];
+		}
+		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_hashTable[0]);
+
+	}
+
+	tmapData->m_nextSize = m_next.size();
+	tmapData->m_nextPtr = tmapData->m_nextSize? (int*)serializer->getUniquePointer((void*)&m_next[0]): 0;
+	if (tmapData->m_nextPtr)
+	{
+		int sz = sizeof(int);
+		int numElem = tmapData->m_nextSize;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		int* memPtr = (int*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			*memPtr = m_next[i];
+		}
+		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*)&m_next[0]);
+	}
+	
+	tmapData->m_numValues = m_valueArray.size();
+	tmapData->m_valueArrayPtr = tmapData->m_numValues ? (btTriangleInfoData*)serializer->getUniquePointer((void*)&m_valueArray[0]): 0;
+	if (tmapData->m_valueArrayPtr)
+	{
+		int sz = sizeof(btTriangleInfoData);
+		int numElem = tmapData->m_numValues;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		btTriangleInfoData* memPtr = (btTriangleInfoData*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			memPtr->m_edgeV0V1Angle = m_valueArray[i].m_edgeV0V1Angle;
+			memPtr->m_edgeV1V2Angle = m_valueArray[i].m_edgeV1V2Angle;
+			memPtr->m_edgeV2V0Angle = m_valueArray[i].m_edgeV2V0Angle;
+			memPtr->m_flags = m_valueArray[i].m_flags;
+		}
+		serializer->finalizeChunk(chunk,"btTriangleInfoData",BT_ARRAY_CODE,(void*) &m_valueArray[0]);
+	}
+	
+	tmapData->m_numKeys = m_keyArray.size();
+	tmapData->m_keyArrayPtr = tmapData->m_numKeys ? (int*)serializer->getUniquePointer((void*)&m_keyArray[0]) : 0;
+	if (tmapData->m_keyArrayPtr)
+	{
+		int sz = sizeof(int);
+		int numElem = tmapData->m_numValues;
+		btChunk* chunk = serializer->allocate(sz,numElem);
+		int* memPtr = (int*)chunk->m_oldPtr;
+		for (int i=0;i<numElem;i++,memPtr++)
+		{
+			*memPtr = m_keyArray[i].getUid1();
+		}
+		serializer->finalizeChunk(chunk,"int",BT_ARRAY_CODE,(void*) &m_keyArray[0]);
+
+	}
+	return "btTriangleInfoMapData";
+}
+
+
+
+///fills the dataBuffer and returns the struct name (and 0 on failure)
+SIMD_FORCE_INLINE	void	btTriangleInfoMap::deSerialize(btTriangleInfoMapData& tmapData )
+{
+
+
+	m_convexEpsilon = tmapData.m_convexEpsilon;
+	m_planarEpsilon = tmapData.m_planarEpsilon;
+	m_equalVertexThreshold = tmapData.m_equalVertexThreshold;
+	m_edgeDistanceThreshold = tmapData.m_edgeDistanceThreshold;
+	m_zeroAreaThreshold = tmapData.m_zeroAreaThreshold;
+	m_hashTable.resize(tmapData.m_hashTableSize);
+	int i =0;
+	for (i=0;i<tmapData.m_hashTableSize;i++)
+	{
+		m_hashTable[i] = tmapData.m_hashTablePtr[i];
+	}
+	m_next.resize(tmapData.m_nextSize);
+	for (i=0;i<tmapData.m_nextSize;i++)
+	{
+		m_next[i] = tmapData.m_nextPtr[i];
+	}
+	m_valueArray.resize(tmapData.m_numValues);
+	for (i=0;i<tmapData.m_numValues;i++)
+	{
+		m_valueArray[i].m_edgeV0V1Angle = tmapData.m_valueArrayPtr[i].m_edgeV0V1Angle;
+		m_valueArray[i].m_edgeV1V2Angle = tmapData.m_valueArrayPtr[i].m_edgeV1V2Angle;
+		m_valueArray[i].m_edgeV2V0Angle = tmapData.m_valueArrayPtr[i].m_edgeV2V0Angle;
+		m_valueArray[i].m_flags = tmapData.m_valueArrayPtr[i].m_flags;
+	}
+	
+	m_keyArray.resize(tmapData.m_numKeys,btHashInt(0));
+	for (i=0;i<tmapData.m_numKeys;i++)
+	{
+		m_keyArray[i].setUid1(tmapData.m_keyArrayPtr[i]);
+	}
+}
+
+
+#endif //_BT_TRIANGLE_INFO_MAP_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
new file mode 100644
index 0000000..b29e0f7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.cpp
@@ -0,0 +1,140 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btTriangleMesh.h"
+
+
+
+btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices)
+:m_use32bitIndices(use32bitIndices),
+m_use4componentVertices(use4componentVertices),
+m_weldingThreshold(0.0)
+{
+	btIndexedMesh meshIndex;
+	meshIndex.m_numTriangles = 0;
+	meshIndex.m_numVertices = 0;
+	meshIndex.m_indexType = PHY_INTEGER;
+	meshIndex.m_triangleIndexBase = 0;
+	meshIndex.m_triangleIndexStride = 3*sizeof(int);
+	meshIndex.m_vertexBase = 0;
+	meshIndex.m_vertexStride = sizeof(btVector3);
+	m_indexedMeshes.push_back(meshIndex);
+
+	if (m_use32bitIndices)
+	{
+		m_indexedMeshes[0].m_numTriangles = m_32bitIndices.size()/3;
+		m_indexedMeshes[0].m_triangleIndexBase = 0;
+		m_indexedMeshes[0].m_indexType = PHY_INTEGER;
+		m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(int);
+	} else
+	{
+		m_indexedMeshes[0].m_numTriangles = m_16bitIndices.size()/3;
+		m_indexedMeshes[0].m_triangleIndexBase = 0;
+		m_indexedMeshes[0].m_indexType = PHY_SHORT;
+		m_indexedMeshes[0].m_triangleIndexStride = 3*sizeof(short int);
+	}
+
+	if (m_use4componentVertices)
+	{
+		m_indexedMeshes[0].m_numVertices = m_4componentVertices.size();
+		m_indexedMeshes[0].m_vertexBase = 0;
+		m_indexedMeshes[0].m_vertexStride = sizeof(btVector3);
+	} else
+	{
+		m_indexedMeshes[0].m_numVertices = m_3componentVertices.size()/3;
+		m_indexedMeshes[0].m_vertexBase = 0;
+		m_indexedMeshes[0].m_vertexStride = 3*sizeof(btScalar);
+	}
+
+
+}
+
+void	btTriangleMesh::addIndex(int index)
+{
+	if (m_use32bitIndices)
+	{
+		m_32bitIndices.push_back(index);
+		m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0];
+	} else
+	{
+		m_16bitIndices.push_back(index);
+		m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0];
+	}
+}
+
+
+int	btTriangleMesh::findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices)
+{
+	//return index of new/existing vertex
+	///@todo: could use acceleration structure for this
+	if (m_use4componentVertices)
+	{
+		if (removeDuplicateVertices)
+			{
+			for (int i=0;i< m_4componentVertices.size();i++)
+			{
+				if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold)
+				{
+					return i;
+				}
+			}
+		}
+		m_indexedMeshes[0].m_numVertices++;
+		m_4componentVertices.push_back(vertex);
+		m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0];
+
+		return m_4componentVertices.size()-1;
+		
+	} else
+	{
+		
+		if (removeDuplicateVertices)
+		{
+			for (int i=0;i< m_3componentVertices.size();i+=3)
+			{
+				btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]);
+				if ((vtx-vertex).length2() <= m_weldingThreshold)
+				{
+					return i/3;
+				}
+			}
+	}
+		m_3componentVertices.push_back((float)vertex.getX());
+		m_3componentVertices.push_back((float)vertex.getY());
+		m_3componentVertices.push_back((float)vertex.getZ());
+		m_indexedMeshes[0].m_numVertices++;
+		m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0];
+		return (m_3componentVertices.size()/3)-1;
+	}
+
+}
+		
+void	btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2,bool removeDuplicateVertices)
+{
+	m_indexedMeshes[0].m_numTriangles++;
+	addIndex(findOrAddVertex(vertex0,removeDuplicateVertices));
+	addIndex(findOrAddVertex(vertex1,removeDuplicateVertices));
+	addIndex(findOrAddVertex(vertex2,removeDuplicateVertices));
+}
+
+int btTriangleMesh::getNumTriangles() const
+{
+	if (m_use32bitIndices)
+	{
+		return m_32bitIndices.size() / 3;
+	}
+	return m_16bitIndices.size() / 3;
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
new file mode 100644
index 0000000..d2624fe
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMesh.h
@@ -0,0 +1,69 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef TRIANGLE_MESH_H
+#define TRIANGLE_MESH_H
+
+#include "btTriangleIndexVertexArray.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+///The btTriangleMesh class is a convenience class derived from btTriangleIndexVertexArray, that provides storage for a concave triangle mesh. It can be used as data for the btBvhTriangleMeshShape.
+///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices.
+///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface.
+///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same.
+class btTriangleMesh : public btTriangleIndexVertexArray
+{
+	btAlignedObjectArray<btVector3>	m_4componentVertices;
+	btAlignedObjectArray<float>		m_3componentVertices;
+
+	btAlignedObjectArray<unsigned int>		m_32bitIndices;
+	btAlignedObjectArray<unsigned short int>		m_16bitIndices;
+	bool	m_use32bitIndices;
+	bool	m_use4componentVertices;
+	
+
+	public:
+		btScalar	m_weldingThreshold;
+
+		btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true);
+
+		bool	getUse32bitIndices() const
+		{
+			return m_use32bitIndices;
+		}
+
+		bool	getUse4componentVertices() const
+		{
+			return m_use4componentVertices;
+		}
+		///By default addTriangle won't search for duplicate vertices, because the search is very slow for large triangle meshes.
+		///In general it is better to directly use btTriangleIndexVertexArray instead.
+		void	addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2, bool removeDuplicateVertices=false);
+		
+		int getNumTriangles() const;
+
+		virtual void	preallocateVertices(int numverts){(void) numverts;}
+		virtual void	preallocateIndices(int numindices){(void) numindices;}
+
+		///findOrAddVertex is an internal method, use addTriangle instead
+		int		findOrAddVertex(const btVector3& vertex, bool removeDuplicateVertices);
+		///addIndex is an internal method, use addTriangle instead
+		void	addIndex(int index);
+		
+};
+
+#endif //TRIANGLE_MESH_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
new file mode 100644
index 0000000..683684d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp
@@ -0,0 +1,211 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleMeshShape.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btQuaternion.h"
+#include "btStridingMeshInterface.h"
+#include "LinearMath/btAabbUtil2.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+
+btTriangleMeshShape::btTriangleMeshShape(btStridingMeshInterface* meshInterface)
+: btConcaveShape (), m_meshInterface(meshInterface)
+{
+	m_shapeType = TRIANGLE_MESH_SHAPE_PROXYTYPE;
+	if(meshInterface->hasPremadeAabb())
+	{
+		meshInterface->getPremadeAabb(&m_localAabbMin, &m_localAabbMax);
+	}
+	else
+	{
+		recalcLocalAabb();
+	}
+}
+
+
+btTriangleMeshShape::~btTriangleMeshShape()
+{
+		
+}
+
+
+
+
+void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const
+{
+
+	btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin);
+	localHalfExtents += btVector3(getMargin(),getMargin(),getMargin());
+	btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin);
+	
+	btMatrix3x3 abs_b = trans.getBasis().absolute();  
+
+	btVector3 center = trans(localCenter);
+
+	btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+		   abs_b[1].dot(localHalfExtents),
+		  abs_b[2].dot(localHalfExtents));
+	aabbMin = center - extent;
+	aabbMax = center + extent;
+
+
+}
+
+void	btTriangleMeshShape::recalcLocalAabb()
+{
+	for (int i=0;i<3;i++)
+	{
+		btVector3 vec(btScalar(0.),btScalar(0.),btScalar(0.));
+		vec[i] = btScalar(1.);
+		btVector3 tmp = localGetSupportingVertex(vec);
+		m_localAabbMax[i] = tmp[i]+m_collisionMargin;
+		vec[i] = btScalar(-1.);
+		tmp = localGetSupportingVertex(vec);
+		m_localAabbMin[i] = tmp[i]-m_collisionMargin;
+	}
+}
+
+
+
+class SupportVertexCallback : public btTriangleCallback
+{
+
+	btVector3 m_supportVertexLocal;
+public:
+
+	btTransform	m_worldTrans;
+	btScalar m_maxDot;
+	btVector3 m_supportVecLocal;
+
+	SupportVertexCallback(const btVector3& supportVecWorld,const btTransform& trans)
+		: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)), m_worldTrans(trans) ,m_maxDot(btScalar(-BT_LARGE_FLOAT))
+		
+	{
+		m_supportVecLocal = supportVecWorld * m_worldTrans.getBasis();
+	}
+
+	virtual void processTriangle( btVector3* triangle,int partId, int triangleIndex)
+	{
+		(void)partId;
+		(void)triangleIndex;
+		for (int i=0;i<3;i++)
+		{
+			btScalar dot = m_supportVecLocal.dot(triangle[i]);
+			if (dot > m_maxDot)
+			{
+				m_maxDot = dot;
+				m_supportVertexLocal = triangle[i];
+			}
+		}
+	}
+
+	btVector3 GetSupportVertexWorldSpace()
+	{
+		return m_worldTrans(m_supportVertexLocal);
+	}
+
+	btVector3	GetSupportVertexLocal()
+	{
+		return m_supportVertexLocal;
+	}
+
+};
+
+	
+void btTriangleMeshShape::setLocalScaling(const btVector3& scaling)
+{
+	m_meshInterface->setScaling(scaling);
+	recalcLocalAabb();
+}
+
+const btVector3& btTriangleMeshShape::getLocalScaling() const
+{
+	return m_meshInterface->getScaling();
+}
+
+
+
+
+
+
+//#define DEBUG_TRIANGLE_MESH
+
+
+
+void	btTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+		struct FilteredCallback : public btInternalTriangleIndexCallback
+	{
+		btTriangleCallback* m_callback;
+		btVector3 m_aabbMin;
+		btVector3 m_aabbMax;
+
+		FilteredCallback(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax)
+			:m_callback(callback),
+			m_aabbMin(aabbMin),
+			m_aabbMax(aabbMax)
+		{
+		}
+
+		virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int triangleIndex)
+		{
+			if (TestTriangleAgainstAabb2(&triangle[0],m_aabbMin,m_aabbMax))
+			{
+				//check aabb in triangle-space, before doing this
+				m_callback->processTriangle(triangle,partId,triangleIndex);
+			}
+			
+		}
+
+	};
+
+	FilteredCallback filterCallback(callback,aabbMin,aabbMax);
+
+	m_meshInterface->InternalProcessAllTriangles(&filterCallback,aabbMin,aabbMax);
+}
+
+
+
+
+
+void	btTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	(void)mass;
+	//moving concave objects not supported
+	btAssert(0);
+	inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+}
+
+
+btVector3 btTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
+{
+	btVector3 supportVertex;
+
+	btTransform ident;
+	ident.setIdentity();
+
+	SupportVertexCallback supportCallback(vec,ident);
+
+	btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	
+	processAllTriangles(&supportCallback,-aabbMax,aabbMax);
+		
+	supportVertex = supportCallback.GetSupportVertexLocal();
+
+	return supportVertex;
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
new file mode 100644
index 0000000..2216698
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleMeshShape.h
@@ -0,0 +1,89 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef TRIANGLE_MESH_SHAPE_H
+#define TRIANGLE_MESH_SHAPE_H
+
+#include "btConcaveShape.h"
+#include "btStridingMeshInterface.h"
+
+
+///The btTriangleMeshShape is an internal concave triangle mesh interface. Don't use this class directly, use btBvhTriangleMeshShape instead.
+class btTriangleMeshShape : public btConcaveShape
+{
+protected:
+	btVector3	m_localAabbMin;
+	btVector3	m_localAabbMax;
+	btStridingMeshInterface* m_meshInterface;
+
+	///btTriangleMeshShape constructor has been disabled/protected, so that users will not mistakenly use this class.
+	///Don't use btTriangleMeshShape but use btBvhTriangleMeshShape instead!
+	btTriangleMeshShape(btStridingMeshInterface* meshInterface);
+
+public:
+
+	virtual ~btTriangleMeshShape();
+
+	virtual btVector3 localGetSupportingVertex(const btVector3& vec) const;
+
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+	{
+		btAssert(0);
+		return localGetSupportingVertex(vec);
+	}
+
+	void	recalcLocalAabb();
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling);
+	virtual const btVector3& getLocalScaling() const;
+	
+	btStridingMeshInterface* getMeshInterface()
+	{
+		return m_meshInterface;
+	}
+
+	const btStridingMeshInterface* getMeshInterface() const
+	{
+		return m_meshInterface;
+	}
+
+	const btVector3& getLocalAabbMin() const
+	{
+		return m_localAabbMin;
+	}
+	const btVector3& getLocalAabbMax() const
+	{
+		return m_localAabbMax;
+	}
+
+
+
+	//debugging
+	virtual const char*	getName()const {return "TRIANGLEMESH";}
+
+	
+
+};
+
+
+
+
+#endif //TRIANGLE_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
new file mode 100644
index 0000000..847147c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btTriangleShape.h
@@ -0,0 +1,182 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef OBB_TRIANGLE_MINKOWSKI_H
+#define OBB_TRIANGLE_MINKOWSKI_H
+
+#include "btConvexShape.h"
+#include "btBoxShape.h"
+
+ATTRIBUTE_ALIGNED16(class) btTriangleShape : public btPolyhedralConvexShape
+{
+
+
+public:
+
+	btVector3	m_vertices1[3];
+
+	virtual int getNumVertices() const
+	{
+		return 3;
+	}
+
+	btVector3& getVertexPtr(int index)
+	{
+		return m_vertices1[index];
+	}
+
+	const btVector3& getVertexPtr(int index) const
+	{
+		return m_vertices1[index];
+	}
+	virtual void getVertex(int index,btVector3& vert) const
+	{
+		vert = m_vertices1[index];
+	}
+
+	virtual int getNumEdges() const
+	{
+		return 3;
+	}
+	
+	virtual void getEdge(int i,btVector3& pa,btVector3& pb) const
+	{
+		getVertex(i,pa);
+		getVertex((i+1)%3,pb);
+	}
+
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const 
+	{
+//		btAssert(0);
+		getAabbSlow(t,aabbMin,aabbMax);
+	}
+
+	btVector3 localGetSupportingVertexWithoutMargin(const btVector3& dir)const 
+	{
+		btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2]));
+	  	return m_vertices1[dots.maxAxis()];
+
+	}
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+	{
+		for (int i=0;i<numVectors;i++)
+		{
+			const btVector3& dir = vectors[i];
+			btVector3 dots(dir.dot(m_vertices1[0]), dir.dot(m_vertices1[1]), dir.dot(m_vertices1[2]));
+  			supportVerticesOut[i] = m_vertices1[dots.maxAxis()];
+		}
+
+	}
+
+	btTriangleShape() : btPolyhedralConvexShape ()
+    {
+		m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+	}
+
+	btTriangleShape(const btVector3& p0,const btVector3& p1,const btVector3& p2) : btPolyhedralConvexShape ()
+    {
+		m_shapeType = TRIANGLE_SHAPE_PROXYTYPE;
+        m_vertices1[0] = p0;
+        m_vertices1[1] = p1;
+        m_vertices1[2] = p2;
+    }
+
+
+	virtual void getPlane(btVector3& planeNormal,btVector3& planeSupport,int i) const
+	{
+		getPlaneEquation(i,planeNormal,planeSupport);
+	}
+
+	virtual int	getNumPlanes() const
+	{
+		return 1;
+	}
+
+	void calcNormal(btVector3& normal) const
+	{
+		normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
+		normal.normalize();
+	}
+
+	virtual void getPlaneEquation(int i, btVector3& planeNormal,btVector3& planeSupport) const
+	{
+		(void)i;
+		calcNormal(planeNormal);
+		planeSupport = m_vertices1[0];
+	}
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const
+	{
+		(void)mass;
+		btAssert(0);
+		inertia.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	}
+
+		virtual	bool isInside(const btVector3& pt,btScalar tolerance) const
+	{
+		btVector3 normal;
+		calcNormal(normal);
+		//distance to plane
+		btScalar dist = pt.dot(normal);
+		btScalar planeconst = m_vertices1[0].dot(normal);
+		dist -= planeconst;
+		if (dist >= -tolerance && dist <= tolerance)
+		{
+			//inside check on edge-planes
+			int i;
+			for (i=0;i<3;i++)
+			{
+				btVector3 pa,pb;
+				getEdge(i,pa,pb);
+				btVector3 edge = pb-pa;
+				btVector3 edgeNormal = edge.cross(normal);
+				edgeNormal.normalize();
+				btScalar dist = pt.dot( edgeNormal);
+				btScalar edgeConst = pa.dot(edgeNormal);
+				dist -= edgeConst;
+				if (dist < -tolerance)
+					return false;
+			}
+			
+			return true;
+		}
+
+		return false;
+	}
+		//debugging
+		virtual const char*	getName()const
+		{
+			return "Triangle";
+		}
+
+		virtual int		getNumPreferredPenetrationDirections() const
+		{
+			return 2;
+		}
+		
+		virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+		{
+			calcNormal(penetrationVector);
+			if (index)
+				penetrationVector *= btScalar(-1.);
+		}
+
+
+};
+
+#endif //OBB_TRIANGLE_MINKOWSKI_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
new file mode 100644
index 0000000..8e86f6b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.cpp
@@ -0,0 +1,115 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btUniformScalingShape.h"
+
+btUniformScalingShape::btUniformScalingShape(	btConvexShape* convexChildShape,btScalar uniformScalingFactor):
+btConvexShape (), m_childConvexShape(convexChildShape),
+m_uniformScalingFactor(uniformScalingFactor)
+{
+	m_shapeType = UNIFORM_SCALING_SHAPE_PROXYTYPE;
+}
+	
+btUniformScalingShape::~btUniformScalingShape()
+{
+}
+	
+
+btVector3	btUniformScalingShape::localGetSupportingVertexWithoutMargin(const btVector3& vec)const
+{
+	btVector3 tmpVertex;
+	tmpVertex = m_childConvexShape->localGetSupportingVertexWithoutMargin(vec);
+	return tmpVertex*m_uniformScalingFactor;
+}
+
+void	btUniformScalingShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
+{
+	m_childConvexShape->batchedUnitVectorGetSupportingVertexWithoutMargin(vectors,supportVerticesOut,numVectors);
+	int i;
+	for (i=0;i<numVectors;i++)
+	{
+		supportVerticesOut[i] = supportVerticesOut[i] * m_uniformScalingFactor;
+	}
+}
+
+
+btVector3	btUniformScalingShape::localGetSupportingVertex(const btVector3& vec)const
+{
+	btVector3 tmpVertex;
+	tmpVertex = m_childConvexShape->localGetSupportingVertex(vec);
+	return tmpVertex*m_uniformScalingFactor;
+}
+
+
+void	btUniformScalingShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+
+	///this linear upscaling is not realistic, but we don't deal with large mass ratios...
+	btVector3 tmpInertia;
+	m_childConvexShape->calculateLocalInertia(mass,tmpInertia);
+	inertia = tmpInertia * m_uniformScalingFactor;
+}
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+void btUniformScalingShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	m_childConvexShape->getAabb(t,aabbMin,aabbMax);
+	btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5);
+	btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor;
+
+	aabbMin = aabbCenter - scaledAabbHalfExtends;
+	aabbMax = aabbCenter + scaledAabbHalfExtends;
+
+}
+
+void btUniformScalingShape::getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+{
+	m_childConvexShape->getAabbSlow(t,aabbMin,aabbMax);
+	btVector3 aabbCenter = (aabbMax+aabbMin)*btScalar(0.5);
+	btVector3 scaledAabbHalfExtends = (aabbMax-aabbMin)*btScalar(0.5)*m_uniformScalingFactor;
+
+	aabbMin = aabbCenter - scaledAabbHalfExtends;
+	aabbMax = aabbCenter + scaledAabbHalfExtends;
+}
+
+void	btUniformScalingShape::setLocalScaling(const btVector3& scaling) 
+{
+	m_childConvexShape->setLocalScaling(scaling);
+}
+
+const btVector3& btUniformScalingShape::getLocalScaling() const
+{
+	return m_childConvexShape->getLocalScaling();
+}
+
+void	btUniformScalingShape::setMargin(btScalar margin)
+{
+	m_childConvexShape->setMargin(margin);
+}
+btScalar	btUniformScalingShape::getMargin() const
+{
+	return m_childConvexShape->getMargin() * m_uniformScalingFactor;
+}
+
+int		btUniformScalingShape::getNumPreferredPenetrationDirections() const
+{
+	return m_childConvexShape->getNumPreferredPenetrationDirections();
+}
+	
+void	btUniformScalingShape::getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const
+{
+	m_childConvexShape->getPreferredPenetrationDirection(index,penetrationVector);
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
new file mode 100644
index 0000000..cbf7e6f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/CollisionShapes/btUniformScalingShape.h
@@ -0,0 +1,87 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_UNIFORM_SCALING_SHAPE_H
+#define BT_UNIFORM_SCALING_SHAPE_H
+
+#include "btConvexShape.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" // for the types
+
+///The btUniformScalingShape allows to re-use uniform scaled instances of btConvexShape in a memory efficient way.
+///Istead of using btUniformScalingShape, it is better to use the non-uniform setLocalScaling method on convex shapes that implement it.
+class btUniformScalingShape : public btConvexShape
+{
+	btConvexShape*	m_childConvexShape;
+
+	btScalar	m_uniformScalingFactor;
+	
+	public:
+	
+	btUniformScalingShape(	btConvexShape* convexChildShape, btScalar uniformScalingFactor);
+	
+	virtual ~btUniformScalingShape();
+	
+	virtual btVector3	localGetSupportingVertexWithoutMargin(const btVector3& vec)const;
+
+	virtual btVector3	localGetSupportingVertex(const btVector3& vec)const;
+
+	virtual void	batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	btScalar	getUniformScalingFactor() const
+	{
+		return m_uniformScalingFactor;
+	}
+
+	btConvexShape*	getChildShape() 
+	{
+		return m_childConvexShape;
+	}
+
+	const btConvexShape*	getChildShape() const
+	{
+		return m_childConvexShape;
+	}
+
+	virtual const char*	getName()const 
+	{
+		return "UniformScalingShape";
+	}
+	
+
+
+	///////////////////////////
+
+
+	///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version
+	void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void getAabbSlow(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const;
+
+	virtual void	setLocalScaling(const btVector3& scaling) ;
+	virtual const btVector3& getLocalScaling() const ;
+
+	virtual void	setMargin(btScalar margin);
+	virtual btScalar	getMargin() const;
+
+	virtual int		getNumPreferredPenetrationDirections() const;
+	
+	virtual void	getPreferredPenetrationDirection(int index, btVector3& penetrationVector) const;
+
+
+};
+
+#endif //BT_UNIFORM_SCALING_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/Doxyfile b/SRC/ChronoEngine/collision/bullet/BulletCollision/Doxyfile
new file mode 100644
index 0000000..4ecb6ac
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/Doxyfile
@@ -0,0 +1,746 @@
+# Doxyfile 1.2.4
+
+# This file describes the settings to be used by doxygen for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project. 
+PROJECT_NAME           = "Bullet Continuous Collision Detection Library"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = 
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, 
+# Korean, Hungarian, Norwegian, Spanish, Romanian, Russian, Croatian, 
+# Polish, Portuguese and Slovene.
+
+OUTPUT_LANGUAGE        = English
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES 
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation. 
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation. 
+
+EXTRACT_STATIC         = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled. 
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these class will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled. 
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this. 
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed. 
+
+REPEAT_BRIEF           = YES
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description. 
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used. 
+
+FULL_PATH_NAMES        = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH        = 
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation. 
+
+INTERNAL_DOCS          = NO
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a class diagram (in Html and LaTeX) for classes with base or 
+# super classes. Setting the tag to NO turns the diagrams off. 
+
+CLASS_DIAGRAMS         = YES
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation. 
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible. 
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower case letters. If set to YES upper case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# users are adviced to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden. 
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this. 
+
+VERBATIM_HEADERS       = YES
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put list of the files that are included by a file in the documentation 
+# of that file. 
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments  will behave just like the Qt-style comments (thus requiring an 
+# explict @brief command for a brief description. 
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# reimplements. 
+
+INHERIT_DOCS           = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members. 
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order. 
+
+SORT_MEMBER_DOCS       = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments. 
+
+TAB_SIZE               = 8
+
+# The ENABLE_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif. 
+
+ENABLED_SECTIONS       = 
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines. 
+
+ALIASES                = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used. 
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used. 
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled. 
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. 
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr. 
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces. 
+
+INPUT                  = .
+
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included. 
+
+FILE_PATTERNS          = *.h *.cpp *.c
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used. 
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag. 
+
+EXCLUDE                = 
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. 
+
+EXCLUDE_PATTERNS       = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command). 
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included. 
+
+EXAMPLE_PATTERNS       = 
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command). 
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output. 
+
+INPUT_FILTER           = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse. 
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces. 
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20]) 
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers. 
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output. 
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path. 
+
+HTML_OUTPUT            = html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet 
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used. 
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) 
+# of the generated HTML documentation. 
+
+GENERATE_HTMLHELP      = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it. 
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation. 
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side pannel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript and frames is required (for instance Netscape 4.0+ 
+# or Internet explorer 4.0+). 
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown. 
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output. 
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path. 
+
+LATEX_OUTPUT           = latex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general. 
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used. 
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output. 
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing! 
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer. 
+
+PDF_HYPERLINKS         = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation. 
+
+USE_PDFLATEX           = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML. 
+
+LATEX_BATCHMODE        = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimised for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path. 
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general. 
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using a WORD or other. 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links. 
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assigments. You only have to provide 
+# replacements, missing definitions are set to their default value. 
+
+RTF_STYLESHEET_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages 
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path. 
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3) 
+
+MAN_EXTENSION          = .3
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation. Warning: This feature 
+# is still experimental and very incomplete.
+
+GENERATE_XML           = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files. 
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES. 
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_PREDEFINED tags. 
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found. 
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor. 
+
+INCLUDE_PATH           = ../../generic/extern
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used. 
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. 
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition. 
+
+EXPAND_AS_DEFINED      = 
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tagfiles. 
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads. 
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed. 
+
+ALLEXTERNALS           = NO
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl'). 
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default) 
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes. 
+
+COLLABORATION_GRAPH    = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDE_GRAPH, and HAVE_DOT tags are set to 
+# YES then doxygen will generate a graph for each documented file showing 
+# the direct and indirect include dependencies of the file with other 
+# documented files. 
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, INCLUDED_BY_GRAPH, and HAVE_DOT tags are set to 
+# YES then doxygen will generate a graph for each documented header file showing 
+# the documented files that directly or indirectly include this file 
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one. 
+
+GRAPHICAL_HIERARCHY    = YES
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found on the path. 
+
+DOT_PATH               = 
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images. 
+
+MAX_DOT_GRAPH_WIDTH    = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
+# this value, doxygen will try to truncate the graph, so that it fits within 
+# the specified constraint. Beware that most browsers cannot cope with very 
+# large images. 
+
+MAX_DOT_GRAPH_HEIGHT   = 1024
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs. 
+
+GENERATE_LEGEND        = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored. 
+
+SEARCHENGINE           = NO
+
+# The CGI_NAME tag should be the name of the CGI script that 
+# starts the search engine (doxysearch) with the correct parameters. 
+# A script with this name will be generated by doxygen. 
+
+CGI_NAME               = search.cgi
+
+# The CGI_URL tag should be the absolute URL to the directory where the 
+# cgi binaries are located. See the documentation of your http daemon for 
+# details. 
+
+CGI_URL                = 
+
+# The DOC_URL tag should be the absolute URL to the directory where the 
+# documentation is located. If left blank the absolute path to the 
+# documentation, with file:// prepended to it, will be used. 
+
+DOC_URL                = 
+
+# The DOC_ABSPATH tag should be the absolute path to the directory where the 
+# documentation is located. If left blank the directory on the local machine 
+# will be used. 
+
+DOC_ABSPATH            = 
+
+# The BIN_ABSPATH tag must point to the directory where the doxysearch binary 
+# is installed. 
+
+BIN_ABSPATH            = c:\program files\doxygen\bin
+
+# The EXT_DOC_PATHS tag can be used to specify one or more paths to 
+# documentation generated for other projects. This allows doxysearch to search 
+# the documentation for these projects as well. 
+
+EXT_DOC_PATHS          = 
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/Jamfile b/SRC/ChronoEngine/collision/bullet/BulletCollision/Jamfile
new file mode 100644
index 0000000..bd968fd
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/Jamfile
@@ -0,0 +1,12 @@
+SubDir TOP src BulletCollision ;
+
+
+Description bulletcollision : "Bullet Collision Detection" ;
+Library bulletcollision :
+  [ Wildcard BroadphaseCollision : *.h *.cpp ] 
+  [ Wildcard CollisionDispatch : *.h *.cpp ] 
+  [ Wildcard CollisionShapes : *.h *.cpp ] 
+  [ Wildcard NarrowPhaseCollision : *.h *.cpp ] 
+;
+LibDepends bulletcollision : bulletmath  ;
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
new file mode 100644
index 0000000..9ee83e7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.cpp
@@ -0,0 +1,236 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btContinuousConvexCollision.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "LinearMath/btTransformUtil.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+#include "btGjkPairDetector.h"
+#include "btPointCollector.h"
+
+
+
+btContinuousConvexCollision::btContinuousConvexCollision ( const btConvexShape*	convexA,const btConvexShape*	convexB,btSimplexSolverInterface* simplexSolver, btConvexPenetrationDepthSolver* penetrationDepthSolver)
+:m_simplexSolver(simplexSolver),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_convexA(convexA),m_convexB(convexB)
+{
+}
+
+/// This maximum should not be necessary. It allows for untested/degenerate cases in production code.
+/// You don't want your game ever to lock-up.
+#define MAX_ITERATIONS 64
+
+bool	btContinuousConvexCollision::calcTimeOfImpact(
+				const btTransform& fromA,
+				const btTransform& toA,
+				const btTransform& fromB,
+				const btTransform& toB,
+				CastResult& result)
+{
+
+	m_simplexSolver->reset();
+
+	/// compute linear and angular velocity for this interval, to interpolate
+	btVector3 linVelA,angVelA,linVelB,angVelB;
+	btTransformUtil::calculateVelocity(fromA,toA,btScalar(1.),linVelA,angVelA);
+	btTransformUtil::calculateVelocity(fromB,toB,btScalar(1.),linVelB,angVelB);
+
+
+	btScalar boundingRadiusA = m_convexA->getAngularMotionDisc();
+	btScalar boundingRadiusB = m_convexB->getAngularMotionDisc();
+
+	btScalar maxAngularProjectedVelocity = angVelA.length() * boundingRadiusA + angVelB.length() * boundingRadiusB;
+	btVector3 relLinVel = (linVelB-linVelA);
+
+	btScalar relLinVelocLength = (linVelB-linVelA).length();
+	
+	if ((relLinVelocLength+maxAngularProjectedVelocity) == 0.f)
+		return false;
+
+
+	btScalar radius = btScalar(0.001);
+
+	btScalar lambda = btScalar(0.);
+	btVector3 v(1,0,0);
+
+	int maxIter = MAX_ITERATIONS;
+
+	btVector3 n;
+	n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	bool hasResult = false;
+	btVector3 c;
+
+	btScalar lastLambda = lambda;
+	//btScalar epsilon = btScalar(0.001);
+
+	int numIter = 0;
+	//first solution, using GJK
+
+
+	btTransform identityTrans;
+	identityTrans.setIdentity();
+
+	btSphereShape	raySphere(btScalar(0.0));
+	raySphere.setMargin(btScalar(0.));
+
+
+//	result.drawCoordSystem(sphereTr);
+
+	btPointCollector	pointCollector1;
+
+	{
+		
+		btGjkPairDetector gjk(m_convexA,m_convexB,m_convexA->getShapeType(),m_convexB->getShapeType(),m_convexA->getMargin(),m_convexB->getMargin(),m_simplexSolver,m_penetrationDepthSolver);		
+		btGjkPairDetector::ClosestPointInput input;
+	
+		//we don't use margins during CCD
+	//	gjk.setIgnoreMargin(true);
+
+		input.m_transformA = fromA;
+		input.m_transformB = fromB;
+		gjk.getClosestPoints(input,pointCollector1,0);
+
+		hasResult = pointCollector1.m_hasResult;
+		c = pointCollector1.m_pointInWorld;
+	}
+
+	if (hasResult)
+	{
+		btScalar dist;
+		dist = pointCollector1.m_distance;
+		n = pointCollector1.m_normalOnBInWorld;
+
+		btScalar projectedLinearVelocity = relLinVel.dot(n);
+		
+		//not close enough
+		while (dist > radius)
+		{
+			if (result.m_debugDrawer)
+			{
+				result.m_debugDrawer->drawSphere(c,0.2f,btVector3(1,1,1));
+			}
+			numIter++;
+			if (numIter > maxIter)
+			{
+				return false; //todo: report a failure
+			}
+			btScalar dLambda = btScalar(0.);
+
+			projectedLinearVelocity = relLinVel.dot(n);
+
+			//calculate safe moving fraction from distance / (linear+rotational velocity)
+			
+			//btScalar clippedDist  = GEN_min(angularConservativeRadius,dist);
+			//btScalar clippedDist  = dist;
+			
+			//don't report time of impact for motion away from the contact normal (or causes minor penetration)
+			if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=SIMD_EPSILON)
+				return false;
+			
+			dLambda = dist / (projectedLinearVelocity+ maxAngularProjectedVelocity);
+
+			
+			
+			lambda = lambda + dLambda;
+
+			if (lambda > btScalar(1.))
+				return false;
+
+			if (lambda < btScalar(0.))
+				return false;
+
+
+			//todo: next check with relative epsilon
+			if (lambda <= lastLambda)
+			{
+				return false;
+				//n.setValue(0,0,0);
+				break;
+			}
+			lastLambda = lambda;
+
+			
+
+			//interpolate to next lambda
+			btTransform interpolatedTransA,interpolatedTransB,relativeTrans;
+
+			btTransformUtil::integrateTransform(fromA,linVelA,angVelA,lambda,interpolatedTransA);
+			btTransformUtil::integrateTransform(fromB,linVelB,angVelB,lambda,interpolatedTransB);
+			relativeTrans = interpolatedTransB.inverseTimes(interpolatedTransA);
+
+			if (result.m_debugDrawer)
+			{
+				result.m_debugDrawer->drawSphere(interpolatedTransA.getOrigin(),0.2f,btVector3(1,0,0));
+			}
+
+			result.DebugDraw( lambda );
+
+			btPointCollector	pointCollector;
+			btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,m_penetrationDepthSolver);
+			btGjkPairDetector::ClosestPointInput input;
+			input.m_transformA = interpolatedTransA;
+			input.m_transformB = interpolatedTransB;
+			gjk.getClosestPoints(input,pointCollector,0);
+			if (pointCollector.m_hasResult)
+			{
+				if (pointCollector.m_distance < btScalar(0.))
+				{
+					//degenerate ?!
+					result.m_fraction = lastLambda;
+					n = pointCollector.m_normalOnBInWorld;
+					result.m_normal=n;//.setValue(1,1,1);// = n;
+					result.m_hitPoint = pointCollector.m_pointInWorld;
+					return true;
+				}
+				c = pointCollector.m_pointInWorld;		
+				n = pointCollector.m_normalOnBInWorld;
+				dist = pointCollector.m_distance;
+			} else
+			{
+				//??
+				return false;
+			}
+			
+
+		}
+	
+		if ((projectedLinearVelocity+ maxAngularProjectedVelocity)<=result.m_allowedPenetration)//SIMD_EPSILON)
+			return false;
+			
+		result.m_fraction = lambda;
+		result.m_normal = n;
+		result.m_hitPoint = c;
+		return true;
+	}
+
+	return false;
+
+/*
+//todo:
+	//if movement away from normal, discard result
+	btVector3 move = transBLocalTo.getOrigin() - transBLocalFrom.getOrigin();
+	if (result.m_fraction < btScalar(1.))
+	{
+		if (move.dot(result.m_normal) <= btScalar(0.))
+		{
+		}
+	}
+*/
+
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
new file mode 100644
index 0000000..28c2b4d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h
@@ -0,0 +1,52 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef CONTINUOUS_COLLISION_CONVEX_CAST_H
+#define CONTINUOUS_COLLISION_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+class btConvexShape;
+
+/// btContinuousConvexCollision implements angular and linear time of impact for convex objects.
+/// Based on Brian Mirtich's Conservative Advancement idea (PhD thesis).
+/// Algorithm operates in worldspace, in order to keep inbetween motion globally consistent.
+/// It uses GJK at the moment. Future improvement would use minkowski sum / supporting vertex, merging innerloops
+class btContinuousConvexCollision : public btConvexCast
+{
+	btSimplexSolverInterface* m_simplexSolver;
+	btConvexPenetrationDepthSolver*	m_penetrationDepthSolver;
+	const btConvexShape*	m_convexA;
+	const btConvexShape*	m_convexB;
+
+
+public:
+
+	btContinuousConvexCollision (const btConvexShape*	shapeA,const btConvexShape*	shapeB ,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver);
+
+	virtual bool	calcTimeOfImpact(
+				const btTransform& fromA,
+				const btTransform& toA,
+				const btTransform& fromB,
+				const btTransform& toB,
+				CastResult& result);
+
+
+};
+
+#endif //CONTINUOUS_COLLISION_CONVEX_CAST_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
new file mode 100644
index 0000000..d2a1310
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.cpp
@@ -0,0 +1,20 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btConvexCast.h"
+
+btConvexCast::~btConvexCast()
+{
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
new file mode 100644
index 0000000..b0bce34
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexCast.h
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef CONVEX_CAST_H
+#define CONVEX_CAST_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"
+class btMinkowskiSumShape;
+#include "LinearMath/btIDebugDraw.h"
+
+/// btConvexCast is an interface for Casting
+class btConvexCast
+{
+public:
+
+
+	virtual ~btConvexCast();
+
+	///RayResult stores the closest result
+	/// alternatively, add a callback method to decide about closest/all results
+	struct	CastResult
+	{
+		//virtual bool	addRayResult(const btVector3& normal,btScalar	fraction) = 0;
+				
+		virtual void	DebugDraw(btScalar	fraction) {(void)fraction;}
+		virtual void	drawCoordSystem(const btTransform& trans) {(void)trans;}
+
+		CastResult()
+			:m_fraction(btScalar(BT_LARGE_FLOAT)),
+			m_debugDrawer(0),
+			m_allowedPenetration(btScalar(0))
+		{
+		}
+
+
+		virtual ~CastResult() {};
+
+		btTransform	m_hitTransformA;
+		btTransform	m_hitTransformB;
+		btVector3	m_normal;
+		btVector3   m_hitPoint;
+		btScalar	m_fraction; //input and output
+		btIDebugDraw* m_debugDrawer;
+		btScalar	m_allowedPenetration;
+
+	};
+
+
+	/// cast a convex against another convex object
+	virtual bool	calcTimeOfImpact(
+					const btTransform& fromA,
+					const btTransform& toA,
+					const btTransform& fromB,
+					const btTransform& toB,
+					CastResult& result) = 0;
+};
+
+#endif //CONVEX_CAST_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
new file mode 100644
index 0000000..7e3fde8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h
@@ -0,0 +1,42 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef __CONVEX_PENETRATION_DEPTH_H
+#define __CONVEX_PENETRATION_DEPTH_H
+
+class btStackAlloc;
+class btVector3;
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+class btTransform;
+
+///ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
+class btConvexPenetrationDepthSolver
+{
+public:	
+	
+	virtual ~btConvexPenetrationDepthSolver() {};
+	virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
+		const btConvexShape* convexA,const btConvexShape* convexB,
+					const btTransform& transA,const btTransform& transB,
+				btVector3& v, btVector3& pa, btVector3& pb,
+				class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
+				) = 0;
+
+
+};
+#endif //CONVEX_PENETRATION_DEPTH_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
new file mode 100644
index 0000000..bc711ad
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h
@@ -0,0 +1,89 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+#define DISCRETE_COLLISION_DETECTOR1_INTERFACE_H
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+class btStackAlloc;
+
+/// This interface is made to be used by an iterative approach to do TimeOfImpact calculations
+/// This interface allows to query for closest points and penetration depth between two (convex) objects
+/// the closest point is on the second object (B), and the normal points from the surface on B towards A.
+/// distance is between closest points on B and closest point on A. So you can calculate closest point on A
+/// by taking closestPointInA = closestPointInB + m_distance * m_normalOnSurfaceB
+struct btDiscreteCollisionDetectorInterface
+{
+	
+	struct Result
+	{
+	
+		virtual ~Result(){}	
+
+		///setShapeIdentifiersA/B provides experimental support for per-triangle material / custom material combiner
+		virtual void setShapeIdentifiersA(int partId0,int index0)=0;
+		virtual void setShapeIdentifiersB(int partId1,int index1)=0;
+		virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)=0;
+	};
+
+	struct ClosestPointInput
+	{
+		ClosestPointInput()
+			:m_maximumDistanceSquared(btScalar(BT_LARGE_FLOAT)),
+			m_stackAlloc(0)
+		{
+		}
+
+		btTransform m_transformA;
+		btTransform m_transformB;
+		btScalar	m_maximumDistanceSquared;
+		btStackAlloc* m_stackAlloc;
+	};
+
+	virtual ~btDiscreteCollisionDetectorInterface() {};
+
+	//
+	// give either closest points (distance > 0) or penetration (distance)
+	// the normal always points from B towards A
+	//
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false) = 0;
+
+};
+
+struct btStorageResult : public btDiscreteCollisionDetectorInterface::Result
+{
+		btVector3	m_normalOnSurfaceB;
+		btVector3	m_closestPointInB;
+		btScalar	m_distance; //negative means penetration !
+
+		btStorageResult() : m_distance(btScalar(BT_LARGE_FLOAT))
+		{
+
+		}
+		virtual ~btStorageResult() {};
+
+		virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+		{
+			if (depth < m_distance)
+			{
+				m_normalOnSurfaceB = normalOnBInWorld;
+				m_closestPointInB = pointInWorld;
+				m_distance = depth;
+			}
+		}
+};
+
+#endif //DISCRETE_COLLISION_DETECTOR_INTERFACE1_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
new file mode 100644
index 0000000..bef697a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.cpp
@@ -0,0 +1,176 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btGjkConvexCast.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "btGjkPairDetector.h"
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#else
+#define MAX_ITERATIONS 32
+#endif
+
+btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
+:m_simplexSolver(simplexSolver),
+m_convexA(convexA),
+m_convexB(convexB)
+{
+}
+
+bool	btGjkConvexCast::calcTimeOfImpact(
+					const btTransform& fromA,
+					const btTransform& toA,
+					const btTransform& fromB,
+					const btTransform& toB,
+					CastResult& result)
+{
+
+
+	m_simplexSolver->reset();
+
+	/// compute linear velocity for this interval, to interpolate
+	//assume no rotation/angular velocity, assert here?
+	btVector3 linVelA,linVelB;
+	linVelA = toA.getOrigin()-fromA.getOrigin();
+	linVelB = toB.getOrigin()-fromB.getOrigin();
+
+	btScalar radius = btScalar(0.001);
+	btScalar lambda = btScalar(0.);
+	btVector3 v(1,0,0);
+
+	int maxIter = MAX_ITERATIONS;
+
+	btVector3 n;
+	n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	bool hasResult = false;
+	btVector3 c;
+	btVector3 r = (linVelA-linVelB);
+
+	btScalar lastLambda = lambda;
+	//btScalar epsilon = btScalar(0.001);
+
+	int numIter = 0;
+	//first solution, using GJK
+
+
+	btTransform identityTrans;
+	identityTrans.setIdentity();
+
+
+//	result.drawCoordSystem(sphereTr);
+
+	btPointCollector	pointCollector;
+
+		
+	btGjkPairDetector gjk(m_convexA,m_convexB,m_simplexSolver,0);//m_penetrationDepthSolver);		
+	btGjkPairDetector::ClosestPointInput input;
+
+	//we don't use margins during CCD
+	//	gjk.setIgnoreMargin(true);
+
+	input.m_transformA = fromA;
+	input.m_transformB = fromB;
+	gjk.getClosestPoints(input,pointCollector,0);
+
+	hasResult = pointCollector.m_hasResult;
+	c = pointCollector.m_pointInWorld;
+
+	if (hasResult)
+	{
+		btScalar dist;
+		dist = pointCollector.m_distance;
+		n = pointCollector.m_normalOnBInWorld;
+
+	
+
+		//not close enough
+		while (dist > radius)
+		{
+			numIter++;
+			if (numIter > maxIter)
+			{
+				return false; //todo: report a failure
+			}
+			btScalar dLambda = btScalar(0.);
+
+			btScalar projectedLinearVelocity = r.dot(n);
+			
+			dLambda = dist / (projectedLinearVelocity);
+
+			lambda = lambda - dLambda;
+
+			if (lambda > btScalar(1.))
+				return false;
+
+			if (lambda < btScalar(0.))
+				return false;
+
+			//todo: next check with relative epsilon
+			if (lambda <= lastLambda)
+			{
+				return false;
+				//n.setValue(0,0,0);
+				break;
+			}
+			lastLambda = lambda;
+
+			//interpolate to next lambda
+			result.DebugDraw( lambda );
+			input.m_transformA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+			input.m_transformB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+			
+			gjk.getClosestPoints(input,pointCollector,0);
+			if (pointCollector.m_hasResult)
+			{
+				if (pointCollector.m_distance < btScalar(0.))
+				{
+					result.m_fraction = lastLambda;
+					n = pointCollector.m_normalOnBInWorld;
+					result.m_normal=n;
+					result.m_hitPoint = pointCollector.m_pointInWorld;
+					return true;
+				}
+				c = pointCollector.m_pointInWorld;		
+				n = pointCollector.m_normalOnBInWorld;
+				dist = pointCollector.m_distance;
+			} else
+			{
+				//??
+				return false;
+			}
+
+		}
+
+		//is n normalized?
+		//don't report time of impact for motion away from the contact normal (or causes minor penetration)
+		if (n.dot(r)>=-result.m_allowedPenetration)
+			return false;
+
+		result.m_fraction = lambda;
+		result.m_normal = n;
+		result.m_hitPoint = c;
+		return true;
+	}
+
+	return false;
+
+
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
new file mode 100644
index 0000000..a977c9e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef GJK_CONVEX_CAST_H
+#define GJK_CONVEX_CAST_H
+
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+#include "LinearMath/btVector3.h"
+#include "btConvexCast.h"
+class btConvexShape;
+class btMinkowskiSumShape;
+#include "btSimplexSolverInterface.h"
+
+///GjkConvexCast performs a raycast on a convex object using support mapping.
+class btGjkConvexCast : public btConvexCast
+{
+	btSimplexSolverInterface*	m_simplexSolver;
+	const btConvexShape*	m_convexA;
+	const btConvexShape*	m_convexB;
+
+public:
+
+	btGjkConvexCast(const btConvexShape*	convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver);
+
+	/// cast a convex against another convex object
+	virtual bool	calcTimeOfImpact(
+					const btTransform& fromA,
+					const btTransform& toA,
+					const btTransform& fromB,
+					const btTransform& toB,
+					CastResult& result);
+
+};
+
+#endif //GJK_CONVEX_CAST_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
new file mode 100644
index 0000000..f74261d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.cpp
@@ -0,0 +1,989 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+#include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "btGjkEpa2.h"
+
+#if defined(DEBUG) || defined (_DEBUG)
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+#endif //__SPU__
+#endif
+
+namespace gjkepa2_impl
+{
+
+	// Config
+
+	/* GJK	*/ 
+#define GJK_MAX_ITERATIONS	128
+#define GJK_ACCURARY		((btScalar)0.0001)
+#define GJK_MIN_DISTANCE	((btScalar)0.0001)
+#define GJK_DUPLICATED_EPS	((btScalar)0.0001)
+#define GJK_SIMPLEX2_EPS	((btScalar)0.0)
+#define GJK_SIMPLEX3_EPS	((btScalar)0.0)
+#define GJK_SIMPLEX4_EPS	((btScalar)0.0)
+
+	/* EPA	*/ 
+#define EPA_MAX_VERTICES	64
+#define EPA_MAX_FACES		(EPA_MAX_VERTICES*2)
+#define EPA_MAX_ITERATIONS	255
+#define EPA_ACCURACY		((btScalar)0.0001)
+#define EPA_FALLBACK		(10*EPA_ACCURACY)
+#define EPA_PLANE_EPS		((btScalar)0.00001)
+#define EPA_INSIDE_EPS		((btScalar)0.01)
+
+
+	// Shorthands
+	typedef unsigned int	U;
+	typedef unsigned char	U1;
+
+	// MinkowskiDiff
+	struct	MinkowskiDiff
+	{
+		const btConvexShape*	m_shapes[2];
+		btMatrix3x3				m_toshape1;
+		btTransform				m_toshape0;
+#ifdef __SPU__
+		bool					m_enableMargin;
+#else
+		btVector3				(btConvexShape::*Ls)(const btVector3&) const;
+#endif//__SPU__
+		
+
+		MinkowskiDiff()
+		{
+
+		}
+#ifdef __SPU__
+			void					EnableMargin(bool enable)
+		{
+			m_enableMargin = enable;
+		}	
+		inline btVector3		Support0(const btVector3& d) const
+		{
+			if (m_enableMargin)
+			{
+				return m_shapes[0]->localGetSupportVertexNonVirtual(d);
+			} else
+			{
+				return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
+			}
+		}
+		inline btVector3		Support1(const btVector3& d) const
+		{
+			if (m_enableMargin)
+			{
+				return m_toshape0*(m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1*d));
+			} else
+			{
+				return m_toshape0*(m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1*d));
+			}
+		}
+#else
+		void					EnableMargin(bool enable)
+		{
+			if(enable)
+				Ls=&btConvexShape::localGetSupportVertexNonVirtual;
+			else
+				Ls=&btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
+		}	
+		inline btVector3		Support0(const btVector3& d) const
+		{
+			return(((m_shapes[0])->*(Ls))(d));
+		}
+		inline btVector3		Support1(const btVector3& d) const
+		{
+			return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d));
+		}
+#endif //__SPU__
+
+		inline btVector3		Support(const btVector3& d) const
+		{
+			return(Support0(d)-Support1(-d));
+		}
+		btVector3				Support(const btVector3& d,U index) const
+		{
+			if(index)
+				return(Support1(d));
+			else
+				return(Support0(d));
+		}
+	};
+
+	typedef	MinkowskiDiff	tShape;
+
+
+	// GJK
+	struct	GJK
+	{
+		/* Types		*/ 
+		struct	sSV
+		{
+			btVector3	d,w;
+		};
+		struct	sSimplex
+		{
+			sSV*		c[4];
+			btScalar	p[4];
+			U			rank;
+		};
+		struct	eStatus	{ enum _ {
+			Valid,
+			Inside,
+			Failed		};};
+			/* Fields		*/ 
+			tShape			m_shape;
+			btVector3		m_ray;
+			btScalar		m_distance;
+			sSimplex		m_simplices[2];
+			sSV				m_store[4];
+			sSV*			m_free[4];
+			U				m_nfree;
+			U				m_current;
+			sSimplex*		m_simplex;
+			eStatus::_		m_status;
+			/* Methods		*/ 
+			GJK()
+			{
+				Initialize();
+			}
+			void				Initialize()
+			{
+				m_ray		=	btVector3(0,0,0);
+				m_nfree		=	0;
+				m_status	=	eStatus::Failed;
+				m_current	=	0;
+				m_distance	=	0;
+			}
+			eStatus::_			Evaluate(const tShape& shapearg,const btVector3& guess)
+			{
+				U			iterations=0;
+				btScalar	sqdist=0;
+				btScalar	alpha=0;
+				btVector3	lastw[4];
+				U			clastw=0;
+				/* Initialize solver		*/ 
+				m_free[0]			=	&m_store[0];
+				m_free[1]			=	&m_store[1];
+				m_free[2]			=	&m_store[2];
+				m_free[3]			=	&m_store[3];
+				m_nfree				=	4;
+				m_current			=	0;
+				m_status			=	eStatus::Valid;
+				m_shape				=	shapearg;
+				m_distance			=	0;
+				/* Initialize simplex		*/ 
+				m_simplices[0].rank	=	0;
+				m_ray				=	guess;
+				const btScalar	sqrl=	m_ray.length2();
+				appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
+				m_simplices[0].p[0]	=	1;
+				m_ray				=	m_simplices[0].c[0]->w;	
+				sqdist				=	sqrl;
+				lastw[0]			=
+					lastw[1]			=
+					lastw[2]			=
+					lastw[3]			=	m_ray;
+				/* Loop						*/ 
+				do	{
+					const U		next=1-m_current;
+					sSimplex&	cs=m_simplices[m_current];
+					sSimplex&	ns=m_simplices[next];
+					/* Check zero							*/ 
+					const btScalar	rl=m_ray.length();
+					if(rl<GJK_MIN_DISTANCE)
+					{/* Touching or inside				*/ 
+						m_status=eStatus::Inside;
+						break;
+					}
+					/* Append new vertice in -'v' direction	*/ 
+					appendvertice(cs,-m_ray);
+					const btVector3&	w=cs.c[cs.rank-1]->w;
+					bool				found=false;
+					for(U i=0;i<4;++i)
+					{
+						if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
+						{ found=true;break; }
+					}
+					if(found)
+					{/* Return old simplex				*/ 
+						removevertice(m_simplices[m_current]);
+						break;
+					}
+					else
+					{/* Update lastw					*/ 
+						lastw[clastw=(clastw+1)&3]=w;
+					}
+					/* Check for termination				*/ 
+					const btScalar	omega=btDot(m_ray,w)/rl;
+					alpha=btMax(omega,alpha);
+					if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
+					{/* Return old simplex				*/ 
+						removevertice(m_simplices[m_current]);
+						break;
+					}		
+					/* Reduce simplex						*/ 
+					btScalar	weights[4];
+					U			mask=0;
+					switch(cs.rank)
+					{
+					case	2:	sqdist=projectorigin(	cs.c[0]->w,
+									cs.c[1]->w,
+									weights,mask);break;
+					case	3:	sqdist=projectorigin(	cs.c[0]->w,
+									cs.c[1]->w,
+									cs.c[2]->w,
+									weights,mask);break;
+					case	4:	sqdist=projectorigin(	cs.c[0]->w,
+									cs.c[1]->w,
+									cs.c[2]->w,
+									cs.c[3]->w,
+									weights,mask);break;
+					}
+					if(sqdist>=0)
+					{/* Valid	*/ 
+						ns.rank		=	0;
+						m_ray		=	btVector3(0,0,0);
+						m_current	=	next;
+						for(U i=0,ni=cs.rank;i<ni;++i)
+						{
+							if(mask&(1<<i))
+							{
+								ns.c[ns.rank]		=	cs.c[i];
+								ns.p[ns.rank++]		=	weights[i];
+								m_ray				+=	cs.c[i]->w*weights[i];
+							}
+							else
+							{
+								m_free[m_nfree++]	=	cs.c[i];
+							}
+						}
+						if(mask==15) m_status=eStatus::Inside;
+					}
+					else
+					{/* Return old simplex				*/ 
+						removevertice(m_simplices[m_current]);
+						break;
+					}
+					m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
+				} while(m_status==eStatus::Valid);
+				m_simplex=&m_simplices[m_current];
+				switch(m_status)
+				{
+				case	eStatus::Valid:		m_distance=m_ray.length();break;
+				case	eStatus::Inside:	m_distance=0;break;
+				default:
+					{
+					}
+				}	
+				return(m_status);
+			}
+			bool					EncloseOrigin()
+			{
+				switch(m_simplex->rank)
+				{
+				case	1:
+					{
+						for(U i=0;i<3;++i)
+						{
+							btVector3		axis=btVector3(0,0,0);
+							axis[i]=1;
+							appendvertice(*m_simplex, axis);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+							appendvertice(*m_simplex,-axis);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+						}
+					}
+					break;
+				case	2:
+					{
+						const btVector3	d=m_simplex->c[1]->w-m_simplex->c[0]->w;
+						for(U i=0;i<3;++i)
+						{
+							btVector3		axis=btVector3(0,0,0);
+							axis[i]=1;
+							const btVector3	p=btCross(d,axis);
+							if(p.length2()>0)
+							{
+								appendvertice(*m_simplex, p);
+								if(EncloseOrigin())	return(true);
+								removevertice(*m_simplex);
+								appendvertice(*m_simplex,-p);
+								if(EncloseOrigin())	return(true);
+								removevertice(*m_simplex);
+							}
+						}
+					}
+					break;
+				case	3:
+					{
+						const btVector3	n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
+							m_simplex->c[2]->w-m_simplex->c[0]->w);
+						if(n.length2()>0)
+						{
+							appendvertice(*m_simplex,n);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+							appendvertice(*m_simplex,-n);
+							if(EncloseOrigin())	return(true);
+							removevertice(*m_simplex);
+						}
+					}
+					break;
+				case	4:
+					{
+						if(btFabs(det(	m_simplex->c[0]->w-m_simplex->c[3]->w,
+							m_simplex->c[1]->w-m_simplex->c[3]->w,
+							m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
+							return(true);
+					}
+					break;
+				}
+				return(false);
+			}
+			/* Internals	*/ 
+			void				getsupport(const btVector3& d,sSV& sv) const
+			{
+				sv.d	=	d/d.length();
+				sv.w	=	m_shape.Support(sv.d);
+			}
+			void				removevertice(sSimplex& simplex)
+			{
+				m_free[m_nfree++]=simplex.c[--simplex.rank];
+			}
+			void				appendvertice(sSimplex& simplex,const btVector3& v)
+			{
+				simplex.p[simplex.rank]=0;
+				simplex.c[simplex.rank]=m_free[--m_nfree];
+				getsupport(v,*simplex.c[simplex.rank++]);
+			}
+			static btScalar		det(const btVector3& a,const btVector3& b,const btVector3& c)
+			{
+				return(	a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
+					a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
+					a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
+			}
+			static btScalar		projectorigin(	const btVector3& a,
+				const btVector3& b,
+				btScalar* w,U& m)
+			{
+				const btVector3	d=b-a;
+				const btScalar	l=d.length2();
+				if(l>GJK_SIMPLEX2_EPS)
+				{
+					const btScalar	t(l>0?-btDot(a,d)/l:0);
+					if(t>=1)		{ w[0]=0;w[1]=1;m=2;return(b.length2()); }
+					else if(t<=0)	{ w[0]=1;w[1]=0;m=1;return(a.length2()); }
+					else			{ w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
+				}
+				return(-1);
+			}
+			static btScalar		projectorigin(	const btVector3& a,
+				const btVector3& b,
+				const btVector3& c,
+				btScalar* w,U& m)
+			{
+				static const U		imd3[]={1,2,0};
+				const btVector3*	vt[]={&a,&b,&c};
+				const btVector3		dl[]={a-b,b-c,c-a};
+				const btVector3		n=btCross(dl[0],dl[1]);
+				const btScalar		l=n.length2();
+				if(l>GJK_SIMPLEX3_EPS)
+				{
+					btScalar	mindist=-1;
+					btScalar	subw[2]={0.f,0.f};
+					U			subm(0);
+					for(U i=0;i<3;++i)
+					{
+						if(btDot(*vt[i],btCross(dl[i],n))>0)
+						{
+							const U			j=imd3[i];
+							const btScalar	subd(projectorigin(*vt[i],*vt[j],subw,subm));
+							if((mindist<0)||(subd<mindist))
+							{
+								mindist		=	subd;
+								m			=	static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
+								w[i]		=	subw[0];
+								w[j]		=	subw[1];
+								w[imd3[j]]	=	0;				
+							}
+						}
+					}
+					if(mindist<0)
+					{
+						const btScalar	d=btDot(a,n);	
+						const btScalar	s=btSqrt(l);
+						const btVector3	p=n*(d/l);
+						mindist	=	p.length2();
+						m		=	7;
+						w[0]	=	(btCross(dl[1],b-p)).length()/s;
+						w[1]	=	(btCross(dl[2],c-p)).length()/s;
+						w[2]	=	1-(w[0]+w[1]);
+					}
+					return(mindist);
+				}
+				return(-1);
+			}
+			static btScalar		projectorigin(	const btVector3& a,
+				const btVector3& b,
+				const btVector3& c,
+				const btVector3& d,
+				btScalar* w,U& m)
+			{
+				static const U		imd3[]={1,2,0};
+				const btVector3*	vt[]={&a,&b,&c,&d};
+				const btVector3		dl[]={a-d,b-d,c-d};
+				const btScalar		vl=det(dl[0],dl[1],dl[2]);
+				const bool			ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
+				if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
+				{
+					btScalar	mindist=-1;
+					btScalar	subw[3]={0.f,0.f,0.f};
+					U			subm(0);
+					for(U i=0;i<3;++i)
+					{
+						const U			j=imd3[i];
+						const btScalar	s=vl*btDot(d,btCross(dl[i],dl[j]));
+						if(s>0)
+						{
+							const btScalar	subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
+							if((mindist<0)||(subd<mindist))
+							{
+								mindist		=	subd;
+								m			=	static_cast<U>((subm&1?1<<i:0)+
+									(subm&2?1<<j:0)+
+									(subm&4?8:0));
+								w[i]		=	subw[0];
+								w[j]		=	subw[1];
+								w[imd3[j]]	=	0;
+								w[3]		=	subw[2];
+							}
+						}
+					}
+					if(mindist<0)
+					{
+						mindist	=	0;
+						m		=	15;
+						w[0]	=	det(c,b,d)/vl;
+						w[1]	=	det(a,c,d)/vl;
+						w[2]	=	det(b,a,d)/vl;
+						w[3]	=	1-(w[0]+w[1]+w[2]);
+					}
+					return(mindist);
+				}
+				return(-1);
+			}
+	};
+
+	// EPA
+	struct	EPA
+	{
+		/* Types		*/ 
+		typedef	GJK::sSV	sSV;
+		struct	sFace
+		{
+			btVector3	n;
+			btScalar	d;
+			btScalar	p;
+			sSV*		c[3];
+			sFace*		f[3];
+			sFace*		l[2];
+			U1			e[3];
+			U1			pass;
+		};
+		struct	sList
+		{
+			sFace*		root;
+			U			count;
+			sList() : root(0),count(0)	{}
+		};
+		struct	sHorizon
+		{
+			sFace*		cf;
+			sFace*		ff;
+			U			nf;
+			sHorizon() : cf(0),ff(0),nf(0)	{}
+		};
+		struct	eStatus { enum _ {
+			Valid,
+			Touching,
+			Degenerated,
+			NonConvex,
+			InvalidHull,		
+			OutOfFaces,
+			OutOfVertices,
+			AccuraryReached,
+			FallBack,
+			Failed		};};
+			/* Fields		*/ 
+			eStatus::_		m_status;
+			GJK::sSimplex	m_result;
+			btVector3		m_normal;
+			btScalar		m_depth;
+			sSV				m_sv_store[EPA_MAX_VERTICES];
+			sFace			m_fc_store[EPA_MAX_FACES];
+			U				m_nextsv;
+			sList			m_hull;
+			sList			m_stock;
+			/* Methods		*/ 
+			EPA()
+			{
+				Initialize();	
+			}
+
+
+			static inline void		bind(sFace* fa,U ea,sFace* fb,U eb)
+			{
+				fa->e[ea]=(U1)eb;fa->f[ea]=fb;
+				fb->e[eb]=(U1)ea;fb->f[eb]=fa;
+			}
+			static inline void		append(sList& list,sFace* face)
+			{
+				face->l[0]	=	0;
+				face->l[1]	=	list.root;
+				if(list.root) list.root->l[0]=face;
+				list.root	=	face;
+				++list.count;
+			}
+			static inline void		remove(sList& list,sFace* face)
+			{
+				if(face->l[1]) face->l[1]->l[0]=face->l[0];
+				if(face->l[0]) face->l[0]->l[1]=face->l[1];
+				if(face==list.root) list.root=face->l[1];
+				--list.count;
+			}
+
+
+			void				Initialize()
+			{
+				m_status	=	eStatus::Failed;
+				m_normal	=	btVector3(0,0,0);
+				m_depth		=	0;
+				m_nextsv	=	0;
+				for(U i=0;i<EPA_MAX_FACES;++i)
+				{
+					append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
+				}
+			}
+			eStatus::_			Evaluate(GJK& gjk,const btVector3& guess)
+			{
+				GJK::sSimplex&	simplex=*gjk.m_simplex;
+				if((simplex.rank>1)&&gjk.EncloseOrigin())
+				{
+
+					/* Clean up				*/ 
+					while(m_hull.root)
+					{
+						sFace*	f = m_hull.root;
+						remove(m_hull,f);
+						append(m_stock,f);
+					}
+					m_status	=	eStatus::Valid;
+					m_nextsv	=	0;
+					/* Orient simplex		*/ 
+					if(gjk.det(	simplex.c[0]->w-simplex.c[3]->w,
+						simplex.c[1]->w-simplex.c[3]->w,
+						simplex.c[2]->w-simplex.c[3]->w)<0)
+					{
+						btSwap(simplex.c[0],simplex.c[1]);
+						btSwap(simplex.p[0],simplex.p[1]);
+					}
+					/* Build initial hull	*/ 
+					sFace*	tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
+						newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
+						newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
+						newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
+					if(m_hull.count==4)
+					{
+						sFace*		best=findbest();
+						sFace		outer=*best;
+						U			pass=0;
+						U			iterations=0;
+						bind(tetra[0],0,tetra[1],0);
+						bind(tetra[0],1,tetra[2],0);
+						bind(tetra[0],2,tetra[3],0);
+						bind(tetra[1],1,tetra[3],2);
+						bind(tetra[1],2,tetra[2],1);
+						bind(tetra[2],2,tetra[3],1);
+						m_status=eStatus::Valid;
+						for(;iterations<EPA_MAX_ITERATIONS;++iterations)
+						{
+							if(m_nextsv<EPA_MAX_VERTICES)
+							{	
+								sHorizon		horizon;
+								sSV*			w=&m_sv_store[m_nextsv++];
+								bool			valid=true;					
+								best->pass	=	(U1)(++pass);
+								gjk.getsupport(best->n,*w);
+								const btScalar	wdist=btDot(best->n,w->w)-best->d;
+								if(wdist>EPA_ACCURACY)
+								{
+									for(U j=0;(j<3)&&valid;++j)
+									{
+										valid&=expand(	pass,w,
+											best->f[j],best->e[j],
+											horizon);
+									}
+									if(valid&&(horizon.nf>=3))
+									{
+										bind(horizon.cf,1,horizon.ff,2);
+										remove(m_hull,best);
+										append(m_stock,best);
+										best=findbest();
+										if(best->p>=outer.p) outer=*best;
+									} else { m_status=eStatus::InvalidHull;break; }
+								} else { m_status=eStatus::AccuraryReached;break; }
+							} else { m_status=eStatus::OutOfVertices;break; }
+						}
+						const btVector3	projection=outer.n*outer.d;
+						m_normal	=	outer.n;
+						m_depth		=	outer.d;
+						m_result.rank	=	3;
+						m_result.c[0]	=	outer.c[0];
+						m_result.c[1]	=	outer.c[1];
+						m_result.c[2]	=	outer.c[2];
+						m_result.p[0]	=	btCross(	outer.c[1]->w-projection,
+							outer.c[2]->w-projection).length();
+						m_result.p[1]	=	btCross(	outer.c[2]->w-projection,
+							outer.c[0]->w-projection).length();
+						m_result.p[2]	=	btCross(	outer.c[0]->w-projection,
+							outer.c[1]->w-projection).length();
+						const btScalar	sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
+						m_result.p[0]	/=	sum;
+						m_result.p[1]	/=	sum;
+						m_result.p[2]	/=	sum;
+						return(m_status);
+					}
+				}
+				/* Fallback		*/ 
+				m_status	=	eStatus::FallBack;
+				m_normal	=	-guess;
+				const btScalar	nl=m_normal.length();
+				if(nl>0)
+					m_normal	=	m_normal/nl;
+				else
+					m_normal	=	btVector3(1,0,0);
+				m_depth	=	0;
+				m_result.rank=1;
+				m_result.c[0]=simplex.c[0];
+				m_result.p[0]=1;	
+				return(m_status);
+			}
+			sFace*				newface(sSV* a,sSV* b,sSV* c,bool forced)
+			{
+				if(m_stock.root)
+				{
+					sFace*	face=m_stock.root;
+					remove(m_stock,face);
+					append(m_hull,face);
+					face->pass	=	0;
+					face->c[0]	=	a;
+					face->c[1]	=	b;
+					face->c[2]	=	c;
+					face->n		=	btCross(b->w-a->w,c->w-a->w);
+					const btScalar	l=face->n.length();
+					const bool		v=l>EPA_ACCURACY;
+					face->p		=	btMin(btMin(
+						btDot(a->w,btCross(face->n,a->w-b->w)),
+						btDot(b->w,btCross(face->n,b->w-c->w))),
+						btDot(c->w,btCross(face->n,c->w-a->w)))	/
+						(v?l:1);
+					face->p		=	face->p>=-EPA_INSIDE_EPS?0:face->p;
+					if(v)
+					{
+						face->d		=	btDot(a->w,face->n)/l;
+						face->n		/=	l;
+						if(forced||(face->d>=-EPA_PLANE_EPS))
+						{
+							return(face);
+						} else m_status=eStatus::NonConvex;
+					} else m_status=eStatus::Degenerated;
+					remove(m_hull,face);
+					append(m_stock,face);
+					return(0);
+				}
+				m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces;
+				return(0);
+			}
+			sFace*				findbest()
+			{
+				sFace*		minf=m_hull.root;
+				btScalar	mind=minf->d*minf->d;
+				btScalar	maxp=minf->p;
+				for(sFace* f=minf->l[1];f;f=f->l[1])
+				{
+					const btScalar	sqd=f->d*f->d;
+					if((f->p>=maxp)&&(sqd<mind))
+					{
+						minf=f;
+						mind=sqd;
+						maxp=f->p;
+					}
+				}
+				return(minf);
+			}
+			bool				expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon)
+			{
+				static const U	i1m3[]={1,2,0};
+				static const U	i2m3[]={2,0,1};
+				if(f->pass!=pass)
+				{
+					const U	e1=i1m3[e];
+					if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
+					{
+						sFace*	nf=newface(f->c[e1],f->c[e],w,false);
+						if(nf)
+						{
+							bind(nf,0,f,e);
+							if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
+							horizon.cf=nf;
+							++horizon.nf;
+							return(true);
+						}
+					}
+					else
+					{
+						const U	e2=i2m3[e];
+						f->pass		=	(U1)pass;
+						if(	expand(pass,w,f->f[e1],f->e[e1],horizon)&&
+							expand(pass,w,f->f[e2],f->e[e2],horizon))
+						{
+							remove(m_hull,f);
+							append(m_stock,f);
+							return(true);
+						}
+					}
+				}
+				return(false);
+			}
+
+	};
+
+	//
+	static void	Initialize(	const btConvexShape* shape0,const btTransform& wtrs0,
+		const btConvexShape* shape1,const btTransform& wtrs1,
+		btGjkEpaSolver2::sResults& results,
+		tShape& shape,
+		bool withmargins)
+	{
+		/* Results		*/ 
+		results.witnesses[0]	=
+			results.witnesses[1]	=	btVector3(0,0,0);
+		results.status			=	btGjkEpaSolver2::sResults::Separated;
+		/* Shape		*/ 
+		shape.m_shapes[0]		=	shape0;
+		shape.m_shapes[1]		=	shape1;
+		shape.m_toshape1		=	wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
+		shape.m_toshape0		=	wtrs0.inverseTimes(wtrs1);
+		shape.EnableMargin(withmargins);
+	}
+
+}
+
+//
+// Api
+//
+
+using namespace	gjkepa2_impl;
+
+//
+int			btGjkEpaSolver2::StackSizeRequirement()
+{
+	return(sizeof(GJK)+sizeof(EPA));
+}
+
+//
+bool		btGjkEpaSolver2::Distance(	const btConvexShape*	shape0,
+									  const btTransform&		wtrs0,
+									  const btConvexShape*	shape1,
+									  const btTransform&		wtrs1,
+									  const btVector3&		guess,
+									  sResults&				results)
+{
+	tShape			shape;
+	Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
+	GJK				gjk;
+	GJK::eStatus::_	gjk_status=gjk.Evaluate(shape,guess);
+	if(gjk_status==GJK::eStatus::Valid)
+	{
+		btVector3	w0=btVector3(0,0,0);
+		btVector3	w1=btVector3(0,0,0);
+		for(U i=0;i<gjk.m_simplex->rank;++i)
+		{
+			const btScalar	p=gjk.m_simplex->p[i];
+			w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+			w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+		}
+		results.witnesses[0]	=	wtrs0*w0;
+		results.witnesses[1]	=	wtrs0*w1;
+		results.normal			=	w0-w1;
+		results.distance		=	results.normal.length();
+		results.normal			/=	results.distance>GJK_MIN_DISTANCE?results.distance:1;
+		return(true);
+	}
+	else
+	{
+		results.status	=	gjk_status==GJK::eStatus::Inside?
+			sResults::Penetrating	:
+		sResults::GJK_Failed	;
+		return(false);
+	}
+}
+
+//
+bool	btGjkEpaSolver2::Penetration(	const btConvexShape*	shape0,
+									 const btTransform&		wtrs0,
+									 const btConvexShape*	shape1,
+									 const btTransform&		wtrs1,
+									 const btVector3&		guess,
+									 sResults&				results,
+									 bool					usemargins)
+{
+	tShape			shape;
+	Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins);
+	GJK				gjk;	
+	GJK::eStatus::_	gjk_status=gjk.Evaluate(shape,-guess);
+	switch(gjk_status)
+	{
+	case	GJK::eStatus::Inside:
+		{
+			EPA				epa;
+			EPA::eStatus::_	epa_status=epa.Evaluate(gjk,-guess);
+			if(epa_status!=EPA::eStatus::Failed)
+			{
+				btVector3	w0=btVector3(0,0,0);
+				for(U i=0;i<epa.m_result.rank;++i)
+				{
+					w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
+				}
+				results.status			=	sResults::Penetrating;
+				results.witnesses[0]	=	wtrs0*w0;
+				results.witnesses[1]	=	wtrs0*(w0-epa.m_normal*epa.m_depth);
+				results.normal			=	-epa.m_normal;
+				results.distance		=	-epa.m_depth;
+				return(true);
+			} else results.status=sResults::EPA_Failed;
+		}
+		break;
+	case	GJK::eStatus::Failed:
+		results.status=sResults::GJK_Failed;
+		break;
+		default:
+					{
+					}
+	}
+	return(false);
+}
+
+#ifndef __SPU__
+//
+btScalar	btGjkEpaSolver2::SignedDistance(const btVector3& position,
+											btScalar margin,
+											const btConvexShape* shape0,
+											const btTransform& wtrs0,
+											sResults& results)
+{
+	tShape			shape;
+	btSphereShape	shape1(margin);
+	btTransform		wtrs1(btQuaternion(0,0,0,1),position);
+	Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
+	GJK				gjk;	
+	GJK::eStatus::_	gjk_status=gjk.Evaluate(shape,btVector3(1,1,1));
+	if(gjk_status==GJK::eStatus::Valid)
+	{
+		btVector3	w0=btVector3(0,0,0);
+		btVector3	w1=btVector3(0,0,0);
+		for(U i=0;i<gjk.m_simplex->rank;++i)
+		{
+			const btScalar	p=gjk.m_simplex->p[i];
+			w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
+			w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
+		}
+		results.witnesses[0]	=	wtrs0*w0;
+		results.witnesses[1]	=	wtrs0*w1;
+		const btVector3	delta=	results.witnesses[1]-
+			results.witnesses[0];
+		const btScalar	margin=	shape0->getMarginNonVirtual()+
+			shape1.getMarginNonVirtual();
+		const btScalar	length=	delta.length();	
+		results.normal			=	delta/length;
+		results.witnesses[0]	+=	results.normal*margin;
+		return(length-margin);
+	}
+	else
+	{
+		if(gjk_status==GJK::eStatus::Inside)
+		{
+			if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
+			{
+				const btVector3	delta=	results.witnesses[0]-
+					results.witnesses[1];
+				const btScalar	length=	delta.length();
+				if (length >= SIMD_EPSILON)
+					results.normal	=	delta/length;			
+				return(-length);
+			}
+		}	
+	}
+	return(SIMD_INFINITY);
+}
+
+//
+bool	btGjkEpaSolver2::SignedDistance(const btConvexShape*	shape0,
+										const btTransform&		wtrs0,
+										const btConvexShape*	shape1,
+										const btTransform&		wtrs1,
+										const btVector3&		guess,
+										sResults&				results)
+{
+	if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
+		return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
+	else
+		return(true);
+}
+#endif //__SPU__
+
+/* Symbols cleanup		*/ 
+
+#undef GJK_MAX_ITERATIONS
+#undef GJK_ACCURARY
+#undef GJK_MIN_DISTANCE
+#undef GJK_DUPLICATED_EPS
+#undef GJK_SIMPLEX2_EPS
+#undef GJK_SIMPLEX3_EPS
+#undef GJK_SIMPLEX4_EPS
+
+#undef EPA_MAX_VERTICES
+#undef EPA_MAX_FACES
+#undef EPA_MAX_ITERATIONS
+#undef EPA_ACCURACY
+#undef EPA_FALLBACK
+#undef EPA_PLANE_EPS
+#undef EPA_INSIDE_EPS
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
new file mode 100644
index 0000000..2296527
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpa2.h
@@ -0,0 +1,73 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the
+use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software in a
+product, an acknowledgment in the product documentation would be appreciated
+but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+GJK-EPA collision solver by Nathanael Presson, 2008
+*/
+#ifndef _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
+#define _68DA1F85_90B7_4bb0_A705_83B4040A75C6_
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+///btGjkEpaSolver contributed under zlib by Nathanael Presson
+struct	btGjkEpaSolver2
+{
+struct	sResults
+	{
+	enum eStatus
+		{
+		Separated,		/* Shapes doesnt penetrate												*/ 
+		Penetrating,	/* Shapes are penetrating												*/ 
+		GJK_Failed,		/* GJK phase fail, no big issue, shapes are probably just 'touching'	*/ 
+		EPA_Failed		/* EPA phase fail, bigger problem, need to save parameters, and debug	*/ 
+		}		status;
+	btVector3	witnesses[2];
+	btVector3	normal;
+	btScalar	distance;
+	};
+
+static int		StackSizeRequirement();
+
+static bool		Distance(	const btConvexShape* shape0,const btTransform& wtrs0,
+							const btConvexShape* shape1,const btTransform& wtrs1,
+							const btVector3& guess,
+							sResults& results);
+
+static bool		Penetration(const btConvexShape* shape0,const btTransform& wtrs0,
+							const btConvexShape* shape1,const btTransform& wtrs1,
+							const btVector3& guess,
+							sResults& results,
+							bool usemargins=true);
+#ifndef __SPU__
+static btScalar	SignedDistance(	const btVector3& position,
+								btScalar margin,
+								const btConvexShape* shape,
+								const btTransform& wtrs,
+								sResults& results);
+							
+static bool		SignedDistance(	const btConvexShape* shape0,const btTransform& wtrs0,
+								const btConvexShape* shape1,const btTransform& wtrs1,
+								const btVector3& guess,
+								sResults& results);
+#endif //__SPU__
+
+};
+
+#endif
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
new file mode 100644
index 0000000..c6dc3f3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp
@@ -0,0 +1,66 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+EPA Copyright (c) Ricardo Padrela 2006
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "btGjkEpaPenetrationDepthSolver.h"
+
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+
+bool btGjkEpaPenetrationDepthSolver::calcPenDepth( btSimplexSolverInterface& simplexSolver,
+											  const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+											  const btTransform& transformA, const btTransform& transformB,
+											  btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+											  class btIDebugDraw* debugDraw, btStackAlloc* stackAlloc )
+{
+
+	(void)debugDraw;
+	(void)v;
+	(void)simplexSolver;
+
+//	const btScalar				radialmargin(btScalar(0.));
+	
+	btVector3	guessVector(transformA.getOrigin()-transformB.getOrigin());
+	btGjkEpaSolver2::sResults	results;
+	
+
+	if(btGjkEpaSolver2::Penetration(pConvexA,transformA,
+								pConvexB,transformB,
+								guessVector,results))
+	
+		{
+	//	debugDraw->drawLine(results.witnesses[1],results.witnesses[1]+results.normal,btVector3(255,0,0));
+		//resultOut->addContactPoint(results.normal,results.witnesses[1],-results.depth);
+		wWitnessOnA = results.witnesses[0];
+		wWitnessOnB = results.witnesses[1];
+		v = results.normal;
+		return true;		
+		} else
+	{
+		if(btGjkEpaSolver2::Distance(pConvexA,transformA,pConvexB,transformB,guessVector,results))
+		{
+			wWitnessOnA = results.witnesses[0];
+			wWitnessOnB = results.witnesses[1];
+			v = results.normal;
+			return false;
+		}
+	}
+
+	return false;
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
new file mode 100644
index 0000000..a49689a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h
@@ -0,0 +1,43 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+EPA Copyright (c) Ricardo Padrela 2006 
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef BT_GJP_EPA_PENETRATION_DEPTH_H
+#define BT_GJP_EPA_PENETRATION_DEPTH_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///EpaPenetrationDepthSolver uses the Expanding Polytope Algorithm to
+///calculate the penetration depth between two convex shapes.
+class btGjkEpaPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+	public :
+
+		btGjkEpaPenetrationDepthSolver()
+		{
+		}
+
+		bool			calcPenDepth( btSimplexSolverInterface& simplexSolver,
+									  const btConvexShape* pConvexA, const btConvexShape* pConvexB,
+									  const btTransform& transformA, const btTransform& transformB,
+									  btVector3& v, btVector3& wWitnessOnA, btVector3& wWitnessOnB,
+									  class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc );
+
+	private :
+
+};
+
+#endif	// BT_GJP_EPA_PENETRATION_DEPTH_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
new file mode 100644
index 0000000..1a56195
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.cpp
@@ -0,0 +1,456 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h"
+
+
+
+#if defined(DEBUG) || defined (_DEBUG)
+//#define TEST_NON_VIRTUAL 1
+#include <stdio.h> //for debug printf
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+//#define DEBUG_SPU_COLLISION_DETECTION 1
+#endif //__SPU__
+#endif
+
+//must be above the machine epsilon
+#define REL_ERROR2 btScalar(1.0e-6)
+
+//temp globals, to improve GJK/EPA/penetration calculations
+int gNumDeepPenetrationChecks = 0;
+int gNumGjkChecks = 0;
+
+
+btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver)
+:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_simplexSolver(simplexSolver),
+m_minkowskiA(objectA),
+m_minkowskiB(objectB),
+m_shapeTypeA(objectA->getShapeType()),
+m_shapeTypeB(objectB->getShapeType()),
+m_marginA(objectA->getMargin()),
+m_marginB(objectB->getMargin()),
+m_ignoreMargin(false),
+m_lastUsedMethod(-1),
+m_catchDegeneracies(1)
+{
+}
+btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver)
+:m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
+m_penetrationDepthSolver(penetrationDepthSolver),
+m_simplexSolver(simplexSolver),
+m_minkowskiA(objectA),
+m_minkowskiB(objectB),
+m_shapeTypeA(shapeTypeA),
+m_shapeTypeB(shapeTypeB),
+m_marginA(marginA),
+m_marginB(marginB),
+m_ignoreMargin(false),
+m_lastUsedMethod(-1),
+m_catchDegeneracies(1)
+{
+}
+
+void	btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
+{
+	(void)swapResults;
+
+	getClosestPointsNonVirtual(input,output,debugDraw);
+}
+
+#ifdef __SPU__
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+#else
+void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
+#endif
+{
+	m_cachedSeparatingDistance = 0.f;
+
+	btScalar distance=btScalar(0.);
+	btVector3	normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
+	btVector3 pointOnA,pointOnB;
+	btTransform	localTransA = input.m_transformA;
+	btTransform localTransB = input.m_transformB;
+	btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
+	localTransA.getOrigin() -= positionOffset;
+	localTransB.getOrigin() -= positionOffset;
+
+	bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
+
+	btScalar marginA = m_marginA;
+	btScalar marginB = m_marginB;
+
+	gNumGjkChecks++;
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+	spu_printf("inside gjk\n");
+#endif
+	//for CCD we don't use margins
+	if (m_ignoreMargin)
+	{
+		marginA = btScalar(0.);
+		marginB = btScalar(0.);
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("ignoring margin\n");
+#endif
+	}
+
+	m_curIter = 0;
+	int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN?
+	m_cachedSeparatingAxis.setValue(0,1,0);
+
+	bool isValid = false;
+	bool checkSimplex = false;
+	bool checkPenetration = true;
+	m_degenerateSimplex = 0;
+
+	m_lastUsedMethod = -1;
+
+	{
+		btScalar squaredDistance = BT_LARGE_FLOAT;
+		btScalar delta = btScalar(0.);
+		
+		btScalar margin = marginA + marginB;
+		
+		
+
+		m_simplexSolver->reset();
+		
+		for ( ; ; )
+		//while (true)
+		{
+
+			btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis();
+			btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis();
+
+#if 1
+
+			btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+			btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+
+//			btVector3 pInA  = localGetSupportingVertexWithoutMargin(m_shapeTypeA, m_minkowskiA, seperatingAxisInA,input.m_convexVertexData[0]);//, &featureIndexA);
+//			btVector3 qInB  = localGetSupportingVertexWithoutMargin(m_shapeTypeB, m_minkowskiB, seperatingAxisInB,input.m_convexVertexData[1]);//, &featureIndexB);
+
+#else
+#ifdef __SPU__
+			btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+			btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+#else
+			btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA);
+			btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB);
+#ifdef TEST_NON_VIRTUAL
+			btVector3 pInAv = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA);
+			btVector3 qInBv = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB);
+			btAssert((pInAv-pInA).length() < 0.0001);
+			btAssert((qInBv-qInB).length() < 0.0001);
+#endif //
+#endif //__SPU__
+#endif
+
+
+			btVector3  pWorld = localTransA(pInA);	
+			btVector3  qWorld = localTransB(qInB);
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("got local supporting vertices\n");
+#endif
+
+			if (check2d)
+			{
+				pWorld[2] = 0.f;
+				qWorld[2] = 0.f;
+			}
+
+			btVector3 w	= pWorld - qWorld;
+			delta = m_cachedSeparatingAxis.dot(w);
+
+			// potential exit, they don't overlap
+			if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared)) 
+			{
+				m_degenerateSimplex = 10;
+				checkSimplex=true;
+				//checkPenetration = false;
+				break;
+			}
+
+			//exit 0: the new point is already in the simplex, or we didn't come any closer
+			if (m_simplexSolver->inSimplex(w))
+			{
+				m_degenerateSimplex = 1;
+				checkSimplex = true;
+				break;
+			}
+			// are we getting any closer ?
+			btScalar f0 = squaredDistance - delta;
+			btScalar f1 = squaredDistance * REL_ERROR2;
+
+			if (f0 <= f1)
+			{
+				if (f0 <= btScalar(0.))
+				{
+					m_degenerateSimplex = 2;
+				} else
+				{
+					m_degenerateSimplex = 11;
+				}
+				checkSimplex = true;
+				break;
+			}
+
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("addVertex 1\n");
+#endif
+			//add current vertex to simplex
+			m_simplexSolver->addVertex(w, pWorld, qWorld);
+#ifdef DEBUG_SPU_COLLISION_DETECTION
+		spu_printf("addVertex 2\n");
+#endif
+			btVector3 newCachedSeparatingAxis;
+
+			//calculate the closest point to the origin (update vector v)
+			if (!m_simplexSolver->closest(newCachedSeparatingAxis))
+			{
+				m_degenerateSimplex = 3;
+				checkSimplex = true;
+				break;
+			}
+
+			if(newCachedSeparatingAxis.length2()<REL_ERROR2)
+            {
+				m_cachedSeparatingAxis = newCachedSeparatingAxis;
+                m_degenerateSimplex = 6;
+                checkSimplex = true;
+                break;
+            }
+
+			btScalar previousSquaredDistance = squaredDistance;
+			squaredDistance = newCachedSeparatingAxis.length2();
+#if 0
+///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
+			if (squaredDistance>previousSquaredDistance)
+			{
+				m_degenerateSimplex = 7;
+				squaredDistance = previousSquaredDistance;
+                checkSimplex = false;
+                break;
+			}
+#endif //
+			
+			m_cachedSeparatingAxis = newCachedSeparatingAxis;
+
+			//redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
+
+			//are we getting any closer ?
+			if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance) 
+			{ 
+				m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+				checkSimplex = true;
+				m_degenerateSimplex = 12;
+				
+				break;
+			}
+
+			  //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject   
+              if (m_curIter++ > gGjkMaxIter)   
+              {   
+                      #if defined(DEBUG) || defined (_DEBUG) || defined (DEBUG_SPU_COLLISION_DETECTION)
+
+                              printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter);   
+                              printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",   
+                              m_cachedSeparatingAxis.getX(),   
+                              m_cachedSeparatingAxis.getY(),   
+                              m_cachedSeparatingAxis.getZ(),   
+                              squaredDistance,   
+                              m_minkowskiA->getShapeType(),   
+                              m_minkowskiB->getShapeType());   
+
+                      #endif   
+                      break;   
+
+              } 
+
+
+			bool check = (!m_simplexSolver->fullSimplex());
+			//bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
+
+			if (!check)
+			{
+				//do we need this backup_closest here ?
+				m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
+				m_degenerateSimplex = 13;
+				break;
+			}
+		}
+
+		if (checkSimplex)
+		{
+			m_simplexSolver->compute_points(pointOnA, pointOnB);
+			normalInB = pointOnA-pointOnB;
+			btScalar lenSqr =m_cachedSeparatingAxis.length2();
+			
+			//valid normal
+			if (lenSqr < 0.0001)
+			{
+				m_degenerateSimplex = 5;
+			} 
+			if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
+			{
+				btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
+				normalInB *= rlen; //normalize
+				btScalar s = btSqrt(squaredDistance);
+			
+				btAssert(s > btScalar(0.0));
+				pointOnA -= m_cachedSeparatingAxis * (marginA / s);
+				pointOnB += m_cachedSeparatingAxis * (marginB / s);
+				distance = ((btScalar(1.)/rlen) - margin);
+				isValid = true;
+				
+				m_lastUsedMethod = 1;
+			} else
+			{
+				m_lastUsedMethod = 2;
+			}
+		}
+
+		bool catchDegeneratePenetrationCase = 
+			(m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01));
+
+		//if (checkPenetration && !isValid)
+		if (checkPenetration && (!isValid || catchDegeneratePenetrationCase ))
+		{
+			//penetration case
+
+			//if there is no way to handle penetrations, bail out
+			if (m_penetrationDepthSolver)
+			{
+				// Penetration depth case.
+				btVector3 tmpPointOnA,tmpPointOnB;
+				
+				gNumDeepPenetrationChecks++;
+				m_cachedSeparatingAxis.setZero();
+
+				bool isValid2 = m_penetrationDepthSolver->calcPenDepth( 
+					*m_simplexSolver, 
+					m_minkowskiA,m_minkowskiB,
+					localTransA,localTransB,
+					m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
+					debugDraw,input.m_stackAlloc
+					);
+
+
+				if (isValid2)
+				{
+					btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA;
+					btScalar lenSqr = tmpNormalInB.length2();
+					if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
+					{
+						tmpNormalInB = m_cachedSeparatingAxis;
+						lenSqr = m_cachedSeparatingAxis.length2();
+					}
+
+					if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
+					{
+						tmpNormalInB /= btSqrt(lenSqr);
+						btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length();
+						//only replace valid penetrations when the result is deeper (check)
+						if (!isValid || (distance2 < distance))
+						{
+							distance = distance2;
+							pointOnA = tmpPointOnA;
+							pointOnB = tmpPointOnB;
+							normalInB = tmpNormalInB;
+							isValid = true;
+							m_lastUsedMethod = 3;
+						} else
+						{
+							m_lastUsedMethod = 8;
+						}
+					} else
+					{
+						m_lastUsedMethod = 9;
+					}
+				} else
+
+				{
+					///this is another degenerate case, where the initial GJK calculation reports a degenerate case
+					///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
+					///reports a valid positive distance. Use the results of the second GJK instead of failing.
+					///thanks to Jacob.Langford for the reproduction case
+					///http://code.google.com/p/bullet/issues/detail?id=250
+
+				
+					if (m_cachedSeparatingAxis.length2() > btScalar(0.))
+					{
+						btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin;
+						//only replace valid distances when the distance is less
+						if (!isValid || (distance2 < distance))
+						{
+							distance = distance2;
+							pointOnA = tmpPointOnA;
+							pointOnB = tmpPointOnB;
+							pointOnA -= m_cachedSeparatingAxis * marginA ;
+							pointOnB += m_cachedSeparatingAxis * marginB ;
+							normalInB = m_cachedSeparatingAxis;
+							normalInB.normalize();
+							isValid = true;
+							m_lastUsedMethod = 6;
+						} else
+						{
+							m_lastUsedMethod = 5;
+						}
+					}
+				}
+				
+			}
+
+		}
+	}
+
+	
+
+	if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared)))
+	{
+#if 0
+///some debugging
+//		if (check2d)
+		{
+			printf("n = %2.3f,%2.3f,%2.3f. ",normalInB[0],normalInB[1],normalInB[2]);
+			printf("distance = %2.3f exit=%d deg=%d\n",distance,m_lastUsedMethod,m_degenerateSimplex);
+		}
+#endif 
+
+		m_cachedSeparatingAxis = normalInB;
+		m_cachedSeparatingDistance = distance;
+
+		output.addContactPoint(
+			normalInB,
+			pointOnB+positionOffset,
+			distance);
+
+	}
+
+
+}
+
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
new file mode 100644
index 0000000..cc6287c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h
@@ -0,0 +1,103 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+
+#ifndef GJK_PAIR_DETECTOR_H
+#define GJK_PAIR_DETECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+
+class btConvexShape;
+#include "btSimplexSolverInterface.h"
+class btConvexPenetrationDepthSolver;
+
+/// btGjkPairDetector uses GJK to implement the btDiscreteCollisionDetectorInterface
+class btGjkPairDetector : public btDiscreteCollisionDetectorInterface
+{
+	
+
+	btVector3	m_cachedSeparatingAxis;
+	btConvexPenetrationDepthSolver*	m_penetrationDepthSolver;
+	btSimplexSolverInterface* m_simplexSolver;
+	const btConvexShape* m_minkowskiA;
+	const btConvexShape* m_minkowskiB;
+	int	m_shapeTypeA;
+	int m_shapeTypeB;
+	btScalar	m_marginA;
+	btScalar	m_marginB;
+
+	bool		m_ignoreMargin;
+	btScalar	m_cachedSeparatingDistance;
+	
+
+public:
+
+	//some debugging to fix degeneracy problems
+	int			m_lastUsedMethod;
+	int			m_curIter;
+	int			m_degenerateSimplex;
+	int			m_catchDegeneracies;
+
+
+	btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver);
+	btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver*	penetrationDepthSolver);
+	virtual ~btGjkPairDetector() {};
+
+	virtual void	getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults=false);
+
+	void	getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw);
+	
+
+	void setMinkowskiA(btConvexShape* minkA)
+	{
+		m_minkowskiA = minkA;
+	}
+
+	void setMinkowskiB(btConvexShape* minkB)
+	{
+		m_minkowskiB = minkB;
+	}
+	void setCachedSeperatingAxis(const btVector3& seperatingAxis)
+	{
+		m_cachedSeparatingAxis = seperatingAxis;
+	}
+
+	const btVector3& getCachedSeparatingAxis() const
+	{
+		return m_cachedSeparatingAxis;
+	}
+	btScalar	getCachedSeparatingDistance() const
+	{
+		return m_cachedSeparatingDistance;
+	}
+
+	void	setPenetrationDepthSolver(btConvexPenetrationDepthSolver*	penetrationDepthSolver)
+	{
+		m_penetrationDepthSolver = penetrationDepthSolver;
+	}
+
+	///don't use setIgnoreMargin, it's for Bullet's internal use
+	void	setIgnoreMargin(bool ignoreMargin)
+	{
+		m_ignoreMargin = ignoreMargin;
+	}
+
+
+};
+
+#endif //GJK_PAIR_DETECTOR_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
new file mode 100644
index 0000000..e492030
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btManifoldPoint.h
@@ -0,0 +1,157 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef MANIFOLD_CONTACT_POINT_H
+#define MANIFOLD_CONTACT_POINT_H
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransformUtil.h"
+
+// Don't change following order of parameters
+ATTRIBUTE_ALIGNED16(struct) PfxConstraintRow {
+	btScalar mNormal[3];
+	btScalar mRhs;
+	btScalar mJacDiagInv;
+	btScalar mLowerLimit;
+	btScalar mUpperLimit;
+	btScalar mAccumImpulse;
+};
+
+
+
+
+/// ManifoldContactPoint collects and maintains persistent contactpoints.
+/// used to improve stability and performance of rigidbody dynamics response.
+class btManifoldPoint
+	{
+		public:
+			btManifoldPoint()
+				:m_userPersistentData(0),
+				m_appliedImpulse(0.f),
+				m_lateralFrictionInitialized(false),
+				m_appliedImpulseLateral1(0.f),
+				m_appliedImpulseLateral2(0.f),
+				m_contactMotion1(0.f),
+				m_contactMotion2(0.f),
+				m_contactCFM1(0.f),
+				m_contactCFM2(0.f),
+				m_lifeTime(0)
+			{
+				reactions_cache[0]=reactions_cache[1]=reactions_cache[2]=reactions_cache[3]=reactions_cache[4]=reactions_cache[5]=0; //***ALEX***
+			}
+
+			btManifoldPoint( const btVector3 &pointA, const btVector3 &pointB, 
+					const btVector3 &normal, 
+					btScalar distance ) :
+					m_localPointA( pointA ), 
+					m_localPointB( pointB ), 
+					m_normalWorldOnB( normal ), 
+					m_distance1( distance ),
+					m_combinedFriction(btScalar(0.)),
+					m_combinedRestitution(btScalar(0.)),
+					m_userPersistentData(0),
+					m_appliedImpulse(0.f),
+					m_lateralFrictionInitialized(false),
+					m_appliedImpulseLateral1(0.f),
+					m_appliedImpulseLateral2(0.f),
+					m_contactMotion1(0.f),
+					m_contactMotion2(0.f),
+					m_contactCFM1(0.f),
+					m_contactCFM2(0.f),
+					m_lifeTime(0)
+			{
+				/* ***ALEX*** 
+				mConstraintRow[0].mAccumImpulse = 0.f;
+				mConstraintRow[1].mAccumImpulse = 0.f;
+				mConstraintRow[2].mAccumImpulse = 0.f;
+				*/ 
+				reactions_cache[0]=reactions_cache[1]=reactions_cache[2]=reactions_cache[3]=reactions_cache[4]=reactions_cache[5]=0; //***ALEX***
+			}
+
+			float reactions_cache[6]; //***ALEX***  cache here the three multipliers N,U,V for warm starting the NCP solver.
+
+			btVector3 m_localPointA;			
+			btVector3 m_localPointB;			
+			btVector3	m_positionWorldOnB;
+			///m_positionWorldOnA is redundant information, see getPositionWorldOnA(), but for clarity
+			btVector3	m_positionWorldOnA;
+			btVector3 m_normalWorldOnB;
+		
+			btScalar	m_distance1;
+			btScalar	m_combinedFriction;
+			btScalar	m_combinedRestitution;
+
+         //BP mod, store contact triangles.
+         int	   m_partId0;
+         int      m_partId1;
+         int      m_index0;
+         int      m_index1;
+				
+			mutable void*	m_userPersistentData;
+			btScalar		m_appliedImpulse;
+
+			bool			m_lateralFrictionInitialized;
+			btScalar		m_appliedImpulseLateral1;
+			btScalar		m_appliedImpulseLateral2;
+			btScalar		m_contactMotion1;
+			btScalar		m_contactMotion2;
+			btScalar		m_contactCFM1;
+			btScalar		m_contactCFM2;
+
+			int				m_lifeTime;//lifetime of the contactpoint in frames
+			
+			btVector3		m_lateralFrictionDir1;
+			btVector3		m_lateralFrictionDir2;
+
+
+
+		//	PfxConstraintRow mConstraintRow[3]; ***ALEX*** remove to save RAM
+
+
+			btScalar getDistance() const
+			{
+				return m_distance1;
+			}
+			int	getLifeTime() const
+			{
+				return m_lifeTime;
+			}
+
+			const btVector3& getPositionWorldOnA() const {
+				return m_positionWorldOnA;
+//				return m_positionWorldOnB + m_normalWorldOnB * m_distance1;
+			}
+
+			const btVector3& getPositionWorldOnB() const
+			{
+				return m_positionWorldOnB;
+			}
+
+			void	setDistance(btScalar dist)
+			{
+				m_distance1 = dist;
+			}
+			
+			///this returns the most recent applied impulse, to satisfy contact constraints by the constraint solver
+			btScalar	getAppliedImpulse() const
+			{
+				return m_appliedImpulse;
+			}
+
+			
+
+	};
+
+#endif //MANIFOLD_CONTACT_POINT_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
new file mode 100644
index 0000000..fe31f08
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp
@@ -0,0 +1,362 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btMinkowskiPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#define NUM_UNITSPHERE_POINTS 42
+
+
+bool btMinkowskiPenetrationDepthSolver::calcPenDepth(btSimplexSolverInterface& simplexSolver,
+												   const btConvexShape* convexA,const btConvexShape* convexB,
+												   const btTransform& transA,const btTransform& transB,
+												   btVector3& v, btVector3& pa, btVector3& pb,
+												   class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
+												   )
+{
+
+	(void)stackAlloc;
+	(void)v;
+	
+	bool check2d= convexA->isConvex2d() && convexB->isConvex2d();
+
+	struct btIntermediateResult : public btDiscreteCollisionDetectorInterface::Result
+	{
+
+		btIntermediateResult():m_hasResult(false)
+		{
+		}
+		
+		btVector3 m_normalOnBInWorld;
+		btVector3 m_pointInWorld;
+		btScalar m_depth;
+		bool	m_hasResult;
+
+		virtual void setShapeIdentifiersA(int partId0,int index0)
+		{
+			(void)partId0;
+			(void)index0;
+		}
+		virtual void setShapeIdentifiersB(int partId1,int index1)
+		{
+			(void)partId1;
+			(void)index1;
+		}
+		void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+		{
+			m_normalOnBInWorld = normalOnBInWorld;
+			m_pointInWorld = pointInWorld;
+			m_depth = depth;
+			m_hasResult = true;
+		}
+	};
+
+	//just take fixed number of orientation, and sample the penetration depth in that direction
+	btScalar minProj = btScalar(BT_LARGE_FLOAT);
+	btVector3 minNorm(btScalar(0.), btScalar(0.), btScalar(0.));
+	btVector3 minA,minB;
+	btVector3 seperatingAxisInA,seperatingAxisInB;
+	btVector3 pInA,qInB,pWorld,qWorld,w;
+
+#ifndef __SPU__
+#define USE_BATCHED_SUPPORT 1
+#endif
+#ifdef USE_BATCHED_SUPPORT
+
+	btVector3	supportVerticesABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	btVector3	supportVerticesBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	btVector3	seperatingAxisInABatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	btVector3	seperatingAxisInBBatch[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2];
+	int i;
+
+	int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+	for (i=0;i<numSampleDirections;i++)
+	{
+		btVector3 norm = getPenetrationDirections()[i];
+		seperatingAxisInABatch[i] =  (-norm) * transA.getBasis() ;
+		seperatingAxisInBBatch[i] =  norm   * transB.getBasis() ;
+	}
+
+	{
+		int numPDA = convexA->getNumPreferredPenetrationDirections();
+		if (numPDA)
+		{
+			for (int i=0;i<numPDA;i++)
+			{
+				btVector3 norm;
+				convexA->getPreferredPenetrationDirection(i,norm);
+				norm  = transA.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+				seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+				numSampleDirections++;
+			}
+		}
+	}
+
+	{
+		int numPDB = convexB->getNumPreferredPenetrationDirections();
+		if (numPDB)
+		{
+			for (int i=0;i<numPDB;i++)
+			{
+				btVector3 norm;
+				convexB->getPreferredPenetrationDirection(i,norm);
+				norm  = transB.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				seperatingAxisInABatch[numSampleDirections] = (-norm) * transA.getBasis();
+				seperatingAxisInBBatch[numSampleDirections] = norm * transB.getBasis();
+				numSampleDirections++;
+			}
+		}
+	}
+
+
+
+
+	convexA->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInABatch,supportVerticesABatch,numSampleDirections);
+	convexB->batchedUnitVectorGetSupportingVertexWithoutMargin(seperatingAxisInBBatch,supportVerticesBBatch,numSampleDirections);
+
+	for (i=0;i<numSampleDirections;i++)
+	{
+		btVector3 norm = getPenetrationDirections()[i];
+		if (check2d)
+		{
+			norm[2] = 0.f;
+		}
+		if (norm.length2()>0.01)
+		{
+
+			seperatingAxisInA = seperatingAxisInABatch[i];
+			seperatingAxisInB = seperatingAxisInBBatch[i];
+
+			pInA = supportVerticesABatch[i];
+			qInB = supportVerticesBBatch[i];
+
+			pWorld = transA(pInA);	
+			qWorld = transB(qInB);
+			if (check2d)
+			{
+				pWorld[2] = 0.f;
+				qWorld[2] = 0.f;
+			}
+
+			w	= qWorld - pWorld;
+			btScalar delta = norm.dot(w);
+			//find smallest delta
+			if (delta < minProj)
+			{
+				minProj = delta;
+				minNorm = norm;
+				minA = pWorld;
+				minB = qWorld;
+			}
+		}
+	}	
+#else
+
+	int numSampleDirections = NUM_UNITSPHERE_POINTS;
+
+#ifndef __SPU__
+	{
+		int numPDA = convexA->getNumPreferredPenetrationDirections();
+		if (numPDA)
+		{
+			for (int i=0;i<numPDA;i++)
+			{
+				btVector3 norm;
+				convexA->getPreferredPenetrationDirection(i,norm);
+				norm  = transA.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				numSampleDirections++;
+			}
+		}
+	}
+
+	{
+		int numPDB = convexB->getNumPreferredPenetrationDirections();
+		if (numPDB)
+		{
+			for (int i=0;i<numPDB;i++)
+			{
+				btVector3 norm;
+				convexB->getPreferredPenetrationDirection(i,norm);
+				norm  = transB.getBasis() * norm;
+				getPenetrationDirections()[numSampleDirections] = norm;
+				numSampleDirections++;
+			}
+		}
+	}
+#endif // __SPU__
+
+	for (int i=0;i<numSampleDirections;i++)
+	{
+		const btVector3& norm = getPenetrationDirections()[i];
+		seperatingAxisInA = (-norm)* transA.getBasis();
+		seperatingAxisInB = norm* transB.getBasis();
+		pInA = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
+		qInB = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
+		pWorld = transA(pInA);	
+		qWorld = transB(qInB);
+		w	= qWorld - pWorld;
+		btScalar delta = norm.dot(w);
+		//find smallest delta
+		if (delta < minProj)
+		{
+			minProj = delta;
+			minNorm = norm;
+			minA = pWorld;
+			minB = qWorld;
+		}
+	}
+#endif //USE_BATCHED_SUPPORT
+
+	//add the margins
+
+	minA += minNorm*convexA->getMarginNonVirtual();
+	minB -= minNorm*convexB->getMarginNonVirtual();
+	//no penetration
+	if (minProj < btScalar(0.))
+		return false;
+
+	btScalar extraSeparation = 0.5f;///scale dependent
+	minProj += extraSeparation+(convexA->getMarginNonVirtual() + convexB->getMarginNonVirtual());
+
+
+
+
+
+//#define DEBUG_DRAW 1
+#ifdef DEBUG_DRAW
+	if (debugDraw)
+	{
+		btVector3 color(0,1,0);
+		debugDraw->drawLine(minA,minB,color);
+		color = btVector3 (1,1,1);
+		btVector3 vec = minB-minA;
+		btScalar prj2 = minNorm.dot(vec);
+		debugDraw->drawLine(minA,minA+(minNorm*minProj),color);
+
+	}
+#endif //DEBUG_DRAW
+
+	
+
+	btGjkPairDetector gjkdet(convexA,convexB,&simplexSolver,0);
+
+	btScalar offsetDist = minProj;
+	btVector3 offset = minNorm * offsetDist;
+	
+
+
+	btGjkPairDetector::ClosestPointInput input;
+		
+	btVector3 newOrg = transA.getOrigin() + offset;
+
+	btTransform displacedTrans = transA;
+	displacedTrans.setOrigin(newOrg);
+
+	input.m_transformA = displacedTrans;
+	input.m_transformB = transB;
+	input.m_maximumDistanceSquared = btScalar(BT_LARGE_FLOAT);//minProj;
+	
+	btIntermediateResult res;
+	gjkdet.setCachedSeperatingAxis(-minNorm);
+	gjkdet.getClosestPoints(input,res,debugDraw);
+
+	btScalar correctedMinNorm = minProj - res.m_depth;
+
+
+	//the penetration depth is over-estimated, relax it
+	btScalar penetration_relaxation= btScalar(1.);
+	minNorm*=penetration_relaxation;
+	
+
+	if (res.m_hasResult)
+	{
+
+		pa = res.m_pointInWorld - minNorm * correctedMinNorm;
+		pb = res.m_pointInWorld;
+		v = minNorm;
+		
+#ifdef DEBUG_DRAW
+		if (debugDraw)
+		{
+			btVector3 color(1,0,0);
+			debugDraw->drawLine(pa,pb,color);
+		}
+#endif//DEBUG_DRAW
+
+
+	}
+	return res.m_hasResult;
+}
+
+btVector3*	btMinkowskiPenetrationDepthSolver::getPenetrationDirections()
+{
+	static btVector3	sPenetrationDirections[NUM_UNITSPHERE_POINTS+MAX_PREFERRED_PENETRATION_DIRECTIONS*2] = 
+	{
+	btVector3(btScalar(0.000000) , btScalar(-0.000000),btScalar(-1.000000)),
+	btVector3(btScalar(0.723608) , btScalar(-0.525725),btScalar(-0.447219)),
+	btVector3(btScalar(-0.276388) , btScalar(-0.850649),btScalar(-0.447219)),
+	btVector3(btScalar(-0.894426) , btScalar(-0.000000),btScalar(-0.447216)),
+	btVector3(btScalar(-0.276388) , btScalar(0.850649),btScalar(-0.447220)),
+	btVector3(btScalar(0.723608) , btScalar(0.525725),btScalar(-0.447219)),
+	btVector3(btScalar(0.276388) , btScalar(-0.850649),btScalar(0.447220)),
+	btVector3(btScalar(-0.723608) , btScalar(-0.525725),btScalar(0.447219)),
+	btVector3(btScalar(-0.723608) , btScalar(0.525725),btScalar(0.447219)),
+	btVector3(btScalar(0.276388) , btScalar(0.850649),btScalar(0.447219)),
+	btVector3(btScalar(0.894426) , btScalar(0.000000),btScalar(0.447216)),
+	btVector3(btScalar(-0.000000) , btScalar(0.000000),btScalar(1.000000)),
+	btVector3(btScalar(0.425323) , btScalar(-0.309011),btScalar(-0.850654)),
+	btVector3(btScalar(-0.162456) , btScalar(-0.499995),btScalar(-0.850654)),
+	btVector3(btScalar(0.262869) , btScalar(-0.809012),btScalar(-0.525738)),
+	btVector3(btScalar(0.425323) , btScalar(0.309011),btScalar(-0.850654)),
+	btVector3(btScalar(0.850648) , btScalar(-0.000000),btScalar(-0.525736)),
+	btVector3(btScalar(-0.525730) , btScalar(-0.000000),btScalar(-0.850652)),
+	btVector3(btScalar(-0.688190) , btScalar(-0.499997),btScalar(-0.525736)),
+	btVector3(btScalar(-0.162456) , btScalar(0.499995),btScalar(-0.850654)),
+	btVector3(btScalar(-0.688190) , btScalar(0.499997),btScalar(-0.525736)),
+	btVector3(btScalar(0.262869) , btScalar(0.809012),btScalar(-0.525738)),
+	btVector3(btScalar(0.951058) , btScalar(0.309013),btScalar(0.000000)),
+	btVector3(btScalar(0.951058) , btScalar(-0.309013),btScalar(0.000000)),
+	btVector3(btScalar(0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+	btVector3(btScalar(0.000000) , btScalar(-1.000000),btScalar(0.000000)),
+	btVector3(btScalar(-0.587786) , btScalar(-0.809017),btScalar(0.000000)),
+	btVector3(btScalar(-0.951058) , btScalar(-0.309013),btScalar(-0.000000)),
+	btVector3(btScalar(-0.951058) , btScalar(0.309013),btScalar(-0.000000)),
+	btVector3(btScalar(-0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+	btVector3(btScalar(-0.000000) , btScalar(1.000000),btScalar(-0.000000)),
+	btVector3(btScalar(0.587786) , btScalar(0.809017),btScalar(-0.000000)),
+	btVector3(btScalar(0.688190) , btScalar(-0.499997),btScalar(0.525736)),
+	btVector3(btScalar(-0.262869) , btScalar(-0.809012),btScalar(0.525738)),
+	btVector3(btScalar(-0.850648) , btScalar(0.000000),btScalar(0.525736)),
+	btVector3(btScalar(-0.262869) , btScalar(0.809012),btScalar(0.525738)),
+	btVector3(btScalar(0.688190) , btScalar(0.499997),btScalar(0.525736)),
+	btVector3(btScalar(0.525730) , btScalar(0.000000),btScalar(0.850652)),
+	btVector3(btScalar(0.162456) , btScalar(-0.499995),btScalar(0.850654)),
+	btVector3(btScalar(-0.425323) , btScalar(-0.309011),btScalar(0.850654)),
+	btVector3(btScalar(-0.425323) , btScalar(0.309011),btScalar(0.850654)),
+	btVector3(btScalar(0.162456) , btScalar(0.499995),btScalar(0.850654))
+	};
+
+	return sPenetrationDirections;
+}
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
new file mode 100644
index 0000000..7b6c8a6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+#define MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+
+#include "btConvexPenetrationDepthSolver.h"
+
+///MinkowskiPenetrationDepthSolver implements bruteforce penetration depth estimation.
+///Implementation is based on sampling the depth using support mapping, and using GJK step to get the witness points.
+class btMinkowskiPenetrationDepthSolver : public btConvexPenetrationDepthSolver
+{
+protected:
+
+	static btVector3*	getPenetrationDirections();
+
+public:
+
+	virtual bool calcPenDepth( btSimplexSolverInterface& simplexSolver,
+	const btConvexShape* convexA,const btConvexShape* convexB,
+				const btTransform& transA,const btTransform& transB,
+			btVector3& v, btVector3& pa, btVector3& pb,
+			class btIDebugDraw* debugDraw,btStackAlloc* stackAlloc
+			);
+};
+
+#endif //MINKOWSKI_PENETRATION_DEPTH_SOLVER_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
new file mode 100644
index 0000000..5cf684c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.cpp
@@ -0,0 +1,261 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btPersistentManifold.h"
+#include "LinearMath/btTransform.h"
+
+btScalar					gContactBreakingThreshold = btScalar(0.004); //***ALEX***, 0.004, original 0.02, warning: do not set too low or you get troubles with aabb
+ContactDestroyedCallback	gContactDestroyedCallback = 0;
+ContactProcessedCallback	gContactProcessedCallback = 0;
+
+
+
+btPersistentManifold::btPersistentManifold()
+:btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+m_body0(0),
+m_body1(0),
+m_cachedPoints (0),
+m_index1a(0)
+{
+}
+
+
+
+
+#ifdef DEBUG_PERSISTENCY
+#include <stdio.h>
+void	btPersistentManifold::DebugPersistency()
+{
+	int i;
+	printf("DebugPersistency : numPoints %d\n",m_cachedPoints);
+	for (i=0;i<m_cachedPoints;i++)
+	{
+		printf("m_pointCache[%d].m_userPersistentData = %x\n",i,m_pointCache[i].m_userPersistentData);
+	}
+}
+#endif //DEBUG_PERSISTENCY
+
+void btPersistentManifold::clearUserCache(btManifoldPoint& pt)
+{
+	pt.reactions_cache[0]=pt.reactions_cache[1]=pt.reactions_cache[2]=0; //***ALEX***
+	pt.reactions_cache[3]=pt.reactions_cache[4]=pt.reactions_cache[5]=0; //***ALEX***
+
+	void* oldPtr = pt.m_userPersistentData;
+	if (oldPtr)
+	{
+#ifdef DEBUG_PERSISTENCY
+		int i;
+		int occurance = 0;
+		for (i=0;i<m_cachedPoints;i++)
+		{
+			if (m_pointCache[i].m_userPersistentData == oldPtr)
+			{
+				occurance++;
+				if (occurance>1)
+					printf("error in clearUserCache\n");
+			}
+		}
+		btAssert(occurance<=0);
+#endif //DEBUG_PERSISTENCY
+
+		if (pt.m_userPersistentData && gContactDestroyedCallback)
+		{
+			(*gContactDestroyedCallback)(pt.m_userPersistentData);
+			pt.m_userPersistentData = 0;
+		}
+		
+#ifdef DEBUG_PERSISTENCY
+		DebugPersistency();
+#endif
+	}
+
+	
+}
+
+
+int btPersistentManifold::sortCachedPoints(const btManifoldPoint& pt) 
+{
+
+		//calculate 4 possible cases areas, and take biggest area
+		//also need to keep 'deepest'
+		
+		int maxPenetrationIndex = -1;
+#define KEEP_DEEPEST_POINT 1
+#ifdef KEEP_DEEPEST_POINT
+		btScalar maxPenetration = pt.getDistance();
+		for (int i=0;i<4;i++)
+		{
+			if (m_pointCache[i].getDistance() < maxPenetration)
+			{
+				maxPenetrationIndex = i;
+				maxPenetration = m_pointCache[i].getDistance();
+			}
+		}
+#endif //KEEP_DEEPEST_POINT
+		
+		btScalar res0(btScalar(0.)),res1(btScalar(0.)),res2(btScalar(0.)),res3(btScalar(0.));
+		if (maxPenetrationIndex != 0)
+		{
+			btVector3 a0 = pt.m_localPointA-m_pointCache[1].m_localPointA;
+			btVector3 b0 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+			btVector3 cross = a0.cross(b0);
+			res0 = cross.length2();
+		}
+		if (maxPenetrationIndex != 1)
+		{
+			btVector3 a1 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+			btVector3 b1 = m_pointCache[3].m_localPointA-m_pointCache[2].m_localPointA;
+			btVector3 cross = a1.cross(b1);
+			res1 = cross.length2();
+		}
+
+		if (maxPenetrationIndex != 2)
+		{
+			btVector3 a2 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+			btVector3 b2 = m_pointCache[3].m_localPointA-m_pointCache[1].m_localPointA;
+			btVector3 cross = a2.cross(b2);
+			res2 = cross.length2();
+		}
+
+		if (maxPenetrationIndex != 3)
+		{
+			btVector3 a3 = pt.m_localPointA-m_pointCache[0].m_localPointA;
+			btVector3 b3 = m_pointCache[2].m_localPointA-m_pointCache[1].m_localPointA;
+			btVector3 cross = a3.cross(b3);
+			res3 = cross.length2();
+		}
+
+		btVector4 maxvec(res0,res1,res2,res3);
+		int biggestarea = maxvec.closestAxis4();
+		return biggestarea;
+}
+
+
+int btPersistentManifold::getCacheEntry(const btManifoldPoint& newPoint) const
+{
+	btScalar shortestDist =  getContactBreakingThreshold() * getContactBreakingThreshold();
+	int size = getNumContacts();
+	int nearestPoint = -1;
+	for( int i = 0; i < size; i++ )
+	{
+		const btManifoldPoint &mp = m_pointCache[i];
+
+		btVector3 diffA =  mp.m_localPointA- newPoint.m_localPointA;
+		const btScalar distToManiPoint = diffA.dot(diffA);
+		if( distToManiPoint < shortestDist )
+		{
+			shortestDist = distToManiPoint;
+			nearestPoint = i;
+		}
+	}
+	return nearestPoint;
+}
+
+int btPersistentManifold::addManifoldPoint(const btManifoldPoint& newPoint)
+{
+	btAssert(validContactDistance(newPoint));
+
+	int insertIndex = getNumContacts();
+	if (insertIndex == MANIFOLD_CACHE_SIZE)
+	{
+#if MANIFOLD_CACHE_SIZE >= 4
+		//sort cache so best points come first, based on area
+		insertIndex = sortCachedPoints(newPoint);
+#else
+		insertIndex = 0;
+#endif
+		clearUserCache(m_pointCache[insertIndex]);
+		
+	} else
+	{
+		m_cachedPoints++;
+
+		
+	}
+	if (insertIndex<0)
+		insertIndex=0;
+
+	btAssert(m_pointCache[insertIndex].m_userPersistentData==0);
+	m_pointCache[insertIndex] = newPoint;
+	return insertIndex;
+}
+
+btScalar	btPersistentManifold::getContactBreakingThreshold() const
+{
+	return m_contactBreakingThreshold;
+}
+
+
+
+void btPersistentManifold::refreshContactPoints(const btTransform& trA,const btTransform& trB)
+{
+	int i;
+#ifdef DEBUG_PERSISTENCY
+	printf("refreshContactPoints posA = (%f,%f,%f) posB = (%f,%f,%f)\n",
+		trA.getOrigin().getX(),
+		trA.getOrigin().getY(),
+		trA.getOrigin().getZ(),
+		trB.getOrigin().getX(),
+		trB.getOrigin().getY(),
+		trB.getOrigin().getZ());
+#endif //DEBUG_PERSISTENCY
+	/// first refresh worldspace positions and distance
+	for (i=getNumContacts()-1;i>=0;i--)
+	{
+		btManifoldPoint &manifoldPoint = m_pointCache[i];
+		manifoldPoint.m_positionWorldOnA = trA( manifoldPoint.m_localPointA );
+		manifoldPoint.m_positionWorldOnB = trB( manifoldPoint.m_localPointB );
+		manifoldPoint.m_distance1 = (manifoldPoint.m_positionWorldOnA -  manifoldPoint.m_positionWorldOnB).dot(manifoldPoint.m_normalWorldOnB);
+		manifoldPoint.m_lifeTime++;
+	}
+
+	/// then 
+	btScalar distance2d;
+	btVector3 projectedDifference,projectedPoint;
+	for (i=getNumContacts()-1;i>=0;i--)
+	{
+		
+		btManifoldPoint &manifoldPoint = m_pointCache[i];
+		//contact becomes invalid when signed distance exceeds margin (projected on contactnormal direction)
+		if (!validContactDistance(manifoldPoint))
+		{
+			removeContactPoint(i);
+		} else
+		{
+			//contact also becomes invalid when relative movement orthogonal to normal exceeds margin
+			projectedPoint = manifoldPoint.m_positionWorldOnA - manifoldPoint.m_normalWorldOnB * manifoldPoint.m_distance1;
+			projectedDifference = manifoldPoint.m_positionWorldOnB - projectedPoint;
+			distance2d = projectedDifference.dot(projectedDifference);
+			if (distance2d  > getContactBreakingThreshold()*getContactBreakingThreshold() )
+			{
+				removeContactPoint(i);
+			} else
+			{
+				//contact point processed callback
+				if (gContactProcessedCallback)
+					(*gContactProcessedCallback)(manifoldPoint,m_body0,m_body1);
+			}
+		}
+	}
+#ifdef DEBUG_PERSISTENCY
+	DebugPersistency();
+#endif //
+}
+
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
new file mode 100644
index 0000000..b374cf7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPersistentManifold.h
@@ -0,0 +1,253 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef PERSISTENT_MANIFOLD_H
+#define PERSISTENT_MANIFOLD_H
+
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "btManifoldPoint.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+struct btCollisionResult;
+
+///maximum contact breaking and merging threshold
+extern btScalar gContactBreakingThreshold;
+
+typedef bool (*ContactDestroyedCallback)(void* userPersistentData);
+typedef bool (*ContactProcessedCallback)(btManifoldPoint& cp,void* body0,void* body1);
+extern ContactDestroyedCallback	gContactDestroyedCallback;
+extern ContactProcessedCallback gContactProcessedCallback;
+
+
+enum btContactManifoldTypes
+{
+	BT_PERSISTENT_MANIFOLD_TYPE = 1,
+	MAX_CONTACT_MANIFOLD_TYPE
+};
+
+#define MANIFOLD_CACHE_SIZE 4
+
+///btPersistentManifold is a contact point cache, it stays persistent as long as objects are overlapping in the broadphase.
+///Those contact points are created by the collision narrow phase.
+///The cache can be empty, or hold 1,2,3 or 4 points. Some collision algorithms (GJK) might only add one point at a time.
+///updates/refreshes old contact points, and throw them away if necessary (distance becomes too large)
+///reduces the cache to 4 points, when more then 4 points are added, using following rules:
+///the contact point with deepest penetration is always kept, and it tries to maximuze the area covered by the points
+///note that some pairs of objects might have more then one contact manifold.
+
+
+ATTRIBUTE_ALIGNED128( class) btPersistentManifold : public btTypedObject
+//ATTRIBUTE_ALIGNED16( class) btPersistentManifold : public btTypedObject
+{
+
+	btManifoldPoint m_pointCache[MANIFOLD_CACHE_SIZE];
+
+	/// this two body pointers can point to the physics rigidbody class.
+	/// void* will allow any rigidbody class
+	void* m_body0;
+	void* m_body1;
+
+	int	m_cachedPoints;
+
+	btScalar	m_contactBreakingThreshold;
+	btScalar	m_contactProcessingThreshold;
+
+	
+	/// sort cached points so most isolated points come first
+	int	sortCachedPoints(const btManifoldPoint& pt);
+
+	int		findContactPoint(const btManifoldPoint* unUsed, int numUnused,const btManifoldPoint& pt);
+
+public:
+
+	BT_DECLARE_ALIGNED_ALLOCATOR();
+
+	int	m_companionIdA;
+	int	m_companionIdB;
+
+	int m_index1a;
+
+	btPersistentManifold();
+
+	btPersistentManifold(void* body0,void* body1,int , btScalar contactBreakingThreshold,btScalar contactProcessingThreshold)
+		: btTypedObject(BT_PERSISTENT_MANIFOLD_TYPE),
+	m_body0(body0),m_body1(body1),m_cachedPoints(0),
+		m_contactBreakingThreshold(contactBreakingThreshold),
+		m_contactProcessingThreshold(contactProcessingThreshold)
+	{
+	}
+
+	SIMD_FORCE_INLINE void* getBody0() { return m_body0;}
+	SIMD_FORCE_INLINE void* getBody1() { return m_body1;}
+
+	SIMD_FORCE_INLINE const void* getBody0() const { return m_body0;}
+	SIMD_FORCE_INLINE const void* getBody1() const { return m_body1;}
+
+	void	setBodies(void* body0,void* body1)
+	{
+		m_body0 = body0;
+		m_body1 = body1;
+	}
+
+	void clearUserCache(btManifoldPoint& pt);
+
+#ifdef DEBUG_PERSISTENCY
+	void	DebugPersistency();
+#endif //
+	
+	SIMD_FORCE_INLINE int	getNumContacts() const { return m_cachedPoints;}
+
+	SIMD_FORCE_INLINE const btManifoldPoint& getContactPoint(int index) const
+	{
+		btAssert(index < m_cachedPoints);
+		return m_pointCache[index];
+	}
+
+	SIMD_FORCE_INLINE btManifoldPoint& getContactPoint(int index)
+	{
+		btAssert(index < m_cachedPoints);
+		return m_pointCache[index];
+	}
+
+	///@todo: get this margin from the current physics / collision environment
+	btScalar	getContactBreakingThreshold() const;
+
+	btScalar	getContactProcessingThreshold() const
+	{
+		return m_contactProcessingThreshold;
+	}
+	
+	int getCacheEntry(const btManifoldPoint& newPoint) const;
+
+	int addManifoldPoint( const btManifoldPoint& newPoint);
+
+	void removeContactPoint (int index)
+	{
+		clearUserCache(m_pointCache[index]);
+
+		int lastUsedIndex = getNumContacts() - 1;
+//		m_pointCache[index] = m_pointCache[lastUsedIndex];
+		if(index != lastUsedIndex) 
+		{
+			m_pointCache[index] = m_pointCache[lastUsedIndex]; 
+			//get rid of duplicated userPersistentData pointer
+			m_pointCache[lastUsedIndex].m_userPersistentData = 0;
+			/* ***ALEX*** 
+			m_pointCache[lastUsedIndex].mConstraintRow[0].mAccumImpulse = 0.f;
+			m_pointCache[lastUsedIndex].mConstraintRow[1].mAccumImpulse = 0.f;
+			m_pointCache[lastUsedIndex].mConstraintRow[2].mAccumImpulse = 0.f;
+			*/
+			m_pointCache[lastUsedIndex].m_appliedImpulse = 0.f;
+			m_pointCache[lastUsedIndex].m_lateralFrictionInitialized = false;
+			m_pointCache[lastUsedIndex].m_appliedImpulseLateral1 = 0.f;
+			m_pointCache[lastUsedIndex].m_appliedImpulseLateral2 = 0.f;
+			m_pointCache[lastUsedIndex].m_lifeTime = 0;
+
+			m_pointCache[lastUsedIndex].reactions_cache[0] = 0;  //***ALEX***
+			m_pointCache[lastUsedIndex].reactions_cache[1] = 0;
+			m_pointCache[lastUsedIndex].reactions_cache[2] = 0;
+			m_pointCache[lastUsedIndex].reactions_cache[3] = 0;
+			m_pointCache[lastUsedIndex].reactions_cache[4] = 0;
+			m_pointCache[lastUsedIndex].reactions_cache[5] = 0;
+		}
+
+		btAssert(m_pointCache[lastUsedIndex].m_userPersistentData==0);
+		m_cachedPoints--;
+	}
+	void replaceContactPoint(const btManifoldPoint& newPoint,int insertIndex)
+	{
+		btAssert(validContactDistance(newPoint));
+
+#define MAINTAIN_PERSISTENCY 1
+#ifdef MAINTAIN_PERSISTENCY
+		int	lifeTime = m_pointCache[insertIndex].getLifeTime();
+		/* ***ALEX*** 
+		btScalar	appliedImpulse = m_pointCache[insertIndex].mConstraintRow[0].mAccumImpulse;
+		btScalar	appliedLateralImpulse1 = m_pointCache[insertIndex].mConstraintRow[1].mAccumImpulse;
+		btScalar	appliedLateralImpulse2 = m_pointCache[insertIndex].mConstraintRow[2].mAccumImpulse;
+		*/
+//		bool isLateralFrictionInitialized = m_pointCache[insertIndex].m_lateralFrictionInitialized;
+		
+		
+			
+		btAssert(lifeTime>=0);
+		void* cache = m_pointCache[insertIndex].m_userPersistentData;
+		
+		float mx = m_pointCache[insertIndex].reactions_cache[0]; //***ALEX***
+		float my = m_pointCache[insertIndex].reactions_cache[1];
+		float mz = m_pointCache[insertIndex].reactions_cache[2];
+		float mf = m_pointCache[insertIndex].reactions_cache[3];
+		float mg = m_pointCache[insertIndex].reactions_cache[4];
+		float mh = m_pointCache[insertIndex].reactions_cache[5];
+
+		m_pointCache[insertIndex] = newPoint;
+
+		m_pointCache[insertIndex].reactions_cache[0] = mx;  //***ALEX***
+		m_pointCache[insertIndex].reactions_cache[1] = my;
+		m_pointCache[insertIndex].reactions_cache[2] = mz;
+		m_pointCache[insertIndex].reactions_cache[3] = mf;
+		m_pointCache[insertIndex].reactions_cache[4] = mg;
+		m_pointCache[insertIndex].reactions_cache[5] = mh;
+
+		m_pointCache[insertIndex].m_userPersistentData = cache;
+
+/* ***ALEX*** 
+		m_pointCache[insertIndex].m_appliedImpulse = appliedImpulse;
+		m_pointCache[insertIndex].m_appliedImpulseLateral1 = appliedLateralImpulse1;
+		m_pointCache[insertIndex].m_appliedImpulseLateral2 = appliedLateralImpulse2;
+		
+		m_pointCache[insertIndex].mConstraintRow[0].mAccumImpulse =  appliedImpulse;
+		m_pointCache[insertIndex].mConstraintRow[1].mAccumImpulse = appliedLateralImpulse1;
+		m_pointCache[insertIndex].mConstraintRow[2].mAccumImpulse = appliedLateralImpulse2;
+		*/
+
+		m_pointCache[insertIndex].m_lifeTime = lifeTime;
+#else
+		clearUserCache(m_pointCache[insertIndex]);
+		m_pointCache[insertIndex] = newPoint;
+	
+#endif
+	}
+
+	bool validContactDistance(const btManifoldPoint& pt) const
+	{
+		return pt.m_distance1 <= getContactBreakingThreshold();
+	}
+	/// calculated new worldspace coordinates and depth, and reject points that exceed the collision margin
+	void	refreshContactPoints(  const btTransform& trA,const btTransform& trB);
+
+	
+	SIMD_FORCE_INLINE	void	clearManifold()
+	{
+		int i;
+		for (i=0;i<m_cachedPoints;i++)
+		{
+			clearUserCache(m_pointCache[i]);
+		}
+		m_cachedPoints = 0;
+	}
+
+
+
+}
+;
+
+
+
+
+
+#endif //PERSISTENT_MANIFOLD_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
new file mode 100644
index 0000000..6ca6054
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btPointCollector.h
@@ -0,0 +1,64 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef POINT_COLLECTOR_H
+#define POINT_COLLECTOR_H
+
+#include "btDiscreteCollisionDetectorInterface.h"
+
+
+
+struct btPointCollector : public btDiscreteCollisionDetectorInterface::Result
+{
+	
+	
+	btVector3 m_normalOnBInWorld;
+	btVector3 m_pointInWorld;
+	btScalar	m_distance;//negative means penetration
+
+	bool	m_hasResult;
+
+	btPointCollector () 
+		: m_distance(btScalar(BT_LARGE_FLOAT)),m_hasResult(false)
+	{
+	}
+
+	virtual void setShapeIdentifiersA(int partId0,int index0)
+	{
+		(void)partId0;
+		(void)index0;
+			
+	}
+	virtual void setShapeIdentifiersB(int partId1,int index1)
+	{
+		(void)partId1;
+		(void)index1;
+	}
+
+	virtual void addContactPoint(const btVector3& normalOnBInWorld,const btVector3& pointInWorld,btScalar depth)
+	{
+		if (depth< m_distance)
+		{
+			m_hasResult = true;
+			m_normalOnBInWorld = normalOnBInWorld;
+			m_pointInWorld = pointInWorld;
+			//negative means penetration
+			m_distance = depth;
+		}
+	}
+};
+
+#endif //POINT_COLLECTOR_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
new file mode 100644
index 0000000..cdb1d22
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.cpp
@@ -0,0 +1,175 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+//#include <stdio.h>
+
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btContinuousConvexCollision.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "btRaycastCallback.h"
+
+btTriangleRaycastCallback::btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags)
+	:
+	m_from(from),
+	m_to(to),
+   //@BP Mod
+   m_flags(flags),
+	m_hitFraction(btScalar(1.))
+{
+
+}
+
+
+
+void btTriangleRaycastCallback::processTriangle(btVector3* triangle,int partId, int triangleIndex)
+{
+	const btVector3 &vert0=triangle[0];
+	const btVector3 &vert1=triangle[1];
+	const btVector3 &vert2=triangle[2];
+
+	btVector3 v10; v10 = vert1 - vert0 ;
+	btVector3 v20; v20 = vert2 - vert0 ;
+
+	btVector3 triangleNormal; triangleNormal = v10.cross( v20 );
+	
+	const btScalar dist = vert0.dot(triangleNormal);
+	btScalar dist_a = triangleNormal.dot(m_from) ;
+	dist_a-= dist;
+	btScalar dist_b = triangleNormal.dot(m_to);
+	dist_b -= dist;
+
+	if ( dist_a * dist_b >= btScalar(0.0) )
+	{
+		return ; // same sign
+	}
+   //@BP Mod - Backface filtering
+   if (((m_flags & kF_FilterBackfaces) != 0) && (dist_a > btScalar(0.0)))
+   {
+      // Backface, skip check
+      return;
+   }
+	
+	const btScalar proj_length=dist_a-dist_b;
+	const btScalar distance = (dist_a)/(proj_length);
+	// Now we have the intersection point on the plane, we'll see if it's inside the triangle
+	// Add an epsilon as a tolerance for the raycast,
+	// in case the ray hits exacly on the edge of the triangle.
+	// It must be scaled for the triangle size.
+	
+	if(distance < m_hitFraction)
+	{
+		
+
+		btScalar edge_tolerance =triangleNormal.length2();		
+		edge_tolerance *= btScalar(-0.0001);
+		btVector3 point; point.setInterpolate3( m_from, m_to, distance);
+		{
+			btVector3 v0p; v0p = vert0 - point;
+			btVector3 v1p; v1p = vert1 - point;
+			btVector3 cp0; cp0 = v0p.cross( v1p );
+
+			if ( (btScalar)(cp0.dot(triangleNormal)) >=edge_tolerance) 
+			{
+						
+
+				btVector3 v2p; v2p = vert2 -  point;
+				btVector3 cp1;
+				cp1 = v1p.cross( v2p);
+				if ( (btScalar)(cp1.dot(triangleNormal)) >=edge_tolerance) 
+				{
+					btVector3 cp2;
+					cp2 = v2p.cross(v0p);
+					
+					if ( (btScalar)(cp2.dot(triangleNormal)) >=edge_tolerance) 
+					{
+                  //@BP Mod
+                  // Triangle normal isn't normalized
+				      triangleNormal.normalize();
+
+                  //@BP Mod - Allow for unflipped normal when raycasting against backfaces
+                  if (((m_flags & kF_KeepUnflippedNormal) != 0) || (dist_a <= btScalar(0.0)))
+						{
+							m_hitFraction = reportHit(-triangleNormal,distance,partId,triangleIndex);
+						}
+						else
+						{
+                     m_hitFraction = reportHit(triangleNormal,distance,partId,triangleIndex);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+
+btTriangleConvexcastCallback::btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin)
+{
+	m_convexShape = convexShape;
+	m_convexShapeFrom = convexShapeFrom;
+	m_convexShapeTo = convexShapeTo;
+	m_triangleToWorld = triangleToWorld;
+	m_hitFraction = 1.0;
+    m_triangleCollisionMargin = triangleCollisionMargin;
+}
+
+void
+btTriangleConvexcastCallback::processTriangle (btVector3* triangle, int partId, int triangleIndex)
+{
+	btTriangleShape triangleShape (triangle[0], triangle[1], triangle[2]);
+    triangleShape.setMargin(m_triangleCollisionMargin);
+
+	btVoronoiSimplexSolver	simplexSolver;
+	btGjkEpaPenetrationDepthSolver	gjkEpaPenetrationSolver;
+
+//#define  USE_SUBSIMPLEX_CONVEX_CAST 1
+//if you reenable USE_SUBSIMPLEX_CONVEX_CAST see commented out code below
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+	btSubsimplexConvexCast convexCaster(m_convexShape, &triangleShape, &simplexSolver);
+#else
+	//btGjkConvexCast	convexCaster(m_convexShape,&triangleShape,&simplexSolver);
+	btContinuousConvexCollision convexCaster(m_convexShape,&triangleShape,&simplexSolver,&gjkEpaPenetrationSolver);
+#endif //#USE_SUBSIMPLEX_CONVEX_CAST
+	
+	btConvexCast::CastResult castResult;
+	castResult.m_fraction = btScalar(1.);
+	if (convexCaster.calcTimeOfImpact(m_convexShapeFrom,m_convexShapeTo,m_triangleToWorld, m_triangleToWorld, castResult))
+	{
+		//add hit
+		if (castResult.m_normal.length2() > btScalar(0.0001))
+		{					
+			if (castResult.m_fraction < m_hitFraction)
+			{
+/* btContinuousConvexCast's normal is already in world space */
+/*
+#ifdef USE_SUBSIMPLEX_CONVEX_CAST
+				//rotate normal into worldspace
+				castResult.m_normal = m_convexShapeFrom.getBasis() * castResult.m_normal;
+#endif //USE_SUBSIMPLEX_CONVEX_CAST
+*/
+				castResult.m_normal.normalize();
+
+				reportHit (castResult.m_normal,
+							castResult.m_hitPoint,
+							castResult.m_fraction,
+							partId,
+							triangleIndex);
+			}
+		}
+	}
+}
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
new file mode 100644
index 0000000..3a1ab38
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btRaycastCallback.h
@@ -0,0 +1,71 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef RAYCAST_TRI_CALLBACK_H
+#define RAYCAST_TRI_CALLBACK_H
+
+#include "BulletCollision/CollisionShapes/btTriangleCallback.h"
+#include "LinearMath/btTransform.h"
+struct btBroadphaseProxy;
+class btConvexShape;
+
+class  btTriangleRaycastCallback: public btTriangleCallback
+{
+public:
+
+	//input
+	btVector3 m_from;
+	btVector3 m_to;
+
+   //@BP Mod - allow backface filtering and unflipped normals
+   enum EFlags
+   {
+      kF_None                 = 0,
+      kF_FilterBackfaces      = 1 << 0,
+      kF_KeepUnflippedNormal  = 1 << 1,   // Prevents returned face normal getting flipped when a ray hits a back-facing triangle
+
+      kF_Terminator        = 0xFFFFFFFF
+   };
+   unsigned int m_flags;
+
+	btScalar	m_hitFraction;
+
+	btTriangleRaycastCallback(const btVector3& from,const btVector3& to, unsigned int flags=0);
+	
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex);
+
+	virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex ) = 0;
+	
+};
+
+class btTriangleConvexcastCallback : public btTriangleCallback
+{
+public:
+	const btConvexShape* m_convexShape;
+	btTransform m_convexShapeFrom;
+	btTransform m_convexShapeTo;
+	btTransform m_triangleToWorld;
+	btScalar m_hitFraction;
+    btScalar m_triangleCollisionMargin;
+
+	btTriangleConvexcastCallback (const btConvexShape* convexShape, const btTransform& convexShapeFrom, const btTransform& convexShapeTo, const btTransform& triangleToWorld, const btScalar triangleCollisionMargin);
+
+	virtual void processTriangle (btVector3* triangle, int partId, int triangleIndex);
+
+	virtual btScalar reportHit (const btVector3& hitNormalLocal, const btVector3& hitPointLocal, btScalar hitFraction, int partId, int triangleIndex) = 0;
+};
+
+#endif //RAYCAST_TRI_CALLBACK_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
new file mode 100644
index 0000000..823b4e7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h
@@ -0,0 +1,63 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef SIMPLEX_SOLVER_INTERFACE_H
+#define SIMPLEX_SOLVER_INTERFACE_H
+
+#include "LinearMath/btVector3.h"
+
+#define NO_VIRTUAL_INTERFACE 1
+#ifdef NO_VIRTUAL_INTERFACE
+#include "btVoronoiSimplexSolver.h"
+#define btSimplexSolverInterface btVoronoiSimplexSolver
+#else
+
+/// btSimplexSolverInterface can incrementally calculate distance between origin and up to 4 vertices
+/// Used by GJK or Linear Casting. Can be implemented by the Johnson-algorithm or alternative approaches based on
+/// voronoi regions or barycentric coordinates
+class btSimplexSolverInterface
+{
+	public:
+		virtual ~btSimplexSolverInterface() {};
+
+	virtual void reset() = 0;
+
+	virtual void addVertex(const btVector3& w, const btVector3& p, const btVector3& q) = 0;
+	
+	virtual bool closest(btVector3& v) = 0;
+
+	virtual btScalar maxVertex() = 0;
+
+	virtual bool fullSimplex() const = 0;
+
+	virtual int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const = 0;
+
+	virtual bool inSimplex(const btVector3& w) = 0;
+	
+	virtual void backup_closest(btVector3& v) = 0;
+
+	virtual bool emptySimplex() const = 0;
+
+	virtual void compute_points(btVector3& p1, btVector3& p2) = 0;
+
+	virtual int numVertices() const =0;
+
+
+};
+#endif
+#endif //SIMPLEX_SOLVER_INTERFACE_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
new file mode 100644
index 0000000..18eb662
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.cpp
@@ -0,0 +1,160 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btSubSimplexConvexCast.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "btPointCollector.h"
+#include "LinearMath/btTransformUtil.h"
+
+btSubsimplexConvexCast::btSubsimplexConvexCast (const btConvexShape* convexA,const btConvexShape* convexB,btSimplexSolverInterface* simplexSolver)
+:m_simplexSolver(simplexSolver),
+m_convexA(convexA),m_convexB(convexB)
+{
+}
+
+///Typically the conservative advancement reaches solution in a few iterations, clip it to 32 for degenerate cases.
+///See discussion about this here http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=565
+#ifdef BT_USE_DOUBLE_PRECISION
+#define MAX_ITERATIONS 64
+#else
+#define MAX_ITERATIONS 32
+#endif
+bool	btSubsimplexConvexCast::calcTimeOfImpact(
+		const btTransform& fromA,
+		const btTransform& toA,
+		const btTransform& fromB,
+		const btTransform& toB,
+		CastResult& result)
+{
+
+	m_simplexSolver->reset();
+
+	btVector3 linVelA,linVelB;
+	linVelA = toA.getOrigin()-fromA.getOrigin();
+	linVelB = toB.getOrigin()-fromB.getOrigin();
+
+	btScalar lambda = btScalar(0.);
+
+	btTransform interpolatedTransA = fromA;
+	btTransform interpolatedTransB = fromB;
+
+	///take relative motion
+	btVector3 r = (linVelA-linVelB);
+	btVector3 v;
+	
+	btVector3 supVertexA = fromA(m_convexA->localGetSupportingVertex(-r*fromA.getBasis()));
+	btVector3 supVertexB = fromB(m_convexB->localGetSupportingVertex(r*fromB.getBasis()));
+	v = supVertexA-supVertexB;
+	int maxIter = MAX_ITERATIONS;
+
+	btVector3 n;
+	n.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+	bool hasResult = false;
+	btVector3 c;
+
+	btScalar lastLambda = lambda;
+
+
+	btScalar dist2 = v.length2();
+#ifdef BT_USE_DOUBLE_PRECISION
+	btScalar epsilon = btScalar(0.0001);
+#else
+	btScalar epsilon = btScalar(0.0001);
+#endif //BT_USE_DOUBLE_PRECISION
+	btVector3	w,p;
+	btScalar VdotR;
+	
+	while ( (dist2 > epsilon) && maxIter--)
+	{
+		supVertexA = interpolatedTransA(m_convexA->localGetSupportingVertex(-v*interpolatedTransA.getBasis()));
+		supVertexB = interpolatedTransB(m_convexB->localGetSupportingVertex(v*interpolatedTransB.getBasis()));
+		w = supVertexA-supVertexB;
+
+		btScalar VdotW = v.dot(w);
+
+		if (lambda > btScalar(1.0))
+		{
+			return false;
+		}
+
+		if ( VdotW > btScalar(0.))
+		{
+			VdotR = v.dot(r);
+
+			if (VdotR >= -(SIMD_EPSILON*SIMD_EPSILON))
+				return false;
+			else
+			{
+				lambda = lambda - VdotW / VdotR;
+				//interpolate to next lambda
+				//	x = s + lambda * r;
+				interpolatedTransA.getOrigin().setInterpolate3(fromA.getOrigin(),toA.getOrigin(),lambda);
+				interpolatedTransB.getOrigin().setInterpolate3(fromB.getOrigin(),toB.getOrigin(),lambda);
+				//m_simplexSolver->reset();
+				//check next line
+				 w = supVertexA-supVertexB;
+				lastLambda = lambda;
+				n = v;
+				hasResult = true;
+			}
+		} 
+		///Just like regular GJK only add the vertex if it isn't already (close) to current vertex, it would lead to divisions by zero and NaN etc.
+		if (!m_simplexSolver->inSimplex(w))
+			m_simplexSolver->addVertex( w, supVertexA , supVertexB);
+
+		if (m_simplexSolver->closest(v))
+		{
+			dist2 = v.length2();
+			hasResult = true;
+			//todo: check this normal for validity
+			//n=v;
+			//printf("V=%f , %f, %f\n",v[0],v[1],v[2]);
+			//printf("DIST2=%f\n",dist2);
+			//printf("numverts = %i\n",m_simplexSolver->numVertices());
+		} else
+		{
+			dist2 = btScalar(0.);
+		} 
+	}
+
+	//int numiter = MAX_ITERATIONS - maxIter;
+//	printf("number of iterations: %d", numiter);
+	
+	//don't report a time of impact when moving 'away' from the hitnormal
+	
+
+	result.m_fraction = lambda;
+	if (n.length2() >= (SIMD_EPSILON*SIMD_EPSILON))
+		result.m_normal = n.normalized();
+	else
+		result.m_normal = btVector3(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+
+	//don't report time of impact for motion away from the contact normal (or causes minor penetration)
+	if (result.m_normal.dot(r)>=-result.m_allowedPenetration)
+		return false;
+
+	btVector3 hitA,hitB;
+	m_simplexSolver->compute_points(hitA,hitB);
+	result.m_hitPoint=hitB;
+	return true;
+}
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
new file mode 100644
index 0000000..05662db
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef SUBSIMPLEX_CONVEX_CAST_H
+#define SUBSIMPLEX_CONVEX_CAST_H
+
+#include "btConvexCast.h"
+#include "btSimplexSolverInterface.h"
+class btConvexShape;
+
+/// btSubsimplexConvexCast implements Gino van den Bergens' paper
+///"Ray Casting against bteral Convex Objects with Application to Continuous Collision Detection"
+/// GJK based Ray Cast, optimized version
+/// Objects should not start in overlap, otherwise results are not defined.
+class btSubsimplexConvexCast : public btConvexCast
+{
+	btSimplexSolverInterface* m_simplexSolver;
+	const btConvexShape*	m_convexA;
+	const btConvexShape*	m_convexB;
+
+public:
+
+	btSubsimplexConvexCast (const btConvexShape*	shapeA,const btConvexShape*	shapeB,btSimplexSolverInterface* simplexSolver);
+
+	//virtual ~btSubsimplexConvexCast();
+	///SimsimplexConvexCast calculateTimeOfImpact calculates the time of impact+normal for the linear cast (sweep) between two moving objects.
+	///Precondition is that objects should not penetration/overlap at the start from the interval. Overlap can be tested using btGjkPairDetector.
+	virtual bool	calcTimeOfImpact(
+			const btTransform& fromA,
+			const btTransform& toA,
+			const btTransform& fromB,
+			const btTransform& toB,
+			CastResult& result);
+
+};
+
+#endif //SUBSIMPLEX_CONVEX_CAST_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
new file mode 100644
index 0000000..a775198
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.cpp
@@ -0,0 +1,609 @@
+
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+	
+	Elsevier CDROM license agreements grants nonexclusive license to use the software
+	for any purpose, commercial or non-commercial as long as the following credit is included
+	identifying the original source of the software:
+
+	Parts of the source are "from the book Real-Time Collision Detection by
+	Christer Ericson, published by Morgan Kaufmann Publishers,
+	(c) 2005 Elsevier Inc."
+		
+*/
+
+
+#include "btVoronoiSimplexSolver.h"
+
+#define VERTA  0
+#define VERTB  1
+#define VERTC  2
+#define VERTD  3
+
+#define CATCH_DEGENERATE_TETRAHEDRON 1
+void	btVoronoiSimplexSolver::removeVertex(int index)
+{
+	
+	btAssert(m_numVertices>0);
+	m_numVertices--;
+	m_simplexVectorW[index] = m_simplexVectorW[m_numVertices];
+	m_simplexPointsP[index] = m_simplexPointsP[m_numVertices];
+	m_simplexPointsQ[index] = m_simplexPointsQ[m_numVertices];
+}
+
+void	btVoronoiSimplexSolver::reduceVertices (const btUsageBitfield& usedVerts)
+{
+	if ((numVertices() >= 4) && (!usedVerts.usedVertexD))
+		removeVertex(3);
+
+	if ((numVertices() >= 3) && (!usedVerts.usedVertexC))
+		removeVertex(2);
+
+	if ((numVertices() >= 2) && (!usedVerts.usedVertexB))
+		removeVertex(1);
+	
+	if ((numVertices() >= 1) && (!usedVerts.usedVertexA))
+		removeVertex(0);
+
+}
+
+
+
+
+
+//clear the simplex, remove all the vertices
+void btVoronoiSimplexSolver::reset()
+{
+	m_cachedValidClosest = false;
+	m_numVertices = 0;
+	m_needsUpdate = true;
+	m_lastW = btVector3(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
+	m_cachedBC.reset();
+}
+
+
+
+	//add a vertex
+void btVoronoiSimplexSolver::addVertex(const btVector3& w, const btVector3& p, const btVector3& q)
+{
+	m_lastW = w;
+	m_needsUpdate = true;
+
+	m_simplexVectorW[m_numVertices] = w;
+	m_simplexPointsP[m_numVertices] = p;
+	m_simplexPointsQ[m_numVertices] = q;
+
+	m_numVertices++;
+}
+
+bool	btVoronoiSimplexSolver::updateClosestVectorAndPoints()
+{
+	
+	if (m_needsUpdate)
+	{
+		m_cachedBC.reset();
+
+		m_needsUpdate = false;
+
+		switch (numVertices())
+		{
+		case 0:
+				m_cachedValidClosest = false;
+				break;
+		case 1:
+			{
+				m_cachedP1 = m_simplexPointsP[0];
+				m_cachedP2 = m_simplexPointsQ[0];
+				m_cachedV = m_cachedP1-m_cachedP2; //== m_simplexVectorW[0]
+				m_cachedBC.reset();
+				m_cachedBC.setBarycentricCoordinates(btScalar(1.),btScalar(0.),btScalar(0.),btScalar(0.));
+				m_cachedValidClosest = m_cachedBC.isValid();
+				break;
+			};
+		case 2:
+			{
+			//closest point origin from line segment
+					const btVector3& from = m_simplexVectorW[0];
+					const btVector3& to = m_simplexVectorW[1];
+					btVector3 nearest;
+
+					btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+					btVector3 diff = p - from;
+					btVector3 v = to - from;
+					btScalar t = v.dot(diff);
+					
+					if (t > 0) {
+						btScalar dotVV = v.dot(v);
+						if (t < dotVV) {
+							t /= dotVV;
+							diff -= t*v;
+							m_cachedBC.m_usedVertices.usedVertexA = true;
+							m_cachedBC.m_usedVertices.usedVertexB = true;
+						} else {
+							t = 1;
+							diff -= v;
+							//reduce to 1 point
+							m_cachedBC.m_usedVertices.usedVertexB = true;
+						}
+					} else
+					{
+						t = 0;
+						//reduce to 1 point
+						m_cachedBC.m_usedVertices.usedVertexA = true;
+					}
+					m_cachedBC.setBarycentricCoordinates(1-t,t);
+					nearest = from + t*v;
+
+					m_cachedP1 = m_simplexPointsP[0] + t * (m_simplexPointsP[1] - m_simplexPointsP[0]);
+					m_cachedP2 = m_simplexPointsQ[0] + t * (m_simplexPointsQ[1] - m_simplexPointsQ[0]);
+					m_cachedV = m_cachedP1 - m_cachedP2;
+					
+					reduceVertices(m_cachedBC.m_usedVertices);
+
+					m_cachedValidClosest = m_cachedBC.isValid();
+					break;
+			}
+		case 3: 
+			{ 
+				//closest point origin from triangle 
+				btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.)); 
+
+				const btVector3& a = m_simplexVectorW[0]; 
+				const btVector3& b = m_simplexVectorW[1]; 
+				const btVector3& c = m_simplexVectorW[2]; 
+
+				closestPtPointTriangle(p,a,b,c,m_cachedBC); 
+				m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] + 
+				m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] + 
+				m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2]; 
+
+				m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] + 
+				m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] + 
+				m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2]; 
+
+				m_cachedV = m_cachedP1-m_cachedP2; 
+
+				reduceVertices (m_cachedBC.m_usedVertices); 
+				m_cachedValidClosest = m_cachedBC.isValid(); 
+
+				break; 
+			}
+		case 4:
+			{
+
+				
+				btVector3 p (btScalar(0.),btScalar(0.),btScalar(0.));
+				
+				const btVector3& a = m_simplexVectorW[0];
+				const btVector3& b = m_simplexVectorW[1];
+				const btVector3& c = m_simplexVectorW[2];
+				const btVector3& d = m_simplexVectorW[3];
+
+				bool hasSeperation = closestPtPointTetrahedron(p,a,b,c,d,m_cachedBC);
+
+				if (hasSeperation)
+				{
+
+					m_cachedP1 = m_simplexPointsP[0] * m_cachedBC.m_barycentricCoords[0] +
+						m_simplexPointsP[1] * m_cachedBC.m_barycentricCoords[1] +
+						m_simplexPointsP[2] * m_cachedBC.m_barycentricCoords[2] +
+						m_simplexPointsP[3] * m_cachedBC.m_barycentricCoords[3];
+
+					m_cachedP2 = m_simplexPointsQ[0] * m_cachedBC.m_barycentricCoords[0] +
+						m_simplexPointsQ[1] * m_cachedBC.m_barycentricCoords[1] +
+						m_simplexPointsQ[2] * m_cachedBC.m_barycentricCoords[2] +
+						m_simplexPointsQ[3] * m_cachedBC.m_barycentricCoords[3];
+
+					m_cachedV = m_cachedP1-m_cachedP2;
+					reduceVertices (m_cachedBC.m_usedVertices);
+				} else
+				{
+//					printf("sub distance got penetration\n");
+
+					if (m_cachedBC.m_degenerate)
+					{
+						m_cachedValidClosest = false;
+					} else
+					{
+						m_cachedValidClosest = true;
+						//degenerate case == false, penetration = true + zero
+						m_cachedV.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+					}
+					break;
+				}
+
+				m_cachedValidClosest = m_cachedBC.isValid();
+
+				//closest point origin from tetrahedron
+				break;
+			}
+		default:
+			{
+				m_cachedValidClosest = false;
+			}
+		};
+	}
+
+	return m_cachedValidClosest;
+
+}
+
+//return/calculate the closest vertex
+bool btVoronoiSimplexSolver::closest(btVector3& v)
+{
+	bool succes = updateClosestVectorAndPoints();
+	v = m_cachedV;
+	return succes;
+}
+
+
+
+btScalar btVoronoiSimplexSolver::maxVertex()
+{
+	int i, numverts = numVertices();
+	btScalar maxV = btScalar(0.);
+	for (i=0;i<numverts;i++)
+	{
+		btScalar curLen2 = m_simplexVectorW[i].length2();
+		if (maxV < curLen2)
+			maxV = curLen2;
+	}
+	return maxV;
+}
+
+
+
+	//return the current simplex
+int btVoronoiSimplexSolver::getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const
+{
+	int i;
+	for (i=0;i<numVertices();i++)
+	{
+		yBuf[i] = m_simplexVectorW[i];
+		pBuf[i] = m_simplexPointsP[i];
+		qBuf[i] = m_simplexPointsQ[i];
+	}
+	return numVertices();
+}
+
+
+
+
+bool btVoronoiSimplexSolver::inSimplex(const btVector3& w)
+{
+	bool found = false;
+	int i, numverts = numVertices();
+	//btScalar maxV = btScalar(0.);
+	
+	//w is in the current (reduced) simplex
+	for (i=0;i<numverts;i++)
+	{
+#ifdef BT_USE_EQUAL_VERTEX_THRESHOLD
+		if ( m_simplexVectorW[i].distance2(w) <= m_equalVertexThreshold)
+#else
+		if (m_simplexVectorW[i] == w)
+#endif
+			found = true;
+	}
+
+	//check in case lastW is already removed
+	if (w == m_lastW)
+		return true;
+    	
+	return found;
+}
+
+void btVoronoiSimplexSolver::backup_closest(btVector3& v) 
+{
+	v = m_cachedV;
+}
+
+
+bool btVoronoiSimplexSolver::emptySimplex() const 
+{
+	return (numVertices() == 0);
+
+}
+
+void btVoronoiSimplexSolver::compute_points(btVector3& p1, btVector3& p2) 
+{
+	updateClosestVectorAndPoints();
+	p1 = m_cachedP1;
+	p2 = m_cachedP2;
+
+}
+
+
+
+
+bool	btVoronoiSimplexSolver::closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result)
+{
+	result.m_usedVertices.reset();
+
+    // Check if P in vertex region outside A
+    btVector3 ab = b - a;
+    btVector3 ac = c - a;
+    btVector3 ap = p - a;
+    btScalar d1 = ab.dot(ap);
+    btScalar d2 = ac.dot(ap);
+    if (d1 <= btScalar(0.0) && d2 <= btScalar(0.0)) 
+	{
+		result.m_closestPointOnSimplex = a;
+		result.m_usedVertices.usedVertexA = true;
+		result.setBarycentricCoordinates(1,0,0);
+		return true;// a; // barycentric coordinates (1,0,0)
+	}
+
+    // Check if P in vertex region outside B
+    btVector3 bp = p - b;
+    btScalar d3 = ab.dot(bp);
+    btScalar d4 = ac.dot(bp);
+    if (d3 >= btScalar(0.0) && d4 <= d3) 
+	{
+		result.m_closestPointOnSimplex = b;
+		result.m_usedVertices.usedVertexB = true;
+		result.setBarycentricCoordinates(0,1,0);
+
+		return true; // b; // barycentric coordinates (0,1,0)
+	}
+    // Check if P in edge region of AB, if so return projection of P onto AB
+    btScalar vc = d1*d4 - d3*d2;
+    if (vc <= btScalar(0.0) && d1 >= btScalar(0.0) && d3 <= btScalar(0.0)) {
+        btScalar v = d1 / (d1 - d3);
+		result.m_closestPointOnSimplex = a + v * ab;
+		result.m_usedVertices.usedVertexA = true;
+		result.m_usedVertices.usedVertexB = true;
+		result.setBarycentricCoordinates(1-v,v,0);
+		return true;
+        //return a + v * ab; // barycentric coordinates (1-v,v,0)
+    }
+
+    // Check if P in vertex region outside C
+    btVector3 cp = p - c;
+    btScalar d5 = ab.dot(cp);
+    btScalar d6 = ac.dot(cp);
+    if (d6 >= btScalar(0.0) && d5 <= d6) 
+	{
+		result.m_closestPointOnSimplex = c;
+		result.m_usedVertices.usedVertexC = true;
+		result.setBarycentricCoordinates(0,0,1);
+		return true;//c; // barycentric coordinates (0,0,1)
+	}
+
+    // Check if P in edge region of AC, if so return projection of P onto AC
+    btScalar vb = d5*d2 - d1*d6;
+    if (vb <= btScalar(0.0) && d2 >= btScalar(0.0) && d6 <= btScalar(0.0)) {
+        btScalar w = d2 / (d2 - d6);
+		result.m_closestPointOnSimplex = a + w * ac;
+		result.m_usedVertices.usedVertexA = true;
+		result.m_usedVertices.usedVertexC = true;
+		result.setBarycentricCoordinates(1-w,0,w);
+		return true;
+        //return a + w * ac; // barycentric coordinates (1-w,0,w)
+    }
+
+    // Check if P in edge region of BC, if so return projection of P onto BC
+    btScalar va = d3*d6 - d5*d4;
+    if (va <= btScalar(0.0) && (d4 - d3) >= btScalar(0.0) && (d5 - d6) >= btScalar(0.0)) {
+        btScalar w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
+		
+		result.m_closestPointOnSimplex = b + w * (c - b);
+		result.m_usedVertices.usedVertexB = true;
+		result.m_usedVertices.usedVertexC = true;
+		result.setBarycentricCoordinates(0,1-w,w);
+		return true;		
+       // return b + w * (c - b); // barycentric coordinates (0,1-w,w)
+    }
+
+    // P inside face region. Compute Q through its barycentric coordinates (u,v,w)
+    btScalar denom = btScalar(1.0) / (va + vb + vc);
+    btScalar v = vb * denom;
+    btScalar w = vc * denom;
+    
+	result.m_closestPointOnSimplex = a + ab * v + ac * w;
+	result.m_usedVertices.usedVertexA = true;
+	result.m_usedVertices.usedVertexB = true;
+	result.m_usedVertices.usedVertexC = true;
+	result.setBarycentricCoordinates(1-v-w,v,w);
+	
+	return true;
+//	return a + ab * v + ac * w; // = u*a + v*b + w*c, u = va * denom = btScalar(1.0) - v - w
+
+}
+
+
+
+
+
+/// Test if point p and d lie on opposite sides of plane through abc
+int btVoronoiSimplexSolver::pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d)
+{
+	btVector3 normal = (b-a).cross(c-a);
+
+    btScalar signp = (p - a).dot(normal); // [AP AB AC]
+    btScalar signd = (d - a).dot( normal); // [AD AB AC]
+
+#ifdef CATCH_DEGENERATE_TETRAHEDRON
+#ifdef BT_USE_DOUBLE_PRECISION
+if (signd * signd < (btScalar(1e-8) * btScalar(1e-8)))
+	{
+		return -1;
+	}
+#else
+	if (signd * signd < (btScalar(1e-4) * btScalar(1e-4)))
+	{
+//		printf("affine dependent/degenerate\n");//
+		return -1;
+	}
+#endif
+
+#endif
+	// Points on opposite sides if expression signs are opposite
+    return signp * signd < btScalar(0.);
+}
+
+
+bool	btVoronoiSimplexSolver::closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult)
+{
+	btSubSimplexClosestResult tempResult;
+
+    // Start out assuming point inside all halfspaces, so closest to itself
+	finalResult.m_closestPointOnSimplex = p;
+	finalResult.m_usedVertices.reset();
+    finalResult.m_usedVertices.usedVertexA = true;
+	finalResult.m_usedVertices.usedVertexB = true;
+	finalResult.m_usedVertices.usedVertexC = true;
+	finalResult.m_usedVertices.usedVertexD = true;
+
+    int pointOutsideABC = pointOutsideOfPlane(p, a, b, c, d);
+	int pointOutsideACD = pointOutsideOfPlane(p, a, c, d, b);
+  	int	pointOutsideADB = pointOutsideOfPlane(p, a, d, b, c);
+	int	pointOutsideBDC = pointOutsideOfPlane(p, b, d, c, a);
+
+   if (pointOutsideABC < 0 || pointOutsideACD < 0 || pointOutsideADB < 0 || pointOutsideBDC < 0)
+   {
+	   finalResult.m_degenerate = true;
+	   return false;
+   }
+
+   if (!pointOutsideABC  && !pointOutsideACD && !pointOutsideADB && !pointOutsideBDC)
+	 {
+		 return false;
+	 }
+
+
+    btScalar bestSqDist = FLT_MAX;
+    // If point outside face abc then compute closest point on abc
+	if (pointOutsideABC) 
+	{
+        closestPtPointTriangle(p, a, b, c,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		
+        btScalar sqDist = (q - p).dot( q - p);
+        // Update best closest point if (squared) distance is less than current best
+        if (sqDist < bestSqDist) {
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			//convert result bitmask!
+			finalResult.m_usedVertices.reset();
+			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexB;
+			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+			finalResult.setBarycentricCoordinates(
+					tempResult.m_barycentricCoords[VERTA],
+					tempResult.m_barycentricCoords[VERTB],
+					tempResult.m_barycentricCoords[VERTC],
+					0
+			);
+
+		}
+    }
+  
+
+	// Repeat test for face acd
+	if (pointOutsideACD) 
+	{
+        closestPtPointTriangle(p, a, c, d,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		//convert result bitmask!
+
+        btScalar sqDist = (q - p).dot( q - p);
+        if (sqDist < bestSqDist) 
+		{
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			finalResult.m_usedVertices.reset();
+			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+
+			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexB;
+			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexC;
+			finalResult.setBarycentricCoordinates(
+					tempResult.m_barycentricCoords[VERTA],
+					0,
+					tempResult.m_barycentricCoords[VERTB],
+					tempResult.m_barycentricCoords[VERTC]
+			);
+
+		}
+    }
+    // Repeat test for face adb
+
+	
+	if (pointOutsideADB)
+	{
+		closestPtPointTriangle(p, a, d, b,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		//convert result bitmask!
+
+        btScalar sqDist = (q - p).dot( q - p);
+        if (sqDist < bestSqDist) 
+		{
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			finalResult.m_usedVertices.reset();
+			finalResult.m_usedVertices.usedVertexA = tempResult.m_usedVertices.usedVertexA;
+			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexC;
+			
+			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+			finalResult.setBarycentricCoordinates(
+					tempResult.m_barycentricCoords[VERTA],
+					tempResult.m_barycentricCoords[VERTC],
+					0,
+					tempResult.m_barycentricCoords[VERTB]
+			);
+
+		}
+    }
+    // Repeat test for face bdc
+    
+
+	if (pointOutsideBDC)
+	{
+        closestPtPointTriangle(p, b, d, c,tempResult);
+		btVector3 q = tempResult.m_closestPointOnSimplex;
+		//convert result bitmask!
+        btScalar sqDist = (q - p).dot( q - p);
+        if (sqDist < bestSqDist) 
+		{
+			bestSqDist = sqDist;
+			finalResult.m_closestPointOnSimplex = q;
+			finalResult.m_usedVertices.reset();
+			//
+			finalResult.m_usedVertices.usedVertexB = tempResult.m_usedVertices.usedVertexA;
+			finalResult.m_usedVertices.usedVertexC = tempResult.m_usedVertices.usedVertexC;
+			finalResult.m_usedVertices.usedVertexD = tempResult.m_usedVertices.usedVertexB;
+
+			finalResult.setBarycentricCoordinates(
+					0,
+					tempResult.m_barycentricCoords[VERTA],
+					tempResult.m_barycentricCoords[VERTC],
+					tempResult.m_barycentricCoords[VERTB]
+			);
+
+		}
+    }
+
+	//help! we ended up full !
+	
+	if (finalResult.m_usedVertices.usedVertexA &&
+		finalResult.m_usedVertices.usedVertexB &&
+		finalResult.m_usedVertices.usedVertexC &&
+		finalResult.m_usedVertices.usedVertexD) 
+	{
+		return true;
+	}
+
+    return true;
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
new file mode 100644
index 0000000..9a4f552
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h
@@ -0,0 +1,178 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef btVoronoiSimplexSolver_H
+#define btVoronoiSimplexSolver_H
+
+#include "btSimplexSolverInterface.h"
+
+
+
+#define VORONOI_SIMPLEX_MAX_VERTS 5
+
+///disable next define, or use defaultCollisionConfiguration->getSimplexSolver()->setEqualVertexThreshold(0.f) to disable/configure
+#define BT_USE_EQUAL_VERTEX_THRESHOLD
+#define VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD 0.0001f
+
+
+struct btUsageBitfield{
+	btUsageBitfield()
+	{
+		reset();
+	}
+
+	void reset()
+	{
+		usedVertexA = false;
+		usedVertexB = false;
+		usedVertexC = false;
+		usedVertexD = false;
+	}
+	unsigned short usedVertexA	: 1;
+	unsigned short usedVertexB	: 1;
+	unsigned short usedVertexC	: 1;
+	unsigned short usedVertexD	: 1;
+	unsigned short unused1		: 1;
+	unsigned short unused2		: 1;
+	unsigned short unused3		: 1;
+	unsigned short unused4		: 1;
+};
+
+
+struct	btSubSimplexClosestResult
+{
+	btVector3	m_closestPointOnSimplex;
+	//MASK for m_usedVertices
+	//stores the simplex vertex-usage, using the MASK, 
+	// if m_usedVertices & MASK then the related vertex is used
+	btUsageBitfield	m_usedVertices;
+	btScalar	m_barycentricCoords[4];
+	bool m_degenerate;
+
+	void	reset()
+	{
+		m_degenerate = false;
+		setBarycentricCoordinates();
+		m_usedVertices.reset();
+	}
+	bool	isValid()
+	{
+		bool valid = (m_barycentricCoords[0] >= btScalar(0.)) &&
+			(m_barycentricCoords[1] >= btScalar(0.)) &&
+			(m_barycentricCoords[2] >= btScalar(0.)) &&
+			(m_barycentricCoords[3] >= btScalar(0.));
+
+
+		return valid;
+	}
+	void	setBarycentricCoordinates(btScalar a=btScalar(0.),btScalar b=btScalar(0.),btScalar c=btScalar(0.),btScalar d=btScalar(0.))
+	{
+		m_barycentricCoords[0] = a;
+		m_barycentricCoords[1] = b;
+		m_barycentricCoords[2] = c;
+		m_barycentricCoords[3] = d;
+	}
+
+};
+
+/// btVoronoiSimplexSolver is an implementation of the closest point distance algorithm from a 1-4 points simplex to the origin.
+/// Can be used with GJK, as an alternative to Johnson distance algorithm.
+#ifdef NO_VIRTUAL_INTERFACE
+class btVoronoiSimplexSolver
+#else
+class btVoronoiSimplexSolver : public btSimplexSolverInterface
+#endif
+{
+public:
+
+	int	m_numVertices;
+
+	btVector3	m_simplexVectorW[VORONOI_SIMPLEX_MAX_VERTS];
+	btVector3	m_simplexPointsP[VORONOI_SIMPLEX_MAX_VERTS];
+	btVector3	m_simplexPointsQ[VORONOI_SIMPLEX_MAX_VERTS];
+
+	
+
+	btVector3	m_cachedP1;
+	btVector3	m_cachedP2;
+	btVector3	m_cachedV;
+	btVector3	m_lastW;
+	
+	btScalar	m_equalVertexThreshold;
+	bool		m_cachedValidClosest;
+
+
+	btSubSimplexClosestResult m_cachedBC;
+
+	bool	m_needsUpdate;
+	
+	void	removeVertex(int index);
+	void	reduceVertices (const btUsageBitfield& usedVerts);
+	bool	updateClosestVectorAndPoints();
+
+	bool	closestPtPointTetrahedron(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d, btSubSimplexClosestResult& finalResult);
+	int		pointOutsideOfPlane(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c, const btVector3& d);
+	bool	closestPtPointTriangle(const btVector3& p, const btVector3& a, const btVector3& b, const btVector3& c,btSubSimplexClosestResult& result);
+
+public:
+
+	btVoronoiSimplexSolver()
+		:  m_equalVertexThreshold(VORONOI_DEFAULT_EQUAL_VERTEX_THRESHOLD)
+	{
+	}
+	 void reset();
+
+	 void addVertex(const btVector3& w, const btVector3& p, const btVector3& q);
+
+	 void	setEqualVertexThreshold(btScalar threshold)
+	 {
+		 m_equalVertexThreshold = threshold;
+	 }
+
+	 btScalar	getEqualVertexThreshold() const
+	 {
+		 return m_equalVertexThreshold;
+	 }
+
+	 bool closest(btVector3& v);
+
+	 btScalar maxVertex();
+
+	 bool fullSimplex() const
+	 {
+		 return (m_numVertices == 4);
+	 }
+
+	 int getSimplex(btVector3 *pBuf, btVector3 *qBuf, btVector3 *yBuf) const;
+
+	 bool inSimplex(const btVector3& w);
+	
+	 void backup_closest(btVector3& v) ;
+
+	 bool emptySimplex() const ;
+
+	 void compute_points(btVector3& p1, btVector3& p2) ;
+
+	 int numVertices() const 
+	 {
+		 return m_numVertices;
+	 }
+
+
+};
+
+#endif //VoronoiSimplexSolver
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bChunk.cpp b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bChunk.cpp
new file mode 100644
index 0000000..564e550
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bChunk.cpp
@@ -0,0 +1,75 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "bChunk.h"
+#include "bDefines.h"
+#include "bFile.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+using namespace bParse;
+
+
+// ----------------------------------------------------- //
+short ChunkUtils::swapShort(short sht)
+{
+	SWITCH_SHORT(sht);
+	return sht;
+}
+
+// ----------------------------------------------------- //
+int ChunkUtils::swapInt(int inte)
+{
+	SWITCH_INT(inte);
+	return inte;
+}
+
+// ----------------------------------------------------- //
+long64 ChunkUtils::swapLong64(long64 lng)
+{
+	SWITCH_LONGINT(lng);
+	return lng;
+}
+
+// ----------------------------------------------------- //
+int ChunkUtils::getOffset(int flags)
+{
+	// if the file is saved in a
+	// different format, get the
+	// file's chunk size
+	int res = CHUNK_HEADER_LEN;
+
+	if (VOID_IS_8)
+	{
+		if (flags &FD_BITS_VARIES)
+			res = sizeof(bChunkPtr4);
+	}
+	else
+	{
+		if (flags &FD_BITS_VARIES)
+			res = sizeof(bChunkPtr8);
+	}
+	return res;
+}
+
+
+
+
+
+//eof
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bChunk.h b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bChunk.h
new file mode 100644
index 0000000..77039bc
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bChunk.h
@@ -0,0 +1,92 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef __BCHUNK_H__
+#define __BCHUNK_H__
+
+#if defined (_WIN32) && ! defined (__MINGW32__)
+	#define long64 __int64
+#elif defined (__MINGW32__)	
+	#include <stdint.h>
+	#define long64 int64_t
+#else
+	#define long64 long long
+#endif
+
+
+namespace bParse {
+
+
+	// ----------------------------------------------------- //
+	class bChunkPtr4
+	{
+	public:
+		bChunkPtr4(){}
+		int code;
+		int len;
+		union
+		{
+			int m_uniqueInt;
+		};
+		int dna_nr;
+		int nr;
+	};
+
+	// ----------------------------------------------------- //
+	class bChunkPtr8
+	{
+	public:
+		bChunkPtr8(){}
+		int code,  len;
+		union
+		{
+			long64 oldPrev;
+			int	m_uniqueInts[2];
+		};
+		int dna_nr, nr;
+	};
+
+	// ----------------------------------------------------- //
+	class bChunkInd
+	{
+	public:
+		bChunkInd(){}
+		int code, len;
+		void *oldPtr;
+		int dna_nr, nr;
+	};
+
+
+	// ----------------------------------------------------- //
+	class ChunkUtils
+	{
+	public:
+		
+		// file chunk offset
+		static int getOffset(int flags);
+
+		// endian utils
+		static short swapShort(short sht);
+		static int swapInt(int inte);
+		static long64 swapLong64(long64 lng);
+
+	};
+
+
+	const int CHUNK_HEADER_LEN = ((sizeof(bChunkInd)));
+	const bool VOID_IS_8 = ((sizeof(void*)==8));
+}
+
+#endif//__BCHUNK_H__
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bCommon.h b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bCommon.h
new file mode 100644
index 0000000..b01d2b8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bCommon.h
@@ -0,0 +1,39 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef __BCOMMON_H__
+#define __BCOMMON_H__
+
+
+#include <assert.h>
+//#include "bLog.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btHashMap.h"
+
+namespace bParse {
+
+	class bMain;
+	class bFileData;
+	class bFile;
+	class bDNA;
+
+	// delete void* undefined
+	typedef struct bStructHandle {int unused;}bStructHandle;
+	typedef btAlignedObjectArray<bStructHandle*>	bListBasePtr;
+	typedef btHashMap<btHashPtr, bStructHandle*> bPtrMap;
+}
+
+
+#endif//__BCOMMON_H__
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDNA.cpp b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDNA.cpp
new file mode 100644
index 0000000..2eac23f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDNA.cpp
@@ -0,0 +1,636 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include <assert.h>
+
+#include "bDNA.h"
+#include "bChunk.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+//this define will force traversal of structures, to check backward (and forward) compatibility
+//#define TEST_BACKWARD_FORWARD_COMPATIBILITY
+
+
+using namespace bParse;
+
+
+// ----------------------------------------------------- //
+bDNA::bDNA()
+	:	mPtrLen(0)
+{
+	// --
+}
+
+// ----------------------------------------------------- //
+bDNA::~bDNA()
+{
+	// --
+}
+
+// ----------------------------------------------------- //
+bool bDNA::lessThan(bDNA *file)
+{
+	return ( m_Names.size() < file->m_Names.size());
+}
+
+// ----------------------------------------------------- //
+char *bDNA::getName(int ind)
+{
+	assert(ind <= (int)m_Names.size());
+	return m_Names[ind].m_name;
+}
+
+
+// ----------------------------------------------------- //
+char *bDNA::getType(int ind)
+{
+	assert(ind<=  (int)mTypes.size());
+	return mTypes[ind];
+}
+
+
+// ----------------------------------------------------- //
+short *bDNA::getStruct(int ind)
+{
+	assert(ind <=  (int)mStructs.size());
+	return mStructs[ind];
+}
+
+
+// ----------------------------------------------------- //
+short bDNA::getLength(int ind)
+{
+	assert(ind <=  (int)mTlens.size());
+	return mTlens[ind];
+}
+
+
+// ----------------------------------------------------- //
+int bDNA::getReverseType(short type)
+{
+
+	int* intPtr = mStructReverse.find(type);
+	if (intPtr)
+		return *intPtr;
+
+	return -1;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getReverseType(const char *type)
+{
+
+	btHashString key(type);
+	int* valuePtr = mTypeLookup.find(key);
+	if (valuePtr)
+		return *valuePtr;
+	
+	return -1;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getNumStructs()
+{
+	return (int)mStructs.size();
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagNotEqual(int dna_nr)
+{
+	assert(dna_nr <=	(int)mCMPFlags.size());
+	return mCMPFlags[dna_nr] == FDF_STRUCT_NEQU;
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagEqual(int dna_nr)
+{
+	assert(dna_nr <=	(int)mCMPFlags.size());
+	int flag = mCMPFlags[dna_nr];
+	return  flag == FDF_STRUCT_EQU;
+}
+
+// ----------------------------------------------------- //
+bool bDNA::flagNone(int dna_nr)
+{
+	assert(dna_nr <=	(int)mCMPFlags.size());
+	return mCMPFlags[dna_nr] == FDF_NONE;
+}
+
+// ----------------------------------------------------- //
+int bDNA::getPointerSize()
+{
+	return mPtrLen;
+}
+
+// ----------------------------------------------------- //
+void bDNA::initRecurseCmpFlags(int iter)
+{
+	// iter is FDF_STRUCT_NEQU
+
+	short *oldStrc = mStructs[iter];
+	short type = oldStrc[0];
+
+	for (int i=0; i<(int)mStructs.size(); i++)
+	{
+		if (i != iter && mCMPFlags[i] == FDF_STRUCT_EQU )
+		{
+			short *curStruct = mStructs[i];
+			int eleLen = curStruct[1];
+			curStruct+=2;
+
+			for (int j=0; j<eleLen; j++, curStruct+=2)
+			{
+				if (curStruct[0] == type)
+				{
+					//char *name = m_Names[curStruct[1]].m_name;
+					//if (name[0] != '*')
+					if (m_Names[curStruct[1]].m_isPointer)
+					{
+						mCMPFlags[i] = FDF_STRUCT_NEQU;
+						initRecurseCmpFlags(i);
+					}
+				}
+			}
+		}
+	}
+}
+
+// ----------------------------------------------------- //
+void bDNA::initCmpFlags(bDNA *memDNA)
+{
+
+    // compare the file to memory
+	// this ptr should be the file data
+
+
+	assert(!m_Names.size() == 0 && "SDNA empty!");
+	mCMPFlags.resize(mStructs.size(), FDF_NONE);
+
+
+
+	int i;
+	for ( i=0; i<(int)mStructs.size(); i++)
+	{
+		short *oldStruct = mStructs[i];
+
+		int oldLookup = getReverseType(oldStruct[0]);
+		if (oldLookup == -1)
+		{
+			mCMPFlags[i] = FDF_NONE;
+			continue;
+		}
+		//char* typeName = mTypes[oldStruct[0]];
+
+//#define SLOW_FORWARD_COMPATIBLE 1
+#ifdef SLOW_FORWARD_COMPATIBLE
+		char* typeName = mTypes[oldLookup];
+		int newLookup = memDNA->getReverseType(typeName);
+		if (newLookup == -1)
+		{
+			mCMPFlags[i] = FDF_NONE;
+			continue;
+		}
+		short *curStruct = memDNA->mStructs[newLookup];
+#else
+		// memory for file
+
+		if (oldLookup < memDNA->mStructs.size())
+		{
+			short *curStruct = memDNA->mStructs[oldLookup];
+#endif	
+	
+		
+
+			// rebuild...
+			mCMPFlags[i] = FDF_STRUCT_NEQU;
+
+#ifndef TEST_BACKWARD_FORWARD_COMPATIBILITY
+
+			if (curStruct[1] == oldStruct[1])
+			{
+				// type len same ...
+				if (mTlens[oldStruct[0]] == memDNA->mTlens[curStruct[0]])
+				{
+					bool isSame = true;
+					int elementLength = oldStruct[1];
+
+
+					curStruct+=2;
+					oldStruct+=2;
+
+
+					for (int j=0; j<elementLength; j++, curStruct+=2, oldStruct+=2)
+					{
+						// type the same
+						//const char* typeFileDNA = mTypes[oldStruct[0]];
+						//const char* typeMemDNA = mTypes[curStruct[0]];
+						if (strcmp(mTypes[oldStruct[0]], memDNA->mTypes[curStruct[0]])!=0)
+						{
+							isSame=false;
+							break;
+						}
+
+						// name the same
+						if (strcmp(m_Names[oldStruct[1]].m_name, memDNA->m_Names[curStruct[1]].m_name)!=0)
+						{
+							isSame=false;
+							break;
+						}
+					}
+					// flag valid ==
+					if (isSame)
+						mCMPFlags[i] = FDF_STRUCT_EQU;
+				}
+			}
+#endif
+		}
+	}
+
+
+
+
+
+	// recurse in
+	for ( i=0; i<(int)mStructs.size(); i++)
+	{
+		if (mCMPFlags[i] == FDF_STRUCT_NEQU)
+			initRecurseCmpFlags(i);
+	}
+}
+
+
+
+
+static int name_is_array(char* name, int* dim1, int* dim2) {
+	int len = strlen(name);
+	/*fprintf(stderr,"[%s]",name);*/
+	/*if (len >= 1) {
+	if (name[len-1] != ']')
+	return 1;
+	}
+	return 0;*/
+	char *bp;
+	int num;
+	if (dim1) {
+		*dim1 = 1;
+	}
+	if (dim2) {
+		*dim2 = 1;
+	}
+	bp = strchr(name, '[');
+	if (!bp) {
+		return 0;
+	}
+	num = 0;
+	while (++bp < name+len-1) {
+		const char c = *bp;
+		if (c == ']') {
+			break;
+		}
+		if (c <= '9' && c >= '0') {
+			num *= 10;
+			num += (c - '0');
+		} else {
+			printf("array parse error.\n");
+			return 0;
+		}
+	}
+	if (dim2) {
+		*dim2 = num;
+	}
+
+	/* find second dim, if any. */
+	bp = strchr(bp, '[');
+	if (!bp) {
+		return 1; /* at least we got the first dim. */
+	}
+	num = 0;
+	while (++bp < name+len-1) {
+		const char c = *bp;
+		if (c == ']') {
+			break;
+		}
+		if (c <= '9' && c >= '0') {
+			num *= 10;
+			num += (c - '0');
+		} else {
+			printf("array2 parse error.\n");
+			return 1;
+		}
+	}
+	if (dim1) {
+		if (dim2) {
+			*dim1 = *dim2;
+			*dim2 = num;
+		} else {
+			*dim1 = num;
+		}
+	}
+
+	return 1;
+}
+
+
+// ----------------------------------------------------- //
+void bDNA::init(char *data, int len, bool swap)
+{
+	//printf("swap = %d\n",swap); ***ALEX***
+	int *intPtr=0;short *shtPtr=0;
+	char *cp = 0;int dataLen =0;long nr=0;
+	intPtr = (int*)data;
+
+	/*
+		SDNA (4 bytes) (magic number)
+		NAME (4 bytes)
+		<nr> (4 bytes) amount of names (int)
+		<string>
+		<string>
+	*/
+
+	if (strncmp(data, "SDNA", 4)==0)
+	{
+		// skip ++ NAME
+		intPtr++; intPtr++;
+	}
+
+
+
+	// Parse names
+	if (swap) dataLen = ChunkUtils::swapInt(*intPtr);
+	else      dataLen = *intPtr;
+	intPtr++;
+
+	cp = (char*)intPtr;
+	int i;
+	for ( i=0; i<dataLen; i++)
+	{
+		bNameInfo info;
+		info.m_name = cp;
+		info.m_isPointer = (info.m_name[0] == '*') || (info.m_name[1] == '*');
+		name_is_array(info.m_name,&info.m_dim0,&info.m_dim1);
+		m_Names.push_back(info);
+		while (*cp)cp++;
+		cp++;
+	}
+
+	
+	{
+		nr= (long)cp;
+	//long mask=3;
+		nr= ((nr+3)&~3)-nr;
+		while (nr--)
+		{
+			cp++;
+		}
+	}
+
+
+	/*
+		TYPE (4 bytes)
+		<nr> amount of types (int)
+		<string>
+		<string>
+	*/
+
+	intPtr = (int*)cp;
+	assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+	if (swap) dataLen = ChunkUtils::swapInt(*intPtr);
+	else      dataLen = *intPtr;
+	intPtr++;
+
+	cp = (char*)intPtr;
+	for ( i=0; i<dataLen; i++)
+	{
+		mTypes.push_back(cp);
+		while (*cp)cp++;
+		cp++;
+	}
+
+{
+		nr= (long)cp;
+	//	long mask=3;
+		nr= ((nr+3)&~3)-nr;
+		while (nr--)
+		{
+			cp++;
+		}
+	}
+
+
+	/*
+		TLEN (4 bytes)
+		<len> (short) the lengths of types
+		<len>
+	*/
+
+	// Parse type lens
+	intPtr = (int*)cp;
+	assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+	dataLen = (int)mTypes.size();
+
+	shtPtr = (short*)intPtr;
+	for ( i=0; i<dataLen; i++, shtPtr++)
+	{
+		if (swap)
+			shtPtr[0] = ChunkUtils::swapShort(shtPtr[0]);
+		mTlens.push_back(shtPtr[0]);
+	}
+
+	if (dataLen & 1) shtPtr++;
+
+	/*
+		STRC (4 bytes)
+		<nr> amount of structs (int)
+		<typenr>
+		<nr_of_elems>
+		<typenr>
+		<namenr>
+		<typenr>
+		<namenr>
+	*/
+
+	intPtr = (int*)shtPtr;
+	cp = (char*)intPtr;
+	assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+
+	if (swap) dataLen = ChunkUtils::swapInt(*intPtr);
+	else      dataLen = *intPtr;
+	intPtr++;
+
+
+	shtPtr = (short*)intPtr;
+	for ( i=0; i<dataLen; i++)
+	{
+		mStructs.push_back (shtPtr);
+		if (swap)
+		{
+			shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+			shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+
+			int len = shtPtr[1];
+			shtPtr+= 2;
+
+			for (int a=0; a<len; a++, shtPtr+=2)
+			{
+				shtPtr[0]= ChunkUtils::swapShort(shtPtr[0]);
+				shtPtr[1]= ChunkUtils::swapShort(shtPtr[1]);
+			}
+		}
+		else
+			shtPtr+= (2*shtPtr[1])+2;
+	}
+
+
+	// build reverse lookups
+	for ( i=0; i<(int)mStructs.size(); i++)
+	{
+		short *strc = mStructs.at(i);
+		if (!mPtrLen && strcmp(mTypes[strc[0]],"ListBase")==0)
+		{
+			mPtrLen = mTlens[strc[0]]/2;
+		}
+
+		mStructReverse.insert(strc[0], i);
+		mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
+	}
+}
+
+
+// ----------------------------------------------------- //
+int bDNA::getArraySize(char* string)
+{
+	int ret = 1;
+	int len = strlen(string);
+
+	
+	char* next = 0;
+	for (int i=0; i<len; i++)
+	{
+		char c = string[i];
+
+		if (c == '[')
+			next = &string[i+1];
+		else if (c==']')
+			if (next)
+				ret *= atoi(next);
+	}
+
+//	print (string << ' ' << ret);
+	return ret;
+}
+
+
+void bDNA::dumpTypeDefinitions()
+{
+	int i;
+
+	int numTypes = mTypes.size();
+	
+	for (i=0;i<numTypes;i++)
+	{
+
+	}
+
+	for ( i=0; i<(int)mStructs.size(); i++)
+	{
+		int totalBytes=0;
+		short *oldStruct = mStructs[i];
+
+		int oldLookup = getReverseType(oldStruct[0]);
+		if (oldLookup == -1)
+		{
+			mCMPFlags[i] = FDF_NONE;
+			continue;
+		}
+
+		short* newStruct = mStructs[oldLookup];
+		char* typeName = mTypes[newStruct[0]];
+		printf("%3d: %s ",i,typeName);
+		
+		//char *name = mNames[oldStruct[1]];
+		int len = oldStruct[1];
+		printf(" (%d fields) ",len);
+		oldStruct+=2;
+
+		printf("{");
+		int j;
+		for (j=0; j<len; ++j,oldStruct+=2) {
+			const char* name = m_Names[oldStruct[1]].m_name;
+			printf("%s %s",	mTypes[oldStruct[0]],name);
+			int elemNumBytes= 0;
+			int arrayDimensions = getArraySizeNew(oldStruct[1]);
+
+			if (m_Names[oldStruct[1]].m_isPointer)
+			{
+				elemNumBytes = VOID_IS_8 ? 8 : 4;
+			} else
+			{
+				elemNumBytes = getLength(oldStruct[0]);
+			}
+			printf(" /* %d bytes */",elemNumBytes*arrayDimensions);
+			
+			if (j == len-1) {
+				printf(";}");
+			} else {
+				printf("; ");
+			}
+			totalBytes+=elemNumBytes*arrayDimensions;
+		}
+		printf("\ntotalBytes=%d\n\n",totalBytes);
+
+	}
+	
+
+
+#if 0
+	/* dump out display of types and their sizes */
+	for (i=0; i<bf->types_count; ++i) {
+		/* if (!bf->types[i].is_struct)*/
+		{
+			printf("%3d: sizeof(%s%s)=%d",
+				i,
+				bf->types[i].is_struct ? "struct " : "atomic ",
+				bf->types[i].name, bf->types[i].size);
+			if (bf->types[i].is_struct) {
+				int j;
+				printf(", %d fields: { ", bf->types[i].fieldtypes_count);
+				for (j=0; j<bf->types[i].fieldtypes_count; ++j) {
+					printf("%s %s",
+						bf->types[bf->types[i].fieldtypes[j]].name,
+						bf->names[bf->types[i].fieldnames[j]]);
+					if (j == bf->types[i].fieldtypes_count-1) {
+						printf(";}");
+					} else {
+						printf("; ");
+					}
+				}
+			}
+			printf("\n\n");
+
+		}
+	}
+#endif
+
+}
+
+
+
+
+//eof
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDNA.h b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDNA.h
new file mode 100644
index 0000000..691080b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDNA.h
@@ -0,0 +1,110 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef __BDNA_H__
+#define __BDNA_H__
+
+
+#include "bCommon.h"
+
+namespace bParse {
+
+	struct	bNameInfo
+	{
+		char*	m_name;
+		bool	m_isPointer;
+		int		m_dim0;
+		int		m_dim1;
+	};
+
+	class bDNA
+	{
+	public:
+		bDNA();
+		~bDNA();
+
+		void init(char *data, int len, bool swap=false);
+
+		int getArraySize(char* str);
+		int getArraySizeNew(short name)
+		{
+			const bNameInfo& nameInfo = m_Names[name];
+			return nameInfo.m_dim0*nameInfo.m_dim1;
+		}
+		int getElementSize(short type, short name)
+		{
+			const bNameInfo& nameInfo = m_Names[name];
+			int size = nameInfo.m_isPointer ? mPtrLen*nameInfo.m_dim0*nameInfo.m_dim1 : mTlens[type]*nameInfo.m_dim0*nameInfo.m_dim1;
+			return size;
+		}
+
+		int	getNumNames() const
+		{
+			return m_Names.size();
+		}
+
+		char *getName(int ind);
+		char *getType(int ind);
+		short *getStruct(int ind);
+		short getLength(int ind);
+		int getReverseType(short type);
+		int getReverseType(const char *type);
+
+
+		int getNumStructs();
+
+		//
+		bool lessThan(bDNA* other);
+
+		void initCmpFlags(bDNA *memDNA);
+		bool flagNotEqual(int dna_nr);
+		bool flagEqual(int dna_nr);
+		bool flagNone(int dna_nr);
+
+
+		int getPointerSize();
+
+		void	dumpTypeDefinitions();
+
+	
+	private:
+		enum FileDNAFlags
+		{
+			FDF_NONE=0,
+			FDF_STRUCT_NEQU,
+			FDF_STRUCT_EQU
+		};
+
+		void initRecurseCmpFlags(int i);
+
+		btAlignedObjectArray<int>			mCMPFlags;
+
+		btAlignedObjectArray<bNameInfo>			m_Names;
+		btAlignedObjectArray<char*>			mTypes;
+		btAlignedObjectArray<short*>			mStructs;
+		btAlignedObjectArray<short>			mTlens;
+		btHashMap<btHashInt, int>			mStructReverse;
+		btHashMap<btHashString,int>	mTypeLookup;
+
+		int							mPtrLen;
+		
+
+
+
+	};
+}
+
+
+#endif//__BDNA_H__
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDefines.h b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDefines.h
new file mode 100644
index 0000000..238df7d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bDefines.h
@@ -0,0 +1,140 @@
+/* Copyright (C) 2006-2009 Charlie C & Erwin Coumans http://gamekit.googlecode.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty.  In no event will the authors be held liable for any damages
+* arising from the use of this software.
+*
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+*
+* 1. The origin of this software must not be misrepresented; you must not
+*    claim that you wrote the original software. If you use this software
+*    in a product, an acknowledgment in the product documentation would be
+*    appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+*    misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef __B_DEFINES_H__
+#define __B_DEFINES_H__
+
+
+// MISC defines, see BKE_global.h, BKE_utildefines.h
+#define SIZEOFBLENDERHEADER 12
+
+
+// ------------------------------------------------------------
+#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#	define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+#	define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+
+// ------------------------------------------------------------
+#if defined(__sgi) || defined(__sparc) || defined(__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#	define MAKE_ID2(c, d) ( (c)<<8 | (d) )
+#	define MOST_SIG_BYTE   0
+#	define BBIG_ENDIAN
+#else
+#	define MAKE_ID2(c, d) ( (d)<<8 | (c) )
+#	define MOST_SIG_BYTE  1
+#	define BLITTLE_ENDIAN
+#endif
+
+// ------------------------------------------------------------
+#define ID_SCE		MAKE_ID2('S', 'C')
+#define ID_LI		MAKE_ID2('L', 'I')
+#define ID_OB		MAKE_ID2('O', 'B')
+#define ID_ME		MAKE_ID2('M', 'E')
+#define ID_CU		MAKE_ID2('C', 'U')
+#define ID_MB		MAKE_ID2('M', 'B')
+#define ID_MA		MAKE_ID2('M', 'A')
+#define ID_TE		MAKE_ID2('T', 'E')
+#define ID_IM		MAKE_ID2('I', 'M')
+#define ID_IK		MAKE_ID2('I', 'K')
+#define ID_WV		MAKE_ID2('W', 'V')
+#define ID_LT		MAKE_ID2('L', 'T')
+#define ID_SE		MAKE_ID2('S', 'E')
+#define ID_LF		MAKE_ID2('L', 'F')
+#define ID_LA		MAKE_ID2('L', 'A')
+#define ID_CA		MAKE_ID2('C', 'A')
+#define ID_IP		MAKE_ID2('I', 'P')
+#define ID_KE		MAKE_ID2('K', 'E')
+#define ID_WO		MAKE_ID2('W', 'O')
+#define ID_SCR		MAKE_ID2('S', 'R')
+#define ID_VF		MAKE_ID2('V', 'F')
+#define ID_TXT		MAKE_ID2('T', 'X')
+#define ID_SO		MAKE_ID2('S', 'O')
+#define ID_SAMPLE	MAKE_ID2('S', 'A')
+#define ID_GR		MAKE_ID2('G', 'R')
+#define ID_ID		MAKE_ID2('I', 'D')
+#define ID_AR		MAKE_ID2('A', 'R')
+#define ID_AC		MAKE_ID2('A', 'C')
+#define ID_SCRIPT	MAKE_ID2('P', 'Y')
+#define ID_FLUIDSIM	MAKE_ID2('F', 'S')
+#define ID_NT		MAKE_ID2('N', 'T')
+#define ID_BR		MAKE_ID2('B', 'R')
+
+
+#define ID_SEQ		MAKE_ID2('S', 'Q')
+#define ID_CO		MAKE_ID2('C', 'O')
+#define ID_PO		MAKE_ID2('A', 'C')
+#define ID_NLA		MAKE_ID2('N', 'L')
+
+#define ID_VS		MAKE_ID2('V', 'S')
+#define ID_VN		MAKE_ID2('V', 'N')
+
+
+// ------------------------------------------------------------
+#define FORM MAKE_ID('F','O','R','M')
+#define DDG1 MAKE_ID('3','D','G','1')
+#define DDG2 MAKE_ID('3','D','G','2')
+#define DDG3 MAKE_ID('3','D','G','3')
+#define DDG4 MAKE_ID('3','D','G','4')
+#define GOUR MAKE_ID('G','O','U','R')
+#define BLEN MAKE_ID('B','L','E','N')
+#define DER_ MAKE_ID('D','E','R','_')
+#define V100 MAKE_ID('V','1','0','0')
+#define DATA MAKE_ID('D','A','T','A')
+#define GLOB MAKE_ID('G','L','O','B')
+#define IMAG MAKE_ID('I','M','A','G')
+#define TEST MAKE_ID('T','E','S','T')
+#define USER MAKE_ID('U','S','E','R')
+
+
+// ------------------------------------------------------------
+#define DNA1 MAKE_ID('D','N','A','1')
+#define REND MAKE_ID('R','E','N','D')
+#define ENDB MAKE_ID('E','N','D','B')
+#define NAME MAKE_ID('N','A','M','E')
+#define SDNA MAKE_ID('S','D','N','A')
+#define TYPE MAKE_ID('T','Y','P','E')
+#define TLEN MAKE_ID('T','L','E','N')
+#define STRC MAKE_ID('S','T','R','C')
+
+
+// ------------------------------------------------------------
+#define SWITCH_INT(a) { \
+    char s_i, *p_i; \
+    p_i= (char *)&(a); \
+    s_i=p_i[0]; p_i[0]=p_i[3]; p_i[3]=s_i; \
+    s_i=p_i[1]; p_i[1]=p_i[2]; p_i[2]=s_i; }
+
+// ------------------------------------------------------------
+#define SWITCH_SHORT(a)	{ \
+    char s_i, *p_i; \
+	p_i= (char *)&(a); \
+	s_i=p_i[0]; p_i[0]=p_i[1]; p_i[1]=s_i; }
+
+// ------------------------------------------------------------
+#define SWITCH_LONGINT(a) { \
+    char s_i, *p_i; \
+    p_i= (char *)&(a);  \
+    s_i=p_i[0]; p_i[0]=p_i[7]; p_i[7]=s_i; \
+    s_i=p_i[1]; p_i[1]=p_i[6]; p_i[6]=s_i; \
+    s_i=p_i[2]; p_i[2]=p_i[5]; p_i[5]=s_i; \
+    s_i=p_i[3]; p_i[3]=p_i[4]; p_i[4]=s_i; }
+
+#endif//__B_DEFINES_H__
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bFile.cpp b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bFile.cpp
new file mode 100644
index 0000000..e886752
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bFile.cpp
@@ -0,0 +1,1354 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "bFile.h"
+#include "bCommon.h"
+#include "bChunk.h"
+#include "bDNA.h"
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "bDefines.h"
+#include "LinearMath/btSerializer.h"
+
+#define SIZEOFBLENDERHEADER 12
+#define MAX_ARRAY_LENGTH 512
+using namespace bParse;
+
+
+
+int numallocs = 0;
+
+// ----------------------------------------------------- //
+bFile::bFile(const char *filename, const char headerString[7])
+	:	mOwnsBuffer(true),
+		mFileBuffer(0),
+		mFileLen(0),
+		mVersion(0),
+		mDataStart(0),
+		mFileDNA(0),
+		mMemoryDNA(0),
+		mFlags(FD_INVALID)
+{
+	for (int i=0;i<7;i++)
+	{
+		m_headerString[i] = headerString[i];
+	}
+
+	FILE *fp = fopen(filename, "rb");
+	if (fp)
+	{
+		fseek(fp, 0L, SEEK_END);
+		mFileLen = ftell(fp);
+		fseek(fp, 0L, SEEK_SET);
+
+		mFileBuffer = (char*)malloc(mFileLen+1);
+		fread(mFileBuffer, mFileLen, 1, fp);
+
+		fclose(fp);
+
+		//
+		parseHeader();
+		
+	}
+}
+
+// ----------------------------------------------------- //
+bFile::bFile( char *memoryBuffer, int len, const char headerString[7])
+:	mOwnsBuffer(false),
+	mFileBuffer(0),
+		mFileLen(0),
+		mVersion(0),
+		mDataStart(0),
+		mFileDNA(0),
+		mMemoryDNA(0),
+		mFlags(FD_INVALID)
+{
+	for (int i=0;i<7;i++)
+	{
+		m_headerString[i] = headerString[i];
+	}
+	mFileBuffer = memoryBuffer;
+	mFileLen = len;
+	
+	parseHeader();
+	
+}
+
+
+// ----------------------------------------------------- //
+bFile::~bFile()
+{
+	if (mOwnsBuffer && mFileBuffer)
+	{
+		free(mFileBuffer);
+		mFileBuffer = 0;
+	}
+
+
+	delete mMemoryDNA;
+	delete mFileDNA;
+}
+
+
+
+
+
+// ----------------------------------------------------- //
+void bFile::parseHeader()
+{
+	if (!mFileLen || !mFileBuffer)
+		return;
+
+	char *blenderBuf = mFileBuffer;
+	char header[SIZEOFBLENDERHEADER+1] ;
+	memcpy(header, blenderBuf, SIZEOFBLENDERHEADER);
+	header[SIZEOFBLENDERHEADER]='\0';
+
+	if (strncmp(header, m_headerString, 6)!=0)
+	{
+		memcpy(header, m_headerString, SIZEOFBLENDERHEADER);
+		printf ("Invalid %s file...",header);
+		return;
+	}
+
+	if (header[6] == 'd')
+	{
+		mFlags |= FD_DOUBLE_PRECISION;
+	}
+
+	char *ver = header+9;
+	mVersion = atoi(ver);
+	if (mVersion <= 241)
+		printf ("Warning, %d not fully tested : <= 242\n", mVersion);
+
+
+	int littleEndian= 1;
+	littleEndian= ((char*)&littleEndian)[0];
+
+	// swap ptr sizes...
+	if (header[7]=='-')
+	{
+		mFlags |= FD_FILE_64;
+		if (!VOID_IS_8)
+			mFlags |= FD_BITS_VARIES;
+	}
+	else if (VOID_IS_8) mFlags |= FD_BITS_VARIES;
+
+	// swap endian...
+	if (header[8]=='V')
+	{
+		if (littleEndian ==1)
+			mFlags |= FD_ENDIAN_SWAP;
+	}
+	else
+		if (littleEndian==0)
+			mFlags |= FD_ENDIAN_SWAP;
+
+/* ***ALEX***
+	printf ("%s\n",header);
+	printf ("\nsizeof(void*) == %d\n",int(sizeof(void*)));
+	const char* endStr = ((mFlags & FD_ENDIAN_SWAP)!=0) ? "yes" : "no";
+	printf ("Swapping endian? %s\n",endStr);
+	const char* bitStr = (mFlags &FD_FILE_64)!=0 ? "64 bit" : "32bit";
+	printf ("File format is %s\n",bitStr);
+	const char* varStr = (mFlags & FD_BITS_VARIES)!=0 ? "yes" : "no";
+	printf ("Varing pointer sizes? %s\n",varStr);
+*/
+
+	mFlags |= FD_OK;
+}
+
+// ----------------------------------------------------- //
+bool bFile::ok()
+{
+	return (mFlags &FD_OK)!=0;
+}
+
+// ----------------------------------------------------- //
+void bFile::parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLength)
+{
+	if ( (mFlags &FD_OK) ==0)
+		return;
+
+	char *blenderData = mFileBuffer;
+	bChunkInd dna;
+	dna.oldPtr = 0;
+
+	char *tempBuffer = blenderData;
+	for (int i=0; i<mFileLen; i++)
+	{
+		// looking for the data's starting position
+		// and the start of SDNA decls
+
+		if (!mDataStart && strncmp(tempBuffer, "REND", 4)==0)
+			mDataStart = i;
+
+		if (strncmp(tempBuffer, "DNA1", 4)==0)
+		{
+			// read the DNA1 block and extract SDNA
+			if (getNextBlock(&dna, tempBuffer, mFlags) > 0)
+			{
+				if (strncmp((tempBuffer + ChunkUtils::getOffset(mFlags)), "SDNANAME", 8) ==0) 
+					dna.oldPtr = (tempBuffer + ChunkUtils::getOffset(mFlags));
+				else dna.oldPtr = 0;
+			}
+			else dna.oldPtr = 0;
+		} 
+		// Some Bullet files are missing the DNA1 block
+		// In Blender it's DNA1 + ChunkUtils::getOffset() + SDNA + NAME
+		// In Bullet tests its SDNA + NAME
+		else if (strncmp(tempBuffer, "SDNANAME", 8) ==0)
+		{
+			dna.oldPtr = blenderData + i;
+			dna.len = mFileLen-i;
+
+			// Also no REND block, so exit now.  
+			if (mVersion==276) break;
+		}
+
+        if (mDataStart && dna.oldPtr) break;
+		tempBuffer++;
+	}
+	if (!dna.oldPtr || !dna.len)
+	{
+		printf("Failed to find DNA1+SDNA pair\n");
+		mFlags &= ~FD_OK;
+		return;
+	}
+
+
+	mFileDNA = new bDNA();
+	mFileDNA->init((char*)dna.oldPtr, dna.len, (mFlags & FD_ENDIAN_SWAP)!=0);
+
+	if (mVersion==276)
+	{
+		int i;
+		for (i=0;i<mFileDNA->getNumNames();i++)
+		{
+			if (strcmp(mFileDNA->getName(i),"int")==0)
+			{
+				mFlags |= FD_BROKEN_DNA;
+			}
+		}
+		if ((mFlags&FD_BROKEN_DNA)!=0)
+		{
+			printf("warning: fixing some broken DNA version\n");
+		}
+	}
+
+
+
+	if (verboseDumpAllTypes)
+	{
+		mFileDNA->dumpTypeDefinitions();
+	}
+
+	mMemoryDNA = new bDNA();
+	int littleEndian= 1;
+	littleEndian= ((char*)&littleEndian)[0];
+			
+	mMemoryDNA->init(memDna,memDnaLength,littleEndian==0);
+
+	
+
+
+	///@todo we need a better version check, add version/sub version info from FileGlobal into memory DNA/header files
+	if (mMemoryDNA->getNumNames() != mFileDNA->getNumNames())
+	{
+		mFlags |= FD_VERSION_VARIES;
+		printf ("Warning, file DNA is different than built in, performance is reduced. Best to re-export file with a matching version/platform");
+	}
+
+	// as long as it kept up to date it will be ok!!
+	if (mMemoryDNA->lessThan(mFileDNA))
+	{
+		printf ("Warning, file DNA is newer than built in.");
+	}
+
+	mFileDNA->initCmpFlags(mMemoryDNA);
+	
+	parseData();
+	
+	resolvePointers(verboseDumpAllTypes);//verboseDumpAllBlocks);
+
+	updateOldPointers();
+
+	// printf("numAllocs = %d\n",numallocs);  ***ALEX***
+}
+
+
+
+// ----------------------------------------------------- //
+void bFile::swap(char *head, bChunkInd& dataChunk)
+{
+	char *data = head;
+	short *strc = mFileDNA->getStruct(dataChunk.dna_nr);
+	int len = mFileDNA->getLength(strc[0]);
+
+	for (int i=0; i<dataChunk.nr; i++)
+	{
+		swapStruct(dataChunk.dna_nr, data);
+		data+=len;
+	}
+}
+
+
+
+// ----------------------------------------------------- //
+char* bFile::readStruct(char *head, bChunkInd&  dataChunk)
+{
+	if (mFlags & FD_ENDIAN_SWAP)
+		swap(head, dataChunk);
+
+	
+
+	if (!mFileDNA->flagEqual(dataChunk.dna_nr))
+	{
+		// Ouch! need to rebuild the struct
+		short *oldStruct,*curStruct;
+		char *oldType, *newType;
+		int oldLen, curLen, reverseOld;
+
+
+		oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+		oldType = mFileDNA->getType(oldStruct[0]);
+		oldLen = mFileDNA->getLength(oldStruct[0]);
+
+		if ((mFlags&FD_BROKEN_DNA)!=0)
+		{
+			if ((strcmp(oldType,"btQuantizedBvhNodeData")==0)&&oldLen==20)
+			{
+				return 0;
+			}
+			if ((strcmp(oldType,"btShortIntIndexData")==0))
+			{
+				int allocLen = 2;
+	    		char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
+				memset(dataAlloc, 0, (dataChunk.nr*allocLen)+1);
+				short* dest = (short*) dataAlloc;
+				const short* src = (short*) head;
+				for (int i=0;i<dataChunk.nr;i++)
+				{
+					dest[i] = src[i];
+					if (mFlags &FD_ENDIAN_SWAP)
+					{
+						SWITCH_SHORT(dest[i]);
+					}
+				}
+				addDataBlock(dataAlloc);
+				return dataAlloc;
+			}
+		}
+
+
+
+		///don't try to convert Link block data, just memcpy it. Other data can be converted.
+		if (strcmp("Link",oldType)!=0)
+		{
+			reverseOld = mMemoryDNA->getReverseType(oldType);
+
+			if ((reverseOld!=-1))
+			{
+				// make sure it's here
+				//assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+
+				//
+				curStruct = mMemoryDNA->getStruct(reverseOld);
+				newType = mMemoryDNA->getType(curStruct[0]);
+				curLen = mMemoryDNA->getLength(curStruct[0]);
+
+
+
+				// make sure it's the same
+				assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
+
+
+				numallocs++;
+				// numBlocks * length
+
+                int allocLen = (curLen);
+    			char *dataAlloc = new char[(dataChunk.nr*allocLen)+1];
+				memset(dataAlloc, 0, (dataChunk.nr*allocLen));
+
+				// track allocated
+				addDataBlock(dataAlloc);
+
+				char *cur = dataAlloc;
+				char *old = head;
+				for (int block=0; block<dataChunk.nr; block++)
+				{
+					bool fixupPointers = true;
+					parseStruct(cur, old, dataChunk.dna_nr, reverseOld, fixupPointers);
+					mLibPointers.insert(old,(bStructHandle*)cur);
+
+					cur += curLen;
+					old += oldLen;
+				}
+				return dataAlloc;
+			}
+		} else
+		{
+			//printf("Link found\n");
+		}
+	} else
+	{
+//#define DEBUG_EQUAL_STRUCTS
+#ifdef DEBUG_EQUAL_STRUCTS
+		short *oldStruct;
+		char *oldType;
+		oldStruct = mFileDNA->getStruct(dataChunk.dna_nr);
+		oldType = mFileDNA->getType(oldStruct[0]);
+		printf("%s equal structure, just memcpy\n",oldType);
+#endif //
+	}
+
+
+	char *dataAlloc = new char[(dataChunk.len)+1];
+	memset(dataAlloc, 0, dataChunk.len+1);
+
+
+	// track allocated
+	addDataBlock(dataAlloc);
+
+	memcpy(dataAlloc, head, dataChunk.len);
+	return dataAlloc;
+
+}
+
+
+// ----------------------------------------------------- //
+void bFile::parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers)
+{
+	if (old_dna == -1) return;
+	if (new_dna == -1) return;
+
+	//disable this, because we need to fixup pointers/ListBase
+	if (0)//mFileDNA->flagEqual(old_dna))
+	{
+		short *strc = mFileDNA->getStruct(old_dna);
+		int len = mFileDNA->getLength(strc[0]);
+
+		memcpy(strcPtr, dtPtr, len);
+		return;
+	}
+
+	// Ok, now build the struct
+	char *memType, *memName, *cpc, *cpo;
+	short *fileStruct, *filePtrOld, *memoryStruct, *firstStruct;
+	int elementLength, size, revType, old_nr, new_nr, fpLen;
+	short firstStructType;
+
+
+	// File to memory lookup
+	memoryStruct = mMemoryDNA->getStruct(new_dna);
+	fileStruct = mFileDNA->getStruct(old_dna);
+	firstStruct = fileStruct;
+
+
+	filePtrOld = fileStruct;
+	firstStructType = mMemoryDNA->getStruct(0)[0];
+
+	// Get number of elements
+	elementLength = memoryStruct[1];
+	memoryStruct+=2;
+
+	cpc = strcPtr; cpo = 0;
+	for (int ele=0; ele<elementLength; ele++, memoryStruct+=2)
+	{
+		memType = mMemoryDNA->getType(memoryStruct[0]);
+		memName = mMemoryDNA->getName(memoryStruct[1]);
+
+
+		size = mMemoryDNA->getElementSize(memoryStruct[0], memoryStruct[1]);
+		revType = mMemoryDNA->getReverseType(memoryStruct[0]);
+
+		if (revType != -1 && memoryStruct[0]>=firstStructType && memName[0] != '*')
+		{
+			cpo = getFileElement(firstStruct, memName, memType, dtPtr, &filePtrOld);
+			if (cpo)
+			{
+				int arrayLen = mFileDNA->getArraySizeNew(filePtrOld[1]);
+				old_nr = mFileDNA->getReverseType(memType);
+				new_nr = revType;
+				fpLen = mFileDNA->getElementSize(filePtrOld[0], filePtrOld[1]);
+				if (arrayLen==1)
+				{
+					parseStruct(cpc, cpo, old_nr, new_nr,fixupPointers);
+				} else
+				{
+					char* tmpCpc = cpc;
+					char* tmpCpo = cpo;
+
+					for (int i=0;i<arrayLen;i++)
+					{
+						parseStruct(tmpCpc, tmpCpo, old_nr, new_nr,fixupPointers);
+						tmpCpc += size/arrayLen;
+						tmpCpo += fpLen/arrayLen;
+					}
+				}
+				cpc+=size;
+				cpo+=fpLen;
+			}
+			else
+				cpc+=size;
+		}
+		else
+		{
+			getMatchingFileDNA(fileStruct, memName, memType, cpc, dtPtr,fixupPointers);
+			cpc+=size;
+		}
+
+	}
+}
+
+
+// ----------------------------------------------------- //
+static void getElement(int arrayLen, const char *cur, const char *old, char *oldPtr, char *curData)
+{
+#define getEle(value, current, type, cast, size, ptr)\
+	if (strcmp(current, type)==0)\
+	{\
+		value = (*(cast*)ptr);\
+		ptr += size;\
+	}
+
+#define setEle(value, current, type, cast, size, ptr)\
+	if (strcmp(current, type)==0)\
+	{\
+		(*(cast*)ptr) = (cast)value;\
+		ptr += size;\
+	}
+	double value = 0.0;
+
+	for (int i=0; i<arrayLen; i++)
+	{
+		getEle(value, old, "char",   char,   sizeof(char),   oldPtr);
+		setEle(value, cur, "char",   char,   sizeof(char),   curData);
+		getEle(value, old, "short",  short,  sizeof(short),  oldPtr);
+		setEle(value, cur, "short",  short,  sizeof(short),  curData);
+		getEle(value, old, "ushort",  unsigned short,  sizeof(unsigned short),  oldPtr);
+		setEle(value, cur, "ushort",  unsigned short,  sizeof(unsigned short),  curData);
+		getEle(value, old, "int",    int,    sizeof(int),    oldPtr);
+		setEle(value, cur, "int",    int,    sizeof(int),    curData);
+		getEle(value, old, "long",   int,    sizeof(int),    oldPtr);
+		setEle(value, cur, "long",   int,    sizeof(int),    curData);
+		getEle(value, old, "float",  float,  sizeof(float),  oldPtr);
+		setEle(value, cur, "float",  float,  sizeof(float),  curData);
+		getEle(value, old, "double", double, sizeof(double), oldPtr);
+		setEle(value, cur, "double", double, sizeof(double), curData);
+	}
+}
+
+
+// ----------------------------------------------------- //
+void bFile::swapData(char *data, short type, int arraySize)
+{
+	if (mFlags &FD_ENDIAN_SWAP)
+	{
+		if (type == 2 || type == 3)
+		{
+			short *sp = (short*)data;
+			for (int i=0; i<arraySize; i++)
+			{
+				sp[0] = ChunkUtils::swapShort(sp[0]);
+				sp++;
+			}
+		}
+		if (type>3 && type <8)
+		{
+			char c;
+			char *cp = data;
+			for (int i=0; i<arraySize; i++)
+			{
+				c = cp[0];
+				cp[0] = cp[3];
+				cp[3] = c;
+				c = cp[1];
+				cp[1] = cp[2];
+				cp[2] = c;
+				cp+=4;
+			}
+		}
+	}
+}
+
+
+
+void bFile::safeSwapPtr(char *dst, const char *src)
+{
+	int ptrFile = mFileDNA->getPointerSize();
+	int ptrMem = mMemoryDNA->getPointerSize();
+
+	if (!src && !dst)
+		return;
+
+
+	if (ptrFile == ptrMem)
+	{
+		memcpy(dst, src, ptrMem);
+	}
+	else if (ptrMem==4 && ptrFile==8)
+	{
+		btPointerUid* oldPtr = (btPointerUid*)src;
+		btPointerUid* newPtr = (btPointerUid*)dst;
+
+		if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+		{
+			//Bullet stores the 32bit unique ID in both upper and lower part of 64bit pointers
+			//so it can be used to distinguish between .blend and .bullet
+			newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+		} else
+		{
+			//deal with pointers the Blender .blend style way, see
+			//readfile.c in the Blender source tree
+			long64 longValue = *((long64*)src);
+			//endian swap for 64bit pointer otherwise truncation will fail due to trailing zeros
+			if (mFlags & FD_ENDIAN_SWAP)
+				SWITCH_LONGINT(longValue);
+			*((int*)dst) = (int)(longValue>>3);
+		}
+		
+	}
+	else if (ptrMem==8 && ptrFile==4)
+	{
+		btPointerUid* oldPtr = (btPointerUid*)src;
+		btPointerUid* newPtr = (btPointerUid*)dst;
+		if (oldPtr->m_uniqueIds[0] == oldPtr->m_uniqueIds[1])
+		{
+			newPtr->m_uniqueIds[0] = oldPtr->m_uniqueIds[0];
+			newPtr->m_uniqueIds[1] = 0;
+		} else
+		{
+			*((long64*)dst)= *((int*)src);
+		}
+	}
+	else
+	{
+		printf ("%d %d\n", ptrFile,ptrMem);
+		assert(0 && "Invalid pointer len");
+	}
+
+
+}
+
+
+// ----------------------------------------------------- //
+void bFile::getMatchingFileDNA(short* dna_addr, const char* lookupName,  const char* lookupType, char *strcData, char *data, bool fixupPointers)
+{
+	// find the matching memory dna data
+	// to the file being loaded. Fill the
+	// memory with the file data...
+
+	int len = dna_addr[1];
+	dna_addr+=2;
+
+	for (int i=0; i<len; i++, dna_addr+=2)
+	{
+		const char* type = mFileDNA->getType(dna_addr[0]);
+		const char* name = mFileDNA->getName(dna_addr[1]);
+
+		
+
+		int eleLen = mFileDNA->getElementSize(dna_addr[0], dna_addr[1]);
+
+		if ((mFlags&FD_BROKEN_DNA)!=0)
+		{
+			if ((strcmp(type,"short")==0)&&(strcmp(name,"int")==0))
+			{
+				eleLen = 0;
+			}
+		}
+
+		if (strcmp(lookupName, name)==0)
+		{
+			//int arrayLenold = mFileDNA->getArraySize((char*)name.c_str());
+			int arrayLen = mFileDNA->getArraySizeNew(dna_addr[1]);
+			//assert(arrayLenold == arrayLen);
+			
+			if (name[0] == '*')
+			{
+				// cast pointers
+				int ptrFile = mFileDNA->getPointerSize();
+				int ptrMem = mMemoryDNA->getPointerSize();
+				safeSwapPtr(strcData,data);
+
+				if (fixupPointers)
+				{
+					if (arrayLen > 1)
+					{
+						//void **sarray = (void**)strcData;
+						//void **darray = (void**)data;
+				
+                        char *cpc, *cpo;
+						cpc = (char*)strcData;
+						cpo = (char*)data;
+						
+						for (int a=0; a<arrayLen; a++)
+						{
+							safeSwapPtr(cpc, cpo);
+							m_pointerFixupArray.push_back(cpc);
+							cpc += ptrMem;
+							cpo += ptrFile;
+						}
+					}
+					else
+					{
+						if (name[1] == '*')
+							m_pointerPtrFixupArray.push_back(strcData);
+						else
+							m_pointerFixupArray.push_back(strcData);
+					}
+				}
+				else
+				{
+//					printf("skipped %s %s : %x\n",type.c_str(),name.c_str(),strcData);
+				}
+
+			}
+
+			else if (strcmp(type, lookupType)==0)
+				memcpy(strcData, data, eleLen);
+			else
+				getElement(arrayLen, lookupType, type, data, strcData);
+
+			// --
+			return;
+		}
+		data+=eleLen;
+	}
+}
+
+
+// ----------------------------------------------------- //
+char* bFile::getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos)
+{
+	short *old = firstStruct;//mFileDNA->getStruct(old_nr);
+	int elementLength = old[1];
+	old+=2;
+
+	for (int i=0; i<elementLength; i++, old+=2)
+	{
+		char* type = mFileDNA->getType(old[0]);
+		char* name = mFileDNA->getName(old[1]);
+		int len = mFileDNA->getElementSize(old[0], old[1]);
+
+		if (strcmp(lookupName, name)==0)
+		{
+			if (strcmp(type, lookupType)==0)
+			{
+				if (foundPos)
+					*foundPos = old;
+				return data;
+			}
+			return 0;
+		}
+		data+=len;
+	}
+	return 0;
+}
+
+
+// ----------------------------------------------------- //
+void bFile::swapStruct(int dna_nr, char *data)
+{
+	if (dna_nr == -1) return;
+
+	short *strc = mFileDNA->getStruct(dna_nr);
+	//short *firstStrc = strc;
+
+	int elementLen= strc[1];
+	strc+=2;
+
+	short first = mFileDNA->getStruct(0)[0];
+
+	char *buf = data;
+	for (int i=0; i<elementLen; i++, strc+=2)
+	{
+		char *type = mFileDNA->getType(strc[0]);
+		char *name = mFileDNA->getName(strc[1]);
+
+		int size = mFileDNA->getElementSize(strc[0], strc[1]);
+		if (strc[0] >= first && name[0]!='*')
+		{
+			int old_nr = mFileDNA->getReverseType(type);
+			int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+			if (arrayLen==1)
+			{
+				swapStruct(old_nr,buf);
+			} else
+			{
+				char* tmpBuf = buf;
+				for (int i=0;i<arrayLen;i++)
+				{
+					swapStruct(old_nr,tmpBuf);
+					tmpBuf+=size/arrayLen;
+				}
+			}
+		}
+		else
+		{
+			//int arrayLenOld = mFileDNA->getArraySize(name);
+			int arrayLen = mFileDNA->getArraySizeNew(strc[1]);
+			//assert(arrayLenOld == arrayLen);
+			swapData(buf, strc[0], arrayLen);
+		}
+		buf+=size;
+	}
+}
+
+void bFile::resolvePointersMismatch()
+{
+//	printf("resolvePointersStructMismatch\n");
+
+	int i;
+
+	for (i=0;i<	m_pointerFixupArray.size();i++)
+	{
+		char* cur = m_pointerFixupArray.at(i);
+		void** ptrptr = (void**) cur;
+		void* ptr = *ptrptr;
+		ptr = findLibPointer(ptr);
+		if (ptr)
+		{
+			//printf("Fixup pointer!\n");
+			*(ptrptr) = ptr;
+		} else
+		{
+//			printf("pointer not found: %x\n",cur);
+		}
+	}
+
+	 
+	for (i=0; i<m_pointerPtrFixupArray.size(); i++)
+	{
+		char* cur= m_pointerPtrFixupArray.at(i);
+		void** ptrptr = (void**)cur;
+
+		bChunkInd *block = m_chunkPtrPtrMap.find(*ptrptr);
+		if (block)
+		{
+			int ptrMem = mMemoryDNA->getPointerSize();
+			int ptrFile = mFileDNA->getPointerSize();
+
+
+			int blockLen = block->len / ptrFile;
+
+			void *onptr = findLibPointer(*ptrptr);
+			if (onptr)
+			{
+				char *newPtr = new char[blockLen * ptrMem];
+				addDataBlock(newPtr);
+				memset(newPtr, 0, blockLen * ptrMem);
+
+				void **onarray = (void**)onptr;
+				char *oldPtr = (char*)onarray;
+
+				int p = 0;
+				while (blockLen-- > 0)
+				{
+					btPointerUid dp = {0};
+					safeSwapPtr((char*)dp.m_uniqueIds, oldPtr);
+
+					void **tptr = (void**)(newPtr + p * ptrMem);
+					*tptr = findLibPointer(dp.m_ptr);
+
+					oldPtr += ptrFile;
+					++p;
+				}
+
+				*ptrptr = newPtr;
+			}
+		}
+	}
+}
+
+
+///this loop only works fine if the Blender DNA structure of the file matches the headerfiles
+void bFile::resolvePointersChunk(const bChunkInd& dataChunk, bool verboseDumpAllBlocks)
+{
+	bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+	short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+	short oldLen = fileDna->getLength(oldStruct[0]);
+	//char* structType = fileDna->getType(oldStruct[0]);
+
+	char* cur	= (char*)findLibPointer(dataChunk.oldPtr);
+	for (int block=0; block<dataChunk.nr; block++)
+	{
+		resolvePointersStructRecursive(cur,dataChunk.dna_nr, verboseDumpAllBlocks,1);
+		cur += oldLen;
+	}
+}
+
+
+void bFile::resolvePointersStructRecursive(char *strcPtr, int dna_nr, bool verboseDumpAllBlocks,int recursion)
+{
+	
+	bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+	char* memType;
+	char* memName;
+	short	firstStructType = fileDna->getStruct(0)[0];
+
+
+	char* elemPtr= strcPtr;
+
+	short int* oldStruct = fileDna->getStruct(dna_nr);
+	
+	int elementLength = oldStruct[1];
+	oldStruct+=2;
+
+
+	for (int ele=0; ele<elementLength; ele++, oldStruct+=2)
+	{
+
+		memType = fileDna->getType(oldStruct[0]);
+		memName = fileDna->getName(oldStruct[1]);
+		
+		
+
+		int arrayLen = fileDna->getArraySizeNew(oldStruct[1]);
+		if (memName[0] == '*')
+		{
+			if (arrayLen > 1)
+			{
+				void **array= (void**)elemPtr;
+				for (int a=0; a<arrayLen; a++)
+					array[a] = findLibPointer(array[a]);
+			}
+			else
+			{
+				void** ptrptr = (void**) elemPtr;
+				void* ptr = *ptrptr;
+				ptr = findLibPointer(ptr);
+				if (ptr)
+				{
+	//				printf("Fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+					*(ptrptr) = ptr;
+					if (memName[1] == '*' && ptrptr && *ptrptr)
+					{
+						// This	will only work if the given	**array	is continuous
+						void **array= (void**)*(ptrptr);
+						void *np= array[0];
+						int	n=0;
+						while (np)
+						{
+							np= findLibPointer(array[n]);
+							if (np) array[n]= np;
+							n++;
+						}
+					}
+				} else
+				{
+	//				printf("Cannot fixup pointer at 0x%x from 0x%x to 0x%x!\n",ptrptr,*ptrptr,ptr);
+				}
+			}
+		} else
+		{
+			int revType = fileDna->getReverseType(oldStruct[0]);
+			if (oldStruct[0]>=firstStructType) //revType != -1 && 
+			{
+				if (verboseDumpAllBlocks)
+				{
+					for (int i=0;i<recursion;i++)
+					{
+						printf("  ");
+					}
+					printf("<%s type=\"%s\">\n",memName,memType);
+				}
+				resolvePointersStructRecursive(elemPtr,revType, verboseDumpAllBlocks,recursion+1);
+				if (verboseDumpAllBlocks)
+				{
+					for (int i=0;i<recursion;i++)
+					{
+						printf("  ");
+					}
+					printf("</%s>\n",memName);
+				}
+			} else
+			{
+				//export a simple type
+				if (verboseDumpAllBlocks)
+				{
+
+					if (arrayLen>MAX_ARRAY_LENGTH)
+					{
+						printf("too long\n");
+					} else
+					{
+						//printf("%s %s\n",memType,memName);
+
+						bool isIntegerType = (strcmp(memType,"char")==0) || (strcmp(memType,"int")==0) || (strcmp(memType,"short")==0);
+
+						if (isIntegerType)
+						{
+							const char* newtype="int";
+							int dbarray[MAX_ARRAY_LENGTH];
+							int* dbPtr = 0;
+							char* tmp = elemPtr;
+							dbPtr = &dbarray[0];
+							if (dbPtr)
+							{
+								int i;
+								getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
+								for (i=0;i<recursion;i++)
+									printf("  ");
+								if (arrayLen==1)
+									printf("<%s type=\"%s\">",memName,memType);
+								else
+									printf("<%s type=\"%s\" count=%d>",memName,memType,arrayLen);
+								for (i=0;i<arrayLen;i++)
+									printf(" %d ",dbPtr[i]);
+								printf("</%s>\n",memName);
+							}
+						} else
+						{
+							const char* newtype="double";
+							double dbarray[MAX_ARRAY_LENGTH];
+					 		double* dbPtr = 0;
+							char* tmp = elemPtr;
+							dbPtr = &dbarray[0];
+							if (dbPtr)
+							{
+								int i;
+								getElement(arrayLen, newtype,memType, tmp, (char*)dbPtr);
+								for (i=0;i<recursion;i++)
+									printf("  ");
+								if (arrayLen==1)
+									printf("<%s type=\"%s\">",memName,memType);
+								else
+									printf("<%s type=\"%s\" count=%d>",memName,memType,arrayLen);
+								for (i=0;i<arrayLen;i++)
+									printf(" %f ",dbPtr[i]);
+								printf("</%s>\n",memName);
+							}
+						}
+					}
+					
+				}
+			}
+		}
+
+		int size = fileDna->getElementSize(oldStruct[0], oldStruct[1]);
+		elemPtr+=size;
+		
+	}
+}
+
+
+///Resolve pointers replaces the original pointers in structures, and linked lists by the new in-memory structures
+void bFile::resolvePointers(bool verboseDumpAllBlocks)
+{
+	bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+	// printf("resolvePointers start\n"); ***ALEX***
+	//char *dataPtr = mFileBuffer+mDataStart;
+
+	if (1) //mFlags & (FD_BITS_VARIES | FD_VERSION_VARIES))
+	{
+		resolvePointersMismatch();	
+	}
+	
+	{
+		for (int i=0;i<m_chunks.size();i++)
+		{
+			const bChunkInd& dataChunk = m_chunks.at(i);
+
+			if (!mFileDNA || fileDna->flagEqual(dataChunk.dna_nr))
+			{
+				//dataChunk.len
+				short int* oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+				char* oldType = fileDna->getType(oldStruct[0]);
+				
+				if (verboseDumpAllBlocks)
+					printf("<%s>\n",oldType);
+
+				resolvePointersChunk(dataChunk, verboseDumpAllBlocks);
+
+				if (verboseDumpAllBlocks)
+					printf("</%s>\n",oldType);
+			} else
+			{
+				//printf("skipping mStruct\n");
+			}
+		}
+	}
+	
+	//printf("resolvePointers end\n"); ***ALEX***
+}
+
+
+// ----------------------------------------------------- //
+void* bFile::findLibPointer(void *ptr)
+{
+
+	bStructHandle** ptrptr = getLibPointers().find(ptr);
+	if (ptrptr)
+		return *ptrptr;
+	return 0;
+}
+
+
+void	bFile::updateOldPointers()
+{
+	int i;
+
+	for (i=0;i<m_chunks.size();i++)
+	{
+		bChunkInd& dataChunk = m_chunks[i];
+		dataChunk.oldPtr = findLibPointer(dataChunk.oldPtr);
+	}
+}
+void	bFile::dumpChunks(bParse::bDNA* dna)
+{
+	int i;
+
+	for (i=0;i<m_chunks.size();i++)
+	{
+		bChunkInd& dataChunk = m_chunks[i];
+		char* codeptr = (char*)&dataChunk.code;
+		char codestr[5] = {codeptr[0],codeptr[1],codeptr[2],codeptr[3],0};
+		
+		short* newStruct = dna->getStruct(dataChunk.dna_nr);
+		char* typeName = dna->getType(newStruct[0]);
+		printf("%3d: %s  ",i,typeName);
+
+		printf("code=%s  ",codestr);
+		
+		printf("ptr=%p  ",dataChunk.oldPtr);
+		printf("len=%d  ",dataChunk.len);
+		printf("nr=%d  ",dataChunk.nr);
+		if (dataChunk.nr!=1)
+		{
+			printf("not 1\n");
+		}
+		printf("\n");
+
+		
+		
+
+	}
+
+#if 0
+	IDFinderData ifd;
+	ifd.success = 0;
+	ifd.IDname = NULL;
+	ifd.just_print_it = 1;
+	for (i=0; i<bf->m_blocks.size(); ++i) 
+	{
+		BlendBlock* bb = bf->m_blocks[i];
+		printf("tag='%s'\tptr=%p\ttype=%s\t[%4d]",		bb->tag, bb,bf->types[bb->type_index].name,bb->m_array_entries_.size());
+		block_ID_finder(bb, bf, &ifd);
+		printf("\n");
+	}
+#endif
+
+}
+
+
+void	bFile::writeChunks(FILE* fp, bool fixupPointers)
+{
+	bParse::bDNA* fileDna = mFileDNA ? mFileDNA : mMemoryDNA;
+
+	for (int i=0;i<m_chunks.size();i++)
+	{
+		bChunkInd& dataChunk = m_chunks.at(i);
+		
+		// Ouch! need to rebuild the struct
+		short *oldStruct,*curStruct;
+		char *oldType, *newType;
+		int oldLen, curLen, reverseOld;
+
+		oldStruct = fileDna->getStruct(dataChunk.dna_nr);
+		oldType = fileDna->getType(oldStruct[0]);
+		oldLen = fileDna->getLength(oldStruct[0]);
+		///don't try to convert Link block data, just memcpy it. Other data can be converted.
+		reverseOld = mMemoryDNA->getReverseType(oldType);
+		
+
+		if ((reverseOld!=-1))
+		{
+			// make sure it's here
+			//assert(reverseOld!= -1 && "getReverseType() returned -1, struct required!");
+			//
+			curStruct = mMemoryDNA->getStruct(reverseOld);
+			newType = mMemoryDNA->getType(curStruct[0]);
+			// make sure it's the same
+			assert((strcmp(oldType, newType)==0) && "internal error, struct mismatch!");
+
+			
+			curLen = mMemoryDNA->getLength(curStruct[0]);
+			dataChunk.dna_nr = reverseOld;
+			if (strcmp("Link",oldType)!=0)
+			{
+				dataChunk.len = curLen * dataChunk.nr;
+			} else
+			{
+//				printf("keep length of link = %d\n",dataChunk.len);
+			}
+		
+			//write the structure header
+			fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+			
+
+
+			short int* curStruct1;
+			curStruct1 = mMemoryDNA->getStruct(dataChunk.dna_nr);
+			assert(curStruct1 == curStruct);
+
+			char* cur	= fixupPointers  ?  (char*)findLibPointer(dataChunk.oldPtr) : (char*)dataChunk.oldPtr;
+
+			//write the actual contents of the structure(s)
+			fwrite(cur,dataChunk.len,1,fp);
+		} else
+		{
+			printf("serious error, struct mismatch: don't write\n");
+		}
+	}
+	
+}
+
+// ----------------------------------------------------- //
+int bFile::getNextBlock(bChunkInd *dataChunk,  const char *dataPtr, const int flags)
+{
+	bool swap = false;
+	bool varies = false;
+
+	if (flags &FD_ENDIAN_SWAP) swap = true;
+	if (flags &FD_BITS_VARIES) varies = true;
+
+	if (VOID_IS_8)
+	{
+		if (varies)
+		{
+			bChunkPtr4 head;
+			memcpy(&head, dataPtr, sizeof(bChunkPtr4));
+
+
+			bChunkPtr8 chunk;
+
+			chunk.code		= head.code;
+			chunk.len		= head.len;
+			chunk.m_uniqueInts[0] = head.m_uniqueInt;
+			chunk.m_uniqueInts[1] = 0;
+			chunk.dna_nr	= head.dna_nr;
+			chunk.nr		= head.nr;
+
+			if (swap)
+			{
+				if ((chunk.code & 0xFFFF)==0)
+					chunk.code >>=16;
+
+				SWITCH_INT(chunk.len);
+				SWITCH_INT(chunk.dna_nr);
+				SWITCH_INT(chunk.nr);
+			}
+
+
+			memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+		}
+		else
+		{
+			bChunkPtr8 c;
+			memcpy(&c, dataPtr, sizeof(bChunkPtr8));
+
+			if (swap)
+			{
+				if ((c.code & 0xFFFF)==0)
+					c.code >>=16;
+
+				SWITCH_INT(c.len);
+				SWITCH_INT(c.dna_nr);
+				SWITCH_INT(c.nr);
+			}
+
+			memcpy(dataChunk, &c, sizeof(bChunkInd));
+		}
+	}
+	else
+	{
+		if (varies)
+		{
+			bChunkPtr8 head;
+			memcpy(&head, dataPtr, sizeof(bChunkPtr8));
+
+
+			bChunkPtr4 chunk;
+			chunk.code = head.code;
+			chunk.len = head.len;
+
+			if (head.m_uniqueInts[0]==head.m_uniqueInts[1])
+			{
+				chunk.m_uniqueInt = head.m_uniqueInts[0];
+			} else
+			{
+				long64 oldPtr =0;
+				memcpy(&oldPtr, &head.m_uniqueInts[0], 8);
+				if (swap) 
+					SWITCH_LONGINT(oldPtr);
+				chunk.m_uniqueInt = (int)(oldPtr >> 3);
+			}
+			
+
+			chunk.dna_nr = head.dna_nr;
+			chunk.nr = head.nr;
+
+			if (swap)
+			{
+				if ((chunk.code & 0xFFFF)==0)
+					chunk.code >>=16;
+
+				SWITCH_INT(chunk.len);
+				SWITCH_INT(chunk.dna_nr);
+				SWITCH_INT(chunk.nr);
+			}
+
+			memcpy(dataChunk, &chunk, sizeof(bChunkInd));
+		}
+		else
+		{
+			bChunkPtr4 c;
+			memcpy(&c, dataPtr, sizeof(bChunkPtr4));
+
+			if (swap)
+			{
+				if ((c.code & 0xFFFF)==0)
+					c.code >>=16;
+
+				SWITCH_INT(c.len);
+				SWITCH_INT(c.dna_nr);
+				SWITCH_INT(c.nr);
+			}
+			memcpy(dataChunk, &c, sizeof(bChunkInd));
+		}
+	}
+
+	if (dataChunk->len < 0)
+		return -1;
+
+#if 0
+	print ("----------");
+	print (dataChunk->code);
+	print (dataChunk->len);
+	print (dataChunk->old);
+	print (dataChunk->dna_nr);
+	print (dataChunk->nr);
+#endif
+	return (dataChunk->len+ChunkUtils::getOffset(flags));
+}
+
+
+
+//eof
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bFile.h b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bFile.h
new file mode 100644
index 0000000..35e923f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/bFile.h
@@ -0,0 +1,154 @@
+/*
+bParse
+Copyright (c) 2006-2009 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef __BFILE_H__
+#define __BFILE_H__
+
+#include "bCommon.h"
+#include "bChunk.h"
+#include <stdio.h>
+
+namespace bParse {
+
+	// ----------------------------------------------------- //
+	enum bFileFlags
+	{
+		FD_INVALID   =0,
+		FD_OK        =1,
+		FD_VOID_IS_8 =2,
+		FD_ENDIAN_SWAP      =4,
+		FD_FILE_64   =8,
+		FD_BITS_VARIES    =16,
+		FD_VERSION_VARIES = 32,
+		FD_DOUBLE_PRECISION =64,
+		FD_BROKEN_DNA = 128
+	};
+
+
+	// ----------------------------------------------------- //
+	class bFile
+	{
+	protected:
+		
+		char				m_headerString[7];
+
+		bool				mOwnsBuffer;
+		char*				mFileBuffer;
+		int					mFileLen;
+		int					mVersion;
+
+
+		bPtrMap				mLibPointers;
+
+		int					mDataStart;
+		bDNA*				mFileDNA;
+		bDNA*				mMemoryDNA;
+
+		btAlignedObjectArray<char*>	m_pointerFixupArray;
+		btAlignedObjectArray<char*>	m_pointerPtrFixupArray;
+		
+		btAlignedObjectArray<bChunkInd>	m_chunks;
+        btHashMap<btHashPtr, bChunkInd> m_chunkPtrPtrMap;
+
+        // 
+	
+		bPtrMap				mDataPointers;
+
+		
+		int					mFlags;
+
+		// ////////////////////////////////////////////////////////////////////////////
+
+			// buffer offset util
+		int getNextBlock(bChunkInd *dataChunk,  const char *dataPtr, const int flags);
+		void safeSwapPtr(char *dst, const char *src);
+
+		virtual	void parseHeader();
+		
+		virtual	void parseData() = 0;
+
+		void resolvePointersMismatch();
+		void resolvePointersChunk(const bChunkInd& dataChunk, bool verboseDumpAllBlocks);
+
+		void resolvePointersStructRecursive(char *strcPtr, int old_dna, bool verboseDumpAllBlocks, int recursion);
+		//void swapPtr(char *dst, char *src);
+
+		void parseStruct(char *strcPtr, char *dtPtr, int old_dna, int new_dna, bool fixupPointers);
+		void getMatchingFileDNA(short* old, const char* lookupName, const char* lookupType, char *strcData, char *data, bool fixupPointers);
+		char* getFileElement(short *firstStruct, char *lookupName, char *lookupType, char *data, short **foundPos);
+
+
+		void swap(char *head, class bChunkInd& ch);
+
+		void swapData(char *data, short type, int arraySize);
+		void swapStruct(int dna_nr, char *data);
+
+
+
+
+		char* readStruct(char *head, class bChunkInd& chunk);
+		char *getAsString(int code);
+
+		void	parseInternal(bool verboseDumpAllTypes, char* memDna,int memDnaLength);
+
+	public:
+		bFile(const char *filename, const char headerString[7]);
+		
+		//todo: make memoryBuffer const char
+		//bFile( const char *memoryBuffer, int len);
+		bFile( char *memoryBuffer, int len, const char headerString[7]);
+		virtual ~bFile();
+
+		bDNA*				getFileDNA()
+		{
+			return mFileDNA;
+		}
+
+		virtual	void	addDataBlock(char* dataBlock) = 0;
+
+		int	getFlags() const
+		{
+			return mFlags;
+		}
+
+		bPtrMap&		getLibPointers()
+		{
+			return mLibPointers;
+		}
+		
+		void* findLibPointer(void *ptr);
+
+		bool ok();
+
+		virtual	void parse(bool verboseDumpAllTypes) = 0;
+
+		virtual	int	write(const char* fileName, bool fixupPointers=false) = 0;
+
+		virtual	void	writeChunks(FILE* fp, bool fixupPointers );
+
+		virtual	void	writeDNA(FILE* fp) = 0;
+
+		void	updateOldPointers();
+		void	resolvePointers(bool verboseDumpAllBlocks);
+
+		void	dumpChunks(bDNA* dna);
+		
+
+		
+	};
+}
+
+
+#endif//__BFILE_H__
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/btBulletFile.cpp b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/btBulletFile.cpp
new file mode 100644
index 0000000..358b2d0
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/btBulletFile.cpp
@@ -0,0 +1,397 @@
+/*
+bParse
+Copyright (c) 2006-2010 Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBulletFile.h"
+#include "bDefines.h"
+#include "bDNA.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+// 32 && 64 bit versions
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#ifdef _WIN64
+extern unsigned char sBulletDNAstr64[];
+extern int sBulletDNAlen64;
+#else
+extern unsigned char sBulletDNAstr[];
+extern int sBulletDNAlen;
+#endif //_WIN64
+#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+extern unsigned char sBulletDNAstr64[];
+extern int sBulletDNAlen64;
+extern unsigned char sBulletDNAstr[];
+extern int sBulletDNAlen;
+
+#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+
+using namespace bParse;
+
+btBulletFile::btBulletFile()
+:bFile("", "BULLET ")
+{
+	mMemoryDNA = new bDNA(); //this memory gets released in the bFile::~bFile destructor, at todo not consistent with the rule 'who allocates it, has to deallocate it"
+
+	m_DnaCopy = 0;
+
+
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+#ifdef _WIN64
+		m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16);
+		memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
+		mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64);
+#else//_WIN64
+		m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16);
+		memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
+		mMemoryDNA->init(m_DnaCopy,sBulletDNAlen);
+#endif//_WIN64
+#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+	if (VOID_IS_8)
+	{
+		m_DnaCopy = (char*) btAlignedAlloc(sBulletDNAlen64,16);
+		memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
+		mMemoryDNA->init(m_DnaCopy,sBulletDNAlen64);
+	}
+	else
+	{
+		m_DnaCopy =(char*) btAlignedAlloc(sBulletDNAlen,16);
+		memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
+		mMemoryDNA->init(m_DnaCopy,sBulletDNAlen);
+	}
+#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+}
+
+
+
+btBulletFile::btBulletFile(const char* fileName)
+:bFile(fileName, "BULLET ")
+{
+	m_DnaCopy = 0;
+}
+
+
+
+btBulletFile::btBulletFile(char *memoryBuffer, int len)
+:bFile(memoryBuffer,len, "BULLET ")
+{
+	m_DnaCopy = 0;
+}
+
+
+btBulletFile::~btBulletFile()
+{
+	if (m_DnaCopy)
+		btAlignedFree(m_DnaCopy);
+
+	
+	while (m_dataBlocks.size())
+	{
+		char* dataBlock = m_dataBlocks[m_dataBlocks.size()-1];
+		delete[] dataBlock;
+		m_dataBlocks.pop_back();
+	}
+
+}
+
+
+
+// ----------------------------------------------------- //
+void btBulletFile::parseData()
+{
+	/* ***ALEX***
+	printf ("Building datablocks");
+	printf ("Chunk size = %d",CHUNK_HEADER_LEN);
+	printf ("File chunk size = %d",ChunkUtils::getOffset(mFlags));
+	*/
+	const bool brokenDNA = (mFlags&FD_BROKEN_DNA)!=0;
+
+	//const bool swap = (mFlags&FD_ENDIAN_SWAP)!=0;
+	
+
+	mDataStart = 12;
+
+	char *dataPtr = mFileBuffer+mDataStart;
+
+	bChunkInd dataChunk;
+	dataChunk.code = 0;
+
+
+	//dataPtr += ChunkUtils::getNextBlock(&dataChunk, dataPtr, mFlags);
+	int seek = getNextBlock(&dataChunk, dataPtr, mFlags);
+	//dataPtr += ChunkUtils::getOffset(mFlags);
+	char *dataPtrHead = 0;
+
+	while (dataChunk.code != DNA1)
+	{
+		if (!brokenDNA || (dataChunk.code != BT_QUANTIZED_BVH_CODE) )
+		{
+
+			// one behind
+			if (dataChunk.code == SDNA) break;
+			//if (dataChunk.code == DNA1) break;
+
+			// same as (BHEAD+DATA dependency)
+			dataPtrHead = dataPtr+ChunkUtils::getOffset(mFlags);
+			if (dataChunk.dna_nr>=0)
+			{
+				char *id = readStruct(dataPtrHead, dataChunk);
+
+				// lookup maps
+				if (id)
+				{
+					m_chunkPtrPtrMap.insert(dataChunk.oldPtr, dataChunk);
+					mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)id);
+
+					m_chunks.push_back(dataChunk);
+					// block it
+					//bListBasePtr *listID = mMain->getListBasePtr(dataChunk.code);
+					//if (listID)
+					//	listID->push_back((bStructHandle*)id);
+				}
+
+				if (dataChunk.code == BT_RIGIDBODY_CODE)
+				{
+					m_rigidBodies.push_back((bStructHandle*) id);
+				}
+
+				if (dataChunk.code == BT_CONSTRAINT_CODE)
+				{
+					m_constraints.push_back((bStructHandle*) id);
+				}
+
+				if (dataChunk.code == BT_QUANTIZED_BVH_CODE)
+				{
+					m_bvhs.push_back((bStructHandle*) id);
+				}
+
+				if (dataChunk.code == BT_TRIANLGE_INFO_MAP)
+				{
+					m_triangleInfoMaps.push_back((bStructHandle*) id);
+				}
+
+				if (dataChunk.code == BT_COLLISIONOBJECT_CODE)
+				{
+					m_collisionObjects.push_back((bStructHandle*) id);
+				}
+
+				if (dataChunk.code == BT_SHAPE_CODE)
+				{
+					m_collisionShapes.push_back((bStructHandle*) id);
+				}
+
+		//		if (dataChunk.code == GLOB)
+		//		{
+		//			m_glob = (bStructHandle*) id;
+		//		}
+			} else
+			{
+				printf("unknown chunk\n");
+
+				mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)dataPtrHead);
+			}
+		} else
+		{
+			printf("skipping BT_QUANTIZED_BVH_CODE due to broken DNA\n");
+		}
+
+		// next please!
+		dataPtr += seek;
+
+		seek =  getNextBlock(&dataChunk, dataPtr, mFlags);
+		if (seek < 0)
+			break;
+	}
+
+}
+
+void	btBulletFile::addDataBlock(char* dataBlock)
+{
+	m_dataBlocks.push_back(dataBlock);
+
+}
+
+
+
+
+void	btBulletFile::writeDNA(FILE* fp)
+{
+
+	bChunkInd dataChunk;
+	dataChunk.code = DNA1;
+	dataChunk.dna_nr = 0;
+	dataChunk.nr = 1;
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES	
+	if (VOID_IS_8)
+	{
+#ifdef _WIN64
+		dataChunk.len = sBulletDNAlen64;
+		dataChunk.oldPtr = sBulletDNAstr64;
+		fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+		fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp);
+#else
+		btAssert(0);
+#endif
+	}
+	else
+	{
+#ifndef _WIN64
+		dataChunk.len = sBulletDNAlen;
+		dataChunk.oldPtr = sBulletDNAstr;
+		fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+		fwrite(sBulletDNAstr, sBulletDNAlen,1,fp);
+#else//_WIN64
+		btAssert(0);
+#endif//_WIN64
+	}
+#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+	if (VOID_IS_8)
+	{
+		dataChunk.len = sBulletDNAlen64;
+		dataChunk.oldPtr = sBulletDNAstr64;
+		fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+		fwrite(sBulletDNAstr64, sBulletDNAlen64,1,fp);
+	}
+	else
+	{
+		dataChunk.len = sBulletDNAlen;
+		dataChunk.oldPtr = sBulletDNAstr;
+		fwrite(&dataChunk,sizeof(bChunkInd),1,fp);
+		fwrite(sBulletDNAstr, sBulletDNAlen,1,fp);
+	}
+#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+}
+
+
+void	btBulletFile::parse(bool verboseDumpAllTypes)
+{
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+	if (VOID_IS_8)
+	{
+#ifdef _WIN64
+		
+		if (m_DnaCopy)
+			delete m_DnaCopy;
+		m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16);
+		memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
+		parseInternal(verboseDumpAllTypes,(char*)sBulletDNAstr64,sBulletDNAlen64);
+#else
+		btAssert(0);
+#endif
+	}
+	else
+	{
+#ifndef _WIN64
+
+		if (m_DnaCopy)
+			delete m_DnaCopy;
+		m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16);
+		memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
+		parseInternal(verboseDumpAllTypes,m_DnaCopy,sBulletDNAlen);
+#else
+		btAssert(0);
+#endif
+	}
+#else//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+	if (VOID_IS_8)
+	{
+		if (m_DnaCopy)
+			delete m_DnaCopy;
+		m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen64,16);
+		memcpy(m_DnaCopy,sBulletDNAstr64,sBulletDNAlen64);
+		parseInternal(verboseDumpAllTypes,m_DnaCopy,sBulletDNAlen64);
+	}
+	else
+	{
+		if (m_DnaCopy)
+			delete m_DnaCopy;
+		m_DnaCopy = (char*)btAlignedAlloc(sBulletDNAlen,16);
+		memcpy(m_DnaCopy,sBulletDNAstr,sBulletDNAlen);
+		parseInternal(verboseDumpAllTypes,m_DnaCopy,sBulletDNAlen);
+	}
+#endif//BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+}
+
+// experimental
+int		btBulletFile::write(const char* fileName, bool fixupPointers)
+{
+	FILE *fp = fopen(fileName, "wb");
+	if (fp)
+	{
+		char header[SIZEOFBLENDERHEADER] ;
+		memcpy(header, m_headerString, 7);
+		int endian= 1;
+		endian= ((char*)&endian)[0];
+
+		if (endian)
+		{
+			header[7] = '_';
+		} else
+		{
+			header[7] = '-';
+		}
+		if (VOID_IS_8)
+		{
+			header[8]='V';
+		} else
+		{
+			header[8]='v';
+		}
+
+		header[9] = '2';
+		header[10] = '7';
+		header[11] = '5';
+		
+		fwrite(header,SIZEOFBLENDERHEADER,1,fp);
+
+		writeChunks(fp, fixupPointers);
+
+		writeDNA(fp);
+
+		fclose(fp);
+		
+	} else
+	{
+		printf("Error: cannot open file %s for writing\n",fileName);
+		return 0;
+	}
+	return 1;
+}
+
+
+
+void	btBulletFile::addStruct(const	char* structType,void* data, int len, void* oldPtr, int code)
+{
+	
+	bParse::bChunkInd dataChunk;
+	dataChunk.code = code;
+	dataChunk.nr = 1;
+	dataChunk.len = len;
+	dataChunk.dna_nr = mMemoryDNA->getReverseType(structType);
+	dataChunk.oldPtr = oldPtr;
+
+	///Perform structure size validation
+	short* structInfo= mMemoryDNA->getStruct(dataChunk.dna_nr);
+	int elemBytes;
+	elemBytes= mMemoryDNA->getLength(structInfo[0]);
+//	int elemBytes = mMemoryDNA->getElementSize(structInfo[0],structInfo[1]);
+	assert(len==elemBytes);
+
+	mLibPointers.insert(dataChunk.oldPtr, (bStructHandle*)data);
+	m_chunks.push_back(dataChunk);
+}
\ No newline at end of file
diff --git a/SRC/ChronoEngine/collision/bullet/BulletFileLoader/btBulletFile.h b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/btBulletFile.h
new file mode 100644
index 0000000..2575cdb
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletFileLoader/btBulletFile.h
@@ -0,0 +1,79 @@
+/*
+bParse
+Copyright (c) 2006-2010 Charlie C & Erwin Coumans  http://gamekit.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_BULLET_FILE_H
+#define BT_BULLET_FILE_H
+
+
+#include "bFile.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "bDefines.h"
+
+#include "LinearMath/btSerializer.h"
+
+
+
+namespace bParse {
+
+	// ----------------------------------------------------- //
+	class btBulletFile : public bFile
+	{
+		
+
+	protected:
+	
+		char*	m_DnaCopy;
+				
+	public:
+
+		btAlignedObjectArray<bStructHandle*>	m_rigidBodies;
+
+		btAlignedObjectArray<bStructHandle*>	m_collisionObjects;
+
+		btAlignedObjectArray<bStructHandle*>	m_collisionShapes;
+
+		btAlignedObjectArray<bStructHandle*>	m_constraints;
+
+		btAlignedObjectArray<bStructHandle*>	m_bvhs;
+
+		btAlignedObjectArray<bStructHandle*>	m_triangleInfoMaps;
+		
+		btAlignedObjectArray<char*>				m_dataBlocks;
+		btBulletFile();
+
+		btBulletFile(const char* fileName);
+
+		btBulletFile(char *memoryBuffer, int len);
+
+		virtual ~btBulletFile();
+
+		virtual	void	addDataBlock(char* dataBlock);
+	
+
+		// experimental
+		virtual int		write(const char* fileName, bool fixupPointers=false);
+
+		virtual	void	parse(bool verboseDumpAllTypes);
+
+		virtual	void parseData();
+
+		virtual	void	writeDNA(FILE* fp);
+
+		void	addStruct(const char* structType,void* data, int len, void* oldPtr, int code);
+
+	};
+};
+
+#endif //BT_BULLET_FILE_H
diff --git a/SRC/ChronoEngine/collision/bullet/BulletWorldImporter/btBulletWorldImporter.cpp b/SRC/ChronoEngine/collision/bullet/BulletWorldImporter/btBulletWorldImporter.cpp
new file mode 100644
index 0000000..78c2d28
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletWorldImporter/btBulletWorldImporter.cpp
@@ -0,0 +1,1233 @@
+
+#include "btBulletWorldImporter.h"
+#include "../BulletFileLoader/btBulletFile.h"
+
+//#include "btBulletDynamicsCommon.h"				//***ALEX***
+#include "btBulletCollisionCommon.h"				//***ALEX***
+//#include "BulletCollision/Gimpact/btGImpactShape.h" //***ALEX***
+
+
+//#define USE_INTERNAL_EDGE_UTILITY
+#ifdef USE_INTERNAL_EDGE_UTILITY
+#include "BulletCollision/CollisionDispatch/btInternalEdgeUtility.h"
+#endif //USE_INTERNAL_EDGE_UTILITY
+
+btBulletWorldImporter::btBulletWorldImporter(btDynamicsWorld* world)
+:m_dynamicsWorld(world),
+m_verboseDumpAllTypes(false)
+{
+}
+
+btBulletWorldImporter::~btBulletWorldImporter()
+{
+}
+
+void btBulletWorldImporter::deleteAllData()
+{
+	int i;
+	for (i=0;i<m_allocatedCollisionShapes.size();i++)
+	{
+		delete m_allocatedCollisionShapes[i];
+	}
+	m_allocatedCollisionShapes.clear();
+
+	for (i=0;i<m_allocatedRigidBodies.size();i++)
+	{
+		delete m_allocatedRigidBodies[i];
+	}
+	m_allocatedRigidBodies.clear();
+
+	for (i=0;i<m_allocatedConstraints.size();i++)
+	{
+		delete m_allocatedConstraints[i];
+	}
+	m_allocatedConstraints.clear();
+
+	for (i=0;i<m_allocatedBvhs.size();i++)
+	{
+		delete m_allocatedBvhs[i];
+	}
+	m_allocatedBvhs.clear();
+	
+	for (i=0;i<m_allocatedTriangleInfoMaps.size();i++)
+	{
+		delete m_allocatedTriangleInfoMaps[i];
+	}
+	m_allocatedTriangleInfoMaps.clear();
+	for (i=0;i<m_allocatedTriangleIndexArrays.size();i++)
+	{
+		delete m_allocatedTriangleIndexArrays[i];
+	}
+	m_allocatedTriangleIndexArrays.clear();
+	for (i=0;i<m_allocatedNames.size();i++)
+	{
+		delete m_allocatedNames[i];
+	}
+	m_allocatedNames.clear();
+
+}
+
+
+bool	btBulletWorldImporter::loadFile( const char* fileName)
+{
+	bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(fileName);
+
+	bool result = loadFileFromMemory(bulletFile2);
+
+	delete bulletFile2;
+	
+	return result;
+
+}
+
+
+
+bool	btBulletWorldImporter::loadFileFromMemory( char* memoryBuffer, int len)
+{
+	bParse::btBulletFile* bulletFile2 = new bParse::btBulletFile(memoryBuffer,len);
+
+	bool result = loadFileFromMemory(bulletFile2);
+
+	delete bulletFile2;
+
+	return result;
+}
+
+btTriangleIndexVertexArray* btBulletWorldImporter::createMeshInterface(btStridingMeshInterfaceData&  meshData)
+{
+	btTriangleIndexVertexArray* meshInterface = createTriangleMeshContainer();
+
+	for (int i=0;i<meshData.m_numMeshParts;i++)
+	{
+		btIndexedMesh meshPart;
+		if (meshData.m_meshPartsPtr[i].m_indices32)
+		{
+			meshPart.m_indexType = PHY_INTEGER;
+			meshPart.m_triangleIndexStride = 3*sizeof(int);
+			meshPart.m_triangleIndexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_indices32;
+		} else
+		{
+			meshPart.m_indexType = PHY_SHORT;
+			if (meshData.m_meshPartsPtr[i].m_3indices16)
+			{
+				meshPart.m_triangleIndexStride = sizeof(btShortIntIndexTripletData);
+				meshPart.m_triangleIndexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_3indices16;
+			}
+			if (meshData.m_meshPartsPtr[i].m_indices16)
+			{
+				meshPart.m_triangleIndexStride = 3*sizeof(short int);
+				meshPart.m_triangleIndexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_indices16;
+			}
+
+		}
+
+		if (meshData.m_meshPartsPtr[i].m_vertices3f)
+		{
+			meshPart.m_vertexType = PHY_FLOAT;
+			meshPart.m_vertexStride = sizeof(btVector3FloatData);
+			meshPart.m_vertexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_vertices3f;
+		} else
+		{
+			meshPart.m_vertexType = PHY_DOUBLE;
+			meshPart.m_vertexStride = sizeof(btVector3DoubleData);
+			meshPart.m_vertexBase = (const unsigned char*)meshData.m_meshPartsPtr[i].m_vertices3d;
+		}
+		meshPart.m_numTriangles = meshData.m_meshPartsPtr[i].m_numTriangles;
+		meshPart.m_numVertices = meshData.m_meshPartsPtr[i].m_numVertices;
+		
+		if (meshPart.m_triangleIndexBase && meshPart.m_vertexBase)
+		{
+			meshInterface->addIndexedMesh(meshPart,meshPart.m_indexType);
+		}
+	}
+
+	return meshInterface;
+}
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+extern ContactAddedCallback		gContactAddedCallback;
+
+static bool btAdjustInternalEdgeContactsCallback(btManifoldPoint& cp,	const btCollisionObject* colObj0,int partId0,int index0,const btCollisionObject* colObj1,int partId1,int index1)
+{
+
+	btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1);
+		//btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_BACKFACE_MODE);
+		//btAdjustInternalEdgeContacts(cp,colObj1,colObj0, partId1,index1, BT_TRIANGLE_CONVEX_DOUBLE_SIDED+BT_TRIANGLE_CONCAVE_DOUBLE_SIDED);
+	return true;
+}
+#endif //USE_INTERNAL_EDGE_UTILITY
+
+btCollisionShape* btBulletWorldImporter::convertCollisionShape(  btCollisionShapeData* shapeData  )
+{
+	btCollisionShape* shape = 0;
+
+	switch (shapeData->m_shapeType)
+		{
+	case STATIC_PLANE_PROXYTYPE:
+		{
+			btStaticPlaneShapeData* planeData = (btStaticPlaneShapeData*)shapeData;
+			btVector3 planeNormal,localScaling;
+			planeNormal.deSerializeFloat(planeData->m_planeNormal);
+			localScaling.deSerializeFloat(planeData->m_localScaling);
+			shape = createPlaneShape(planeNormal,planeData->m_planeConstant);
+			shape->setLocalScaling(localScaling);
+
+			break;
+		}
+		/* ***ALEX***
+	case GIMPACT_SHAPE_PROXYTYPE:
+		{
+			btGImpactMeshShapeData* gimpactData = (btGImpactMeshShapeData*) shapeData;
+			if (gimpactData->m_gimpactSubType == CONST_GIMPACT_TRIMESH_SHAPE)
+			{
+				btTriangleIndexVertexArray* meshInterface = createMeshInterface(gimpactData->m_meshInterface);
+				btGImpactMeshShape* gimpactShape = createGimpactShape(meshInterface);
+				btVector3 localScaling;
+				localScaling.deSerializeFloat(gimpactData->m_localScaling);
+				gimpactShape->setLocalScaling(localScaling);
+				gimpactShape->setMargin(btScalar(gimpactData->m_collisionMargin));
+				gimpactShape->updateBound();
+				shape = gimpactShape;
+			} else
+			{
+				printf("unsupported gimpact sub type\n");
+			}
+			break;
+		}
+*/
+		case CYLINDER_SHAPE_PROXYTYPE:
+		case CAPSULE_SHAPE_PROXYTYPE:
+		case BOX_SHAPE_PROXYTYPE:
+		case SPHERE_SHAPE_PROXYTYPE:
+		case MULTI_SPHERE_SHAPE_PROXYTYPE:
+		case CONVEX_HULL_SHAPE_PROXYTYPE:
+			{
+				btConvexInternalShapeData* bsd = (btConvexInternalShapeData*)shapeData;
+				btVector3 implicitShapeDimensions;
+				implicitShapeDimensions.deSerializeFloat(bsd->m_implicitShapeDimensions);
+				btVector3 localScaling;
+				localScaling.deSerializeFloat(bsd->m_localScaling);
+				btVector3 margin(bsd->m_collisionMargin,bsd->m_collisionMargin,bsd->m_collisionMargin);
+				switch (shapeData->m_shapeType)
+				{
+					case BOX_SHAPE_PROXYTYPE:
+						{
+							shape = createBoxShape(implicitShapeDimensions/localScaling+margin);
+							break;
+						}
+					case SPHERE_SHAPE_PROXYTYPE:
+						{
+							shape = createSphereShape(implicitShapeDimensions.getX());
+							break;
+						}
+					case CAPSULE_SHAPE_PROXYTYPE:
+						{
+							btCapsuleShapeData* capData = (btCapsuleShapeData*)shapeData;
+							switch (capData->m_upAxis)
+							{
+							case 0:
+								{
+									shape = createCapsuleShapeX(implicitShapeDimensions.getY(),2*implicitShapeDimensions.getX());
+									break;
+								}
+							case 1:
+								{
+									shape = createCapsuleShapeY(implicitShapeDimensions.getX(),2*implicitShapeDimensions.getY());
+									break;
+								}
+							case 2:
+								{
+									shape = createCapsuleShapeZ(implicitShapeDimensions.getX(),2*implicitShapeDimensions.getZ());
+									break;
+								}
+							default:
+								{
+									printf("error: wrong up axis for btCapsuleShape\n");
+								}
+
+							};
+							
+							break;
+						}
+					case CYLINDER_SHAPE_PROXYTYPE:
+						{
+							btCylinderShapeData* cylData = (btCylinderShapeData*) shapeData;
+							btVector3 halfExtents = implicitShapeDimensions+margin;
+							switch (cylData->m_upAxis)
+							{
+							case 0:
+								{
+									shape = createCylinderShapeX(halfExtents.getY(),halfExtents.getX());
+									break;
+								}
+							case 1:
+								{
+									shape = createCylinderShapeY(halfExtents.getX(),halfExtents.getY());
+									break;
+								}
+							case 2:
+								{
+									shape = createCylinderShapeZ(halfExtents.getX(),halfExtents.getZ());
+									break;
+								}
+							default:
+								{
+									printf("unknown Cylinder up axis\n");
+								}
+
+							};
+							
+
+							
+							break;
+						}
+					case MULTI_SPHERE_SHAPE_PROXYTYPE:
+						{
+							btMultiSphereShapeData* mss = (btMultiSphereShapeData*)bsd;
+							int numSpheres = mss->m_localPositionArraySize;
+
+							btAlignedObjectArray<btVector3> tmpPos;
+							btAlignedObjectArray<btScalar> radii;
+							radii.resize(numSpheres);
+							tmpPos.resize(numSpheres);
+							int i;
+							for ( i=0;i<numSpheres;i++)
+							{
+								tmpPos[i].deSerializeFloat(mss->m_localPositionArrayPtr[i].m_pos);
+								radii[i] = mss->m_localPositionArrayPtr[i].m_radius;
+							}
+							shape = new btMultiSphereShape(&tmpPos[0],&radii[0],numSpheres);
+							break;
+						}
+					case CONVEX_HULL_SHAPE_PROXYTYPE:
+						{
+						//	int sz = sizeof(btConvexHullShapeData);
+						//	int sz2 = sizeof(btConvexInternalShapeData);
+						//	int sz3 = sizeof(btCollisionShapeData);
+							btConvexHullShapeData* convexData = (btConvexHullShapeData*)bsd;
+							int numPoints = convexData->m_numUnscaledPoints;
+
+							btAlignedObjectArray<btVector3> tmpPoints;
+							tmpPoints.resize(numPoints);
+							int i;
+							for ( i=0;i<numPoints;i++)
+							{
+#ifdef BT_USE_DOUBLE_PRECISION
+							if (convexData->m_unscaledPointsDoublePtr)
+								tmpPoints[i].deSerialize(convexData->m_unscaledPointsDoublePtr[i]);
+							if (convexData->m_unscaledPointsFloatPtr)
+								tmpPoints[i].deSerializeFloat(convexData->m_unscaledPointsFloatPtr[i]);
+#else
+							if (convexData->m_unscaledPointsFloatPtr)
+								tmpPoints[i].deSerialize(convexData->m_unscaledPointsFloatPtr[i]);
+							if (convexData->m_unscaledPointsDoublePtr)
+								tmpPoints[i].deSerializeDouble(convexData->m_unscaledPointsDoublePtr[i]);
+#endif //BT_USE_DOUBLE_PRECISION
+							}
+							btConvexHullShape* hullShape = createConvexHullShape();
+							for (i=0;i<numPoints;i++)
+							{
+								hullShape->addPoint(tmpPoints[i]);
+							}
+							shape = hullShape;
+							break;
+						}
+					default:
+						{
+							printf("error: cannot create shape type (%d)\n",shapeData->m_shapeType);
+						}
+				}
+
+				if (shape)
+				{
+					shape->setMargin(bsd->m_collisionMargin);
+					btVector3 localScaling;
+					localScaling.deSerializeFloat(bsd->m_localScaling);
+					shape->setLocalScaling(localScaling);
+					
+				}
+				break;
+			}
+		case TRIANGLE_MESH_SHAPE_PROXYTYPE:
+		{
+			btTriangleMeshShapeData* trimesh = (btTriangleMeshShapeData*)shapeData;
+			btTriangleIndexVertexArray* meshInterface = createMeshInterface(trimesh->m_meshInterface);
+			if (!meshInterface->getNumSubParts())
+			{
+				return 0;
+			}
+
+			btVector3 scaling; scaling.deSerializeFloat(trimesh->m_meshInterface.m_scaling);
+			meshInterface->setScaling(scaling);
+
+
+			btOptimizedBvh* bvh = 0;
+#if 0
+			if (trimesh->m_quantizedFloatBvh)
+			{
+				btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedFloatBvh);
+				if (bvhPtr && *bvhPtr)
+				{
+					bvh = *bvhPtr;
+				} else
+				{
+					bvh = createOptimizedBvh();
+					bvh->deSerializeFloat(*trimesh->m_quantizedFloatBvh);
+				}
+			}
+			if (trimesh->m_quantizedDoubleBvh)
+			{
+				btOptimizedBvh** bvhPtr = m_bvhMap.find(trimesh->m_quantizedDoubleBvh);
+				if (bvhPtr && *bvhPtr)
+				{
+					bvh = *bvhPtr;
+				} else
+				{
+					bvh = createOptimizedBvh();
+					bvh->deSerializeDouble(*trimesh->m_quantizedDoubleBvh);
+				}
+			}
+#endif
+
+
+			btBvhTriangleMeshShape* trimeshShape = createBvhTriangleMeshShape(meshInterface,bvh);
+			trimeshShape->setMargin(trimesh->m_collisionMargin);
+			shape = trimeshShape;
+
+			if (trimesh->m_triangleInfoMap)
+			{
+				btTriangleInfoMap* map = createTriangleInfoMap();
+				map->deSerialize(*trimesh->m_triangleInfoMap);
+				trimeshShape->setTriangleInfoMap(map);
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+				gContactAddedCallback = btAdjustInternalEdgeContactsCallback;
+#endif //USE_INTERNAL_EDGE_UTILITY
+
+			}
+
+			//printf("trimesh->m_collisionMargin=%f\n",trimesh->m_collisionMargin);
+			break;
+		}
+		case COMPOUND_SHAPE_PROXYTYPE:
+			{
+				btCompoundShapeData* compoundData = (btCompoundShapeData*)shapeData;
+				btCompoundShape* compoundShape = createCompoundShape();
+
+
+				btAlignedObjectArray<btCollisionShape*> childShapes;
+				for (int i=0;i<compoundData->m_numChildShapes;i++)
+				{
+					btCollisionShape* childShape = convertCollisionShape(compoundData->m_childShapePtr[i].m_childShape);
+					if (childShape)
+					{
+						btTransform localTransform;
+						localTransform.deSerializeFloat(compoundData->m_childShapePtr[i].m_transform);
+						compoundShape->addChildShape(localTransform,childShape);
+					} else
+					{
+						printf("error: couldn't create childShape for compoundShape\n");
+					}
+					
+				}
+				shape = compoundShape;
+
+				break;
+			}
+		default:
+			{
+				printf("unsupported shape type (%d)\n",shapeData->m_shapeType);
+			}
+		}
+
+		return shape;
+	
+}
+
+char* btBulletWorldImporter::duplicateName(const char* name)
+{
+	if (name)
+	{
+		int l = (int)strlen(name);
+		char* newName = new char[l+1];
+		memcpy(newName,name,l);
+		newName[l] = 0;
+		m_allocatedNames.push_back(newName);
+		return newName;
+	}
+	return 0;
+}
+
+bool	btBulletWorldImporter::loadFileFromMemory(  bParse::btBulletFile* bulletFile2)
+{
+	bool ok = (bulletFile2->getFlags()& bParse::FD_OK)!=0;
+	
+	if (ok)
+		bulletFile2->parse(m_verboseDumpAllTypes);
+	else 
+		return false;
+	
+	if (m_verboseDumpAllTypes)
+	{
+		bulletFile2->dumpChunks(bulletFile2->getFileDNA());
+	}
+
+	return convertAllObjects(bulletFile2);
+
+}
+
+bool	btBulletWorldImporter::convertAllObjects(  bParse::btBulletFile* bulletFile2)
+{
+	int i;
+	
+	for (i=0;i<bulletFile2->m_bvhs.size();i++)
+	{
+		btOptimizedBvh* bvh = createOptimizedBvh();
+
+		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
+		{
+			btQuantizedBvhDoubleData* bvhData = (btQuantizedBvhDoubleData*)bulletFile2->m_bvhs[i];
+			bvh->deSerializeDouble(*bvhData);
+		} else
+		{
+			btQuantizedBvhFloatData* bvhData = (btQuantizedBvhFloatData*)bulletFile2->m_bvhs[i];
+			bvh->deSerializeFloat(*bvhData);
+		}
+		m_bvhMap.insert(bulletFile2->m_bvhs[i],bvh);
+	}
+
+
+
+	btHashMap<btHashPtr,btCollisionShape*>	shapeMap;
+
+	for (i=0;i<bulletFile2->m_collisionShapes.size();i++)
+	{
+		btCollisionShapeData* shapeData = (btCollisionShapeData*)bulletFile2->m_collisionShapes[i];
+		btCollisionShape* shape = convertCollisionShape(shapeData);
+		if (shape)
+		{
+			//printf("shapeMap.insert(%x,%x)\n",shapeData,shape);
+			shapeMap.insert(shapeData,shape);
+		}
+
+		if (shape&& shapeData->m_name)
+		{
+			char* newname = duplicateName(shapeData->m_name);
+			m_objectNameMap.insert(shape,newname);
+			m_nameShapeMap.insert(newname,shape);
+		}
+	}
+
+	btHashMap<btHashPtr,btCollisionObject*>	bodyMap;
+
+	/* ***ALEX***
+
+	for (i=0;i<bulletFile2->m_rigidBodies.size();i++)
+	{
+		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
+		{
+			btRigidBodyDoubleData* colObjData = (btRigidBodyDoubleData*)bulletFile2->m_rigidBodies[i];
+			btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f);
+			btVector3 localInertia;
+			localInertia.setZero();
+			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape);
+			if (shapePtr && *shapePtr)
+			{
+				btTransform startTransform;
+				startTransform.deSerializeDouble(colObjData->m_collisionObjectData.m_worldTransform);
+			//	startTransform.setBasis(btMatrix3x3::getIdentity());
+				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+				if (shape->isNonMoving())
+				{
+					mass = 0.f;
+				}
+
+				if (mass)
+				{
+					shape->calculateLocalInertia(mass,localInertia);
+				}
+				bool isDynamic = mass!=0.f;
+				
+				btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape,colObjData->m_collisionObjectData.m_name);
+#ifdef USE_INTERNAL_EDGE_UTILITY
+				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+				{
+					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+					if (trimesh->getTriangleInfoMap())
+					{
+						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+					}
+				}
+#endif //USE_INTERNAL_EDGE_UTILITY
+				bodyMap.insert(colObjData,body);
+			} else
+			{
+				printf("error: no shape found\n");
+			}
+	
+		} else
+		{
+			btRigidBodyFloatData* colObjData = (btRigidBodyFloatData*)bulletFile2->m_rigidBodies[i];
+			btScalar mass = btScalar(colObjData->m_inverseMass? 1.f/colObjData->m_inverseMass : 0.f);
+			btVector3 localInertia;
+			localInertia.setZero();
+			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionObjectData.m_collisionShape);
+			if (shapePtr && *shapePtr)
+			{
+				btTransform startTransform;
+				startTransform.deSerializeFloat(colObjData->m_collisionObjectData.m_worldTransform);
+			//	startTransform.setBasis(btMatrix3x3::getIdentity());
+				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+				if (shape->isNonMoving())
+				{
+					mass = 0.f;
+				}
+				if (mass)
+				{
+					shape->calculateLocalInertia(mass,localInertia);
+				}
+				bool isDynamic = mass!=0.f;
+				btRigidBody* body = createRigidBody(isDynamic,mass,startTransform,shape,colObjData->m_collisionObjectData.m_name);
+#ifdef USE_INTERNAL_EDGE_UTILITY
+				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+				{
+					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+					if (trimesh->getTriangleInfoMap())
+					{
+						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+					}
+				}
+#endif //USE_INTERNAL_EDGE_UTILITY
+				bodyMap.insert(colObjData,body);
+			} else
+			{
+				printf("error: no shape found\n");
+			}
+		}
+	}
+
+	for (i=0;i<bulletFile2->m_collisionObjects.size();i++)
+	{
+		if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
+		{
+			btCollisionObjectDoubleData* colObjData = (btCollisionObjectDoubleData*)bulletFile2->m_collisionObjects[i];
+			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionShape);
+			if (shapePtr && *shapePtr)
+			{
+				btTransform startTransform;
+				startTransform.deSerializeDouble(colObjData->m_worldTransform);
+				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+				btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+				{
+					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+					if (trimesh->getTriangleInfoMap())
+					{
+						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+					}
+				}
+#endif //USE_INTERNAL_EDGE_UTILITY
+				bodyMap.insert(colObjData,body);
+			} else
+			{
+				printf("error: no shape found\n");
+			}
+	
+		} else
+		{
+			btCollisionObjectFloatData* colObjData = (btCollisionObjectFloatData*)bulletFile2->m_collisionObjects[i];
+			btCollisionShape** shapePtr = shapeMap.find(colObjData->m_collisionShape);
+			if (shapePtr && *shapePtr)
+			{
+				btTransform startTransform;
+				startTransform.deSerializeFloat(colObjData->m_worldTransform);
+				btCollisionShape* shape = (btCollisionShape*)*shapePtr;
+				btCollisionObject* body = createCollisionObject(startTransform,shape,colObjData->m_name);
+
+#ifdef USE_INTERNAL_EDGE_UTILITY
+				if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE)
+				{
+					btBvhTriangleMeshShape* trimesh = (btBvhTriangleMeshShape*)shape;
+					if (trimesh->getTriangleInfoMap())
+					{
+						body->setCollisionFlags(body->getCollisionFlags()  | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
+					}
+				}
+#endif //USE_INTERNAL_EDGE_UTILITY
+				bodyMap.insert(colObjData,body);
+			} else
+			{
+				printf("error: no shape found\n");
+			}
+		}
+		
+		printf("bla");
+	}
+
+	for (i=0;i<bulletFile2->m_constraints.size();i++)
+	{
+		btTypedConstraintData* constraintData = (btTypedConstraintData*)bulletFile2->m_constraints[i];
+		btCollisionObject** colAptr = bodyMap.find(constraintData->m_rbA);
+		btCollisionObject** colBptr = bodyMap.find(constraintData->m_rbB);
+
+		btRigidBody* rbA = 0;
+		btRigidBody* rbB = 0;
+
+		if (colAptr)
+		{
+			rbA = btRigidBody::upcast(*colAptr);
+			if (!rbA)
+				rbA = &getFixedBody();
+		}
+		if (colBptr)
+		{
+			rbB = btRigidBody::upcast(*colBptr);
+			if (!rbB)
+				rbB = &getFixedBody();
+		}
+		if (!rbA && !rbB)
+			continue;
+				
+		btTypedConstraint* constraint = 0;
+
+		switch (constraintData->m_objectType)
+		{
+		case POINT2POINT_CONSTRAINT_TYPE:
+			{
+				if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
+				{
+					btPoint2PointConstraintDoubleData* p2pData = (btPoint2PointConstraintDoubleData*)constraintData;
+					if (rbA && rbB)
+					{					
+						btVector3 pivotInA,pivotInB;
+						pivotInA.deSerializeDouble(p2pData->m_pivotInA);
+						pivotInB.deSerializeDouble(p2pData->m_pivotInB);
+						constraint = createPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB);
+					} else
+					{
+						btVector3 pivotInA;
+						pivotInA.deSerializeDouble(p2pData->m_pivotInA);
+						constraint = createPoint2PointConstraint(*rbA,pivotInA);
+					}
+				} else
+				{
+					btPoint2PointConstraintFloatData* p2pData = (btPoint2PointConstraintFloatData*)constraintData;
+					if (rbA&& rbB)
+					{					
+						btVector3 pivotInA,pivotInB;
+						pivotInA.deSerializeFloat(p2pData->m_pivotInA);
+						pivotInB.deSerializeFloat(p2pData->m_pivotInB);
+						constraint = createPoint2PointConstraint(*rbA,*rbB,pivotInA,pivotInB);
+					
+					} else
+					{
+						btVector3 pivotInA;
+						pivotInA.deSerializeFloat(p2pData->m_pivotInA);
+						constraint = createPoint2PointConstraint(*rbA,pivotInA);
+					}
+
+				}
+
+				break;
+			}
+		case HINGE_CONSTRAINT_TYPE:
+			{
+				btHingeConstraint* hinge = 0;
+
+				if (bulletFile2->getFlags() & bParse::FD_DOUBLE_PRECISION)
+				{
+					btHingeConstraintDoubleData* hingeData = (btHingeConstraintDoubleData*)constraintData;
+					if (rbA&& rbB)
+					{
+						btTransform rbAFrame,rbBFrame;
+						rbAFrame.deSerializeDouble(hingeData->m_rbAFrame);
+						rbBFrame.deSerializeDouble(hingeData->m_rbBFrame);
+						hinge = createHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0);
+					} else
+					{
+						btTransform rbAFrame;
+						rbAFrame.deSerializeDouble(hingeData->m_rbAFrame);
+						hinge = createHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0);
+					}
+					if (hingeData->m_enableAngularMotor)
+					{
+						hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse);
+					}
+					hinge->setAngularOnly(hingeData->m_angularOnly!=0);
+					hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor));
+				} else
+				{
+					btHingeConstraintFloatData* hingeData = (btHingeConstraintFloatData*)constraintData;
+					if (rbA&& rbB)
+					{
+						btTransform rbAFrame,rbBFrame;
+						rbAFrame.deSerializeFloat(hingeData->m_rbAFrame);
+						rbBFrame.deSerializeFloat(hingeData->m_rbBFrame);
+						hinge = createHingeConstraint(*rbA,*rbB,rbAFrame,rbBFrame,hingeData->m_useReferenceFrameA!=0);
+					} else
+					{
+						btTransform rbAFrame;
+						rbAFrame.deSerializeFloat(hingeData->m_rbAFrame);
+						hinge = createHingeConstraint(*rbA,rbAFrame,hingeData->m_useReferenceFrameA!=0);
+					}
+					if (hingeData->m_enableAngularMotor)
+					{
+						hinge->enableAngularMotor(true,hingeData->m_motorTargetVelocity,hingeData->m_maxMotorImpulse);
+					}
+					hinge->setAngularOnly(hingeData->m_angularOnly!=0);
+					hinge->setLimit(btScalar(hingeData->m_lowerLimit),btScalar(hingeData->m_upperLimit),btScalar(hingeData->m_limitSoftness),btScalar(hingeData->m_biasFactor),btScalar(hingeData->m_relaxationFactor));
+				}
+
+				constraint = hinge;
+				break;
+
+			}
+		case CONETWIST_CONSTRAINT_TYPE:
+			{
+				btConeTwistConstraintData* coneData = (btConeTwistConstraintData*)constraintData;
+				btConeTwistConstraint* coneTwist = 0;
+				
+				if (rbA&& rbB)
+				{
+					btTransform rbAFrame,rbBFrame;
+					rbAFrame.deSerializeFloat(coneData->m_rbAFrame);
+					rbBFrame.deSerializeFloat(coneData->m_rbBFrame);
+					coneTwist = createConeTwistConstraint(*rbA,*rbB,rbAFrame,rbBFrame);
+				} else
+				{
+					btTransform rbAFrame;
+					rbAFrame.deSerializeFloat(coneData->m_rbAFrame);
+					coneTwist = createConeTwistConstraint(*rbA,rbAFrame);
+				}
+				coneTwist->setLimit(coneData->m_swingSpan1,coneData->m_swingSpan2,coneData->m_twistSpan,coneData->m_limitSoftness,coneData->m_biasFactor,coneData->m_relaxationFactor);
+				coneTwist->setDamping(coneData->m_damping);
+				
+				constraint = coneTwist;
+				break;
+			}
+
+		case D6_CONSTRAINT_TYPE:
+			{
+				btGeneric6DofConstraintData* dofData = (btGeneric6DofConstraintData*)constraintData;
+				btGeneric6DofConstraint* dof = 0;
+
+				if (rbA&& rbB)
+				{
+					btTransform rbAFrame,rbBFrame;
+					rbAFrame.deSerializeFloat(dofData->m_rbAFrame);
+					rbBFrame.deSerializeFloat(dofData->m_rbBFrame);
+					dof = createGeneric6DofConstraint(*rbA,*rbB,rbAFrame,rbBFrame,dofData->m_useLinearReferenceFrameA!=0);
+				} else
+				{
+					if (rbB)
+					{
+						btTransform rbBFrame;
+						rbBFrame.deSerializeFloat(dofData->m_rbBFrame);
+						dof = createGeneric6DofConstraint(*rbB,rbBFrame,dofData->m_useLinearReferenceFrameA!=0);
+					} else
+					{
+						printf("Error in btWorldImporter::createGeneric6DofConstraint: missing rbB\n");
+					}
+				}
+
+				if (dof)
+				{
+					btVector3 angLowerLimit,angUpperLimit, linLowerLimit,linUpperlimit;
+					angLowerLimit.deSerializeFloat(dofData->m_angularLowerLimit);
+					angUpperLimit.deSerializeFloat(dofData->m_angularUpperLimit);
+					linLowerLimit.deSerializeFloat(dofData->m_linearLowerLimit);
+					linUpperlimit.deSerializeFloat(dofData->m_linearUpperLimit);
+					
+					dof->setAngularLowerLimit(angLowerLimit);
+					dof->setAngularUpperLimit(angUpperLimit);
+					dof->setLinearLowerLimit(linLowerLimit);
+					dof->setLinearUpperLimit(linUpperlimit);
+				}
+
+				constraint = dof;
+				break;
+			}
+		case SLIDER_CONSTRAINT_TYPE:
+			{
+				btSliderConstraintData* sliderData = (btSliderConstraintData*)constraintData;
+				btSliderConstraint* slider = 0;
+				if (rbA&& rbB)
+				{
+					btTransform rbAFrame,rbBFrame;
+					rbAFrame.deSerializeFloat(sliderData->m_rbAFrame);
+					rbBFrame.deSerializeFloat(sliderData->m_rbBFrame);
+					slider = createSliderConstraint(*rbA,*rbB,rbAFrame,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0);
+				} else
+				{
+					btTransform rbBFrame;
+					rbBFrame.deSerializeFloat(sliderData->m_rbBFrame);
+					slider = createSliderConstraint(*rbB,rbBFrame,sliderData->m_useLinearReferenceFrameA!=0);
+				}
+				slider->setLowerLinLimit(sliderData->m_linearLowerLimit);
+				slider->setUpperLinLimit(sliderData->m_linearUpperLimit);
+				slider->setLowerAngLimit(sliderData->m_angularLowerLimit);
+				slider->setUpperAngLimit(sliderData->m_angularUpperLimit);
+				slider->setUseFrameOffset(sliderData->m_useOffsetForConstraintFrame!=0);
+				constraint = slider;
+				break;
+			}
+		
+		default:
+			{
+				printf("unknown constraint type\n");
+			}
+		};
+
+		if (constraint)
+		{
+			constraint->setDbgDrawSize(constraintData->m_dbgDrawSize);
+			if (constraintData->m_name)
+			{
+				char* newname = duplicateName(constraintData->m_name);
+				m_nameConstraintMap.insert(newname,constraint);
+				m_objectNameMap.insert(constraint,newname);
+			}
+			if(m_dynamicsWorld)
+				m_dynamicsWorld->addConstraint(constraint,constraintData->m_disableCollisionsBetweenLinkedBodies!=0);
+		}
+		
+	}
+	*/
+
+	return true;
+}
+
+
+/* ***ALEX***
+btCollisionObject* btBulletWorldImporter::createCollisionObject(const btTransform& startTransform,btCollisionShape* shape, const char* bodyName)
+{
+	return createRigidBody(false,0,startTransform,shape,bodyName);
+}
+*/
+
+/* ***ALEX***
+btRigidBody*  btBulletWorldImporter::createRigidBody(bool isDynamic, btScalar mass, const btTransform& startTransform,btCollisionShape* shape,const char* bodyName)
+{
+	btVector3 localInertia;
+	localInertia.setZero();
+
+	if (mass)
+		shape->calculateLocalInertia(mass,localInertia);
+	
+	btRigidBody* body = new btRigidBody(mass,0,shape,localInertia);	
+	body->setWorldTransform(startTransform);
+
+	if (m_dynamicsWorld)
+		m_dynamicsWorld->addRigidBody(body);
+	
+	if (bodyName)
+	{
+		char* newname = duplicateName(bodyName);
+		m_objectNameMap.insert(body,newname);
+		m_nameBodyMap.insert(newname,body);
+	}
+	m_allocatedRigidBodies.push_back(body);
+	return body;
+
+}
+*/
+
+btCollisionShape* btBulletWorldImporter::createPlaneShape(const btVector3& planeNormal,btScalar planeConstant)
+{
+	btStaticPlaneShape* shape = new btStaticPlaneShape(planeNormal,planeConstant);
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+btCollisionShape* btBulletWorldImporter::createBoxShape(const btVector3& halfExtents)
+{
+	btBoxShape* shape = new btBoxShape(halfExtents);
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+btCollisionShape* btBulletWorldImporter::createSphereShape(btScalar radius)
+{
+	btSphereShape* shape = new btSphereShape(radius);
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+
+btCollisionShape* btBulletWorldImporter::createCapsuleShapeX(btScalar radius, btScalar height)
+{
+	btCapsuleShapeX* shape = new btCapsuleShapeX(radius,height);
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+btCollisionShape* btBulletWorldImporter::createCapsuleShapeY(btScalar radius, btScalar height)
+{
+	btCapsuleShape* shape = new btCapsuleShape(radius,height);
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+btCollisionShape* btBulletWorldImporter::createCapsuleShapeZ(btScalar radius, btScalar height)
+{
+	btCapsuleShapeZ* shape = new btCapsuleShapeZ(radius,height);
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+btCollisionShape* btBulletWorldImporter::createCylinderShapeX(btScalar radius,btScalar height)
+{
+	btCylinderShapeX* shape = new btCylinderShapeX(btVector3(height,radius,radius));
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+btCollisionShape* btBulletWorldImporter::createCylinderShapeY(btScalar radius,btScalar height)
+{
+	btCylinderShape* shape = new btCylinderShape(btVector3(radius,height,radius));
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+btCollisionShape* btBulletWorldImporter::createCylinderShapeZ(btScalar radius,btScalar height)
+{
+	btCylinderShapeZ* shape = new btCylinderShapeZ(btVector3(radius,radius,height));
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+btTriangleIndexVertexArray*	btBulletWorldImporter::createTriangleMeshContainer()
+{
+	btTriangleIndexVertexArray* in = new btTriangleIndexVertexArray();
+	m_allocatedTriangleIndexArrays.push_back(in);
+	return in;
+}
+
+btOptimizedBvh*	btBulletWorldImporter::createOptimizedBvh()
+{
+	btOptimizedBvh* bvh = new btOptimizedBvh();
+	m_allocatedBvhs.push_back(bvh);
+	return bvh;
+}
+
+
+btTriangleInfoMap* btBulletWorldImporter::createTriangleInfoMap()
+{
+	btTriangleInfoMap* tim = new btTriangleInfoMap();
+	m_allocatedTriangleInfoMaps.push_back(tim);
+	return tim;
+}
+
+btBvhTriangleMeshShape* btBulletWorldImporter::createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh)
+{
+	if (bvh)
+	{
+		btBvhTriangleMeshShape* bvhTriMesh = new btBvhTriangleMeshShape(trimesh,bvh->isQuantized(), false);
+		bvhTriMesh->setOptimizedBvh(bvh);
+		m_allocatedCollisionShapes.push_back(bvhTriMesh);
+		return bvhTriMesh;
+	}
+
+	btBvhTriangleMeshShape* ts = new btBvhTriangleMeshShape(trimesh,true);
+	m_allocatedCollisionShapes.push_back(ts);
+	return ts;
+
+}
+btCollisionShape* btBulletWorldImporter::createConvexTriangleMeshShape(btStridingMeshInterface* trimesh)
+{
+	return 0;
+}
+
+/* ***ALEX***
+btGImpactMeshShape* btBulletWorldImporter::createGimpactShape(btStridingMeshInterface* trimesh)
+{
+	btGImpactMeshShape* shape = new btGImpactMeshShape(trimesh);
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+*/
+
+btConvexHullShape* btBulletWorldImporter::createConvexHullShape()
+{
+	btConvexHullShape* shape = new btConvexHullShape();
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+btCompoundShape* btBulletWorldImporter::createCompoundShape()
+{
+	btCompoundShape* shape = new btCompoundShape();
+	m_allocatedCollisionShapes.push_back(shape);
+	return shape;
+}
+
+/*
+btRigidBody& btBulletWorldImporter::getFixedBody()
+{
+	static btRigidBody s_fixed(0, 0,0);
+	s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+	return s_fixed;
+}
+
+btPoint2PointConstraint* btBulletWorldImporter::createPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB)
+{
+	btPoint2PointConstraint* p2p = new btPoint2PointConstraint(rbA,rbB,pivotInA,pivotInB);
+	m_allocatedConstraints.push_back(p2p);
+	return p2p;
+}
+
+btPoint2PointConstraint* btBulletWorldImporter::createPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA)
+{
+	btPoint2PointConstraint* p2p = new btPoint2PointConstraint(rbA,pivotInA);
+	m_allocatedConstraints.push_back(p2p);
+	return p2p;
+}
+
+
+btHingeConstraint* btBulletWorldImporter::createHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA)
+{
+	btHingeConstraint* hinge = new btHingeConstraint(rbA,rbB,rbAFrame,rbBFrame,useReferenceFrameA);
+	m_allocatedConstraints.push_back(hinge);
+	return hinge;
+}
+
+btHingeConstraint* btBulletWorldImporter::createHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA)
+{
+	btHingeConstraint* hinge = new btHingeConstraint(rbA,rbAFrame,useReferenceFrameA);
+	m_allocatedConstraints.push_back(hinge);
+	return hinge;
+}
+
+btConeTwistConstraint* btBulletWorldImporter::createConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame)
+{
+	btConeTwistConstraint* cone = new btConeTwistConstraint(rbA,rbB,rbAFrame,rbBFrame);
+	m_allocatedConstraints.push_back(cone);
+	return cone;
+}
+
+btConeTwistConstraint* btBulletWorldImporter::createConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame)
+{
+	btConeTwistConstraint* cone = new btConeTwistConstraint(rbA,rbAFrame);
+	m_allocatedConstraints.push_back(cone);
+	return cone;
+}
+
+
+btGeneric6DofConstraint* btBulletWorldImporter::createGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA)
+{
+	btGeneric6DofConstraint* dof = new btGeneric6DofConstraint(rbA,rbB,frameInA,frameInB,useLinearReferenceFrameA);
+	m_allocatedConstraints.push_back(dof);
+	return dof;
+}
+
+btGeneric6DofConstraint* btBulletWorldImporter::createGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB)
+{
+	btGeneric6DofConstraint* dof =  new btGeneric6DofConstraint(rbB,frameInB,useLinearReferenceFrameB);
+	m_allocatedConstraints.push_back(dof);
+	return dof;
+}
+btSliderConstraint* btBulletWorldImporter::createSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA)
+{
+	btSliderConstraint* slider = new btSliderConstraint(rbA,rbB,frameInA,frameInB,useLinearReferenceFrameA);
+	m_allocatedConstraints.push_back(slider);
+	return slider;
+}
+
+btSliderConstraint* btBulletWorldImporter::createSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA)
+{
+	btSliderConstraint* slider = new btSliderConstraint(rbB,frameInB,useLinearReferenceFrameA);
+	m_allocatedConstraints.push_back(slider);
+	return slider;
+}
+*/
+
+	// query for data
+int	btBulletWorldImporter::getNumCollisionShapes() const
+{
+	return m_allocatedCollisionShapes.size();
+}
+
+btCollisionShape* btBulletWorldImporter::getCollisionShapeByIndex(int index)
+{
+	return m_allocatedCollisionShapes[index];
+}
+
+btCollisionShape* btBulletWorldImporter::getCollisionShapeByName(const char* name)
+{
+	btCollisionShape** shapePtr = m_nameShapeMap.find(name);
+	if (shapePtr&& *shapePtr)
+	{
+		return *shapePtr;
+	}
+	return 0;
+}
+/* ***ALEX***
+btRigidBody* btBulletWorldImporter::getRigidBodyByName(const char* name)
+{
+	btRigidBody** bodyPtr = m_nameBodyMap.find(name);
+	if (bodyPtr && *bodyPtr)
+	{
+		return *bodyPtr;
+	}
+	return 0;
+}
+
+btTypedConstraint* btBulletWorldImporter::getConstraintByName(const char* name)
+{
+	btTypedConstraint** constraintPtr = m_nameConstraintMap.find(name);
+	if (constraintPtr && *constraintPtr)
+	{
+		return *constraintPtr;
+	}
+	return 0;
+}
+*/
+
+const char*	btBulletWorldImporter::getNameForPointer(const void* ptr) const
+{
+	const char*const * namePtr = m_objectNameMap.find(ptr);
+	if (namePtr && *namePtr)
+		return *namePtr;
+	return 0;
+}
+
+/* ***ALEX***
+int btBulletWorldImporter::getNumRigidBodies() const
+{
+	return m_allocatedRigidBodies.size();
+}
+
+btCollisionObject* btBulletWorldImporter::getRigidBodyByIndex(int index) const
+{
+	return m_allocatedRigidBodies[index];
+}
+int btBulletWorldImporter::getNumConstraints() const
+{
+	return m_allocatedConstraints.size();
+}
+
+btTypedConstraint* btBulletWorldImporter::getConstraintByIndex(int index) const
+{
+	return m_allocatedConstraints[index];
+}
+*/
+
+int btBulletWorldImporter::getNumBvhs() const
+{
+	return m_allocatedBvhs.size();
+}
+ btOptimizedBvh* btBulletWorldImporter::getBvhByIndex(int index) const
+{
+	return m_allocatedBvhs[index];
+}
+
+int btBulletWorldImporter::getNumTriangleInfoMaps() const
+{
+	return m_allocatedTriangleInfoMaps.size();
+}
+
+btTriangleInfoMap* btBulletWorldImporter::getTriangleInfoMapByIndex(int index) const
+{
+	return m_allocatedTriangleInfoMaps[index];
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/BulletWorldImporter/btBulletWorldImporter.h b/SRC/ChronoEngine/collision/bullet/BulletWorldImporter/btBulletWorldImporter.h
new file mode 100644
index 0000000..705568d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/BulletWorldImporter/btBulletWorldImporter.h
@@ -0,0 +1,188 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2010 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BULLET_WORLD_IMPORTER_H
+#define BULLET_WORLD_IMPORTER_H
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btHashMap.h"
+
+
+class btBulletFile;
+class btCollisionShape;
+class btCollisionObject;
+class btRigidBody;
+class btTypedConstraint;
+class btDynamicsWorld;
+struct ConstraintInput;
+class btRigidBodyColladaInfo;
+struct btCollisionShapeData;
+class btTriangleIndexVertexArray;
+class btStridingMeshInterface;
+struct btStridingMeshInterfaceData;
+class btGImpactMeshShape;
+class btOptimizedBvh;
+struct btTriangleInfoMap;
+class btBvhTriangleMeshShape;
+class btPoint2PointConstraint;
+class btHingeConstraint;
+class btConeTwistConstraint;
+class btGeneric6DofConstraint;
+class btSliderConstraint;
+
+
+
+namespace bParse
+{
+	class btBulletFile;
+	
+};
+
+
+class btBulletWorldImporter
+{
+protected:
+
+	btDynamicsWorld* m_dynamicsWorld;
+
+	bool m_verboseDumpAllTypes;
+
+	btCollisionShape* convertCollisionShape(  btCollisionShapeData* shapeData  );
+
+	btAlignedObjectArray<btCollisionShape*>  m_allocatedCollisionShapes;
+	btAlignedObjectArray<btCollisionObject*> m_allocatedRigidBodies;
+	btAlignedObjectArray<btTypedConstraint*> m_allocatedConstraints;
+	btAlignedObjectArray<btOptimizedBvh*>	 m_allocatedBvhs;
+	btAlignedObjectArray<btTriangleInfoMap*> m_allocatedTriangleInfoMaps;
+	btAlignedObjectArray<btTriangleIndexVertexArray*> m_allocatedTriangleIndexArrays;
+	btAlignedObjectArray<char*>				m_allocatedNames;
+
+	btHashMap<btHashPtr,btOptimizedBvh*>	m_bvhMap;
+	btHashMap<btHashPtr,btTriangleInfoMap*>	m_timMap;
+	
+	btHashMap<btHashString,btCollisionShape*>	m_nameShapeMap;
+	// btHashMap<btHashString,btRigidBody*>	m_nameBodyMap; ***ALEX***
+	// btHashMap<btHashString,btTypedConstraint*>	m_nameConstraintMap; ***ALEX***
+	btHashMap<btHashPtr,const char*>	m_objectNameMap;
+
+	//methods
+
+	btTriangleIndexVertexArray* createMeshInterface(btStridingMeshInterfaceData& meshData);
+
+	// static btRigidBody& getFixedBody(); ***ALEX***
+
+	char*	duplicateName(const char* name);
+
+public:
+	
+	btBulletWorldImporter(btDynamicsWorld* world=0);
+
+	virtual ~btBulletWorldImporter();
+
+	///delete all memory collision shapes, rigid bodies, constraints etc. allocated during the load.
+	///make sure you don't use the dynamics world containing objects after you call this method
+	virtual void deleteAllData();
+
+	bool	loadFile(const char* fileName);
+
+	///the memoryBuffer might be modified (for example if endian swaps are necessary)
+	bool	loadFileFromMemory(char *memoryBuffer, int len);
+
+	bool	loadFileFromMemory(bParse::btBulletFile* file);
+
+	//call make sure bulletFile2 has been parsed, either using btBulletFile::parse or btBulletWorldImporter::loadFileFromMemory
+	bool	convertAllObjects(bParse::btBulletFile* file);
+
+	void	setVerboseMode(bool verboseDumpAllTypes)
+	{
+		m_verboseDumpAllTypes = verboseDumpAllTypes;
+	}
+
+	bool getVerboseMode() const
+	{
+		return m_verboseDumpAllTypes;
+	}
+
+	// query for data
+	int	getNumCollisionShapes() const;
+	btCollisionShape* getCollisionShapeByIndex(int index);
+	/* ***ALEX***
+	int getNumRigidBodies() const;
+	btCollisionObject* getRigidBodyByIndex(int index) const;
+	int getNumConstraints() const;
+	btTypedConstraint* getConstraintByIndex(int index) const;
+	*/
+	int getNumBvhs() const;
+	btOptimizedBvh*  getBvhByIndex(int index) const;
+	int getNumTriangleInfoMaps() const;
+	btTriangleInfoMap* getTriangleInfoMapByIndex(int index) const;
+	
+	// queris involving named objects
+	btCollisionShape* getCollisionShapeByName(const char* name);
+	/* ***ALEX***
+	btRigidBody* getRigidBodyByName(const char* name);
+	btTypedConstraint* getConstraintByName(const char* name);
+	*/
+	const char*	getNameForPointer(const void* ptr) const;
+
+	///those virtuals are called by load and can be overridden by the user
+
+	//bodies
+	//virtual btRigidBody*  createRigidBody(bool isDynamic, 	btScalar mass, 	const btTransform& startTransform,	btCollisionShape* shape,const char* bodyName);
+	//virtual btCollisionObject*  createCollisionObject(	const btTransform& startTransform,	btCollisionShape* shape,const char* bodyName);
+
+	///shapes
+
+	virtual btCollisionShape* createPlaneShape(const btVector3& planeNormal,btScalar planeConstant);
+	virtual btCollisionShape* createBoxShape(const btVector3& halfExtents);
+	virtual btCollisionShape* createSphereShape(btScalar radius);
+	virtual btCollisionShape* createCapsuleShapeX(btScalar radius, btScalar height);
+	virtual btCollisionShape* createCapsuleShapeY(btScalar radius, btScalar height);
+	virtual btCollisionShape* createCapsuleShapeZ(btScalar radius, btScalar height);
+	
+	virtual btCollisionShape* createCylinderShapeX(btScalar radius,btScalar height);
+	virtual btCollisionShape* createCylinderShapeY(btScalar radius,btScalar height);
+	virtual btCollisionShape* createCylinderShapeZ(btScalar radius,btScalar height);
+	virtual class btTriangleIndexVertexArray*	createTriangleMeshContainer();
+	virtual	btBvhTriangleMeshShape* createBvhTriangleMeshShape(btStridingMeshInterface* trimesh, btOptimizedBvh* bvh);
+	virtual btCollisionShape* createConvexTriangleMeshShape(btStridingMeshInterface* trimesh);
+	// virtual btGImpactMeshShape* createGimpactShape(btStridingMeshInterface* trimesh); ***ALEX***
+	virtual class btConvexHullShape* createConvexHullShape();
+	virtual class btCompoundShape* createCompoundShape();
+
+	///acceleration and connectivity structures
+	virtual btOptimizedBvh*	createOptimizedBvh();
+	virtual btTriangleInfoMap* createTriangleInfoMap();
+
+	///constraints
+/* ***ALEX***
+	virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA,btRigidBody& rbB, const btVector3& pivotInA,const btVector3& pivotInB);
+	virtual btPoint2PointConstraint* createPoint2PointConstraint(btRigidBody& rbA,const btVector3& pivotInA);
+	virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA,btRigidBody& rbB, const btTransform& rbAFrame, const btTransform& rbBFrame, bool useReferenceFrameA=false);
+	virtual btHingeConstraint* createHingeConstraint(btRigidBody& rbA,const btTransform& rbAFrame, bool useReferenceFrameA=false);
+	virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA,btRigidBody& rbB,const btTransform& rbAFrame, const btTransform& rbBFrame);
+	virtual btConeTwistConstraint* createConeTwistConstraint(btRigidBody& rbA,const btTransform& rbAFrame);
+	virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+    virtual btGeneric6DofConstraint* createGeneric6DofConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameB);
+	virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbA, btRigidBody& rbB, const btTransform& frameInA, const btTransform& frameInB ,bool useLinearReferenceFrameA);
+    virtual btSliderConstraint* createSliderConstraint(btRigidBody& rbB, const btTransform& frameInB, bool useLinearReferenceFrameA);
+*/
+};
+
+#endif //BULLET_WORLD_IMPORTER_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/Jamfile b/SRC/ChronoEngine/collision/bullet/LinearMath/Jamfile
new file mode 100644
index 0000000..4697841
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/Jamfile
@@ -0,0 +1,10 @@
+
+SubDir TOP src LinearMath ;
+
+Description bulletmath : "Bullet Math Library" ;
+
+Library bulletmath :
+[ Wildcard *.h *.cpp ]
+	;
+
+#InstallHeader [ Wildcard *.h ] ;
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btAabbUtil2.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btAabbUtil2.h
new file mode 100644
index 0000000..532ce1b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btAabbUtil2.h
@@ -0,0 +1,236 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef AABB_UTIL2
+#define AABB_UTIL2
+
+#include "btTransform.h"
+#include "btVector3.h"
+#include "btMinMax.h"
+
+
+
+SIMD_FORCE_INLINE void AabbExpand (btVector3& aabbMin,
+								   btVector3& aabbMax,
+								   const btVector3& expansionMin,
+								   const btVector3& expansionMax)
+{
+	aabbMin = aabbMin + expansionMin;
+	aabbMax = aabbMax + expansionMax;
+}
+
+/// conservative test for overlap between two aabbs
+SIMD_FORCE_INLINE bool TestPointAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
+								const btVector3 &point)
+{
+	bool overlap = true;
+	overlap = (aabbMin1.getX() > point.getX() || aabbMax1.getX() < point.getX()) ? false : overlap;
+	overlap = (aabbMin1.getZ() > point.getZ() || aabbMax1.getZ() < point.getZ()) ? false : overlap;
+	overlap = (aabbMin1.getY() > point.getY() || aabbMax1.getY() < point.getY()) ? false : overlap;
+	return overlap;
+}
+
+
+/// conservative test for overlap between two aabbs
+SIMD_FORCE_INLINE bool TestAabbAgainstAabb2(const btVector3 &aabbMin1, const btVector3 &aabbMax1,
+								const btVector3 &aabbMin2, const btVector3 &aabbMax2)
+{
+	bool overlap = true;
+	overlap = (aabbMin1.getX() > aabbMax2.getX() || aabbMax1.getX() < aabbMin2.getX()) ? false : overlap;
+	overlap = (aabbMin1.getZ() > aabbMax2.getZ() || aabbMax1.getZ() < aabbMin2.getZ()) ? false : overlap;
+	overlap = (aabbMin1.getY() > aabbMax2.getY() || aabbMax1.getY() < aabbMin2.getY()) ? false : overlap;
+	return overlap;
+}
+
+/// conservative test for overlap between triangle and aabb
+SIMD_FORCE_INLINE bool TestTriangleAgainstAabb2(const btVector3 *vertices,
+									const btVector3 &aabbMin, const btVector3 &aabbMax)
+{
+	const btVector3 &p1 = vertices[0];
+	const btVector3 &p2 = vertices[1];
+	const btVector3 &p3 = vertices[2];
+
+	if (btMin(btMin(p1[0], p2[0]), p3[0]) > aabbMax[0]) return false;
+	if (btMax(btMax(p1[0], p2[0]), p3[0]) < aabbMin[0]) return false;
+
+	if (btMin(btMin(p1[2], p2[2]), p3[2]) > aabbMax[2]) return false;
+	if (btMax(btMax(p1[2], p2[2]), p3[2]) < aabbMin[2]) return false;
+  
+	if (btMin(btMin(p1[1], p2[1]), p3[1]) > aabbMax[1]) return false;
+	if (btMax(btMax(p1[1], p2[1]), p3[1]) < aabbMin[1]) return false;
+	return true;
+}
+
+
+SIMD_FORCE_INLINE int	btOutcode(const btVector3& p,const btVector3& halfExtent) 
+{
+	return (p.getX()  < -halfExtent.getX() ? 0x01 : 0x0) |    
+		   (p.getX() >  halfExtent.getX() ? 0x08 : 0x0) |
+		   (p.getY() < -halfExtent.getY() ? 0x02 : 0x0) |    
+		   (p.getY() >  halfExtent.getY() ? 0x10 : 0x0) |
+		   (p.getZ() < -halfExtent.getZ() ? 0x4 : 0x0) |    
+		   (p.getZ() >  halfExtent.getZ() ? 0x20 : 0x0);
+}
+
+
+
+SIMD_FORCE_INLINE bool btRayAabb2(const btVector3& rayFrom,
+								  const btVector3& rayInvDirection,
+								  const unsigned int raySign[3],
+								  const btVector3 bounds[2],
+								  btScalar& tmin,
+								  btScalar lambda_min,
+								  btScalar lambda_max)
+{
+	btScalar tmax, tymin, tymax, tzmin, tzmax;
+	tmin = (bounds[raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+	tmax = (bounds[1-raySign[0]].getX() - rayFrom.getX()) * rayInvDirection.getX();
+	tymin = (bounds[raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+	tymax = (bounds[1-raySign[1]].getY() - rayFrom.getY()) * rayInvDirection.getY();
+
+	if ( (tmin > tymax) || (tymin > tmax) )
+		return false;
+
+	if (tymin > tmin)
+		tmin = tymin;
+
+	if (tymax < tmax)
+		tmax = tymax;
+
+	tzmin = (bounds[raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+	tzmax = (bounds[1-raySign[2]].getZ() - rayFrom.getZ()) * rayInvDirection.getZ();
+
+	if ( (tmin > tzmax) || (tzmin > tmax) )
+		return false;
+	if (tzmin > tmin)
+		tmin = tzmin;
+	if (tzmax < tmax)
+		tmax = tzmax;
+	return ( (tmin < lambda_max) && (tmax > lambda_min) );
+}
+
+SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, 
+								 const btVector3& rayTo, 
+								 const btVector3& aabbMin, 
+								 const btVector3& aabbMax,
+					  btScalar& param, btVector3& normal) 
+{
+	btVector3 aabbHalfExtent = (aabbMax-aabbMin)* btScalar(0.5);
+	btVector3 aabbCenter = (aabbMax+aabbMin)* btScalar(0.5);
+	btVector3	source = rayFrom - aabbCenter;
+	btVector3	target = rayTo - aabbCenter;
+	int	sourceOutcode = btOutcode(source,aabbHalfExtent);
+	int targetOutcode = btOutcode(target,aabbHalfExtent);
+	if ((sourceOutcode & targetOutcode) == 0x0)
+	{
+		btScalar lambda_enter = btScalar(0.0);
+		btScalar lambda_exit  = param;
+		btVector3 r = target - source;
+		int i;
+		btScalar	normSign = 1;
+		btVector3	hitNormal(0,0,0);
+		int bit=1;
+
+		for (int j=0;j<2;j++)
+		{
+			for (i = 0; i != 3; ++i)
+			{
+				if (sourceOutcode & bit)
+				{
+					btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+					if (lambda_enter <= lambda)
+					{
+						lambda_enter = lambda;
+						hitNormal.setValue(0,0,0);
+						hitNormal[i] = normSign;
+					}
+				}
+				else if (targetOutcode & bit) 
+				{
+					btScalar lambda = (-source[i] - aabbHalfExtent[i]*normSign) / r[i];
+					btSetMin(lambda_exit, lambda);
+				}
+				bit<<=1;
+			}
+			normSign = btScalar(-1.);
+		}
+		if (lambda_enter <= lambda_exit)
+		{
+			param = lambda_enter;
+			normal = hitNormal;
+			return true;
+		}
+	}
+	return false;
+}
+
+
+
+SIMD_FORCE_INLINE	void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+{
+	btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin);
+	btMatrix3x3 abs_b = t.getBasis().absolute();  
+	btVector3 center = t.getOrigin();
+	btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin),
+		   abs_b[1].dot(halfExtentsWithMargin),
+		  abs_b[2].dot(halfExtentsWithMargin));
+	aabbMinOut = center - extent;
+	aabbMaxOut = center + extent;
+}
+
+
+SIMD_FORCE_INLINE	void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut)
+{
+		btAssert(localAabbMin.getX() <= localAabbMax.getX());
+		btAssert(localAabbMin.getY() <= localAabbMax.getY());
+		btAssert(localAabbMin.getZ() <= localAabbMax.getZ());
+		btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin);
+		localHalfExtents+=btVector3(margin,margin,margin);
+
+		btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin);
+		btMatrix3x3 abs_b = trans.getBasis().absolute();  
+		btVector3 center = trans(localCenter);
+		btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents),
+			   abs_b[1].dot(localHalfExtents),
+			  abs_b[2].dot(localHalfExtents));
+		aabbMinOut = center-extent;
+		aabbMaxOut = center+extent;
+}
+
+#define USE_BANCHLESS 1
+#ifdef USE_BANCHLESS
+	//This block replaces the block below and uses no branches, and replaces the 8 bit return with a 32 bit return for improved performance (~3x on XBox 360)
+	SIMD_FORCE_INLINE unsigned testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+	{		
+		return static_cast<unsigned int>(btSelect((unsigned)((aabbMin1[0] <= aabbMax2[0]) & (aabbMax1[0] >= aabbMin2[0])
+			& (aabbMin1[2] <= aabbMax2[2]) & (aabbMax1[2] >= aabbMin2[2])
+			& (aabbMin1[1] <= aabbMax2[1]) & (aabbMax1[1] >= aabbMin2[1])),
+			1, 0));
+	}
+#else
+	SIMD_FORCE_INLINE bool testQuantizedAabbAgainstQuantizedAabb(const unsigned short int* aabbMin1,const unsigned short int* aabbMax1,const unsigned short int* aabbMin2,const unsigned short int* aabbMax2)
+	{
+		bool overlap = true;
+		overlap = (aabbMin1[0] > aabbMax2[0] || aabbMax1[0] < aabbMin2[0]) ? false : overlap;
+		overlap = (aabbMin1[2] > aabbMax2[2] || aabbMax1[2] < aabbMin2[2]) ? false : overlap;
+		overlap = (aabbMin1[1] > aabbMax2[1] || aabbMax1[1] < aabbMin2[1]) ? false : overlap;
+		return overlap;
+	}
+#endif //USE_BANCHLESS
+
+#endif
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedAllocator.cpp b/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedAllocator.cpp
new file mode 100644
index 0000000..189b759
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedAllocator.cpp
@@ -0,0 +1,182 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btAlignedAllocator.h"
+
+int gNumAlignedAllocs = 0;
+int gNumAlignedFree = 0;
+int gTotalBytesAlignedAllocs = 0;//detect memory leaks
+
+static void *btAllocDefault(size_t size)
+{
+	return malloc(size);
+}
+
+static void btFreeDefault(void *ptr)
+{
+	free(ptr);
+}
+
+static btAllocFunc *sAllocFunc = btAllocDefault;
+static btFreeFunc *sFreeFunc = btFreeDefault;
+
+
+
+#if defined (BT_HAS_ALIGNED_ALLOCATOR)
+#include <malloc.h>
+static void *btAlignedAllocDefault(size_t size, int alignment)
+{
+	return _aligned_malloc(size, (size_t)alignment);
+}
+
+static void btAlignedFreeDefault(void *ptr)
+{
+	_aligned_free(ptr);
+}
+#elif defined(__CELLOS_LV2__)
+#include <stdlib.h>
+
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+	return memalign(alignment, size);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+	free(ptr);
+}
+#else
+static inline void *btAlignedAllocDefault(size_t size, int alignment)
+{
+  void *ret;
+  char *real;
+  unsigned long offset;
+
+  real = (char *)sAllocFunc(size + sizeof(void *) + (alignment-1));
+  if (real) {
+    offset = (alignment - (unsigned long)(real + sizeof(void *))) & (alignment-1);
+    ret = (void *)((real + sizeof(void *)) + offset);
+    *((void **)(ret)-1) = (void *)(real);
+  } else {
+    ret = (void *)(real);
+  }
+  return (ret);
+}
+
+static inline void btAlignedFreeDefault(void *ptr)
+{
+  void* real;
+
+  if (ptr) {
+    real = *((void **)(ptr)-1);
+    sFreeFunc(real);
+  }
+}
+#endif
+
+
+static btAlignedAllocFunc *sAlignedAllocFunc = btAlignedAllocDefault;
+static btAlignedFreeFunc *sAlignedFreeFunc = btAlignedFreeDefault;
+
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc)
+{
+  sAlignedAllocFunc = allocFunc ? allocFunc : btAlignedAllocDefault;
+  sAlignedFreeFunc = freeFunc ? freeFunc : btAlignedFreeDefault;
+}
+
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc)
+{
+  sAllocFunc = allocFunc ? allocFunc : btAllocDefault;
+  sFreeFunc = freeFunc ? freeFunc : btFreeDefault;
+}
+
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+//this generic allocator provides the total allocated number of bytes
+#include <stdio.h>
+
+void*   btAlignedAllocInternal  (size_t size, int alignment,int line,char* filename)
+{
+ void *ret;
+ char *real;
+ unsigned long offset;
+
+ gTotalBytesAlignedAllocs += size;
+ gNumAlignedAllocs++;
+
+ 
+ real = (char *)sAllocFunc(size + 2*sizeof(void *) + (alignment-1));
+ if (real) {
+   offset = (alignment - (unsigned long)(real + 2*sizeof(void *))) &
+(alignment-1);
+   ret = (void *)((real + 2*sizeof(void *)) + offset);
+   *((void **)(ret)-1) = (void *)(real);
+       *((int*)(ret)-2) = size;
+
+ } else {
+   ret = (void *)(real);//??
+ }
+
+ printf("allocation#%d at address %x, from %s,line %d, size %d\n",gNumAlignedAllocs,real, filename,line,size);
+
+ int* ptr = (int*)ret;
+ *ptr = 12;
+ return (ret);
+}
+
+void    btAlignedFreeInternal   (void* ptr,int line,char* filename)
+{
+
+ void* real;
+ gNumAlignedFree++;
+
+ if (ptr) {
+   real = *((void **)(ptr)-1);
+       int size = *((int*)(ptr)-2);
+       gTotalBytesAlignedAllocs -= size;
+
+	   printf("free #%d at address %x, from %s,line %d, size %d\n",gNumAlignedFree,real, filename,line,size);
+
+   sFreeFunc(real);
+ } else
+ {
+	 printf("NULL ptr\n");
+ }
+}
+
+#else //BT_DEBUG_MEMORY_ALLOCATIONS
+
+void*	btAlignedAllocInternal	(size_t size, int alignment)
+{
+	gNumAlignedAllocs++;
+	void* ptr;
+	ptr = sAlignedAllocFunc(size, alignment);
+//	printf("btAlignedAllocInternal %d, %x\n",size,ptr);
+	return ptr;
+}
+
+void	btAlignedFreeInternal	(void* ptr)
+{
+	if (!ptr)
+	{
+		return;
+	}
+
+	gNumAlignedFree++;
+//	printf("btAlignedFreeInternal %x\n",ptr);
+	sAlignedFreeFunc(ptr);
+}
+
+#endif //BT_DEBUG_MEMORY_ALLOCATIONS
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedAllocator.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedAllocator.h
new file mode 100644
index 0000000..f168f3c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedAllocator.h
@@ -0,0 +1,107 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_ALIGNED_ALLOCATOR
+#define BT_ALIGNED_ALLOCATOR
+
+///we probably replace this with our own aligned memory allocator
+///so we replace _aligned_malloc and _aligned_free with our own
+///that is better portable and more predictable
+
+#include "btScalar.h"
+//#define BT_DEBUG_MEMORY_ALLOCATIONS 1
+#ifdef BT_DEBUG_MEMORY_ALLOCATIONS
+
+#define btAlignedAlloc(a,b) \
+		btAlignedAllocInternal(a,b,__LINE__,__FILE__)
+
+#define btAlignedFree(ptr) \
+		btAlignedFreeInternal(ptr,__LINE__,__FILE__)
+
+void*	btAlignedAllocInternal	(size_t size, int alignment,int line,char* filename);
+
+void	btAlignedFreeInternal	(void* ptr,int line,char* filename);
+
+#else
+	void*	btAlignedAllocInternal	(size_t size, int alignment);
+	void	btAlignedFreeInternal	(void* ptr);
+
+	#define btAlignedAlloc(size,alignment) btAlignedAllocInternal(size,alignment)
+	#define btAlignedFree(ptr) btAlignedFreeInternal(ptr)
+
+#endif
+typedef int	size_type;
+
+typedef void *(btAlignedAllocFunc)(size_t size, int alignment);
+typedef void (btAlignedFreeFunc)(void *memblock);
+typedef void *(btAllocFunc)(size_t size);
+typedef void (btFreeFunc)(void *memblock);
+
+///The developer can let all Bullet memory allocations go through a custom memory allocator, using btAlignedAllocSetCustom
+void btAlignedAllocSetCustom(btAllocFunc *allocFunc, btFreeFunc *freeFunc);
+///If the developer has already an custom aligned allocator, then btAlignedAllocSetCustomAligned can be used. The default aligned allocator pre-allocates extra memory using the non-aligned allocator, and instruments it.
+void btAlignedAllocSetCustomAligned(btAlignedAllocFunc *allocFunc, btAlignedFreeFunc *freeFunc);
+
+
+///The btAlignedAllocator is a portable class for aligned memory allocations.
+///Default implementations for unaligned and aligned allocations can be overridden by a custom allocator using btAlignedAllocSetCustom and btAlignedAllocSetCustomAligned.
+template < typename T , unsigned Alignment >
+class btAlignedAllocator {
+	
+	typedef btAlignedAllocator< T , Alignment > self_type;
+	
+public:
+
+	//just going down a list:
+	btAlignedAllocator() {}
+	/*
+	btAlignedAllocator( const self_type & ) {}
+	*/
+
+	template < typename Other >
+	btAlignedAllocator( const btAlignedAllocator< Other , Alignment > & ) {}
+
+	typedef const T*         const_pointer;
+	typedef const T&         const_reference;
+	typedef T*               pointer;
+	typedef T&               reference;
+	typedef T                value_type;
+
+	pointer       address   ( reference        ref ) const                           { return &ref; }
+	const_pointer address   ( const_reference  ref ) const                           { return &ref; }
+	pointer       allocate  ( size_type        n   , const_pointer *      hint = 0 ) {
+		(void)hint;
+		return reinterpret_cast< pointer >(btAlignedAlloc( sizeof(value_type) * n , Alignment ));
+	}
+	void          construct ( pointer          ptr , const value_type &   value    ) { new (ptr) value_type( value ); }
+	void          deallocate( pointer          ptr ) {
+		btAlignedFree( reinterpret_cast< void * >( ptr ) );
+	}
+	void          destroy   ( pointer          ptr )                                 { ptr->~value_type(); }
+	
+
+	template < typename O > struct rebind {
+		typedef btAlignedAllocator< O , Alignment > other;
+	};
+	template < typename O >
+	self_type & operator=( const btAlignedAllocator< O , Alignment > & ) { return *this; }
+
+	friend bool operator==( const self_type & , const self_type & ) { return true; }
+};
+
+
+
+#endif //BT_ALIGNED_ALLOCATOR
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedObjectArray.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedObjectArray.h
new file mode 100644
index 0000000..d5716ef
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btAlignedObjectArray.h
@@ -0,0 +1,471 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_OBJECT_ARRAY__
+#define BT_OBJECT_ARRAY__
+
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btAlignedAllocator.h"
+
+///If the platform doesn't support placement new, you can disable BT_USE_PLACEMENT_NEW
+///then the btAlignedObjectArray doesn't support objects with virtual methods, and non-trivial constructors/destructors
+///You can enable BT_USE_MEMCPY, then swapping elements in the array will use memcpy instead of operator=
+///see discussion here: http://continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1231 and
+///http://www.continuousphysics.com/Bullet/phpBB2/viewtopic.php?t=1240
+
+#define BT_USE_PLACEMENT_NEW 1
+//#define BT_USE_MEMCPY 1 //disable, because it is cumbersome to find out for each platform where memcpy is defined. It can be in <memory.h> or <string.h> or otherwise...
+
+#ifdef BT_USE_MEMCPY
+#include <memory.h>
+#include <string.h>
+#endif //BT_USE_MEMCPY
+
+#ifdef BT_USE_PLACEMENT_NEW
+#include <new> //for placement new
+#endif //BT_USE_PLACEMENT_NEW
+
+
+///The btAlignedObjectArray template class uses a subset of the stl::vector interface for its methods
+///It is developed to replace stl::vector to avoid portability issues, including STL alignment issues to add SIMD/SSE data
+template <typename T> 
+//template <class T> 
+class btAlignedObjectArray
+{
+	btAlignedAllocator<T , 16>	m_allocator;
+
+	int					m_size;
+	int					m_capacity;
+	T*					m_data;
+	//PCK: added this line
+	bool				m_ownsMemory;
+
+	protected:
+		SIMD_FORCE_INLINE	int	allocSize(int size)
+		{
+			return (size ? size*2 : 1);
+		}
+		SIMD_FORCE_INLINE	void	copy(int start,int end, T* dest) const
+		{
+			int i;
+			for (i=start;i<end;++i)
+#ifdef BT_USE_PLACEMENT_NEW
+				new (&dest[i]) T(m_data[i]);
+#else
+				dest[i] = m_data[i];
+#endif //BT_USE_PLACEMENT_NEW
+		}
+
+		SIMD_FORCE_INLINE	void	init()
+		{
+			//PCK: added this line
+			m_ownsMemory = true;
+			m_data = 0;
+			m_size = 0;
+			m_capacity = 0;
+		}
+		SIMD_FORCE_INLINE	void	destroy(int first,int last)
+		{
+			int i;
+			for (i=first; i<last;i++)
+			{
+				m_data[i].~T();
+			}
+		}
+
+		SIMD_FORCE_INLINE	void* allocate(int size)
+		{
+			if (size)
+				return m_allocator.allocate(size);
+			return 0;
+		}
+
+		SIMD_FORCE_INLINE	void	deallocate()
+		{
+			if(m_data)	{
+				//PCK: enclosed the deallocation in this block
+				if (m_ownsMemory)
+				{
+					m_allocator.deallocate(m_data);
+				}
+				m_data = 0;
+			}
+		}
+
+	
+
+
+	public:
+		
+		btAlignedObjectArray()
+		{
+			init();
+		}
+
+		~btAlignedObjectArray()
+		{
+			clear();
+		}
+
+		///Generally it is best to avoid using the copy constructor of an btAlignedObjectArray, and use a (const) reference to the array instead.
+		btAlignedObjectArray(const btAlignedObjectArray& otherArray)
+		{
+			init();
+
+			int otherSize = otherArray.size();
+			resize (otherSize);
+			otherArray.copy(0, otherSize, m_data);
+		}
+
+		
+		
+		/// return the number of elements in the array
+		SIMD_FORCE_INLINE	int size() const
+		{	
+			return m_size;
+		}
+		
+		SIMD_FORCE_INLINE const T& at(int n) const
+		{
+			return m_data[n];
+		}
+
+		SIMD_FORCE_INLINE T& at(int n)
+		{
+			return m_data[n];
+		}
+
+		SIMD_FORCE_INLINE const T& operator[](int n) const
+		{
+			return m_data[n];
+		}
+
+		SIMD_FORCE_INLINE T& operator[](int n)
+		{
+			return m_data[n];
+		}
+		
+
+		///clear the array, deallocated memory. Generally it is better to use array.resize(0), to reduce performance overhead of run-time memory (de)allocations.
+		SIMD_FORCE_INLINE	void	clear()
+		{
+			destroy(0,size());
+			
+			deallocate();
+			
+			init();
+		}
+
+		SIMD_FORCE_INLINE	void	pop_back()
+		{
+			m_size--;
+			m_data[m_size].~T();
+		}
+
+		///resize changes the number of elements in the array. If the new size is larger, the new elements will be constructed using the optional second argument.
+		///when the new number of elements is smaller, the destructor will be called, but memory will not be freed, to reduce performance overhead of run-time memory (de)allocations.
+		SIMD_FORCE_INLINE	void	resize(int newsize, const T& fillData=T())
+		{
+			int curSize = size();
+
+			if (newsize < curSize)
+			{
+				for(int i = newsize; i < curSize; i++)
+				{
+					m_data[i].~T();
+				}
+			} else
+			{
+				if (newsize > size())
+				{
+					reserve(newsize);
+				}
+#ifdef BT_USE_PLACEMENT_NEW
+				for (int i=curSize;i<newsize;i++)
+				{
+					new ( &m_data[i]) T(fillData);
+				}
+#endif //BT_USE_PLACEMENT_NEW
+
+			}
+
+			m_size = newsize;
+		}
+	
+		SIMD_FORCE_INLINE	T&  expandNonInitializing( )
+		{	
+			int sz = size();
+			if( sz == capacity() )
+			{
+				reserve( allocSize(size()) );
+			}
+			m_size++;
+
+			return m_data[sz];		
+		}
+
+
+		SIMD_FORCE_INLINE	T&  expand( const T& fillValue=T())
+		{	
+			int sz = size();
+			if( sz == capacity() )
+			{
+				reserve( allocSize(size()) );
+			}
+			m_size++;
+#ifdef BT_USE_PLACEMENT_NEW
+			new (&m_data[sz]) T(fillValue); //use the in-place new (not really allocating heap memory)
+#endif
+
+			return m_data[sz];		
+		}
+
+
+		SIMD_FORCE_INLINE	void push_back(const T& _Val)
+		{	
+			int sz = size();
+			if( sz == capacity() )
+			{
+				reserve( allocSize(size()) );
+			}
+			
+#ifdef BT_USE_PLACEMENT_NEW
+			new ( &m_data[m_size] ) T(_Val);
+#else
+			m_data[size()] = _Val;			
+#endif //BT_USE_PLACEMENT_NEW
+
+			m_size++;
+		}
+
+	
+		/// return the pre-allocated (reserved) elements, this is at least as large as the total number of elements,see size() and reserve()
+		SIMD_FORCE_INLINE	int capacity() const
+		{	
+			return m_capacity;
+		}
+		
+		SIMD_FORCE_INLINE	void reserve(int _Count)
+		{	// determine new minimum length of allocated storage
+			if (capacity() < _Count)
+			{	// not enough room, reallocate
+				T*	s = (T*)allocate(_Count);
+
+				copy(0, size(), s);
+
+				destroy(0,size());
+
+				deallocate();
+				
+				//PCK: added this line
+				m_ownsMemory = true;
+
+				m_data = s;
+				
+				m_capacity = _Count;
+
+			}
+		}
+
+
+		class less
+		{
+			public:
+
+				bool operator() ( const T& a, const T& b )
+				{
+					return ( a < b );
+				}
+		};
+	
+		template <typename L>
+		void quickSortInternal(L CompareFunc,int lo, int hi)
+		{
+		//  lo is the lower index, hi is the upper index
+		//  of the region of array a that is to be sorted
+			int i=lo, j=hi;
+			T x=m_data[(lo+hi)/2];
+
+			//  partition
+			do
+			{    
+				while (CompareFunc(m_data[i],x)) 
+					i++; 
+				while (CompareFunc(x,m_data[j])) 
+					j--;
+				if (i<=j)
+				{
+					swap(i,j);
+					i++; j--;
+				}
+			} while (i<=j);
+
+			//  recursion
+			if (lo<j) 
+				quickSortInternal( CompareFunc, lo, j);
+			if (i<hi) 
+				quickSortInternal( CompareFunc, i, hi);
+		}
+
+
+		template <typename L>
+		void quickSort(L CompareFunc)
+		{
+			//don't sort 0 or 1 elements
+			if (size()>1)
+			{
+				quickSortInternal(CompareFunc,0,size()-1);
+			}
+		}
+
+
+		///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+		template <typename L>
+		void downHeap(T *pArr, int k, int n,L CompareFunc)
+		{
+			/*  PRE: a[k+1..N] is a heap */
+			/* POST:  a[k..N]  is a heap */
+			
+			T temp = pArr[k - 1];
+			/* k has child(s) */
+			while (k <= n/2) 
+			{
+				int child = 2*k;
+				
+				if ((child < n) && CompareFunc(pArr[child - 1] , pArr[child]))
+				{
+					child++;
+				}
+				/* pick larger child */
+				if (CompareFunc(temp , pArr[child - 1]))
+				{
+					/* move child up */
+					pArr[k - 1] = pArr[child - 1];
+					k = child;
+				}
+				else
+				{
+					break;
+				}
+			}
+			pArr[k - 1] = temp;
+		} /*downHeap*/
+
+		void	swap(int index0,int index1)
+		{
+#ifdef BT_USE_MEMCPY
+			char	temp[sizeof(T)];
+			memcpy(temp,&m_data[index0],sizeof(T));
+			memcpy(&m_data[index0],&m_data[index1],sizeof(T));
+			memcpy(&m_data[index1],temp,sizeof(T));
+#else
+			T temp = m_data[index0];
+			m_data[index0] = m_data[index1];
+			m_data[index1] = temp;
+#endif //BT_USE_PLACEMENT_NEW
+
+		}
+
+	template <typename L>
+	void heapSort(L CompareFunc)
+	{
+		/* sort a[0..N-1],  N.B. 0 to N-1 */
+		int k;
+		int n = m_size;
+		for (k = n/2; k > 0; k--) 
+		{
+			downHeap(m_data, k, n, CompareFunc);
+		}
+
+		/* a[1..N] is now a heap */
+		while ( n>=1 ) 
+		{
+			swap(0,n-1); /* largest of a[0..n-1] */
+
+
+			n = n - 1;
+			/* restore a[1..i-1] heap */
+			downHeap(m_data, 1, n, CompareFunc);
+		} 
+	}
+
+	///non-recursive binary search, assumes sorted array
+	int	findBinarySearch(const T& key) const
+	{
+		int first = 0;
+		int last = size();
+
+		//assume sorted array
+		while (first <= last) {
+			int mid = (first + last) / 2;  // compute mid point.
+			if (key > m_data[mid]) 
+				first = mid + 1;  // repeat search in top half.
+			else if (key < m_data[mid]) 
+				last = mid - 1; // repeat search in bottom half.
+			else
+				return mid;     // found it. return position /////
+		}
+		return size();    // failed to find key
+	}
+
+
+	int	findLinearSearch(const T& key) const
+	{
+		int index=size();
+		int i;
+
+		for (i=0;i<size();i++)
+		{
+			if (m_data[i] == key)
+			{
+				index = i;
+				break;
+			}
+		}
+		return index;
+	}
+
+	void	remove(const T& key)
+	{
+
+		int findIndex = findLinearSearch(key);
+		if (findIndex<size())
+		{
+			swap( findIndex,size()-1);
+			pop_back();
+		}
+	}
+
+	//PCK: whole function
+	void initializeFromBuffer(void *buffer, int size, int capacity)
+	{
+		clear();
+		m_ownsMemory = false;
+		m_data = (T*)buffer;
+		m_size = size;
+		m_capacity = capacity;
+	}
+
+	void copyFromArray(const btAlignedObjectArray& otherArray)
+	{
+		int otherSize = otherArray.size();
+		resize (otherSize);
+		otherArray.copy(0, otherSize, m_data);
+	}
+
+};
+
+#endif //BT_OBJECT_ARRAY__
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btConvexHull.cpp b/SRC/ChronoEngine/collision/bullet/LinearMath/btConvexHull.cpp
new file mode 100644
index 0000000..532d76d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btConvexHull.cpp
@@ -0,0 +1,1174 @@
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2003-2006 Stan Melax http://www.melax.com/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <string.h>
+
+#include "btConvexHull.h"
+#include "btAlignedObjectArray.h"
+#include "btMinMax.h"
+#include "btVector3.h"
+
+
+
+template <class T>
+void Swap(T &a,T &b)
+{
+	T tmp = a;
+	a=b;
+	b=tmp;
+}
+
+
+//----------------------------------
+
+class int3  
+{
+public:
+	int x,y,z;
+	int3(){};
+	int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;}
+	const int& operator[](int i) const {return (&x)[i];}
+	int& operator[](int i) {return (&x)[i];}
+};
+
+
+//------- btPlane ----------
+
+
+inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);}
+inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
+inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); }
+
+
+//--------- Utility Functions ------
+
+btVector3  PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1);
+btVector3  PlaneProject(const btPlane &plane, const btVector3 &point);
+
+btVector3  ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2);
+btVector3  ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2)
+{
+	btVector3 N1 = p0.normal;
+	btVector3 N2 = p1.normal;
+	btVector3 N3 = p2.normal;
+
+	btVector3 n2n3; n2n3 = N2.cross(N3);
+	btVector3 n3n1; n3n1 = N3.cross(N1);
+	btVector3 n1n2; n1n2 = N1.cross(N2);
+
+	btScalar quotient = (N1.dot(n2n3));
+
+	btAssert(btFabs(quotient) > btScalar(0.000001));
+	
+	quotient = btScalar(-1.) / quotient;
+	n2n3 *= p0.dist;
+	n3n1 *= p1.dist;
+	n1n2 *= p2.dist;
+	btVector3 potentialVertex = n2n3;
+	potentialVertex += n3n1;
+	potentialVertex += n1n2;
+	potentialVertex *= quotient;
+
+	btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ());
+	return result;
+
+}
+
+btScalar   DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL);
+btVector3  TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2);
+btVector3  NormalOf(const btVector3 *vert, const int n);
+
+
+btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1)
+{
+	// returns the point where the line p0-p1 intersects the plane n&d
+				static btVector3 dif;
+		dif = p1-p0;
+				btScalar dn= btDot(plane.normal,dif);
+				btScalar t = -(plane.dist+btDot(plane.normal,p0) )/dn;
+				return p0 + (dif*t);
+}
+
+btVector3 PlaneProject(const btPlane &plane, const btVector3 &point)
+{
+	return point - plane.normal * (btDot(point,plane.normal)+plane.dist);
+}
+
+btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2)
+{
+	// return the normal of the triangle
+	// inscribed by v0, v1, and v2
+	btVector3 cp=btCross(v1-v0,v2-v1);
+	btScalar m=cp.length();
+	if(m==0) return btVector3(1,0,0);
+	return cp*(btScalar(1.0)/m);
+}
+
+
+btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint)
+{
+	static btVector3 cp;
+	cp = btCross(udir,vdir).normalized();
+
+	btScalar distu = -btDot(cp,ustart);
+	btScalar distv = -btDot(cp,vstart);
+	btScalar dist = (btScalar)fabs(distu-distv);
+	if(upoint) 
+		{
+		btPlane plane;
+		plane.normal = btCross(vdir,cp).normalized();
+		plane.dist = -btDot(plane.normal,vstart);
+		*upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
+	}
+	if(vpoint) 
+		{
+		btPlane plane;
+		plane.normal = btCross(udir,cp).normalized();
+		plane.dist = -btDot(plane.normal,ustart);
+		*vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
+	}
+	return dist;
+}
+
+
+
+
+
+
+
+#define COPLANAR   (0)
+#define UNDER      (1)
+#define OVER       (2)
+#define SPLIT      (OVER|UNDER)
+#define PAPERWIDTH (btScalar(0.001))
+
+btScalar planetestepsilon = PAPERWIDTH;
+
+
+
+typedef ConvexH::HalfEdge HalfEdge;
+
+ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size)
+{
+	vertices.resize(vertices_size);
+	edges.resize(edges_size);
+	facets.resize(facets_size);
+}
+
+
+int PlaneTest(const btPlane &p, const btVector3 &v);
+int PlaneTest(const btPlane &p, const btVector3 &v) {
+	btScalar a  = btDot(v,p.normal)+p.dist;
+	int   flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
+	return flag;
+}
+
+int SplitTest(ConvexH &convex,const btPlane &plane);
+int SplitTest(ConvexH &convex,const btPlane &plane) {
+	int flag=0;
+	for(int i=0;i<convex.vertices.size();i++) {
+		flag |= PlaneTest(plane,convex.vertices[i]);
+	}
+	return flag;
+}
+
+class VertFlag
+{
+public:
+	unsigned char planetest;
+	unsigned char junk;
+	unsigned char undermap;
+	unsigned char overmap;
+};
+class EdgeFlag 
+{
+public:
+	unsigned char planetest;
+	unsigned char fixes;
+	short undermap;
+	short overmap;
+};
+class PlaneFlag
+{
+public:
+	unsigned char undermap;
+	unsigned char overmap;
+};
+class Coplanar{
+public:
+	unsigned short ea;
+	unsigned char v0;
+	unsigned char v1;
+};
+
+
+
+
+
+
+
+
+template<class T>
+int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+{
+	btAssert(count);
+	int m=-1;
+	for(int i=0;i<count;i++) 
+		if(allow[i])
+		{
+			if(m==-1 || btDot(p[i],dir)>btDot(p[m],dir))
+				m=i;
+		}
+	btAssert(m!=-1);
+	return m;
+} 
+
+btVector3 orth(const btVector3 &v);
+btVector3 orth(const btVector3 &v)
+{
+	btVector3 a=btCross(v,btVector3(0,0,1));
+	btVector3 b=btCross(v,btVector3(0,1,0));
+	if (a.length() > b.length())
+	{
+		return a.normalized();
+	} else {
+		return b.normalized();
+	}
+}
+
+
+template<class T>
+int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray<int> &allow)
+{
+	int m=-1;
+	while(m==-1)
+	{
+		m = maxdirfiltered(p,count,dir,allow);
+		if(allow[m]==3) return m;
+		T u = orth(dir);
+		T v = btCross(u,dir);
+		int ma=-1;
+		for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0))
+		{
+			btScalar s = btSin(SIMD_RADS_PER_DEG*(x));
+			btScalar c = btCos(SIMD_RADS_PER_DEG*(x));
+			int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
+			if(ma==m && mb==m)
+			{
+				allow[m]=3;
+				return m;
+			}
+			if(ma!=-1 && ma!=mb)  // Yuck - this is really ugly
+			{
+				int mc = ma;
+				for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0))
+				{
+					btScalar s = btSin(SIMD_RADS_PER_DEG*(xx));
+					btScalar c = btCos(SIMD_RADS_PER_DEG*(xx));
+					int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow);
+					if(mc==m && md==m)
+					{
+						allow[m]=3;
+						return m;
+					}
+					mc=md;
+				}
+			}
+			ma=mb;
+		}
+		allow[m]=0;
+		m=-1;
+	}
+	btAssert(0);
+	return m;
+} 
+
+
+
+
+int operator ==(const int3 &a,const int3 &b);
+int operator ==(const int3 &a,const int3 &b) 
+{
+	for(int i=0;i<3;i++) 
+	{
+		if(a[i]!=b[i]) return 0;
+	}
+	return 1;
+}
+
+
+int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon);
+int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) 
+{
+	btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
+	return (btDot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
+}
+int hasedge(const int3 &t, int a,int b);
+int hasedge(const int3 &t, int a,int b)
+{
+	for(int i=0;i<3;i++)
+	{
+		int i1= (i+1)%3;
+		if(t[i]==a && t[i1]==b) return 1;
+	}
+	return 0;
+}
+int hasvert(const int3 &t, int v);
+int hasvert(const int3 &t, int v)
+{
+	return (t[0]==v || t[1]==v || t[2]==v) ;
+}
+int shareedge(const int3 &a,const int3 &b);
+int shareedge(const int3 &a,const int3 &b)
+{
+	int i;
+	for(i=0;i<3;i++)
+	{
+		int i1= (i+1)%3;
+		if(hasedge(a,b[i1],b[i])) return 1;
+	}
+	return 0;
+}
+
+class btHullTriangle;
+
+
+
+class btHullTriangle : public int3
+{
+public:
+	int3 n;
+	int id;
+	int vmax;
+	btScalar rise;
+	btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1)
+	{
+		vmax=-1;
+		rise = btScalar(0.0);
+	}
+	~btHullTriangle()
+	{
+	}
+	int &neib(int a,int b);
+};
+
+
+int &btHullTriangle::neib(int a,int b)
+{
+	static int er=-1;
+	int i;
+	for(i=0;i<3;i++) 
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		if((*this)[i]==a && (*this)[i1]==b) return n[i2];
+		if((*this)[i]==b && (*this)[i1]==a) return n[i2];
+	}
+	btAssert(0);
+	return er;
+}
+void HullLibrary::b2bfix(btHullTriangle* s,btHullTriangle*t)
+{
+	int i;
+	for(i=0;i<3;i++) 
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		int a = (*s)[i1];
+		int b = (*s)[i2];
+		btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id);
+		btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id);
+		m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
+		m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
+	}
+}
+
+void HullLibrary::removeb2b(btHullTriangle* s,btHullTriangle*t)
+{
+	b2bfix(s,t);
+	deAllocateTriangle(s);
+
+	deAllocateTriangle(t);
+}
+
+void HullLibrary::checkit(btHullTriangle *t)
+{
+	(void)t;
+
+	int i;
+	btAssert(m_tris[t->id]==t);
+	for(i=0;i<3;i++)
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		int a = (*t)[i1];
+		int b = (*t)[i2];
+
+		// release compile fix
+		(void)i1;
+		(void)i2;
+		(void)a;
+		(void)b;
+
+		btAssert(a!=b);
+		btAssert( m_tris[t->n[i]]->neib(b,a) == t->id);
+	}
+}
+
+btHullTriangle*	HullLibrary::allocateTriangle(int a,int b,int c)
+{
+	void* mem = btAlignedAlloc(sizeof(btHullTriangle),16);
+	btHullTriangle* tr = new (mem)btHullTriangle(a,b,c);
+	tr->id = m_tris.size();
+	m_tris.push_back(tr);
+
+	return tr;
+}
+
+void	HullLibrary::deAllocateTriangle(btHullTriangle* tri)
+{
+	btAssert(m_tris[tri->id]==tri);
+	m_tris[tri->id]=NULL;
+	tri->~btHullTriangle();
+	btAlignedFree(tri);
+}
+
+
+void HullLibrary::extrude(btHullTriangle *t0,int v)
+{
+	int3 t= *t0;
+	int n = m_tris.size();
+	btHullTriangle* ta = allocateTriangle(v,t[1],t[2]);
+	ta->n = int3(t0->n[0],n+1,n+2);
+	m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
+	btHullTriangle* tb = allocateTriangle(v,t[2],t[0]);
+	tb->n = int3(t0->n[1],n+2,n+0);
+	m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
+	btHullTriangle* tc = allocateTriangle(v,t[0],t[1]);
+	tc->n = int3(t0->n[2],n+0,n+1);
+	m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
+	checkit(ta);
+	checkit(tb);
+	checkit(tc);
+	if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]);
+	if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]);
+	if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]);
+	deAllocateTriangle(t0);
+
+}
+
+btHullTriangle* HullLibrary::extrudable(btScalar epsilon)
+{
+	int i;
+	btHullTriangle *t=NULL;
+	for(i=0;i<m_tris.size();i++)
+	{
+		if(!t || (m_tris[i] && t->rise<m_tris[i]->rise))
+		{
+			t = m_tris[i];
+		}
+	}
+	return (t->rise >epsilon)?t:NULL ;
+}
+
+
+
+
+int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow)
+{
+	btVector3 basis[3];
+	basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) );      
+	int p0 = maxdirsterid(verts,verts_count, basis[0],allow);   
+	int	p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
+	basis[0] = verts[p0]-verts[p1];
+	if(p0==p1 || basis[0]==btVector3(0,0,0)) 
+		return int4(-1,-1,-1,-1);
+	basis[1] = btCross(btVector3(     btScalar(1),btScalar(0.02), btScalar(0)),basis[0]);
+	basis[2] = btCross(btVector3(btScalar(-0.02),     btScalar(1), btScalar(0)),basis[0]);
+	if (basis[1].length() > basis[2].length())
+	{
+		basis[1].normalize();
+	} else {
+		basis[1] = basis[2];
+		basis[1].normalize ();
+	}
+	int p2 = maxdirsterid(verts,verts_count,basis[1],allow);
+	if(p2 == p0 || p2 == p1)
+	{
+		p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
+	}
+	if(p2 == p0 || p2 == p1) 
+		return int4(-1,-1,-1,-1);
+	basis[1] = verts[p2] - verts[p0];
+	basis[2] = btCross(basis[1],basis[0]).normalized();
+	int p3 = maxdirsterid(verts,verts_count,basis[2],allow);
+	if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
+	if(p3==p0||p3==p1||p3==p2) 
+		return int4(-1,-1,-1,-1);
+	btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
+	if(btDot(verts[p3]-verts[p0],btCross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);}
+	return int4(p0,p1,p2,p3);
+}
+
+int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit)
+{
+	if(verts_count <4) return 0;
+	if(vlimit==0) vlimit=1000000000;
+	int j;
+	btVector3 bmin(*verts),bmax(*verts);
+	btAlignedObjectArray<int> isextreme;
+	isextreme.reserve(verts_count);
+	btAlignedObjectArray<int> allow;
+	allow.reserve(verts_count);
+
+	for(j=0;j<verts_count;j++) 
+	{
+		allow.push_back(1);
+		isextreme.push_back(0);
+		bmin.setMin (verts[j]);
+		bmax.setMax (verts[j]);
+	}
+	btScalar epsilon = (bmax-bmin).length() * btScalar(0.001);
+	btAssert (epsilon != 0.0);
+
+
+	int4 p = FindSimplex(verts,verts_count,allow);
+	if(p.x==-1) return 0; // simplex failed
+
+
+
+	btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0);  // a valid interior point
+	btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1);
+	btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0);
+	btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3);
+	btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2);
+	isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
+	checkit(t0);checkit(t1);checkit(t2);checkit(t3);
+
+	for(j=0;j<m_tris.size();j++)
+	{
+		btHullTriangle *t=m_tris[j];
+		btAssert(t);
+		btAssert(t->vmax<0);
+		btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+		t->vmax = maxdirsterid(verts,verts_count,n,allow);
+		t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+	}
+	btHullTriangle *te;
+	vlimit-=4;
+	while(vlimit >0 && ((te=extrudable(epsilon)) != 0))
+	{
+		int3 ti=*te;
+		int v=te->vmax;
+		btAssert(v != -1);
+		btAssert(!isextreme[v]);  // wtf we've already done this vertex
+		isextreme[v]=1;
+		//if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
+		j=m_tris.size();
+		while(j--) {
+			if(!m_tris[j]) continue;
+			int3 t=*m_tris[j];
+			if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) 
+			{
+				extrude(m_tris[j],v);
+			}
+		}
+		// now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
+		j=m_tris.size();
+		while(j--)
+		{
+			if(!m_tris[j]) continue;
+			if(!hasvert(*m_tris[j],v)) break;
+			int3 nt=*m_tris[j];
+			if(above(verts,nt,center,btScalar(0.01)*epsilon)  || btCross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) )
+			{
+				btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
+				btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j);
+				extrude(nb,v);
+				j=m_tris.size(); 
+			}
+		} 
+		j=m_tris.size();
+		while(j--)
+		{
+			btHullTriangle *t=m_tris[j];
+			if(!t) continue;
+			if(t->vmax>=0) break;
+			btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+			t->vmax = maxdirsterid(verts,verts_count,n,allow);
+			if(isextreme[t->vmax]) 
+			{
+				t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
+			}
+			else
+			{
+				t->rise = btDot(n,verts[t->vmax]-verts[(*t)[0]]);
+			}
+		}
+		vlimit --;
+	}
+	return 1;
+}
+
+int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit) 
+{
+	int rc=calchullgen(verts,verts_count,  vlimit) ;
+	if(!rc) return 0;
+	btAlignedObjectArray<int> ts;
+	int i;
+
+	for(i=0;i<m_tris.size();i++)
+	{
+		if(m_tris[i])
+		{
+			for(int j=0;j<3;j++)
+				ts.push_back((*m_tris[i])[j]);
+			deAllocateTriangle(m_tris[i]);
+		}
+	}
+	tris_count = ts.size()/3;
+	tris_out.resize(ts.size());
+	
+	for (i=0;i<ts.size();i++)
+	{
+		tris_out[i] = static_cast<unsigned int>(ts[i]);
+	}
+	m_tris.resize(0);
+
+	return 1;
+}
+
+
+
+
+
+bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit)
+{
+	
+	int    tris_count;
+	int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast<int>(vlimit) );
+	if(!ret) return false;
+	result.mIndexCount = (unsigned int) (tris_count*3);
+	result.mFaceCount  = (unsigned int) tris_count;
+	result.mVertices   = (btVector3*) vertices;
+	result.mVcount     = (unsigned int) vcount;
+	return true;
+
+}
+
+
+void ReleaseHull(PHullResult &result);
+void ReleaseHull(PHullResult &result)
+{
+	if ( result.m_Indices.size() )
+	{
+		result.m_Indices.clear();
+	}
+
+	result.mVcount = 0;
+	result.mIndexCount = 0;
+	result.mVertices = 0;
+}
+
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib header
+//*********************************************************************
+//*********************************************************************
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib implementation
+//*********************************************************************
+//*********************************************************************
+
+HullError HullLibrary::CreateConvexHull(const HullDesc       &desc,           // describes the input request
+																					HullResult           &result)         // contains the resulst
+{
+	HullError ret = QE_FAIL;
+
+
+	PHullResult hr;
+
+	unsigned int vcount = desc.mVcount;
+	if ( vcount < 8 ) vcount = 8;
+
+	btAlignedObjectArray<btVector3> vertexSource;
+	vertexSource.resize(static_cast<int>(vcount));
+
+	btVector3 scale;
+
+	unsigned int ovcount;
+
+	bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
+
+	if ( ok )
+	{
+
+
+//		if ( 1 ) // scale vertices back to their original size.
+		{
+			for (unsigned int i=0; i<ovcount; i++)
+			{
+				btVector3& v = vertexSource[static_cast<int>(i)];
+				v[0]*=scale[0];
+				v[1]*=scale[1];
+				v[2]*=scale[2];
+			}
+		}
+
+		ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices);
+
+		if ( ok )
+		{
+
+			// re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
+			btAlignedObjectArray<btVector3>	vertexScratch;
+			vertexScratch.resize(static_cast<int>(hr.mVcount));
+
+			BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount );
+
+			ret = QE_OK;
+
+			if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
+			{
+				result.mPolygons          = false;
+				result.mNumOutputVertices = ovcount;
+				result.m_OutputVertices.resize(static_cast<int>(ovcount));
+				result.mNumFaces          = hr.mFaceCount;
+				result.mNumIndices        = hr.mIndexCount;
+
+				result.m_Indices.resize(static_cast<int>(hr.mIndexCount));
+
+				memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+
+  			if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+				{
+
+					const unsigned int *source = &hr.m_Indices[0];
+					unsigned int *dest   = &result.m_Indices[0];
+
+					for (unsigned int i=0; i<hr.mFaceCount; i++)
+					{
+						dest[0] = source[2];
+						dest[1] = source[1];
+						dest[2] = source[0];
+						dest+=3;
+						source+=3;
+					}
+
+				}
+				else
+				{
+					memcpy(&result.m_Indices[0], &hr.m_Indices[0], sizeof(unsigned int)*hr.mIndexCount);
+				}
+			}
+			else
+			{
+				result.mPolygons          = true;
+				result.mNumOutputVertices = ovcount;
+				result.m_OutputVertices.resize(static_cast<int>(ovcount));
+				result.mNumFaces          = hr.mFaceCount;
+				result.mNumIndices        = hr.mIndexCount+hr.mFaceCount;
+				result.m_Indices.resize(static_cast<int>(result.mNumIndices));
+				memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount );
+
+//				if ( 1 )
+				{
+					const unsigned int *source = &hr.m_Indices[0];
+					unsigned int *dest   = &result.m_Indices[0];
+					for (unsigned int i=0; i<hr.mFaceCount; i++)
+					{
+						dest[0] = 3;
+						if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+						{
+							dest[1] = source[2];
+							dest[2] = source[1];
+							dest[3] = source[0];
+						}
+						else
+						{
+							dest[1] = source[0];
+							dest[2] = source[1];
+							dest[3] = source[2];
+						}
+
+						dest+=4;
+						source+=3;
+					}
+				}
+			}
+			ReleaseHull(hr);
+		}
+	}
+
+	return ret;
+}
+
+
+
+HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
+{
+	if ( result.m_OutputVertices.size())
+	{
+		result.mNumOutputVertices=0;
+		result.m_OutputVertices.clear();
+	}
+	if ( result.m_Indices.size() )
+	{
+		result.mNumIndices=0;
+		result.m_Indices.clear();
+	}
+	return QE_OK;
+}
+
+
+static void addPoint(unsigned int &vcount,btVector3 *p,btScalar x,btScalar y,btScalar z)
+{
+	// XXX, might be broken
+	btVector3& dest = p[vcount];
+	dest[0] = x;
+	dest[1] = y;
+	dest[2] = z;
+	vcount++;
+}
+
+btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2);
+btScalar GetDist(btScalar px,btScalar py,btScalar pz,const btScalar *p2)
+{
+
+	btScalar dx = px - p2[0];
+	btScalar dy = py - p2[1];
+	btScalar dz = pz - p2[2];
+
+	return dx*dx+dy*dy+dz*dz;
+}
+
+
+
+bool  HullLibrary::CleanupVertices(unsigned int svcount,
+				   const btVector3 *svertices,
+				   unsigned int stride,
+				   unsigned int &vcount,       // output number of vertices
+				   btVector3 *vertices,                 // location to store the results.
+				   btScalar  normalepsilon,
+				   btVector3& scale)
+{
+	if ( svcount == 0 ) return false;
+
+	m_vertexIndexMapping.resize(0);
+
+
+#define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */
+
+	vcount = 0;
+
+	btScalar recip[3]={0.f,0.f,0.f};
+
+	if ( scale )
+	{
+		scale[0] = 1;
+		scale[1] = 1;
+		scale[2] = 1;
+	}
+
+	btScalar bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
+	btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+	const char *vtx = (const char *) svertices;
+
+//	if ( 1 )
+	{
+		for (unsigned int i=0; i<svcount; i++)
+		{
+			const btScalar *p = (const btScalar *) vtx;
+
+			vtx+=stride;
+
+			for (int j=0; j<3; j++)
+			{
+				if ( p[j] < bmin[j] ) bmin[j] = p[j];
+				if ( p[j] > bmax[j] ) bmax[j] = p[j];
+			}
+		}
+	}
+
+	btScalar dx = bmax[0] - bmin[0];
+	btScalar dy = bmax[1] - bmin[1];
+	btScalar dz = bmax[2] - bmin[2];
+
+	btVector3 center;
+
+	center[0] = dx*btScalar(0.5) + bmin[0];
+	center[1] = dy*btScalar(0.5) + bmin[1];
+	center[2] = dz*btScalar(0.5) + bmin[2];
+
+	if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
+	{
+
+		btScalar len = FLT_MAX;
+
+		if ( dx > EPSILON && dx < len ) len = dx;
+		if ( dy > EPSILON && dy < len ) len = dy;
+		if ( dz > EPSILON && dz < len ) len = dz;
+
+		if ( len == FLT_MAX )
+		{
+			dx = dy = dz = btScalar(0.01); // one centimeter
+		}
+		else
+		{
+			if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+			if ( dy < EPSILON ) dy = len * btScalar(0.05);
+			if ( dz < EPSILON ) dz = len * btScalar(0.05);
+		}
+
+		btScalar x1 = center[0] - dx;
+		btScalar x2 = center[0] + dx;
+
+		btScalar y1 = center[1] - dy;
+		btScalar y2 = center[1] + dy;
+
+		btScalar z1 = center[2] - dz;
+		btScalar z2 = center[2] + dz;
+
+		addPoint(vcount,vertices,x1,y1,z1);
+		addPoint(vcount,vertices,x2,y1,z1);
+		addPoint(vcount,vertices,x2,y2,z1);
+		addPoint(vcount,vertices,x1,y2,z1);
+		addPoint(vcount,vertices,x1,y1,z2);
+		addPoint(vcount,vertices,x2,y1,z2);
+		addPoint(vcount,vertices,x2,y2,z2);
+		addPoint(vcount,vertices,x1,y2,z2);
+
+		return true; // return cube
+
+
+	}
+	else
+	{
+		if ( scale )
+		{
+			scale[0] = dx;
+			scale[1] = dy;
+			scale[2] = dz;
+
+			recip[0] = 1 / dx;
+			recip[1] = 1 / dy;
+			recip[2] = 1 / dz;
+
+			center[0]*=recip[0];
+			center[1]*=recip[1];
+			center[2]*=recip[2];
+
+		}
+
+	}
+
+
+
+	vtx = (const char *) svertices;
+
+	for (unsigned int i=0; i<svcount; i++)
+	{
+		const btVector3 *p = (const btVector3 *)vtx;
+		vtx+=stride;
+
+		btScalar px = p->getX();
+		btScalar py = p->getY();
+		btScalar pz = p->getZ();
+
+		if ( scale )
+		{
+			px = px*recip[0]; // normalize
+			py = py*recip[1]; // normalize
+			pz = pz*recip[2]; // normalize
+		}
+
+//		if ( 1 )
+		{
+			unsigned int j;
+
+			for (j=0; j<vcount; j++)
+			{
+				/// XXX might be broken
+				btVector3& v = vertices[j];
+
+				btScalar x = v[0];
+				btScalar y = v[1];
+				btScalar z = v[2];
+
+				btScalar dx = btFabs(x - px );
+				btScalar dy = btFabs(y - py );
+				btScalar dz = btFabs(z - pz );
+
+				if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
+				{
+					// ok, it is close enough to the old one
+					// now let us see if it is further from the center of the point cloud than the one we already recorded.
+					// in which case we keep this one instead.
+
+					btScalar dist1 = GetDist(px,py,pz,center);
+					btScalar dist2 = GetDist(v[0],v[1],v[2],center);
+
+					if ( dist1 > dist2 )
+					{
+						v[0] = px;
+						v[1] = py;
+						v[2] = pz;
+						
+					}
+
+					break;
+				}
+			}
+
+			if ( j == vcount )
+			{
+				btVector3& dest = vertices[vcount];
+				dest[0] = px;
+				dest[1] = py;
+				dest[2] = pz;
+				vcount++;
+			}
+			m_vertexIndexMapping.push_back(j);
+		}
+	}
+
+	// ok..now make sure we didn't prune so many vertices it is now invalid.
+//	if ( 1 )
+	{
+		btScalar bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
+		btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+		for (unsigned int i=0; i<vcount; i++)
+		{
+			const btVector3& p = vertices[i];
+			for (int j=0; j<3; j++)
+			{
+				if ( p[j] < bmin[j] ) bmin[j] = p[j];
+				if ( p[j] > bmax[j] ) bmax[j] = p[j];
+			}
+		}
+
+		btScalar dx = bmax[0] - bmin[0];
+		btScalar dy = bmax[1] - bmin[1];
+		btScalar dz = bmax[2] - bmin[2];
+
+		if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
+		{
+			btScalar cx = dx*btScalar(0.5) + bmin[0];
+			btScalar cy = dy*btScalar(0.5) + bmin[1];
+			btScalar cz = dz*btScalar(0.5) + bmin[2];
+
+			btScalar len = FLT_MAX;
+
+			if ( dx >= EPSILON && dx < len ) len = dx;
+			if ( dy >= EPSILON && dy < len ) len = dy;
+			if ( dz >= EPSILON && dz < len ) len = dz;
+
+			if ( len == FLT_MAX )
+			{
+				dx = dy = dz = btScalar(0.01); // one centimeter
+			}
+			else
+			{
+				if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge.
+				if ( dy < EPSILON ) dy = len * btScalar(0.05);
+				if ( dz < EPSILON ) dz = len * btScalar(0.05);
+			}
+
+			btScalar x1 = cx - dx;
+			btScalar x2 = cx + dx;
+
+			btScalar y1 = cy - dy;
+			btScalar y2 = cy + dy;
+
+			btScalar z1 = cz - dz;
+			btScalar z2 = cz + dz;
+
+			vcount = 0; // add box
+
+			addPoint(vcount,vertices,x1,y1,z1);
+			addPoint(vcount,vertices,x2,y1,z1);
+			addPoint(vcount,vertices,x2,y2,z1);
+			addPoint(vcount,vertices,x1,y2,z1);
+			addPoint(vcount,vertices,x1,y1,z2);
+			addPoint(vcount,vertices,x2,y1,z2);
+			addPoint(vcount,vertices,x2,y2,z2);
+			addPoint(vcount,vertices,x1,y2,z2);
+
+			return true;
+		}
+	}
+
+	return true;
+}
+
+void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
+{
+	btAlignedObjectArray<int>tmpIndices;
+	tmpIndices.resize(m_vertexIndexMapping.size());
+	int i;
+
+	for (i=0;i<m_vertexIndexMapping.size();i++)
+	{
+		tmpIndices[i] = m_vertexIndexMapping[i];
+	}
+
+	TUIntArray usedIndices;
+	usedIndices.resize(static_cast<int>(vcount));
+	memset(&usedIndices[0],0,sizeof(unsigned int)*vcount);
+
+	ocount = 0;
+
+	for (i=0; i<int (indexcount); i++)
+	{
+		unsigned int v = indices[i]; // original array index
+
+		btAssert( v >= 0 && v < vcount );
+
+		if ( usedIndices[static_cast<int>(v)] ) // if already remapped
+		{
+			indices[i] = usedIndices[static_cast<int>(v)]-1; // index to new array
+		}
+		else
+		{
+
+			indices[i] = ocount;      // new index mapping
+
+			overts[ocount][0] = verts[v][0]; // copy old vert to new vert array
+			overts[ocount][1] = verts[v][1];
+			overts[ocount][2] = verts[v][2];
+
+			for (int k=0;k<m_vertexIndexMapping.size();k++)
+			{
+				if (tmpIndices[k]==int(v))
+					m_vertexIndexMapping[k]=ocount;
+			}
+
+			ocount++; // increment output vert count
+
+			btAssert( ocount >=0 && ocount <= vcount );
+
+			usedIndices[static_cast<int>(v)] = ocount; // assign new index remapping
+
+		
+		}
+	}
+
+	
+}
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btConvexHull.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btConvexHull.h
new file mode 100644
index 0000000..a23fa4d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btConvexHull.h
@@ -0,0 +1,241 @@
+
+/*
+Stan Melax Convex Hull Computation
+Copyright (c) 2008 Stan Melax http://www.melax.com/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+///includes modifications/improvements by John Ratcliff, see BringOutYourDead below.
+
+#ifndef CD_HULL_H
+#define CD_HULL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+typedef btAlignedObjectArray<unsigned int> TUIntArray;
+
+class HullResult
+{
+public:
+	HullResult(void)
+	{
+		mPolygons = true;
+		mNumOutputVertices = 0;
+		mNumFaces = 0;
+		mNumIndices = 0;
+	}
+	bool                    mPolygons;                  // true if indices represents polygons, false indices are triangles
+	unsigned int            mNumOutputVertices;         // number of vertices in the output hull
+	btAlignedObjectArray<btVector3>	m_OutputVertices;            // array of vertices
+	unsigned int            mNumFaces;                  // the number of faces produced
+	unsigned int            mNumIndices;                // the total number of indices
+	btAlignedObjectArray<unsigned int>    m_Indices;                   // pointer to indices.
+
+// If triangles, then indices are array indexes into the vertex list.
+// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
+};
+
+enum HullFlag
+{
+	QF_TRIANGLES         = (1<<0),             // report results as triangles, not polygons.
+	QF_REVERSE_ORDER     = (1<<1),             // reverse order of the triangle indices.
+	QF_DEFAULT           = QF_TRIANGLES
+};
+
+
+class HullDesc
+{
+public:
+	HullDesc(void)
+	{
+		mFlags          = QF_DEFAULT;
+		mVcount         = 0;
+		mVertices       = 0;
+		mVertexStride   = sizeof(btVector3);
+		mNormalEpsilon  = 0.001f;
+		mMaxVertices	= 4096; // maximum number of points to be considered for a convex hull.
+		mMaxFaces	= 4096;
+	};
+
+	HullDesc(HullFlag flag,
+		 unsigned int vcount,
+		 const btVector3 *vertices,
+		 unsigned int stride = sizeof(btVector3))
+	{
+		mFlags          = flag;
+		mVcount         = vcount;
+		mVertices       = vertices;
+		mVertexStride   = stride;
+		mNormalEpsilon  = btScalar(0.001);
+		mMaxVertices    = 4096;
+	}
+
+	bool HasHullFlag(HullFlag flag) const
+	{
+		if ( mFlags & flag ) return true;
+		return false;
+	}
+
+	void SetHullFlag(HullFlag flag)
+	{
+		mFlags|=flag;
+	}
+
+	void ClearHullFlag(HullFlag flag)
+	{
+		mFlags&=~flag;
+	}
+
+	unsigned int      mFlags;           // flags to use when generating the convex hull.
+	unsigned int      mVcount;          // number of vertices in the input point cloud
+	const btVector3  *mVertices;        // the array of vertices.
+	unsigned int      mVertexStride;    // the stride of each vertex, in bytes.
+	btScalar             mNormalEpsilon;   // the epsilon for removing duplicates.  This is a normalized value, if normalized bit is on.
+	unsigned int      mMaxVertices;     // maximum number of vertices to be considered for the hull!
+	unsigned int      mMaxFaces;
+};
+
+enum HullError
+{
+	QE_OK,            // success!
+	QE_FAIL           // failed.
+};
+
+class btPlane
+{
+	public:
+	btVector3	normal;
+	btScalar	dist;   // distance below origin - the D from plane equasion Ax+By+Cz+D=0
+			btPlane(const btVector3 &n,btScalar d):normal(n),dist(d){}
+			btPlane():normal(),dist(0){}
+	
+};
+
+
+
+class ConvexH 
+{
+  public:
+	class HalfEdge
+	{
+	  public:
+		short ea;         // the other half of the edge (index into edges list)
+		unsigned char v;  // the vertex at the start of this edge (index into vertices list)
+		unsigned char p;  // the facet on which this edge lies (index into facets list)
+		HalfEdge(){}
+		HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
+	};
+	ConvexH()
+	{
+	}
+	~ConvexH()
+	{
+	}
+	btAlignedObjectArray<btVector3> vertices;
+	btAlignedObjectArray<HalfEdge> edges;
+	btAlignedObjectArray<btPlane>  facets;
+	ConvexH(int vertices_size,int edges_size,int facets_size);
+};
+
+
+class int4
+{
+public:
+	int x,y,z,w;
+	int4(){};
+	int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
+	const int& operator[](int i) const {return (&x)[i];}
+	int& operator[](int i) {return (&x)[i];}
+};
+
+class PHullResult
+{
+public:
+
+	PHullResult(void)
+	{
+		mVcount = 0;
+		mIndexCount = 0;
+		mFaceCount = 0;
+		mVertices = 0;
+	}
+
+	unsigned int mVcount;
+	unsigned int mIndexCount;
+	unsigned int mFaceCount;
+	btVector3*   mVertices;
+	TUIntArray m_Indices;
+};
+
+
+
+///The HullLibrary class can create a convex hull from a collection of vertices, using the ComputeHull method.
+///The btShapeHull class uses this HullLibrary to create a approximate convex mesh given a general (non-polyhedral) convex shape.
+class HullLibrary
+{
+
+	btAlignedObjectArray<class btHullTriangle*> m_tris;
+
+public:
+
+	btAlignedObjectArray<int> m_vertexIndexMapping;
+
+
+	HullError CreateConvexHull(const HullDesc& desc, // describes the input request
+				   HullResult&     result);        // contains the resulst
+	HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
+
+private:
+
+	bool ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit);
+
+	class btHullTriangle*	allocateTriangle(int a,int b,int c);
+	void	deAllocateTriangle(btHullTriangle*);
+	void b2bfix(btHullTriangle* s,btHullTriangle*t);
+
+	void removeb2b(btHullTriangle* s,btHullTriangle*t);
+
+	void checkit(btHullTriangle *t);
+
+	btHullTriangle* extrudable(btScalar epsilon);
+
+	int calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit);
+
+	int calchullgen(btVector3 *verts,int verts_count, int vlimit);
+
+	int4 FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray<int> &allow);
+
+	class ConvexH* ConvexHCrop(ConvexH& convex,const btPlane& slice);
+
+	void extrude(class btHullTriangle* t0,int v);
+
+	ConvexH* test_cube();
+
+	//BringOutYourDead (John Ratcliff): When you create a convex hull you hand it a large input set of vertices forming a 'point cloud'. 
+	//After the hull is generated it give you back a set of polygon faces which index the *original* point cloud.
+	//The thing is, often times, there are many 'dead vertices' in the point cloud that are on longer referenced by the hull.
+	//The routine 'BringOutYourDead' find only the referenced vertices, copies them to an new buffer, and re-indexes the hull so that it is a minimal representation.
+	void BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int* indices,unsigned indexcount);
+
+	bool CleanupVertices(unsigned int svcount,
+			     const btVector3* svertices,
+			     unsigned int stride,
+			     unsigned int &vcount, // output number of vertices
+			     btVector3* vertices, // location to store the results.
+			     btScalar  normalepsilon,
+			     btVector3& scale);
+};
+
+
+#endif
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btDefaultMotionState.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btDefaultMotionState.h
new file mode 100644
index 0000000..7858a10
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btDefaultMotionState.h
@@ -0,0 +1,40 @@
+#ifndef DEFAULT_MOTION_STATE_H
+#define DEFAULT_MOTION_STATE_H
+
+#include "btMotionState.h"
+
+///The btDefaultMotionState provides a common implementation to synchronize world transforms with offsets.
+struct	btDefaultMotionState : public btMotionState
+{
+	btTransform m_graphicsWorldTrans;
+	btTransform	m_centerOfMassOffset;
+	btTransform m_startWorldTrans;
+	void*		m_userPointer;
+
+	btDefaultMotionState(const btTransform& startTrans = btTransform::getIdentity(),const btTransform& centerOfMassOffset = btTransform::getIdentity())
+		: m_graphicsWorldTrans(startTrans),
+		m_centerOfMassOffset(centerOfMassOffset),
+		m_startWorldTrans(startTrans),
+		m_userPointer(0)
+
+	{
+	}
+
+	///synchronizes world transform from user to physics
+	virtual void	getWorldTransform(btTransform& centerOfMassWorldTrans ) const 
+	{
+			centerOfMassWorldTrans = 	m_centerOfMassOffset.inverse() * m_graphicsWorldTrans ;
+	}
+
+	///synchronizes world transform from physics to user
+	///Bullet only calls the update of worldtransform for active objects
+	virtual void	setWorldTransform(const btTransform& centerOfMassWorldTrans)
+	{
+			m_graphicsWorldTrans = centerOfMassWorldTrans * m_centerOfMassOffset ;
+	}
+
+	
+
+};
+
+#endif //DEFAULT_MOTION_STATE_H
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btGeometryUtil.cpp b/SRC/ChronoEngine/collision/bullet/LinearMath/btGeometryUtil.cpp
new file mode 100644
index 0000000..5ac230f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btGeometryUtil.cpp
@@ -0,0 +1,185 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#include "btGeometryUtil.h"
+
+
+/*
+  Make sure this dummy function never changes so that it
+  can be used by probes that are checking whether the
+  library is actually installed.
+*/
+extern "C"
+{	
+	void btBulletMathProbe ();
+
+	void btBulletMathProbe () {}
+}
+
+
+bool	btGeometryUtil::isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar	margin)
+{
+	int numbrushes = planeEquations.size();
+	for (int i=0;i<numbrushes;i++)
+	{
+		const btVector3& N1 = planeEquations[i];
+		btScalar dist = btScalar(N1.dot(point))+btScalar(N1[3])-margin;
+		if (dist>btScalar(0.))
+		{
+			return false;
+		}
+	}
+	return true;
+		
+}
+
+
+bool	btGeometryUtil::areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar	margin)
+{
+	int numvertices = vertices.size();
+	for (int i=0;i<numvertices;i++)
+	{
+		const btVector3& N1 = vertices[i];
+		btScalar dist = btScalar(planeNormal.dot(N1))+btScalar(planeNormal[3])-margin;
+		if (dist>btScalar(0.))
+		{
+			return false;
+		}
+	}
+	return true;
+}
+
+bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations);
+
+bool notExist(const btVector3& planeEquation,const btAlignedObjectArray<btVector3>& planeEquations)
+{
+	int numbrushes = planeEquations.size();
+	for (int i=0;i<numbrushes;i++)
+	{
+		const btVector3& N1 = planeEquations[i];
+		if (planeEquation.dot(N1) > btScalar(0.999))
+		{
+			return false;
+		} 
+	}
+	return true;
+}
+
+void	btGeometryUtil::getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut )
+{
+		const int numvertices = vertices.size();
+	// brute force:
+	for (int i=0;i<numvertices;i++)
+	{
+		const btVector3& N1 = vertices[i];
+		
+
+		for (int j=i+1;j<numvertices;j++)
+		{
+			const btVector3& N2 = vertices[j];
+				
+			for (int k=j+1;k<numvertices;k++)
+			{
+
+				const btVector3& N3 = vertices[k];
+
+				btVector3 planeEquation,edge0,edge1;
+				edge0 = N2-N1;
+				edge1 = N3-N1;
+				btScalar normalSign = btScalar(1.);
+				for (int ww=0;ww<2;ww++)
+				{
+					planeEquation = normalSign * edge0.cross(edge1);
+					if (planeEquation.length2() > btScalar(0.0001))
+					{
+						planeEquation.normalize();
+						if (notExist(planeEquation,planeEquationsOut))
+						{
+							planeEquation[3] = -planeEquation.dot(N1);
+							
+								//check if inside, and replace supportingVertexOut if needed
+								if (areVerticesBehindPlane(planeEquation,vertices,btScalar(0.01)))
+								{
+									planeEquationsOut.push_back(planeEquation);
+								}
+						}
+					}
+					normalSign = btScalar(-1.);
+				}
+			
+			}
+		}
+	}
+
+}
+
+void	btGeometryUtil::getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut )
+{
+	const int numbrushes = planeEquations.size();
+	// brute force:
+	for (int i=0;i<numbrushes;i++)
+	{
+		const btVector3& N1 = planeEquations[i];
+		
+
+		for (int j=i+1;j<numbrushes;j++)
+		{
+			const btVector3& N2 = planeEquations[j];
+				
+			for (int k=j+1;k<numbrushes;k++)
+			{
+
+				const btVector3& N3 = planeEquations[k];
+
+				btVector3 n2n3; n2n3 = N2.cross(N3);
+				btVector3 n3n1; n3n1 = N3.cross(N1);
+				btVector3 n1n2; n1n2 = N1.cross(N2);
+				
+				if ( ( n2n3.length2() > btScalar(0.0001) ) &&
+					 ( n3n1.length2() > btScalar(0.0001) ) &&
+					 ( n1n2.length2() > btScalar(0.0001) ) )
+				{
+					//point P out of 3 plane equations:
+
+					//	d1 ( N2 * N3 ) + d2 ( N3 * N1 ) + d3 ( N1 * N2 )  
+					//P =  -------------------------------------------------------------------------  
+					//   N1 . ( N2 * N3 )  
+
+
+					btScalar quotient = (N1.dot(n2n3));
+					if (btFabs(quotient) > btScalar(0.000001))
+					{
+						quotient = btScalar(-1.) / quotient;
+						n2n3 *= N1[3];
+						n3n1 *= N2[3];
+						n1n2 *= N3[3];
+						btVector3 potentialVertex = n2n3;
+						potentialVertex += n3n1;
+						potentialVertex += n1n2;
+						potentialVertex *= quotient;
+
+						//check if inside, and replace supportingVertexOut if needed
+						if (isPointInsidePlanes(planeEquations,potentialVertex,btScalar(0.01)))
+						{
+							verticesOut.push_back(potentialVertex);
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btGeometryUtil.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btGeometryUtil.h
new file mode 100644
index 0000000..a4b13b4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btGeometryUtil.h
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef BT_GEOMETRY_UTIL_H
+#define BT_GEOMETRY_UTIL_H
+
+#include "btVector3.h"
+#include "btAlignedObjectArray.h"
+
+///The btGeometryUtil helper class provides a few methods to convert between plane equations and vertices.
+class btGeometryUtil
+{
+	public:
+	
+	
+		static void	getPlaneEquationsFromVertices(btAlignedObjectArray<btVector3>& vertices, btAlignedObjectArray<btVector3>& planeEquationsOut );
+
+		static void	getVerticesFromPlaneEquations(const btAlignedObjectArray<btVector3>& planeEquations , btAlignedObjectArray<btVector3>& verticesOut );
+	
+		static bool	isInside(const btAlignedObjectArray<btVector3>& vertices, const btVector3& planeNormal, btScalar	margin);
+		
+		static bool	isPointInsidePlanes(const btAlignedObjectArray<btVector3>& planeEquations, const btVector3& point, btScalar	margin);
+
+		static bool	areVerticesBehindPlane(const btVector3& planeNormal, const btAlignedObjectArray<btVector3>& vertices, btScalar	margin);
+
+};
+
+
+#endif //BT_GEOMETRY_UTIL_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btHashMap.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btHashMap.h
new file mode 100644
index 0000000..e3302b5
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btHashMap.h
@@ -0,0 +1,434 @@
+#ifndef BT_HASH_MAP_H
+#define BT_HASH_MAP_H
+
+#include "btAlignedObjectArray.h"
+
+///very basic hashable string implementation, compatible with btHashMap
+struct btHashString
+{
+	const char* m_string;
+	unsigned int	m_hash;
+
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		return m_hash;
+	}
+
+	btHashString(const char* name)
+		:m_string(name)
+	{
+		/* magic numbers from http://www.isthe.com/chongo/tech/comp/fnv/ */
+		static const unsigned int  InitialFNV = 2166136261u;
+		static const unsigned int FNVMultiple = 16777619u;
+
+		/* Fowler / Noll / Vo (FNV) Hash */
+		unsigned int hash = InitialFNV;
+		
+		for(int i = 0; m_string[i]; i++)
+		{
+			hash = hash ^ (m_string[i]);       /* xor  the low 8 bits */
+			hash = hash * FNVMultiple;  /* multiply by the magic number */
+		}
+		m_hash = hash;
+	}
+
+	int portableStringCompare(const char* src,	const char* dst) const
+	{
+			int ret = 0 ;
+
+			while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
+					++src, ++dst;
+
+			if ( ret < 0 )
+					ret = -1 ;
+			else if ( ret > 0 )
+					ret = 1 ;
+
+			return( ret );
+	}
+
+	bool equals(const btHashString& other) const
+	{
+		return (m_string == other.m_string) ||
+			(0==portableStringCompare(m_string,other.m_string));
+
+	}
+
+};
+
+const int BT_HASH_NULL=0xffffffff;
+
+
+class btHashInt
+{
+	int	m_uid;
+public:
+	btHashInt(int uid)	:m_uid(uid)
+	{
+	}
+
+	int	getUid1() const
+	{
+		return m_uid;
+	}
+
+	void	setUid1(int uid)
+	{
+		m_uid = uid;
+	}
+
+	bool equals(const btHashInt& other) const
+	{
+		return getUid1() == other.getUid1();
+	}
+	//to our success
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		int key = m_uid;
+		// Thomas Wang's hash
+		key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+		return key;
+	}
+};
+
+
+
+class btHashPtr
+{
+
+	union
+	{
+		const void*	m_pointer;
+		int	m_hashValues[2];
+	};
+
+public:
+
+	btHashPtr(const void* ptr)
+		:m_pointer(ptr)
+	{
+	}
+
+	const void*	getPointer() const
+	{
+		return m_pointer;
+	}
+
+	bool equals(const btHashPtr& other) const
+	{
+		return getPointer() == other.getPointer();
+	}
+
+	//to our success
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		const bool VOID_IS_8 = ((sizeof(void*)==8));
+		
+		int key = VOID_IS_8? m_hashValues[0]+m_hashValues[1] : m_hashValues[0];
+	
+		// Thomas Wang's hash
+		key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+		return key;
+	}
+
+	
+};
+
+
+template <class Value>
+class btHashKeyPtr
+{
+        int     m_uid;
+public:
+
+        btHashKeyPtr(int uid)    :m_uid(uid)
+        {
+        }
+
+        int     getUid1() const
+        {
+                return m_uid;
+        }
+
+        bool equals(const btHashKeyPtr<Value>& other) const
+        {
+                return getUid1() == other.getUid1();
+        }
+
+        //to our success
+        SIMD_FORCE_INLINE       unsigned int getHash()const
+        {
+                int key = m_uid;
+                // Thomas Wang's hash
+                key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+                return key;
+        }
+
+        
+};
+
+
+template <class Value>
+class btHashKey
+{
+	int	m_uid;
+public:
+
+	btHashKey(int uid)	:m_uid(uid)
+	{
+	}
+
+	int	getUid1() const
+	{
+		return m_uid;
+	}
+
+	bool equals(const btHashKey<Value>& other) const
+	{
+		return getUid1() == other.getUid1();
+	}
+	//to our success
+	SIMD_FORCE_INLINE	unsigned int getHash()const
+	{
+		int key = m_uid;
+		// Thomas Wang's hash
+		key += ~(key << 15);	key ^=  (key >> 10);	key +=  (key << 3);	key ^=  (key >> 6);	key += ~(key << 11);	key ^=  (key >> 16);
+		return key;
+	}
+};
+
+
+///The btHashMap template class implements a generic and lightweight hashmap.
+///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp
+template <class Key, class Value>
+class btHashMap
+{
+
+protected:
+	btAlignedObjectArray<int>		m_hashTable;
+	btAlignedObjectArray<int>		m_next;
+	
+	btAlignedObjectArray<Value>		m_valueArray;
+	btAlignedObjectArray<Key>		m_keyArray;
+
+	void	growTables(const Key& /*key*/)
+	{
+		int newCapacity = m_valueArray.capacity();
+
+		if (m_hashTable.size() < newCapacity)
+		{
+			//grow hashtable and next table
+			int curHashtableSize = m_hashTable.size();
+
+			m_hashTable.resize(newCapacity);
+			m_next.resize(newCapacity);
+
+			int i;
+
+			for (i= 0; i < newCapacity; ++i)
+			{
+				m_hashTable[i] = BT_HASH_NULL;
+			}
+			for (i = 0; i < newCapacity; ++i)
+			{
+				m_next[i] = BT_HASH_NULL;
+			}
+
+			for(i=0;i<curHashtableSize;i++)
+			{
+				//const Value& value = m_valueArray[i];
+				//const Key& key = m_keyArray[i];
+
+				int	hashValue = m_keyArray[i].getHash() & (m_valueArray.capacity()-1);	// New hash value with new mask
+				m_next[i] = m_hashTable[hashValue];
+				m_hashTable[hashValue] = i;
+			}
+
+
+		}
+	}
+
+	public:
+
+	void insert(const Key& key, const Value& value) {
+		int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+		//replace value if the key is already there
+		int index = findIndex(key);
+		if (index != BT_HASH_NULL)
+		{
+			m_valueArray[index]=value;
+			return;
+		}
+
+		int count = m_valueArray.size();
+		int oldCapacity = m_valueArray.capacity();
+		m_valueArray.push_back(value);
+		m_keyArray.push_back(key);
+
+		int newCapacity = m_valueArray.capacity();
+		if (oldCapacity < newCapacity)
+		{
+			growTables(key);
+			//hash with new capacity
+			hash = key.getHash() & (m_valueArray.capacity()-1);
+		}
+		m_next[count] = m_hashTable[hash];
+		m_hashTable[hash] = count;
+	}
+
+	void remove(const Key& key) {
+
+		int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+		int pairIndex = findIndex(key);
+		
+		if (pairIndex ==BT_HASH_NULL)
+		{
+			return;
+		}
+
+		// Remove the pair from the hash table.
+		int index = m_hashTable[hash];
+		btAssert(index != BT_HASH_NULL);
+
+		int previous = BT_HASH_NULL;
+		while (index != pairIndex)
+		{
+			previous = index;
+			index = m_next[index];
+		}
+
+		if (previous != BT_HASH_NULL)
+		{
+			btAssert(m_next[previous] == pairIndex);
+			m_next[previous] = m_next[pairIndex];
+		}
+		else
+		{
+			m_hashTable[hash] = m_next[pairIndex];
+		}
+
+		// We now move the last pair into spot of the
+		// pair being removed. We need to fix the hash
+		// table indices to support the move.
+
+		int lastPairIndex = m_valueArray.size() - 1;
+
+		// If the removed pair is the last pair, we are done.
+		if (lastPairIndex == pairIndex)
+		{
+			m_valueArray.pop_back();
+			m_keyArray.pop_back();
+			return;
+		}
+
+		// Remove the last pair from the hash table.
+		int lastHash = m_keyArray[lastPairIndex].getHash() & (m_valueArray.capacity()-1);
+
+		index = m_hashTable[lastHash];
+		btAssert(index != BT_HASH_NULL);
+
+		previous = BT_HASH_NULL;
+		while (index != lastPairIndex)
+		{
+			previous = index;
+			index = m_next[index];
+		}
+
+		if (previous != BT_HASH_NULL)
+		{
+			btAssert(m_next[previous] == lastPairIndex);
+			m_next[previous] = m_next[lastPairIndex];
+		}
+		else
+		{
+			m_hashTable[lastHash] = m_next[lastPairIndex];
+		}
+
+		// Copy the last pair into the remove pair's spot.
+		m_valueArray[pairIndex] = m_valueArray[lastPairIndex];
+		m_keyArray[pairIndex] = m_keyArray[lastPairIndex];
+
+		// Insert the last pair into the hash table
+		m_next[pairIndex] = m_hashTable[lastHash];
+		m_hashTable[lastHash] = pairIndex;
+
+		m_valueArray.pop_back();
+		m_keyArray.pop_back();
+
+	}
+
+
+	int size() const
+	{
+		return m_valueArray.size();
+	}
+
+	const Value* getAtIndex(int index) const
+	{
+		btAssert(index < m_valueArray.size());
+
+		return &m_valueArray[index];
+	}
+
+	Value* getAtIndex(int index)
+	{
+		btAssert(index < m_valueArray.size());
+
+		return &m_valueArray[index];
+	}
+
+	Value* operator[](const Key& key) {
+		return find(key);
+	}
+
+	const Value*	find(const Key& key) const
+	{
+		int index = findIndex(key);
+		if (index == BT_HASH_NULL)
+		{
+			return NULL;
+		}
+		return &m_valueArray[index];
+	}
+
+	Value*	find(const Key& key)
+	{
+		int index = findIndex(key);
+		if (index == BT_HASH_NULL)
+		{
+			return NULL;
+		}
+		return &m_valueArray[index];
+	}
+
+
+	int	findIndex(const Key& key) const
+	{
+		unsigned int hash = key.getHash() & (m_valueArray.capacity()-1);
+
+		if (hash >= (unsigned int)m_hashTable.size())
+		{
+			return BT_HASH_NULL;
+		}
+
+		int index = m_hashTable[hash];
+		while ((index != BT_HASH_NULL) && key.equals(m_keyArray[index]) == false)
+		{
+			index = m_next[index];
+		}
+		return index;
+	}
+
+	void	clear()
+	{
+		m_hashTable.clear();
+		m_next.clear();
+		m_valueArray.clear();
+		m_keyArray.clear();
+	}
+
+};
+
+#endif //BT_HASH_MAP_H
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btIDebugDraw.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btIDebugDraw.h
new file mode 100644
index 0000000..e7849f6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btIDebugDraw.h
@@ -0,0 +1,316 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef IDEBUG_DRAW__H
+#define IDEBUG_DRAW__H
+
+#include "btVector3.h"
+#include "btTransform.h"
+
+
+///The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations.
+///Typical use case: create a debug drawer object, and assign it to a btCollisionWorld or btDynamicsWorld using setDebugDrawer and call debugDrawWorld.
+///A class that implements the btIDebugDraw interface has to implement the drawLine method at a minimum.
+///For color arguments the X,Y,Z components refer to Red, Green and Blue each in the range [0..1]
+class	btIDebugDraw
+{
+	public:
+
+	enum	DebugDrawModes
+	{
+		DBG_NoDebug=0,
+		DBG_DrawWireframe = 1,
+		DBG_DrawAabb=2,
+		DBG_DrawFeaturesText=4,
+		DBG_DrawContactPoints=8,
+		DBG_NoDeactivation=16,
+		DBG_NoHelpText = 32,
+		DBG_DrawText=64,
+		DBG_ProfileTimings = 128,
+		DBG_EnableSatComparison = 256,
+		DBG_DisableBulletLCP = 512,
+		DBG_EnableCCD = 1024,
+		DBG_DrawConstraints = (1 << 11),
+		DBG_DrawConstraintLimits = (1 << 12),
+		DBG_FastWireframe = (1<<13),
+		DBG_MAX_DEBUG_DRAW_MODE
+	};
+
+	virtual ~btIDebugDraw() {};
+
+	virtual void	drawLine(const btVector3& from,const btVector3& to,const btVector3& color)=0;
+		
+	virtual void    drawLine(const btVector3& from,const btVector3& to, const btVector3& fromColor, const btVector3& toColor)
+	{
+        (void) toColor;
+		drawLine (from, to, fromColor);
+	}
+
+	virtual void	drawSphere(btScalar radius, const btTransform& transform, const btVector3& color)
+	{
+		btVector3 start = transform.getOrigin();
+
+		const btVector3 xoffs = transform.getBasis() * btVector3(radius,0,0);
+		const btVector3 yoffs = transform.getBasis() * btVector3(0,radius,0);
+		const btVector3 zoffs = transform.getBasis() * btVector3(0,0,radius);
+
+		// XY 
+		drawLine(start-xoffs, start+yoffs, color);
+		drawLine(start+yoffs, start+xoffs, color);
+		drawLine(start+xoffs, start-yoffs, color);
+		drawLine(start-yoffs, start-xoffs, color);
+
+		// XZ
+		drawLine(start-xoffs, start+zoffs, color);
+		drawLine(start+zoffs, start+xoffs, color);
+		drawLine(start+xoffs, start-zoffs, color);
+		drawLine(start-zoffs, start-xoffs, color);
+
+		// YZ
+		drawLine(start-yoffs, start+zoffs, color);
+		drawLine(start+zoffs, start+yoffs, color);
+		drawLine(start+yoffs, start-zoffs, color);
+		drawLine(start-zoffs, start-yoffs, color);
+	}
+	
+	virtual void	drawSphere (const btVector3& p, btScalar radius, const btVector3& color)
+	{
+		btTransform tr;
+		tr.setIdentity();
+		tr.setOrigin(p);
+		drawSphere(radius,tr,color);
+	}
+	
+	virtual	void	drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& /*n0*/,const btVector3& /*n1*/,const btVector3& /*n2*/,const btVector3& color, btScalar alpha)
+	{
+		drawTriangle(v0,v1,v2,color,alpha);
+	}
+	virtual	void	drawTriangle(const btVector3& v0,const btVector3& v1,const btVector3& v2,const btVector3& color, btScalar /*alpha*/)
+	{
+		drawLine(v0,v1,color);
+		drawLine(v1,v2,color);
+		drawLine(v2,v0,color);
+	}
+
+	virtual void	drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,btScalar distance,int lifeTime,const btVector3& color)=0;
+
+	virtual void	reportErrorWarning(const char* warningString) = 0;
+
+	virtual void	draw3dText(const btVector3& location,const char* textString) = 0;
+	
+	virtual void	setDebugMode(int debugMode) =0;
+	
+	virtual int		getDebugMode() const = 0;
+
+	virtual void drawAabb(const btVector3& from,const btVector3& to,const btVector3& color)
+	{
+
+		btVector3 halfExtents = (to-from)* 0.5f;
+		btVector3 center = (to+from) *0.5f;
+		int i,j;
+
+		btVector3 edgecoord(1.f,1.f,1.f),pa,pb;
+		for (i=0;i<4;i++)
+		{
+			for (j=0;j<3;j++)
+			{
+				pa = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],		
+					edgecoord[2]*halfExtents[2]);
+				pa+=center;
+
+				int othercoord = j%3;
+				edgecoord[othercoord]*=-1.f;
+				pb = btVector3(edgecoord[0]*halfExtents[0], edgecoord[1]*halfExtents[1],	
+					edgecoord[2]*halfExtents[2]);
+				pb+=center;
+
+				drawLine(pa,pb,color);
+			}
+			edgecoord = btVector3(-1.f,-1.f,-1.f);
+			if (i<3)
+				edgecoord[i]*=-1.f;
+		}
+	}
+	virtual void drawTransform(const btTransform& transform, btScalar orthoLen)
+	{
+		btVector3 start = transform.getOrigin();
+		drawLine(start, start+transform.getBasis() * btVector3(orthoLen, 0, 0), btVector3(0.7f,0,0));
+		drawLine(start, start+transform.getBasis() * btVector3(0, orthoLen, 0), btVector3(0,0.7f,0));
+		drawLine(start, start+transform.getBasis() * btVector3(0, 0, orthoLen), btVector3(0,0,0.7f));
+	}
+
+	virtual void drawArc(const btVector3& center, const btVector3& normal, const btVector3& axis, btScalar radiusA, btScalar radiusB, btScalar minAngle, btScalar maxAngle, 
+				const btVector3& color, bool drawSect, btScalar stepDegrees = btScalar(10.f))
+	{
+		const btVector3& vx = axis;
+		btVector3 vy = normal.cross(axis);
+		btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+		int nSteps = (int)((maxAngle - minAngle) / step);
+		if(!nSteps) nSteps = 1;
+		btVector3 prev = center + radiusA * vx * btCos(minAngle) + radiusB * vy * btSin(minAngle);
+		if(drawSect)
+		{
+			drawLine(center, prev, color);
+		}
+		for(int i = 1; i <= nSteps; i++)
+		{
+			btScalar angle = minAngle + (maxAngle - minAngle) * btScalar(i) / btScalar(nSteps);
+			btVector3 next = center + radiusA * vx * btCos(angle) + radiusB * vy * btSin(angle);
+			drawLine(prev, next, color);
+			prev = next;
+		}
+		if(drawSect)
+		{
+			drawLine(center, prev, color);
+		}
+	}
+	virtual void drawSpherePatch(const btVector3& center, const btVector3& up, const btVector3& axis, btScalar radius, 
+		btScalar minTh, btScalar maxTh, btScalar minPs, btScalar maxPs, const btVector3& color, btScalar stepDegrees = btScalar(10.f))
+	{
+		btVector3 vA[74];
+		btVector3 vB[74];
+		btVector3 *pvA = vA, *pvB = vB, *pT;
+		btVector3 npole = center + up * radius;
+		btVector3 spole = center - up * radius;
+		btVector3 arcStart;
+		btScalar step = stepDegrees * SIMD_RADS_PER_DEG;
+		const btVector3& kv = up;
+		const btVector3& iv = axis;
+		btVector3 jv = kv.cross(iv);
+		bool drawN = false;
+		bool drawS = false;
+		if(minTh <= -SIMD_HALF_PI)
+		{
+			minTh = -SIMD_HALF_PI + step;
+			drawN = true;
+		}
+		if(maxTh >= SIMD_HALF_PI)
+		{
+			maxTh = SIMD_HALF_PI - step;
+			drawS = true;
+		}
+		if(minTh > maxTh)
+		{
+			minTh = -SIMD_HALF_PI + step;
+			maxTh =  SIMD_HALF_PI - step;
+			drawN = drawS = true;
+		}
+		int n_hor = (int)((maxTh - minTh) / step) + 1;
+		if(n_hor < 2) n_hor = 2;
+		btScalar step_h = (maxTh - minTh) / btScalar(n_hor - 1);
+		bool isClosed = false;
+		if(minPs > maxPs)
+		{
+			minPs = -SIMD_PI + step;
+			maxPs =  SIMD_PI;
+			isClosed = true;
+		}
+		else if((maxPs - minPs) >= SIMD_PI * btScalar(2.f))
+		{
+			isClosed = true;
+		}
+		else
+		{
+			isClosed = false;
+		}
+		int n_vert = (int)((maxPs - minPs) / step) + 1;
+		if(n_vert < 2) n_vert = 2;
+		btScalar step_v = (maxPs - minPs) / btScalar(n_vert - 1);
+		for(int i = 0; i < n_hor; i++)
+		{
+			btScalar th = minTh + btScalar(i) * step_h;
+			btScalar sth = radius * btSin(th);
+			btScalar cth = radius * btCos(th);
+			for(int j = 0; j < n_vert; j++)
+			{
+				btScalar psi = minPs + btScalar(j) * step_v;
+				btScalar sps = btSin(psi);
+				btScalar cps = btCos(psi);
+				pvB[j] = center + cth * cps * iv + cth * sps * jv + sth * kv;
+				if(i)
+				{
+					drawLine(pvA[j], pvB[j], color);
+				}
+				else if(drawS)
+				{
+					drawLine(spole, pvB[j], color);
+				}
+				if(j)
+				{
+					drawLine(pvB[j-1], pvB[j], color);
+				}
+				else
+				{
+					arcStart = pvB[j];
+				}
+				if((i == (n_hor - 1)) && drawN)
+				{
+					drawLine(npole, pvB[j], color);
+				}
+				if(isClosed)
+				{
+					if(j == (n_vert-1))
+					{
+						drawLine(arcStart, pvB[j], color);
+					}
+				}
+				else
+				{
+					if(((!i) || (i == (n_hor-1))) && ((!j) || (j == (n_vert-1))))
+					{
+						drawLine(center, pvB[j], color);
+					}
+				}
+			}
+			pT = pvA; pvA = pvB; pvB = pT;
+		}
+	}
+	
+	virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btVector3& color)
+	{
+		drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+		drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+		drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+		drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+		drawLine(btVector3(bbMin[0], bbMin[1], bbMin[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMin[1], bbMin[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMax[1], bbMin[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMin[0], bbMax[1], bbMin[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMin[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMin[1], bbMax[2]), btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMax[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(btVector3(bbMin[0], bbMax[1], bbMax[2]), btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+	}
+	virtual void drawBox(const btVector3& bbMin, const btVector3& bbMax, const btTransform& trans, const btVector3& color)
+	{
+		drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMin[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMin[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMin[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMin[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMin[1], bbMax[2]), trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMax[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), color);
+		drawLine(trans * btVector3(bbMin[0], bbMax[1], bbMax[2]), trans * btVector3(bbMin[0], bbMin[1], bbMax[2]), color);
+	}
+};
+
+
+#endif //IDEBUG_DRAW__H
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btList.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btList.h
new file mode 100644
index 0000000..c87b47f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btList.h
@@ -0,0 +1,73 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef GEN_LIST_H
+#define GEN_LIST_H
+
+class btGEN_Link {
+public:
+    btGEN_Link() : m_next(0), m_prev(0) {}
+    btGEN_Link(btGEN_Link *next, btGEN_Link *prev) : m_next(next), m_prev(prev) {}
+    
+    btGEN_Link *getNext() const { return m_next; }  
+    btGEN_Link *getPrev() const { return m_prev; }  
+
+    bool isHead() const { return m_prev == 0; }
+    bool isTail() const { return m_next == 0; }
+
+    void insertBefore(btGEN_Link *link) {
+        m_next         = link;
+        m_prev         = link->m_prev;
+        m_next->m_prev = this;
+        m_prev->m_next = this;
+    } 
+
+    void insertAfter(btGEN_Link *link) {
+        m_next         = link->m_next;
+        m_prev         = link;
+        m_next->m_prev = this;
+        m_prev->m_next = this;
+    } 
+
+    void remove() { 
+        m_next->m_prev = m_prev; 
+        m_prev->m_next = m_next;
+    }
+
+private:  
+    btGEN_Link  *m_next;
+    btGEN_Link  *m_prev;
+};
+
+class btGEN_List {
+public:
+    btGEN_List() : m_head(&m_tail, 0), m_tail(0, &m_head) {}
+
+    btGEN_Link *getHead() const { return m_head.getNext(); } 
+    btGEN_Link *getTail() const { return m_tail.getPrev(); } 
+
+    void addHead(btGEN_Link *link) { link->insertAfter(&m_head); }
+    void addTail(btGEN_Link *link) { link->insertBefore(&m_tail); }
+    
+private:
+    btGEN_Link m_head;
+    btGEN_Link m_tail;
+};
+
+#endif
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btMatrix3x3.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btMatrix3x3.h
new file mode 100644
index 0000000..3c37f6e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btMatrix3x3.h
@@ -0,0 +1,688 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef	BT_MATRIX3x3_H
+#define BT_MATRIX3x3_H
+
+#include "btVector3.h"
+#include "btQuaternion.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btMatrix3x3Data	btMatrix3x3DoubleData 
+#else
+#define btMatrix3x3Data	btMatrix3x3FloatData
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+/**@brief The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with btQuaternion, btTransform and btVector3.
+* Make sure to only include a pure orthogonal matrix without scaling. */
+class btMatrix3x3 {
+
+	///Data storage for the matrix, each vector is a row of the matrix
+	btVector3 m_el[3];
+
+public:
+	/** @brief No initializaion constructor */
+	btMatrix3x3 () {}
+
+	//		explicit btMatrix3x3(const btScalar *m) { setFromOpenGLSubMatrix(m); }
+
+	/**@brief Constructor from Quaternion */
+	explicit btMatrix3x3(const btQuaternion& q) { setRotation(q); }
+	/*
+	template <typename btScalar>
+	Matrix3x3(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{ 
+	setEulerYPR(yaw, pitch, roll);
+	}
+	*/
+	/** @brief Constructor with row major formatting */
+	btMatrix3x3(const btScalar& xx, const btScalar& xy, const btScalar& xz,
+		const btScalar& yx, const btScalar& yy, const btScalar& yz,
+		const btScalar& zx, const btScalar& zy, const btScalar& zz)
+	{ 
+		setValue(xx, xy, xz, 
+			yx, yy, yz, 
+			zx, zy, zz);
+	}
+	/** @brief Copy constructor */
+	SIMD_FORCE_INLINE btMatrix3x3 (const btMatrix3x3& other)
+	{
+		m_el[0] = other.m_el[0];
+		m_el[1] = other.m_el[1];
+		m_el[2] = other.m_el[2];
+	}
+	/** @brief Assignment Operator */
+	SIMD_FORCE_INLINE btMatrix3x3& operator=(const btMatrix3x3& other)
+	{
+		m_el[0] = other.m_el[0];
+		m_el[1] = other.m_el[1];
+		m_el[2] = other.m_el[2];
+		return *this;
+	}
+
+	/** @brief Get a column of the matrix as a vector 
+	*  @param i Column number 0 indexed */
+	SIMD_FORCE_INLINE btVector3 getColumn(int i) const
+	{
+		return btVector3(m_el[0][i],m_el[1][i],m_el[2][i]);
+	}
+
+
+	/** @brief Get a row of the matrix as a vector 
+	*  @param i Row number 0 indexed */
+	SIMD_FORCE_INLINE const btVector3& getRow(int i) const
+	{
+		btFullAssert(0 <= i && i < 3);
+		return m_el[i];
+	}
+
+	/** @brief Get a mutable reference to a row of the matrix as a vector 
+	*  @param i Row number 0 indexed */
+	SIMD_FORCE_INLINE btVector3&  operator[](int i)
+	{ 
+		btFullAssert(0 <= i && i < 3);
+		return m_el[i]; 
+	}
+
+	/** @brief Get a const reference to a row of the matrix as a vector 
+	*  @param i Row number 0 indexed */
+	SIMD_FORCE_INLINE const btVector3& operator[](int i) const
+	{
+		btFullAssert(0 <= i && i < 3);
+		return m_el[i]; 
+	}
+
+	/** @brief Multiply by the target matrix on the right
+	*  @param m Rotation matrix to be applied 
+	* Equivilant to this = this * m */
+	btMatrix3x3& operator*=(const btMatrix3x3& m); 
+
+	/** @brief Set from a carray of btScalars 
+	*  @param m A pointer to the beginning of an array of 9 btScalars */
+	void setFromOpenGLSubMatrix(const btScalar *m)
+	{
+		m_el[0].setValue(m[0],m[4],m[8]);
+		m_el[1].setValue(m[1],m[5],m[9]);
+		m_el[2].setValue(m[2],m[6],m[10]);
+
+	}
+	/** @brief Set the values of the matrix explicitly (row major)
+	*  @param xx Top left
+	*  @param xy Top Middle
+	*  @param xz Top Right
+	*  @param yx Middle Left
+	*  @param yy Middle Middle
+	*  @param yz Middle Right
+	*  @param zx Bottom Left
+	*  @param zy Bottom Middle
+	*  @param zz Bottom Right*/
+	void setValue(const btScalar& xx, const btScalar& xy, const btScalar& xz, 
+		const btScalar& yx, const btScalar& yy, const btScalar& yz, 
+		const btScalar& zx, const btScalar& zy, const btScalar& zz)
+	{
+		m_el[0].setValue(xx,xy,xz);
+		m_el[1].setValue(yx,yy,yz);
+		m_el[2].setValue(zx,zy,zz);
+	}
+
+	/** @brief Set the matrix from a quaternion
+	*  @param q The Quaternion to match */  
+	void setRotation(const btQuaternion& q) 
+	{
+		btScalar d = q.length2();
+		btFullAssert(d != btScalar(0.0));
+		btScalar s = btScalar(2.0) / d;
+		btScalar xs = q.x() * s,   ys = q.y() * s,   zs = q.z() * s;
+		btScalar wx = q.w() * xs,  wy = q.w() * ys,  wz = q.w() * zs;
+		btScalar xx = q.x() * xs,  xy = q.x() * ys,  xz = q.x() * zs;
+		btScalar yy = q.y() * ys,  yz = q.y() * zs,  zz = q.z() * zs;
+		setValue(btScalar(1.0) - (yy + zz), xy - wz, xz + wy,
+			xy + wz, btScalar(1.0) - (xx + zz), yz - wx,
+			xz - wy, yz + wx, btScalar(1.0) - (xx + yy));
+	}
+
+
+	/** @brief Set the matrix from euler angles using YPR around YXZ respectively
+	*  @param yaw Yaw about Y axis
+	*  @param pitch Pitch about X axis
+	*  @param roll Roll about Z axis 
+	*/
+	void setEulerYPR(const btScalar& yaw, const btScalar& pitch, const btScalar& roll) 
+	{
+		setEulerZYX(roll, pitch, yaw);
+	}
+
+	/** @brief Set the matrix from euler angles YPR around ZYX axes
+	* @param eulerX Roll about X axis
+	* @param eulerY Pitch around Y axis
+	* @param eulerZ Yaw aboud Z axis
+	* 
+	* These angles are used to produce a rotation matrix. The euler
+	* angles are applied in ZYX order. I.e a vector is first rotated 
+	* about X then Y and then Z
+	**/
+	void setEulerZYX(btScalar eulerX,btScalar eulerY,btScalar eulerZ) { 
+		///@todo proposed to reverse this since it's labeled zyx but takes arguments xyz and it will match all other parts of the code
+		btScalar ci ( btCos(eulerX)); 
+		btScalar cj ( btCos(eulerY)); 
+		btScalar ch ( btCos(eulerZ)); 
+		btScalar si ( btSin(eulerX)); 
+		btScalar sj ( btSin(eulerY)); 
+		btScalar sh ( btSin(eulerZ)); 
+		btScalar cc = ci * ch; 
+		btScalar cs = ci * sh; 
+		btScalar sc = si * ch; 
+		btScalar ss = si * sh;
+
+		setValue(cj * ch, sj * sc - cs, sj * cc + ss,
+			cj * sh, sj * ss + cc, sj * cs - sc, 
+			-sj,      cj * si,      cj * ci);
+	}
+
+	/**@brief Set the matrix to the identity */
+	void setIdentity()
+	{ 
+		setValue(btScalar(1.0), btScalar(0.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(1.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(0.0), btScalar(1.0)); 
+	}
+
+	static const btMatrix3x3&	getIdentity()
+	{
+		static const btMatrix3x3 identityMatrix(btScalar(1.0), btScalar(0.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(1.0), btScalar(0.0), 
+			btScalar(0.0), btScalar(0.0), btScalar(1.0));
+		return identityMatrix;
+	}
+
+	/**@brief Fill the values of the matrix into a 9 element array 
+	* @param m The array to be filled */
+	void getOpenGLSubMatrix(btScalar *m) const 
+	{
+		m[0]  = btScalar(m_el[0].x()); 
+		m[1]  = btScalar(m_el[1].x());
+		m[2]  = btScalar(m_el[2].x());
+		m[3]  = btScalar(0.0); 
+		m[4]  = btScalar(m_el[0].y());
+		m[5]  = btScalar(m_el[1].y());
+		m[6]  = btScalar(m_el[2].y());
+		m[7]  = btScalar(0.0); 
+		m[8]  = btScalar(m_el[0].z()); 
+		m[9]  = btScalar(m_el[1].z());
+		m[10] = btScalar(m_el[2].z());
+		m[11] = btScalar(0.0); 
+	}
+
+	/**@brief Get the matrix represented as a quaternion 
+	* @param q The quaternion which will be set */
+	void getRotation(btQuaternion& q) const
+	{
+		btScalar trace = m_el[0].x() + m_el[1].y() + m_el[2].z();
+		btScalar temp[4];
+
+		if (trace > btScalar(0.0)) 
+		{
+			btScalar s = btSqrt(trace + btScalar(1.0));
+			temp[3]=(s * btScalar(0.5));
+			s = btScalar(0.5) / s;
+
+			temp[0]=((m_el[2].y() - m_el[1].z()) * s);
+			temp[1]=((m_el[0].z() - m_el[2].x()) * s);
+			temp[2]=((m_el[1].x() - m_el[0].y()) * s);
+		} 
+		else 
+		{
+			int i = m_el[0].x() < m_el[1].y() ? 
+				(m_el[1].y() < m_el[2].z() ? 2 : 1) :
+				(m_el[0].x() < m_el[2].z() ? 2 : 0); 
+			int j = (i + 1) % 3;  
+			int k = (i + 2) % 3;
+
+			btScalar s = btSqrt(m_el[i][i] - m_el[j][j] - m_el[k][k] + btScalar(1.0));
+			temp[i] = s * btScalar(0.5);
+			s = btScalar(0.5) / s;
+
+			temp[3] = (m_el[k][j] - m_el[j][k]) * s;
+			temp[j] = (m_el[j][i] + m_el[i][j]) * s;
+			temp[k] = (m_el[k][i] + m_el[i][k]) * s;
+		}
+		q.setValue(temp[0],temp[1],temp[2],temp[3]);
+	}
+
+	/**@brief Get the matrix represented as euler angles around YXZ, roundtrip with setEulerYPR
+	* @param yaw Yaw around Y axis
+	* @param pitch Pitch around X axis
+	* @param roll around Z axis */	
+	void getEulerYPR(btScalar& yaw, btScalar& pitch, btScalar& roll) const
+	{
+
+		// first use the normal calculus
+		yaw = btScalar(btAtan2(m_el[1].x(), m_el[0].x()));
+		pitch = btScalar(btAsin(-m_el[2].x()));
+		roll = btScalar(btAtan2(m_el[2].y(), m_el[2].z()));
+
+		// on pitch = +/-HalfPI
+		if (btFabs(pitch)==SIMD_HALF_PI)
+		{
+			if (yaw>0)
+				yaw-=SIMD_PI;
+			else
+				yaw+=SIMD_PI;
+
+			if (roll>0)
+				roll-=SIMD_PI;
+			else
+				roll+=SIMD_PI;
+		}
+	};
+
+
+	/**@brief Get the matrix represented as euler angles around ZYX
+	* @param yaw Yaw around X axis
+	* @param pitch Pitch around Y axis
+	* @param roll around X axis 
+	* @param solution_number Which solution of two possible solutions ( 1 or 2) are possible values*/	
+	void getEulerZYX(btScalar& yaw, btScalar& pitch, btScalar& roll, unsigned int solution_number = 1) const
+	{
+		struct Euler
+		{
+			btScalar yaw;
+			btScalar pitch;
+			btScalar roll;
+		};
+
+		Euler euler_out;
+		Euler euler_out2; //second solution
+		//get the pointer to the raw data
+
+		// Check that pitch is not at a singularity
+		if (btFabs(m_el[2].x()) >= 1)
+		{
+			euler_out.yaw = 0;
+			euler_out2.yaw = 0;
+
+			// From difference of angles formula
+			btScalar delta = btAtan2(m_el[0].x(),m_el[0].z());
+			if (m_el[2].x() > 0)  //gimbal locked up
+			{
+				euler_out.pitch = SIMD_PI / btScalar(2.0);
+				euler_out2.pitch = SIMD_PI / btScalar(2.0);
+				euler_out.roll = euler_out.pitch + delta;
+				euler_out2.roll = euler_out.pitch + delta;
+			}
+			else // gimbal locked down
+			{
+				euler_out.pitch = -SIMD_PI / btScalar(2.0);
+				euler_out2.pitch = -SIMD_PI / btScalar(2.0);
+				euler_out.roll = -euler_out.pitch + delta;
+				euler_out2.roll = -euler_out.pitch + delta;
+			}
+		}
+		else
+		{
+			euler_out.pitch = - btAsin(m_el[2].x());
+			euler_out2.pitch = SIMD_PI - euler_out.pitch;
+
+			euler_out.roll = btAtan2(m_el[2].y()/btCos(euler_out.pitch), 
+				m_el[2].z()/btCos(euler_out.pitch));
+			euler_out2.roll = btAtan2(m_el[2].y()/btCos(euler_out2.pitch), 
+				m_el[2].z()/btCos(euler_out2.pitch));
+
+			euler_out.yaw = btAtan2(m_el[1].x()/btCos(euler_out.pitch), 
+				m_el[0].x()/btCos(euler_out.pitch));
+			euler_out2.yaw = btAtan2(m_el[1].x()/btCos(euler_out2.pitch), 
+				m_el[0].x()/btCos(euler_out2.pitch));
+		}
+
+		if (solution_number == 1)
+		{ 
+			yaw = euler_out.yaw; 
+			pitch = euler_out.pitch;
+			roll = euler_out.roll;
+		}
+		else
+		{ 
+			yaw = euler_out2.yaw; 
+			pitch = euler_out2.pitch;
+			roll = euler_out2.roll;
+		}
+	}
+
+	/**@brief Create a scaled copy of the matrix 
+	* @param s Scaling vector The elements of the vector will scale each column */
+
+	btMatrix3x3 scaled(const btVector3& s) const
+	{
+		return btMatrix3x3(m_el[0].x() * s.x(), m_el[0].y() * s.y(), m_el[0].z() * s.z(),
+			m_el[1].x() * s.x(), m_el[1].y() * s.y(), m_el[1].z() * s.z(),
+			m_el[2].x() * s.x(), m_el[2].y() * s.y(), m_el[2].z() * s.z());
+	}
+
+	/**@brief Return the determinant of the matrix */
+	btScalar            determinant() const;
+	/**@brief Return the adjoint of the matrix */
+	btMatrix3x3 adjoint() const;
+	/**@brief Return the matrix with all values non negative */
+	btMatrix3x3 absolute() const;
+	/**@brief Return the transpose of the matrix */
+	btMatrix3x3 transpose() const;
+	/**@brief Return the inverse of the matrix */
+	btMatrix3x3 inverse() const; 
+
+	btMatrix3x3 transposeTimes(const btMatrix3x3& m) const;
+	btMatrix3x3 timesTranspose(const btMatrix3x3& m) const;
+
+	SIMD_FORCE_INLINE btScalar tdotx(const btVector3& v) const 
+	{
+		return m_el[0].x() * v.x() + m_el[1].x() * v.y() + m_el[2].x() * v.z();
+	}
+	SIMD_FORCE_INLINE btScalar tdoty(const btVector3& v) const 
+	{
+		return m_el[0].y() * v.x() + m_el[1].y() * v.y() + m_el[2].y() * v.z();
+	}
+	SIMD_FORCE_INLINE btScalar tdotz(const btVector3& v) const 
+	{
+		return m_el[0].z() * v.x() + m_el[1].z() * v.y() + m_el[2].z() * v.z();
+	}
+
+
+	/**@brief diagonalizes this matrix by the Jacobi method.
+	* @param rot stores the rotation from the coordinate system in which the matrix is diagonal to the original
+	* coordinate system, i.e., old_this = rot * new_this * rot^T. 
+	* @param threshold See iteration
+	* @param iteration The iteration stops when all off-diagonal elements are less than the threshold multiplied 
+	* by the sum of the absolute values of the diagonal, or when maxSteps have been executed. 
+	* 
+	* Note that this matrix is assumed to be symmetric. 
+	*/
+	void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps)
+	{
+		rot.setIdentity();
+		for (int step = maxSteps; step > 0; step--)
+		{
+			// find off-diagonal element [p][q] with largest magnitude
+			int p = 0;
+			int q = 1;
+			int r = 2;
+			btScalar max = btFabs(m_el[0][1]);
+			btScalar v = btFabs(m_el[0][2]);
+			if (v > max)
+			{
+				q = 2;
+				r = 1;
+				max = v;
+			}
+			v = btFabs(m_el[1][2]);
+			if (v > max)
+			{
+				p = 1;
+				q = 2;
+				r = 0;
+				max = v;
+			}
+
+			btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2]));
+			if (max <= t)
+			{
+				if (max <= SIMD_EPSILON * t)
+				{
+					return;
+				}
+				step = 1;
+			}
+
+			// compute Jacobi rotation J which leads to a zero for element [p][q] 
+			btScalar mpq = m_el[p][q];
+			btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq);
+			btScalar theta2 = theta * theta;
+			btScalar cos;
+			btScalar sin;
+			if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON))
+			{
+				t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2))
+					: 1 / (theta - btSqrt(1 + theta2));
+				cos = 1 / btSqrt(1 + t * t);
+				sin = cos * t;
+			}
+			else
+			{
+				// approximation for large theta-value, i.e., a nearly diagonal matrix
+				t = 1 / (theta * (2 + btScalar(0.5) / theta2));
+				cos = 1 - btScalar(0.5) * t * t;
+				sin = cos * t;
+			}
+
+			// apply rotation to matrix (this = J^T * this * J)
+			m_el[p][q] = m_el[q][p] = 0;
+			m_el[p][p] -= t * mpq;
+			m_el[q][q] += t * mpq;
+			btScalar mrp = m_el[r][p];
+			btScalar mrq = m_el[r][q];
+			m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq;
+			m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp;
+
+			// apply rotation to rot (rot = rot * J)
+			for (int i = 0; i < 3; i++)
+			{
+				btVector3& row = rot[i];
+				mrp = row[p];
+				mrq = row[q];
+				row[p] = cos * mrp - sin * mrq;
+				row[q] = cos * mrq + sin * mrp;
+			}
+		}
+	}
+
+
+
+
+	/**@brief Calculate the matrix cofactor 
+	* @param r1 The first row to use for calculating the cofactor
+	* @param c1 The first column to use for calculating the cofactor
+	* @param r1 The second row to use for calculating the cofactor
+	* @param c1 The second column to use for calculating the cofactor
+	* See http://en.wikipedia.org/wiki/Cofactor_(linear_algebra) for more details
+	*/
+	btScalar cofac(int r1, int c1, int r2, int c2) const 
+	{
+		return m_el[r1][c1] * m_el[r2][c2] - m_el[r1][c2] * m_el[r2][c1];
+	}
+
+	void	serialize(struct	btMatrix3x3Data& dataOut) const;
+
+	void	serializeFloat(struct	btMatrix3x3FloatData& dataOut) const;
+
+	void	deSerialize(const struct	btMatrix3x3Data& dataIn);
+
+	void	deSerializeFloat(const struct	btMatrix3x3FloatData& dataIn);
+
+	void	deSerializeDouble(const struct	btMatrix3x3DoubleData& dataIn);
+
+};
+
+
+SIMD_FORCE_INLINE btMatrix3x3& 
+btMatrix3x3::operator*=(const btMatrix3x3& m)
+{
+	setValue(m.tdotx(m_el[0]), m.tdoty(m_el[0]), m.tdotz(m_el[0]),
+		m.tdotx(m_el[1]), m.tdoty(m_el[1]), m.tdotz(m_el[1]),
+		m.tdotx(m_el[2]), m.tdoty(m_el[2]), m.tdotz(m_el[2]));
+	return *this;
+}
+
+SIMD_FORCE_INLINE btScalar 
+btMatrix3x3::determinant() const
+{ 
+	return btTriple((*this)[0], (*this)[1], (*this)[2]);
+}
+
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::absolute() const
+{
+	return btMatrix3x3(
+		btFabs(m_el[0].x()), btFabs(m_el[0].y()), btFabs(m_el[0].z()),
+		btFabs(m_el[1].x()), btFabs(m_el[1].y()), btFabs(m_el[1].z()),
+		btFabs(m_el[2].x()), btFabs(m_el[2].y()), btFabs(m_el[2].z()));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::transpose() const 
+{
+	return btMatrix3x3(m_el[0].x(), m_el[1].x(), m_el[2].x(),
+		m_el[0].y(), m_el[1].y(), m_el[2].y(),
+		m_el[0].z(), m_el[1].z(), m_el[2].z());
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::adjoint() const 
+{
+	return btMatrix3x3(cofac(1, 1, 2, 2), cofac(0, 2, 2, 1), cofac(0, 1, 1, 2),
+		cofac(1, 2, 2, 0), cofac(0, 0, 2, 2), cofac(0, 2, 1, 0),
+		cofac(1, 0, 2, 1), cofac(0, 1, 2, 0), cofac(0, 0, 1, 1));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::inverse() const
+{
+	btVector3 co(cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1));
+	btScalar det = (*this)[0].dot(co);
+	btFullAssert(det != btScalar(0.0));
+	btScalar s = btScalar(1.0) / det;
+	return btMatrix3x3(co.x() * s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
+		co.y() * s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
+		co.z() * s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s);
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::transposeTimes(const btMatrix3x3& m) const
+{
+	return btMatrix3x3(
+		m_el[0].x() * m[0].x() + m_el[1].x() * m[1].x() + m_el[2].x() * m[2].x(),
+		m_el[0].x() * m[0].y() + m_el[1].x() * m[1].y() + m_el[2].x() * m[2].y(),
+		m_el[0].x() * m[0].z() + m_el[1].x() * m[1].z() + m_el[2].x() * m[2].z(),
+		m_el[0].y() * m[0].x() + m_el[1].y() * m[1].x() + m_el[2].y() * m[2].x(),
+		m_el[0].y() * m[0].y() + m_el[1].y() * m[1].y() + m_el[2].y() * m[2].y(),
+		m_el[0].y() * m[0].z() + m_el[1].y() * m[1].z() + m_el[2].y() * m[2].z(),
+		m_el[0].z() * m[0].x() + m_el[1].z() * m[1].x() + m_el[2].z() * m[2].x(),
+		m_el[0].z() * m[0].y() + m_el[1].z() * m[1].y() + m_el[2].z() * m[2].y(),
+		m_el[0].z() * m[0].z() + m_el[1].z() * m[1].z() + m_el[2].z() * m[2].z());
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+btMatrix3x3::timesTranspose(const btMatrix3x3& m) const
+{
+	return btMatrix3x3(
+		m_el[0].dot(m[0]), m_el[0].dot(m[1]), m_el[0].dot(m[2]),
+		m_el[1].dot(m[0]), m_el[1].dot(m[1]), m_el[1].dot(m[2]),
+		m_el[2].dot(m[0]), m_el[2].dot(m[1]), m_el[2].dot(m[2]));
+
+}
+
+SIMD_FORCE_INLINE btVector3 
+operator*(const btMatrix3x3& m, const btVector3& v) 
+{
+	return btVector3(m[0].dot(v), m[1].dot(v), m[2].dot(v));
+}
+
+
+SIMD_FORCE_INLINE btVector3
+operator*(const btVector3& v, const btMatrix3x3& m)
+{
+	return btVector3(m.tdotx(v), m.tdoty(v), m.tdotz(v));
+}
+
+SIMD_FORCE_INLINE btMatrix3x3 
+operator*(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+	return btMatrix3x3(
+		m2.tdotx( m1[0]), m2.tdoty( m1[0]), m2.tdotz( m1[0]),
+		m2.tdotx( m1[1]), m2.tdoty( m1[1]), m2.tdotz( m1[1]),
+		m2.tdotx( m1[2]), m2.tdoty( m1[2]), m2.tdotz( m1[2]));
+}
+
+/*
+SIMD_FORCE_INLINE btMatrix3x3 btMultTransposeLeft(const btMatrix3x3& m1, const btMatrix3x3& m2) {
+return btMatrix3x3(
+m1[0][0] * m2[0][0] + m1[1][0] * m2[1][0] + m1[2][0] * m2[2][0],
+m1[0][0] * m2[0][1] + m1[1][0] * m2[1][1] + m1[2][0] * m2[2][1],
+m1[0][0] * m2[0][2] + m1[1][0] * m2[1][2] + m1[2][0] * m2[2][2],
+m1[0][1] * m2[0][0] + m1[1][1] * m2[1][0] + m1[2][1] * m2[2][0],
+m1[0][1] * m2[0][1] + m1[1][1] * m2[1][1] + m1[2][1] * m2[2][1],
+m1[0][1] * m2[0][2] + m1[1][1] * m2[1][2] + m1[2][1] * m2[2][2],
+m1[0][2] * m2[0][0] + m1[1][2] * m2[1][0] + m1[2][2] * m2[2][0],
+m1[0][2] * m2[0][1] + m1[1][2] * m2[1][1] + m1[2][2] * m2[2][1],
+m1[0][2] * m2[0][2] + m1[1][2] * m2[1][2] + m1[2][2] * m2[2][2]);
+}
+*/
+
+/**@brief Equality operator between two matrices
+* It will test all elements are equal.  */
+SIMD_FORCE_INLINE bool operator==(const btMatrix3x3& m1, const btMatrix3x3& m2)
+{
+	return ( m1[0][0] == m2[0][0] && m1[1][0] == m2[1][0] && m1[2][0] == m2[2][0] &&
+		m1[0][1] == m2[0][1] && m1[1][1] == m2[1][1] && m1[2][1] == m2[2][1] &&
+		m1[0][2] == m2[0][2] && m1[1][2] == m2[1][2] && m1[2][2] == m2[2][2] );
+}
+
+///for serialization
+struct	btMatrix3x3FloatData
+{
+	btVector3FloatData m_el[3];
+};
+
+///for serialization
+struct	btMatrix3x3DoubleData
+{
+	btVector3DoubleData m_el[3];
+};
+
+
+	
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::serialize(struct	btMatrix3x3Data& dataOut) const
+{
+	for (int i=0;i<3;i++)
+		m_el[i].serialize(dataOut.m_el[i]);
+}
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::serializeFloat(struct	btMatrix3x3FloatData& dataOut) const
+{
+	for (int i=0;i<3;i++)
+		m_el[i].serializeFloat(dataOut.m_el[i]);
+}
+
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::deSerialize(const struct	btMatrix3x3Data& dataIn)
+{
+	for (int i=0;i<3;i++)
+		m_el[i].deSerialize(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::deSerializeFloat(const struct	btMatrix3x3FloatData& dataIn)
+{
+	for (int i=0;i<3;i++)
+		m_el[i].deSerializeFloat(dataIn.m_el[i]);
+}
+
+SIMD_FORCE_INLINE	void	btMatrix3x3::deSerializeDouble(const struct	btMatrix3x3DoubleData& dataIn)
+{
+	for (int i=0;i<3;i++)
+		m_el[i].deSerializeDouble(dataIn.m_el[i]);
+}
+
+#endif //BT_MATRIX3x3_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btMinMax.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btMinMax.h
new file mode 100644
index 0000000..80601c1
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btMinMax.h
@@ -0,0 +1,71 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef GEN_MINMAX_H
+#define GEN_MINMAX_H
+
+#include "LinearMath/btScalar.h"
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMin(const T& a, const T& b) 
+{
+  return a < b ? a : b ;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btMax(const T& a, const T& b) 
+{
+  return  a > b ? a : b;
+}
+
+template <class T>
+SIMD_FORCE_INLINE const T& btClamped(const T& a, const T& lb, const T& ub) 
+{
+	return a < lb ? lb : (ub < a ? ub : a); 
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMin(T& a, const T& b) 
+{
+    if (b < a) 
+	{
+		a = b;
+	}
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btSetMax(T& a, const T& b) 
+{
+    if (a < b) 
+	{
+		a = b;
+	}
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btClamp(T& a, const T& lb, const T& ub) 
+{
+	if (a < lb) 
+	{
+		a = lb; 
+	}
+	else if (ub < a) 
+	{
+		a = ub;
+	}
+}
+
+#endif
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btMotionState.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btMotionState.h
new file mode 100644
index 0000000..9431814
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btMotionState.h
@@ -0,0 +1,40 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_MOTIONSTATE_H
+#define BT_MOTIONSTATE_H
+
+#include "btTransform.h"
+
+///The btMotionState interface class allows the dynamics world to synchronize and interpolate the updated world transforms with graphics
+///For optimizations, potentially only moving objects get synchronized (using setWorldPosition/setWorldOrientation)
+class	btMotionState
+{
+	public:
+		
+		virtual ~btMotionState()
+		{
+			
+		}
+		
+		virtual void	getWorldTransform(btTransform& worldTrans ) const =0;
+
+		//Bullet only calls the update of worldtransform for active objects
+		virtual void	setWorldTransform(const btTransform& worldTrans)=0;
+		
+	
+};
+
+#endif //BT_MOTIONSTATE_H
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btPoolAllocator.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btPoolAllocator.h
new file mode 100644
index 0000000..e3b4be9
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btPoolAllocator.h
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef _BT_POOL_ALLOCATOR_H
+#define _BT_POOL_ALLOCATOR_H
+
+#include "btScalar.h"
+#include "btAlignedAllocator.h"
+
+///The btPoolAllocator class allows to efficiently allocate a large pool of objects, instead of dynamically allocating them separately.
+class btPoolAllocator
+{
+	int				m_elemSize;
+	int				m_maxElements;
+	int				m_freeCount;
+	void*			m_firstFree;
+	unsigned char*	m_pool;
+
+public:
+
+	btPoolAllocator(int elemSize, int maxElements)
+		:m_elemSize(elemSize),
+		m_maxElements(maxElements)
+	{
+		m_pool = (unsigned char*) btAlignedAlloc( static_cast<unsigned int>(m_elemSize*m_maxElements),16);
+
+		unsigned char* p = m_pool;
+        m_firstFree = p;
+        m_freeCount = m_maxElements;
+        int count = m_maxElements;
+        while (--count) {
+            *(void**)p = (p + m_elemSize);
+            p += m_elemSize;
+        }
+        *(void**)p = 0;
+    }
+
+	~btPoolAllocator()
+	{
+		btAlignedFree( m_pool);
+	}
+
+	int	getFreeCount() const
+	{
+		return m_freeCount;
+	}
+
+	int getUsedCount() const
+	{
+		return m_maxElements - m_freeCount;
+	}
+
+	void*	allocate(int size)
+	{
+		// release mode fix
+		(void)size;
+		btAssert(!size || size<=m_elemSize);
+		btAssert(m_freeCount>0);
+        void* result = m_firstFree;
+        m_firstFree = *(void**)m_firstFree;
+        --m_freeCount;
+        return result;
+	}
+
+	bool validPtr(void* ptr)
+	{
+		if (ptr) {
+			if (((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize))
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+
+	void	freeMemory(void* ptr)
+	{
+		 if (ptr) {
+            btAssert((unsigned char*)ptr >= m_pool && (unsigned char*)ptr < m_pool + m_maxElements * m_elemSize);
+
+            *(void**)ptr = m_firstFree;
+            m_firstFree = ptr;
+            ++m_freeCount;
+        }
+	}
+
+	int	getElementSize() const
+	{
+		return m_elemSize;
+	}
+
+	unsigned char*	getPoolAddress()
+	{
+		return m_pool;
+	}
+
+	const unsigned char*	getPoolAddress() const
+	{
+		return m_pool;
+	}
+
+};
+
+#endif //_BT_POOL_ALLOCATOR_H
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btQuadWord.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuadWord.h
new file mode 100644
index 0000000..c657afd
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuadWord.h
@@ -0,0 +1,180 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef SIMD_QUADWORD_H
+#define SIMD_QUADWORD_H
+
+#include "btScalar.h"
+#include "btMinMax.h"
+
+
+#if defined (__CELLOS_LV2) && defined (__SPU__)
+#include <altivec.h>
+#endif
+
+/**@brief The btQuadWord class is base class for btVector3 and btQuaternion. 
+ * Some issues under PS3 Linux with IBM 2.1 SDK, gcc compiler prevent from using aligned quadword.
+ */
+#ifndef USE_LIBSPE2
+ATTRIBUTE_ALIGNED16(class) btQuadWord
+#else
+class btQuadWord
+#endif
+{
+protected:
+
+#if defined (__SPU__) && defined (__CELLOS_LV2__)
+	union {
+		vec_float4 mVec128;
+		btScalar	m_floats[4];
+	};
+public:
+	vec_float4	get128() const
+	{
+		return mVec128;
+	}
+protected:
+#else //__CELLOS_LV2__ __SPU__
+	btScalar	m_floats[4];
+#endif //__CELLOS_LV2__ __SPU__
+
+	public:
+  
+
+  /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+  /**@brief Set the x value */
+		SIMD_FORCE_INLINE void	setX(btScalar x) { m_floats[0] = x;};
+  /**@brief Set the y value */
+		SIMD_FORCE_INLINE void	setY(btScalar y) { m_floats[1] = y;};
+  /**@brief Set the z value */
+		SIMD_FORCE_INLINE void	setZ(btScalar z) { m_floats[2] = z;};
+  /**@brief Set the w value */
+		SIMD_FORCE_INLINE void	setW(btScalar w) { m_floats[3] = w;};
+  /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+  /**@brief Return the w value */
+		SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+	//SIMD_FORCE_INLINE btScalar&       operator[](int i)       { return (&m_floats[0])[i];	}      
+	//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+	///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+	SIMD_FORCE_INLINE	operator       btScalar *()       { return &m_floats[0]; }
+	SIMD_FORCE_INLINE	operator const btScalar *() const { return &m_floats[0]; }
+
+	SIMD_FORCE_INLINE	bool	operator==(const btQuadWord& other) const
+	{
+		return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
+	}
+
+	SIMD_FORCE_INLINE	bool	operator!=(const btQuadWord& other) const
+	{
+		return !(*this == other);
+	}
+
+  /**@brief Set x,y,z and zero w 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+		SIMD_FORCE_INLINE void 	setValue(const btScalar& x, const btScalar& y, const btScalar& z)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3] = 0.f;
+		}
+
+/*		void getValue(btScalar *m) const 
+		{
+			m[0] = m_floats[0];
+			m[1] = m_floats[1];
+			m[2] = m_floats[2];
+		}
+*/
+/**@brief Set the values 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+		SIMD_FORCE_INLINE void	setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3]=w;
+		}
+  /**@brief No initialization constructor */
+		SIMD_FORCE_INLINE btQuadWord()
+		//	:m_floats[0](btScalar(0.)),m_floats[1](btScalar(0.)),m_floats[2](btScalar(0.)),m_floats[3](btScalar(0.))
+		{
+		}
+ 
+  /**@brief Three argument constructor (zeros w)
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+		SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z)		
+		{
+			m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = 0.0f;
+		}
+
+/**@brief Initializing constructor
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+		SIMD_FORCE_INLINE btQuadWord(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 
+		{
+			m_floats[0] = x, m_floats[1] = y, m_floats[2] = z, m_floats[3] = w;
+		}
+
+  /**@brief Set each element to the max of the current values and the values of another btQuadWord
+   * @param other The other btQuadWord to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMax(const btQuadWord& other)
+		{
+			btSetMax(m_floats[0], other.m_floats[0]);
+			btSetMax(m_floats[1], other.m_floats[1]);
+			btSetMax(m_floats[2], other.m_floats[2]);
+			btSetMax(m_floats[3], other.m_floats[3]);
+		}
+  /**@brief Set each element to the min of the current values and the values of another btQuadWord
+   * @param other The other btQuadWord to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMin(const btQuadWord& other)
+		{
+			btSetMin(m_floats[0], other.m_floats[0]);
+			btSetMin(m_floats[1], other.m_floats[1]);
+			btSetMin(m_floats[2], other.m_floats[2]);
+			btSetMin(m_floats[3], other.m_floats[3]);
+		}
+
+
+
+};
+
+#endif //SIMD_QUADWORD_H
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btQuaternion.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuaternion.h
new file mode 100644
index 0000000..15cf5f8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuaternion.h
@@ -0,0 +1,433 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef SIMD__QUATERNION_H_
+#define SIMD__QUATERNION_H_
+
+
+#include "btVector3.h"
+#include "btQuadWord.h"
+
+/**@brief The btQuaternion implements quaternion to perform linear algebra rotations in combination with btMatrix3x3, btVector3 and btTransform. */
+class btQuaternion : public btQuadWord {
+public:
+  /**@brief No initialization constructor */
+	btQuaternion() {}
+
+	//		template <typename btScalar>
+	//		explicit Quaternion(const btScalar *v) : Tuple4<btScalar>(v) {}
+  /**@brief Constructor from scalars */
+	btQuaternion(const btScalar& x, const btScalar& y, const btScalar& z, const btScalar& w) 
+		: btQuadWord(x, y, z, w) 
+	{}
+  /**@brief Axis angle Constructor
+   * @param axis The axis which the rotation is around
+   * @param angle The magnitude of the rotation around the angle (Radians) */
+	btQuaternion(const btVector3& axis, const btScalar& angle) 
+	{ 
+		setRotation(axis, angle); 
+	}
+  /**@brief Constructor from Euler angles
+   * @param yaw Angle around Y unless BT_EULER_DEFAULT_ZYX defined then Z
+   * @param pitch Angle around X unless BT_EULER_DEFAULT_ZYX defined then Y
+   * @param roll Angle around Z unless BT_EULER_DEFAULT_ZYX defined then X */
+	btQuaternion(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{ 
+#ifndef BT_EULER_DEFAULT_ZYX
+		setEuler(yaw, pitch, roll); 
+#else
+		setEulerZYX(yaw, pitch, roll); 
+#endif 
+	}
+  /**@brief Set the rotation using axis angle notation 
+   * @param axis The axis around which to rotate
+   * @param angle The magnitude of the rotation in Radians */
+	void setRotation(const btVector3& axis, const btScalar& angle)
+	{
+		btScalar d = axis.length();
+		btAssert(d != btScalar(0.0));
+		btScalar s = btSin(angle * btScalar(0.5)) / d;
+		setValue(axis.x() * s, axis.y() * s, axis.z() * s, 
+			btCos(angle * btScalar(0.5)));
+	}
+  /**@brief Set the quaternion using Euler angles
+   * @param yaw Angle around Y
+   * @param pitch Angle around X
+   * @param roll Angle around Z */
+	void setEuler(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{
+		btScalar halfYaw = btScalar(yaw) * btScalar(0.5);  
+		btScalar halfPitch = btScalar(pitch) * btScalar(0.5);  
+		btScalar halfRoll = btScalar(roll) * btScalar(0.5);  
+		btScalar cosYaw = btCos(halfYaw);
+		btScalar sinYaw = btSin(halfYaw);
+		btScalar cosPitch = btCos(halfPitch);
+		btScalar sinPitch = btSin(halfPitch);
+		btScalar cosRoll = btCos(halfRoll);
+		btScalar sinRoll = btSin(halfRoll);
+		setValue(cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw,
+			cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw,
+			sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw,
+			cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw);
+	}
+  /**@brief Set the quaternion using euler angles 
+   * @param yaw Angle around Z
+   * @param pitch Angle around Y
+   * @param roll Angle around X */
+	void setEulerZYX(const btScalar& yaw, const btScalar& pitch, const btScalar& roll)
+	{
+		btScalar halfYaw = btScalar(yaw) * btScalar(0.5);  
+		btScalar halfPitch = btScalar(pitch) * btScalar(0.5);  
+		btScalar halfRoll = btScalar(roll) * btScalar(0.5);  
+		btScalar cosYaw = btCos(halfYaw);
+		btScalar sinYaw = btSin(halfYaw);
+		btScalar cosPitch = btCos(halfPitch);
+		btScalar sinPitch = btSin(halfPitch);
+		btScalar cosRoll = btCos(halfRoll);
+		btScalar sinRoll = btSin(halfRoll);
+		setValue(sinRoll * cosPitch * cosYaw - cosRoll * sinPitch * sinYaw, //x
+                         cosRoll * sinPitch * cosYaw + sinRoll * cosPitch * sinYaw, //y
+                         cosRoll * cosPitch * sinYaw - sinRoll * sinPitch * cosYaw, //z
+                         cosRoll * cosPitch * cosYaw + sinRoll * sinPitch * sinYaw); //formerly yzx
+	}
+  /**@brief Add two quaternions
+   * @param q The quaternion to add to this one */
+	SIMD_FORCE_INLINE	btQuaternion& operator+=(const btQuaternion& q)
+	{
+		m_floats[0] += q.x(); m_floats[1] += q.y(); m_floats[2] += q.z(); m_floats[3] += q.m_floats[3];
+		return *this;
+	}
+
+  /**@brief Subtract out a quaternion
+   * @param q The quaternion to subtract from this one */
+	btQuaternion& operator-=(const btQuaternion& q) 
+	{
+		m_floats[0] -= q.x(); m_floats[1] -= q.y(); m_floats[2] -= q.z(); m_floats[3] -= q.m_floats[3];
+		return *this;
+	}
+
+  /**@brief Scale this quaternion
+   * @param s The scalar to scale by */
+	btQuaternion& operator*=(const btScalar& s)
+	{
+		m_floats[0] *= s; m_floats[1] *= s; m_floats[2] *= s; m_floats[3] *= s;
+		return *this;
+	}
+
+  /**@brief Multiply this quaternion by q on the right
+   * @param q The other quaternion 
+   * Equivilant to this = this * q */
+	btQuaternion& operator*=(const btQuaternion& q)
+	{
+		setValue(m_floats[3] * q.x() + m_floats[0] * q.m_floats[3] + m_floats[1] * q.z() - m_floats[2] * q.y(),
+			m_floats[3] * q.y() + m_floats[1] * q.m_floats[3] + m_floats[2] * q.x() - m_floats[0] * q.z(),
+			m_floats[3] * q.z() + m_floats[2] * q.m_floats[3] + m_floats[0] * q.y() - m_floats[1] * q.x(),
+			m_floats[3] * q.m_floats[3] - m_floats[0] * q.x() - m_floats[1] * q.y() - m_floats[2] * q.z());
+		return *this;
+	}
+  /**@brief Return the dot product between this quaternion and another
+   * @param q The other quaternion */
+	btScalar dot(const btQuaternion& q) const
+	{
+		return m_floats[0] * q.x() + m_floats[1] * q.y() + m_floats[2] * q.z() + m_floats[3] * q.m_floats[3];
+	}
+
+  /**@brief Return the length squared of the quaternion */
+	btScalar length2() const
+	{
+		return dot(*this);
+	}
+
+  /**@brief Return the length of the quaternion */
+	btScalar length() const
+	{
+		return btSqrt(length2());
+	}
+
+  /**@brief Normalize the quaternion 
+   * Such that x^2 + y^2 + z^2 +w^2 = 1 */
+	btQuaternion& normalize() 
+	{
+		return *this /= length();
+	}
+
+  /**@brief Return a scaled version of this quaternion
+   * @param s The scale factor */
+	SIMD_FORCE_INLINE btQuaternion
+	operator*(const btScalar& s) const
+	{
+		return btQuaternion(x() * s, y() * s, z() * s, m_floats[3] * s);
+	}
+
+
+  /**@brief Return an inversely scaled versionof this quaternion
+   * @param s The inverse scale factor */
+	btQuaternion operator/(const btScalar& s) const
+	{
+		btAssert(s != btScalar(0.0));
+		return *this * (btScalar(1.0) / s);
+	}
+
+  /**@brief Inversely scale this quaternion
+   * @param s The scale factor */
+	btQuaternion& operator/=(const btScalar& s) 
+	{
+		btAssert(s != btScalar(0.0));
+		return *this *= btScalar(1.0) / s;
+	}
+
+  /**@brief Return a normalized version of this quaternion */
+	btQuaternion normalized() const 
+	{
+		return *this / length();
+	} 
+  /**@brief Return the angle between this quaternion and the other 
+   * @param q The other quaternion */
+	btScalar angle(const btQuaternion& q) const 
+	{
+		btScalar s = btSqrt(length2() * q.length2());
+		btAssert(s != btScalar(0.0));
+		return btAcos(dot(q) / s);
+	}
+  /**@brief Return the angle of rotation represented by this quaternion */
+	btScalar getAngle() const 
+	{
+		btScalar s = btScalar(2.) * btAcos(m_floats[3]);
+		return s;
+	}
+
+	/**@brief Return the axis of the rotation represented by this quaternion */
+	btVector3 getAxis() const
+	{
+		btScalar s_squared = btScalar(1.) - btPow(m_floats[3], btScalar(2.));
+		if (s_squared < btScalar(10.) * SIMD_EPSILON) //Check for divide by zero
+			return btVector3(1.0, 0.0, 0.0);  // Arbitrary
+		btScalar s = btSqrt(s_squared);
+		return btVector3(m_floats[0] / s, m_floats[1] / s, m_floats[2] / s);
+	}
+
+	/**@brief Return the inverse of this quaternion */
+	btQuaternion inverse() const
+	{
+		return btQuaternion(-m_floats[0], -m_floats[1], -m_floats[2], m_floats[3]);
+	}
+
+  /**@brief Return the sum of this quaternion and the other 
+   * @param q2 The other quaternion */
+	SIMD_FORCE_INLINE btQuaternion
+	operator+(const btQuaternion& q2) const
+	{
+		const btQuaternion& q1 = *this;
+		return btQuaternion(q1.x() + q2.x(), q1.y() + q2.y(), q1.z() + q2.z(), q1.m_floats[3] + q2.m_floats[3]);
+	}
+
+  /**@brief Return the difference between this quaternion and the other 
+   * @param q2 The other quaternion */
+	SIMD_FORCE_INLINE btQuaternion
+	operator-(const btQuaternion& q2) const
+	{
+		const btQuaternion& q1 = *this;
+		return btQuaternion(q1.x() - q2.x(), q1.y() - q2.y(), q1.z() - q2.z(), q1.m_floats[3] - q2.m_floats[3]);
+	}
+
+  /**@brief Return the negative of this quaternion 
+   * This simply negates each element */
+	SIMD_FORCE_INLINE btQuaternion operator-() const
+	{
+		const btQuaternion& q2 = *this;
+		return btQuaternion( - q2.x(), - q2.y(),  - q2.z(),  - q2.m_floats[3]);
+	}
+  /**@todo document this and it's use */
+	SIMD_FORCE_INLINE btQuaternion farthest( const btQuaternion& qd) const 
+	{
+		btQuaternion diff,sum;
+		diff = *this - qd;
+		sum = *this + qd;
+		if( diff.dot(diff) > sum.dot(sum) )
+			return qd;
+		return (-qd);
+	}
+
+	/**@todo document this and it's use */
+	SIMD_FORCE_INLINE btQuaternion nearest( const btQuaternion& qd) const 
+	{
+		btQuaternion diff,sum;
+		diff = *this - qd;
+		sum = *this + qd;
+		if( diff.dot(diff) < sum.dot(sum) )
+			return qd;
+		return (-qd);
+	}
+
+
+  /**@brief Return the quaternion which is the result of Spherical Linear Interpolation between this and the other quaternion
+   * @param q The other quaternion to interpolate with 
+   * @param t The ratio between this and q to interpolate.  If t = 0 the result is this, if t=1 the result is q.
+   * Slerp interpolates assuming constant velocity.  */
+	btQuaternion slerp(const btQuaternion& q, const btScalar& t) const
+	{
+		btScalar theta = angle(q);
+		if (theta != btScalar(0.0))
+		{
+			btScalar d = btScalar(1.0) / btSin(theta);
+			btScalar s0 = btSin((btScalar(1.0) - t) * theta);
+			btScalar s1 = btSin(t * theta);   
+                        if (dot(q) < 0) // Take care of long angle case see http://en.wikipedia.org/wiki/Slerp
+                          return btQuaternion((m_floats[0] * s0 + -q.x() * s1) * d,
+                                              (m_floats[1] * s0 + -q.y() * s1) * d,
+                                              (m_floats[2] * s0 + -q.z() * s1) * d,
+                                              (m_floats[3] * s0 + -q.m_floats[3] * s1) * d);
+                        else
+                          return btQuaternion((m_floats[0] * s0 + q.x() * s1) * d,
+                                              (m_floats[1] * s0 + q.y() * s1) * d,
+                                              (m_floats[2] * s0 + q.z() * s1) * d,
+                                              (m_floats[3] * s0 + q.m_floats[3] * s1) * d);
+                        
+		}
+		else
+		{
+			return *this;
+		}
+	}
+
+	static const btQuaternion&	getIdentity()
+	{
+		static const btQuaternion identityQuat(btScalar(0.),btScalar(0.),btScalar(0.),btScalar(1.));
+		return identityQuat;
+	}
+
+	SIMD_FORCE_INLINE const btScalar& getW() const { return m_floats[3]; }
+
+	
+};
+
+
+/**@brief Return the negative of a quaternion */
+SIMD_FORCE_INLINE btQuaternion
+operator-(const btQuaternion& q)
+{
+	return btQuaternion(-q.x(), -q.y(), -q.z(), -q.w());
+}
+
+
+
+/**@brief Return the product of two quaternions */
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q1, const btQuaternion& q2) {
+	return btQuaternion(q1.w() * q2.x() + q1.x() * q2.w() + q1.y() * q2.z() - q1.z() * q2.y(),
+		q1.w() * q2.y() + q1.y() * q2.w() + q1.z() * q2.x() - q1.x() * q2.z(),
+		q1.w() * q2.z() + q1.z() * q2.w() + q1.x() * q2.y() - q1.y() * q2.x(),
+		q1.w() * q2.w() - q1.x() * q2.x() - q1.y() * q2.y() - q1.z() * q2.z()); 
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btQuaternion& q, const btVector3& w)
+{
+	return btQuaternion( q.w() * w.x() + q.y() * w.z() - q.z() * w.y(),
+		q.w() * w.y() + q.z() * w.x() - q.x() * w.z(),
+		q.w() * w.z() + q.x() * w.y() - q.y() * w.x(),
+		-q.x() * w.x() - q.y() * w.y() - q.z() * w.z()); 
+}
+
+SIMD_FORCE_INLINE btQuaternion
+operator*(const btVector3& w, const btQuaternion& q)
+{
+	return btQuaternion( w.x() * q.w() + w.y() * q.z() - w.z() * q.y(),
+		w.y() * q.w() + w.z() * q.x() - w.x() * q.z(),
+		w.z() * q.w() + w.x() * q.y() - w.y() * q.x(),
+		-w.x() * q.x() - w.y() * q.y() - w.z() * q.z()); 
+}
+
+/**@brief Calculate the dot product between two quaternions */
+SIMD_FORCE_INLINE btScalar 
+dot(const btQuaternion& q1, const btQuaternion& q2) 
+{ 
+	return q1.dot(q2); 
+}
+
+
+/**@brief Return the length of a quaternion */
+SIMD_FORCE_INLINE btScalar
+length(const btQuaternion& q) 
+{ 
+	return q.length(); 
+}
+
+/**@brief Return the angle between two quaternions*/
+SIMD_FORCE_INLINE btScalar
+angle(const btQuaternion& q1, const btQuaternion& q2) 
+{ 
+	return q1.angle(q2); 
+}
+
+/**@brief Return the inverse of a quaternion*/
+SIMD_FORCE_INLINE btQuaternion
+inverse(const btQuaternion& q) 
+{
+	return q.inverse();
+}
+
+/**@brief Return the result of spherical linear interpolation betwen two quaternions 
+ * @param q1 The first quaternion
+ * @param q2 The second quaternion 
+ * @param t The ration between q1 and q2.  t = 0 return q1, t=1 returns q2 
+ * Slerp assumes constant velocity between positions. */
+SIMD_FORCE_INLINE btQuaternion
+slerp(const btQuaternion& q1, const btQuaternion& q2, const btScalar& t) 
+{
+	return q1.slerp(q2, t);
+}
+
+SIMD_FORCE_INLINE btVector3 
+quatRotate(const btQuaternion& rotation, const btVector3& v) 
+{
+	btQuaternion q = rotation * v;
+	q *= rotation.inverse();
+	return btVector3(q.getX(),q.getY(),q.getZ());
+}
+
+SIMD_FORCE_INLINE btQuaternion 
+shortestArcQuat(const btVector3& v0, const btVector3& v1) // Game Programming Gems 2.10. make sure v0,v1 are normalized
+{
+	btVector3 c = v0.cross(v1);
+	btScalar  d = v0.dot(v1);
+
+	if (d < -1.0 + SIMD_EPSILON)
+	{
+		btVector3 n,unused;
+		btPlaneSpace1(v0,n,unused);
+		return btQuaternion(n.x(),n.y(),n.z(),0.0f); // just pick any vector that is orthogonal to v0
+	}
+
+	btScalar  s = btSqrt((1.0f + d) * 2.0f);
+	btScalar rs = 1.0f / s;
+
+	return btQuaternion(c.getX()*rs,c.getY()*rs,c.getZ()*rs,s * 0.5f);
+}
+
+SIMD_FORCE_INLINE btQuaternion 
+shortestArcQuatNormalize2(btVector3& v0,btVector3& v1)
+{
+	v0.normalize();
+	v1.normalize();
+	return shortestArcQuat(v0,v1);
+}
+
+#endif
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btQuickprof.cpp b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuickprof.cpp
new file mode 100644
index 0000000..1453406
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuickprof.cpp
@@ -0,0 +1,565 @@
+/*
+
+***************************************************************************************************
+**
+** profile.cpp
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
+
+// Credits: The Clock class was inspired by the Timer classes in 
+// Ogre (www.ogre3d.org).
+
+#include "btQuickprof.h"
+
+#ifndef BT_NO_PROFILE
+
+
+static btClock gProfileClock;
+
+
+#ifdef __CELLOS_LV2__
+#include <sys/sys_time.h>
+#include <sys/time_util.h>
+#include <stdio.h>
+#endif
+
+#if defined (SUNOS) || defined (__SUNOS__) 
+#include <stdio.h> 
+#endif
+
+#if defined(WIN32) || defined(_WIN32)
+
+#define BT_USE_WINDOWS_TIMERS
+#define WIN32_LEAN_AND_MEAN
+#define NOWINRES
+#define NOMCX
+#define NOIME 
+
+#ifdef _XBOX
+	#include <Xtl.h>
+#else //_XBOX
+	#include <windows.h>
+#endif //_XBOX
+
+#include <time.h>
+
+
+#else //_WIN32
+#include <sys/time.h>
+#endif //_WIN32
+
+#define mymin(a,b) (a > b ? a : b)
+
+struct btClockData
+{
+
+#ifdef BT_USE_WINDOWS_TIMERS
+	LARGE_INTEGER mClockFrequency;
+	DWORD mStartTick;
+	LONGLONG mPrevElapsedTime;
+	LARGE_INTEGER mStartTime;
+#else
+#ifdef __CELLOS_LV2__
+	uint64_t	mStartTime;
+#else
+	struct timeval mStartTime;
+#endif
+#endif //__CELLOS_LV2__
+
+};
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+btClock::btClock()
+{
+	m_data = new btClockData;
+#ifdef BT_USE_WINDOWS_TIMERS
+	QueryPerformanceFrequency(&m_data->mClockFrequency);
+#endif
+	reset();
+}
+
+btClock::~btClock()
+{
+	delete m_data;
+}
+
+btClock::btClock(const btClock& other)
+{
+	m_data = new btClockData;
+	*m_data = *other.m_data;
+}
+
+btClock& btClock::operator=(const btClock& other)
+{
+	*m_data = *other.m_data;
+	return *this;
+}
+
+
+	/// Resets the initial reference time.
+void btClock::reset()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+	QueryPerformanceCounter(&m_data->mStartTime);
+	m_data->mStartTick = GetTickCount();
+	m_data->mPrevElapsedTime = 0;
+#else
+#ifdef __CELLOS_LV2__
+
+	typedef uint64_t  ClockSize;
+	ClockSize newTime;
+	//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+	SYS_TIMEBASE_GET( newTime );
+	m_data->mStartTime = newTime;
+#else
+	gettimeofday(&m_data->mStartTime, 0);
+#endif
+#endif
+}
+
+/// Returns the time in ms since the last call to reset or since 
+/// the btClock was created.
+unsigned long int btClock::getTimeMilliseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+	LARGE_INTEGER currentTime;
+	QueryPerformanceCounter(&currentTime);
+	LONGLONG elapsedTime = currentTime.QuadPart - 
+		m_data->mStartTime.QuadPart;
+		// Compute the number of millisecond ticks elapsed.
+	unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
+		m_data->mClockFrequency.QuadPart);
+		// Check for unexpected leaps in the Win32 performance counter.  
+	// (This is caused by unexpected data across the PCI to ISA 
+		// bridge, aka south bridge.  See Microsoft KB274323.)
+		unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
+		signed long msecOff = (signed long)(msecTicks - elapsedTicks);
+		if (msecOff < -100 || msecOff > 100)
+		{
+			// Adjust the starting time forwards.
+			LONGLONG msecAdjustment = mymin(msecOff * 
+				m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 
+				m_data->mPrevElapsedTime);
+			m_data->mStartTime.QuadPart += msecAdjustment;
+			elapsedTime -= msecAdjustment;
+
+			// Recompute the number of millisecond ticks elapsed.
+			msecTicks = (unsigned long)(1000 * elapsedTime / 
+				m_data->mClockFrequency.QuadPart);
+		}
+
+		// Store the current elapsed time for adjustments next time.
+		m_data->mPrevElapsedTime = elapsedTime;
+
+		return msecTicks;
+#else
+
+#ifdef __CELLOS_LV2__
+		uint64_t freq=sys_time_get_timebase_frequency();
+		double dFreq=((double) freq) / 1000.0;
+		typedef uint64_t  ClockSize;
+		ClockSize newTime;
+		SYS_TIMEBASE_GET( newTime );
+		//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+
+		return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+		struct timeval currentTime;
+		gettimeofday(&currentTime, 0);
+		return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000 + 
+			(currentTime.tv_usec - m_data->mStartTime.tv_usec) / 1000;
+#endif //__CELLOS_LV2__
+#endif
+}
+
+	/// Returns the time in us since the last call to reset or since 
+	/// the Clock was created.
+unsigned long int btClock::getTimeMicroseconds()
+{
+#ifdef BT_USE_WINDOWS_TIMERS
+		LARGE_INTEGER currentTime;
+		QueryPerformanceCounter(&currentTime);
+		LONGLONG elapsedTime = currentTime.QuadPart - 
+			m_data->mStartTime.QuadPart;
+
+		// Compute the number of millisecond ticks elapsed.
+		unsigned long msecTicks = (unsigned long)(1000 * elapsedTime / 
+			m_data->mClockFrequency.QuadPart);
+
+		// Check for unexpected leaps in the Win32 performance counter.  
+		// (This is caused by unexpected data across the PCI to ISA 
+		// bridge, aka south bridge.  See Microsoft KB274323.)
+		unsigned long elapsedTicks = GetTickCount() - m_data->mStartTick;
+		signed long msecOff = (signed long)(msecTicks - elapsedTicks);
+		if (msecOff < -100 || msecOff > 100)
+		{
+			// Adjust the starting time forwards.
+			LONGLONG msecAdjustment = mymin(msecOff * 
+				m_data->mClockFrequency.QuadPart / 1000, elapsedTime - 
+				m_data->mPrevElapsedTime);
+			m_data->mStartTime.QuadPart += msecAdjustment;
+			elapsedTime -= msecAdjustment;
+		}
+
+		// Store the current elapsed time for adjustments next time.
+		m_data->mPrevElapsedTime = elapsedTime;
+
+		// Convert to microseconds.
+		unsigned long usecTicks = (unsigned long)(1000000 * elapsedTime / 
+			m_data->mClockFrequency.QuadPart);
+
+		return usecTicks;
+#else
+
+#ifdef __CELLOS_LV2__
+		uint64_t freq=sys_time_get_timebase_frequency();
+		double dFreq=((double) freq)/ 1000000.0;
+		typedef uint64_t  ClockSize;
+		ClockSize newTime;
+		//__asm __volatile__( "mftb %0" : "=r" (newTime) : : "memory");
+		SYS_TIMEBASE_GET( newTime );
+
+		return (unsigned long int)((double(newTime-m_data->mStartTime)) / dFreq);
+#else
+
+		struct timeval currentTime;
+		gettimeofday(&currentTime, 0);
+		return (currentTime.tv_sec - m_data->mStartTime.tv_sec) * 1000000 + 
+			(currentTime.tv_usec - m_data->mStartTime.tv_usec);
+#endif//__CELLOS_LV2__
+#endif 
+}
+
+
+
+
+
+inline void Profile_Get_Ticks(unsigned long int * ticks)
+{
+	*ticks = gProfileClock.getTimeMicroseconds();
+}
+
+inline float Profile_Get_Tick_Rate(void)
+{
+//	return 1000000.f;
+	return 1000.f;
+
+}
+
+
+
+/***************************************************************************************************
+**
+** CProfileNode
+**
+***************************************************************************************************/
+
+/***********************************************************************************************
+ * INPUT:                                                                                      *
+ * name - pointer to a static string which is the name of this profile node                    *
+ * parent - parent pointer                                                                     *
+ *                                                                                             *
+ * WARNINGS:                                                                                   *
+ * The name is assumed to be a static pointer, only the pointer is stored and compared for     *
+ * efficiency reasons.                                                                         *
+ *=============================================================================================*/
+CProfileNode::CProfileNode( const char * name, CProfileNode * parent ) :
+	Name( name ),
+	TotalCalls( 0 ),
+	TotalTime( 0 ),
+	StartTime( 0 ),
+	RecursionCounter( 0 ),
+	Parent( parent ),
+	Child( NULL ),
+	Sibling( NULL )
+{
+	Reset();
+}
+
+
+void	CProfileNode::CleanupMemory()
+{
+	delete ( Child);
+	Child = NULL;
+	delete ( Sibling);
+	Sibling = NULL;
+}
+
+CProfileNode::~CProfileNode( void )
+{
+	delete ( Child);
+	delete ( Sibling);
+}
+
+
+/***********************************************************************************************
+ * INPUT:                                                                                      *
+ * name - static string pointer to the name of the node we are searching for                   *
+ *                                                                                             *
+ * WARNINGS:                                                                                   *
+ * All profile names are assumed to be static strings so this function uses pointer compares   *
+ * to find the named node.                                                                     *
+ *=============================================================================================*/
+CProfileNode * CProfileNode::Get_Sub_Node( const char * name )
+{
+	// Try to find this sub node
+	CProfileNode * child = Child;
+	while ( child ) {
+		if ( child->Name == name ) {
+			return child;
+		}
+		child = child->Sibling;
+	}
+
+	// We didn't find it, so add it
+	
+	CProfileNode * node = new CProfileNode( name, this );
+	node->Sibling = Child;
+	Child = node;
+	return node;
+}
+
+
+void	CProfileNode::Reset( void )
+{
+	TotalCalls = 0;
+	TotalTime = 0.0f;
+	
+
+	if ( Child ) {
+		Child->Reset();
+	}
+	if ( Sibling ) {
+		Sibling->Reset();
+	}
+}
+
+
+void	CProfileNode::Call( void )
+{
+	TotalCalls++;
+	if (RecursionCounter++ == 0) {
+		Profile_Get_Ticks(&StartTime);
+	}
+}
+
+
+bool	CProfileNode::Return( void )
+{
+	if ( --RecursionCounter == 0 && TotalCalls != 0 ) { 
+		unsigned long int time;
+		Profile_Get_Ticks(&time);
+		time-=StartTime;
+		TotalTime += (float)time / Profile_Get_Tick_Rate();
+	}
+	return ( RecursionCounter == 0 );
+}
+
+
+/***************************************************************************************************
+**
+** CProfileIterator
+**
+***************************************************************************************************/
+CProfileIterator::CProfileIterator( CProfileNode * start )
+{
+	CurrentParent = start;
+	CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void	CProfileIterator::First(void)
+{
+	CurrentChild = CurrentParent->Get_Child();
+}
+
+
+void	CProfileIterator::Next(void)
+{
+	CurrentChild = CurrentChild->Get_Sibling();
+}
+
+
+bool	CProfileIterator::Is_Done(void)
+{
+	return CurrentChild == NULL;
+}
+
+
+void	CProfileIterator::Enter_Child( int index )
+{
+	CurrentChild = CurrentParent->Get_Child();
+	while ( (CurrentChild != NULL) && (index != 0) ) {
+		index--;
+		CurrentChild = CurrentChild->Get_Sibling();
+	}
+
+	if ( CurrentChild != NULL ) {
+		CurrentParent = CurrentChild;
+		CurrentChild = CurrentParent->Get_Child();
+	}
+}
+
+
+void	CProfileIterator::Enter_Parent( void )
+{
+	if ( CurrentParent->Get_Parent() != NULL ) {
+		CurrentParent = CurrentParent->Get_Parent();
+	}
+	CurrentChild = CurrentParent->Get_Child();
+}
+
+
+/***************************************************************************************************
+**
+** CProfileManager
+**
+***************************************************************************************************/
+
+CProfileNode	CProfileManager::Root( "Root", NULL );
+CProfileNode *	CProfileManager::CurrentNode = &CProfileManager::Root;
+int				CProfileManager::FrameCounter = 0;
+unsigned long int			CProfileManager::ResetTime = 0;
+
+
+/***********************************************************************************************
+ * CProfileManager::Start_Profile -- Begin a named profile                                    *
+ *                                                                                             *
+ * Steps one level deeper into the tree, if a child already exists with the specified name     *
+ * then it accumulates the profiling; otherwise a new child node is added to the profile tree. *
+ *                                                                                             *
+ * INPUT:                                                                                      *
+ * name - name of this profiling record                                                        *
+ *                                                                                             *
+ * WARNINGS:                                                                                   *
+ * The string used is assumed to be a static string; pointer compares are used throughout      *
+ * the profiling code for efficiency.                                                          *
+ *=============================================================================================*/
+void	CProfileManager::Start_Profile( const char * name )
+{
+	if (name != CurrentNode->Get_Name()) {
+		CurrentNode = CurrentNode->Get_Sub_Node( name );
+	} 
+	
+	CurrentNode->Call();
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Stop_Profile -- Stop timing and record the results.                       *
+ *=============================================================================================*/
+void	CProfileManager::Stop_Profile( void )
+{
+	// Return will indicate whether we should back up to our parent (we may
+	// be profiling a recursive function)
+	if (CurrentNode->Return()) {
+		CurrentNode = CurrentNode->Get_Parent();
+	}
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Reset -- Reset the contents of the profiling system                       *
+ *                                                                                             *
+ *    This resets everything except for the tree structure.  All of the timing data is reset.  *
+ *=============================================================================================*/
+void	CProfileManager::Reset( void )
+{ 
+	gProfileClock.reset();
+	Root.Reset();
+    Root.Call();
+	FrameCounter = 0;
+	Profile_Get_Ticks(&ResetTime);
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Increment_Frame_Counter -- Increment the frame counter                    *
+ *=============================================================================================*/
+void CProfileManager::Increment_Frame_Counter( void )
+{
+	FrameCounter++;
+}
+
+
+/***********************************************************************************************
+ * CProfileManager::Get_Time_Since_Reset -- returns the elapsed time since last reset         *
+ *=============================================================================================*/
+float CProfileManager::Get_Time_Since_Reset( void )
+{
+	unsigned long int time;
+	Profile_Get_Ticks(&time);
+	time -= ResetTime;
+	return (float)time / Profile_Get_Tick_Rate();
+}
+
+#include <stdio.h>
+
+void	CProfileManager::dumpRecursive(CProfileIterator* profileIterator, int spacing)
+{
+	profileIterator->First();
+	if (profileIterator->Is_Done())
+		return;
+
+	float accumulated_time=0,parent_time = profileIterator->Is_Root() ? CProfileManager::Get_Time_Since_Reset() : profileIterator->Get_Current_Parent_Total_Time();
+	int i;
+	int frames_since_reset = CProfileManager::Get_Frame_Count_Since_Reset();
+	for (i=0;i<spacing;i++)	printf(".");
+	printf("----------------------------------\n");
+	for (i=0;i<spacing;i++)	printf(".");
+	printf("Profiling: %s (total running time: %.3f ms) ---\n",	profileIterator->Get_Current_Parent_Name(), parent_time );
+	float totalTime = 0.f;
+
+	
+	int numChildren = 0;
+	
+	for (i = 0; !profileIterator->Is_Done(); i++,profileIterator->Next())
+	{
+		numChildren++;
+		float current_total_time = profileIterator->Get_Current_Total_Time();
+		accumulated_time += current_total_time;
+		float fraction = parent_time > SIMD_EPSILON ? (current_total_time / parent_time) * 100 : 0.f;
+		{
+			int i;	for (i=0;i<spacing;i++)	printf(".");
+		}
+		printf("%d -- %s (%.2f %%) :: %.3f ms / frame (%d calls)\n",i, profileIterator->Get_Current_Name(), fraction,(current_total_time / (double)frames_since_reset),profileIterator->Get_Current_Total_Calls());
+		totalTime += current_total_time;
+		//recurse into children
+	}
+
+	if (parent_time < accumulated_time)
+	{
+		printf("what's wrong\n");
+	}
+	for (i=0;i<spacing;i++)	printf(".");
+	printf("%s (%.3f %%) :: %.3f ms\n", "Unaccounted:",parent_time > SIMD_EPSILON ? ((parent_time - accumulated_time) / parent_time) * 100 : 0.f, parent_time - accumulated_time);
+	
+	for (i=0;i<numChildren;i++)
+	{
+		profileIterator->Enter_Child(i);
+		dumpRecursive(profileIterator,spacing+3);
+		profileIterator->Enter_Parent();
+	}
+}
+
+
+
+void	CProfileManager::dumpAll()
+{
+	CProfileIterator* profileIterator = 0;
+	profileIterator = CProfileManager::Get_Iterator();
+
+	dumpRecursive(profileIterator,0);
+
+	CProfileManager::Release_Iterator(profileIterator);
+}
+
+
+
+
+#endif //BT_NO_PROFILE
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btQuickprof.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuickprof.h
new file mode 100644
index 0000000..adfbbe6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btQuickprof.h
@@ -0,0 +1,196 @@
+
+/***************************************************************************************************
+**
+** Real-Time Hierarchical Profiling for Game Programming Gems 3
+**
+** by Greg Hjelstrom & Byon Garrabrant
+**
+***************************************************************************************************/
+
+// Credits: The Clock class was inspired by the Timer classes in 
+// Ogre (www.ogre3d.org).
+
+
+
+#ifndef QUICK_PROF_H
+#define QUICK_PROF_H
+
+//To disable built-in profiling, please comment out next line
+//#define BT_NO_PROFILE 1
+#ifndef BT_NO_PROFILE
+#include <stdio.h>//@todo remove this, backwards compatibility
+#include "btScalar.h"
+#include "btAlignedAllocator.h"
+#include <new>
+
+
+
+
+
+#define USE_BT_CLOCK 1
+
+#ifdef USE_BT_CLOCK
+
+///The btClock is a portable basic clock that measures accurate time in seconds, use for profiling.
+class btClock
+{
+public:
+	btClock();
+
+	btClock(const btClock& other);
+	btClock& operator=(const btClock& other);
+
+	~btClock();
+
+	/// Resets the initial reference time.
+	void reset();
+
+	/// Returns the time in ms since the last call to reset or since 
+	/// the btClock was created.
+	unsigned long int getTimeMilliseconds();
+
+	/// Returns the time in us since the last call to reset or since 
+	/// the Clock was created.
+	unsigned long int getTimeMicroseconds();
+private:
+	struct btClockData* m_data;
+};
+
+#endif //USE_BT_CLOCK
+
+
+
+
+///A node in the Profile Hierarchy Tree
+class	CProfileNode {
+
+public:
+	CProfileNode( const char * name, CProfileNode * parent );
+	~CProfileNode( void );
+
+	CProfileNode * Get_Sub_Node( const char * name );
+
+	CProfileNode * Get_Parent( void )		{ return Parent; }
+	CProfileNode * Get_Sibling( void )		{ return Sibling; }
+	CProfileNode * Get_Child( void )			{ return Child; }
+
+	void				CleanupMemory();
+	void				Reset( void );
+	void				Call( void );
+	bool				Return( void );
+
+	const char *	Get_Name( void )				{ return Name; }
+	int				Get_Total_Calls( void )		{ return TotalCalls; }
+	float				Get_Total_Time( void )		{ return TotalTime; }
+
+protected:
+
+	const char *	Name;
+	int				TotalCalls;
+	float				TotalTime;
+	unsigned long int			StartTime;
+	int				RecursionCounter;
+
+	CProfileNode *	Parent;
+	CProfileNode *	Child;
+	CProfileNode *	Sibling;
+};
+
+///An iterator to navigate through the tree
+class CProfileIterator
+{
+public:
+	// Access all the children of the current parent
+	void				First(void);
+	void				Next(void);
+	bool				Is_Done(void);
+	bool                Is_Root(void) { return (CurrentParent->Get_Parent() == 0); }
+
+	void				Enter_Child( int index );		// Make the given child the new parent
+	void				Enter_Largest_Child( void );	// Make the largest child the new parent
+	void				Enter_Parent( void );			// Make the current parent's parent the new parent
+
+	// Access the current child
+	const char *	Get_Current_Name( void )			{ return CurrentChild->Get_Name(); }
+	int				Get_Current_Total_Calls( void )	{ return CurrentChild->Get_Total_Calls(); }
+	float				Get_Current_Total_Time( void )	{ return CurrentChild->Get_Total_Time(); }
+
+	// Access the current parent
+	const char *	Get_Current_Parent_Name( void )			{ return CurrentParent->Get_Name(); }
+	int				Get_Current_Parent_Total_Calls( void )	{ return CurrentParent->Get_Total_Calls(); }
+	float				Get_Current_Parent_Total_Time( void )	{ return CurrentParent->Get_Total_Time(); }
+
+protected:
+
+	CProfileNode *	CurrentParent;
+	CProfileNode *	CurrentChild;
+
+	CProfileIterator( CProfileNode * start );
+	friend	class		CProfileManager;
+};
+
+
+///The Manager for the Profile system
+class	CProfileManager {
+public:
+	static	void						Start_Profile( const char * name );
+	static	void						Stop_Profile( void );
+
+	static	void						CleanupMemory(void)
+	{
+		Root.CleanupMemory();
+	}
+
+	static	void						Reset( void );
+	static	void						Increment_Frame_Counter( void );
+	static	int						Get_Frame_Count_Since_Reset( void )		{ return FrameCounter; }
+	static	float						Get_Time_Since_Reset( void );
+
+	static	CProfileIterator *	Get_Iterator( void )	
+	{ 
+		
+		return new CProfileIterator( &Root ); 
+	}
+	static	void						Release_Iterator( CProfileIterator * iterator ) { delete ( iterator); }
+
+	static void	dumpRecursive(CProfileIterator* profileIterator, int spacing);
+
+	static void	dumpAll();
+
+private:
+	static	CProfileNode			Root;
+	static	CProfileNode *			CurrentNode;
+	static	int						FrameCounter;
+	static	unsigned long int					ResetTime;
+};
+
+
+///ProfileSampleClass is a simple way to profile a function's scope
+///Use the BT_PROFILE macro at the start of scope to time
+class	CProfileSample {
+public:
+	CProfileSample( const char * name )
+	{ 
+		CProfileManager::Start_Profile( name ); 
+	}
+
+	~CProfileSample( void )					
+	{ 
+		CProfileManager::Stop_Profile(); 
+	}
+};
+
+
+#define	BT_PROFILE( name )			CProfileSample __profile( name )
+
+#else
+
+#define	BT_PROFILE( name )
+
+#endif //#ifndef BT_NO_PROFILE
+
+
+
+#endif //QUICK_PROF_H
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btRandom.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btRandom.h
new file mode 100644
index 0000000..fdf65e0
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btRandom.h
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef GEN_RANDOM_H
+#define GEN_RANDOM_H
+
+#ifdef MT19937
+
+#include <limits.h>
+#include <mt19937.h>
+
+#define GEN_RAND_MAX UINT_MAX
+
+SIMD_FORCE_INLINE void         GEN_srand(unsigned int seed) { init_genrand(seed); }
+SIMD_FORCE_INLINE unsigned int GEN_rand()                   { return genrand_int32(); }
+
+#else
+
+#include <stdlib.h>
+
+#define GEN_RAND_MAX RAND_MAX
+
+SIMD_FORCE_INLINE void         GEN_srand(unsigned int seed) { srand(seed); } 
+SIMD_FORCE_INLINE unsigned int GEN_rand()                   { return rand(); }
+
+#endif
+
+#endif
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btScalar.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btScalar.h
new file mode 100644
index 0000000..7417d6f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btScalar.h
@@ -0,0 +1,524 @@
+/*
+Copyright (c) 2003-2009 Erwin Coumans  http://bullet.googlecode.com
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef SIMD___SCALAR_H
+#define SIMD___SCALAR_H
+
+#ifdef BT_MANAGED_CODE
+//Aligned data types not supported in managed code
+#pragma unmanaged
+#endif
+
+
+#include <math.h>
+#include <stdlib.h>//size_t for MSVC 6.0
+#include <cstdlib>
+#include <cfloat>
+#include <float.h>
+
+/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
+#define BT_BULLET_VERSION 277
+
+inline int	btGetVersion()
+{
+	return BT_BULLET_VERSION;
+}
+
+#if defined(DEBUG) || defined (_DEBUG)
+#define BT_DEBUG
+#endif
+
+
+#ifdef _WIN32
+
+		#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
+
+			#define SIMD_FORCE_INLINE inline
+			#define ATTRIBUTE_ALIGNED16(a) a
+			#define ATTRIBUTE_ALIGNED64(a) a
+			#define ATTRIBUTE_ALIGNED128(a) a
+		#else
+			//#define BT_HAS_ALIGNED_ALLOCATOR
+			#pragma warning(disable : 4324) // disable padding warning
+//			#pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
+//			#pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+//			#pragma warning(disable:4786) // Disable the "debug name too long" warning
+
+			#define SIMD_FORCE_INLINE __forceinline
+			#define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
+			#define ATTRIBUTE_ALIGNED64(a) __declspec(align(64)) a
+			#define ATTRIBUTE_ALIGNED128(a) __declspec (align(128)) a
+		#ifdef _XBOX
+			#define BT_USE_VMX128
+
+			#include <ppcintrinsics.h>
+ 			#define BT_HAVE_NATIVE_FSEL
+ 			#define btFsel(a,b,c) __fsel((a),(b),(c))
+		#else
+
+#if (defined (_WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
+			#define BT_USE_SSE
+			#include <emmintrin.h>
+#endif
+
+		#endif//_XBOX
+
+		#endif //__MINGW32__
+
+		#include <assert.h>
+#ifdef BT_DEBUG
+		#define btAssert assert
+#else
+		#define btAssert(x)
+#endif
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+
+		#define btLikely(_c)  _c
+		#define btUnlikely(_c) _c
+
+#else
+	
+#if defined	(__CELLOS_LV2__)
+		#define SIMD_FORCE_INLINE inline __attribute__((always_inline))
+		#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+		#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+		#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+		#ifndef assert
+		#include <assert.h>
+		#endif
+#ifdef BT_DEBUG
+#ifdef __SPU__
+#include <spu_printf.h>
+#define printf spu_printf
+	#define btAssert(x) {if(!(x)){printf("Assert "__FILE__ ":%u ("#x")\n", __LINE__);spu_hcmpeq(0,0);}}
+#else
+	#define btAssert assert
+#endif
+	
+#else
+		#define btAssert(x)
+#endif
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+
+		#define btLikely(_c)  _c
+		#define btUnlikely(_c) _c
+
+#else
+
+#ifdef USE_LIBSPE2
+
+		#define SIMD_FORCE_INLINE __inline
+		#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+		#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+		#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+		#ifndef assert
+		#include <assert.h>
+		#endif
+#ifdef BT_DEBUG
+		#define btAssert assert
+#else
+		#define btAssert(x)
+#endif
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+
+
+		#define btLikely(_c)   __builtin_expect((_c), 1)
+		#define btUnlikely(_c) __builtin_expect((_c), 0)
+		
+
+#else
+	//non-windows systems
+
+#if (defined (__APPLE__) && defined (__i386__) && (!defined (BT_USE_DOUBLE_PRECISION)))
+	#define BT_USE_SSE
+	#include <emmintrin.h>
+
+	#define SIMD_FORCE_INLINE inline
+///@todo: check out alignment methods for other platforms/compilers
+	#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+	#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+	#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+	#ifndef assert
+	#include <assert.h>
+	#endif
+
+	#if defined(DEBUG) || defined (_DEBUG)
+		#define btAssert assert
+	#else
+		#define btAssert(x)
+	#endif
+
+	//btFullAssert is optional, slows down a lot
+	#define btFullAssert(x)
+	#define btLikely(_c)  _c
+	#define btUnlikely(_c) _c
+
+#else
+
+		#define SIMD_FORCE_INLINE inline
+		///@todo: check out alignment methods for other platforms/compilers
+		///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
+		///#define ATTRIBUTE_ALIGNED64(a) a __attribute__ ((aligned (64)))
+		///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
+		#define ATTRIBUTE_ALIGNED16(a) a
+		#define ATTRIBUTE_ALIGNED64(a) a
+		#define ATTRIBUTE_ALIGNED128(a) a
+		#ifndef assert
+		#include <assert.h>
+		#endif
+
+#if defined(DEBUG) || defined (_DEBUG)
+		#define btAssert assert
+#else
+		#define btAssert(x)
+#endif
+
+		//btFullAssert is optional, slows down a lot
+		#define btFullAssert(x)
+		#define btLikely(_c)  _c
+		#define btUnlikely(_c) _c
+#endif //__APPLE__ 
+
+#endif // LIBSPE2
+
+#endif	//__CELLOS_LV2__
+#endif
+
+
+///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
+#if defined(BT_USE_DOUBLE_PRECISION)
+typedef double btScalar;
+//this number could be bigger in double precision
+#define BT_LARGE_FLOAT 1e30
+#else
+typedef float btScalar;
+//keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
+#define BT_LARGE_FLOAT 1e18f
+#endif
+
+
+
+#define BT_DECLARE_ALIGNED_ALLOCATOR() \
+   SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
+   SIMD_FORCE_INLINE void  operator delete(void* ptr)         { btAlignedFree(ptr); }   \
+   SIMD_FORCE_INLINE void* operator new(size_t, void* ptr)   { return ptr; }   \
+   SIMD_FORCE_INLINE void  operator delete(void*, void*)      { }   \
+   SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
+   SIMD_FORCE_INLINE void  operator delete[](void* ptr)         { btAlignedFree(ptr); }   \
+   SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr)   { return ptr; }   \
+   SIMD_FORCE_INLINE void  operator delete[](void*, void*)      { }   \
+
+
+
+#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
+		
+SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); }
+SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
+SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
+SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
+SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
+SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { if (x<btScalar(-1))	x=btScalar(-1); if (x>btScalar(1))	x=btScalar(1); return acos(x); }
+SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { if (x<btScalar(-1))	x=btScalar(-1); if (x>btScalar(1))	x=btScalar(1); return asin(x); }
+SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
+SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
+SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
+SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
+SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); }
+SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); }
+
+#else
+		
+SIMD_FORCE_INLINE btScalar btSqrt(btScalar y) 
+{ 
+#ifdef USE_APPROXIMATION
+    double x, z, tempf;
+    unsigned long *tfptr = ((unsigned long *)&tempf) + 1;
+
+	tempf = y;
+	*tfptr = (0xbfcdd90a - *tfptr)>>1; /* estimate of 1/sqrt(y) */
+	x =  tempf;
+	z =  y*btScalar(0.5);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);         /* iteration formula     */
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	x = (btScalar(1.5)*x)-(x*x)*(x*z);
+	return x*y;
+#else
+	return sqrtf(y); 
+#endif
+}
+SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabsf(x); }
+SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cosf(x); }
+SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sinf(x); }
+SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tanf(x); }
+SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { 
+	if (x<btScalar(-1))	
+		x=btScalar(-1); 
+	if (x>btScalar(1))	
+		x=btScalar(1);
+	return acosf(x); 
+}
+SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { 
+	if (x<btScalar(-1))	
+		x=btScalar(-1); 
+	if (x>btScalar(1))	
+		x=btScalar(1);
+	return asinf(x); 
+}
+SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atanf(x); }
+SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2f(x, y); }
+SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return expf(x); }
+SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return logf(x); }
+SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return powf(x,y); }
+SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmodf(x,y); }
+	
+#endif
+
+#define SIMD_2_PI         btScalar(6.283185307179586232)
+#define SIMD_PI           (SIMD_2_PI * btScalar(0.5))
+#define SIMD_HALF_PI      (SIMD_2_PI * btScalar(0.25))
+#define SIMD_RADS_PER_DEG (SIMD_2_PI / btScalar(360.0))
+#define SIMD_DEGS_PER_RAD  (btScalar(360.0) / SIMD_2_PI)
+#define SIMDSQRT12 btScalar(0.7071067811865475244008443621048490)
+
+#define btRecipSqrt(x) ((btScalar)(btScalar(1.0)/btSqrt(btScalar(x))))		/* reciprocal square root */
+
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define SIMD_EPSILON      DBL_EPSILON
+#define SIMD_INFINITY     DBL_MAX
+#else
+#define SIMD_EPSILON      FLT_EPSILON
+#define SIMD_INFINITY     FLT_MAX
+#endif
+
+SIMD_FORCE_INLINE btScalar btAtan2Fast(btScalar y, btScalar x) 
+{
+	btScalar coeff_1 = SIMD_PI / 4.0f;
+	btScalar coeff_2 = 3.0f * coeff_1;
+	btScalar abs_y = btFabs(y);
+	btScalar angle;
+	if (x >= 0.0f) {
+		btScalar r = (x - abs_y) / (x + abs_y);
+		angle = coeff_1 - coeff_1 * r;
+	} else {
+		btScalar r = (x + abs_y) / (abs_y - x);
+		angle = coeff_2 - coeff_1 * r;
+	}
+	return (y < 0.0f) ? -angle : angle;
+}
+
+SIMD_FORCE_INLINE bool      btFuzzyZero(btScalar x) { return btFabs(x) < SIMD_EPSILON; }
+
+SIMD_FORCE_INLINE bool	btEqual(btScalar a, btScalar eps) {
+	return (((a) <= eps) && !((a) < -eps));
+}
+SIMD_FORCE_INLINE bool	btGreaterEqual (btScalar a, btScalar eps) {
+	return (!((a) <= eps));
+}
+
+
+SIMD_FORCE_INLINE int       btIsNegative(btScalar x) {
+    return x < btScalar(0.0) ? 1 : 0;
+}
+
+SIMD_FORCE_INLINE btScalar btRadians(btScalar x) { return x * SIMD_RADS_PER_DEG; }
+SIMD_FORCE_INLINE btScalar btDegrees(btScalar x) { return x * SIMD_DEGS_PER_RAD; }
+
+#define BT_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name
+
+#ifndef btFsel
+SIMD_FORCE_INLINE btScalar btFsel(btScalar a, btScalar b, btScalar c)
+{
+	return a >= 0 ? b : c;
+}
+#endif
+#define btFsels(a,b,c) (btScalar)btFsel(a,b,c)
+
+
+SIMD_FORCE_INLINE bool btMachineIsLittleEndian()
+{
+   long int i = 1;
+   const char *p = (const char *) &i;
+   if (p[0] == 1)  // Lowest address contains the least significant byte
+	   return true;
+   else
+	   return false;
+}
+
+
+
+///btSelect avoids branches, which makes performance much better for consoles like Playstation 3 and XBox 360
+///Thanks Phil Knight. See also http://www.cellperformance.com/articles/2006/04/more_techniques_for_eliminatin_1.html
+SIMD_FORCE_INLINE unsigned btSelect(unsigned condition, unsigned valueIfConditionNonZero, unsigned valueIfConditionZero) 
+{
+    // Set testNz to 0xFFFFFFFF if condition is nonzero, 0x00000000 if condition is zero
+    // Rely on positive value or'ed with its negative having sign bit on
+    // and zero value or'ed with its negative (which is still zero) having sign bit off 
+    // Use arithmetic shift right, shifting the sign bit through all 32 bits
+    unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+    unsigned testEqz = ~testNz;
+    return ((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz)); 
+}
+SIMD_FORCE_INLINE int btSelect(unsigned condition, int valueIfConditionNonZero, int valueIfConditionZero)
+{
+    unsigned testNz = (unsigned)(((int)condition | -(int)condition) >> 31);
+    unsigned testEqz = ~testNz; 
+    return static_cast<int>((valueIfConditionNonZero & testNz) | (valueIfConditionZero & testEqz));
+}
+SIMD_FORCE_INLINE float btSelect(unsigned condition, float valueIfConditionNonZero, float valueIfConditionZero)
+{
+#ifdef BT_HAVE_NATIVE_FSEL
+    return (float)btFsel((btScalar)condition - btScalar(1.0f), valueIfConditionNonZero, valueIfConditionZero);
+#else
+    return (condition != 0) ? valueIfConditionNonZero : valueIfConditionZero; 
+#endif
+}
+
+template<typename T> SIMD_FORCE_INLINE void btSwap(T& a, T& b)
+{
+	T tmp = a;
+	a = b;
+	b = tmp;
+}
+
+
+//PCK: endian swapping functions
+SIMD_FORCE_INLINE unsigned btSwapEndian(unsigned val)
+{
+	return (((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8)  | ((val & 0x000000ff) << 24));
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(unsigned short val)
+{
+	return static_cast<unsigned short>(((val & 0xff00) >> 8) | ((val & 0x00ff) << 8));
+}
+
+SIMD_FORCE_INLINE unsigned btSwapEndian(int val)
+{
+	return btSwapEndian((unsigned)val);
+}
+
+SIMD_FORCE_INLINE unsigned short btSwapEndian(short val)
+{
+	return btSwapEndian((unsigned short) val);
+}
+
+///btSwapFloat uses using char pointers to swap the endianness
+////btSwapFloat/btSwapDouble will NOT return a float, because the machine might 'correct' invalid floating point values
+///Not all values of sign/exponent/mantissa are valid floating point numbers according to IEEE 754. 
+///When a floating point unit is faced with an invalid value, it may actually change the value, or worse, throw an exception. 
+///In most systems, running user mode code, you wouldn't get an exception, but instead the hardware/os/runtime will 'fix' the number for you. 
+///so instead of returning a float/double, we return integer/long long integer
+SIMD_FORCE_INLINE unsigned int  btSwapEndianFloat(float d)
+{
+    unsigned int a = 0;
+    unsigned char *dst = (unsigned char *)&a;
+    unsigned char *src = (unsigned char *)&d;
+
+    dst[0] = src[3];
+    dst[1] = src[2];
+    dst[2] = src[1];
+    dst[3] = src[0];
+    return a;
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE float btUnswapEndianFloat(unsigned int a) 
+{
+    float d = 0.0f;
+    unsigned char *src = (unsigned char *)&a;
+    unsigned char *dst = (unsigned char *)&d;
+
+    dst[0] = src[3];
+    dst[1] = src[2];
+    dst[2] = src[1];
+    dst[3] = src[0];
+
+    return d;
+}
+
+
+// swap using char pointers
+SIMD_FORCE_INLINE void  btSwapEndianDouble(double d, unsigned char* dst)
+{
+    unsigned char *src = (unsigned char *)&d;
+
+    dst[0] = src[7];
+    dst[1] = src[6];
+    dst[2] = src[5];
+    dst[3] = src[4];
+    dst[4] = src[3];
+    dst[5] = src[2];
+    dst[6] = src[1];
+    dst[7] = src[0];
+
+}
+
+// unswap using char pointers
+SIMD_FORCE_INLINE double btUnswapEndianDouble(const unsigned char *src) 
+{
+    double d = 0.0;
+    unsigned char *dst = (unsigned char *)&d;
+
+    dst[0] = src[7];
+    dst[1] = src[6];
+    dst[2] = src[5];
+    dst[3] = src[4];
+    dst[4] = src[3];
+    dst[5] = src[2];
+    dst[6] = src[1];
+    dst[7] = src[0];
+
+	return d;
+}
+
+// returns normalized value in range [-SIMD_PI, SIMD_PI]
+SIMD_FORCE_INLINE btScalar btNormalizeAngle(btScalar angleInRadians) 
+{
+	angleInRadians = btFmod(angleInRadians, SIMD_2_PI);
+	if(angleInRadians < -SIMD_PI)
+	{
+		return angleInRadians + SIMD_2_PI;
+	}
+	else if(angleInRadians > SIMD_PI)
+	{
+		return angleInRadians - SIMD_2_PI;
+	}
+	else
+	{
+		return angleInRadians;
+	}
+}
+
+///rudimentary class to provide type info
+struct btTypedObject
+{
+	btTypedObject(int objectType)
+		:m_objectType(objectType)
+	{
+	}
+	int	m_objectType;
+	inline int getObjectType() const
+	{
+		return m_objectType;
+	}
+};
+#endif //SIMD___SCALAR_H
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btSerializer.cpp b/SRC/ChronoEngine/collision/bullet/LinearMath/btSerializer.cpp
new file mode 100644
index 0000000..708a419
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btSerializer.cpp
@@ -0,0 +1,577 @@
+char sBulletDNAstr64[]= {
+83,68,78,65,78,65,77,69,-79,0,0,0,109,95,115,105,122,101,0,109,
+95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
+99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
+108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
+115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
+116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
+93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
+95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
+116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
+65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
+101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
+105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
+95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
+114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
+95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
+120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
+118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
+97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
+0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
+101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
+111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
+95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
+111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
+117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
+122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
+114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
+109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
+109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
+97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
+100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
+83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
+108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
+95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
+108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
+0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
+95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
+105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
+83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
+115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
+97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
+109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
+97,108,117,101,115,91,51,93,0,42,109,95,118,101,114,116,105,99,101,115,
+51,102,0,42,109,95,118,101,114,116,105,99,101,115,51,100,0,42,109,95,
+105,110,100,105,99,101,115,51,50,0,42,109,95,51,105,110,100,105,99,101,
+115,49,54,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,
+117,109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,
+116,105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,
+114,0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,
+104,80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,
+99,101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,
+66,118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,
+108,101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,
+111,77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,97,
+110,115,102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,
+0,109,95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,
+99,104,105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,
+83,104,97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,
+104,97,112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,
+103,115,0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,
+95,101,100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,
+101,86,50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,
+98,108,101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,
+95,118,97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,
+121,65,114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,
+115,105,108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,
+110,0,109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,
+104,111,108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,
+104,114,101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,
+104,114,101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,
+109,95,104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,
+109,86,97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,
+103,105,109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,
+115,99,97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,
+0,42,109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,
+117,98,108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,
+100,80,111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,
+93,0,42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,
+101,0,42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
+42,109,95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,
+101,0,109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,
+95,105,110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,
+114,97,110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,
+116,105,111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,
+95,105,110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,
+114,86,101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,
+112,105,99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,
+116,80,114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,
+0,109,95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,
+109,95,102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,
+116,105,111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,
+95,99,99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,
+115,0,109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,
+108,100,0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,
+114,105,99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,
+108,97,103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,
+99,111,109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,
+116,105,111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,
+108,84,121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,
+87,105,116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,
+99,116,68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,
+101,110,115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,
+101,108,111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,
+111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,
+114,0,109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,
+114,97,118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,
+101,108,101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,
+105,97,76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,
+0,109,95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,
+101,114,115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,
+112,105,110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,
+103,0,109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,
+103,70,97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,
+76,105,110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,
+108,100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,
+103,117,108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,
+100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,
+117,108,97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,
+108,105,110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,
+111,108,100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,
+103,84,104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,
+110,97,108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,
+116,114,97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,
+65,0,42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,
+101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,
+112,101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,
+100,0,109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,
+97,112,112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,
+68,114,97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,
+108,108,105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,
+100,66,111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,
+116,121,112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,
+95,112,105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,
+0,109,95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,
+109,101,0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,
+109,101,65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,
+101,110,97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,
+95,109,111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,
+0,109,95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,
+95,108,111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,
+105,109,105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,
+0,109,95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,
+120,97,116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,
+83,112,97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,
+95,116,119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,
+0,109,95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,
+109,95,108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
+95,97,110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,
+95,97,110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
+95,117,115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,
+114,97,109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,
+67,111,110,115,116,114,97,105,110,116,70,114,97,109,101,0,84,89,80,69,
+58,0,0,0,99,104,97,114,0,117,99,104,97,114,0,115,104,111,114,116,
+0,117,115,104,111,114,116,0,105,110,116,0,108,111,110,103,0,117,108,111,
+110,103,0,102,108,111,97,116,0,100,111,117,98,108,101,0,118,111,105,100,
+0,80,111,105,110,116,101,114,65,114,114,97,121,0,98,116,80,104,121,115,
+105,99,115,83,121,115,116,101,109,0,76,105,115,116,66,97,115,101,0,98,
+116,86,101,99,116,111,114,51,70,108,111,97,116,68,97,116,97,0,98,116,
+86,101,99,116,111,114,51,68,111,117,98,108,101,68,97,116,97,0,98,116,
+77,97,116,114,105,120,51,120,51,70,108,111,97,116,68,97,116,97,0,98,
+116,77,97,116,114,105,120,51,120,51,68,111,117,98,108,101,68,97,116,97,
+0,98,116,84,114,97,110,115,102,111,114,109,70,108,111,97,116,68,97,116,
+97,0,98,116,84,114,97,110,115,102,111,114,109,68,111,117,98,108,101,68,
+97,116,97,0,98,116,66,118,104,83,117,98,116,114,101,101,73,110,102,111,
+68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,
+111,100,101,70,108,111,97,116,68,97,116,97,0,98,116,79,112,116,105,109,
+105,122,101,100,66,118,104,78,111,100,101,68,111,117,98,108,101,68,97,116,
+97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,78,111,100,101,
+68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,70,
+108,111,97,116,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,
+66,118,104,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
+105,115,105,111,110,83,104,97,112,101,68,97,116,97,0,98,116,83,116,97,
+116,105,99,80,108,97,110,101,83,104,97,112,101,68,97,116,97,0,98,116,
+67,111,110,118,101,120,73,110,116,101,114,110,97,108,83,104,97,112,101,68,
+97,116,97,0,98,116,80,111,115,105,116,105,111,110,65,110,100,82,97,100,
+105,117,115,0,98,116,77,117,108,116,105,83,112,104,101,114,101,83,104,97,
+112,101,68,97,116,97,0,98,116,73,110,116,73,110,100,101,120,68,97,116,
+97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,68,97,116,
+97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,84,114,105,
+112,108,101,116,68,97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,
+97,116,97,0,98,116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,
+116,101,114,102,97,99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,
+108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,
+105,97,110,103,108,101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,
+67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68,97,
+116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68,97,
+116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68,97,
+116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97,116,
+97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116,97,
+0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101,68,
+97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97,112,
+101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98,106,
+101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
+105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116,97,
+0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97,116,
+97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101,68,
+97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102,111,
+49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116,68,
+97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97,0,
+98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,
+105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110,116,
+50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117,98,
+108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116,114,
+97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,
+103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,
+97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114,97,
+105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68,111,
+102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,
+105,100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,0,
+84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0,
+8,0,0,0,16,0,48,0,16,0,16,0,32,0,48,0,96,0,64,0,
+-128,0,20,0,48,0,80,0,16,0,96,0,-112,0,16,0,56,0,56,0,
+20,0,72,0,4,0,4,0,8,0,48,0,32,0,80,0,72,0,80,0,
+32,0,64,0,64,0,16,0,72,0,80,0,-40,1,8,1,-16,1,-88,3,
+8,0,56,0,0,0,88,0,120,0,96,1,-32,0,-40,0,0,1,-48,0,
+83,84,82,67,47,0,0,0,10,0,3,0,4,0,0,0,4,0,1,0,
+9,0,2,0,11,0,3,0,10,0,3,0,10,0,4,0,10,0,5,0,
+12,0,2,0,9,0,6,0,9,0,7,0,13,0,1,0,7,0,8,0,
+14,0,1,0,8,0,8,0,15,0,1,0,13,0,9,0,16,0,1,0,
+14,0,9,0,17,0,2,0,15,0,10,0,13,0,11,0,18,0,2,0,
+16,0,10,0,14,0,11,0,19,0,4,0,4,0,12,0,4,0,13,0,
+2,0,14,0,2,0,15,0,20,0,6,0,13,0,16,0,13,0,17,0,
+4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,21,0,6,0,
+14,0,16,0,14,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0,
+0,0,21,0,22,0,3,0,2,0,14,0,2,0,15,0,4,0,22,0,
+23,0,12,0,13,0,23,0,13,0,24,0,13,0,25,0,4,0,26,0,
+4,0,27,0,4,0,28,0,4,0,29,0,20,0,30,0,22,0,31,0,
+19,0,32,0,4,0,33,0,4,0,34,0,24,0,12,0,14,0,23,0,
+14,0,24,0,14,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,
+4,0,29,0,21,0,30,0,22,0,31,0,4,0,33,0,4,0,34,0,
+19,0,32,0,25,0,3,0,0,0,35,0,4,0,36,0,0,0,37,0,
+26,0,5,0,25,0,38,0,13,0,39,0,13,0,40,0,7,0,41,0,
+0,0,21,0,27,0,5,0,25,0,38,0,13,0,39,0,13,0,42,0,
+7,0,43,0,4,0,44,0,28,0,2,0,13,0,45,0,7,0,46,0,
+29,0,4,0,27,0,47,0,28,0,48,0,4,0,49,0,0,0,37,0,
+30,0,1,0,4,0,50,0,31,0,2,0,2,0,50,0,0,0,51,0,
+32,0,2,0,2,0,52,0,0,0,51,0,33,0,7,0,13,0,53,0,
+14,0,54,0,30,0,55,0,32,0,56,0,31,0,57,0,4,0,58,0,
+4,0,59,0,34,0,4,0,33,0,60,0,13,0,61,0,4,0,62,0,
+0,0,37,0,35,0,7,0,25,0,38,0,34,0,63,0,23,0,64,0,
+24,0,65,0,36,0,66,0,7,0,43,0,0,0,67,0,37,0,4,0,
+17,0,68,0,25,0,69,0,4,0,70,0,7,0,71,0,38,0,4,0,
+25,0,38,0,37,0,72,0,4,0,73,0,7,0,43,0,39,0,3,0,
+27,0,47,0,4,0,74,0,0,0,37,0,40,0,3,0,27,0,47,0,
+4,0,74,0,0,0,37,0,41,0,4,0,4,0,75,0,7,0,76,0,
+7,0,77,0,7,0,78,0,36,0,14,0,4,0,79,0,4,0,80,0,
+41,0,81,0,4,0,82,0,7,0,83,0,7,0,84,0,7,0,85,0,
+7,0,86,0,7,0,87,0,4,0,88,0,4,0,89,0,4,0,90,0,
+4,0,91,0,0,0,37,0,42,0,5,0,25,0,38,0,34,0,63,0,
+13,0,39,0,7,0,43,0,4,0,92,0,43,0,5,0,27,0,47,0,
+13,0,93,0,14,0,94,0,4,0,95,0,0,0,96,0,44,0,24,0,
+9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,18,0,100,0,
+18,0,101,0,14,0,102,0,14,0,103,0,14,0,104,0,8,0,105,0,
+8,0,106,0,8,0,107,0,8,0,108,0,8,0,109,0,8,0,110,0,
+8,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
+4,0,116,0,4,0,117,0,4,0,118,0,0,0,37,0,45,0,23,0,
+9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,17,0,100,0,
+17,0,101,0,13,0,102,0,13,0,103,0,13,0,104,0,7,0,105,0,
+7,0,106,0,7,0,107,0,7,0,108,0,7,0,109,0,7,0,110,0,
+7,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
+4,0,116,0,4,0,117,0,4,0,118,0,46,0,21,0,45,0,119,0,
+15,0,120,0,13,0,121,0,13,0,122,0,13,0,123,0,13,0,124,0,
+13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0,13,0,-127,0,
+7,0,-126,0,7,0,-125,0,7,0,-124,0,7,0,-123,0,7,0,-122,0,
+7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0,4,0,-117,0,
+47,0,22,0,44,0,119,0,16,0,120,0,14,0,121,0,14,0,122,0,
+14,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0,14,0,127,0,
+14,0,-128,0,14,0,-127,0,8,0,-126,0,8,0,-125,0,8,0,-124,0,
+8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0,8,0,-119,0,
+8,0,-118,0,4,0,-117,0,0,0,37,0,48,0,2,0,4,0,-116,0,
+4,0,-115,0,49,0,11,0,50,0,-114,0,50,0,-113,0,0,0,35,0,
+4,0,-112,0,4,0,-111,0,4,0,-110,0,4,0,-109,0,7,0,-108,0,
+7,0,-107,0,4,0,-106,0,0,0,-105,0,51,0,3,0,49,0,-104,0,
+13,0,-103,0,13,0,-102,0,52,0,3,0,49,0,-104,0,14,0,-103,0,
+14,0,-102,0,53,0,13,0,49,0,-104,0,18,0,-101,0,18,0,-100,0,
+4,0,-99,0,4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,
+7,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,
+54,0,13,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,4,0,-99,0,
+4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,7,0,-94,0,
+7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,55,0,11,0,
+49,0,-104,0,17,0,-101,0,17,0,-100,0,7,0,-89,0,7,0,-88,0,
+7,0,-87,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,7,0,-86,0,
+0,0,21,0,56,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
+13,0,-85,0,13,0,-84,0,13,0,-83,0,13,0,-82,0,4,0,-81,0,
+4,0,-80,0,57,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
+7,0,-85,0,7,0,-84,0,7,0,-83,0,7,0,-82,0,4,0,-81,0,
+4,0,-80,0,};
+int sBulletDNAlen64= sizeof(sBulletDNAstr64);
+
+char sBulletDNAstr[]= {
+83,68,78,65,78,65,77,69,-79,0,0,0,109,95,115,105,122,101,0,109,
+95,99,97,112,97,99,105,116,121,0,42,109,95,100,97,116,97,0,109,95,
+99,111,108,108,105,115,105,111,110,83,104,97,112,101,115,0,109,95,99,111,
+108,108,105,115,105,111,110,79,98,106,101,99,116,115,0,109,95,99,111,110,
+115,116,114,97,105,110,116,115,0,42,102,105,114,115,116,0,42,108,97,115,
+116,0,109,95,102,108,111,97,116,115,91,52,93,0,109,95,101,108,91,51,
+93,0,109,95,98,97,115,105,115,0,109,95,111,114,105,103,105,110,0,109,
+95,114,111,111,116,78,111,100,101,73,110,100,101,120,0,109,95,115,117,98,
+116,114,101,101,83,105,122,101,0,109,95,113,117,97,110,116,105,122,101,100,
+65,97,98,98,77,105,110,91,51,93,0,109,95,113,117,97,110,116,105,122,
+101,100,65,97,98,98,77,97,120,91,51,93,0,109,95,97,97,98,98,77,
+105,110,79,114,103,0,109,95,97,97,98,98,77,97,120,79,114,103,0,109,
+95,101,115,99,97,112,101,73,110,100,101,120,0,109,95,115,117,98,80,97,
+114,116,0,109,95,116,114,105,97,110,103,108,101,73,110,100,101,120,0,109,
+95,112,97,100,91,52,93,0,109,95,101,115,99,97,112,101,73,110,100,101,
+120,79,114,84,114,105,97,110,103,108,101,73,110,100,101,120,0,109,95,98,
+118,104,65,97,98,98,77,105,110,0,109,95,98,118,104,65,97,98,98,77,
+97,120,0,109,95,98,118,104,81,117,97,110,116,105,122,97,116,105,111,110,
+0,109,95,99,117,114,78,111,100,101,73,110,100,101,120,0,109,95,117,115,
+101,81,117,97,110,116,105,122,97,116,105,111,110,0,109,95,110,117,109,67,
+111,110,116,105,103,117,111,117,115,76,101,97,102,78,111,100,101,115,0,109,
+95,110,117,109,81,117,97,110,116,105,122,101,100,67,111,110,116,105,103,117,
+111,117,115,78,111,100,101,115,0,42,109,95,99,111,110,116,105,103,117,111,
+117,115,78,111,100,101,115,80,116,114,0,42,109,95,113,117,97,110,116,105,
+122,101,100,67,111,110,116,105,103,117,111,117,115,78,111,100,101,115,80,116,
+114,0,42,109,95,115,117,98,84,114,101,101,73,110,102,111,80,116,114,0,
+109,95,116,114,97,118,101,114,115,97,108,77,111,100,101,0,109,95,110,117,
+109,83,117,98,116,114,101,101,72,101,97,100,101,114,115,0,42,109,95,110,
+97,109,101,0,109,95,115,104,97,112,101,84,121,112,101,0,109,95,112,97,
+100,100,105,110,103,91,52,93,0,109,95,99,111,108,108,105,115,105,111,110,
+83,104,97,112,101,68,97,116,97,0,109,95,108,111,99,97,108,83,99,97,
+108,105,110,103,0,109,95,112,108,97,110,101,78,111,114,109,97,108,0,109,
+95,112,108,97,110,101,67,111,110,115,116,97,110,116,0,109,95,105,109,112,
+108,105,99,105,116,83,104,97,112,101,68,105,109,101,110,115,105,111,110,115,
+0,109,95,99,111,108,108,105,115,105,111,110,77,97,114,103,105,110,0,109,
+95,112,97,100,100,105,110,103,0,109,95,112,111,115,0,109,95,114,97,100,
+105,117,115,0,109,95,99,111,110,118,101,120,73,110,116,101,114,110,97,108,
+83,104,97,112,101,68,97,116,97,0,42,109,95,108,111,99,97,108,80,111,
+115,105,116,105,111,110,65,114,114,97,121,80,116,114,0,109,95,108,111,99,
+97,108,80,111,115,105,116,105,111,110,65,114,114,97,121,83,105,122,101,0,
+109,95,118,97,108,117,101,0,109,95,112,97,100,91,50,93,0,109,95,118,
+97,108,117,101,115,91,51,93,0,42,109,95,118,101,114,116,105,99,101,115,
+51,102,0,42,109,95,118,101,114,116,105,99,101,115,51,100,0,42,109,95,
+105,110,100,105,99,101,115,51,50,0,42,109,95,51,105,110,100,105,99,101,
+115,49,54,0,42,109,95,105,110,100,105,99,101,115,49,54,0,109,95,110,
+117,109,84,114,105,97,110,103,108,101,115,0,109,95,110,117,109,86,101,114,
+116,105,99,101,115,0,42,109,95,109,101,115,104,80,97,114,116,115,80,116,
+114,0,109,95,115,99,97,108,105,110,103,0,109,95,110,117,109,77,101,115,
+104,80,97,114,116,115,0,109,95,109,101,115,104,73,110,116,101,114,102,97,
+99,101,0,42,109,95,113,117,97,110,116,105,122,101,100,70,108,111,97,116,
+66,118,104,0,42,109,95,113,117,97,110,116,105,122,101,100,68,111,117,98,
+108,101,66,118,104,0,42,109,95,116,114,105,97,110,103,108,101,73,110,102,
+111,77,97,112,0,109,95,112,97,100,51,91,52,93,0,109,95,116,114,97,
+110,115,102,111,114,109,0,42,109,95,99,104,105,108,100,83,104,97,112,101,
+0,109,95,99,104,105,108,100,83,104,97,112,101,84,121,112,101,0,109,95,
+99,104,105,108,100,77,97,114,103,105,110,0,42,109,95,99,104,105,108,100,
+83,104,97,112,101,80,116,114,0,109,95,110,117,109,67,104,105,108,100,83,
+104,97,112,101,115,0,109,95,117,112,65,120,105,115,0,109,95,102,108,97,
+103,115,0,109,95,101,100,103,101,86,48,86,49,65,110,103,108,101,0,109,
+95,101,100,103,101,86,49,86,50,65,110,103,108,101,0,109,95,101,100,103,
+101,86,50,86,48,65,110,103,108,101,0,42,109,95,104,97,115,104,84,97,
+98,108,101,80,116,114,0,42,109,95,110,101,120,116,80,116,114,0,42,109,
+95,118,97,108,117,101,65,114,114,97,121,80,116,114,0,42,109,95,107,101,
+121,65,114,114,97,121,80,116,114,0,109,95,99,111,110,118,101,120,69,112,
+115,105,108,111,110,0,109,95,112,108,97,110,97,114,69,112,115,105,108,111,
+110,0,109,95,101,113,117,97,108,86,101,114,116,101,120,84,104,114,101,115,
+104,111,108,100,0,109,95,101,100,103,101,68,105,115,116,97,110,99,101,84,
+104,114,101,115,104,111,108,100,0,109,95,122,101,114,111,65,114,101,97,84,
+104,114,101,115,104,111,108,100,0,109,95,110,101,120,116,83,105,122,101,0,
+109,95,104,97,115,104,84,97,98,108,101,83,105,122,101,0,109,95,110,117,
+109,86,97,108,117,101,115,0,109,95,110,117,109,75,101,121,115,0,109,95,
+103,105,109,112,97,99,116,83,117,98,84,121,112,101,0,42,109,95,117,110,
+115,99,97,108,101,100,80,111,105,110,116,115,70,108,111,97,116,80,116,114,
+0,42,109,95,117,110,115,99,97,108,101,100,80,111,105,110,116,115,68,111,
+117,98,108,101,80,116,114,0,109,95,110,117,109,85,110,115,99,97,108,101,
+100,80,111,105,110,116,115,0,109,95,112,97,100,100,105,110,103,51,91,52,
+93,0,42,109,95,98,114,111,97,100,112,104,97,115,101,72,97,110,100,108,
+101,0,42,109,95,99,111,108,108,105,115,105,111,110,83,104,97,112,101,0,
+42,109,95,114,111,111,116,67,111,108,108,105,115,105,111,110,83,104,97,112,
+101,0,109,95,119,111,114,108,100,84,114,97,110,115,102,111,114,109,0,109,
+95,105,110,116,101,114,112,111,108,97,116,105,111,110,87,111,114,108,100,84,
+114,97,110,115,102,111,114,109,0,109,95,105,110,116,101,114,112,111,108,97,
+116,105,111,110,76,105,110,101,97,114,86,101,108,111,99,105,116,121,0,109,
+95,105,110,116,101,114,112,111,108,97,116,105,111,110,65,110,103,117,108,97,
+114,86,101,108,111,99,105,116,121,0,109,95,97,110,105,115,111,116,114,111,
+112,105,99,70,114,105,99,116,105,111,110,0,109,95,99,111,110,116,97,99,
+116,80,114,111,99,101,115,115,105,110,103,84,104,114,101,115,104,111,108,100,
+0,109,95,100,101,97,99,116,105,118,97,116,105,111,110,84,105,109,101,0,
+109,95,102,114,105,99,116,105,111,110,0,109,95,114,101,115,116,105,116,117,
+116,105,111,110,0,109,95,104,105,116,70,114,97,99,116,105,111,110,0,109,
+95,99,99,100,83,119,101,112,116,83,112,104,101,114,101,82,97,100,105,117,
+115,0,109,95,99,99,100,77,111,116,105,111,110,84,104,114,101,115,104,111,
+108,100,0,109,95,104,97,115,65,110,105,115,111,116,114,111,112,105,99,70,
+114,105,99,116,105,111,110,0,109,95,99,111,108,108,105,115,105,111,110,70,
+108,97,103,115,0,109,95,105,115,108,97,110,100,84,97,103,49,0,109,95,
+99,111,109,112,97,110,105,111,110,73,100,0,109,95,97,99,116,105,118,97,
+116,105,111,110,83,116,97,116,101,49,0,109,95,105,110,116,101,114,110,97,
+108,84,121,112,101,0,109,95,99,104,101,99,107,67,111,108,108,105,100,101,
+87,105,116,104,0,109,95,99,111,108,108,105,115,105,111,110,79,98,106,101,
+99,116,68,97,116,97,0,109,95,105,110,118,73,110,101,114,116,105,97,84,
+101,110,115,111,114,87,111,114,108,100,0,109,95,108,105,110,101,97,114,86,
+101,108,111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,86,101,108,
+111,99,105,116,121,0,109,95,97,110,103,117,108,97,114,70,97,99,116,111,
+114,0,109,95,108,105,110,101,97,114,70,97,99,116,111,114,0,109,95,103,
+114,97,118,105,116,121,0,109,95,103,114,97,118,105,116,121,95,97,99,99,
+101,108,101,114,97,116,105,111,110,0,109,95,105,110,118,73,110,101,114,116,
+105,97,76,111,99,97,108,0,109,95,116,111,116,97,108,70,111,114,99,101,
+0,109,95,116,111,116,97,108,84,111,114,113,117,101,0,109,95,105,110,118,
+101,114,115,101,77,97,115,115,0,109,95,108,105,110,101,97,114,68,97,109,
+112,105,110,103,0,109,95,97,110,103,117,108,97,114,68,97,109,112,105,110,
+103,0,109,95,97,100,100,105,116,105,111,110,97,108,68,97,109,112,105,110,
+103,70,97,99,116,111,114,0,109,95,97,100,100,105,116,105,111,110,97,108,
+76,105,110,101,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,
+108,100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,
+103,117,108,97,114,68,97,109,112,105,110,103,84,104,114,101,115,104,111,108,
+100,83,113,114,0,109,95,97,100,100,105,116,105,111,110,97,108,65,110,103,
+117,108,97,114,68,97,109,112,105,110,103,70,97,99,116,111,114,0,109,95,
+108,105,110,101,97,114,83,108,101,101,112,105,110,103,84,104,114,101,115,104,
+111,108,100,0,109,95,97,110,103,117,108,97,114,83,108,101,101,112,105,110,
+103,84,104,114,101,115,104,111,108,100,0,109,95,97,100,100,105,116,105,111,
+110,97,108,68,97,109,112,105,110,103,0,109,95,110,117,109,67,111,110,115,
+116,114,97,105,110,116,82,111,119,115,0,110,117,98,0,42,109,95,114,98,
+65,0,42,109,95,114,98,66,0,109,95,111,98,106,101,99,116,84,121,112,
+101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,84,121,
+112,101,0,109,95,117,115,101,114,67,111,110,115,116,114,97,105,110,116,73,
+100,0,109,95,110,101,101,100,115,70,101,101,100,98,97,99,107,0,109,95,
+97,112,112,108,105,101,100,73,109,112,117,108,115,101,0,109,95,100,98,103,
+68,114,97,119,83,105,122,101,0,109,95,100,105,115,97,98,108,101,67,111,
+108,108,105,115,105,111,110,115,66,101,116,119,101,101,110,76,105,110,107,101,
+100,66,111,100,105,101,115,0,109,95,112,97,100,52,91,52,93,0,109,95,
+116,121,112,101,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,109,
+95,112,105,118,111,116,73,110,65,0,109,95,112,105,118,111,116,73,110,66,
+0,109,95,114,98,65,70,114,97,109,101,0,109,95,114,98,66,70,114,97,
+109,101,0,109,95,117,115,101,82,101,102,101,114,101,110,99,101,70,114,97,
+109,101,65,0,109,95,97,110,103,117,108,97,114,79,110,108,121,0,109,95,
+101,110,97,98,108,101,65,110,103,117,108,97,114,77,111,116,111,114,0,109,
+95,109,111,116,111,114,84,97,114,103,101,116,86,101,108,111,99,105,116,121,
+0,109,95,109,97,120,77,111,116,111,114,73,109,112,117,108,115,101,0,109,
+95,108,111,119,101,114,76,105,109,105,116,0,109,95,117,112,112,101,114,76,
+105,109,105,116,0,109,95,108,105,109,105,116,83,111,102,116,110,101,115,115,
+0,109,95,98,105,97,115,70,97,99,116,111,114,0,109,95,114,101,108,97,
+120,97,116,105,111,110,70,97,99,116,111,114,0,109,95,115,119,105,110,103,
+83,112,97,110,49,0,109,95,115,119,105,110,103,83,112,97,110,50,0,109,
+95,116,119,105,115,116,83,112,97,110,0,109,95,100,97,109,112,105,110,103,
+0,109,95,108,105,110,101,97,114,85,112,112,101,114,76,105,109,105,116,0,
+109,95,108,105,110,101,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
+95,97,110,103,117,108,97,114,85,112,112,101,114,76,105,109,105,116,0,109,
+95,97,110,103,117,108,97,114,76,111,119,101,114,76,105,109,105,116,0,109,
+95,117,115,101,76,105,110,101,97,114,82,101,102,101,114,101,110,99,101,70,
+114,97,109,101,65,0,109,95,117,115,101,79,102,102,115,101,116,70,111,114,
+67,111,110,115,116,114,97,105,110,116,70,114,97,109,101,0,84,89,80,69,
+58,0,0,0,99,104,97,114,0,117,99,104,97,114,0,115,104,111,114,116,
+0,117,115,104,111,114,116,0,105,110,116,0,108,111,110,103,0,117,108,111,
+110,103,0,102,108,111,97,116,0,100,111,117,98,108,101,0,118,111,105,100,
+0,80,111,105,110,116,101,114,65,114,114,97,121,0,98,116,80,104,121,115,
+105,99,115,83,121,115,116,101,109,0,76,105,115,116,66,97,115,101,0,98,
+116,86,101,99,116,111,114,51,70,108,111,97,116,68,97,116,97,0,98,116,
+86,101,99,116,111,114,51,68,111,117,98,108,101,68,97,116,97,0,98,116,
+77,97,116,114,105,120,51,120,51,70,108,111,97,116,68,97,116,97,0,98,
+116,77,97,116,114,105,120,51,120,51,68,111,117,98,108,101,68,97,116,97,
+0,98,116,84,114,97,110,115,102,111,114,109,70,108,111,97,116,68,97,116,
+97,0,98,116,84,114,97,110,115,102,111,114,109,68,111,117,98,108,101,68,
+97,116,97,0,98,116,66,118,104,83,117,98,116,114,101,101,73,110,102,111,
+68,97,116,97,0,98,116,79,112,116,105,109,105,122,101,100,66,118,104,78,
+111,100,101,70,108,111,97,116,68,97,116,97,0,98,116,79,112,116,105,109,
+105,122,101,100,66,118,104,78,111,100,101,68,111,117,98,108,101,68,97,116,
+97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,78,111,100,101,
+68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,66,118,104,70,
+108,111,97,116,68,97,116,97,0,98,116,81,117,97,110,116,105,122,101,100,
+66,118,104,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
+105,115,105,111,110,83,104,97,112,101,68,97,116,97,0,98,116,83,116,97,
+116,105,99,80,108,97,110,101,83,104,97,112,101,68,97,116,97,0,98,116,
+67,111,110,118,101,120,73,110,116,101,114,110,97,108,83,104,97,112,101,68,
+97,116,97,0,98,116,80,111,115,105,116,105,111,110,65,110,100,82,97,100,
+105,117,115,0,98,116,77,117,108,116,105,83,112,104,101,114,101,83,104,97,
+112,101,68,97,116,97,0,98,116,73,110,116,73,110,100,101,120,68,97,116,
+97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,68,97,116,
+97,0,98,116,83,104,111,114,116,73,110,116,73,110,100,101,120,84,114,105,
+112,108,101,116,68,97,116,97,0,98,116,77,101,115,104,80,97,114,116,68,
+97,116,97,0,98,116,83,116,114,105,100,105,110,103,77,101,115,104,73,110,
+116,101,114,102,97,99,101,68,97,116,97,0,98,116,84,114,105,97,110,103,
+108,101,77,101,115,104,83,104,97,112,101,68,97,116,97,0,98,116,84,114,
+105,97,110,103,108,101,73,110,102,111,77,97,112,68,97,116,97,0,98,116,
+67,111,109,112,111,117,110,100,83,104,97,112,101,67,104,105,108,100,68,97,
+116,97,0,98,116,67,111,109,112,111,117,110,100,83,104,97,112,101,68,97,
+116,97,0,98,116,67,121,108,105,110,100,101,114,83,104,97,112,101,68,97,
+116,97,0,98,116,67,97,112,115,117,108,101,83,104,97,112,101,68,97,116,
+97,0,98,116,84,114,105,97,110,103,108,101,73,110,102,111,68,97,116,97,
+0,98,116,71,73,109,112,97,99,116,77,101,115,104,83,104,97,112,101,68,
+97,116,97,0,98,116,67,111,110,118,101,120,72,117,108,108,83,104,97,112,
+101,68,97,116,97,0,98,116,67,111,108,108,105,115,105,111,110,79,98,106,
+101,99,116,68,111,117,98,108,101,68,97,116,97,0,98,116,67,111,108,108,
+105,115,105,111,110,79,98,106,101,99,116,70,108,111,97,116,68,97,116,97,
+0,98,116,82,105,103,105,100,66,111,100,121,70,108,111,97,116,68,97,116,
+97,0,98,116,82,105,103,105,100,66,111,100,121,68,111,117,98,108,101,68,
+97,116,97,0,98,116,67,111,110,115,116,114,97,105,110,116,73,110,102,111,
+49,0,98,116,84,121,112,101,100,67,111,110,115,116,114,97,105,110,116,68,
+97,116,97,0,98,116,82,105,103,105,100,66,111,100,121,68,97,116,97,0,
+98,116,80,111,105,110,116,50,80,111,105,110,116,67,111,110,115,116,114,97,
+105,110,116,70,108,111,97,116,68,97,116,97,0,98,116,80,111,105,110,116,
+50,80,111,105,110,116,67,111,110,115,116,114,97,105,110,116,68,111,117,98,
+108,101,68,97,116,97,0,98,116,72,105,110,103,101,67,111,110,115,116,114,
+97,105,110,116,68,111,117,98,108,101,68,97,116,97,0,98,116,72,105,110,
+103,101,67,111,110,115,116,114,97,105,110,116,70,108,111,97,116,68,97,116,
+97,0,98,116,67,111,110,101,84,119,105,115,116,67,111,110,115,116,114,97,
+105,110,116,68,97,116,97,0,98,116,71,101,110,101,114,105,99,54,68,111,
+102,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,98,116,83,108,
+105,100,101,114,67,111,110,115,116,114,97,105,110,116,68,97,116,97,0,0,
+84,76,69,78,1,0,1,0,2,0,2,0,4,0,4,0,4,0,4,0,
+8,0,0,0,12,0,36,0,8,0,16,0,32,0,48,0,96,0,64,0,
+-128,0,20,0,48,0,80,0,16,0,84,0,-124,0,12,0,52,0,52,0,
+20,0,64,0,4,0,4,0,8,0,28,0,28,0,60,0,56,0,76,0,
+24,0,60,0,60,0,16,0,64,0,68,0,-56,1,-8,0,-32,1,-104,3,
+8,0,44,0,0,0,76,0,108,0,84,1,-44,0,-52,0,-12,0,-60,0,
+83,84,82,67,47,0,0,0,10,0,3,0,4,0,0,0,4,0,1,0,
+9,0,2,0,11,0,3,0,10,0,3,0,10,0,4,0,10,0,5,0,
+12,0,2,0,9,0,6,0,9,0,7,0,13,0,1,0,7,0,8,0,
+14,0,1,0,8,0,8,0,15,0,1,0,13,0,9,0,16,0,1,0,
+14,0,9,0,17,0,2,0,15,0,10,0,13,0,11,0,18,0,2,0,
+16,0,10,0,14,0,11,0,19,0,4,0,4,0,12,0,4,0,13,0,
+2,0,14,0,2,0,15,0,20,0,6,0,13,0,16,0,13,0,17,0,
+4,0,18,0,4,0,19,0,4,0,20,0,0,0,21,0,21,0,6,0,
+14,0,16,0,14,0,17,0,4,0,18,0,4,0,19,0,4,0,20,0,
+0,0,21,0,22,0,3,0,2,0,14,0,2,0,15,0,4,0,22,0,
+23,0,12,0,13,0,23,0,13,0,24,0,13,0,25,0,4,0,26,0,
+4,0,27,0,4,0,28,0,4,0,29,0,20,0,30,0,22,0,31,0,
+19,0,32,0,4,0,33,0,4,0,34,0,24,0,12,0,14,0,23,0,
+14,0,24,0,14,0,25,0,4,0,26,0,4,0,27,0,4,0,28,0,
+4,0,29,0,21,0,30,0,22,0,31,0,4,0,33,0,4,0,34,0,
+19,0,32,0,25,0,3,0,0,0,35,0,4,0,36,0,0,0,37,0,
+26,0,5,0,25,0,38,0,13,0,39,0,13,0,40,0,7,0,41,0,
+0,0,21,0,27,0,5,0,25,0,38,0,13,0,39,0,13,0,42,0,
+7,0,43,0,4,0,44,0,28,0,2,0,13,0,45,0,7,0,46,0,
+29,0,4,0,27,0,47,0,28,0,48,0,4,0,49,0,0,0,37,0,
+30,0,1,0,4,0,50,0,31,0,2,0,2,0,50,0,0,0,51,0,
+32,0,2,0,2,0,52,0,0,0,51,0,33,0,7,0,13,0,53,0,
+14,0,54,0,30,0,55,0,32,0,56,0,31,0,57,0,4,0,58,0,
+4,0,59,0,34,0,4,0,33,0,60,0,13,0,61,0,4,0,62,0,
+0,0,37,0,35,0,7,0,25,0,38,0,34,0,63,0,23,0,64,0,
+24,0,65,0,36,0,66,0,7,0,43,0,0,0,67,0,37,0,4,0,
+17,0,68,0,25,0,69,0,4,0,70,0,7,0,71,0,38,0,4,0,
+25,0,38,0,37,0,72,0,4,0,73,0,7,0,43,0,39,0,3,0,
+27,0,47,0,4,0,74,0,0,0,37,0,40,0,3,0,27,0,47,0,
+4,0,74,0,0,0,37,0,41,0,4,0,4,0,75,0,7,0,76,0,
+7,0,77,0,7,0,78,0,36,0,14,0,4,0,79,0,4,0,80,0,
+41,0,81,0,4,0,82,0,7,0,83,0,7,0,84,0,7,0,85,0,
+7,0,86,0,7,0,87,0,4,0,88,0,4,0,89,0,4,0,90,0,
+4,0,91,0,0,0,37,0,42,0,5,0,25,0,38,0,34,0,63,0,
+13,0,39,0,7,0,43,0,4,0,92,0,43,0,5,0,27,0,47,0,
+13,0,93,0,14,0,94,0,4,0,95,0,0,0,96,0,44,0,24,0,
+9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,18,0,100,0,
+18,0,101,0,14,0,102,0,14,0,103,0,14,0,104,0,8,0,105,0,
+8,0,106,0,8,0,107,0,8,0,108,0,8,0,109,0,8,0,110,0,
+8,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
+4,0,116,0,4,0,117,0,4,0,118,0,0,0,37,0,45,0,23,0,
+9,0,97,0,9,0,98,0,25,0,99,0,0,0,35,0,17,0,100,0,
+17,0,101,0,13,0,102,0,13,0,103,0,13,0,104,0,7,0,105,0,
+7,0,106,0,7,0,107,0,7,0,108,0,7,0,109,0,7,0,110,0,
+7,0,111,0,4,0,112,0,4,0,113,0,4,0,114,0,4,0,115,0,
+4,0,116,0,4,0,117,0,4,0,118,0,46,0,21,0,45,0,119,0,
+15,0,120,0,13,0,121,0,13,0,122,0,13,0,123,0,13,0,124,0,
+13,0,125,0,13,0,126,0,13,0,127,0,13,0,-128,0,13,0,-127,0,
+7,0,-126,0,7,0,-125,0,7,0,-124,0,7,0,-123,0,7,0,-122,0,
+7,0,-121,0,7,0,-120,0,7,0,-119,0,7,0,-118,0,4,0,-117,0,
+47,0,22,0,44,0,119,0,16,0,120,0,14,0,121,0,14,0,122,0,
+14,0,123,0,14,0,124,0,14,0,125,0,14,0,126,0,14,0,127,0,
+14,0,-128,0,14,0,-127,0,8,0,-126,0,8,0,-125,0,8,0,-124,0,
+8,0,-123,0,8,0,-122,0,8,0,-121,0,8,0,-120,0,8,0,-119,0,
+8,0,-118,0,4,0,-117,0,0,0,37,0,48,0,2,0,4,0,-116,0,
+4,0,-115,0,49,0,11,0,50,0,-114,0,50,0,-113,0,0,0,35,0,
+4,0,-112,0,4,0,-111,0,4,0,-110,0,4,0,-109,0,7,0,-108,0,
+7,0,-107,0,4,0,-106,0,0,0,-105,0,51,0,3,0,49,0,-104,0,
+13,0,-103,0,13,0,-102,0,52,0,3,0,49,0,-104,0,14,0,-103,0,
+14,0,-102,0,53,0,13,0,49,0,-104,0,18,0,-101,0,18,0,-100,0,
+4,0,-99,0,4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,
+7,0,-94,0,7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,
+54,0,13,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,4,0,-99,0,
+4,0,-98,0,4,0,-97,0,7,0,-96,0,7,0,-95,0,7,0,-94,0,
+7,0,-93,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,55,0,11,0,
+49,0,-104,0,17,0,-101,0,17,0,-100,0,7,0,-89,0,7,0,-88,0,
+7,0,-87,0,7,0,-92,0,7,0,-91,0,7,0,-90,0,7,0,-86,0,
+0,0,21,0,56,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
+13,0,-85,0,13,0,-84,0,13,0,-83,0,13,0,-82,0,4,0,-81,0,
+4,0,-80,0,57,0,9,0,49,0,-104,0,17,0,-101,0,17,0,-100,0,
+7,0,-85,0,7,0,-84,0,7,0,-83,0,7,0,-82,0,4,0,-81,0,
+4,0,-80,0,};
+int sBulletDNAlen= sizeof(sBulletDNAstr);
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btSerializer.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btSerializer.h
new file mode 100644
index 0000000..8553138
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btSerializer.h
@@ -0,0 +1,606 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_SERIALIZER_H
+#define BT_SERIALIZER_H
+
+#include "btScalar.h" // has definitions like SIMD_FORCE_INLINE
+#include "btStackAlloc.h"
+#include "btHashMap.h"
+
+#if !defined( __CELLOS_LV2__) && !defined(__MWERKS__)
+#include <memory.h>
+#endif
+#include <string.h>
+
+
+
+///only the 32bit versions for now
+extern unsigned char sBulletDNAstr[];
+extern int sBulletDNAlen;
+extern unsigned char sBulletDNAstr64[];
+extern int sBulletDNAlen64;
+
+SIMD_FORCE_INLINE	int btStrLen(const char* str) 
+{
+    if (!str) 
+		return(0);
+	int len = 0;
+    
+	while (*str != 0)
+	{
+        str++;
+        len++;
+    }
+
+    return len;
+}
+
+
+class btChunk
+{
+public:
+	int		m_chunkCode;
+	int		m_length;
+	void	*m_oldPtr;
+	int		m_dna_nr;
+	int		m_number;
+};
+
+enum	btSerializationFlags
+{
+	BT_SERIALIZE_NO_BVH = 1,
+	BT_SERIALIZE_NO_TRIANGLEINFOMAP = 2,
+	BT_SERIALIZE_NO_DUPLICATE_ASSERT = 4
+};
+
+class	btSerializer
+{
+
+public:
+
+	virtual ~btSerializer() {}
+
+	virtual	const unsigned char*		getBufferPointer() const = 0;
+
+	virtual	int		getCurrentBufferSize() const = 0;
+
+	virtual	btChunk*	allocate(size_t size, int numElements) = 0;
+
+	virtual	void	finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)= 0;
+
+	virtual	 void*	findPointer(void* oldPtr)  = 0;
+
+	virtual	void*	getUniquePointer(void*oldPtr) = 0;
+
+	virtual	void	startSerialization() = 0;
+	
+	virtual	void	finishSerialization() = 0;
+
+	virtual	const char*	findNameForPointer(const void* ptr) const = 0;
+
+	virtual	void	registerNameForPointer(const void* ptr, const char* name) = 0;
+
+	virtual void	serializeName(const char* ptr) = 0;
+
+	virtual int		getSerializationFlags() const = 0;
+
+	virtual void	setSerializationFlags(int flags) = 0;
+
+
+};
+
+
+
+#define BT_HEADER_LENGTH 12
+#if defined(__sgi) || defined (__sparc) || defined (__sparc__) || defined (__PPC__) || defined (__ppc__) || defined (__BIG_ENDIAN__)
+#	define MAKE_ID(a,b,c,d) ( (int)(a)<<24 | (int)(b)<<16 | (c)<<8 | (d) )
+#else
+#	define MAKE_ID(a,b,c,d) ( (int)(d)<<24 | (int)(c)<<16 | (b)<<8 | (a) )
+#endif
+
+#define BT_COLLISIONOBJECT_CODE MAKE_ID('C','O','B','J')
+#define BT_RIGIDBODY_CODE		MAKE_ID('R','B','D','Y')
+#define BT_CONSTRAINT_CODE		MAKE_ID('C','O','N','S')
+#define BT_BOXSHAPE_CODE		MAKE_ID('B','O','X','S')
+#define BT_QUANTIZED_BVH_CODE	MAKE_ID('Q','B','V','H')
+#define BT_TRIANLGE_INFO_MAP	MAKE_ID('T','M','A','P')
+#define BT_SHAPE_CODE			MAKE_ID('S','H','A','P')
+#define BT_ARRAY_CODE			MAKE_ID('A','R','A','Y')
+#define BT_DNA_CODE				MAKE_ID('D','N','A','1')
+
+
+
+struct	btPointerUid
+{
+	union
+	{
+		void*	m_ptr;
+		int		m_uniqueIds[2];
+	};
+};
+
+
+class btDefaultSerializer	:	public btSerializer
+{
+
+
+	btAlignedObjectArray<char*>			mTypes;
+	btAlignedObjectArray<short*>			mStructs;
+	btAlignedObjectArray<short>			mTlens;
+	btHashMap<btHashInt, int>			mStructReverse;
+	btHashMap<btHashString,int>	mTypeLookup;
+
+	
+	btHashMap<btHashPtr,void*>	m_chunkP;
+	
+	btHashMap<btHashPtr,const char*>	m_nameMap;
+
+	btHashMap<btHashPtr,btPointerUid>	m_uniquePointers;
+	int	m_uniqueIdGenerator;
+
+	int					m_totalSize;
+	unsigned char*		m_buffer;
+	int					m_currentSize;
+	void*				m_dna;
+	int					m_dnaLength;
+
+	int					m_serializationFlags;
+
+
+	btAlignedObjectArray<btChunk*>	m_chunkPtrs;
+	
+protected:
+
+	virtual	void*	findPointer(void* oldPtr) 
+	{
+		void** ptr = m_chunkP.find(oldPtr);
+		if (ptr && *ptr)
+			return *ptr;
+		return 0;
+	}
+
+	
+
+
+
+		void	writeDNA()
+		{
+			btChunk* dnaChunk = allocate(m_dnaLength,1);
+			memcpy(dnaChunk->m_oldPtr,m_dna,m_dnaLength);
+			finalizeChunk(dnaChunk,"DNA1",BT_DNA_CODE, m_dna);
+		}
+
+		int getReverseType(const char *type) const
+		{
+
+			btHashString key(type);
+			const int* valuePtr = mTypeLookup.find(key);
+			if (valuePtr)
+				return *valuePtr;
+			
+			return -1;
+		}
+
+		void initDNA(const char* bdnaOrg,int dnalen)
+		{
+			///was already initialized
+			if (m_dna)
+				return;
+
+			int littleEndian= 1;
+			littleEndian= ((char*)&littleEndian)[0];
+			
+
+			m_dna = btAlignedAlloc(dnalen,16);
+			memcpy(m_dna,bdnaOrg,dnalen);
+			m_dnaLength = dnalen;
+
+			int *intPtr=0;
+			short *shtPtr=0;
+			char *cp = 0;int dataLen =0;long nr=0;
+			intPtr = (int*)m_dna;
+
+			/*
+				SDNA (4 bytes) (magic number)
+				NAME (4 bytes)
+				<nr> (4 bytes) amount of names (int)
+				<string>
+				<string>
+			*/
+
+			if (strncmp((const char*)m_dna, "SDNA", 4)==0)
+			{
+				// skip ++ NAME
+				intPtr++; intPtr++;
+			}
+
+			// Parse names
+			if (!littleEndian)
+				*intPtr = btSwapEndian(*intPtr);
+				
+			dataLen = *intPtr;
+			
+			intPtr++;
+
+			cp = (char*)intPtr;
+			int i;
+			for ( i=0; i<dataLen; i++)
+			{
+				
+				while (*cp)cp++;
+				cp++;
+			}
+			{
+				nr= (long)cp;
+			//	long mask=3;
+				nr= ((nr+3)&~3)-nr;
+				while (nr--)
+				{
+					cp++;
+				}
+			}
+
+			/*
+				TYPE (4 bytes)
+				<nr> amount of types (int)
+				<string>
+				<string>
+			*/
+
+			intPtr = (int*)cp;
+			assert(strncmp(cp, "TYPE", 4)==0); intPtr++;
+
+			if (!littleEndian)
+				*intPtr =  btSwapEndian(*intPtr);
+			
+			dataLen = *intPtr;
+			intPtr++;
+
+			
+			cp = (char*)intPtr;
+			for (i=0; i<dataLen; i++)
+			{
+				mTypes.push_back(cp);
+				while (*cp)cp++;
+				cp++;
+			}
+
+		{
+				nr= (long)cp;
+			//	long mask=3;
+				nr= ((nr+3)&~3)-nr;
+				while (nr--)
+				{
+					cp++;
+				}
+			}
+
+
+			/*
+				TLEN (4 bytes)
+				<len> (short) the lengths of types
+				<len>
+			*/
+
+			// Parse type lens
+			intPtr = (int*)cp;
+			assert(strncmp(cp, "TLEN", 4)==0); intPtr++;
+
+			dataLen = (int)mTypes.size();
+
+			shtPtr = (short*)intPtr;
+			for (i=0; i<dataLen; i++, shtPtr++)
+			{
+				if (!littleEndian)
+					shtPtr[0] = btSwapEndian(shtPtr[0]);
+				mTlens.push_back(shtPtr[0]);
+			}
+
+			if (dataLen & 1) shtPtr++;
+
+			/*
+				STRC (4 bytes)
+				<nr> amount of structs (int)
+				<typenr>
+				<nr_of_elems>
+				<typenr>
+				<namenr>
+				<typenr>
+				<namenr>
+			*/
+
+			intPtr = (int*)shtPtr;
+			cp = (char*)intPtr;
+			assert(strncmp(cp, "STRC", 4)==0); intPtr++;
+
+			if (!littleEndian)
+				*intPtr = btSwapEndian(*intPtr);
+			dataLen = *intPtr ; 
+			intPtr++;
+
+
+			shtPtr = (short*)intPtr;
+			for (i=0; i<dataLen; i++)
+			{
+				mStructs.push_back (shtPtr);
+				
+				if (!littleEndian)
+				{
+					shtPtr[0]= btSwapEndian(shtPtr[0]);
+					shtPtr[1]= btSwapEndian(shtPtr[1]);
+
+					int len = shtPtr[1];
+					shtPtr+= 2;
+
+					for (int a=0; a<len; a++, shtPtr+=2)
+					{
+							shtPtr[0]= btSwapEndian(shtPtr[0]);
+							shtPtr[1]= btSwapEndian(shtPtr[1]);
+					}
+
+				} else
+				{
+					shtPtr+= (2*shtPtr[1])+2;
+				}
+			}
+
+			// build reverse lookups
+			for (i=0; i<(int)mStructs.size(); i++)
+			{
+				short *strc = mStructs.at(i);
+				mStructReverse.insert(strc[0], i);
+				mTypeLookup.insert(btHashString(mTypes[strc[0]]),i);
+			}
+		}
+
+public:	
+	
+
+	
+
+		btDefaultSerializer(int totalSize)
+			:m_totalSize(totalSize),
+			m_currentSize(0),
+			m_dna(0),
+			m_dnaLength(0),
+			m_serializationFlags(0)
+		{
+			m_buffer = (unsigned char*)btAlignedAlloc(totalSize, 16);
+			
+			const bool VOID_IS_8 = ((sizeof(void*)==8));
+
+#ifdef BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+			if (VOID_IS_8)
+			{
+#if _WIN64
+				initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
+#else
+				btAssert(0);
+#endif
+			} else
+			{
+#ifndef _WIN64
+				initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
+#else
+				btAssert(0);
+#endif
+			}
+	
+#else //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+			if (VOID_IS_8)
+			{
+				initDNA((const char*)sBulletDNAstr64,sBulletDNAlen64);
+			} else
+			{
+				initDNA((const char*)sBulletDNAstr,sBulletDNAlen);
+			}
+#endif //BT_INTERNAL_UPDATE_SERIALIZATION_STRUCTURES
+	
+		}
+
+		virtual ~btDefaultSerializer() 
+		{
+			if (m_buffer)
+				btAlignedFree(m_buffer);
+			if (m_dna)
+				btAlignedFree(m_dna);
+		}
+
+		virtual	void	startSerialization()
+		{
+			m_uniqueIdGenerator= 1;
+
+			m_currentSize = BT_HEADER_LENGTH;
+
+#ifdef  BT_USE_DOUBLE_PRECISION
+			memcpy(m_buffer, "BULLETd", 7);
+#else
+			memcpy(m_buffer, "BULLETf", 7);
+#endif //BT_USE_DOUBLE_PRECISION
+	
+			int littleEndian= 1;
+			littleEndian= ((char*)&littleEndian)[0];
+
+			if (sizeof(void*)==8)
+			{
+				m_buffer[7] = '-';
+			} else
+			{
+				m_buffer[7] = '_';
+			}
+
+			if (littleEndian)
+			{
+				m_buffer[8]='v';				
+			} else
+			{
+				m_buffer[8]='V';
+			}
+
+
+			m_buffer[9] = '2';
+			m_buffer[10] = '7';
+			m_buffer[11] = '7';
+
+			
+		}
+
+		virtual	void	finishSerialization()
+		{
+			writeDNA();
+
+
+			mTypes.clear();
+			mStructs.clear();
+			mTlens.clear();
+			mStructReverse.clear();
+			mTypeLookup.clear();
+			m_chunkP.clear();
+			m_nameMap.clear();
+			m_uniquePointers.clear();
+		}
+
+		virtual	void*	getUniquePointer(void*oldPtr)
+		{
+			if (!oldPtr)
+				return 0;
+
+			btPointerUid* uptr = (btPointerUid*)m_uniquePointers.find(oldPtr);
+			if (uptr)
+			{
+				return uptr->m_ptr;
+			}
+			m_uniqueIdGenerator++;
+			
+			btPointerUid uid;
+			uid.m_uniqueIds[0] = m_uniqueIdGenerator;
+			uid.m_uniqueIds[1] = m_uniqueIdGenerator;
+			m_uniquePointers.insert(oldPtr,uid);
+			return uid.m_ptr;
+
+		}
+
+		virtual	const unsigned char*		getBufferPointer() const
+		{
+			return m_buffer;
+		}
+
+		virtual	int					getCurrentBufferSize() const
+		{
+			return	m_currentSize;
+		}
+
+		virtual	void	finalizeChunk(btChunk* chunk, const char* structType, int chunkCode,void* oldPtr)
+		{
+			if (!(m_serializationFlags&BT_SERIALIZE_NO_DUPLICATE_ASSERT))
+			{
+				btAssert(!findPointer(oldPtr));
+			}
+
+			chunk->m_dna_nr = getReverseType(structType);
+			
+			chunk->m_chunkCode = chunkCode;
+			
+			void* uniquePtr = getUniquePointer(oldPtr);
+			
+			m_chunkP.insert(oldPtr,uniquePtr);//chunk->m_oldPtr);
+			chunk->m_oldPtr = uniquePtr;//oldPtr;
+			
+		}
+
+		
+
+		
+
+		virtual	btChunk*	allocate(size_t size, int numElements)
+		{
+
+			unsigned char* ptr = m_buffer+m_currentSize;
+			m_currentSize += int(size)*numElements+sizeof(btChunk);
+			btAssert(m_currentSize<m_totalSize);
+
+			unsigned char* data = ptr + sizeof(btChunk);
+			
+			btChunk* chunk = (btChunk*)ptr;
+			chunk->m_chunkCode = 0;
+			chunk->m_oldPtr = data;
+			chunk->m_length = int(size)*numElements;
+			chunk->m_number = numElements;
+			
+			m_chunkPtrs.push_back(chunk);
+			
+
+			return chunk;
+		}
+
+		virtual	const char*	findNameForPointer(const void* ptr) const
+		{
+			const char*const * namePtr = m_nameMap.find(ptr);
+			if (namePtr && *namePtr)
+				return *namePtr;
+			return 0;
+
+		}
+
+		virtual	void	registerNameForPointer(const void* ptr, const char* name)
+		{
+			m_nameMap.insert(ptr,name);
+		}
+
+		virtual void	serializeName(const char* name)
+		{
+			if (name)
+			{
+				//don't serialize name twice
+				if (findPointer((void*)name))
+					return;
+
+				int len = btStrLen(name);
+				if (len)
+				{
+
+					int newLen = len+1;
+					int padding = ((newLen+3)&~3)-newLen;
+					newLen += padding;
+
+					//serialize name string now
+					btChunk* chunk = allocate(sizeof(char),newLen);
+					char* destinationName = (char*)chunk->m_oldPtr;
+					for (int i=0;i<len;i++)
+					{
+						destinationName[i] = name[i];
+					}
+					destinationName[len] = 0;
+					finalizeChunk(chunk,"char",BT_ARRAY_CODE,(void*)name);
+				}
+			}
+		}
+
+		virtual int		getSerializationFlags() const
+		{
+			return m_serializationFlags;
+		}
+
+		virtual void	setSerializationFlags(int flags)
+		{
+			m_serializationFlags = flags;
+		}
+
+};
+
+
+#endif //BT_SERIALIZER_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btStackAlloc.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btStackAlloc.h
new file mode 100644
index 0000000..397b084
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btStackAlloc.h
@@ -0,0 +1,116 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+StackAlloc extracted from GJK-EPA collision solver by Nathanael Presson
+Nov.2006
+*/
+
+#ifndef BT_STACK_ALLOC
+#define BT_STACK_ALLOC
+
+#include "btScalar.h" //for btAssert
+#include "btAlignedAllocator.h"
+
+///The btBlock class is an internal structure for the btStackAlloc memory allocator.
+struct btBlock
+{
+	btBlock*			previous;
+	unsigned char*		address;
+};
+
+///The StackAlloc class provides some fast stack-based memory allocator (LIFO last-in first-out)
+class btStackAlloc
+{
+public:
+
+	btStackAlloc(unsigned int size)	{ ctor();create(size); }
+	~btStackAlloc()		{ destroy(); }
+	
+	inline void		create(unsigned int size)
+	{
+		destroy();
+		data		=  (unsigned char*) btAlignedAlloc(size,16);
+		totalsize	=	size;
+	}
+	inline void		destroy()
+	{
+		btAssert(usedsize==0);
+		//Raise(L"StackAlloc is still in use");
+
+		if(usedsize==0)
+		{
+			if(!ischild && data)		
+				btAlignedFree(data);
+
+			data				=	0;
+			usedsize			=	0;
+		}
+		
+	}
+
+	int	getAvailableMemory() const
+	{
+		return static_cast<int>(totalsize - usedsize);
+	}
+
+	unsigned char*			allocate(unsigned int size)
+	{
+		const unsigned int	nus(usedsize+size);
+		if(nus<totalsize)
+		{
+			usedsize=nus;
+			return(data+(usedsize-size));
+		}
+		btAssert(0);
+		//&& (L"Not enough memory"));
+		
+		return(0);
+	}
+	SIMD_FORCE_INLINE btBlock*		beginBlock()
+	{
+		btBlock*	pb = (btBlock*)allocate(sizeof(btBlock));
+		pb->previous	=	current;
+		pb->address		=	data+usedsize;
+		current			=	pb;
+		return(pb);
+	}
+	SIMD_FORCE_INLINE void		endBlock(btBlock* block)
+	{
+		btAssert(block==current);
+		//Raise(L"Unmatched blocks");
+		if(block==current)
+		{
+			current		=	block->previous;
+			usedsize	=	(unsigned int)((block->address-data)-sizeof(btBlock));
+		}
+	}
+
+private:
+	void		ctor()
+	{
+		data		=	0;
+		totalsize	=	0;
+		usedsize	=	0;
+		current		=	0;
+		ischild		=	false;
+	}
+	unsigned char*		data;
+	unsigned int		totalsize;
+	unsigned int		usedsize;
+	btBlock*	current;
+	bool		ischild;
+};
+
+#endif //BT_STACK_ALLOC
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btTransform.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btTransform.h
new file mode 100644
index 0000000..187b091
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btTransform.h
@@ -0,0 +1,307 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef btTransform_H
+#define btTransform_H
+
+
+#include "btMatrix3x3.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btTransformData btTransformDoubleData
+#else
+#define btTransformData btTransformFloatData
+#endif
+
+
+
+
+/**@brief The btTransform class supports rigid transforms with only translation and rotation and no scaling/shear.
+ *It can be used in combination with btVector3, btQuaternion and btMatrix3x3 linear algebra classes. */
+class btTransform {
+	
+  ///Storage for the rotation
+	btMatrix3x3 m_basis;
+  ///Storage for the translation
+	btVector3   m_origin;
+
+public:
+	
+  /**@brief No initialization constructor */
+	btTransform() {}
+  /**@brief Constructor from btQuaternion (optional btVector3 )
+   * @param q Rotation from quaternion 
+   * @param c Translation from Vector (default 0,0,0) */
+	explicit SIMD_FORCE_INLINE btTransform(const btQuaternion& q, 
+		const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0))) 
+		: m_basis(q),
+		m_origin(c)
+	{}
+
+  /**@brief Constructor from btMatrix3x3 (optional btVector3)
+   * @param b Rotation from Matrix 
+   * @param c Translation from Vector default (0,0,0)*/
+	explicit SIMD_FORCE_INLINE btTransform(const btMatrix3x3& b, 
+		const btVector3& c = btVector3(btScalar(0), btScalar(0), btScalar(0)))
+		: m_basis(b),
+		m_origin(c)
+	{}
+  /**@brief Copy constructor */
+	SIMD_FORCE_INLINE btTransform (const btTransform& other)
+		: m_basis(other.m_basis),
+		m_origin(other.m_origin)
+	{
+	}
+  /**@brief Assignment Operator */
+	SIMD_FORCE_INLINE btTransform& operator=(const btTransform& other)
+	{
+		m_basis = other.m_basis;
+		m_origin = other.m_origin;
+		return *this;
+	}
+
+
+  /**@brief Set the current transform as the value of the product of two transforms
+   * @param t1 Transform 1
+   * @param t2 Transform 2
+   * This = Transform1 * Transform2 */
+		SIMD_FORCE_INLINE void mult(const btTransform& t1, const btTransform& t2) {
+			m_basis = t1.m_basis * t2.m_basis;
+			m_origin = t1(t2.m_origin);
+		}
+
+/*		void multInverseLeft(const btTransform& t1, const btTransform& t2) {
+			btVector3 v = t2.m_origin - t1.m_origin;
+			m_basis = btMultTransposeLeft(t1.m_basis, t2.m_basis);
+			m_origin = v * t1.m_basis;
+		}
+		*/
+
+/**@brief Return the transform of the vector */
+	SIMD_FORCE_INLINE btVector3 operator()(const btVector3& x) const
+	{
+		return btVector3(m_basis[0].dot(x) + m_origin.x(), 
+			m_basis[1].dot(x) + m_origin.y(), 
+			m_basis[2].dot(x) + m_origin.z());
+	}
+
+  /**@brief Return the transform of the vector */
+	SIMD_FORCE_INLINE btVector3 operator*(const btVector3& x) const
+	{
+		return (*this)(x);
+	}
+
+  /**@brief Return the transform of the btQuaternion */
+	SIMD_FORCE_INLINE btQuaternion operator*(const btQuaternion& q) const
+	{
+		return getRotation() * q;
+	}
+
+  /**@brief Return the basis matrix for the rotation */
+	SIMD_FORCE_INLINE btMatrix3x3&       getBasis()          { return m_basis; }
+  /**@brief Return the basis matrix for the rotation */
+	SIMD_FORCE_INLINE const btMatrix3x3& getBasis()    const { return m_basis; }
+
+  /**@brief Return the origin vector translation */
+	SIMD_FORCE_INLINE btVector3&         getOrigin()         { return m_origin; }
+  /**@brief Return the origin vector translation */
+	SIMD_FORCE_INLINE const btVector3&   getOrigin()   const { return m_origin; }
+
+  /**@brief Return a quaternion representing the rotation */
+	btQuaternion getRotation() const { 
+		btQuaternion q;
+		m_basis.getRotation(q);
+		return q;
+	}
+	
+	
+  /**@brief Set from an array 
+   * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+	void setFromOpenGLMatrix(const btScalar *m)
+	{
+		m_basis.setFromOpenGLSubMatrix(m);
+		m_origin.setValue(m[12],m[13],m[14]);
+	}
+
+  /**@brief Fill an array representation
+   * @param m A pointer to a 15 element array (12 rotation(row major padded on the right by 1), and 3 translation */
+	void getOpenGLMatrix(btScalar *m) const 
+	{
+		m_basis.getOpenGLSubMatrix(m);
+		m[12] = m_origin.x();
+		m[13] = m_origin.y();
+		m[14] = m_origin.z();
+		m[15] = btScalar(1.0);
+	}
+
+  /**@brief Set the translational element
+   * @param origin The vector to set the translation to */
+	SIMD_FORCE_INLINE void setOrigin(const btVector3& origin) 
+	{ 
+		m_origin = origin;
+	}
+
+	SIMD_FORCE_INLINE btVector3 invXform(const btVector3& inVec) const;
+
+
+  /**@brief Set the rotational element by btMatrix3x3 */
+	SIMD_FORCE_INLINE void setBasis(const btMatrix3x3& basis)
+	{ 
+		m_basis = basis;
+	}
+
+  /**@brief Set the rotational element by btQuaternion */
+	SIMD_FORCE_INLINE void setRotation(const btQuaternion& q)
+	{
+		m_basis.setRotation(q);
+	}
+
+
+  /**@brief Set this transformation to the identity */
+	void setIdentity()
+	{
+		m_basis.setIdentity();
+		m_origin.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+	}
+
+  /**@brief Multiply this Transform by another(this = this * another) 
+   * @param t The other transform */
+	btTransform& operator*=(const btTransform& t) 
+	{
+		m_origin += m_basis * t.m_origin;
+		m_basis *= t.m_basis;
+		return *this;
+	}
+
+  /**@brief Return the inverse of this transform */
+	btTransform inverse() const
+	{ 
+		btMatrix3x3 inv = m_basis.transpose();
+		return btTransform(inv, inv * -m_origin);
+	}
+
+  /**@brief Return the inverse of this transform times the other transform
+   * @param t The other transform 
+   * return this.inverse() * the other */
+	btTransform inverseTimes(const btTransform& t) const;  
+
+  /**@brief Return the product of this transform and the other */
+	btTransform operator*(const btTransform& t) const;
+
+  /**@brief Return an identity transform */
+	static const btTransform&	getIdentity()
+	{
+		static const btTransform identityTransform(btMatrix3x3::getIdentity());
+		return identityTransform;
+	}
+
+	void	serialize(struct	btTransformData& dataOut) const;
+
+	void	serializeFloat(struct	btTransformFloatData& dataOut) const;
+
+	void	deSerialize(const struct	btTransformData& dataIn);
+
+	void	deSerializeDouble(const struct	btTransformDoubleData& dataIn);
+
+	void	deSerializeFloat(const struct	btTransformFloatData& dataIn);
+
+};
+
+
+SIMD_FORCE_INLINE btVector3
+btTransform::invXform(const btVector3& inVec) const
+{
+	btVector3 v = inVec - m_origin;
+	return (m_basis.transpose() * v);
+}
+
+SIMD_FORCE_INLINE btTransform 
+btTransform::inverseTimes(const btTransform& t) const  
+{
+	btVector3 v = t.getOrigin() - m_origin;
+		return btTransform(m_basis.transposeTimes(t.m_basis),
+			v * m_basis);
+}
+
+SIMD_FORCE_INLINE btTransform 
+btTransform::operator*(const btTransform& t) const
+{
+	return btTransform(m_basis * t.m_basis, 
+		(*this)(t.m_origin));
+}
+
+/**@brief Test if two transforms have all elements equal */
+SIMD_FORCE_INLINE bool operator==(const btTransform& t1, const btTransform& t2)
+{
+   return ( t1.getBasis()  == t2.getBasis() &&
+            t1.getOrigin() == t2.getOrigin() );
+}
+
+
+///for serialization
+struct	btTransformFloatData
+{
+	btMatrix3x3FloatData	m_basis;
+	btVector3FloatData	m_origin;
+};
+
+struct	btTransformDoubleData
+{
+	btMatrix3x3DoubleData	m_basis;
+	btVector3DoubleData	m_origin;
+};
+
+
+
+SIMD_FORCE_INLINE	void	btTransform::serialize(btTransformData& dataOut) const
+{
+	m_basis.serialize(dataOut.m_basis);
+	m_origin.serialize(dataOut.m_origin);
+}
+
+SIMD_FORCE_INLINE	void	btTransform::serializeFloat(btTransformFloatData& dataOut) const
+{
+	m_basis.serializeFloat(dataOut.m_basis);
+	m_origin.serializeFloat(dataOut.m_origin);
+}
+
+
+SIMD_FORCE_INLINE	void	btTransform::deSerialize(const btTransformData& dataIn)
+{
+	m_basis.deSerialize(dataIn.m_basis);
+	m_origin.deSerialize(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE	void	btTransform::deSerializeFloat(const btTransformFloatData& dataIn)
+{
+	m_basis.deSerializeFloat(dataIn.m_basis);
+	m_origin.deSerializeFloat(dataIn.m_origin);
+}
+
+SIMD_FORCE_INLINE	void	btTransform::deSerializeDouble(const btTransformDoubleData& dataIn)
+{
+	m_basis.deSerializeDouble(dataIn.m_basis);
+	m_origin.deSerializeDouble(dataIn.m_origin);
+}
+
+
+#endif
+
+
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btTransformUtil.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btTransformUtil.h
new file mode 100644
index 0000000..626110c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btTransformUtil.h
@@ -0,0 +1,228 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef SIMD_TRANSFORM_UTIL_H
+#define SIMD_TRANSFORM_UTIL_H
+
+#include "btTransform.h"
+#define ANGULAR_MOTION_THRESHOLD btScalar(0.5)*SIMD_HALF_PI
+
+
+
+
+SIMD_FORCE_INLINE btVector3 btAabbSupport(const btVector3& halfExtents,const btVector3& supportDir)
+{
+	return btVector3(supportDir.x() < btScalar(0.0) ? -halfExtents.x() : halfExtents.x(),
+      supportDir.y() < btScalar(0.0) ? -halfExtents.y() : halfExtents.y(),
+      supportDir.z() < btScalar(0.0) ? -halfExtents.z() : halfExtents.z()); 
+}
+
+
+
+
+
+
+/// Utils related to temporal transforms
+class btTransformUtil
+{
+
+public:
+
+	static void integrateTransform(const btTransform& curTrans,const btVector3& linvel,const btVector3& angvel,btScalar timeStep,btTransform& predictedTransform)
+	{
+		predictedTransform.setOrigin(curTrans.getOrigin() + linvel * timeStep);
+//	#define QUATERNION_DERIVATIVE
+	#ifdef QUATERNION_DERIVATIVE
+		btQuaternion predictedOrn = curTrans.getRotation();
+		predictedOrn += (angvel * predictedOrn) * (timeStep * btScalar(0.5));
+		predictedOrn.normalize();
+	#else
+		//Exponential map
+		//google for "Practical Parameterization of Rotations Using the Exponential Map", F. Sebastian Grassia
+
+		btVector3 axis;
+		btScalar	fAngle = angvel.length(); 
+		//limit the angular motion
+		if (fAngle*timeStep > ANGULAR_MOTION_THRESHOLD)
+		{
+			fAngle = ANGULAR_MOTION_THRESHOLD / timeStep;
+		}
+
+		if ( fAngle < btScalar(0.001) )
+		{
+			// use Taylor's expansions of sync function
+			axis   = angvel*( btScalar(0.5)*timeStep-(timeStep*timeStep*timeStep)*(btScalar(0.020833333333))*fAngle*fAngle );
+		}
+		else
+		{
+			// sync(fAngle) = sin(c*fAngle)/t
+			axis   = angvel*( btSin(btScalar(0.5)*fAngle*timeStep)/fAngle );
+		}
+		btQuaternion dorn (axis.x(),axis.y(),axis.z(),btCos( fAngle*timeStep*btScalar(0.5) ));
+		btQuaternion orn0 = curTrans.getRotation();
+
+		btQuaternion predictedOrn = dorn * orn0;
+		predictedOrn.normalize();
+	#endif
+		predictedTransform.setRotation(predictedOrn);
+	}
+
+	static void	calculateVelocityQuaternion(const btVector3& pos0,const btVector3& pos1,const btQuaternion& orn0,const btQuaternion& orn1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+	{
+		linVel = (pos1 - pos0) / timeStep;
+		btVector3 axis;
+		btScalar  angle;
+		if (orn0 != orn1)
+		{
+			calculateDiffAxisAngleQuaternion(orn0,orn1,axis,angle);
+			angVel = axis * angle / timeStep;
+		} else
+		{
+			angVel.setValue(0,0,0);
+		}
+	}
+
+	static void calculateDiffAxisAngleQuaternion(const btQuaternion& orn0,const btQuaternion& orn1a,btVector3& axis,btScalar& angle)
+	{
+		btQuaternion orn1 = orn0.nearest(orn1a);
+		btQuaternion dorn = orn1 * orn0.inverse();
+		angle = dorn.getAngle();
+		axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+		axis[3] = btScalar(0.);
+		//check for axis length
+		btScalar len = axis.length2();
+		if (len < SIMD_EPSILON*SIMD_EPSILON)
+			axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+		else
+			axis /= btSqrt(len);
+	}
+
+	static void	calculateVelocity(const btTransform& transform0,const btTransform& transform1,btScalar timeStep,btVector3& linVel,btVector3& angVel)
+	{
+		linVel = (transform1.getOrigin() - transform0.getOrigin()) / timeStep;
+		btVector3 axis;
+		btScalar  angle;
+		calculateDiffAxisAngle(transform0,transform1,axis,angle);
+		angVel = axis * angle / timeStep;
+	}
+
+	static void calculateDiffAxisAngle(const btTransform& transform0,const btTransform& transform1,btVector3& axis,btScalar& angle)
+	{
+		btMatrix3x3 dmat = transform1.getBasis() * transform0.getBasis().inverse();
+		btQuaternion dorn;
+		dmat.getRotation(dorn);
+
+		///floating point inaccuracy can lead to w component > 1..., which breaks 
+		dorn.normalize();
+		
+		angle = dorn.getAngle();
+		axis = btVector3(dorn.x(),dorn.y(),dorn.z());
+		axis[3] = btScalar(0.);
+		//check for axis length
+		btScalar len = axis.length2();
+		if (len < SIMD_EPSILON*SIMD_EPSILON)
+			axis = btVector3(btScalar(1.),btScalar(0.),btScalar(0.));
+		else
+			axis /= btSqrt(len);
+	}
+
+};
+
+
+///The btConvexSeparatingDistanceUtil can help speed up convex collision detection 
+///by conservatively updating a cached separating distance/vector instead of re-calculating the closest distance
+class	btConvexSeparatingDistanceUtil
+{
+	btQuaternion	m_ornA;
+	btQuaternion	m_ornB;
+	btVector3	m_posA;
+	btVector3	m_posB;
+	
+	btVector3	m_separatingNormal;
+
+	btScalar	m_boundingRadiusA;
+	btScalar	m_boundingRadiusB;
+	btScalar	m_separatingDistance;
+
+public:
+
+	btConvexSeparatingDistanceUtil(btScalar	boundingRadiusA,btScalar	boundingRadiusB)
+		:m_boundingRadiusA(boundingRadiusA),
+		m_boundingRadiusB(boundingRadiusB),
+		m_separatingDistance(0.f)
+	{
+	}
+
+	btScalar	getConservativeSeparatingDistance()
+	{
+		return m_separatingDistance;
+	}
+
+	void	updateSeparatingDistance(const btTransform& transA,const btTransform& transB)
+	{
+		const btVector3& toPosA = transA.getOrigin();
+		const btVector3& toPosB = transB.getOrigin();
+		btQuaternion toOrnA = transA.getRotation();
+		btQuaternion toOrnB = transB.getRotation();
+
+		if (m_separatingDistance>0.f)
+		{
+			
+
+			btVector3 linVelA,angVelA,linVelB,angVelB;
+			btTransformUtil::calculateVelocityQuaternion(m_posA,toPosA,m_ornA,toOrnA,btScalar(1.),linVelA,angVelA);
+			btTransformUtil::calculateVelocityQuaternion(m_posB,toPosB,m_ornB,toOrnB,btScalar(1.),linVelB,angVelB);
+			btScalar maxAngularProjectedVelocity = angVelA.length() * m_boundingRadiusA + angVelB.length() * m_boundingRadiusB;
+			btVector3 relLinVel = (linVelB-linVelA);
+			btScalar relLinVelocLength = relLinVel.dot(m_separatingNormal);
+			if (relLinVelocLength<0.f)
+			{
+				relLinVelocLength = 0.f;
+			}
+	
+			btScalar	projectedMotion = maxAngularProjectedVelocity +relLinVelocLength;
+			m_separatingDistance -= projectedMotion;
+		}
+	
+		m_posA = toPosA;
+		m_posB = toPosB;
+		m_ornA = toOrnA;
+		m_ornB = toOrnB;
+	}
+
+	void	initSeparatingDistance(const btVector3& separatingVector,btScalar separatingDistance,const btTransform& transA,const btTransform& transB)
+	{
+		m_separatingDistance = separatingDistance;
+
+		if (m_separatingDistance>0.f)
+		{
+			m_separatingNormal = separatingVector;
+			
+			const btVector3& toPosA = transA.getOrigin();
+			const btVector3& toPosB = transB.getOrigin();
+			btQuaternion toOrnA = transA.getRotation();
+			btQuaternion toOrnB = transB.getRotation();
+			m_posA = toPosA;
+			m_posB = toPosB;
+			m_ornA = toOrnA;
+			m_ornB = toOrnB;
+		}
+	}
+
+};
+
+
+#endif //SIMD_TRANSFORM_UTIL_H
+
diff --git a/SRC/ChronoEngine/collision/bullet/LinearMath/btVector3.h b/SRC/ChronoEngine/collision/bullet/LinearMath/btVector3.h
new file mode 100644
index 0000000..068e87c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/LinearMath/btVector3.h
@@ -0,0 +1,766 @@
+/*
+Copyright (c) 2003-2006 Gino van den Bergen / Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+
+#ifndef SIMD__VECTOR3_H
+#define SIMD__VECTOR3_H
+
+
+#include "btScalar.h"
+#include "btMinMax.h"
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btVector3Data btVector3DoubleData
+#define btVector3DataName "btVector3DoubleData"
+#else
+#define btVector3Data btVector3FloatData
+#define btVector3DataName "btVector3FloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+
+
+/**@brief btVector3 can be used to represent 3D points and vectors.
+ * It has an un-used w component to suit 16-byte alignment when btVector3 is stored in containers. This extra component can be used by derived classes (Quaternion?) or by user
+ * Ideally, this class should be replaced by a platform optimized SIMD version that keeps the data in registers
+ */
+ATTRIBUTE_ALIGNED16(class) btVector3
+{
+public:
+
+#if defined (__SPU__) && defined (__CELLOS_LV2__)
+		btScalar	m_floats[4];
+public:
+	SIMD_FORCE_INLINE const vec_float4&	get128() const
+	{
+		return *((const vec_float4*)&m_floats[0]);
+	}
+public:
+#else //__CELLOS_LV2__ __SPU__
+#ifdef BT_USE_SSE // _WIN32
+	union {
+		__m128 mVec128;
+		btScalar	m_floats[4];
+	};
+	SIMD_FORCE_INLINE	__m128	get128() const
+	{
+		return mVec128;
+	}
+	SIMD_FORCE_INLINE	void	set128(__m128 v128)
+	{
+		mVec128 = v128;
+	}
+#else
+	btScalar	m_floats[4];
+#endif
+#endif //__CELLOS_LV2__ __SPU__
+
+	public:
+
+  /**@brief No initialization constructor */
+	SIMD_FORCE_INLINE btVector3() {}
+
+ 
+	
+  /**@brief Constructor from scalars 
+   * @param x X value
+   * @param y Y value 
+   * @param z Z value 
+   */
+	SIMD_FORCE_INLINE btVector3(const btScalar& x, const btScalar& y, const btScalar& z)
+	{
+		m_floats[0] = x;
+		m_floats[1] = y;
+		m_floats[2] = z;
+		m_floats[3] = btScalar(0.);
+	}
+
+	
+/**@brief Add a vector to this one 
+ * @param The vector to add to this one */
+	SIMD_FORCE_INLINE btVector3& operator+=(const btVector3& v)
+	{
+
+		m_floats[0] += v.m_floats[0]; m_floats[1] += v.m_floats[1];m_floats[2] += v.m_floats[2];
+		return *this;
+	}
+
+
+  /**@brief Subtract a vector from this one
+   * @param The vector to subtract */
+	SIMD_FORCE_INLINE btVector3& operator-=(const btVector3& v) 
+	{
+		m_floats[0] -= v.m_floats[0]; m_floats[1] -= v.m_floats[1];m_floats[2] -= v.m_floats[2];
+		return *this;
+	}
+  /**@brief Scale the vector
+   * @param s Scale factor */
+	SIMD_FORCE_INLINE btVector3& operator*=(const btScalar& s)
+	{
+		m_floats[0] *= s; m_floats[1] *= s;m_floats[2] *= s;
+		return *this;
+	}
+
+  /**@brief Inversely scale the vector 
+   * @param s Scale factor to divide by */
+	SIMD_FORCE_INLINE btVector3& operator/=(const btScalar& s) 
+	{
+		btFullAssert(s != btScalar(0.0));
+		return *this *= btScalar(1.0) / s;
+	}
+
+  /**@brief Return the dot product
+   * @param v The other vector in the dot product */
+	SIMD_FORCE_INLINE btScalar dot(const btVector3& v) const
+	{
+		return m_floats[0] * v.m_floats[0] + m_floats[1] * v.m_floats[1] +m_floats[2] * v.m_floats[2];
+	}
+
+  /**@brief Return the length of the vector squared */
+	SIMD_FORCE_INLINE btScalar length2() const
+	{
+		return dot(*this);
+	}
+
+  /**@brief Return the length of the vector */
+	SIMD_FORCE_INLINE btScalar length() const
+	{
+		return btSqrt(length2());
+	}
+
+  /**@brief Return the distance squared between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+	SIMD_FORCE_INLINE btScalar distance2(const btVector3& v) const;
+
+  /**@brief Return the distance between the ends of this and another vector
+   * This is symantically treating the vector like a point */
+	SIMD_FORCE_INLINE btScalar distance(const btVector3& v) const;
+
+	SIMD_FORCE_INLINE btVector3& safeNormalize() 
+	{
+		btVector3 absVec = this->absolute();
+		int maxIndex = absVec.maxAxis();
+		if (absVec[maxIndex]>0)
+		{
+			*this /= absVec[maxIndex];
+			return *this /= length();
+		}
+		setValue(1,0,0);
+		return *this;
+	}
+
+  /**@brief Normalize this vector 
+   * x^2 + y^2 + z^2 = 1 */
+	SIMD_FORCE_INLINE btVector3& normalize() 
+	{
+		return *this /= length();
+	}
+
+  /**@brief Return a normalized version of this vector */
+	SIMD_FORCE_INLINE btVector3 normalized() const;
+
+  /**@brief Return a rotated version of this vector
+   * @param wAxis The axis to rotate about 
+   * @param angle The angle to rotate by */
+	SIMD_FORCE_INLINE btVector3 rotate( const btVector3& wAxis, const btScalar angle ) const;
+
+  /**@brief Return the angle between this and another vector
+   * @param v The other vector */
+	SIMD_FORCE_INLINE btScalar angle(const btVector3& v) const 
+	{
+		btScalar s = btSqrt(length2() * v.length2());
+		btFullAssert(s != btScalar(0.0));
+		return btAcos(dot(v) / s);
+	}
+  /**@brief Return a vector will the absolute values of each element */
+	SIMD_FORCE_INLINE btVector3 absolute() const 
+	{
+		return btVector3(
+			btFabs(m_floats[0]), 
+			btFabs(m_floats[1]), 
+			btFabs(m_floats[2]));
+	}
+  /**@brief Return the cross product between this and another vector 
+   * @param v The other vector */
+	SIMD_FORCE_INLINE btVector3 cross(const btVector3& v) const
+	{
+		return btVector3(
+			m_floats[1] * v.m_floats[2] -m_floats[2] * v.m_floats[1],
+			m_floats[2] * v.m_floats[0] - m_floats[0] * v.m_floats[2],
+			m_floats[0] * v.m_floats[1] - m_floats[1] * v.m_floats[0]);
+	}
+
+	SIMD_FORCE_INLINE btScalar triple(const btVector3& v1, const btVector3& v2) const
+	{
+		return m_floats[0] * (v1.m_floats[1] * v2.m_floats[2] - v1.m_floats[2] * v2.m_floats[1]) + 
+			m_floats[1] * (v1.m_floats[2] * v2.m_floats[0] - v1.m_floats[0] * v2.m_floats[2]) + 
+			m_floats[2] * (v1.m_floats[0] * v2.m_floats[1] - v1.m_floats[1] * v2.m_floats[0]);
+	}
+
+  /**@brief Return the axis with the smallest value 
+   * Note return values are 0,1,2 for x, y, or z */
+	SIMD_FORCE_INLINE int minAxis() const
+	{
+		return m_floats[0] < m_floats[1] ? (m_floats[0] <m_floats[2] ? 0 : 2) : (m_floats[1] <m_floats[2] ? 1 : 2);
+	}
+
+  /**@brief Return the axis with the largest value 
+   * Note return values are 0,1,2 for x, y, or z */
+	SIMD_FORCE_INLINE int maxAxis() const 
+	{
+		return m_floats[0] < m_floats[1] ? (m_floats[1] <m_floats[2] ? 2 : 1) : (m_floats[0] <m_floats[2] ? 2 : 0);
+	}
+
+	SIMD_FORCE_INLINE int furthestAxis() const
+	{
+		return absolute().minAxis();
+	}
+
+	SIMD_FORCE_INLINE int closestAxis() const 
+	{
+		return absolute().maxAxis();
+	}
+
+	SIMD_FORCE_INLINE void setInterpolate3(const btVector3& v0, const btVector3& v1, btScalar rt)
+	{
+		btScalar s = btScalar(1.0) - rt;
+		m_floats[0] = s * v0.m_floats[0] + rt * v1.m_floats[0];
+		m_floats[1] = s * v0.m_floats[1] + rt * v1.m_floats[1];
+		m_floats[2] = s * v0.m_floats[2] + rt * v1.m_floats[2];
+		//don't do the unused w component
+		//		m_co[3] = s * v0[3] + rt * v1[3];
+	}
+
+  /**@brief Return the linear interpolation between this and another vector 
+   * @param v The other vector 
+   * @param t The ration of this to v (t = 0 => return this, t=1 => return other) */
+	SIMD_FORCE_INLINE btVector3 lerp(const btVector3& v, const btScalar& t) const 
+	{
+		return btVector3(m_floats[0] + (v.m_floats[0] - m_floats[0]) * t,
+			m_floats[1] + (v.m_floats[1] - m_floats[1]) * t,
+			m_floats[2] + (v.m_floats[2] -m_floats[2]) * t);
+	}
+
+  /**@brief Elementwise multiply this vector by the other 
+   * @param v The other vector */
+	SIMD_FORCE_INLINE btVector3& operator*=(const btVector3& v)
+	{
+		m_floats[0] *= v.m_floats[0]; m_floats[1] *= v.m_floats[1];m_floats[2] *= v.m_floats[2];
+		return *this;
+	}
+
+	 /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& getX() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& getY() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& getZ() const { return m_floats[2]; }
+  /**@brief Set the x value */
+		SIMD_FORCE_INLINE void	setX(btScalar x) { m_floats[0] = x;};
+  /**@brief Set the y value */
+		SIMD_FORCE_INLINE void	setY(btScalar y) { m_floats[1] = y;};
+  /**@brief Set the z value */
+		SIMD_FORCE_INLINE void	setZ(btScalar z) {m_floats[2] = z;};
+  /**@brief Set the w value */
+		SIMD_FORCE_INLINE void	setW(btScalar w) { m_floats[3] = w;};
+  /**@brief Return the x value */
+		SIMD_FORCE_INLINE const btScalar& x() const { return m_floats[0]; }
+  /**@brief Return the y value */
+		SIMD_FORCE_INLINE const btScalar& y() const { return m_floats[1]; }
+  /**@brief Return the z value */
+		SIMD_FORCE_INLINE const btScalar& z() const { return m_floats[2]; }
+  /**@brief Return the w value */
+		SIMD_FORCE_INLINE const btScalar& w() const { return m_floats[3]; }
+
+	//SIMD_FORCE_INLINE btScalar&       operator[](int i)       { return (&m_floats[0])[i];	}      
+	//SIMD_FORCE_INLINE const btScalar& operator[](int i) const { return (&m_floats[0])[i]; }
+	///operator btScalar*() replaces operator[], using implicit conversion. We added operator != and operator == to avoid pointer comparisons.
+	SIMD_FORCE_INLINE	operator       btScalar *()       { return &m_floats[0]; }
+	SIMD_FORCE_INLINE	operator const btScalar *() const { return &m_floats[0]; }
+
+	SIMD_FORCE_INLINE	bool	operator==(const btVector3& other) const
+	{
+		return ((m_floats[3]==other.m_floats[3]) && (m_floats[2]==other.m_floats[2]) && (m_floats[1]==other.m_floats[1]) && (m_floats[0]==other.m_floats[0]));
+	}
+
+	SIMD_FORCE_INLINE	bool	operator!=(const btVector3& other) const
+	{
+		return !(*this == other);
+	}
+
+	 /**@brief Set each element to the max of the current values and the values of another btVector3
+   * @param other The other btVector3 to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMax(const btVector3& other)
+		{
+			btSetMax(m_floats[0], other.m_floats[0]);
+			btSetMax(m_floats[1], other.m_floats[1]);
+			btSetMax(m_floats[2], other.m_floats[2]);
+			btSetMax(m_floats[3], other.w());
+		}
+  /**@brief Set each element to the min of the current values and the values of another btVector3
+   * @param other The other btVector3 to compare with 
+   */
+		SIMD_FORCE_INLINE void	setMin(const btVector3& other)
+		{
+			btSetMin(m_floats[0], other.m_floats[0]);
+			btSetMin(m_floats[1], other.m_floats[1]);
+			btSetMin(m_floats[2], other.m_floats[2]);
+			btSetMin(m_floats[3], other.w());
+		}
+
+		SIMD_FORCE_INLINE void 	setValue(const btScalar& x, const btScalar& y, const btScalar& z)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3] = btScalar(0.);
+		}
+
+		void	getSkewSymmetricMatrix(btVector3* v0,btVector3* v1,btVector3* v2) const
+		{
+			v0->setValue(0.		,-z()		,y());
+			v1->setValue(z()	,0.			,-x());
+			v2->setValue(-y()	,x()	,0.);
+		}
+
+		void	setZero()
+		{
+			setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+		}
+
+		SIMD_FORCE_INLINE bool isZero() const 
+		{
+			return m_floats[0] == btScalar(0) && m_floats[1] == btScalar(0) && m_floats[2] == btScalar(0);
+		}
+
+		SIMD_FORCE_INLINE bool fuzzyZero() const 
+		{
+			return length2() < SIMD_EPSILON;
+		}
+
+		SIMD_FORCE_INLINE	void	serialize(struct	btVector3Data& dataOut) const;
+
+		SIMD_FORCE_INLINE	void	deSerialize(const struct	btVector3Data& dataIn);
+
+		SIMD_FORCE_INLINE	void	serializeFloat(struct	btVector3FloatData& dataOut) const;
+
+		SIMD_FORCE_INLINE	void	deSerializeFloat(const struct	btVector3FloatData& dataIn);
+
+		SIMD_FORCE_INLINE	void	serializeDouble(struct	btVector3DoubleData& dataOut) const;
+
+		SIMD_FORCE_INLINE	void	deSerializeDouble(const struct	btVector3DoubleData& dataIn);
+
+};
+
+/**@brief Return the sum of two vectors (Point symantics)*/
+SIMD_FORCE_INLINE btVector3 
+operator+(const btVector3& v1, const btVector3& v2) 
+{
+	return btVector3(v1.m_floats[0] + v2.m_floats[0], v1.m_floats[1] + v2.m_floats[1], v1.m_floats[2] + v2.m_floats[2]);
+}
+
+/**@brief Return the elementwise product of two vectors */
+SIMD_FORCE_INLINE btVector3 
+operator*(const btVector3& v1, const btVector3& v2) 
+{
+	return btVector3(v1.m_floats[0] * v2.m_floats[0], v1.m_floats[1] * v2.m_floats[1], v1.m_floats[2] * v2.m_floats[2]);
+}
+
+/**@brief Return the difference between two vectors */
+SIMD_FORCE_INLINE btVector3 
+operator-(const btVector3& v1, const btVector3& v2)
+{
+	return btVector3(v1.m_floats[0] - v2.m_floats[0], v1.m_floats[1] - v2.m_floats[1], v1.m_floats[2] - v2.m_floats[2]);
+}
+/**@brief Return the negative of the vector */
+SIMD_FORCE_INLINE btVector3 
+operator-(const btVector3& v)
+{
+	return btVector3(-v.m_floats[0], -v.m_floats[1], -v.m_floats[2]);
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3 
+operator*(const btVector3& v, const btScalar& s)
+{
+	return btVector3(v.m_floats[0] * s, v.m_floats[1] * s, v.m_floats[2] * s);
+}
+
+/**@brief Return the vector scaled by s */
+SIMD_FORCE_INLINE btVector3 
+operator*(const btScalar& s, const btVector3& v)
+{ 
+	return v * s; 
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v, const btScalar& s)
+{
+	btFullAssert(s != btScalar(0.0));
+	return v * (btScalar(1.0) / s);
+}
+
+/**@brief Return the vector inversely scaled by s */
+SIMD_FORCE_INLINE btVector3
+operator/(const btVector3& v1, const btVector3& v2)
+{
+	return btVector3(v1.m_floats[0] / v2.m_floats[0],v1.m_floats[1] / v2.m_floats[1],v1.m_floats[2] / v2.m_floats[2]);
+}
+
+/**@brief Return the dot product between two vectors */
+SIMD_FORCE_INLINE btScalar 
+btDot(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.dot(v2); 
+}
+
+
+/**@brief Return the distance squared between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance2(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.distance2(v2); 
+}
+
+
+/**@brief Return the distance between two vectors */
+SIMD_FORCE_INLINE btScalar
+btDistance(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.distance(v2); 
+}
+
+/**@brief Return the angle between two vectors */
+SIMD_FORCE_INLINE btScalar
+btAngle(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.angle(v2); 
+}
+
+/**@brief Return the cross product of two vectors */
+SIMD_FORCE_INLINE btVector3 
+btCross(const btVector3& v1, const btVector3& v2) 
+{ 
+	return v1.cross(v2); 
+}
+
+SIMD_FORCE_INLINE btScalar
+btTriple(const btVector3& v1, const btVector3& v2, const btVector3& v3)
+{
+	return v1.triple(v2, v3);
+}
+
+/**@brief Return the linear interpolation between two vectors
+ * @param v1 One vector 
+ * @param v2 The other vector 
+ * @param t The ration of this to v (t = 0 => return v1, t=1 => return v2) */
+SIMD_FORCE_INLINE btVector3 
+lerp(const btVector3& v1, const btVector3& v2, const btScalar& t)
+{
+	return v1.lerp(v2, t);
+}
+
+
+
+SIMD_FORCE_INLINE btScalar btVector3::distance2(const btVector3& v) const
+{
+	return (v - *this).length2();
+}
+
+SIMD_FORCE_INLINE btScalar btVector3::distance(const btVector3& v) const
+{
+	return (v - *this).length();
+}
+
+SIMD_FORCE_INLINE btVector3 btVector3::normalized() const
+{
+	return *this / length();
+} 
+
+SIMD_FORCE_INLINE btVector3 btVector3::rotate( const btVector3& wAxis, const btScalar angle ) const
+{
+	// wAxis must be a unit lenght vector
+
+	btVector3 o = wAxis * wAxis.dot( *this );
+	btVector3 x = *this - o;
+	btVector3 y;
+
+	y = wAxis.cross( *this );
+
+	return ( o + x * btCos( angle ) + y * btSin( angle ) );
+}
+
+class btVector4 : public btVector3
+{
+public:
+
+	SIMD_FORCE_INLINE btVector4() {}
+
+
+	SIMD_FORCE_INLINE btVector4(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w) 
+		: btVector3(x,y,z)
+	{
+		m_floats[3] = w;
+	}
+
+
+	SIMD_FORCE_INLINE btVector4 absolute4() const 
+	{
+		return btVector4(
+			btFabs(m_floats[0]), 
+			btFabs(m_floats[1]), 
+			btFabs(m_floats[2]),
+			btFabs(m_floats[3]));
+	}
+
+
+
+	btScalar	getW() const { return m_floats[3];}
+
+
+		SIMD_FORCE_INLINE int maxAxis4() const
+	{
+		int maxIndex = -1;
+		btScalar maxVal = btScalar(-BT_LARGE_FLOAT);
+		if (m_floats[0] > maxVal)
+		{
+			maxIndex = 0;
+			maxVal = m_floats[0];
+		}
+		if (m_floats[1] > maxVal)
+		{
+			maxIndex = 1;
+			maxVal = m_floats[1];
+		}
+		if (m_floats[2] > maxVal)
+		{
+			maxIndex = 2;
+			maxVal =m_floats[2];
+		}
+		if (m_floats[3] > maxVal)
+		{
+			maxIndex = 3;
+			maxVal = m_floats[3];
+		}
+		
+		
+		
+
+		return maxIndex;
+
+	}
+
+
+	SIMD_FORCE_INLINE int minAxis4() const
+	{
+		int minIndex = -1;
+		btScalar minVal = btScalar(BT_LARGE_FLOAT);
+		if (m_floats[0] < minVal)
+		{
+			minIndex = 0;
+			minVal = m_floats[0];
+		}
+		if (m_floats[1] < minVal)
+		{
+			minIndex = 1;
+			minVal = m_floats[1];
+		}
+		if (m_floats[2] < minVal)
+		{
+			minIndex = 2;
+			minVal =m_floats[2];
+		}
+		if (m_floats[3] < minVal)
+		{
+			minIndex = 3;
+			minVal = m_floats[3];
+		}
+		
+		return minIndex;
+
+	}
+
+
+	SIMD_FORCE_INLINE int closestAxis4() const 
+	{
+		return absolute4().maxAxis4();
+	}
+
+	
+ 
+
+  /**@brief Set x,y,z and zero w 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   */
+		
+
+/*		void getValue(btScalar *m) const 
+		{
+			m[0] = m_floats[0];
+			m[1] = m_floats[1];
+			m[2] =m_floats[2];
+		}
+*/
+/**@brief Set the values 
+   * @param x Value of x
+   * @param y Value of y
+   * @param z Value of z
+   * @param w Value of w
+   */
+		SIMD_FORCE_INLINE void	setValue(const btScalar& x, const btScalar& y, const btScalar& z,const btScalar& w)
+		{
+			m_floats[0]=x;
+			m_floats[1]=y;
+			m_floats[2]=z;
+			m_floats[3]=w;
+		}
+
+
+};
+
+
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void	btSwapScalarEndian(const btScalar& sourceVal, btScalar& destVal)
+{
+	#ifdef BT_USE_DOUBLE_PRECISION
+	unsigned char* dest = (unsigned char*) &destVal;
+	unsigned char* src  = (unsigned char*) &sourceVal;
+	dest[0] = src[7];
+    dest[1] = src[6];
+    dest[2] = src[5];
+    dest[3] = src[4];
+    dest[4] = src[3];
+    dest[5] = src[2];
+    dest[6] = src[1];
+    dest[7] = src[0];
+#else
+	unsigned char* dest = (unsigned char*) &destVal;
+	unsigned char* src  = (unsigned char*) &sourceVal;
+	dest[0] = src[3];
+    dest[1] = src[2];
+    dest[2] = src[1];
+    dest[3] = src[0];
+#endif //BT_USE_DOUBLE_PRECISION
+}
+///btSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void	btSwapVector3Endian(const btVector3& sourceVec, btVector3& destVec)
+{
+	for (int i=0;i<4;i++)
+	{
+		btSwapScalarEndian(sourceVec[i],destVec[i]);
+	}
+
+}
+
+///btUnSwapVector3Endian swaps vector endianness, useful for network and cross-platform serialization
+SIMD_FORCE_INLINE void	btUnSwapVector3Endian(btVector3& vector)
+{
+
+	btVector3	swappedVec;
+	for (int i=0;i<4;i++)
+	{
+		btSwapScalarEndian(vector[i],swappedVec[i]);
+	}
+	vector = swappedVec;
+}
+
+template <class T>
+SIMD_FORCE_INLINE void btPlaneSpace1 (const T& n, T& p, T& q)
+{
+  if (btFabs(n[2]) > SIMDSQRT12) {
+    // choose p in y-z plane
+    btScalar a = n[1]*n[1] + n[2]*n[2];
+    btScalar k = btRecipSqrt (a);
+    p[0] = 0;
+	p[1] = -n[2]*k;
+	p[2] = n[1]*k;
+    // set q = n x p
+    q[0] = a*k;
+	q[1] = -n[0]*p[2];
+	q[2] = n[0]*p[1];
+  }
+  else {
+    // choose p in x-y plane
+    btScalar a = n[0]*n[0] + n[1]*n[1];
+    btScalar k = btRecipSqrt (a);
+    p[0] = -n[1]*k;
+	p[1] = n[0]*k;
+	p[2] = 0;
+    // set q = n x p
+    q[0] = -n[2]*p[1];
+	q[1] = n[2]*p[0];
+	q[2] = a*k;
+  }
+}
+
+
+struct	btVector3FloatData
+{
+	float	m_floats[4];
+};
+
+struct	btVector3DoubleData
+{
+	double	m_floats[4];
+
+};
+
+SIMD_FORCE_INLINE	void	btVector3::serializeFloat(struct	btVector3FloatData& dataOut) const
+{
+	///could also do a memcpy, check if it is worth it
+	for (int i=0;i<4;i++)
+		dataOut.m_floats[i] = float(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void	btVector3::deSerializeFloat(const struct	btVector3FloatData& dataIn)
+{
+	for (int i=0;i<4;i++)
+		m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE	void	btVector3::serializeDouble(struct	btVector3DoubleData& dataOut) const
+{
+	///could also do a memcpy, check if it is worth it
+	for (int i=0;i<4;i++)
+		dataOut.m_floats[i] = double(m_floats[i]);
+}
+
+SIMD_FORCE_INLINE void	btVector3::deSerializeDouble(const struct	btVector3DoubleData& dataIn)
+{
+	for (int i=0;i<4;i++)
+		m_floats[i] = btScalar(dataIn.m_floats[i]);
+}
+
+
+SIMD_FORCE_INLINE	void	btVector3::serialize(struct	btVector3Data& dataOut) const
+{
+	///could also do a memcpy, check if it is worth it
+	for (int i=0;i<4;i++)
+		dataOut.m_floats[i] = m_floats[i];
+}
+
+SIMD_FORCE_INLINE void	btVector3::deSerialize(const struct	btVector3Data& dataIn)
+{
+	for (int i=0;i<4;i++)
+		m_floats[i] = dataIn.m_floats[i];
+}
+
+
+#endif //SIMD__VECTOR3_H
diff --git a/SRC/ChronoEngine/collision/bullet/btBulletCollisionCommon.h b/SRC/ChronoEngine/collision/bullet/btBulletCollisionCommon.h
new file mode 100644
index 0000000..9a7bffb
--- /dev/null
+++ b/SRC/ChronoEngine/collision/bullet/btBulletCollisionCommon.h
@@ -0,0 +1,68 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BULLET_COLLISION_COMMON_H
+#define BULLET_COLLISION_COMMON_H
+
+///Common headerfile includes for Bullet Collision Detection
+
+///Bullet's btCollisionWorld and btCollisionObject definitions
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+///Collision Shapes
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+#include "BulletCollision/CollisionShapes/btCapsuleShape.h"
+#include "BulletCollision/CollisionShapes/btCylinderShape.h"
+#include "BulletCollision/CollisionShapes/btConeShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMesh.h"
+#include "BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleMeshShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleIndexVertexArray.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "BulletCollision/CollisionShapes/btEmptyShape.h"
+#include "BulletCollision/CollisionShapes/btMultiSphereShape.h"
+#include "BulletCollision/CollisionShapes/btUniformScalingShape.h"
+
+///Narrowphase Collision Detector
+#include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h"
+
+//btSphereBoxCollisionAlgorithm is broken, use gjk for now
+//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h"
+#include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h"
+
+///Dispatching and generation of collision pairs (broadphase)
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btAxisSweep3.h"
+#include "BulletCollision/BroadphaseCollision/btMultiSapBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btDbvtBroadphase.h"
+
+///Math library & Utils
+#include "LinearMath/btQuaternion.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btDefaultMotionState.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "LinearMath/btSerializer.h"
+
+
+#endif //BULLET_COLLISION_COMMON_H
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCAABB.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCAABB.cpp
new file mode 100644
index 0000000..ee7e086
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCAABB.cpp
@@ -0,0 +1,245 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChCAABB.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+#include <stdlib.h> 
+#include <math.h>
+#include "ChCAABB.h"
+#include "ChCMatVec.h"
+#include "collision/ChCCollisionPair.h"
+
+
+
+namespace chrono
+{
+namespace collision
+{
+
+
+CHAABB::CHAABB()
+{
+	first_child = 0;
+
+	To = VNULL;
+	d =  VNULL;
+}
+
+CHAABB::~CHAABB()
+{
+}
+
+
+
+void CHAABB::FitToGeometries(std::vector<ChGeometry*> mgeos, int firstgeo, int ngeos, double envelope)
+{
+	double minx, maxx, miny, maxy, minz, maxz;
+	minx = miny = minz = +10e20;
+	maxx = maxy = maxz = -10e20;
+
+	ChGeometry* nit = mgeos[firstgeo];
+	for(int count = 0; count < ngeos; ++count)
+	{
+	 nit = mgeos[firstgeo+count];
+	 if(nit)
+	 {
+		nit->InflateBoundingBox(minx, maxx, miny, maxy, minz, maxz, NULL);
+	 }
+	}
+
+
+	To.x = 0.5*(maxx + minx);
+	To.y = 0.5*(maxy + miny);
+	To.z = 0.5*(maxz + minz);
+
+	d.x = 0.5*(maxx - minx) + envelope;
+	d.y = 0.5*(maxy - miny) + envelope;
+	d.z = 0.5*(maxz - minz) + envelope;
+}
+
+
+bool CHAABB::AABB_Overlap(ChMatrix33<>& B, Vector T, CHAABB *b1, CHAABB *b2)
+{
+	  ChMatrix33<> Bf;
+	  const double reps = (double)1e-6;
+
+	  // Bf = fabs(B)
+	  Bf(0,0) = myfabs(B.Get33Element(0,0));  Bf(0,0) += reps;
+	  Bf(0,1) = myfabs(B.Get33Element(0,1));  Bf(0,1) += reps;
+	  Bf(0,2) = myfabs(B.Get33Element(0,2));  Bf(0,2) += reps;
+	  Bf(1,0) = myfabs(B.Get33Element(1,0));  Bf(1,0) += reps;
+	  Bf(1,1) = myfabs(B.Get33Element(1,1));  Bf(1,1) += reps;
+	  Bf(1,2) = myfabs(B.Get33Element(1,2));  Bf(1,2) += reps;
+	  Bf(2,0) = myfabs(B.Get33Element(2,0));  Bf(2,0) += reps;
+	  Bf(2,1) = myfabs(B.Get33Element(2,1));  Bf(2,1) += reps;
+	  Bf(2,2) = myfabs(B.Get33Element(2,2));  Bf(2,2) += reps;
+
+	  return AABB_Overlap(B, Bf, T, b1, b2);
+}
+
+
+
+bool CHAABB::AABB_Overlap(ChMatrix33<>& B, ChMatrix33<>& Bf, Vector T, CHAABB *b1, CHAABB *b2)
+{
+	  register double t, s;
+	  register int r;
+
+	  Vector& a = b1->d;
+	  Vector& b = b2->d;
+
+	  // if any of these tests are one-sided, then the polyhedra are disjoint
+	  r = 1;
+
+	  // A1 x A2 = A0
+	  t = myfabs(T.x);
+
+	  r &= (t <=
+		  (a.x + b.x * Bf.Get33Element(0,0) + b.y * Bf.Get33Element(0,1) + b.z * Bf.Get33Element(0,2)));
+	  if (!r) return false;
+
+	  // B1 x B2 = B0
+	  s = T.x*B.Get33Element(0,0) + T.y*B.Get33Element(1,0) + T.z*B.Get33Element(2,0);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (b.x + a.x * Bf.Get33Element(0,0) + a.y * Bf.Get33Element(1,0) + a.z * Bf.Get33Element(2,0)));
+	  if (!r) return false;
+
+	  // A2 x A0 = A1
+	  t = myfabs(T.y);
+
+	  r &= ( t <=
+		  (a.y + b.x * Bf.Get33Element(1,0) + b.y * Bf.Get33Element(1,1) + b.z * Bf.Get33Element(1,2)));
+	  if (!r) return false;
+
+	  // A0 x A1 = A2
+	  t = myfabs(T.z);
+
+	  r &= ( t <=
+		  (a.z + b.x * Bf.Get33Element(2,0) + b.y * Bf.Get33Element(2,1) + b.z * Bf.Get33Element(2,2)));
+	  if (!r) return false;
+
+	  // B2 x B0 = B1
+	  s = T.x*B.Get33Element(0,1) + T.y*B.Get33Element(1,1) + T.z*B.Get33Element(2,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (b.y + a.x * Bf.Get33Element(0,1) + a.y * Bf.Get33Element(1,1) + a.z * Bf.Get33Element(2,1)));
+	  if (!r) return false;
+
+	  // B0 x B1 = B2
+	  s = T.x*B.Get33Element(0,2) + T.y*B.Get33Element(1,2) + T.z*B.Get33Element(2,2);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (b.z + a.x * Bf.Get33Element(0,2) + a.y * Bf.Get33Element(1,2) + a.z * Bf.Get33Element(2,2)));
+	  if (!r) return false;
+
+	  // A0 x B0
+	  s = T.z * B.Get33Element(1,0) - T.y * B.Get33Element(2,0);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		(a.y * Bf.Get33Element(2,0) + a.z * Bf.Get33Element(1,0) +
+		 b.y * Bf.Get33Element(0,2) + b.z * Bf.Get33Element(0,1)));
+	  if (!r) return false;
+
+	  // A0 x B1
+	  s = T.z * B.Get33Element(1,1) - T.y * B.Get33Element(2,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		(a.y * Bf.Get33Element(2,1) + a.z * Bf.Get33Element(1,1) +
+		 b.x * Bf.Get33Element(0,2) + b.z * Bf.Get33Element(0,0)));
+	  if (!r) return false;
+
+	  // A0 x B2
+	  s = T.z * B.Get33Element(1,2) - T.y * B.Get33Element(2,2);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.y * Bf.Get33Element(2,2) + a.z * Bf.Get33Element(1,2) +
+		   b.x * Bf.Get33Element(0,1) + b.y * Bf.Get33Element(0,0)));
+	  if (!r) return false;
+
+	  // A1 x B0
+	  s = T.x * B.Get33Element(2,0) - T.z * B.Get33Element(0,0);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(2,0) + a.z * Bf.Get33Element(0,0) +
+		   b.y * Bf.Get33Element(1,2) + b.z * Bf.Get33Element(1,1)));
+	  if (!r) return false;
+
+	  // A1 x B1
+	  s = T.x * B.Get33Element(2,1) - T.z * B.Get33Element(0,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(2,1) + a.z * Bf.Get33Element(0,1) +
+		   b.x * Bf.Get33Element(1,2) + b.z * Bf.Get33Element(1,0)));
+	  if (!r) return false;
+
+	  // A1 x B2
+	  s = T.x * B.Get33Element(2,2) - T.z * B.Get33Element(0,2);
+	  t = myfabs(s);
+
+	  r &= (t <=
+		  (a.x * Bf.Get33Element(2,2) + a.z * Bf.Get33Element(0,2) +
+		   b.x * Bf.Get33Element(1,1) + b.y * Bf.Get33Element(1,0)));
+	  if (!r) return false;
+
+	  // A2 x B0
+	  s = T.y * B.Get33Element(0,0) - T.x * B.Get33Element(1,0);
+	  t = myfabs(s);
+
+	  r &= (t <=
+		  (a.x * Bf.Get33Element(1,0) + a.y * Bf.Get33Element(0,0) +
+		   b.y * Bf.Get33Element(2,2) + b.z * Bf.Get33Element(2,1)));
+	  if (!r) return false;
+
+	  // A2 x B1
+	  s = T.y * B.Get33Element(0,1) - T.x * B.Get33Element(1,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(1,1) + a.y * Bf.Get33Element(0,1) +
+		   b.x * Bf.Get33Element(2,2) + b.z * Bf.Get33Element(2,0)));
+	  if (!r) return false;
+
+	  // A2 x B2
+	  s = T.y * B.Get33Element(0,2) - T.x * B.Get33Element(1,2);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(1,2) + a.y * Bf.Get33Element(0,2) +
+		   b.x * Bf.Get33Element(2,1) + b.y * Bf.Get33Element(2,0)));
+	  if (!r) return false;
+
+	  return true;  // no separation: BV collide
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCAABB.h b/SRC/ChronoEngine/collision/edgetempest/ChCAABB.h
new file mode 100644
index 0000000..020cc8c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCAABB.h
@@ -0,0 +1,143 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_AABB_H
+#define CHC_AABB_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCAABB.h
+//
+//   Header for the Axially Aligned Bounding Box
+//   class. Useful for BSP collision queries.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include <vector>
+#include "geometry/ChCGeometry.h"
+#include "ChCCompile.h"
+
+
+using namespace chrono::geometry;
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+///
+/// Class for Axially Aligned Bounding Box (AABB).
+/// This class is useful for collision tests based on
+/// trees of bounding volumes.
+///
+
+
+class CHAABB
+{
+public:
+  			// DATA
+
+  Vector To;			///< Position of center of aabb
+
+  Vector  d;			///< Size, (half) dimensions of obb
+
+
+  int first_child;      ///< Positive value is index of first_child AABB.
+                        ///  Negative value is -(index + 1) of geometry in geom.list
+
+
+			// FUNCTIONS
+  CHAABB();
+  ~CHAABB();
+  			// Copy constructor 
+  CHAABB(const CHAABB& other) {To=other.To; d=other.d; first_child=other.first_child;}
+
+						
+						/// Return 1 if this is a leaf 
+  inline int IsLeaf()  { return first_child < 0; }
+						
+						/// Returns the index of the geometry in the geometry vector of the model
+						/// Caution: must be used only if IsLeaf()==true
+  inline int GetGeometryIndex()	{return (-first_child -1);}
+
+						/// Returns the index of the first child box, in box vector of the model
+						/// Caution: must be used only if IsLeaf()==false
+  inline int GetFirstChildIndex()	{return first_child;}
+
+ 						/// Returns the index of the second child box, in box vector of the model
+						/// Caution: must be used only if IsLeaf()==false
+  inline int GetSecondChildIndex()	{return first_child+1;}
+
+
+						/// Returns the size of the bounding box (sphere radius)
+  double   GetSize() { return (d.x*d.x + d.y*d.y + d.z*d.z);}
+  
+
+						/// Given  a list of geometric object, this function recomputes the
+						/// bounding box in order to enclose 'ngeos' geometries, 
+						/// from index 'firstgeo' up to 'firstgeo+ngeos', not included.
+						/// 
+  void     FitToGeometries( std::vector<ChGeometry*> mgeos, ///< vector of geometric objects 
+							int firstgeo,	///< geometries will be fit from this index... 
+							int ngeos,		///< .. up to this index
+							double envelope ///< inflate all boxes by this amount
+							);	
+
+
+						/// Find if two box AABB are overlapping, given relative 
+						/// rotation matrix, relative translation, and the two AABB
+						/// \return true if overlapping
+						///
+  static bool AABB_Overlap(	ChMatrix33<>& B,		///< relative rotation matrix
+							Vector T,		///< relative translation
+							CHAABB *b1,		///< first bounding box
+							CHAABB *b2		///< second bounding box
+						  );
+
+						/// Find if two box AABB are overlapping, given relative 
+						/// rotation matrix B, relative translation T, and the two AABB,
+						/// Optimized for case when the absolute fabsB matrix is precomputed, since
+						/// B and fabsB do not change during the many overlap tests on AABB of two models.
+						/// \return true if overlapping
+						///
+  static bool AABB_Overlap( ChMatrix33<>& B,		///< relative rotation matrix
+							ChMatrix33<>& fabsB,	///< relative rotation, but with absolute values 
+							Vector T,		///< relative translation
+							CHAABB *b1,		///< first bounding box
+							CHAABB *b2		///< second bounding box
+						  );
+
+
+
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif
+
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCAABBTree.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCAABBTree.cpp
new file mode 100644
index 0000000..15ebcb3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCAABBTree.cpp
@@ -0,0 +1,314 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChCAABBTree.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include <stdio.h>
+#include <string.h>
+
+#include "ChCMatVec.h"
+#include "ChCGetTime.h"
+#include "ChCAABBTree.h"
+
+
+
+namespace chrono
+{
+namespace collision
+{
+
+
+
+CHAABBTree::CHAABBTree()
+{
+	current_box = 0;
+}
+
+
+CHAABBTree::~CHAABBTree()
+{
+	ResetModel();
+}
+
+
+
+
+int CHAABBTree::ResetModel()
+{
+  // INHERIT PARENT CLASS RESET FUNCTION
+  ChCollisionTree::ResetModel();
+
+  b.clear();
+
+  current_box = 0;
+
+  return ChC_OK;
+}
+
+
+
+int CHAABBTree::BuildModel(double envelope)
+{
+  // INHERIT PARENT CLASS RESET FUNCTION
+  ChCollisionTree::BuildModel(envelope);
+
+  if (build_state == ChC_BUILD_STATE_PROCESSED)
+  {
+	  return ChC_OK;
+  }
+
+  // create an array of BVs for the model
+
+  b.clear();
+
+  if (num_geometries==0) 
+	return ChC_OK;
+
+  b.resize(2*num_geometries - 1);
+
+
+  current_box = 0;
+
+  // we should build the model now.
+
+  build_model(envelope);	// %%%%%%%%%%%% BUILD HIERARCHY HERE %%%%%%%%%%%
+
+  build_state = ChC_BUILD_STATE_PROCESSED;
+
+
+  return ChC_OK;
+}
+
+
+void recurse_scan_AABBs (CHAABBTree* mmodel, int nb,
+						void* userdata, int current_level, int& counter,
+						void callback(ChMatrix33<>& Rot,Vector& Pos,Vector& d, int level, void* userdata))
+{
+	counter++;
+
+	// compute root-relative coords for each box
+	ChMatrix33<> Rot;
+	Rot.Set33Identity();
+
+	// execute callback
+	callback(Rot, mmodel->child(nb)->To, mmodel->child(nb)->d, current_level, userdata);
+
+	// break recursion on leaf
+	if (mmodel->child(nb)->IsLeaf())
+		return;
+
+
+	int c1 = mmodel->child(nb)->first_child;
+    int c2 = c1 + 1;
+
+	int new_currlevel = current_level + 1;
+
+	recurse_scan_AABBs(mmodel, c1, userdata, new_currlevel, counter, callback);
+
+	recurse_scan_AABBs(mmodel, c2, userdata, new_currlevel, counter, callback);
+
+}
+
+
+int CHAABBTree::TraverseBoundingBoxes( void callback(ChMatrix33<>& Rot,Vector& Pos,Vector& d,int level, void* userdata),
+									  void* userdata)
+{
+	int nboxes = 0;
+
+	recurse_scan_AABBs(this, 0, userdata, 0, nboxes, callback);
+
+	return nboxes;
+}
+
+
+///////////////////////////////////////////////////////////////////
+
+//
+// Building of the model
+//
+
+
+
+
+
+static void get_centroid_geometries(Vector& mean, std::vector<ChGeometry*>& mgeos, int firstgeo, int ngeos)
+{
+  mean = VNULL;
+
+  // get center of mass
+  ChGeometry* nit = mgeos[firstgeo];
+  for(int count = 0; count < ngeos; ++count)
+  {
+	nit = mgeos[firstgeo+count];
+	Vector baricenter = nit->Baricenter();
+
+    mean.x += baricenter.x;
+    mean.y += baricenter.y;
+    mean.z += baricenter.z;
+  }
+
+  mean.x /= ngeos;
+  mean.y /= ngeos;
+  mean.z /= ngeos;
+}
+
+
+
+
+
+static int split_geometries(std::vector<ChGeometry*>& mgeos, int firstgeo, int ngeos,
+							Vector& direction, double c)
+{
+  int c1 = 0;
+  double x;
+  ChGeometry* temp;
+
+  for(int count = 0; count < ngeos; count++)
+  {
+    int i = count+firstgeo;
+
+    // loop invariant: up to (but not including) index c1 in group 1,
+    // then up to (but not including) index i in group 2
+    //
+    //  [1] [1] [1] [1] [2] [2] [2] [x] [x] ... [x]
+    //                   c1          i
+    //
+	Vector vg = mgeos[i]->Baricenter();
+
+
+	x = Vdot(vg,direction);
+
+    if (x <= c)
+    {
+	    // group 1
+	    temp = mgeos[i];
+	    mgeos[i] = mgeos[firstgeo+c1];
+	    mgeos[firstgeo+c1] = temp;
+	    c1++;
+    }
+    else
+    {
+	    // group 2 -- do nothing
+    }
+  }
+
+  // split arbitrarily if one group empty
+
+  if ((c1 == 0) || (c1 == ngeos)) c1 = ngeos/2;
+
+  return c1;
+}
+
+
+
+
+// Fits m->child(bn) to the num_tris triangles starting at first_tri
+// Then, if num_tris is greater than one, partitions the tris into two
+// sets, and recursively builds two children of m->child(bn)
+
+int build_recurse(CHAABBTree *m, int bn, int first_geo, int num_geos, double envelope)
+{
+  CHAABB *b = m->child(bn);
+
+  double coord;
+  Vector axis;
+  Vector mean;
+
+    // fit the BV
+
+  b->FitToGeometries(m->geometries, first_geo, num_geos, envelope);
+
+  if (num_geos == 1)
+  {
+    // BV is a leaf BV - first_child will index a triangle
+
+    b->first_child = -(first_geo + 1);
+  }
+  else if (num_geos > 1)
+  {
+    // BV not a leaf - first_child will index a BV
+
+    b->first_child = m->current_box;
+    m->current_box+=2;
+
+    // choose splitting axis
+
+	axis = VECT_X;
+	if (b->d.y > b->d.x)
+		axis = VECT_Y;
+	if (b->d.z > b->d.y)
+		axis = VECT_Z;
+	if (b->d.z > b->d.x)
+		axis = VECT_Z;
+
+	// choose splitting coord
+
+	get_centroid_geometries(mean, m->geometries, first_geo, num_geos);
+
+    coord = Vdot(axis, mean);
+
+	//*** TO DO***??? other splitting criterions??
+
+
+    // now split
+
+    int num_first_half = split_geometries(m->geometries, first_geo, num_geos,
+		axis, coord);
+
+
+    // recursively build the children
+
+    build_recurse(m, m->child(bn)->first_child,
+					first_geo, num_first_half,
+					envelope);
+    build_recurse(m, m->child(bn)->first_child + 1,
+                    first_geo + num_first_half, num_geos - num_first_half,
+					envelope);
+  }
+
+  return ChC_OK;
+}
+
+
+
+
+
+
+
+
+int CHAABBTree::build_model(double envelope)
+{
+  // set num_bvs to 1, the first index for a child bv
+
+  current_box = 1;
+
+  // build recursively
+
+  build_recurse(this, 0, 0, num_geometries, envelope);
+
+
+  return ChC_OK;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCAABBTree.h b/SRC/ChronoEngine/collision/edgetempest/ChCAABBTree.h
new file mode 100644
index 0000000..99e5cb6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCAABBTree.h
@@ -0,0 +1,99 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_AABBTREE_H
+#define CHC_AABBTREE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCAABBTree.h
+//
+//   Class for the binary space partitioning tree 
+//   (aka BSP) based on AABB bounding volumes
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChCCollisionTree.h"
+#include "ChCAABB.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+///
+/// Class containing a tree of Axially Aligned Bounding Boxes, ready for 
+/// collision detection.
+/// Each rigid body can have one of these models
+///
+
+
+class CHAABBTree : public ChCollisionTree
+{
+
+public:
+
+  CHAABBTree();
+  ~CHAABBTree();
+
+		/// Deletes all inserted geometries and resets bounding box hierarchies
+  int ResetModel();
+
+		/// Rebuilds the AABB hierarchy 
+		/// (boxes may be inflated by an 'envelope' amount).
+  int BuildModel(double envelope=0.);
+
+		/// This function can be used if you want to easily scan the hierarchy 
+		/// of bounding boxes. You must provide a callback to a function which 
+		/// will be automatically called per each bounding box in this tree.
+		/// Note that the callback will get info about the rotation Rot of the 
+		/// box, its position Pos, its size d, its level. Also you can pass generic
+		/// user data via a pointer.  \return the number of scanned boxes.
+  int TraverseBoundingBoxes( void callback(ChMatrix33<>& Rot,Vector& Pos,Vector& d,int level, void* userdata),
+									  void* userdata);
+
+  		/// Returns the n-th child of the tree.
+  CHAABB* child(int n) { return &b[n]; }
+
+public:
+ 
+		/// Vector of AABB bounding boxes.
+	std::vector<CHAABB> b;
+
+		/// Used by internal algorithms
+	int current_box;
+
+		/// From geometric objects, builds the hierarchy of BV bounding volumes
+	int build_model(double envelope);
+};
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCAABBcollider.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCAABBcollider.cpp
new file mode 100644
index 0000000..db7d788
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCAABBcollider.cpp
@@ -0,0 +1,195 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCAABBcollider.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include <stdio.h>
+#include <string.h>
+
+
+#include "ChCMatVec.h"
+#include "ChCGetTime.h"
+#include "ChCAABBcollider.h"
+
+#include "ChCGeometryCollider.h"
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+CHAABBcollider::CHAABBcollider()
+{
+	this->Rabs.Set33Identity();
+}
+
+CHAABBcollider::~CHAABBcollider()
+{
+
+}
+
+
+
+
+
+void CHAABBcollider::CollideRecurse(
+               CHAABBTree *o1, int b1, 
+               CHAABBTree *o2, int b2, 
+			   eCollMode flag)
+{
+ 
+  CHAABB* box1 = o1->child(b1);
+  CHAABB* box2 = o2->child(b2);
+
+  this->num_bv_tests++;
+
+  // first thing, see if we're overlapping
+
+  static Vector Translation;
+  Translation = Vsub (this->T, box1->To);
+  Translation = Vadd (Translation, this->R.Matr_x_Vect(box2->To));
+
+  if (!CHAABB::AABB_Overlap(this->R, this->Rabs, Translation, box1, box2)) 
+	  return;
+  
+  // if we are, see if we test triangles next
+
+  int l1 = box1->IsLeaf();
+  int l2 = box2->IsLeaf();
+
+  //
+  // CASE TWO LEAVES
+  //
+
+  if (l1 && l2) 
+  {
+    this->num_geo_tests++;
+
+    // transform the points in b2 into space of b1, then compare
+
+	ChGeometry* mgeo1 = o1->geometries[box1->GetGeometryIndex()];
+	ChGeometry* mgeo2 = o2->geometries[box2->GetGeometryIndex()];
+
+	bool just_intersect = false;
+	if (flag==ChNarrowPhaseCollider::ChC_FIRST_CONTACT)
+		just_intersect = true;
+
+	ChGeometryCollider::ComputeCollisions(*mgeo1, &this->R1, &this->T1, 
+										  *mgeo2, &this->R2, &this->T2, 
+										  *this, 
+										  &this->R, &this->T, 
+										  just_intersect);
+	return;
+  }
+
+  // we dont, so decide whose children to visit next
+
+  double sz1 = box1->GetSize();
+  double sz2 = box2->GetSize();
+
+    
+  if (l2 || (!l1 && (sz1 > sz2)))
+  {
+    int c1 = box1->GetFirstChildIndex();
+    int c2 = box1->GetSecondChildIndex();
+
+    CollideRecurse(o1,c1,o2,b2,flag);
+
+     if ((flag == ChC_FIRST_CONTACT) && (this->GetNumPairs() > 0)) return;
+
+    CollideRecurse(o1,c2,o2,b2,flag);
+  }
+  else 
+  {
+    int c1 = box2->GetFirstChildIndex();
+    int c2 = box2->GetSecondChildIndex();
+
+    CollideRecurse(o1,b1,o2,c1,flag);
+
+     if ((flag == ChC_FIRST_CONTACT) && (this->GetNumPairs() > 0)) return;
+
+    CollideRecurse(o1,b1,o2,c2,flag);
+  }
+}
+
+
+//
+// PERFORM COLLISION DETECTION
+//
+
+ChNarrowPhaseCollider::eCollSuccess CHAABBcollider::ComputeCollisions(
+            ChMatrix33<>& R1, Vector T1, ChCollisionTree *oc1,
+            ChMatrix33<>& R2, Vector T2, ChCollisionTree *oc2,
+            eCollMode flag)
+{
+  double t1 = GetTime();
+
+  // INHERIT parent class behaviour
+
+  if (ChNarrowPhaseCollider::ComputeCollisions(
+			R1, T1, oc1,
+            R2, T2, oc2,
+            flag) != ChC_RESULT_OK)
+				return ChC_RESULT_GENERICERROR;
+ 
+  // Downcasting 
+  CHAABBTree* o1 = (CHAABBTree*)oc1;
+  CHAABBTree* o2 = (CHAABBTree*)oc2;
+
+  // clear the stats
+
+  this->num_bv_tests = 0;
+  this->num_geo_tests = 0;
+  
+
+  // Precompute the Rabs matrix, to be used many times in AABB collisions
+
+  const double reps = (double)1e-6;
+  // Rabs = fabs(R)+eps
+  Rabs(0,0) = myfabs(R.Get33Element(0,0));  Rabs(0,0) += reps;
+  Rabs(0,1) = myfabs(R.Get33Element(0,1));  Rabs(0,1) += reps;
+  Rabs(0,2) = myfabs(R.Get33Element(0,2));  Rabs(0,2) += reps;
+  Rabs(1,0) = myfabs(R.Get33Element(1,0));  Rabs(1,0) += reps;
+  Rabs(1,1) = myfabs(R.Get33Element(1,1));  Rabs(1,1) += reps;
+  Rabs(1,2) = myfabs(R.Get33Element(1,2));  Rabs(1,2) += reps;
+  Rabs(2,0) = myfabs(R.Get33Element(2,0));  Rabs(2,0) += reps;
+  Rabs(2,1) = myfabs(R.Get33Element(2,1));  Rabs(2,1) += reps;
+  Rabs(2,2) = myfabs(R.Get33Element(2,2));  Rabs(2,2) += reps;
+
+  // Now start with both top level BVs and recurse... 
+
+  CollideRecurse(o1,0,o2,0,flag);
+  
+
+  
+  double t2 = GetTime();
+  this->query_time_secs = t2 - t1;
+
+  return ChC_RESULT_OK; 
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCAABBcollider.h b/SRC/ChronoEngine/collision/edgetempest/ChCAABBcollider.h
new file mode 100644
index 0000000..05bc151
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCAABBcollider.h
@@ -0,0 +1,95 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_AABBCOLLIDER_H
+#define CHC_AABBCOLLIDER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCAABBcollider.h
+//
+//   Detects collisions between a pair of collision 
+//   models based on AABBs
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChCCompile.h"   
+#include "collision/ChCCollisionPair.h"                           
+#include "ChCAABBTree.h"
+#include "ChCNarrowPhaseCollider.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+/// 
+/// This class specializes the ChNarrowPhaseCollider base class, in order
+/// to compute the case of collisions between two collision models
+/// based on AABB trees.
+///
+
+class CHAABBcollider : public ChNarrowPhaseCollider
+{
+public:
+
+  CHAABBcollider();
+  ~CHAABBcollider();
+
+	// PERFORM THE COLLISION DETECTION
+
+			/// Perform collision detection between two AABB-based
+			/// collision models (each belonging to a different rigid
+			/// body, for example), given the absolute orientations and
+			/// translations of the two models.
+			/// The identified contacts will be inserted in the Contacts vector.
+			///
+  eCollSuccess ComputeCollisions(
+            ChMatrix33<>& R1, Vector T1, ChCollisionTree *oc1,
+            ChMatrix33<>& R2, Vector T2, ChCollisionTree *oc2,
+			eCollMode flag);
+
+private:
+		// as this->>R, but absolute values plus some epsilon. Precomputed and used for AABB intersection
+	ChMatrix33<> Rabs;
+
+	void CollideRecurse(
+               CHAABBTree *o1, int b1, 
+               CHAABBTree *o2, int b2, 
+			   eCollMode flag);
+};
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif
+
+
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCAbsoluteAABB.h b/SRC/ChronoEngine/collision/edgetempest/ChCAbsoluteAABB.h
new file mode 100644
index 0000000..3a93866
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCAbsoluteAABB.h
@@ -0,0 +1,124 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_ABSOLUTEAABB_H
+#define CHC_ABSOLUTEAABB_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCAbsoluteAABB.h
+//
+//   Header for defining axis-aligned bounding 
+//   boxes in absolute space, to be used with
+//   the 'sweep and prune' broad-phase
+//   collision detection stage.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+/// Class for end point, to be used for X or Y or Z lists of 
+/// the 'sweep and prune' broad-phase collision.
+
+template<class coll_model_type>
+class ChIntervalEndpoint
+{
+
+  public:
+
+		/// Constructor
+    ChIntervalEndpoint(void):m_type(0),m_model(0){};
+
+		/// Initialize
+    void init(coll_model_type* model, const unsigned int & type)
+				{
+					assert(model);
+					assert(type==0 || type==1);
+					this->m_model = model;
+					this->m_type = type;
+				};
+
+  public:
+
+	double				m_value;  ///< scalar value of the endpoint.
+	coll_model_type*	m_model;   ///< pointer to the body.
+	unsigned int		m_type;   ///< start point=0; end point =1;
+
+};
+
+
+
+
+
+/// Header for defining AABB (axis-aligned bounding 
+/// boxes) in absolute space, to be used with
+/// the 'sweep and prune' broad-phase
+/// collision detection stage. This AABB is made of eight
+/// ChIntervalEndpoint() items. 
+
+template<class coll_model_type>
+class ChAbsoluteAABB
+{
+  public:
+
+    ChAbsoluteAABB(void):m_model(0){};
+
+    void init(coll_model_type* amodel)
+    {
+      if(!m_model)
+      {
+        m_model = amodel;
+        m_beginX.init(amodel,0);
+        m_beginY.init(amodel,0);
+        m_beginZ.init(amodel,0);
+        m_endX.init(amodel,1);
+        m_endY.init(amodel,1);
+        m_endZ.init(amodel,1);
+      }
+      assert(m_model);
+    };
+
+  public:
+
+    coll_model_type* m_model;   ///< A pointer to the corresponding collision model this AABB encloses.
+
+    ChIntervalEndpoint<coll_model_type> m_beginX;
+    ChIntervalEndpoint<coll_model_type> m_beginY;
+    ChIntervalEndpoint<coll_model_type> m_beginZ;
+    ChIntervalEndpoint<coll_model_type> m_endX;
+    ChIntervalEndpoint<coll_model_type> m_endY;
+    ChIntervalEndpoint<coll_model_type> m_endZ;
+
+};
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCBroadPhaseCollider.h b/SRC/ChronoEngine/collision/edgetempest/ChCBroadPhaseCollider.h
new file mode 100644
index 0000000..875642e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCBroadPhaseCollider.h
@@ -0,0 +1,97 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_BROADPHASECOLLIDER_H
+#define CHC_BROADPHASECOLLIDER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCBroadPhaseCollider.h
+//
+//   Header for base class for generic broad-phase 
+//   collision engine.
+//   Class must be specialized by children classes.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#if	(_MSC_VER >= 1200)
+ #pragma warning(4: 4786)
+#endif
+
+
+#include <list>
+
+#include "ChCMates.h"
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+
+
+
+///
+/// Base class for generic broad-phase collision engine.
+/// Most methods are 'pure virtual': they need to be implemented
+/// by child classes.
+/// 
+
+template<class model_type> 
+class ChBroadPhaseCollider
+{
+  public:
+	typedef typename std::list<ChMates<model_type>*> ChMatesPtrList;
+
+  public:
+
+	ChBroadPhaseCollider() {};
+	virtual ~ChBroadPhaseCollider() {};
+
+					/// Clears all data instanced by this algorithm.
+    virtual void Clear(void) = 0;
+
+					/// Adds a collision model to the broad-phase
+					/// engine (custom data may be allocated).
+    virtual void Add(model_type* model) = 0;
+
+					/// Removes a collision model from the broad-phase
+					/// engine (custom data may be deallocated).
+    virtual void Remove(model_type* model) = 0;
+
+					/// Run the broad-phase collision algorithm, which finds the
+					/// overlapping pairs of bounding boxes
+	virtual void Run() = 0;
+
+					/// After the broad phase algorithm has run, you can use
+					/// this method to access the list with the reported pairs of
+					/// overlapping models.
+	virtual ChMatesPtrList& GetReportedMates() = 0;
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCBruteForce.h b/SRC/ChronoEngine/collision/edgetempest/ChCBruteForce.h
new file mode 100644
index 0000000..c02c436
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCBruteForce.h
@@ -0,0 +1,145 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_BRUTEFORCE_H
+#define CHC_BRUTEFORCE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCBruteForce.h
+//
+//   Header for a simple broad-phase collision engine,
+//   Such 'brute force' broad-phase exploits a bad
+//   combinatorial complexity. Therefore it is here just
+//   for benchmark and profiling.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "geometry/ChCGeometry.h"
+#include "ChCBroadPhaseCollider.h"
+
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+
+
+/// 
+/// The 'brute force' broad-phase exploits a bad
+/// combinatorial complexity. Therefore it is here just
+/// for benchmark and profiling.
+///
+
+
+template<class model_type> 
+class ChBruteForce : public ChBroadPhaseCollider<model_type>
+{
+  protected: 
+
+	ChMatesPtrList m_reported;			///< A list containing all possible overlaps
+	std::list<model_type*> m_models;	///< A list of inserted models
+
+  public:
+
+	ChBruteForce() {};
+	virtual ~ChBruteForce() 
+				{
+					Clear();
+				};
+
+					/// Clears all data instanced by this algorithm.
+    virtual void Clear(void) 
+				{
+					m_models.clear();
+
+					while(!m_reported.empty())
+					{
+						std::list<ChMates<model_type>*>::iterator mates = m_reported.begin();
+						delete *mates;
+						m_reported.erase(mates);
+					}
+					m_reported.clear(); // unuseful?
+				}
+
+					/// Adds a collision model to the broad-phase
+					/// engine (custom data may be allocated).
+    virtual void Add(model_type* model) 
+				{
+					std::list<model_type*>::iterator pastmodel = m_models.begin();
+					while(pastmodel != m_models.end())
+					{
+						ChMates<model_type>* newmates = new ChMates<model_type>(*pastmodel,model);
+						m_reported.push_back(newmates);
+						pastmodel++;
+					}
+					  
+					m_models.push_back(model);
+				}
+
+					/// Removes a single collision model from the broad-phase
+					/// engine (custom data may be deallocated).
+					 //***TO CHECK***
+    virtual void Remove(model_type* model)
+				{
+					m_models.remove(model); 
+
+					ChMatesPtrList::iterator imate = m_reported.begin();
+					while(imate != m_reported.end())
+					{
+						if ( ((*imate)->GetModelA() == model) || ((*imate)->GetModelB() == model))
+						{
+							ChMatesPtrList::iterator idelmate =imate;
+							imate++;
+							delete(*idelmate);
+							m_reported.erase(idelmate);
+						}
+						else
+							imate++;
+					}
+				}
+
+					/// Run the 'brute force' algorithm, which finds the
+					/// overlapping pairs of bounding boxes
+	virtual void Run() 
+				{
+					// nothing to do because overlaps are already instanced at 'Add() time..
+				};
+
+					/// After the broad phase algorithm has run, you can use
+					/// this method to access the list with the reported pairs of
+					/// overlapping models.
+	virtual ChMatesPtrList& GetReportedMates() {return m_reported;};
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCCollisionTree.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCCollisionTree.cpp
new file mode 100644
index 0000000..031b497
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCCollisionTree.cpp
@@ -0,0 +1,158 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionTree.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+
+#include <stdio.h>
+#include <string.h>
+
+
+#include "ChCMatVec.h"
+#include "ChCGetTime.h"
+#include "ChCCollisionTree.h"
+#include "physics/ChBody.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+ChCollisionTree::ChCollisionTree()
+{
+  // no bounding volume tree yet
+  num_geometries = 0;
+
+  last_geometry = NULL;
+ 
+  build_state = ChC_BUILD_STATE_MODIFIED;
+
+  m_body =NULL;
+}
+
+
+ChCollisionTree::~ChCollisionTree()
+{
+   ResetModel();
+}
+
+
+int ChCollisionTree::ResetModel()
+{
+  // delete previously added geometries
+  std::vector<ChGeometry*>::iterator nit = geometries.begin();
+  for(;nit!=geometries.end();++nit)
+  {
+	  if (*nit) 
+		  delete (*nit); 
+	  *nit = NULL;
+  }
+  geometries.clear();  
+  num_geometries = 0;
+  
+  build_state = ChC_BUILD_STATE_MODIFIED;
+
+  return ChC_OK;
+}
+
+
+
+int ChCollisionTree::BuildModel(double envelope)
+{
+  if (build_state == ChC_BUILD_STATE_PROCESSED)
+  {
+    //fprintf(stderr,"Warning! Called EndModel() on ChCollisionTree \n"
+    //               "object that was already ended. EndModel() was\n"
+    //               "ignored.  Must do a BeginModel() to clear the\n"
+    //               "model for addition of new triangles\n");
+    return ChC_OK;
+  }
+
+  if (num_geometries)
+	last_geometry = *geometries.begin();
+  else 
+	last_geometry = NULL;
+
+  return ChC_OK;
+}
+
+
+int ChCollisionTree::AddGeometry(ChGeometry* mgeo)
+{
+	this->geometries.push_back(mgeo);
+
+	num_geometries += 1;
+
+	build_state = ChC_BUILD_STATE_MODIFIED;
+
+	return ChC_OK;
+}
+ 
+ 
+void ChCollisionTree::GetBoundingBox(  double& xmin, double& xmax, 
+							  double& ymin, double& ymax, 
+							  double& zmin, double& zmax, 
+							  ChMatrix33<>* Rot)
+{
+	xmin = ymin = zmin = +10e20;
+	xmax = ymax = zmax = -10e20;
+
+	std::vector<ChGeometry*>::iterator nit = geometries.begin();
+    for(;nit!=geometries.end();++nit)
+	{
+	 if((*nit))
+	 {
+		(*nit)->InflateBoundingBox(xmin, xmax, ymin, ymax, zmin, zmax, Rot);
+	 }
+	}
+}
+
+
+		
+void ChCollisionTree::UpdateAbsoluteAABB(double envelope)
+{
+	assert(m_body);
+
+	double xmin, xmax, ymin, ymax, zmin, zmax;
+
+	m_absoluteAABB.init(this);
+
+	static ChMatrix33<> at;
+	at.CopyFromMatrixT(*this->m_body->GetA());
+
+	GetBoundingBox(xmin, xmax, ymin, ymax, zmin, zmax, &at);
+
+	m_absoluteAABB.m_beginX.m_value= xmin -envelope + m_body->GetPos().x;
+	m_absoluteAABB.m_endX.m_value  = xmax +envelope + m_body->GetPos().x;
+	m_absoluteAABB.m_beginY.m_value= ymin -envelope + m_body->GetPos().y;
+	m_absoluteAABB.m_endY.m_value  = ymax +envelope + m_body->GetPos().y;
+	m_absoluteAABB.m_beginZ.m_value= zmin -envelope + m_body->GetPos().z;
+	m_absoluteAABB.m_endZ.m_value  = zmax +envelope + m_body->GetPos().z;
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCCollisionTree.h b/SRC/ChronoEngine/collision/edgetempest/ChCCollisionTree.h
new file mode 100644
index 0000000..4777b6a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCCollisionTree.h
@@ -0,0 +1,192 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_COLLISIONTREE_H
+#define CHC_COLLISIONTREE_H
+ 
+//////////////////////////////////////////////////
+//  
+//   ChCCollisionTree.h
+//
+//   The collision tree class, defining a tree
+//   of geometric objects.
+// 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <vector>
+
+#include "geometry/ChCGeometry.h"
+#include "ChCAbsoluteAABB.h"
+
+#define CH_COLL_ENVELOPE 0.0022
+
+using namespace chrono::geometry;
+
+namespace chrono 
+{
+
+// forward references
+class ChBody;
+
+
+namespace collision 
+{
+
+
+
+
+
+///
+/// Class defining a hierarchical tree of geometric trees, for
+/// fast collision-detection purposes. To be specialized and
+/// implemented by child classes such as CHOBBTree() or CHAABBTree()
+///
+
+class ChCollisionTree
+{
+public:
+
+  ChCollisionTree();
+  virtual ~ChCollisionTree();
+  
+
+
+		/// Deletes all inserted geometries
+		/// MUST be inherited by child classes! (ex for resetting also BV hierarchies)
+  virtual int ResetModel();
+
+		/// Add a ChGeometry in this model. 
+		/// All the added geometries will be automatically deleted when this 
+		/// model is deleted. 
+  virtual int AddGeometry(ChGeometry* mgeo);
+
+		/// Builds the BV hierarchy
+		/// MUST be inherited by child classes! (ex for bulding BV hierarchies)
+		/// The 'out_layer' parameter can be used if contacts have to be detected 
+		/// even at a distance='envelope' from the surface (shortly, the effect
+		/// is that bounding boxes are 'inflated' by this parameter).
+  virtual int BuildModel(double envelope=0.);
+
+
+		/// This function can be used if you want to easily scan the hierarchy 
+		/// of bounding boxes. You must provide a callback to a function which 
+		/// will be automatically called per each bounding box in this tree.
+		/// Note that the callback will get info about the rotation Rot of the 
+		/// box, its position Pos, its size d, its level. Also you can pass generic
+		/// user data via a pointer.  
+		/// This is not implemented here, since there are no boxes in the base class,
+		/// but all children classes implementing some type of bounding box should implement this.
+		///  \return the number of scanned boxes.
+  virtual int TraverseBoundingBoxes( void callback(ChMatrix33<>& Rot,Vector& Pos,Vector& d,int level, void* userdata),
+									  void* userdata)
+				{return 0;};
+
+	
+		/// Compute bounding box (in model reference frame).
+		/// If a matrix Rot is not null, it should compute bounding box along
+		/// the rotated directions represented by that transformation matrix Rot.
+  virtual void GetBoundingBox(double& xmin, double& xmax, 
+							  double& ymin, double& ymax, 
+							  double& zmin, double& zmax, 
+							  ChMatrix33<>* Rot = NULL);
+
+
+  		/// Gets the pointer to the owner rigid body
+  ChBody* GetBody() {return m_body;}
+		/// Sets the pointer to the owner rigid body
+  void SetBody(ChBody* mbo) {m_body = mbo;}
+
+		/// Given pos&rot of body, this function recomputes the absolute-axis-aligned
+		/// bounding box in order to enclose all the geometries of the model.
+		/// Also initializes the ChAbsoluteAABB pointers, useful for sweep&prune.
+  void UpdateAbsoluteAABB(double envelope);
+
+
+public:
+
+  enum eChBuildState
+  { 
+	  ChC_BUILD_STATE_MODIFIED,  ///< someone added/modified geometry, so it requires tree rebuilding
+	  ChC_BUILD_STATE_PROCESSED  ///< after tree has been built, ready to use
+  };
+
+		/// Build state.  \see eChBuildState 
+  eChBuildState build_state;
+
+		/// Vector of pointers to geometric objects.
+  std::vector<ChGeometry*> geometries;
+	
+		/// Total number of geometric objects added
+  int num_geometries;
+	
+		/// Used by internal algorithms, contains the last accessed geometry.
+  ChGeometry *last_geometry;
+
+private:
+
+  ChBody* m_body;
+
+public:
+  ChAbsoluteAABB<ChCollisionTree> m_absoluteAABB;
+
+
+};
+
+
+
+
+
+//
+// ERROR CODES
+//
+
+
+const int ChC_OK = 0; 
+  // Used by all API routines upon successful completion except
+  // constructors and destructors
+
+const int ChC_ERR_MODEL_OUT_OF_MEMORY = -1; 
+  // Returned when an API function cannot obtain enough memory to
+  // store or process a ChCollisionTree object.
+
+const int ChC_ERR_OUT_OF_MEMORY = -2;
+  // Returned when a query cannot allocate enough storage to
+  // compute or hold query information.  In this case, the returned
+  // data should not be trusted.
+
+const int ChC_ERR_UNPROCESSED_MODEL = -3;
+  // Returned when an unprocessed model is passed to a function which
+  // expects only processed models, such as PQP_Collide() or
+  // PQP_Distance().
+
+const int ChC_ERR_BUILD_EMPTY_MODEL = -5; 
+  // Returned when EndModel() is called on a model to which no
+  // triangles have been added.  This is similar in spirit to the
+  // OUT_OF_SEQUENCE return code, except that the requested operation
+  // has FAILED -- the model remains "unprocessed", and the client may
+  // NOT use it in queries.
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCCompile.h b/SRC/ChronoEngine/collision/edgetempest/ChCCompile.h
new file mode 100644
index 0000000..2cafe7e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCCompile.h
@@ -0,0 +1,67 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_COMPILE_H
+#define CHC_COMPILE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCCompile.h
+// 
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+// prevents compiler warnings when PQP_REAL is float
+/*
+inline float sqrt(float x) { return (float)sqrt((double)x); }
+inline float cos(float x) { return (float)cos((double)x); }
+inline float sin(float x) { return (float)sin((double)x); }
+inline float fabs(float x) { return (float)fabs((double)x); }
+*/
+
+	
+	
+//-------------------------------------------------------------------------
+//
+// PQP_REAL
+//
+// This is the floating point type used throughout PQP.  doubles are
+// recommended, both for their precision and because the software has
+// mainly been tested using them.  However, floats appear to be faster 
+// (by 60% on some machines).
+//
+//-------------------------------------------------------------------------
+
+typedef double PQP_REAL;
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCGeometryCollider.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCGeometryCollider.cpp
new file mode 100644
index 0000000..2a04b33
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCGeometryCollider.cpp
@@ -0,0 +1,1434 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChCGeometryCollider.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <stdio.h>
+#include <cmath>
+
+#include "ChCGeometryCollider.h"
+#include "geometry/ChCTriangle.h"
+#include "geometry/ChCSphere.h"
+#include "geometry/ChCBox.h"
+#include "ChCOBB.h"
+
+#include "core/ChTrasform.h"
+
+#define COLL_PRECISION 0.000001
+
+
+using namespace chrono::collision;
+
+
+namespace chrono
+{
+namespace collision
+{
+
+
+
+int ChGeometryCollider::ComputeCollisions(
+							 ChGeometry& mgeo1,		///< first geometric primitive
+							 ChMatrix33<>* R1,			///< absolute rotation of first geometric primitive
+							 Vector* T1,			///< absolute position of first geometric primitive
+							 ChGeometry& mgeo2,		///< second geometric primitive
+							 ChMatrix33<>* R2,			///< absolute rotation of second geometric primitive
+							 Vector* T2,			///< absolute position of second geometric primitive
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 ChMatrix33<>* relRot,		///< relative rotation of mgeo2 respect to mgeo1, if available, for optimization
+							 Vector* relPos,		///< relative position of mgeo2 respect to mgeo1, if available, for optimization
+							 bool just_intersection	///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 )
+{
+
+//GetLog() << "  ChGeometryCollider::ComputeCollisions! geos:" << (int)&mgeo1 << " " << (int)&mgeo2 << "\n";
+
+	// Dispatch all subcases of geometry-geometry pairs..
+
+	if((mgeo1.GetClassType() == CH_GEOCLASS_TRIANGLE) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_TRIANGLE))
+	{
+		//***TO DO***
+		return 0;
+	}
+
+	if((mgeo1.GetClassType() == CH_GEOCLASS_SPHERE) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_SPHERE))
+	{
+		ChSphere* msph1 = (ChSphere*)&mgeo1;
+		ChSphere* msph2 = (ChSphere*)&mgeo2;
+		Vector c1, c2;
+		c1 = ChTrasform<>::TrasformLocalToParent(msph1->center, *T1, *R1);
+		c2 = ChTrasform<>::TrasformLocalToParent(msph2->center, *T2, *R2);
+		return ComputeSphereSphereCollisions(*msph1, &c1, *msph2, &c2, mcollider, just_intersection);
+	}
+
+	if((mgeo1.GetClassType() == CH_GEOCLASS_BOX) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_BOX))
+	{
+		ChBox* mbox1  = (ChBox*)&mgeo1;
+		ChBox* mbox2  = (ChBox*)&mgeo2;
+		return ComputeBoxBoxCollisions(*mbox1, R1, T1, *mbox2, R2, T2, mcollider, just_intersection);
+	}
+
+	if((mgeo1.GetClassType() == CH_GEOCLASS_SPHERE) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_TRIANGLE))
+	{
+		ChSphere*   msph   = (ChSphere*)&mgeo1;
+		ChTriangle* mtri = (ChTriangle*)&mgeo2;
+		Vector c1 = ChTrasform<>::TrasformLocalToParent(msph->center, *T1, *R1);
+		return ComputeSphereTriangleCollisions(*msph, &c1, *mtri, R2, T2,
+							mcollider, just_intersection, false);
+	}
+	if((mgeo1.GetClassType() == CH_GEOCLASS_TRIANGLE) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_SPHERE))
+	{
+		ChSphere*   msph   = (ChSphere*)&mgeo2;
+		ChTriangle* mtri = (ChTriangle*)&mgeo1;
+		Vector c2 = ChTrasform<>::TrasformLocalToParent(msph->center, *T2, *R2);
+		return ComputeSphereTriangleCollisions(*msph, &c2, *mtri, R1, T1,
+							mcollider, just_intersection, true);
+	}
+
+	if((mgeo1.GetClassType() == CH_GEOCLASS_SPHERE) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_BOX))
+	{
+		ChSphere* msph =  (ChSphere*)&mgeo1;
+		ChBox*    mbox =  (ChBox*)&mgeo2;
+		Vector c1 = ChTrasform<>::TrasformLocalToParent(msph->center, *T1, *R1);
+		return ComputeSphereBoxCollisions(*msph, &c1, *mbox, R2, T2,
+							mcollider, just_intersection, false);
+	}
+	if((mgeo1.GetClassType() == CH_GEOCLASS_BOX) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_SPHERE))
+	{
+		ChSphere* msph =  (ChSphere*)&mgeo2;
+		ChBox*    mbox =  (ChBox*)&mgeo1;
+		Vector c2 = ChTrasform<>::TrasformLocalToParent(msph->center, *T2, *R2);
+		return ComputeSphereBoxCollisions(*msph, &c2, *mbox, R1, T1,
+							mcollider, just_intersection, true);
+	}
+
+	if((mgeo1.GetClassType() == CH_GEOCLASS_BOX) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_TRIANGLE))
+	{
+		ChBox* mbox =		(ChBox*)&mgeo1;
+		ChTriangle* mtri =  (ChTriangle*)&mgeo2;
+		return ComputeBoxTriangleCollisions(*mbox, R1, T1, *mtri, R2, T2,
+							mcollider, just_intersection, false);
+	}
+	if((mgeo1.GetClassType() == CH_GEOCLASS_TRIANGLE) &&
+	   (mgeo2.GetClassType() == CH_GEOCLASS_BOX))
+	{
+		ChBox* mbox =		(ChBox*)&mgeo2;
+		ChTriangle* mtri =  (ChTriangle*)&mgeo1;
+		return ComputeBoxTriangleCollisions(*mbox, R2, T2, *mtri, R1, T1,
+							mcollider, just_intersection, true);
+	}
+
+	// default: this collision pair is not supported
+	return 0;
+}
+
+
+
+
+
+// SPHERE - SPHERE
+
+int ChGeometryCollider::ComputeSphereSphereCollisions(
+							 ChSphere& mgeo1,		///< first sphere
+							 Vector* c1,			///< absolute position of 1st
+							 ChSphere& mgeo2,		///< second sphere
+							 Vector* c2,			///< absolute position of 2nd
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection
+ 							 )
+{
+	Vector relPos = Vsub(*c2, *c1);
+	Vector dir = Vnorm(relPos);
+	double dist = Vlenght(relPos);
+	if (just_intersection)
+	{
+ 		 if (dist < (mgeo1.rad + mgeo2.rad))
+		 {
+ 			ChCollisionPair temp=ChCollisionPair(&mgeo1, &mgeo2);
+			mcollider.AddCollisionPair(&temp);
+			return 1;
+		 }
+	}
+	else
+	{
+		if (dist < CH_COLL_ENVELOPE+(mgeo1.rad + mgeo2.rad))
+		{
+			ChCollisionPair temp=ChCollisionPair(
+					&mgeo1, &mgeo2,						// geometries
+					Vadd(*c1, Vmul(dir,  mgeo1.rad)),	// p1
+					Vadd(*c2, Vmul(dir, -mgeo2.rad)),	// p2
+					dir);								// normal
+			mcollider.AddCollisionPair(&temp);
+			return 1;
+		}
+		
+	}
+
+	return 0;
+}
+
+
+
+
+
+
+int ChGeometryCollider::ComputeSphereTriangleCollisions(
+							 ChSphere& mgeo1,		///< sphere
+							 Vector* c1,			///< absolute position of 1st center
+							 ChTriangle& mgeo2,		///< triangle
+							 ChMatrix33<>* R2,			///< absolute roation of 2nd model
+							 Vector* T2,			///< absolute position of 2nd model
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection,///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 bool swap_pairs		///< if true, pairs are reported as Triangle-Sphere (triangle will be the main ref.)
+							 )
+{
+	Vector v_center  = *c1;
+	Vector v_1	     = ChTrasform<>::TrasformLocalToParent(mgeo2.p1, *T2, *R2);
+	Vector v_2	     = ChTrasform<>::TrasformLocalToParent(mgeo2.p2, *T2, *R2);
+	Vector v_3	     = ChTrasform<>::TrasformLocalToParent(mgeo2.p3, *T2, *R2);
+
+	Vector mnormal, mp1, mp2, ept;
+	Vector ver_cen;
+	double mdist = 10e20;
+	double tdist = 10e20;
+	double mu,mv;
+	bool is_into = true;
+	bool touched = false;
+
+			// test sphere-vertexes
+	ver_cen = Vsub(v_1, v_center);
+	tdist = -mgeo1.rad+ Vlenght(ver_cen);
+	if (tdist < 0)
+	{
+		touched = true;
+		mnormal = Vnorm(ver_cen);
+		mp1 = Vadd(v_center, Vmul(mnormal, mgeo1.rad));
+		mp2 = v_1;
+		mdist = tdist;
+	}
+	ver_cen = Vsub(v_2, v_center);
+	tdist = -mgeo1.rad+ Vlenght(ver_cen);
+	if (tdist < 0)
+		if (tdist < mdist)
+	{
+		touched = true;
+		mnormal = Vnorm(ver_cen);
+		mp1 = Vadd(v_center, Vmul(mnormal, mgeo1.rad));
+		mp2 = v_2;
+		mdist = tdist;
+	}
+	ver_cen = Vsub(v_3, v_center);
+	tdist = -mgeo1.rad + Vlenght(ver_cen);
+	if (tdist < 0)
+		if (tdist < mdist)
+	{
+		touched = true;
+		mnormal = Vnorm(ver_cen);
+		mp1 = Vadd(v_center, Vmul(mnormal, mgeo1.rad));
+		mp2 = v_3;
+		mdist = tdist;
+	}
+
+
+		// test sphere-plane
+	tdist = -mgeo1.rad + fabs(ChTriangle::PointTriangleDistance(v_center, v_1, v_2, v_3, mu,mv, is_into, ept));
+	if (is_into)
+		if (tdist<0)
+		if (tdist<mdist)
+		{
+			touched = true;
+			mnormal = Vnorm(Vsub(ept,v_center));
+			mp1=Vadd(v_center,  Vmul(mnormal, mgeo1.rad));
+			mp2= ept;
+			mdist = tdist;
+		}
+
+		// test edge-sphere
+	tdist = -mgeo1.rad + fabs(ChTriangle::PointLineDistance(v_center, v_1, v_2, mu, is_into));
+	if (is_into)
+		if (tdist<0)
+		if (tdist<mdist)
+		{
+			touched = true;
+			ept = Vadd(v_1,Vmul(Vsub(v_2,v_1), mu));
+			mnormal = Vnorm(Vsub(ept,v_center));
+			mp1= Vadd(v_center,  Vmul(mnormal, mgeo1.rad));
+			mp2= ept;
+			mdist = tdist;
+		}
+	tdist = -mgeo1.rad + fabs(ChTriangle::PointLineDistance(v_center, v_2, v_3, mu, is_into));
+	if (is_into)
+		if (tdist<0)
+		if (tdist<mdist)
+		{
+			touched = true;
+			ept = Vadd(v_2,Vmul(Vsub(v_3,v_2), mu));
+			mnormal = Vnorm(Vsub(ept,v_center));
+			mp1= Vadd(v_center,  Vmul(mnormal, mgeo1.rad));
+			mp2= ept;
+			mdist = tdist;
+		}
+	tdist = -mgeo1.rad + fabs(ChTriangle::PointLineDistance(v_center, v_3, v_1, mu, is_into));
+	if (is_into)
+		if (tdist<0)
+		if (tdist<mdist)
+		{
+			touched = true;
+			ept = Vadd(v_3,Vmul(Vsub(v_1,v_3), mu));
+			mnormal = Vnorm(Vsub(ept,v_center));
+			mp1= Vadd(v_center,  Vmul(mnormal, mgeo1.rad));
+			mp2= ept;
+			mdist = tdist;
+		}
+
+	if (touched)
+	{
+		ChCollisionPair mcoll(
+				&mgeo1, &mgeo2,
+				mp1,
+				mp2,
+				mnormal);
+		if (swap_pairs)
+			mcoll.SwapGeometries();
+		mcollider.AddCollisionPair(&mcoll);
+
+		return 1;
+	}
+
+
+	return 0;
+}
+
+
+
+  class BoxBoxCollisionTest2
+  {
+
+  public:
+
+
+    // Collision Test.
+    //
+    // @param p_a       Center of box A in WCS.
+    // @param p_b       Center of box B in WCS
+    // @param R_a       Box A's orientation in WCS
+    // @param R_b       Box B's orientation in WCS
+    // @param a         Extents of box A, i.e. half edge sizes.
+    // @param b         Extents of box B, i.e. half edge sizes.
+    // @param envelope  The size of the collision envelope. If cloest point are separted by more than this distance then there is no contact.
+    // @param p         Pointer to array of contact points, must have room for at least eight vectors.
+    // @param n         Upon return this argument holds the contact normal pointing from box A towards box B.
+    // @param distance  Pointer to array of separation (or penetration) distances. Must have room for at least eight values.
+	//
+    // @return          If contacts exist then the return value indicates the number of contacts, if no contacts exist the return valeu is zero.
+
+
+    static unsigned int BoxBoxContacts(
+      Vector&  p_a, ChMatrix33<>& R_a, Vector const & ext_a,
+      Vector&  p_b, ChMatrix33<>& R_b, Vector const & ext_b,
+      double const & envelope,
+      Vector * p,
+	  Vector & n,
+	  double * distances
+      )
+    {
+      assert(p);
+      assert(distances);
+
+	  unsigned int cnt = 0;
+
+      //--- Sign lookup table, could be precomputed!!!
+      Vector sign[8];
+      for(unsigned int mask=0;mask<8;++mask)
+      {
+        sign[mask](0) = (mask&0x0001)?1:-1;
+        sign[mask](1) = ((mask>>1)&0x0001)?1:-1;
+        sign[mask](2) = ((mask>>2)&0x0001)?1:-1;
+      }
+      //--- extract axis of boxes in WCS
+      Vector A[3];
+      A[0].x = R_a(0,0);   A[0].y = R_a(1,0);   A[0].z = R_a(2,0);
+      A[1].x = R_a(0,1);   A[1].y = R_a(1,1);   A[1].z = R_a(2,1);
+      A[2].x = R_a(0,2);   A[2].y = R_a(1,2);   A[2].z = R_a(2,2);
+      Vector B[3];
+      B[0].x = R_b(0,0);   B[0].y = R_b(1,0);   B[0].z = R_b(2,0);
+      B[1].x = R_b(0,1);   B[1].y = R_b(1,1);   B[1].z = R_b(2,1);
+      B[2].x = R_b(0,2);   B[2].y = R_b(1,2);   B[2].z = R_b(2,2);
+
+      //--- To compat numerical round-offs, these tend to favor edge-edge
+      //--- cases, when one really rather wants a face-case. Truncating
+      //--- seems to let the algorithm pick face cases over edge-edge
+      //--- cases.
+      unsigned int i;
+
+      for( i=0;i<3;++i)
+        for(unsigned int j=0;j<3;++j)
+        {
+          if(fabs(A[i](j))<10e-7)
+            A[i](j) = 0.;
+          if(fabs(B[i](j))<10e-7)
+            B[i](j) = 0.;
+        }
+
+      Vector a[8];
+      Vector b[8];
+      //--- corner points of boxes in WCS
+      for( i=0;i<8;++i)
+      {
+        a[i] = A[2]*(sign[i](2)*ext_a(2)) + A[1]*(sign[i](1)*ext_a(1)) + A[0]*(sign[i](0)*ext_a(0)) + p_a;
+        b[i] = B[2]*(sign[i](2)*ext_b(2)) + B[1]*(sign[i](1)*ext_b(1)) + B[0]*(sign[i](0)*ext_b(0)) + p_b;
+	  }
+      //--- Potential separating axes in WCS
+      Vector axis[15];
+      axis[0] = A[0];
+      axis[1] = A[1];
+      axis[2] = A[2];
+      axis[3] = B[0];
+      axis[4] = B[1];
+      axis[5] = B[2];
+      axis[6].Cross(A[0],B[0]);
+      if(axis[6](0)==0 && axis[6](1)==0 && axis[6](2)==0)
+        axis[6] = A[0];
+      else
+        axis[6] /= sqrt(axis[6].Dot(axis[6]));
+      axis[7].Cross(A[0],B[1]);
+      if(axis[7](0)==0 && axis[7](1)==0 && axis[7](2)==0)
+        axis[7] = A[0];
+      else
+        axis[7] /= sqrt(axis[7].Dot(axis[7]));
+      axis[8].Cross(A[0],B[2]);
+      if(axis[8](0)==0 && axis[8](1)==0 && axis[8](2)==0)
+        axis[8] = A[0];
+      else
+        axis[8] /= sqrt(axis[8].Dot(axis[8]));
+      axis[9].Cross(A[1],B[0]);
+      if(axis[9](0)==0 && axis[9](1)==0 && axis[9](2)==0)
+        axis[9] = A[1];
+      else
+        axis[9] /= sqrt(axis[9].Dot(axis[9]));
+      axis[10].Cross(A[1],B[1]);
+      if(axis[10](0)==0 && axis[10](1)==0 && axis[10](2)==0)
+        axis[10] = A[1];
+      else
+        axis[10] /= sqrt(axis[10].Dot(axis[10]));
+      axis[11].Cross(A[1],B[2]);
+      if(axis[11](0)==0 && axis[11](1)==0 && axis[11](2)==0)
+        axis[11] = A[1];
+      else
+        axis[11] /= sqrt(axis[11].Dot(axis[11]));
+      axis[12].Cross(A[2],B[0]);
+      if(axis[12](0)==0 && axis[12](1)==0 && axis[12](2)==0)
+        axis[12] = A[2];
+      else
+        axis[12] /= sqrt(axis[12].Dot(axis[12]));
+      axis[13].Cross(A[2],B[1]);
+      if(axis[13](0)==0 && axis[13](1)==0 && axis[13](2)==0)
+        axis[13] = A[2];
+      else
+        axis[13] /= sqrt(axis[13].Dot(axis[13]));
+      axis[14].Cross(A[2],B[2]);
+      if(axis[14](0)==0 && axis[14](1)==0 && axis[14](2)==0)
+        axis[14] = A[2];
+      else
+        axis[14] /= sqrt(axis[14].Dot(axis[14]));
+      //--- project vertices of boxes onto separating axis
+      double min_proj_a[15];
+      double min_proj_b[15];
+      double max_proj_a[15];
+      double max_proj_b[15];
+      for(i=0;i<15;++i)
+      {
+        min_proj_a[i] = min_proj_b[i] = 10e30;
+        max_proj_a[i] = max_proj_b[i] = -10e30;
+      }
+      for(i=0;i<15;++i)
+      {
+        for(unsigned int j=0;j<8;++j)
+        {
+          double proj_a = a[j].Dot(axis[i]);
+          double proj_b = b[j].Dot(axis[i]);
+          min_proj_a[i] = ChMin(min_proj_a[i],proj_a);
+          max_proj_a[i] = ChMax(max_proj_a[i],proj_a);
+          min_proj_b[i] = ChMin(min_proj_b[i],proj_b);
+          max_proj_b[i] = ChMax(max_proj_b[i],proj_b);
+        }
+        //--- test for valid separation axis if so return
+        if (min_proj_a[i] > (max_proj_b[i]+envelope) ||   min_proj_b[i] > (max_proj_a[i]+envelope))
+          return 0;
+      }
+      //--- Compute box overlaps along all 15 separating axes, and determine
+      //--- minimum overlap
+      double overlap[15];
+      double minimum_overlap = -10e30;
+      unsigned int minimum_axis = 15;
+      bool flip_axis[15];
+      //--- Notice that edge-edge cases are testet last, so face cases
+      //--- are favored over edge-edge cases
+      for(i=0;i<15;++i)
+      {
+        flip_axis[i] = false;
+        overlap[i] = 10e30;
+        if(max_proj_a[i] <= min_proj_b[i])
+        {
+          overlap[i] = ChMin( overlap[i], min_proj_b[i] - max_proj_a[i] );
+          if(overlap[i]>minimum_overlap)
+          {
+            minimum_overlap = overlap[i];
+            minimum_axis = i;
+            flip_axis[i] = false;
+          }
+        }
+        if(max_proj_b[i] <= min_proj_a[i])
+        {
+          overlap[i] = ChMin( overlap[i], min_proj_a[i] - max_proj_b[i] );
+          if(overlap[i]>minimum_overlap)
+          {
+            minimum_overlap = overlap[i];
+            minimum_axis = i;
+            flip_axis[i] = true;
+          }
+        }
+        if(min_proj_a[i] <= min_proj_b[i] &&  min_proj_b[i] <= max_proj_a[i])
+        {
+          overlap[i] = ChMin( overlap[i], -(max_proj_a[i] - min_proj_b[i]) );
+          if(overlap[i]>minimum_overlap)
+          {
+            minimum_overlap = overlap[i];
+            minimum_axis = i;
+            flip_axis[i] = false;
+          }
+        }
+        if(min_proj_b[i] <= min_proj_a[i] &&  min_proj_a[i] <= max_proj_b[i])
+        {
+          overlap[i] = ChMin(overlap[i], -(max_proj_b[i] - min_proj_a[i]) );
+          if(overlap[i]>minimum_overlap)
+          {
+            minimum_overlap = overlap[i];
+            minimum_axis = i;
+            flip_axis[i] = true;
+          }
+        }
+      }
+      if(minimum_overlap>envelope)
+        return 0;
+      //--- Take care of normals, so they point in the correct direction.
+      for(i=0;i<15;++i)
+      {
+        if(flip_axis[i])
+          axis[i] = - axis[i];
+      }
+      //--- At this point we know that a projection along axis[minimum_axis] with
+      //--- value minimum_overlap will lead to non-penetration of the two boxes. We
+      //--- just need to generate the contact points!!!
+      unsigned int corners_inside = 0;
+      unsigned int corners_B_in_A = 0;
+      unsigned int corners_A_in_B = 0;
+      bool AinB[8];
+      bool BinA[8];
+      Coordsys WCStoA(p_a, R_a.Get_A_quaternion());
+	  Coordsys WCStoB(p_b, R_b.Get_A_quaternion());
+      Vector eps_a = ext_a + Vector(envelope,envelope,envelope);
+      Vector eps_b = ext_b + Vector(envelope,envelope,envelope);
+      for(i=0;i<8;++i)
+      {
+		Vector a_in_B = WCStoB.TrasformParentToLocal(a[i]);//ChTrasform<>::TrasformParentToLocal(a[i], p_a, R_a);
+		// = WCStoB.TrasformParentToLocal(a[i]);
+        Vector abs_a(fabs(a_in_B.x),fabs(a_in_B.y),fabs(a_in_B.z) ) ;
+        if(abs_a <= eps_b)
+        {
+          ++corners_inside;
+          ++corners_A_in_B;
+          AinB[i] = true;
+        }
+        else
+          AinB[i] = false;
+        Vector b_in_A = WCStoA.TrasformParentToLocal(b[i]);//= ChTrasform<>::TrasformParentToLocal(b[i], p_b, R_b);
+		// = WCStoA.TrasformParentToLocal(b[i]);
+        Vector abs_b(fabs(b_in_A.x),fabs(b_in_A.y),fabs(b_in_A.z) );
+        if(abs_b <= eps_a)
+        {
+          ++corners_inside;
+          ++corners_B_in_A;
+          BinA[i] = true;
+        }
+        else
+          BinA[i] = false;
+      }
+      //--- This may indicate an edge-edge case
+      if(minimum_axis >= 6)
+      {
+        //--- However the edge-edge case may not be the best choice,
+        //--- so if we find a corner point of one box being inside
+        //--- the other, we fall back to use the face case with
+        //--- minimum overlap.
+        if(corners_inside)//--- Actually we only need to test end-points of edge for inclusion (4 points instead of 16!!!).
+        {
+          minimum_overlap = -10e30;
+          minimum_axis = 15;
+          for(unsigned int i=0;i<6;++i)
+          {
+            if(overlap[i]>minimum_overlap)
+            {
+              minimum_overlap = overlap[i];
+              minimum_axis = i;
+            }
+          }
+        }
+      }
+
+      //--- now we can safely pick the contact normal, since we
+      //--- know wheter we have a face-case or edge-edge case.
+      n = axis[minimum_axis];
+
+      //--- This is definitely an edge-edge case
+      if(minimum_axis>=6)
+      {
+        //--- Find a point p_a on the edge from box A.
+        for(unsigned int i=0;i<3;++i)
+          if(n.Dot(A[i]) > 0.)
+            p_a += ext_a(i)*A[i];
+          else
+            p_a -= ext_a(i)*A[i];
+        //--- Find a point p_b on the edge from box B.
+        for(int ci=0;ci<3;++ci)
+          if(n.Dot(B[ci]) < 0.)
+            p_b += ext_b(ci)*B[ci];
+          else
+            p_b -= ext_b(ci)*B[ci];
+
+        //--- Determine the indices of two unit edge direction vectors (columns
+        //--- of rotation matrices in WCS).
+        int columnA = ((minimum_axis)-6)/3;
+        int columnB = ((minimum_axis)-6)%3;
+        double s,t;
+        //--- Compute the edge-paramter values s and t corresponding to the closest
+        //--- points between the two infinite lines parallel to the two edges.
+        ClosestPointsBetweenLines()(p_a,A[columnA],p_b,B[columnB],s,t);
+        //--- Use the edge parameter values to compute the closest
+        //--- points between the two edges.
+        p_a += A[columnA]*s;
+        p_b += B[columnB]*t;
+        //--- Let the contact point be given by the mean of the closest points.
+        p[0] = (p_a + p_b)*.5;
+        distances[0] = overlap[minimum_axis];
+        return 1;
+      }
+      //--- This is a face-``something else'' case, we actually already have taken
+      //--- care of all corner points, but there might be some edge-edge crossings
+      //--- generating contact points
+
+
+
+      //--- Make sure that we work in the frame of the box that defines the contact
+      //--- normal. This coordinate frame is nice, because the contact-face is a axis
+      //--- aligned rectangle. We will refer to this frame as the reference frame, and
+      //--- use the letter 'r' or 'R' for it. The other box is named the incident box,
+      //--- its closest face towards the reference face is called the incidient face, and
+      //--- is denoted by the letter 'i' or 'I'.
+      Vector * R_r,* R_i;  //--- Box direction vectors in WCS
+      Vector ext_r,ext_i;          //--- Box extents
+      Vector p_r,p_i;              //--- Box centers in WCS
+      bool * incident_inside;    //--- corner inside state of incident box.
+      if (minimum_axis  < 3)
+      {
+        //--- This means that box A is defining the reference frame
+        R_r = A;
+        R_i = B;
+        p_r = p_a;
+        p_i = p_b;
+        ext_r = ext_a;
+        ext_i = ext_b;
+        incident_inside = BinA;
+      }
+      else
+      {
+        //--- This means that box B is defining the reference frame
+        R_r = B;
+        R_i = A;
+        p_r = p_b;
+        p_i = p_a;
+        ext_r = ext_b;
+        ext_i = ext_a;
+        incident_inside = AinB;
+      }
+      //--- Following vectors are used for computing the corner points of the incident
+      //--- face. At first they are used to determine the axis of the incidient box
+      //--- pointing towards the reference box.
+      //---
+      //--- n_r_wcs = normal pointing away from reference frame in WCS coordinates.
+      //--- n_r = normal vector of reference face dotted with axes of incident box.
+      //--- abs_n_r = absolute values of n_r.
+      Vector n_r_wcs,n_r,abs_n_r;
+      if (minimum_axis < 3)
+      {
+        n_r_wcs = n;
+      }
+      else
+      {
+        n_r_wcs = -n;
+      }
+
+      //--- Each of these is a measure for how much the axis' of the incident box
+      //--- points in the direction of n_r_wcs. The largest absolute value give
+      //--- us the axis along which we will find the closest face towards the reference
+      //--- box. The sign will tell us if we should take the positive or negative
+      //--- face to get the closest incident face.
+      n_r(0) = R_i[0].Dot(n_r_wcs);
+      n_r(1) = R_i[1].Dot(n_r_wcs);
+      n_r(2) = R_i[2].Dot(n_r_wcs);
+      abs_n_r(0) = fabs (n_r(0));
+      abs_n_r(1) = fabs (n_r(1));
+      abs_n_r(2) = fabs (n_r(2));
+      //--- Find the largest compontent of abs_n_r: This corresponds to the normal
+      //--- for the indident face. The axis number is stored in a3. the other
+      //--- axis numbers of the indicent face are stored in a1,a2.
+      int a1,a2,a3;
+      if (abs_n_r(1) > abs_n_r(0))
+      {
+        if (abs_n_r(1) > abs_n_r(2))
+        {
+          a1 = 2; a2 = 0; a3 = 1;
+        }
+        else
+        {
+          a1 = 0; a2 = 1; a3 = 2;
+        }
+      }
+      else
+      {
+        if (abs_n_r(0) > abs_n_r(2))
+        {
+          a1 = 1; a2 = 2; a3 = 0;
+        }
+        else
+        {
+          a1 = 0; a2 = 1; a3 = 2;
+        }
+      }
+      //--- Now we have information enough to determine the incidient face, that means we can
+      //--- compute the center point of incident face in WCS coordinates.
+
+      int plus_sign[3];
+      Vector center_i_wcs;
+      if (n_r(a3) < 0)
+      {
+        center_i_wcs = p_i + ext_i(a3) * R_i[a3];
+        plus_sign[a3] = 1;
+      }
+      else
+      {
+        center_i_wcs = p_i - ext_i(a3) * R_i[a3];
+        plus_sign[a3] = 0;
+      }
+      //--- Compute difference of center point of incident face with center of reference coordinates.
+      Vector center_ir = center_i_wcs - p_r;
+      //--- Find the normal and non-normal axis numbers of the reference box
+      int code1,code2,code3;
+      if (minimum_axis < 3)
+        code3 = minimum_axis;  //012
+      else
+        code3 = minimum_axis-3;  //345
+      if (code3==0)
+      {
+        code1 = 1;
+        code2 = 2;
+      }
+      else if (code3==1)
+      {
+        code1 = 2;
+        code2 = 0;
+      }
+      else
+      {
+        code1 = 0;
+        code2 = 1;
+      }
+      //--- Find the four corners of the incident face, in reference-face coordinates
+      double quad[8]; //--- 2D coordinate of incident face (stored as x,y pairs).
+      bool inside[4];     //--- inside state of the four coners of the quad
+      //--- Project center_ri onto reference-face coordinate system (has origo
+      //--- at the center of the reference face, and the two orthogonal unit vectors
+      //--- denoted by R_r[code1] and R_r[code2] spaning the face-plane).
+      double c1 = R_r[code1].Dot( center_ir);
+      double c2 = R_r[code2].Dot( center_ir);
+      //--- Compute the projections of the axis spanning the incidient
+      //--- face, onto the axis spanning the reference face.
+      //---
+      //--- This will allow us to determine the coordinates in the reference-face
+      //--- when we step along a direction of the incident face given by either
+      //--- a1 or a2.
+      double m11 = R_r[code1].Dot( R_i[a1]);
+      double m12 = R_r[code1].Dot( R_i[a2]);
+      double m21 = R_r[code2].Dot( R_i[a1]);
+      double m22 = R_r[code2].Dot( R_i[a2]);
+      {
+        double k1 = m11 * ext_i(a1);
+        double k2 = m21 * ext_i(a1);
+        double k3 = m12 * ext_i(a2);
+        double k4 = m22 * ext_i(a2);
+
+        plus_sign[a1] = 0;
+        plus_sign[a2] = 0;
+        unsigned int mask = ( (plus_sign[a1]<<a1) |  (plus_sign[a2]<<a2) |  (plus_sign[a3]<<a3));
+        inside[0] = incident_inside[ mask ];
+
+        quad[0] = c1 - k1 - k3;
+        quad[1] = c2 - k2 - k4;
+
+        plus_sign[a1] = 0;
+        plus_sign[a2] = 1;
+        mask = (plus_sign[a1]<<a1 |  plus_sign[a2]<<a2 |  plus_sign[a3]<<a3);
+        inside[1] = incident_inside[ mask ];
+
+        quad[2] = c1 - k1 + k3;
+        quad[3] = c2 - k2 + k4;
+
+        plus_sign[a1] = 1;
+        plus_sign[a2] = 1;
+        mask = (plus_sign[a1]<<a1 |  plus_sign[a2]<<a2 |  plus_sign[a3]<<a3);
+        inside[2] = incident_inside[ mask ];
+
+        quad[4] = c1 + k1 + k3;
+        quad[5] = c2 + k2 + k4;
+
+        plus_sign[a1] = 1;
+        plus_sign[a2] = 0;
+        mask = (plus_sign[a1]<<a1 |  plus_sign[a2]<<a2 |  plus_sign[a3]<<a3);
+        inside[3] = incident_inside[ mask ];
+
+        quad[6] = c1 + k1 - k3;
+        quad[7] = c2 + k2 - k4;
+      }
+      //--- find the size of the reference face
+      double rect[2];
+      rect[0] = ext_r(code1);
+      rect[1] = ext_r(code2);
+
+      //--- Intersect the edges of the incident and the reference face
+      double crossings[16];
+      unsigned int edge_crossings = RectQuadEdgeIntersectionTest()(envelope,rect,quad,inside,crossings);
+      assert(edge_crossings<=8);
+
+      if(!corners_inside && !edge_crossings)
+        return 0;
+
+      //--- Convert the intersection points into reference-face coordinates,
+      //--- and compute the contact position and depth for each point.
+      double det1 = 1./(m11*m22 - m12*m21);
+      m11 *= det1;
+      m12 *= det1;
+      m21 *= det1;
+      m22 *= det1;
+
+      for (unsigned int j=0; j < edge_crossings; ++j)
+      {
+        //--- Get coordinates of edge-edge crossing point in reference face coordinate system.
+        double p0 = crossings[j*2] - c1;
+        double p1 = crossings[j*2+1] - c2;
+        //--- Compute intersection point in (almost) WCS. Actually we have
+        //--- displaced origin to center of reference frame box
+        double k1 =  m22*p0 - m12*p1;
+        double k2 = -m21*p0 + m11*p1;
+        Vector point = center_ir + k1*R_i[a1] + k2*R_i[a2];
+        //--- Depth of intersection point
+        double depth = n_r_wcs.Dot(point) - ext_r(code3);
+        if(depth<envelope)
+        {
+          p[cnt] = point + p_r;//--- Move origin from center of reference frame box to WCS
+          distances[cnt] = depth;
+          ++cnt;
+        }
+      }
+      //      assert((corners_inside + cnt)<=8);//--- If not we are in serious trouble!!!
+      //--- I think there is a special case, if corners_inside = 8 and
+      //--- corners_in_A = 4 and corners_in_B = 4, then there really
+      //--- can only be 4 contacts???
+
+      if(corners_inside)
+      {
+        unsigned int start_corner_A = cnt;
+        unsigned int end_corner_A = cnt;
+
+        //--- Compute Displacement of contact plane from origin of WCS, the
+        //--- contact plane is equal to the face plane of the reference box
+        double w =   ext_r(code3) +  n_r_wcs.Dot(p_r);
+
+        if(corners_A_in_B)
+        {
+          for (unsigned int i=0; i < 8; ++i)
+          {
+            if(AinB[i])
+            {
+              Vector point = a[i];
+              double depth = n_r_wcs.Dot(point) - w;
+              if(depth<envelope)
+              {
+                p[cnt] = point;
+                distances[cnt] = depth;
+                ++cnt;
+              }
+            }
+          }
+          end_corner_A = cnt;
+        }
+        if(corners_B_in_A)
+        {
+          for (unsigned int i=0; i < 8; ++i)
+          {
+            if(BinA[i])
+            {
+              Vector point = b[i];
+              bool redundant = false;
+              for(unsigned int j=start_corner_A;j<end_corner_A;++j)
+              {
+                if( p[j].Equals(point,envelope) )
+                {
+                  redundant = true;
+                  break;
+                }
+              }
+              if(redundant)
+                continue;
+              double depth = n_r_wcs.Dot(point) - w;
+              if(depth<envelope)
+              {
+                p[cnt] = point;
+                distances[cnt] = depth;
+                ++cnt;
+              }
+            }
+          }
+        }
+      }
+      //      assert(cnt<=8);//--- If not we are in serious trouble!!!
+      return cnt;
+    };
+
+  protected:
+
+    struct ClosestPointsBetweenLines
+    {
+      void operator()(Vector & pA,Vector & uA,Vector & pB,Vector & uB,double & s,double & t)
+      {
+        Vector r = pB - pA;
+        double k = uA.Dot(uB);
+        double q1 = uA.Dot(r);
+        double q2 = -uB.Dot(r);
+        double w = 1 - k*k;
+        s = 0;  t = 0;
+        if(fabs(w) > COLL_PRECISION)
+        {
+          s = (q1 + k*q2)/w;
+          t = (q2 + k*q1)/w;
+        }
+      }
+    };
+
+
+    struct RectQuadEdgeIntersectionTest
+    {
+      int operator()(double const & envelope, double * rect, double * quad, bool * inside, double * ret)
+      {
+        int cnt = 0;
+        double * r = ret;
+        {
+          //--- Test the four edges of the quad for crossing the edges of the rect.
+          double qx0,qy0,qx1,qy1,tst;
+          double * q = quad;
+          for(int i=0;i<4;++i)
+          {
+            qx0 = *q;     ++q;
+            qy0 = *q;     ++q;
+            double * nextq = (i==3)?quad:q;
+            qx1 = *nextq; ++nextq;
+            qy1 = *nextq;
+            bool inside0 = inside[i];
+            bool inside1 = inside[(i+1)%4];
+            if(inside0 && inside1)
+              continue;
+            double dx = (qx1-qx0);
+            double dy = (qy1-qy0);
+            if(dx)
+            {
+              double alpha = dy/dx;
+              tst = - rect[0];     //--- left side
+              if( ((qx0 < tst) && (qx1 > tst)) || ((qx0 > tst) && (qx1 < tst)) )
+              {
+                double qxt = -rect[0];
+                double qyt = qy0 + (qxt-qx0)*alpha;
+                if( (-rect[1] < qyt) &&   (qyt < rect[1]))
+                {
+                  *r = qxt; ++r;
+                  *r = qyt; ++r;
+                  ++cnt;
+                }
+              }
+              tst = rect[0];
+              if( ((qx0 < tst) && (qx1 > tst)) || ((qx0 > tst) && (qx1 < tst)) )
+              {
+                double qxt = rect[0];
+                double qyt = qy0 + (qxt-qx0)*alpha;
+                if( (-rect[1] < qyt) &&   (qyt < rect[1]))
+                {
+                  *r = qxt; ++r;
+                  *r = qyt; ++r;
+                  ++cnt;
+                }
+              }
+            }
+            if(dy)
+            {
+              double inv_alpha = dx/dy;
+              tst = - rect[1];     //--- bottom side
+              if( ((qy0 < tst) && (qy1 > tst)) || ((qy0 > tst) && (qy1 < tst)) )
+              {
+                double qyt = -rect[1];
+                double qxt = qx0 + (qyt-qy0)*inv_alpha;
+                if( (-rect[0] < qxt)&&(qxt < rect[0]))
+                {
+                  *r = qxt;  ++r;
+                  *r = qyt;  ++r;
+                  ++cnt;
+                }
+              }
+              tst =  rect[1];     //--- top side
+              if( ((qy0 < tst) && (qy1 > tst)) || ((qy0 > tst) && (qy1 < tst)) )
+              {
+                double qyt = rect[1];
+                double qxt = qx0 + (qyt-qy0)*inv_alpha;
+                if( (-rect[0] < qxt)&&(qxt < rect[0]))
+                {
+                  *r = qxt;  ++r;
+                  *r = qyt;  ++r;
+                  ++cnt;
+                }
+              }
+            }
+          }
+        }
+        return cnt;
+      };
+
+
+  };//End of class
+
+};
+
+
+
+
+int ChGeometryCollider::ComputeBoxBoxCollisions(
+							 ChBox& mgeo1,			///< box 1
+							 ChMatrix33<>* R1,			///< absolute rotation of 1st model (with box 1)
+							 Vector* T1,			///< absolute position of 1st model (with box 1)
+							 ChBox& mgeo2,			///< box 2
+							 ChMatrix33<>* R2,			///< absolute rotation of 2nd model (with box 2)
+							 Vector* T2,			///< absolute position of 2nd model (with box 2)
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection ///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 )
+{
+	if (just_intersection)
+	{
+		ChMatrix33<> relRot;
+		relRot.MatrTMultiply(*R1, *R2);
+		Vector relPos = R1->MatrT_x_Vect((*T2)-(*T1));
+
+		if (CHOBB::OBB_Overlap(relRot, relPos, mgeo1.Size, mgeo2.Size))
+		{
+			ChCollisionPair temp=ChCollisionPair(&mgeo1, &mgeo2);
+			mcollider.AddCollisionPair(&temp);
+			return 1;
+		}
+	}
+	else
+	{
+		double ArrDist[12]; // 8 should be enough
+		Vector ArrP[12];	// 8 should be enough
+		Vector mnormal;
+
+		ChMatrix33<> aBox1Rot = (*R1) * mgeo1.Rot;
+		ChMatrix33<> aBox2Rot = (*R2) * mgeo2.Rot;
+		Vector aBox1Pos = ChTrasform<>::TrasformLocalToParent(mgeo1.Pos, (*T1), (*R1));
+		Vector aBox2Pos = ChTrasform<>::TrasformLocalToParent(mgeo2.Pos, (*T2), (*R2));
+
+		int ncontacts  = BoxBoxCollisionTest2::BoxBoxContacts(
+								aBox1Pos, aBox1Rot, mgeo1.Size,
+								aBox2Pos, aBox2Rot, mgeo2.Size,
+								CH_COLL_ENVELOPE, ArrP, mnormal, ArrDist);
+
+		for (int i=0; i < ncontacts; i++)
+		{
+			if (ArrDist[i]<CH_COLL_ENVELOPE){
+				ChCollisionPair temp=ChCollisionPair(
+						&mgeo1, &mgeo2,	// geometries
+						Vadd(ArrP[i], Vmul(mnormal, -ArrDist[i])),
+						ArrP[i],
+						mnormal);	// normal
+				mcollider.AddCollisionPair(&temp);
+			}
+		}
+	}
+	return 0;
+}
+
+
+
+
+			/// SPHERE - BOX specific case
+			///
+int ChGeometryCollider::ComputeSphereBoxCollisions(
+							 ChSphere& mgeo1,		///< sphere
+							 Vector* c1,			///< absolute position of center
+							 ChBox& mgeo2,			///< box
+							 ChMatrix33<>* R2,			///< absolute rotation of 2nd model (with box)
+							 Vector* T2,			///< absolute position of 2nd model (with box)
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection,///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 bool swap_pairs		///< if true, pairs are reported as Triangle-Sphere (triangle will be the main ref.)
+							 )
+{
+	ChMatrix33<> aBoxRot = (*R2) * mgeo2.Rot;
+	Vector aBoxPos = ChTrasform<>::TrasformLocalToParent(mgeo2.Pos, (*T2), (*R2));
+
+	Vector relC = ChTrasform<>::TrasformParentToLocal(*c1, aBoxPos, aBoxRot);
+
+	if (just_intersection)
+	{
+		if( ((fabs(relC.x) <= mgeo2.Size.x + mgeo1.rad)  &&
+			 (fabs(relC.y) <= mgeo2.Size.y ) &&
+			 (fabs(relC.z) <= mgeo2.Size.z ) )  ||
+			((fabs(relC.y) <= mgeo2.Size.y + mgeo1.rad)  &&
+			 (fabs(relC.x) <= mgeo2.Size.x ) &&
+			 (fabs(relC.z) <= mgeo2.Size.z ) )  ||
+			((fabs(relC.z) <= mgeo2.Size.z + mgeo1.rad)  &&
+			 (fabs(relC.x) <= mgeo2.Size.x ) &&
+			 (fabs(relC.y) <= mgeo2.Size.y ) )  ||
+			((sqrt(pow(fabs(relC.x)-mgeo2.Size.x,2)+pow(fabs(relC.y)-mgeo2.Size.y,2)) <= mgeo1.rad)  &&
+			 (fabs(relC.z) <= mgeo2.Size.z ) )  ||
+			((sqrt(pow(fabs(relC.y)-mgeo2.Size.y,2)+pow(fabs(relC.z)-mgeo2.Size.z,2)) <= mgeo1.rad)  &&
+			 (fabs(relC.x) <= mgeo2.Size.x ) )  ||
+			((sqrt(pow(fabs(relC.z)-mgeo2.Size.z,2)+pow(fabs(relC.x)-mgeo2.Size.x,2)) <= mgeo1.rad)  &&
+			 (fabs(relC.y) <= mgeo2.Size.y ) )  ||
+			((sqrt(pow(fabs(relC.x)-mgeo2.Size.x,2)+pow(fabs(relC.y)-mgeo2.Size.y,2)+pow(fabs(relC.z)-mgeo2.Size.z,2)) <= mgeo1.rad) )
+		  )
+		{
+			ChCollisionPair temp=ChCollisionPair(&mgeo1, &mgeo2);
+
+			mcollider.AddCollisionPair(&temp);
+			return 1;
+		}
+	}
+	else
+	{
+		Vector pt_loc;
+		bool done = false;
+		double dist = 0;
+
+		if ( (fabs(relC.x) <= mgeo2.Size.x + mgeo1.rad)  &&
+			 (fabs(relC.y) <= mgeo2.Size.y ) &&
+			 (fabs(relC.z) <= mgeo2.Size.z ) )
+			if( relC.x >=0)	{
+				pt_loc = relC; pt_loc.x =  mgeo2.Size.x; done = true;
+			}
+			else	{
+				pt_loc = relC; pt_loc.x = -mgeo2.Size.x; done = true;
+			}
+		if (!done)
+		if ( (fabs(relC.y) <= mgeo2.Size.y + mgeo1.rad)  &&
+			 (fabs(relC.z) <= mgeo2.Size.z ) &&
+			 (fabs(relC.x) <= mgeo2.Size.x ) )
+			if( relC.y >=0)	{
+				pt_loc = relC; pt_loc.y =  mgeo2.Size.y; done = true;
+			}
+			else	{
+				pt_loc = relC; pt_loc.y = -mgeo2.Size.y; done = true;
+			}
+		if (!done)
+		if ( (fabs(relC.z) <= mgeo2.Size.z + mgeo1.rad)  &&
+			 (fabs(relC.x) <= mgeo2.Size.x ) &&
+			 (fabs(relC.y) <= mgeo2.Size.y ) )
+			if( relC.z >=0)	{
+				pt_loc = relC; pt_loc.z =  mgeo2.Size.z; done = true;
+			}
+			else	{
+				pt_loc = relC; pt_loc.z = -mgeo2.Size.z; done = true;
+			}
+		if (!done)
+		if ( (sqrt(pow(fabs(relC.x)-mgeo2.Size.x,2)+pow(fabs(relC.y)-mgeo2.Size.y,2)) <= mgeo1.rad)  &&
+			 (fabs(relC.z) <= mgeo2.Size.z ) )
+			if(relC.x >0)
+				if (relC.y >0)	{
+					pt_loc = relC; pt_loc.x = mgeo2.Size.x; pt_loc.y =  mgeo2.Size.y; done = true;
+				}
+				else{
+					pt_loc = relC; pt_loc.x = mgeo2.Size.x; pt_loc.y = -mgeo2.Size.y; done = true;
+				}
+			else
+				if (relC.y >0)	{
+					pt_loc = relC; pt_loc.x = -mgeo2.Size.x; pt_loc.y =  mgeo2.Size.y; done = true;
+				}
+				else{
+					pt_loc = relC; pt_loc.x = -mgeo2.Size.x; pt_loc.y = -mgeo2.Size.y; done = true;
+				}
+		if (!done)
+		if ( (sqrt(pow(fabs(relC.y)-mgeo2.Size.y,2)+pow(fabs(relC.z)-mgeo2.Size.z,2)) <= mgeo1.rad)  &&
+			 (fabs(relC.x) <= mgeo2.Size.x ) )
+			if(relC.y >0)
+				if (relC.z >0)	{
+					pt_loc = relC; pt_loc.y = mgeo2.Size.y; pt_loc.z =  mgeo2.Size.z; done = true;
+				}
+				else{
+					pt_loc = relC; pt_loc.y = mgeo2.Size.y; pt_loc.z = -mgeo2.Size.z; done = true;
+				}
+			else
+				if (relC.z >0)	{
+					pt_loc = relC; pt_loc.y = -mgeo2.Size.y; pt_loc.z =  mgeo2.Size.z; done = true;
+				}
+				else{
+					pt_loc = relC; pt_loc.y = -mgeo2.Size.y; pt_loc.z = -mgeo2.Size.z; done = true;
+				}
+		if (!done)
+		if ( (sqrt(pow(fabs(relC.z)-mgeo2.Size.z,2)+pow(fabs(relC.x)-mgeo2.Size.x,2)) <= mgeo1.rad)  &&
+			 (fabs(relC.y) <= mgeo2.Size.y ) )
+			if(relC.z >0)
+				if (relC.x >0)	{
+					pt_loc = relC; pt_loc.z = mgeo2.Size.z; pt_loc.x =  mgeo2.Size.x; done = true;
+				}
+				else{
+					pt_loc = relC; pt_loc.z = mgeo2.Size.z; pt_loc.x = -mgeo2.Size.x; done = true;
+				}
+			else
+				if (relC.x >0)	{
+					pt_loc = relC; pt_loc.z = -mgeo2.Size.z; pt_loc.x =  mgeo2.Size.x; done = true;
+				}
+				else{
+					pt_loc = relC; pt_loc.z = -mgeo2.Size.z; pt_loc.x = -mgeo2.Size.x; done = true;
+				}
+		for (int i= 1; i<=8; i++)
+		{
+			if (done) break;
+			Vector loc_corner = ChTrasform<>::TrasformParentToLocal(mgeo2.GetPn(i), mgeo2.Pos, mgeo2.Rot);
+			if (Vlenght(loc_corner-relC) <=  mgeo1.rad )
+			{
+				pt_loc = loc_corner;
+				done = true;
+			}
+		}
+
+		if (done)
+		{
+			Vector pt_2 = ChTrasform<>::TrasformLocalToParent(pt_loc, aBoxPos, aBoxRot);
+			Vector mnormal = Vnorm (pt_2 - *c1);
+			if (Vdot(mnormal, aBoxPos- *c1) <0)
+				mnormal = -mnormal;
+			Vector pt_1 = *c1 + (mnormal*mgeo1.rad);
+			ChCollisionPair mcoll(
+					&mgeo1, &mgeo2,						// geometries
+					pt_1,								// p1
+					pt_2,								// p2
+					mnormal				  				// normal
+					);
+			if (swap_pairs)
+				mcoll.SwapGeometries();
+			mcollider.AddCollisionPair(&mcoll);
+		}
+
+	}
+
+	return 0;
+}
+
+
+
+static double ChPointTriangleDistance(Vector& B, Vector& A1, Vector& A2, Vector& A3,
+							   double& mu, double& mv, int& is_into,
+							   Vector& Bprojected)
+{
+	// defaults
+	is_into = 0;
+	mu=mv=-1;
+	double mdistance = 10e22;
+
+	Vector Dx, Dy, Dz, T1, T1p;
+
+	Dx= Vsub (A2, A1);
+	Dz= Vsub (A3, A1);
+	Dy= Vcross(Dz,Dx);
+
+	double dylen = Vlenght(Dy);
+
+	if(fabs(dylen)<0.000001)	// degenere triangle
+		return mdistance;
+
+	Dy= Vmul(Dy,1.0/dylen);
+
+	static ChMatrix33<> mA;
+	static ChMatrix33<> mAi;
+	mA.Set_A_axis(Dx,Dy,Dz);
+
+	// invert triangle coordinate matrix -if singular matrix, was degenerate triangle-.
+	if (fabs(mA.FastInvert(&mAi)) <0.000001)
+		return mdistance;
+
+	T1 = mAi.Matr_x_Vect( Vsub (B, A1) );
+	T1p = T1;
+	T1p.y=0;
+	mu = T1.x;
+	mv = T1.z;
+	if (mu >=0  &&  mv >=0  &&  mv<=1.0-mu)
+	{
+		is_into = 1;
+		mdistance = fabs(T1.y);
+		Bprojected = Vadd(A1, mA.Matr_x_Vect(T1p));
+	}
+
+	return mdistance;
+}
+
+
+/// BOX - TRIANGLE specific case
+///
+int ChGeometryCollider::ComputeBoxTriangleCollisions(
+							 ChBox& mbox,			///< box
+							 ChMatrix33<>* R1,			///< absolute rotation of 1st model (with box)
+							 Vector* T1,			///< absolute position of 1st model (with box)
+							 ChTriangle& mtri,		///< triangle
+							 ChMatrix33<>* R2,			///< absolute rotation of 2nd model (with triangle)
+							 Vector* T2,			///< absolute position of 2nd model (with triangle)
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection,///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 bool swap_pairs		///< if true, pairs are reported as Triangle-Box (triangle will be the main ref.)
+							 )
+{
+	Vector v_1	     = ChTrasform<>::TrasformLocalToParent(mtri.p1, *T2, *R2);
+	Vector v_2	     = ChTrasform<>::TrasformLocalToParent(mtri.p2, *T2, *R2);
+	Vector v_3	     = ChTrasform<>::TrasformLocalToParent(mtri.p3, *T2, *R2);
+
+	ChMatrix33<> aBoxRot = (*R1) * mbox.Rot;
+	Vector aBoxPos = ChTrasform<>::TrasformLocalToParent(mbox.Pos, (*T1), (*R1));
+
+	Vector v_b[3];
+	v_b[0] = ChTrasform<>::TrasformParentToLocal(v_1, aBoxPos, aBoxRot);
+	v_b[1] = ChTrasform<>::TrasformParentToLocal(v_2, aBoxPos, aBoxRot);
+	v_b[2] = ChTrasform<>::TrasformParentToLocal(v_3, aBoxPos, aBoxRot);
+
+	double distc;
+	bool hit = false;
+	Vector P1_b; Vector P2_b;
+	Vector P1_w; Vector P2_w;
+
+    int nv;
+
+	for (nv = 0; nv<3; nv++)		// triangle points against cube volume
+	{
+		distc = -10e24;
+		P1_b = v_b[nv];
+		P2_b = v_b[nv];
+		if ((fabs(v_b[nv].x) <= mbox.Size.x) && (fabs(v_b[nv].y) <= mbox.Size.y) && (fabs(v_b[nv].z) <= mbox.Size.z))
+		{
+			hit = true;
+			if (v_b[nv].x - mbox.Size.x > distc) {
+				distc = v_b[nv].x - mbox.Size.x;
+				P1_b=v_b[nv]; P1_b.x =  mbox.Size.x;
+			}
+			if (-v_b[nv].x - mbox.Size.x > distc) {
+				distc = -v_b[nv].x - mbox.Size.x;
+				P1_b=v_b[nv]; P1_b.x = -mbox.Size.x;
+			}
+			if (v_b[nv].y - mbox.Size.y > distc) {
+				distc = v_b[nv].y - mbox.Size.y;
+				P1_b=v_b[nv]; P1_b.y =  mbox.Size.y;
+			}
+			if (-v_b[nv].y - mbox.Size.y > distc) {
+				distc = -v_b[nv].y - mbox.Size.y;
+				P1_b=v_b[nv]; P1_b.y = -mbox.Size.y;
+			}
+			if (v_b[nv].z - mbox.Size.z > distc) {
+				distc = v_b[nv].z - mbox.Size.z;
+				P1_b=v_b[nv]; P1_b.z =  mbox.Size.z;
+			}
+			if (-v_b[nv].z - mbox.Size.z > distc) {
+				distc = -v_b[nv].z - mbox.Size.z;
+				P1_b=v_b[nv]; P1_b.z = -mbox.Size.z;
+			}
+
+			Vector P1_w = ChTrasform<>::TrasformLocalToParent(P1_b, aBoxPos, aBoxRot);
+			Vector P2_w = ChTrasform<>::TrasformLocalToParent(P2_b, aBoxPos, aBoxRot);
+			Vector mnormal = Vnorm (P1_w - P2_w);
+			ChCollisionPair mcoll(
+					&mbox, &mtri,					// geometries
+					P1_w,							// p1
+					P2_w,							// p2
+					mnormal				  			// normal
+					);
+			if (swap_pairs)
+				mcoll.SwapGeometries();
+			mcollider.AddCollisionPair(&mcoll);
+		}
+	}
+
+	for (nv = 0; nv<8; nv++)		// box points against triangle
+	{
+		distc = -10e24;
+
+		Vector v_w = ChTrasform<>::TrasformLocalToParent(mbox.GetPn(nv), *T1, *R1);
+
+		P1_w = v_w;
+		P2_w = v_w;
+		int is_into;
+		double mu, mv;
+
+		double dist = ChPointTriangleDistance (P1_w, v_1, v_2, v_3, mu, mv, is_into, P2_w);
+
+		Vector dir = P2_w - P1_w;
+
+		if (is_into)
+		if (Vdot(dir, mtri.GetNormal()) < 0)
+		{
+			Vector mnormal = Vnorm (P1_w - P2_w);
+			ChCollisionPair mcoll(
+					&mbox, &mtri,					// geometries
+					P1_w,								// p1
+					P2_w,								// p2
+					mnormal				  			// normal
+					);
+			if (swap_pairs)
+				mcoll.SwapGeometries();
+			mcollider.AddCollisionPair(&mcoll);
+			hit  =true;
+		}
+	}
+
+	return 0;
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCGeometryCollider.h b/SRC/ChronoEngine/collision/edgetempest/ChCGeometryCollider.h
new file mode 100644
index 0000000..da97095
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCGeometryCollider.h
@@ -0,0 +1,164 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_GEOMETRYCOLLIDER_H
+#define CHC_GEOMETRYCOLLIDER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCGeometryCollider.h
+//
+//   Here you can find functions to compute
+//   the contact points between colliding geometries
+//   of different kinds..
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+
+#include "ChCNarrowPhaseCollider.h"
+#include "geometry/ChCGeometry.h"
+#include "geometry/ChCSphere.h"
+#include "geometry/ChCTriangle.h"
+#include "geometry/ChCBox.h"
+
+using namespace chrono::geometry;
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+///
+/// Static functions to get contacts between geometry pairs of
+/// same or different kinds. These functions are automatically
+/// called, for example, by the collision engine when it 
+/// discovers that two AABB or two OBB intersecate: in such a 
+/// case, the enclosed geometries are tested more precisely using
+/// the metods in this class.
+///
+
+class ChGeometryCollider {
+public:
+
+			/// GEOMETRY - GEOMETRY  generic case (dispatches all pair sub cases)
+			/// Function which computes collisions between two generic
+			/// geometry objects \see ChGeometry, given relative orientation
+			/// of second geometry respect to first.
+			/// Run time type checking of geometric object will automatically
+			/// call the appropriate functions for triangle-triangle or triangle-sphere
+			/// etc. etc cases. 
+			/// The computed contacts are inserted in the collision arrays of
+			/// the ChNarrowPhaseCollider object \see ChNarrowPhaseCollider passed as parameter.
+			///   \return number of found contacts
+			///
+static int ComputeCollisions(ChGeometry& mgeo1,		///< first geometric primitive	
+							 ChMatrix33<>* R1,		///< absolute rotation of model enclosing first geometric primitive
+							 Vector* T1,			///< absolute position of model enclosing primitive
+							 ChGeometry& mgeo2,		///< second geometric primitive
+							 ChMatrix33<>* R2,		///< absolute rotation of model enclosing second geometric primitive
+							 Vector* T2,			///< absolute position of model enclosing second geometric primitive
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 ChMatrix33<>* relRot = NULL,	///< relative rotation of mgeo2 respect to mgeo1, if available (for optimization)
+							 Vector* relPos = NULL,	///< relative position of mgeo2 respect to mgeo1, if available (for optimization)
+							 bool just_intersection = false	///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 );
+
+
+
+			// Following functions are for specific cases of colliding
+			// geometries. Using the ComputeCollisions(), one of the following is
+			// automatically used.
+
+			/// SPHERE - SPHERE specific case
+			///
+static int ComputeSphereSphereCollisions(
+							 ChSphere& mgeo1,		///< first sphere	
+							 Vector* c1,			///< absolute position of 1st center
+							 ChSphere& mgeo2,		///< second sphere
+							 Vector* c2,			///< absolute position of 2nd center
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection	///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 );
+
+
+			/// SPHERE - TRIANGLE specific case
+			///
+static int ComputeSphereTriangleCollisions(
+							 ChSphere& mgeo1,		///< sphere	
+							 Vector* c1,			///< absolute position of 1st center
+							 ChTriangle& mgeo2,		///< triangle
+							 ChMatrix33<>* R2,		///< absolute rotation of 2nd model (with triangle)
+							 Vector* T2,			///< absolute position of 2nd model (with triangle)
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection,///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 bool swap_pairs		///< if true, pairs are reported as Triangle-Sphere (triangle will be the main ref.)
+							 );
+
+			/// BOX - BOX specific case
+			///
+static int ComputeBoxBoxCollisions(
+							 ChBox& mgeo1,			///< box 1	
+							 ChMatrix33<>* R1,		///< absolute rotation of 1st model (with box 1)
+							 Vector* T1,			///< absolute position of 1st model (with box 1)
+							 ChBox& mgeo2,			///< box 2
+							 ChMatrix33<>* R2,		///< absolute rotation of 2nd model (with box 2)
+							 Vector* T2,			///< absolute position of 2nd model (with box 2)
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection ///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 );
+
+			/// SPHERE - BOX specific case
+			///
+static int ComputeSphereBoxCollisions(
+							 ChSphere& mgeo1,		///< sphere	
+							 Vector* c1,			///< absolute position of center
+							 ChBox& mgeo2,			///< box 
+							 ChMatrix33<>* R2,		///< absolute rotation of 2nd model (with box)
+							 Vector* T2,			///< absolute position of 2nd model (with box)
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection,///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 bool swap_pairs		///< if true, pairs are reported as Triangle-Sphere (triangle will be the main ref.)
+							 );
+
+			/// BOX - TRIANGLE specific case
+			///
+static int ComputeBoxTriangleCollisions(
+							 ChBox& mbox,			///< box 	
+							 ChMatrix33<>* R1,		///< absolute rotation of 1st model (with box)
+							 Vector* T1,			///< absolute position of 1st model (with box)
+							 ChTriangle& mtri,		///< triangle
+							 ChMatrix33<>* R2,		///< absolute rotation of 2nd model (with triangle)
+							 Vector* T2,			///< absolute position of 2nd model (with triangle)
+							 ChNarrowPhaseCollider& mcollider,	///< reference to a collider to store contacts into
+							 bool just_intersection,///< if true, just report if intersecting (no further calculus on normal, depht, etc.)
+							 bool swap_pairs		///< if true, pairs are reported as Triangle-Box (triangle will be the main ref.)
+							 );
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCGetTime.h b/SRC/ChronoEngine/collision/edgetempest/ChCGetTime.h
new file mode 100644
index 0000000..486d667
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCGetTime.h
@@ -0,0 +1,52 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef PQP_GETTIME_H
+#define PQP_GETTIME_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCGetTime.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#if  (defined WIN32)||(defined WIN64)
+  #include <time.h>
+  #include <sys/timeb.h>
+  inline
+  double 
+  GetTime()
+  {
+    struct _timeb thistime;
+    _ftime(&thistime);    
+    return (thistime.time + thistime.millitm * 1e-3);
+  }
+#else
+  #include <sys/time.h>
+  inline
+  double 
+  GetTime()
+  {
+    struct timeval thistime;
+    gettimeofday(&thistime, 0);    
+    return (thistime.tv_sec + thistime.tv_usec * 1e-6);
+  }
+
+#endif
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCMatVec.h b/SRC/ChronoEngine/collision/edgetempest/ChCMatVec.h
new file mode 100644
index 0000000..f0dc133
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCMatVec.h
@@ -0,0 +1,889 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MATVEC_H
+#define CHC_MATVEC_H
+
+//////////////////////////////////////////////////
+//
+//   ChCMatVec.h
+//  
+//   Just for backward compatibility with the old
+//   collision detection engine, based on PQP!
+//  
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+#include <stdio.h>
+#include "ChCCompile.h"
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+#ifndef M_PI
+const PQP_REAL M_PI = (PQP_REAL)3.14159265359;
+#endif
+
+#define myfabs(x) ((x < 0) ? -x : x)
+
+inline
+void
+Mprintg(const PQP_REAL M[3][3])
+{
+  printf("%g %g %g\n%g %g %g\n%g %g %g\n",
+	 M[0][0], M[0][1], M[0][2],
+	 M[1][0], M[1][1], M[1][2],
+	 M[2][0], M[2][1], M[2][2]);
+}
+
+
+inline
+void
+Mfprint(FILE *f, const PQP_REAL M[3][3])
+{
+  fprintf(f, "%g %g %g\n%g %g %g\n%g %g %g\n",
+	 M[0][0], M[0][1], M[0][2],
+	 M[1][0], M[1][1], M[1][2],
+	 M[2][0], M[2][1], M[2][2]);
+}
+
+inline
+void
+Mprint(const PQP_REAL M[3][3])
+{
+  printf("%g %g %g\n%g %g %g\n%g %g %g\n",
+	 M[0][0], M[0][1], M[0][2],
+	 M[1][0], M[1][1], M[1][2],
+	 M[2][0], M[2][1], M[2][2]);
+}
+
+inline
+void
+Vprintg(const PQP_REAL V[3])
+{
+  printf("%g %g %g\n", V[0], V[1], V[2]);
+}
+
+inline
+void
+Vfprint(FILE *f, const PQP_REAL V[3])
+{
+  fprintf(f, "%g %g %g\n", V[0], V[1], V[2]);
+}
+
+inline
+void
+Vprint(const PQP_REAL V[3])
+{
+  printf("%g %g %g\n", V[0], V[1], V[2]);
+}
+
+inline
+void
+Midentity(PQP_REAL M[3][3])
+{
+  M[0][0] = M[1][1] = M[2][2] = 1.0;
+  M[0][1] = M[1][2] = M[2][0] = 0.0;
+  M[0][2] = M[1][0] = M[2][1] = 0.0;
+}
+
+inline
+void
+Videntity(PQP_REAL T[3])
+{
+  T[0] = T[1] = T[2] = 0.0;
+}
+
+inline
+void
+McM(PQP_REAL Mr[3][3], const PQP_REAL M[3][3])
+{
+  Mr[0][0] = M[0][0];  Mr[0][1] = M[0][1];  Mr[0][2] = M[0][2];
+  Mr[1][0] = M[1][0];  Mr[1][1] = M[1][1];  Mr[1][2] = M[1][2];
+  Mr[2][0] = M[2][0];  Mr[2][1] = M[2][1];  Mr[2][2] = M[2][2];
+}
+
+inline
+void
+MTcM(PQP_REAL Mr[3][3], const PQP_REAL M[3][3])
+{
+  Mr[0][0] = M[0][0];  Mr[1][0] = M[0][1];  Mr[2][0] = M[0][2];
+  Mr[0][1] = M[1][0];  Mr[1][1] = M[1][1];  Mr[2][1] = M[1][2];
+  Mr[0][2] = M[2][0];  Mr[1][2] = M[2][1];  Mr[2][2] = M[2][2];
+}
+
+inline
+void
+VcV(PQP_REAL Vr[3], const PQP_REAL V[3])
+{
+  Vr[0] = V[0];  Vr[1] = V[1];  Vr[2] = V[2];
+}
+
+inline
+void
+McolcV(PQP_REAL Vr[3], const PQP_REAL M[3][3], int c)
+{
+  Vr[0] = M[0][c];
+  Vr[1] = M[1][c];
+  Vr[2] = M[2][c];
+}
+
+inline
+void
+McolcMcol(PQP_REAL Mr[3][3], int cr, const PQP_REAL M[3][3], int c)
+{
+  Mr[0][cr] = M[0][c];
+  Mr[1][cr] = M[1][c];
+  Mr[2][cr] = M[2][c];
+}
+
+inline
+void
+MxMpV(PQP_REAL Mr[3][3], const PQP_REAL M1[3][3], const PQP_REAL M2[3][3], const PQP_REAL T[3])
+{
+  Mr[0][0] = (M1[0][0] * M2[0][0] +
+	      M1[0][1] * M2[1][0] +
+	      M1[0][2] * M2[2][0] +
+	      T[0]);
+  Mr[1][0] = (M1[1][0] * M2[0][0] +
+	      M1[1][1] * M2[1][0] +
+	      M1[1][2] * M2[2][0] +
+	      T[1]);
+  Mr[2][0] = (M1[2][0] * M2[0][0] +
+	      M1[2][1] * M2[1][0] +
+	      M1[2][2] * M2[2][0] +
+	      T[2]);
+  Mr[0][1] = (M1[0][0] * M2[0][1] +
+	      M1[0][1] * M2[1][1] +
+	      M1[0][2] * M2[2][1] +
+	      T[0]);
+  Mr[1][1] = (M1[1][0] * M2[0][1] +
+	      M1[1][1] * M2[1][1] +
+ 	      M1[1][2] * M2[2][1] +
+	      T[1]);
+  Mr[2][1] = (M1[2][0] * M2[0][1] +
+	      M1[2][1] * M2[1][1] +
+	      M1[2][2] * M2[2][1] +
+	      T[2]);
+  Mr[0][2] = (M1[0][0] * M2[0][2] +
+	      M1[0][1] * M2[1][2] +
+	      M1[0][2] * M2[2][2] +
+	      T[0]);
+  Mr[1][2] = (M1[1][0] * M2[0][2] +
+	      M1[1][1] * M2[1][2] +
+	      M1[1][2] * M2[2][2] +
+	      T[1]);
+  Mr[2][2] = (M1[2][0] * M2[0][2] +
+	      M1[2][1] * M2[1][2] +
+	      M1[2][2] * M2[2][2] +
+	      T[2]);
+}
+
+inline
+void
+MxM(PQP_REAL Mr[3][3], const PQP_REAL M1[3][3], const PQP_REAL M2[3][3])
+{
+  Mr[0][0] = (M1[0][0] * M2[0][0] +
+	      M1[0][1] * M2[1][0] +
+	      M1[0][2] * M2[2][0]);
+  Mr[1][0] = (M1[1][0] * M2[0][0] +
+	      M1[1][1] * M2[1][0] +
+	      M1[1][2] * M2[2][0]);
+  Mr[2][0] = (M1[2][0] * M2[0][0] +
+	      M1[2][1] * M2[1][0] +
+	      M1[2][2] * M2[2][0]);
+  Mr[0][1] = (M1[0][0] * M2[0][1] +
+	      M1[0][1] * M2[1][1] +
+	      M1[0][2] * M2[2][1]);
+  Mr[1][1] = (M1[1][0] * M2[0][1] +
+	      M1[1][1] * M2[1][1] +
+ 	      M1[1][2] * M2[2][1]);
+  Mr[2][1] = (M1[2][0] * M2[0][1] +
+	      M1[2][1] * M2[1][1] +
+	      M1[2][2] * M2[2][1]);
+  Mr[0][2] = (M1[0][0] * M2[0][2] +
+	      M1[0][1] * M2[1][2] +
+	      M1[0][2] * M2[2][2]);
+  Mr[1][2] = (M1[1][0] * M2[0][2] +
+	      M1[1][1] * M2[1][2] +
+	      M1[1][2] * M2[2][2]);
+  Mr[2][2] = (M1[2][0] * M2[0][2] +
+	      M1[2][1] * M2[1][2] +
+	      M1[2][2] * M2[2][2]);
+}
+
+
+inline
+void
+MxMT(PQP_REAL Mr[3][3], const PQP_REAL M1[3][3], const PQP_REAL M2[3][3])
+{
+  Mr[0][0] = (M1[0][0] * M2[0][0] +
+	      M1[0][1] * M2[0][1] +
+	      M1[0][2] * M2[0][2]);
+  Mr[1][0] = (M1[1][0] * M2[0][0] +
+	      M1[1][1] * M2[0][1] +
+	      M1[1][2] * M2[0][2]);
+  Mr[2][0] = (M1[2][0] * M2[0][0] +
+	      M1[2][1] * M2[0][1] +
+	      M1[2][2] * M2[0][2]);
+  Mr[0][1] = (M1[0][0] * M2[1][0] +
+	      M1[0][1] * M2[1][1] +
+	      M1[0][2] * M2[1][2]);
+  Mr[1][1] = (M1[1][0] * M2[1][0] +
+	      M1[1][1] * M2[1][1] +
+ 	      M1[1][2] * M2[1][2]);
+  Mr[2][1] = (M1[2][0] * M2[1][0] +
+	      M1[2][1] * M2[1][1] +
+	      M1[2][2] * M2[1][2]);
+  Mr[0][2] = (M1[0][0] * M2[2][0] +
+	      M1[0][1] * M2[2][1] +
+	      M1[0][2] * M2[2][2]);
+  Mr[1][2] = (M1[1][0] * M2[2][0] +
+	      M1[1][1] * M2[2][1] +
+	      M1[1][2] * M2[2][2]);
+  Mr[2][2] = (M1[2][0] * M2[2][0] +
+	      M1[2][1] * M2[2][1] +
+	      M1[2][2] * M2[2][2]);
+}
+
+inline
+void
+MTxM(PQP_REAL Mr[3][3], const PQP_REAL M1[3][3], const PQP_REAL M2[3][3])
+{
+  Mr[0][0] = (M1[0][0] * M2[0][0] +
+	      M1[1][0] * M2[1][0] +
+	      M1[2][0] * M2[2][0]);
+  Mr[1][0] = (M1[0][1] * M2[0][0] +
+	      M1[1][1] * M2[1][0] +
+	      M1[2][1] * M2[2][0]);
+  Mr[2][0] = (M1[0][2] * M2[0][0] +
+	      M1[1][2] * M2[1][0] +
+	      M1[2][2] * M2[2][0]);
+  Mr[0][1] = (M1[0][0] * M2[0][1] +
+	      M1[1][0] * M2[1][1] +
+	      M1[2][0] * M2[2][1]);
+  Mr[1][1] = (M1[0][1] * M2[0][1] +
+	      M1[1][1] * M2[1][1] +
+ 	      M1[2][1] * M2[2][1]);
+  Mr[2][1] = (M1[0][2] * M2[0][1] +
+	      M1[1][2] * M2[1][1] +
+	      M1[2][2] * M2[2][1]);
+  Mr[0][2] = (M1[0][0] * M2[0][2] +
+	      M1[1][0] * M2[1][2] +
+	      M1[2][0] * M2[2][2]);
+  Mr[1][2] = (M1[0][1] * M2[0][2] +
+	      M1[1][1] * M2[1][2] +
+	      M1[2][1] * M2[2][2]);
+  Mr[2][2] = (M1[0][2] * M2[0][2] +
+	      M1[1][2] * M2[1][2] +
+	      M1[2][2] * M2[2][2]);
+}
+
+inline
+void
+MxV(PQP_REAL Vr[3], const PQP_REAL M1[3][3], const PQP_REAL V1[3])
+{
+  Vr[0] = (M1[0][0] * V1[0] +
+	   M1[0][1] * V1[1] + 
+	   M1[0][2] * V1[2]);
+  Vr[1] = (M1[1][0] * V1[0] +
+	   M1[1][1] * V1[1] + 
+	   M1[1][2] * V1[2]);
+  Vr[2] = (M1[2][0] * V1[0] +
+	   M1[2][1] * V1[1] + 
+	   M1[2][2] * V1[2]);
+}
+
+
+inline
+void
+MxVpV(PQP_REAL Vr[3], const PQP_REAL M1[3][3], const PQP_REAL V1[3], const PQP_REAL V2[3])
+{
+  Vr[0] = (M1[0][0] * V1[0] +
+	   M1[0][1] * V1[1] + 
+	   M1[0][2] * V1[2] + 
+	   V2[0]);
+  Vr[1] = (M1[1][0] * V1[0] +
+	   M1[1][1] * V1[1] + 
+	   M1[1][2] * V1[2] + 
+	   V2[1]);
+  Vr[2] = (M1[2][0] * V1[0] +
+	   M1[2][1] * V1[1] + 
+	   M1[2][2] * V1[2] + 
+	   V2[2]);
+}
+
+
+inline
+void
+sMxVpV(PQP_REAL Vr[3], PQP_REAL s1, const PQP_REAL M1[3][3], const PQP_REAL V1[3], const PQP_REAL V2[3])
+{
+  Vr[0] = s1 * (M1[0][0] * V1[0] +
+		M1[0][1] * V1[1] + 
+		M1[0][2] * V1[2]) +
+		V2[0];
+  Vr[1] = s1 * (M1[1][0] * V1[0] +
+		M1[1][1] * V1[1] + 
+		M1[1][2] * V1[2]) + 
+		V2[1];
+  Vr[2] = s1 * (M1[2][0] * V1[0] +
+		M1[2][1] * V1[1] + 
+		M1[2][2] * V1[2]) + 
+		V2[2];
+}
+
+inline
+void
+MTxV(PQP_REAL Vr[3], const PQP_REAL M1[3][3], const PQP_REAL V1[3])
+{
+  Vr[0] = (M1[0][0] * V1[0] +
+	   M1[1][0] * V1[1] + 
+	   M1[2][0] * V1[2]); 
+  Vr[1] = (M1[0][1] * V1[0] +
+	   M1[1][1] * V1[1] + 
+	   M1[2][1] * V1[2]);
+  Vr[2] = (M1[0][2] * V1[0] +
+	   M1[1][2] * V1[1] + 
+	   M1[2][2] * V1[2]); 
+}
+
+inline
+void
+sMTxV(PQP_REAL Vr[3], PQP_REAL s1, const PQP_REAL M1[3][3], const PQP_REAL V1[3])
+{
+  Vr[0] = s1*(M1[0][0] * V1[0] +
+	      M1[1][0] * V1[1] + 
+	      M1[2][0] * V1[2]); 
+  Vr[1] = s1*(M1[0][1] * V1[0] +
+	      M1[1][1] * V1[1] + 
+	      M1[2][1] * V1[2]);
+  Vr[2] = s1*(M1[0][2] * V1[0] +
+	      M1[1][2] * V1[1] + 
+	      M1[2][2] * V1[2]); 
+}
+
+inline
+void
+sMxV(PQP_REAL Vr[3], PQP_REAL s1, const PQP_REAL M1[3][3], const PQP_REAL V1[3])
+{
+  Vr[0] = s1*(M1[0][0] * V1[0] +
+	      M1[0][1] * V1[1] + 
+	      M1[0][2] * V1[2]); 
+  Vr[1] = s1*(M1[1][0] * V1[0] +
+	      M1[1][1] * V1[1] + 
+	      M1[1][2] * V1[2]);
+  Vr[2] = s1*(M1[2][0] * V1[0] +
+	      M1[2][1] * V1[1] + 
+	      M1[2][2] * V1[2]); 
+}
+
+
+inline
+void
+VmV(PQP_REAL Vr[3], const PQP_REAL V1[3], const PQP_REAL V2[3])
+{
+  Vr[0] = V1[0] - V2[0];
+  Vr[1] = V1[1] - V2[1];
+  Vr[2] = V1[2] - V2[2];
+}
+
+inline
+void
+VpV(PQP_REAL Vr[3], const PQP_REAL V1[3], const PQP_REAL V2[3])
+{
+  Vr[0] = V1[0] + V2[0];
+  Vr[1] = V1[1] + V2[1];
+  Vr[2] = V1[2] + V2[2];
+}
+
+inline
+void
+VpVxS(PQP_REAL Vr[3], const PQP_REAL V1[3], const PQP_REAL V2[3], PQP_REAL s)
+{
+  Vr[0] = V1[0] + V2[0] * s;
+  Vr[1] = V1[1] + V2[1] * s;
+  Vr[2] = V1[2] + V2[2] * s;
+}
+
+inline 
+void
+MskewV(PQP_REAL M[3][3], const PQP_REAL v[3])
+{
+  M[0][0] = M[1][1] = M[2][2] = 0.0;
+  M[1][0] = v[2];
+  M[0][1] = -v[2];
+  M[0][2] = v[1];
+  M[2][0] = -v[1];
+  M[1][2] = -v[0];
+  M[2][1] = v[0];
+}
+
+
+inline
+void
+VcrossV(PQP_REAL Vr[3], const PQP_REAL V1[3], const PQP_REAL V2[3])
+{
+  Vr[0] = V1[1]*V2[2] - V1[2]*V2[1];
+  Vr[1] = V1[2]*V2[0] - V1[0]*V2[2];
+  Vr[2] = V1[0]*V2[1] - V1[1]*V2[0];
+}
+
+inline
+PQP_REAL
+Vlength(PQP_REAL V[3])
+{
+  return sqrt(V[0]*V[0] + V[1]*V[1] + V[2]*V[2]);
+}
+
+inline
+void
+Vnormalize(PQP_REAL V[3])
+{
+  PQP_REAL d = (PQP_REAL)1.0 / sqrt(V[0]*V[0] + V[1]*V[1] + V[2]*V[2]);
+  V[0] *= d;
+  V[1] *= d;
+  V[2] *= d;
+}
+
+inline
+PQP_REAL
+VdotV(const PQP_REAL V1[3], const PQP_REAL V2[3])
+{
+  return (V1[0]*V2[0] + V1[1]*V2[1] + V1[2]*V2[2]);
+}
+
+inline
+PQP_REAL
+VdistV2(const PQP_REAL V1[3], const PQP_REAL V2[3])
+{
+  return ( (V1[0]-V2[0]) * (V1[0]-V2[0]) + 
+	   (V1[1]-V2[1]) * (V1[1]-V2[1]) + 
+	   (V1[2]-V2[2]) * (V1[2]-V2[2]));
+}
+
+inline
+void
+VxS(PQP_REAL Vr[3], const PQP_REAL V[3], PQP_REAL s)
+{
+  Vr[0] = V[0] * s;
+  Vr[1] = V[1] * s;
+  Vr[2] = V[2] * s;
+}
+
+inline
+void
+MRotZ(PQP_REAL Mr[3][3], PQP_REAL t)
+{
+  Mr[0][0] = cos(t);
+  Mr[1][0] = sin(t);
+  Mr[0][1] = -Mr[1][0];
+  Mr[1][1] = Mr[0][0];
+  Mr[2][0] = Mr[2][1] = 0.0;
+  Mr[0][2] = Mr[1][2] = 0.0;
+  Mr[2][2] = 1.0;
+}
+
+inline
+void
+MRotX(PQP_REAL Mr[3][3], PQP_REAL t)
+{
+  Mr[1][1] = cos(t);
+  Mr[2][1] = sin(t);
+  Mr[1][2] = -Mr[2][1];
+  Mr[2][2] = Mr[1][1];
+  Mr[0][1] = Mr[0][2] = 0.0;
+  Mr[1][0] = Mr[2][0] = 0.0;
+  Mr[0][0] = 1.0;
+}
+
+inline
+void
+MRotY(PQP_REAL Mr[3][3], PQP_REAL t)
+{
+  Mr[2][2] = cos(t);
+  Mr[0][2] = sin(t);
+  Mr[2][0] = -Mr[0][2];
+  Mr[0][0] = Mr[2][2];
+  Mr[1][2] = Mr[1][0] = 0.0;
+  Mr[2][1] = Mr[0][1] = 0.0;
+  Mr[1][1] = 1.0;
+}
+
+inline
+void
+MVtoOGL(double oglm[16], const PQP_REAL R[3][3], const PQP_REAL T[3])
+{
+  oglm[0] = (double)R[0][0]; 
+  oglm[1] = (double)R[1][0]; 
+  oglm[2] = (double)R[2][0]; 
+  oglm[3] = 0.0;
+  oglm[4] = (double)R[0][1]; 
+  oglm[5] = (double)R[1][1];
+  oglm[6] = (double)R[2][1];
+  oglm[7] = 0.0;
+  oglm[8] = (double)R[0][2];
+  oglm[9] = (double)R[1][2];
+  oglm[10] = (double)R[2][2];
+  oglm[11] = 0.0;
+  oglm[12] = (double)T[0];
+  oglm[13] = (double)T[1];
+  oglm[14] = (double)T[2];
+  oglm[15] = 1.0;
+}
+
+inline 
+void
+OGLtoMV(PQP_REAL R[3][3], PQP_REAL T[3], const double oglm[16])
+{
+  R[0][0] = (PQP_REAL)oglm[0];
+  R[1][0] = (PQP_REAL)oglm[1];
+  R[2][0] = (PQP_REAL)oglm[2];
+
+  R[0][1] = (PQP_REAL)oglm[4];
+  R[1][1] = (PQP_REAL)oglm[5];
+  R[2][1] = (PQP_REAL)oglm[6];
+
+  R[0][2] = (PQP_REAL)oglm[8];
+  R[1][2] = (PQP_REAL)oglm[9];
+  R[2][2] = (PQP_REAL)oglm[10];
+
+  T[0] = (PQP_REAL)oglm[12];
+  T[1] = (PQP_REAL)oglm[13];
+  T[2] = (PQP_REAL)oglm[14];
+}
+
+// taken from quatlib, written by Richard Holloway
+const int QX = 0;
+const int QY = 1;
+const int QZ = 2;
+const int QW = 3;
+
+inline
+void 
+MRotQ(PQP_REAL destMatrix[3][3], PQP_REAL srcQuat[4])
+{
+  PQP_REAL  s;
+  PQP_REAL  xs, ys, zs,
+    	    wx, wy, wz,
+	        xx, xy, xz,
+	        yy, yz, zz;
+
+  /* 
+   * For unit srcQuat, just set s = 2.0; or set xs = srcQuat[QX] + 
+   *   srcQuat[QX], etc. 
+   */
+
+  s = (PQP_REAL)2.0 / (srcQuat[QX]*srcQuat[QX] + srcQuat[QY]*srcQuat[QY] + 
+    	     srcQuat[QZ]*srcQuat[QZ] + srcQuat[QW]*srcQuat[QW]);
+
+  xs = srcQuat[QX] * s;   ys = srcQuat[QY] * s;   zs = srcQuat[QZ] * s;
+  wx = srcQuat[QW] * xs;  wy = srcQuat[QW] * ys;  wz = srcQuat[QW] * zs;
+  xx = srcQuat[QX] * xs;  xy = srcQuat[QX] * ys;  xz = srcQuat[QX] * zs;
+  yy = srcQuat[QY] * ys;  yz = srcQuat[QY] * zs;  zz = srcQuat[QZ] * zs;
+
+  destMatrix[QX][QX] = (PQP_REAL)1.0 - (yy + zz);
+  destMatrix[QX][QY] = xy + wz;
+  destMatrix[QX][QZ] = xz - wy;
+
+  destMatrix[QY][QX] = xy - wz;
+  destMatrix[QY][QY] = (PQP_REAL)1.0 - (xx + zz);
+  destMatrix[QY][QZ] = yz + wx;
+
+  destMatrix[QZ][QX] = xz + wy;
+  destMatrix[QZ][QY] = yz - wx;
+  destMatrix[QZ][QZ] = (PQP_REAL)1.0 - (xx + yy);
+} 
+
+inline
+void
+Mqinverse(PQP_REAL Mr[3][3], PQP_REAL m[3][3])
+{
+  int i,j;
+
+  for(i=0; i<3; i++)
+    for(j=0; j<3; j++)
+    {
+      int i1 = (i+1)%3;
+      int i2 = (i+2)%3;
+      int j1 = (j+1)%3;
+      int j2 = (j+2)%3;
+      Mr[i][j] = (m[j1][i1]*m[j2][i2] - m[j1][i2]*m[j2][i1]);
+    }
+}  
+
+inline
+double 
+M33FastInvert (PQP_REAL matra[3][3], PQP_REAL mthis[3][3])	
+{
+	double det;
+	double sdet0, sdet1, sdet2;
+
+	sdet0 =+(mthis[1][1] * mthis[2][2])
+		   -(mthis[2][1] * mthis[1][2]);
+	sdet1 =-(mthis[1][0] * mthis[2][2])
+		   +(mthis[2][0] * mthis[1][2]);
+	sdet2 =+(mthis[1][0] * mthis[2][1])
+		   -(mthis[2][0] * mthis[1][1]);
+
+	det = sdet0 * mthis[0][0] +
+		  sdet1 * mthis[0][1] +
+		  sdet2 * mthis[0][2];
+
+	matra[0][0]= sdet0/det;
+	matra[1][0]= sdet1/det;
+	matra[2][0]= sdet2/det;
+	matra[0][1]= (-(mthis[0][1] * mthis[2][2])
+						      +(mthis[2][1] * mthis[0][2]))/det;
+	matra[1][1]= (+(mthis[0][0] * mthis[2][2])
+						      -(mthis[2][0] * mthis[0][2]))/det;
+	matra[2][1]= (-(mthis[0][0] * mthis[2][1])
+						      +(mthis[2][0] * mthis[0][1]))/det;
+	matra[0][2]= (+(mthis[0][1] * mthis[1][2])
+						      -(mthis[1][1] * mthis[0][2]))/det;
+	matra[1][2]= (-(mthis[0][0] * mthis[1][2])
+						      +(mthis[1][0] * mthis[0][2]))/det;
+	matra[2][2]= (+(mthis[0][0] * mthis[1][1])
+						      -(mthis[1][0] * mthis[0][1]))/det;
+
+	return (det);
+}
+// Meigen from Numerical Recipes in C
+
+#if 0
+
+#define rfabs(x) ((x < 0) ? -x : x)
+
+#define ROT(a,i,j,k,l) g=a[i][j]; h=a[k][l]; a[i][j]=g-s*(h+g*tau); a[k][l]=h+s*(g-h*tau);
+
+int
+inline
+Meigen(PQP_REAL vout[3][3], PQP_REAL dout[3], PQP_REAL a[3][3])
+{
+  int i;
+  PQP_REAL tresh,theta,tau,t,sm,s,h,g,c;
+  int nrot;
+  PQP_REAL b[3];
+  PQP_REAL z[3];
+  PQP_REAL v[3][3];
+  PQP_REAL d[3];
+
+  v[0][0] = v[1][1] = v[2][2] = 1.0;
+  v[0][1] = v[1][2] = v[2][0] = 0.0;
+  v[0][2] = v[1][0] = v[2][1] = 0.0;
+  
+  b[0] = a[0][0]; d[0] = a[0][0]; z[0] = 0.0;
+  b[1] = a[1][1]; d[1] = a[1][1]; z[1] = 0.0;
+  b[2] = a[2][2]; d[2] = a[2][2]; z[2] = 0.0;
+
+  nrot = 0;
+
+  
+  for(i=0; i<50; i++)
+    {
+
+      printf("2\n");
+
+      sm=0.0; sm+=fabs(a[0][1]); sm+=fabs(a[0][2]); sm+=fabs(a[1][2]);
+      if (sm == 0.0) { McM(vout,v); VcV(dout,d); return i; }
+      
+      if (i < 3) tresh=0.2*sm/(3*3); else tresh=0.0;
+      
+      {
+	g = 100.0*rfabs(a[0][1]);  
+	if (i>3 && rfabs(d[0])+g==rfabs(d[0]) && rfabs(d[1])+g==rfabs(d[1]))
+	  a[0][1]=0.0;
+	else if (rfabs(a[0][1])>tresh)
+	  {
+	    h = d[1]-d[0];
+	    if (rfabs(h)+g == rfabs(h)) t=(a[0][1])/h;
+	    else
+	      {
+		theta=0.5*h/(a[0][1]);
+		t=1.0/(rfabs(theta)+sqrt(1.0+theta*theta));
+		if (theta < 0.0) t = -t;
+	      }
+	    c=1.0/sqrt(1+t*t); s=t*c; tau=s/(1.0+c); h=t*a[0][1];
+	    z[0] -= h; z[1] += h; d[0] -= h; d[1] += h;
+	    a[0][1]=0.0;
+	    ROT(a,0,2,1,2); ROT(v,0,0,0,1); ROT(v,1,0,1,1); ROT(v,2,0,2,1); 
+	    nrot++;
+	  }
+      }
+
+      {
+	g = 100.0*rfabs(a[0][2]);
+	if (i>3 && rfabs(d[0])+g==rfabs(d[0]) && rfabs(d[2])+g==rfabs(d[2]))
+	  a[0][2]=0.0;
+	else if (rfabs(a[0][2])>tresh)
+	  {
+	    h = d[2]-d[0];
+	    if (rfabs(h)+g == rfabs(h)) t=(a[0][2])/h;
+	    else
+	      {
+		theta=0.5*h/(a[0][2]);
+		t=1.0/(rfabs(theta)+sqrt(1.0+theta*theta));
+		if (theta < 0.0) t = -t;
+	      }
+	    c=1.0/sqrt(1+t*t); s=t*c; tau=s/(1.0+c); h=t*a[0][2];
+	    z[0] -= h; z[2] += h; d[0] -= h; d[2] += h;
+	    a[0][2]=0.0;
+	    ROT(a,0,1,1,2); ROT(v,0,0,0,2); ROT(v,1,0,1,2); ROT(v,2,0,2,2); 
+	    nrot++;
+	  }
+      }
+
+      {
+	g = 100.0*rfabs(a[1][2]);
+	if (i>3 && rfabs(d[1])+g==rfabs(d[1]) && rfabs(d[2])+g==rfabs(d[2]))
+	  a[1][2]=0.0;
+	else if (rfabs(a[1][2])>tresh)
+	  {
+	    h = d[2]-d[1];
+	    if (rfabs(h)+g == rfabs(h)) t=(a[1][2])/h;
+	    else
+	      {
+		theta=0.5*h/(a[1][2]);
+		t=1.0/(rfabs(theta)+sqrt(1.0+theta*theta));
+		if (theta < 0.0) t = -t;
+	      }
+	    c=1.0/sqrt(1+t*t); s=t*c; tau=s/(1.0+c); h=t*a[1][2];
+	    z[1] -= h; z[2] += h; d[1] -= h; d[2] += h;
+	    a[1][2]=0.0;
+	    ROT(a,0,1,0,2); ROT(v,0,1,0,2); ROT(v,1,1,1,2); ROT(v,2,1,2,2); 
+	    nrot++;
+	  }
+      }
+
+      b[0] += z[0]; d[0] = b[0]; z[0] = 0.0;
+      b[1] += z[1]; d[1] = b[1]; z[1] = 0.0;
+      b[2] += z[2]; d[2] = b[2]; z[2] = 0.0;
+      
+    }
+
+  fprintf(stderr, "eigen: too many iterations in Jacobi transform (%d).\n", i);
+
+  return i;
+}
+
+#else
+
+
+
+#define ROTATE(a,i,j,k,l) g=a[i][j]; h=a[k][l]; a[i][j]=g-s*(h+g*tau); a[k][l]=h+s*(g-h*tau);
+
+void
+inline
+Meigen(PQP_REAL vout[3][3], PQP_REAL dout[3], PQP_REAL a[3][3])
+{
+  int n = 3;
+  int j,iq,ip,i;
+  PQP_REAL tresh,theta,tau,t,sm,s,h,g,c;
+  int nrot;
+  PQP_REAL b[3];
+  PQP_REAL z[3];
+  PQP_REAL v[3][3];
+  PQP_REAL d[3];
+  
+  Midentity(v);
+  for(ip=0; ip<n; ip++) 
+    {
+      b[ip] = a[ip][ip];
+      d[ip] = a[ip][ip];
+      z[ip] = 0.0;
+    }
+  
+  nrot = 0;
+  
+  for(i=0; i<50; i++)
+    {
+
+      sm=0.0;
+      for(ip=0;ip<n;ip++) for(iq=ip+1;iq<n;iq++) sm+=fabs(a[ip][iq]);
+      if (sm == 0.0)
+	{
+	  McM(vout, v);
+	  VcV(dout, d);
+	  return;
+	}
+      
+      
+      if (i < 3) tresh=(PQP_REAL)0.2*sm/(n*n);
+      else tresh=0.0;
+      
+      for(ip=0; ip<n; ip++) for(iq=ip+1; iq<n; iq++)
+	{
+	  g = (PQP_REAL)100.0*fabs(a[ip][iq]);
+	  if (i>3 && 
+	      fabs(d[ip])+g==fabs(d[ip]) && 
+	      fabs(d[iq])+g==fabs(d[iq]))
+	    a[ip][iq]=0.0;
+	  else if (fabs(a[ip][iq])>tresh)
+	    {
+	      h = d[iq]-d[ip];
+	      if (fabs(h)+g == fabs(h)) t=(a[ip][iq])/h;
+	      else
+		{
+		  theta=(PQP_REAL)0.5*h/(a[ip][iq]);
+		  t=(PQP_REAL)(1.0/(fabs(theta)+sqrt(1.0+theta*theta)));
+		  if (theta < 0.0) t = -t;
+		}
+	      c=(PQP_REAL)1.0/sqrt(1+t*t);
+	      s=t*c;
+	      tau=s/((PQP_REAL)1.0+c);
+	      h=t*a[ip][iq];
+	      z[ip] -= h;
+	      z[iq] += h;
+	      d[ip] -= h;
+	      d[iq] += h;
+	      a[ip][iq]=0.0;
+	      for(j=0;j<ip;j++) { ROTATE(a,j,ip,j,iq); } 
+	      for(j=ip+1;j<iq;j++) { ROTATE(a,ip,j,j,iq); } 
+	      for(j=iq+1;j<n;j++) { ROTATE(a,ip,j,iq,j); } 
+	      for(j=0;j<n;j++) { ROTATE(v,j,ip,j,iq); } 
+	      nrot++;
+	    }
+	}
+      for(ip=0;ip<n;ip++)
+	{
+	  b[ip] += z[ip];
+	  d[ip] = b[ip];
+	  z[ip] = 0.0;
+	}
+    }
+
+  fprintf(stderr, "eigen: too many iterations in Jacobi transform.\n");
+
+  return;
+}
+
+#endif  // end if meigen
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCMates.h b/SRC/ChronoEngine/collision/edgetempest/ChCMates.h
new file mode 100644
index 0000000..7dd0ccd
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCMates.h
@@ -0,0 +1,106 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_MATES_H
+#define CHC_MATES_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCMates.h
+//
+//   Header for items representing a couple of colliding
+//   models.
+//   Mostly used by broadphase colliders, like in 
+//   sweep and prune.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+/// Class for couple of 'overlapping' models, i.e. neighbouring graph edge
+/// (connecting two collision models).
+/// Mostly used by broadphase colliders, for example like in 
+/// ChSweepAndPrune() engine.
+
+template<class model_type>
+class ChMates
+{
+private:
+	model_type* m_A;
+	model_type* m_B;                     
+
+public: 
+				/// Axis overlap counter 
+				/// (0=no overlaps, 1=partial overlap,only on an axis, 2=.., 3=full overlap on XYZ axes
+	short m_snp_axis_overlap_count; 
+		
+				/// Boolean flag indicating whether a ovelap have been reported.
+	bool  m_snp_overlap_reported;
+				
+
+				/// Iterator to already-reported overlap.
+	typename std::list<ChMates<model_type>*>::iterator m_snp_reported_overlap;
+
+				/// Constructor. Arguments are the A and B models linked by this
+				/// graph edge of mates.
+	ChMates(model_type* mA=0, model_type* mB=0) : m_A(mA), m_B(mB), m_snp_axis_overlap_count(0), m_snp_overlap_reported(false){};
+
+				/// Return the hash key of this mates
+    const unsigned int getHashkey(void)const
+			{
+			  return ChMates::getHashkey(m_A,m_B);
+			};
+
+				/// Static function: return hash key for a generic mates item.
+	static const unsigned int getHashkey(model_type* A,  model_type* B)
+			{
+			  assert(A);
+			  assert(B);
+			  assert(A->GetBody()->GetIdentifier()!=B->GetBody()->GetIdentifier());
+			  if(A->GetBody()->GetIdentifier()<B->GetBody()->GetIdentifier())
+				return static_cast<unsigned int>( ((A->GetBody()->GetIdentifier()<<16)|(B->GetBody()->GetIdentifier()&0x0000FFFF)) );
+			  return static_cast<unsigned int>( ((B->GetBody()->GetIdentifier()<<16)|(A->GetBody()->GetIdentifier()&0x0000FFFF)) );
+			};
+
+				/// Returns the first collision model
+	model_type* GetModelA() {return m_A;}
+
+				/// Returns the second collision model
+	model_type* GetModelB() {return m_B;}
+
+};
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCNarrowPhaseCollider.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCNarrowPhaseCollider.cpp
new file mode 100644
index 0000000..996dd63
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCNarrowPhaseCollider.cpp
@@ -0,0 +1,123 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2003, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCNarrowPhaseCollider.cpp
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+#include <string.h>
+
+ 
+#include "ChCMatVec.h"
+#include "ChCGetTime.h"
+#include "ChCNarrowPhaseCollider.h"
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+ChNarrowPhaseCollider::ChNarrowPhaseCollider()
+{
+	// initially reserve a bit of space to contact array, 
+	// to avoid many reallocations if resizing needed for enlarging it.
+  pairs.clear();
+  num_collision_pairs = 0;
+  num_bv_tests = 0;
+  num_geo_tests = 0;
+}
+
+ChNarrowPhaseCollider::~ChNarrowPhaseCollider()
+{
+  pairs.clear();	// should be automatic, anyway.
+}
+
+void ChNarrowPhaseCollider::ClearPairsList()
+{
+  num_collision_pairs = 0;
+  pairs.clear();
+}
+
+
+void ChNarrowPhaseCollider::AddCollisionPair(ChCollisionPair* mcollision)
+{
+	pairs.push_back(*mcollision);
+
+	num_collision_pairs++;
+}
+
+
+ 
+ 
+//
+// PERFORM COLLISION DETECTION
+//
+
+ChNarrowPhaseCollider::eCollSuccess ChNarrowPhaseCollider::ComputeCollisions(
+            ChMatrix33<>& aR1, Vector aT1, ChCollisionTree *o1,
+            ChMatrix33<>& aR2, Vector aT2, ChCollisionTree *o2,
+            eCollMode flag)
+{
+  // collision models must be here
+  if (!o1 || !o2)
+    return ChC_RESULT_GENERICERROR;
+
+  // make sure that the models are built
+  if (o1->build_state != ChCollisionTree::ChC_BUILD_STATE_PROCESSED) 
+    return ChC_RESULT_MODELSNOTBUILT;
+  if (o2->build_state != ChCollisionTree::ChC_BUILD_STATE_PROCESSED) 
+    return ChC_RESULT_MODELSNOTBUILT;
+
+  // clear the stats
+ 
+  this->num_bv_tests = 0;
+  this->num_geo_tests = 0;
+  
+  // don't release the memory, 
+  // DONT reset the num_collision_pairs counter (may be mutiple calls for different object couples)
+  // this->ClearPairsList();
+ 
+  // Precompute useful matrices
+
+  this->R.MatrTMultiply(aR1, aR2);	//  MTxM(this->R,R1,R2);
+
+  static Vector Ttemp;
+  Ttemp = Vsub (aT2, aT1);			// VmV(Ttemp, T2, T1);  
+  this->T = aR1.MatrT_x_Vect(Ttemp); // MTxV(this->T, R1, Ttemp);
+
+  this->T1 = aT1;
+  this->T2 = aT2;
+  this->R1.CopyFromMatrix(aR1);
+  this->R2.CopyFromMatrix(aR2);
+
+  //
+  // CHILD CLASSES SHOULD IMPLEMENT THE REST....
+  // .....(ex. code for collisions between AABB and AABB models, etc.
+  //
+
+  return ChC_RESULT_OK; 
+}
+
+
+ 
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCNarrowPhaseCollider.h b/SRC/ChronoEngine/collision/edgetempest/ChCNarrowPhaseCollider.h
new file mode 100644
index 0000000..4b75022
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCNarrowPhaseCollider.h
@@ -0,0 +1,162 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_NARROWPHASECOLLIDER_H
+#define CHC_NARROWPHASECOLLIDER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCNarrowPhaseCollider.h
+//   
+//   Header file for the class implementing method
+//   which computes collisions/contacts between a
+//   pair of models.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChCCompile.h"   
+#include "collision/ChCCollisionPair.h"                             
+#include "ChCCollisionTree.h"
+
+
+namespace chrono 
+{
+/// Namespace for classes devoted to
+/// collision detection.
+namespace collision
+{
+	
+
+
+
+
+///
+/// Base class for the narrow-phase collision detection algorithm (collision
+/// between a single couple of models).
+/// It just implements algorithms to handle the list of the contact
+/// pairs, but child classes must implement the most important function,
+/// that is the ComputeCollisions() function, which should find the 
+/// contact pairs between two collision models. \see ChCollisionTree
+///
+
+
+class ChNarrowPhaseCollider  
+{
+public:
+			/// Constructor
+  ChNarrowPhaseCollider();
+			/// Destructor
+  virtual ~ChNarrowPhaseCollider();
+
+			/// Child classes must use this function to insert a new CollisionPair 
+			/// into  the vector of contacts. (The pair is automatically copied and allocated).
+  void AddCollisionPair(ChCollisionPair* mcollision);
+
+			/// Free the vector of contact pairs.
+  void ClearPairsList(); 
+
+			/// Returns 1 if colliding, return 0 if not colliding (after calling ComputeCollisions())
+  int IsColliding() { return (num_collision_pairs > 0); }
+
+			/// Returns number of collision pairs (after calling ComputeCollisions())
+  int GetNumPairs() { return num_collision_pairs; }
+
+			/// Returns reference to vector of collision pairs (after calling ComputeCollisions())
+  std::vector<ChCollisionPair>& GetPairs() {return pairs; }
+  
+
+			/// Returns the number of bounding volume tests, for statistics
+  int GetNumBVTests() { return num_bv_tests; }
+			/// Returns the number of intersection between geometric primitives, for statistics
+  int NumGeoTests()		{ return num_geo_tests; }
+			/// Time of execution of last call to ComputeCollisions()
+  double QueryTimeSecs() { return query_time_secs; }
+
+
+
+
+	// PERFORM THE COLLISION DETECTION
+
+  enum eCollMode {
+		ChC_ALL_CONTACTS = 1,  ///< find all possible contact pairs
+		ChC_FIRST_CONTACT = 2, ///< report first intersecting entity and shortcircuit search
+  };
+  enum eCollSuccess {
+		ChC_RESULT_OK = 1,				///< ComputeCollisions() performed ok
+		ChC_RESULT_MODELSNOTBUILT = 2,  ///< No collision query was possible: models not correctly built!
+		ChC_RESULT_GENERICERROR = 100,	///< ComputeCollisions() generic failure to performs
+  };
+			/// Perform collision detection between two 
+			/// collision models (each belonging to a different rigid
+			/// body, for example), given the absolute orientations and
+			/// translations of the two models.
+			/// The identified contacts will be inserted in the Contacts vector.
+			/// All child classes must implement this.
+			///
+   virtual eCollSuccess ComputeCollisions(
+            ChMatrix33<>& R1,						///< abs.rotation of first model		
+			Vector T1,						///< abs.position of first model
+			ChCollisionTree *o1,			///< reference to first model
+            ChMatrix33<>& R2,						///< abs.rotation of second model
+			Vector T2,						///< abs position of second model
+			ChCollisionTree *o2,			///< reference to second model
+            eCollMode flag					///< mode of collision \see eCollMode
+			);
+
+
+protected:
+	
+	// DATA
+
+
+  int num_collision_pairs;	///< number of collision pairs (contact points) detected
+  std::vector<ChCollisionPair> pairs; ///< vector of collision pairs (contact points)
+
+  int num_bv_tests;			///< number of bounding volume tests, for statistics
+  int num_geo_tests;		///< number of test of intersection between primitive pairs
+  double query_time_secs;	///< time of execution of last call to collision detection
+
+		// Used internally, initialized after call to base function ComputeCollisions()
+		// and then they can be used by children classes which inherit specific ComputeCollisions() features
+  ChMatrix33<> R;		// relative rotation of model 2 respect to model 1
+  Vector T;		// relative position of model 2 respect to model 1
+  ChMatrix33<> R1;	// abs.rotation of model1
+  Vector T1;	// abs.position of model1
+  ChMatrix33<> R2;	// abs.rotation of model2
+  Vector T2;	// abs.position of model2
+};
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
+
+
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCOBB.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCOBB.cpp
new file mode 100644
index 0000000..d473aa4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCOBB.cpp
@@ -0,0 +1,253 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChCOBB.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include <stdlib.h>
+#include <math.h>
+#include "ChCOBB.h"
+#include "ChCMatVec.h"
+#include "collision/ChCCollisionPair.h"
+
+ 
+namespace chrono
+{
+namespace collision
+{
+
+
+
+CHOBB::CHOBB()
+{
+	first_child = 0;
+
+	Rot.Set33Identity();
+
+	To = VNULL;
+	d = VNULL;
+}
+
+CHOBB::~CHOBB()
+{
+}
+
+
+
+void CHOBB::FitToGeometries(ChMatrix33<>& O, std::vector<ChGeometry*> mgeos, int firstgeo, int ngeos, double envelope)
+{
+	// store orientation
+
+	this->Rot.CopyFromMatrix(O);
+
+	double minx, maxx, miny, maxy, minz, maxz;
+	minx = miny = minz = +10e20;
+	maxx = maxy = maxz = -10e20;
+
+	Vector c;
+
+	ChGeometry* nit;
+	for(int count = 0; count < ngeos; ++count)
+	{
+	 nit = mgeos[firstgeo+count];
+	 if(nit)
+	 {
+		nit->InflateBoundingBox(minx, maxx, miny, maxy, minz, maxz, &Rot);
+	 }
+	}
+
+
+	c.x = 0.5*(maxx + minx);
+	c.y = 0.5*(maxy + miny);
+	c.z = 0.5*(maxz + minz);
+	To = Rot.Matr_x_Vect(c);
+
+	d.x = 0.5*(maxx - minx) + envelope;
+	d.y = 0.5*(maxy - miny) + envelope;
+	d.z = 0.5*(maxz - minz) + envelope;
+
+}
+
+bool CHOBB::OBB_Overlap(ChMatrix33<>& B, Vector T, CHOBB *b1, CHOBB *b2)
+{
+	return  OBB_Overlap(B, T, b1->d, b2->d);
+}
+
+bool CHOBB::OBB_Overlap(ChMatrix33<>& B, Vector T, Vector a, Vector b)
+{
+	  register double t, s;
+	  register int r;
+	  static ChMatrix33<> Bf;
+	  const double reps = (double)1e-6;
+
+	  //Vector& a = b1->d;
+	  //Vector& b = b2->d;
+
+	  // Bf = fabs(B)
+	  Bf(0,0) = myfabs(B.Get33Element(0,0));  Bf(0,0) += reps;
+	  Bf(0,1) = myfabs(B.Get33Element(0,1));  Bf(0,1) += reps;
+	  Bf(0,2) = myfabs(B.Get33Element(0,2));  Bf(0,2) += reps;
+	  Bf(1,0) = myfabs(B.Get33Element(1,0));  Bf(1,0) += reps;
+	  Bf(1,1) = myfabs(B.Get33Element(1,1));  Bf(1,1) += reps;
+	  Bf(1,2) = myfabs(B.Get33Element(1,2));  Bf(1,2) += reps;
+	  Bf(2,0) = myfabs(B.Get33Element(2,0));  Bf(2,0) += reps;
+	  Bf(2,1) = myfabs(B.Get33Element(2,1));  Bf(2,1) += reps;
+	  Bf(2,2) = myfabs(B.Get33Element(2,2));  Bf(2,2) += reps;
+
+	  // if any of these tests are one-sided, then the polyhedra are disjoint
+	  r = 1;
+
+	  // A1 x A2 = A0
+	  t = myfabs(T.x);
+
+	  r &= (t <=
+		  (a.x + b.x * Bf.Get33Element(0,0) + b.y * Bf.Get33Element(0,1) + b.z * Bf.Get33Element(0,2)));
+	  if (!r) return false;
+
+	  // B1 x B2 = B0
+	  s = T.x*B.Get33Element(0,0) + T.y*B.Get33Element(1,0) + T.z*B.Get33Element(2,0);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (b.x + a.x * Bf.Get33Element(0,0) + a.y * Bf.Get33Element(1,0) + a.z * Bf.Get33Element(2,0)));
+	  if (!r) return false;
+
+	  // A2 x A0 = A1
+	  t = myfabs(T.y);
+
+	  r &= ( t <=
+		  (a.y + b.x * Bf.Get33Element(1,0) + b.y * Bf.Get33Element(1,1) + b.z * Bf.Get33Element(1,2)));
+	  if (!r) return false;
+
+	  // A0 x A1 = A2
+	  t = myfabs(T.z);
+
+	  r &= ( t <=
+		  (a.z + b.x * Bf.Get33Element(2,0) + b.y * Bf.Get33Element(2,1) + b.z * Bf.Get33Element(2,2)));
+	  if (!r) return false;
+
+	  // B2 x B0 = B1
+	  s = T.x*B.Get33Element(0,1) + T.y*B.Get33Element(1,1) + T.z*B.Get33Element(2,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (b.y + a.x * Bf.Get33Element(0,1) + a.y * Bf.Get33Element(1,1) + a.z * Bf.Get33Element(2,1)));
+	  if (!r) return false;
+
+	  // B0 x B1 = B2
+	  s = T.x*B.Get33Element(0,2) + T.y*B.Get33Element(1,2) + T.z*B.Get33Element(2,2);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (b.z + a.x * Bf.Get33Element(0,2) + a.y * Bf.Get33Element(1,2) + a.z * Bf.Get33Element(2,2)));
+	  if (!r) return false;
+
+	  // A0 x B0
+	  s = T.z * B.Get33Element(1,0) - T.y * B.Get33Element(2,0);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		(a.y * Bf.Get33Element(2,0) + a.z * Bf.Get33Element(1,0) +
+		 b.y * Bf.Get33Element(0,2) + b.z * Bf.Get33Element(0,1)));
+	  if (!r) return false;
+
+	  // A0 x B1
+	  s = T.z * B.Get33Element(1,1) - T.y * B.Get33Element(2,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		(a.y * Bf.Get33Element(2,1) + a.z * Bf.Get33Element(1,1) +
+		 b.x * Bf.Get33Element(0,2) + b.z * Bf.Get33Element(0,0)));
+	  if (!r) return false;
+
+	  // A0 x B2
+	  s = T.z * B.Get33Element(1,2) - T.y * B.Get33Element(2,2);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.y * Bf.Get33Element(2,2) + a.z * Bf.Get33Element(1,2) +
+		   b.x * Bf.Get33Element(0,1) + b.y * Bf.Get33Element(0,0)));
+	  if (!r) return false;
+
+	  // A1 x B0
+	  s = T.x * B.Get33Element(2,0) - T.z * B.Get33Element(0,0);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(2,0) + a.z * Bf.Get33Element(0,0) +
+		   b.y * Bf.Get33Element(1,2) + b.z * Bf.Get33Element(1,1)));
+	  if (!r) return false;
+
+	  // A1 x B1
+	  s = T.x * B.Get33Element(2,1) - T.z * B.Get33Element(0,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(2,1) + a.z * Bf.Get33Element(0,1) +
+		   b.x * Bf.Get33Element(1,2) + b.z * Bf.Get33Element(1,0)));
+	  if (!r) return false;
+
+	  // A1 x B2
+	  s = T.x * B.Get33Element(2,2) - T.z * B.Get33Element(0,2);
+	  t = myfabs(s);
+
+	  r &= (t <=
+		  (a.x * Bf.Get33Element(2,2) + a.z * Bf.Get33Element(0,2) +
+		   b.x * Bf.Get33Element(1,1) + b.y * Bf.Get33Element(1,0)));
+	  if (!r) return false;
+
+	  // A2 x B0
+	  s = T.y * B.Get33Element(0,0) - T.x * B.Get33Element(1,0);
+	  t = myfabs(s);
+
+	  r &= (t <=
+		  (a.x * Bf.Get33Element(1,0) + a.y * Bf.Get33Element(0,0) +
+		   b.y * Bf.Get33Element(2,2) + b.z * Bf.Get33Element(2,1)));
+	  if (!r) return false;
+
+	  // A2 x B1
+	  s = T.y * B.Get33Element(0,1) - T.x * B.Get33Element(1,1);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(1,1) + a.y * Bf.Get33Element(0,1) +
+		   b.x * Bf.Get33Element(2,2) + b.z * Bf.Get33Element(2,0)));
+	  if (!r) return false;
+
+	  // A2 x B2
+	  s = T.y * B.Get33Element(0,2) - T.x * B.Get33Element(1,2);
+	  t = myfabs(s);
+
+	  r &= ( t <=
+		  (a.x * Bf.Get33Element(1,2) + a.y * Bf.Get33Element(0,2) +
+		   b.x * Bf.Get33Element(2,1) + b.y * Bf.Get33Element(2,0)));
+	  if (!r) return false;
+
+
+	  return true;  // no separation: BV collide!!
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCOBB.h b/SRC/ChronoEngine/collision/edgetempest/ChCOBB.h
new file mode 100644
index 0000000..943a200
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCOBB.h
@@ -0,0 +1,123 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_OBB_H
+#define CHC_OBB_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCOBB.h
+//
+//   Header for the Object oriented Bounding Box
+//   class. Useful for BSP collision queries.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+#include "geometry/ChCGeometry.h"
+#include "ChCCompile.h"
+#include <vector>
+
+using namespace chrono::geometry;
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+///
+/// Class for Object aligned Bounding Box (OBB)
+/// This class is useful for collision tests based on
+/// trees of bounding volumes.
+///
+
+
+class CHOBB
+{
+public:
+
+			// DATA
+
+  ChMatrix33<> Rot;		///< orientation of RSS & OBB
+
+  Vector To;			///< position of center of obb
+
+  Vector  d;			///< (half) dimensions of obb
+
+
+  int first_child;      ///< positive value is index of first_child OBB,
+                        ///  negative value is -(index + 1) of geometry in geom.list
+
+
+
+			// FUNCTIONS		
+  CHOBB();
+  ~CHOBB();
+						// Copy constructor 
+  CHOBB(const CHOBB& other) { To=other.To; d=other.d; first_child=other.first_child; Rot.CopyFromMatrix(other.Rot);}
+
+						/// Returns 1 if this is a leaf in BV tree
+  inline int IsLeaf()    { return first_child < 0; }
+						
+						/// Returns the index of the geometry in the geometry vector of the model
+						/// Caution: must be used only if IsLeaf()==true
+  inline int GetGeometryIndex()	{return (-first_child -1);}
+
+						/// Returns the index of the first child box, in box vector of the model
+						/// Caution: must be used only if IsLeaf()==false
+  inline int GetFirstChildIndex()	{return first_child;}
+
+ 						/// Returns the index of the second child box, in box vector of the model
+						/// Caution: must be used only if IsLeaf()==false
+  inline int GetSecondChildIndex()	{return first_child+1;}
+
+
+						/// Returns the size of the OBB (as sphere radius)
+  double   GetSize() { return (d.x*d.x + d.y*d.y + d.z*d.z);}
+  
+  						/// Given a rotation matrix O which tells the direction of the
+						/// axis, and a list of geometric object, this function recomputes the
+						/// bounding box in order to enclose 'ngeos' geometries, from index 'firstgeo' 
+						/// Box may be also 'inflated' by a thinckness='envelope' 
+  void     FitToGeometries(ChMatrix33<>& O, std::vector<ChGeometry*> mgeos, int firstgeo, int ngeos, double envelope);
+
+  						/// Find if two box OBB are overlapping, given relative 
+						/// rotation matrix B, relative translation T, and half-sizes of the two OBB
+  static bool OBB_Overlap(ChMatrix33<>& B, Vector T, Vector a, Vector b);
+
+						/// Find if two box OBB are overlapping, given relative 
+						/// rotation matrix B, relative translation T, and the two OBB
+  static bool OBB_Overlap(ChMatrix33<>& B, Vector T, CHOBB *b1, CHOBB *b2);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif
+
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCOBBTree.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCOBBTree.cpp
new file mode 100644
index 0000000..ff3738a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCOBBTree.cpp
@@ -0,0 +1,418 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChCOBBTree.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include <stdio.h>
+#include <string.h>
+
+#include "ChCMatVec.h"
+#include "ChCGetTime.h"
+#include "ChCOBBTree.h"
+#include "core/ChTrasform.h"
+
+
+
+namespace chrono
+{
+namespace collision
+{
+
+
+
+
+
+CHOBBTree::CHOBBTree()
+{
+	current_box = 0;
+}
+
+
+CHOBBTree::~CHOBBTree()
+{
+	ResetModel();
+}
+
+
+
+int CHOBBTree::ResetModel()
+{
+  // INHERIT PARENT CLASS RESET FUNCTION
+  ChCollisionTree::ResetModel();
+
+  b.clear();
+
+  current_box = 0;
+
+  return ChC_OK;
+}
+
+
+int CHOBBTree::BuildModel(double envelope)
+{
+  // INHERIT PARENT CLASS RESET FUNCTION
+  ChCollisionTree::BuildModel(envelope);
+
+  if (build_state == ChC_BUILD_STATE_PROCESSED)
+  {
+	  return ChC_OK;
+  }
+
+  // create an array of BVs for the model
+
+  b.clear();
+
+  if (num_geometries==0) 
+	return ChC_OK;
+
+  b.resize(2*num_geometries - 1);
+
+  current_box = 0;
+
+
+  // we should build the model now.
+
+  build_model(envelope);	// %%%%%%%%%%%% BUILD HIERARCHY HERE %%%%%%%%%%%
+
+  build_state = ChC_BUILD_STATE_PROCESSED;
+
+
+  return ChC_OK;
+}
+
+
+void recurse_scan_OBBs (ChMatrix33<>& PrevRot, Vector& PrevPos,
+						CHOBBTree* mmodel, int nb,
+						void* userdata, int current_level, int& counter,
+						void callback(ChMatrix33<>& Rot,Vector& Pos,Vector& d,int level, void* userdata))
+{
+	counter++;
+
+	// compute root-relative coords for each box
+	ChMatrix33<> Rot;
+	Vector Pos;
+	ChMatrix33<> tempRot;
+	Vector tempPos;
+	tempRot.MatrMultiply(PrevRot, mmodel->child(nb)->Rot);
+    tempPos = ChTrasform<>::TrasformLocalToParent(mmodel->child(nb)->To, PrevPos, PrevRot);
+	Rot.CopyFromMatrix(tempRot);
+	Pos = tempPos;
+
+	// execute callback
+	callback(Rot, Pos, mmodel->child(nb)->d, current_level, userdata);
+
+	// break recursion on leaf
+	if (mmodel->child(nb)->IsLeaf())
+		return;
+
+	int c1 = mmodel->child(nb)->first_child;
+    int c2 = c1 + 1;
+
+	int new_currlevel = current_level + 1;
+
+	recurse_scan_OBBs(Rot, Pos, mmodel, c1, userdata, new_currlevel, counter, callback);
+
+	recurse_scan_OBBs(Rot, Pos, mmodel, c2, userdata, new_currlevel, counter, callback);
+
+}
+
+int CHOBBTree::TraverseBoundingBoxes( void callback(ChMatrix33<>& Rot,Vector& Pos,Vector& d,int level, void* userdata),
+									  void* userdata)
+{
+	int nboxes = 0;
+
+	static ChMatrix33<> mrot;
+	mrot.Set33Identity();
+	static Vector mpos;
+	mpos = VNULL;
+
+	recurse_scan_OBBs(mrot, mpos, this, 0, userdata, 0, nboxes, callback);
+
+	return nboxes;
+}
+
+
+///////////////////////////////////////////////////////////////////
+
+//
+// Building of the model
+//
+
+
+
+
+
+void get_centroid_geometries(PQP_REAL c[3], std::vector<ChGeometry*>& mgeos, int firstgeo, int ngeos)
+{
+
+  c[0] = c[1] = c[2] = 0.0;
+
+  // get center of mass
+  ChGeometry* nit;
+  for(int count = 0; count < ngeos; ++count)
+  {
+	nit = mgeos[firstgeo+count];
+
+	Vector baricenter = nit->Baricenter();
+
+    c[0] += baricenter.x;
+    c[1] += baricenter.y;
+    c[2] += baricenter.z;
+  }
+
+  c[0] /= ngeos;
+  c[1] /= ngeos;
+  c[2] /= ngeos;
+}
+
+
+void get_covariance_geometries(PQP_REAL M[3][3], std::vector<ChGeometry*>& mgeos, int firstgeo, int ngeos)
+{
+  static Vector S1;
+  static Vector S1_geo;
+  static ChMatrix33<> S2;
+  static ChMatrix33<> S2_geo;
+  S1 = VNULL;
+  S1_geo = VNULL;
+  S2.Reset();
+  S2_geo.Reset();
+
+  // get center of mass
+  ChGeometry* nit;
+  for(int count = 0; count < ngeos; ++count)
+  {
+	nit = mgeos[firstgeo+count];
+
+	S1_geo = nit->Baricenter();
+
+	S1 = Vadd(S1, S1_geo);
+
+	nit->CovarianceMatrix(S2_geo);
+
+	S2.MatrInc(S2_geo);
+  }
+
+  // now get covariances
+
+  M[0][0] = S2(0,0) - S1.x*S1.x / ngeos;
+  M[1][1] = S2(1,1) - S1.y*S1.y / ngeos;
+  M[2][2] = S2(2,2) - S1.z*S1.z / ngeos;
+  M[0][1] = S2(0,1) - S1.x*S1.y / ngeos;
+  M[1][2] = S2(1,2) - S1.y*S1.z / ngeos;
+  M[0][2] = S2(0,2) - S1.x*S1.z / ngeos;
+  M[1][0] = M[0][1];
+  M[2][0] = M[0][2];
+  M[2][1] = M[1][2];
+}
+
+
+
+
+int split_geometries(std::vector<ChGeometry*>& mgeos, int firstgeo, int ngeos, PQP_REAL a[3], PQP_REAL c)
+{
+  int c1 = 0;
+  PQP_REAL p[3];
+  PQP_REAL x;
+  ChGeometry* temp;
+
+
+  for(int count = 0; count < ngeos; count++)
+  {
+    int i = count+firstgeo;
+
+    // loop invariant: up to (but not including) index c1 in group 1,
+    // then up to (but not including) index i in group 2
+    //
+    //  [1] [1] [1] [1] [2] [2] [2] [x] [x] ... [x]
+    //                   c1          i
+    //
+	Vector vg = mgeos[i]->Baricenter();
+    p[0] = vg.x;
+	p[1] = vg.y;
+	p[2] = vg.z;
+
+    x = VdotV(p, a);
+
+    if (x <= c)
+    {
+	    // group 1
+	    temp = mgeos[i];
+	    mgeos[i] = mgeos[firstgeo+c1];
+	    mgeos[firstgeo+c1] = temp;
+	    c1++;
+    }
+    else
+    {
+	    // group 2 -- do nothing
+    }
+  }
+
+  // split arbitrarily if one group empty
+
+  if ((c1 == 0) || (c1 == ngeos)) c1 = ngeos/2;
+
+  return c1;
+}
+
+
+
+
+// Fits m->child(bn) to the num_tris triangles starting at first_tri
+// Then, if num_tris is greater than one, partitions the tris into two
+// sets, and recursively builds two children of m->child(bn)
+
+int build_recurse(CHOBBTree *m, int bn, int first_geo, int num_geos, double envelope)
+{
+  CHOBB *b = m->child(bn);
+
+  // compute a rotation matrix
+
+  PQP_REAL C[3][3], E[3][3], R[3][3], s[3], axis[3], mean[3], coord;
+
+  get_covariance_geometries(C, m->geometries, first_geo, num_geos);
+
+  Meigen(E, s, C);
+
+  // place axes of E in order of increasing s
+
+  int min, mid, max;
+  if (s[0] > s[1]) { max = 0; min = 1; }
+  else { min = 0; max = 1; }
+  if (s[2] < s[min]) { mid = min; min = 2; }
+  else if (s[2] > s[max]) { mid = max; max = 2; }
+  else { mid = 2; }
+  McolcMcol(R,0,E,max);
+  McolcMcol(R,1,E,mid);
+  R[0][2] = E[1][max]*E[2][mid] - E[1][mid]*E[2][max];
+  R[1][2] = E[0][mid]*E[2][max] - E[0][max]*E[2][mid];
+  R[2][2] = E[0][max]*E[1][mid] - E[0][mid]*E[1][max];
+
+  static ChMatrix33<> Rch;
+  Rch.Set33Element(0,0, R[0][0]);Rch.Set33Element(0,1, R[0][1]);Rch.Set33Element(0,2, R[0][2]);
+  Rch.Set33Element(1,0, R[1][0]);Rch.Set33Element(1,1, R[1][1]);Rch.Set33Element(1,2, R[1][2]);
+  Rch.Set33Element(2,0, R[2][0]);Rch.Set33Element(2,1, R[2][1]);Rch.Set33Element(2,2, R[2][2]);
+
+  // fit the BV
+
+  b->FitToGeometries(Rch, m->geometries, first_geo, num_geos, envelope);
+
+  if (num_geos == 1)
+  {
+    // BV is a leaf BV - first_child will index a triangle
+
+    b->first_child = -(first_geo + 1);
+  }
+  else if (num_geos > 1)
+  {
+    // BV not a leaf - first_child will index a BV
+
+    b->first_child = m->current_box;
+    m->current_box +=2;
+
+    // choose splitting axis and splitting coord
+
+    McolcV(axis,R,0);
+
+	get_centroid_geometries(mean, m->geometries, first_geo, num_geos);
+
+    coord = VdotV(axis, mean);
+
+    // now split
+
+    int num_first_half = split_geometries(m->geometries, first_geo, num_geos, axis, coord);
+
+    // recursively build the children
+
+    build_recurse(m, m->child(bn)->first_child, first_geo, num_first_half,
+					envelope);
+    build_recurse(m, m->child(bn)->first_child + 1,
+                  first_geo + num_first_half, num_geos - num_first_half,
+					envelope);
+  }
+  return ChC_OK;
+}
+
+
+
+
+// This descends the hierarchy, converting world-relative
+// transforms to parent-relative transforms
+
+void make_parent_relative(CHOBBTree *m, int bn,
+                     ChMatrix33<>& parentR,
+                     Vector& parentTo
+                    )
+{
+  static ChMatrix33<> Rpc;
+  static Vector Tpc;
+
+  if (!m->child(bn)->IsLeaf())
+  {
+    // make children parent-relative
+
+    make_parent_relative(m,m->child(bn)->first_child,
+                          m->child(bn)->Rot,
+                          m->child(bn)->To
+                         );
+    make_parent_relative(m,m->child(bn)->first_child+1,
+                          m->child(bn)->Rot,
+                          m->child(bn)->To
+                         );
+  }
+
+  // make self parent relative
+
+  Rpc.MatrTMultiply(parentR, m->child(bn)->Rot);	// MTxM(Rpc,parentR,m->child(bn)->R);
+  m->child(bn)->Rot.CopyFromMatrix(Rpc);			// McM(m->child(bn)->R,Rpc);
+  Tpc = Vsub(m->child(bn)->To,parentTo);			// VmV(Tpc,m->child(bn)->To,parentTo);
+  m->child(bn)->To = parentR.MatrT_x_Vect(Tpc);		// Tpc MTxV(m->child(bn)->To,parentR,Tpc);
+
+}
+
+
+
+
+int CHOBBTree::build_model(double envelope)
+{
+  // set num_bvs to 1, the first index for a child bv
+
+  current_box = 1;
+
+  // build recursively
+
+  build_recurse(this, 0, 0, num_geometries, envelope);
+
+  // change BV orientations from world-relative to parent-relative
+
+  static ChMatrix33<> R;
+  static Vector T;
+
+  R.Set33Identity();
+  T = VNULL;
+
+  make_parent_relative(this,0, R, T);
+
+  return ChC_OK;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCOBBTree.h b/SRC/ChronoEngine/collision/edgetempest/ChCOBBTree.h
new file mode 100644
index 0000000..ab85bf8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCOBBTree.h
@@ -0,0 +1,95 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_OBBTREE
+#define CHC_OBBTREE
+
+//////////////////////////////////////////////////
+//  
+//   ChCOBBTree.h
+//
+//   Class for the binary space partitioning tree 
+//   (aka BSP) based on OBB bounding volumes
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChCCollisionTree.h"
+#include "ChCOBB.h"
+
+ 
+namespace chrono 
+{
+namespace collision 
+{
+
+
+///
+/// Class containing a tree of Object oriented boxes OOB, 
+/// ready for collision detection.
+///
+
+
+class CHOBBTree : public ChCollisionTree
+{
+
+public:
+
+  CHOBBTree();
+  ~CHOBBTree();
+
+		/// Deletes all inserted geometries and resets bounding box hierarchies
+  int ResetModel();
+
+		/// Rebuilds the OBB BV hierarchy
+		/// (boxes may be inflated by an 'envelope' amount).
+  int BuildModel(double envelope=0.);
+
+		/// This function can be used if you want to easily scan the hierarchy 
+		/// of bounding boxes. You must provide a callback to a function which 
+		/// will be automatically called per each bounding box in this tree.
+		/// Note that the callback will get info about the rotation Rot of the 
+		/// box, its position Pos, its size d, its level. Also you can pass generic
+		/// user data via a pointer.  \return the number of scanned boxes.  
+  int TraverseBoundingBoxes( void callback(ChMatrix33<>& Rot,Vector& Pos,Vector& d,int level, void* userdata),
+									  void* userdata);
+	
+		/// Returns the n-th child of the tree.
+	CHOBB* child(int n) { return &b[n]; }
+
+public:
+
+		/// Vector of AABB bounding boxes.
+	std::vector<CHOBB> b;
+
+		/// Used by internal algorithms
+	int current_box;
+
+		/// From geometric objects, builds the hierarchy of BV bounding volumes
+	int build_model(double envelope);
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCOBBcollider.cpp b/SRC/ChronoEngine/collision/edgetempest/ChCOBBcollider.cpp
new file mode 100644
index 0000000..2625449
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCOBBcollider.cpp
@@ -0,0 +1,212 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCOBBcollider.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+#include <string.h>
+
+
+#include "ChCMatVec.h"
+#include "ChCGetTime.h"
+#include "ChCOBBcollider.h"
+ 
+#include "ChCGeometryCollider.h"
+#include "core/ChTrasform.h"
+
+
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+
+CHOBBcollider::CHOBBcollider()
+{
+
+}
+
+CHOBBcollider::~CHOBBcollider()
+{
+
+}
+
+
+
+
+
+void CHOBBcollider::CollideRecurse(
+               ChMatrix33<>& boR, Vector& boT, 
+               CHOBBTree *o1, int b1, 
+               CHOBBTree *o2, int b2, 
+			   eCollMode flag)
+{
+  this->num_bv_tests++;
+
+  CHOBB* box1 = o1->child(b1);
+  CHOBB* box2 = o2->child(b2);
+
+  // first thing, see if we're overlapping
+  if (!CHOBB::OBB_Overlap(boR, boT, box1, box2)) 
+	  return;
+ 
+  // if we are, see if we test geometries next
+
+  int l1 = box1->IsLeaf();
+  int l2 = box2->IsLeaf();
+ 
+  //
+  // CASE TWO LEAVES
+  //
+
+  if (l1 && l2) 
+  {
+    this->num_geo_tests++;
+
+    // transform the points in b2 into space of b1, then compare
+
+	ChGeometry* mgeo1 = o1->geometries[box1->GetGeometryIndex()];
+	ChGeometry* mgeo2 = o2->geometries[box2->GetGeometryIndex()];
+
+	bool just_intersect = false;
+	if (flag==ChNarrowPhaseCollider::ChC_FIRST_CONTACT)
+		just_intersect = true;
+
+
+	ChGeometryCollider::ComputeCollisions(*mgeo1, &this->R1, &this->T1, 
+										  *mgeo2, &this->R2, &this->T2, 
+										  *this, 
+										  &this->R, &this->T, 
+										  just_intersect);
+	return;
+  } 
+
+  // we dont, so decide whose children to visit next
+
+  double sz1 = box1->GetSize();
+  double sz2 = box2->GetSize();
+
+  ChMatrix33<> Rc;
+  Vector Tc;
+    
+  if (l2 || (!l1 && (sz1 > sz2)))
+  {
+    int c1 = box1->GetFirstChildIndex();
+    int c2 = box1->GetSecondChildIndex();
+
+	Rc.MatrTMultiply(o1->child(c1)->Rot, boR);	
+
+	Tc = ChTrasform<>::TrasformParentToLocal(boT, o1->child(c1)->To, o1->child(c1)->Rot);
+
+    CollideRecurse(Rc,Tc,o1,c1,o2,b2,flag);
+
+
+     if ((flag == ChC_FIRST_CONTACT) && (this->GetNumPairs() > 0)) return;
+
+    Rc.MatrTMultiply(o1->child(c2)->Rot, boR);		
+ 
+	Tc = ChTrasform<>::TrasformParentToLocal(boT, o1->child(c2)->To, o1->child(c2)->Rot);
+
+    CollideRecurse(Rc,Tc,o1,c2,o2,b2,flag);
+  }
+  else 
+  {
+    int c1 = box2->GetFirstChildIndex();
+    int c2 = box2->GetSecondChildIndex();
+
+    Rc.MatrMultiply(boR, o2->child(c1)->Rot);		  
+
+    Tc = ChTrasform<>::TrasformLocalToParent(o2->child(c1)->To,boT, boR); 
+
+    CollideRecurse(Rc,Tc,o1,b1,o2,c1,flag);
+
+
+     if ((flag == ChC_FIRST_CONTACT) && (this->GetNumPairs() > 0)) return;
+
+    Rc.MatrMultiply(boR, o2->child(c2)->Rot);		  
+
+    Tc = ChTrasform<>::TrasformLocalToParent(o2->child(c2)->To,boT, boR); 
+
+    CollideRecurse(Rc,Tc,o1,b1,o2,c2,flag);
+  }
+}
+
+
+//
+// PERFORM COLLISION DETECTION
+//
+
+ChNarrowPhaseCollider::eCollSuccess CHOBBcollider::ComputeCollisions(
+            ChMatrix33<>& R1, Vector T1, ChCollisionTree *oc1,
+            ChMatrix33<>& R2, Vector T2, ChCollisionTree *oc2,
+            eCollMode flag)
+{
+  double t1 = GetTime();
+
+  // INHERIT parent class behaviour
+
+  if (ChNarrowPhaseCollider::ComputeCollisions(
+			R1, T1, oc1,
+            R2, T2, oc2,
+            flag) != ChC_RESULT_OK)
+				return ChC_RESULT_GENERICERROR;
+ 
+  // Downcasting 
+  CHOBBTree* o1 = (CHOBBTree*)oc1;
+  CHOBBTree* o2 = (CHOBBTree*)oc2;
+
+  // clear the stats
+
+  this->num_bv_tests = 0;
+  this->num_geo_tests = 0;
+  
+  
+  // compute the transform from o1->child(0) to o2->child(0)
+
+  static ChMatrix33<> Rtemp;
+  static ChMatrix33<> bR;
+  static Vector bT;
+  static Vector Ttemp;
+
+  Rtemp.MatrMultiply(this->R,o2->child(0)->Rot);	// MxM(Rtemp,this->R,o2->child(0)->R);
+  bR.MatrMultiply(o1->child(0)->Rot, Rtemp);		// MTxM(R,o1->child(0)->R,Rtemp);
+
+  Ttemp = ChTrasform<>::TrasformLocalToParent(o2->child(0)->To, this->T, this->R); // MxVpV(Ttemp,this->R,o2->child(0)->To,this->T);
+  Ttemp = Vsub(Ttemp, o1->child(0)->To);		// VmV(Ttemp,Ttemp,o1->child(0)->To);
+
+  bT = o1->child(0)->Rot.MatrT_x_Vect(Ttemp);		// MTxV(T,o1->child(0)->R,Ttemp);
+
+  // now start with both top level BVs  
+
+  CollideRecurse(bR,bT,o1,0,o2,0,flag);
+  
+  double t2 = GetTime();
+  this->query_time_secs = t2 - t1;
+  
+  return ChC_RESULT_OK; 
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCOBBcollider.h b/SRC/ChronoEngine/collision/edgetempest/ChCOBBcollider.h
new file mode 100644
index 0000000..34cc70b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCOBBcollider.h
@@ -0,0 +1,94 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_OBBCOLLIDER
+#define CHC_OBBCOLLIDER
+
+//////////////////////////////////////////////////
+//  
+//   ChCOBBcollider.h
+//
+//   Detects collisions between a pair of models 
+//   based on OBBs
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChCCompile.h"   
+#include "collision/ChCCollisionPair.h"                            
+#include "ChCOBBTree.h"
+#include "ChCNarrowPhaseCollider.h"
+
+
+namespace chrono 
+{
+namespace collision 
+{
+
+
+/// 
+/// This class specializes the ChNarrowPhaseCollider base class, in order
+/// to compute the case of collisions between two collision models
+/// based on AABB trees.
+///
+
+class CHOBBcollider : public ChNarrowPhaseCollider
+{
+public:
+
+  CHOBBcollider();
+  ~CHOBBcollider();
+
+			/// Perform collision detection between two OBB-based
+			/// collision models (each belonging to a different rigid
+			/// body, for example), given the absolute orientations and
+			/// translations of the two models.
+			/// The identified contacts will be inserted in the Contacts vector.
+			///
+   eCollSuccess ComputeCollisions(
+            ChMatrix33<>& R1, Vector T1, ChCollisionTree *oc1,
+            ChMatrix33<>& R2, Vector T2, ChCollisionTree *oc2,
+			eCollMode flag);
+
+private:
+	
+	void CollideRecurse(
+               ChMatrix33<>& R, Vector& T, 
+               CHOBBTree *o1, int b1, 
+               CHOBBTree *o2, int b2, 
+			   eCollMode flag);
+};
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
+
+
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/edgetempest/ChCSweepAndPrune.h b/SRC/ChronoEngine/collision/edgetempest/ChCSweepAndPrune.h
new file mode 100644
index 0000000..d12b0ad
--- /dev/null
+++ b/SRC/ChronoEngine/collision/edgetempest/ChCSweepAndPrune.h
@@ -0,0 +1,433 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_SWEEPANDPRUNE_H
+#define CHC_SWEEPANDPRUNE_H
+
+//////////////////////////////////////////////////
+//
+//   ChCSweepAndPrune.h
+//
+//   Header for the 'sweep and prune' broad-phase
+//   collision detection stage.
+//
+//   Part of the code is a modified version of the
+//   retro_sweepnprune.h code from the OpenTissue
+//   project, by K.Erleben:
+//
+//   "OpenTissue, A toolbox for physical based simulation and animation.
+//   Copyright (C) 2004 Department of Computer Science, University of Copenhagen"
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#if	(_MSC_VER >= 1200)
+ #pragma warning(4: 4786)
+#endif
+
+
+#include "geometry/ChCGeometry.h"
+#include "ChCBroadPhaseCollider.h"
+#include "core/ChWrapHashmap.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+
+namespace chrono
+{
+namespace collision
+{
+
+
+
+
+///
+/// Class for the 'sweep and prune' broad-phase collision.
+///  This phase organizes all the min-max endpoints of the
+/// AABB boxes of bodies into three sorted lists for the
+/// x,y,z world axes. Overlapping pairs are roughly
+/// detected in quasi-linear time during the sorting operation,
+/// which is almost linear especially if a previous sorting is
+/// available (i.e.: please exploit coherence as much as possible)
+///  This algorithm uses an hash search to store/retrieve the
+/// partial overlaps, for maximum speed efficiency - however it
+/// may need lot of memory for storing the partial overlaps, when
+/// number of objects is high (>1000).
+///
+
+template<class model_type>
+class ChSweepAndPrune : public ChBroadPhaseCollider<model_type>
+{
+  protected:
+
+    typedef typename ChIntervalEndpoint<model_type> ChEndPoint;
+    typedef typename std::list<ChEndPoint*>         ChAxisOfCoordinates;
+    typedef typename chronohash::hash_map<unsigned int, ChMates<model_type>*>  ChMatesPtrMap;
+
+    ChAxisOfCoordinates m_axisX;             ///< X-Axis. The x-coordinates of AABB interval endpoints.
+    ChAxisOfCoordinates m_axisY;             ///< Y-Axis. The y-coordinates of AABB interval endpoints.
+    ChAxisOfCoordinates m_axisZ;             ///< Z-Axis. The z-coordinates of AABB interval endpoints.
+
+
+	ChMatesPtrList m_reported;	 ///< A list containing the currently reported overlaps.
+
+	ChMatesPtrMap m_mates;	     ///< An hash map with partial overlaps (only true overlaps if their counter =3)
+
+
+
+
+  public:
+					/// Constructor
+    ChSweepAndPrune()
+				{
+				};
+
+					/// Destructor
+	virtual ~ChSweepAndPrune(void)
+				{
+					removeAllChMates();	// this because mates were instanced
+				}
+
+
+					/// Clears all data instanced by this algorithm.
+    virtual void Clear(void)
+				{
+				  m_axisX.clear();
+				  m_axisY.clear();
+				  m_axisZ.clear();
+				  m_reported.clear();
+				  removeAllChMates();			
+				};
+
+					/// Adds a collision model to the broad-phase
+					/// engine (custom data may be allocated).
+    virtual void Add(model_type* model)
+				{
+				  m_axisX.push_back(&model->m_absoluteAABB.m_beginX);
+				  m_axisX.push_back(&model->m_absoluteAABB.m_endX);
+				  m_axisY.push_back(&model->m_absoluteAABB.m_beginY);
+				  m_axisY.push_back(&model->m_absoluteAABB.m_endY);
+				  m_axisZ.push_back(&model->m_absoluteAABB.m_beginZ);
+				  m_axisZ.push_back(&model->m_absoluteAABB.m_endZ);
+				};
+
+					/// Removes a collision model from the broad-phase
+					/// engine (custom data may be deallocated).
+    virtual void Remove(model_type* model)
+				{
+				  //assert(m_configuration);
+				  m_axisX.remove(&model->m_absoluteAABB.m_beginX);
+				  m_axisX.remove(&model->m_absoluteAABB.m_endX);
+				  m_axisY.remove(&model->m_absoluteAABB.m_beginY);
+				  m_axisY.remove(&model->m_absoluteAABB.m_endY);
+				  m_axisZ.remove(&model->m_absoluteAABB.m_beginZ);
+				  m_axisZ.remove(&model->m_absoluteAABB.m_endZ);
+
+				  // Delete references in reported pairs
+				  ChMatesPtrList::iterator repmates = m_reported.begin();
+				  while(repmates != m_reported.end())
+				  {
+						ChMates<model_type>* mymates = *repmates;
+						if ((mymates->GetModelA()==model)||(mymates->GetModelB()==model))
+						{
+							ChMatesPtrList::iterator delmates = repmates;
+							repmates++;
+							m_reported.erase(delmates);
+						}
+						else
+						{
+							repmates++;
+						}
+				  }
+
+				  // Delete references in partial pairs
+				  ChMatesPtrMap::iterator mates = m_mates.begin();
+				  while(mates != m_mates.end())
+				  {
+						if ((mates->second->GetModelA()==model)||(mates->second->GetModelB()==model))
+						{
+							ChMatesPtrMap::iterator delmates = mates;
+							mates++;
+							delete delmates->second;  // also delete allocated mates data!
+							m_mates.erase(delmates);
+						}
+						else
+						{
+							mates++;
+						}
+				  }
+
+				};
+
+
+					/// Run the 'sweep and prune' algorithm, which finds the
+					/// overlapping pairs of bounding boxes using three sort operations.
+					/// If you call this function mutiple times, the execution
+					/// time will be really small, because x,y,z lists usually change
+					/// few intervals, so sorting takes few operations (exploits time coherency)
+					/// After the algorithm has run, you can look into the list of
+					/// reported pairs using the GetReportedMates()
+	virtual void Run()
+				{ 
+				  sort(m_axisX);
+				  sort(m_axisY);
+				  sort(m_axisZ);
+
+				  //purgeUnusedChMates();
+				};
+
+
+					/// After the broad phase algorithm has run, you can use
+					/// this method to access the list with the reported pairs of
+					/// overlapping models.
+	virtual ChMatesPtrList& GetReportedMates() {return m_reported;}
+
+
+
+
+  private:
+
+
+					/// Get the connection between two bodies A and B, using the
+					/// hash mapping, to avoid linear time complexity.
+	ChMates<model_type>* getChMates(model_type* A, model_type* B)
+				{
+					assert(A);
+					assert(B);
+					assert(A!=B);
+					typename ChMatesPtrMap::iterator mates = m_mates.find(ChMates<model_type>::getHashkey(A,B));
+					if(mates==m_mates.end())
+						return 0;
+					return mates->second;
+				};
+
+					/// Store the connection between two bodies A and B, using the
+					/// hash mapping, to avoid linear time complexity.
+    ChMates<model_type>* addChMates(model_type* A, model_type* B)
+				{
+					assert(A);
+					assert(B);
+					assert(A!=B);
+					assert(m_mates.find(ChMates<model_type>::getHashkey(A,B))==m_mates.end());
+					ChMates<model_type>* mates = new ChMates<model_type>(A,B);
+					m_mates.insert(std::pair< unsigned int, ChMates<model_type>* >(mates->getHashkey(),mates));
+					return mates;
+				};
+
+	void removeAllChMates()
+				{
+					ChMatesPtrMap::iterator mates = m_mates.begin();
+					while(mates != m_mates.end())
+					{
+						delete mates->second;
+						mates++;
+					}
+
+					m_mates.clear();
+
+					//*****TO CHECK****
+				}
+
+
+	void purgeUnusedChMates()
+				{
+					ChMatesPtrMap::iterator mates = m_mates.begin();
+					while(mates != m_mates.end())
+					{
+						if (mates->second->m_snp_axis_overlap_count ==0)
+						{
+							ChMatesPtrMap::iterator delmates = mates;
+							mates++;
+							delete delmates->second;
+							m_mates.erase(delmates);
+						}
+						else
+						{
+							mates++;
+						}
+					}
+				}
+
+
+  protected:
+
+					/// Coordinate Sorting Algorithm.
+					/// Performs custom (non STL) list sorting
+    void sort(ChAxisOfCoordinates & axis)
+				{
+				  if (axis.empty()) return;
+				  typename ChAxisOfCoordinates::iterator left;
+				  typename ChAxisOfCoordinates::iterator right;
+				  typename ChAxisOfCoordinates::iterator scan = axis.begin();
+				  left = scan;
+				  ++scan;
+
+				  //--- Scan list from left to right
+				  for(;scan!=axis.end();)
+				  {
+					right = scan;
+					++right;
+					//--- Check if we encountered an element that was smaller
+					//--- than its left neighbor
+					if( isWrong(*left,*scan) )
+					{
+					  //--- If so we contineously swap the element to the left
+					  //--- in the list until its left neighbor is no longer
+					  //--- bigger than itself
+					  typename ChAxisOfCoordinates::iterator _right;
+					  typename ChAxisOfCoordinates::iterator _left;
+					  _right = scan;
+					  _left  = left;
+					  do 
+					  {
+						//Boxes was crossing: test if broad phase collision
+					    //must be reported
+						swapAction(*_left,*_right);
+						//std::iter_swap(_right,_left); //***vc6
+						std::swap(*_right,*_left); //***vc2003
+						_right = _left;
+						if (_left==axis.begin()) break; 
+						--_left;
+					  }
+					  while(isWrong(*_left,*_right)); 
+					}
+					//--- Now we can pick up the overall left-to-right scan again
+					left = scan;
+					scan = right;
+				  }
+				};
+
+
+					/// Wrongly Sorted Query Method.
+					/// Computes whatever the two end
+					/// points appears in the proper order along a
+					/// coordinate axis.
+					///
+					/// @param left     A pointer to the endpoint that has the
+					///                 left position in the list (head is assumed
+					///                 to be left most and tail rightmost).
+					/// @param right    A pointer to the endpoint that has the
+					///                 right position in the list.
+					///
+					/// @return         If left and right should be swapped
+					///                 then the return value it true otherwise
+					///                 it is false.
+
+    const bool isWrong(ChEndPoint * left,ChEndPoint * right)
+				{
+				  //--- Values must be sorted in increasing order from left to right
+				  if(right->m_value<left->m_value)
+					return true;
+				  //--- Endpoints must be sorted so ``begin '' comes before ``end''
+				  if(right->m_value==left->m_value)
+				  {
+					if((right->m_type==0)&&(left->m_type==1))
+					  return true;
+				  }
+				  return false;
+				};
+
+					/// Swap Action.
+					/// NOTE: The method is called before the actual swap!!!
+					///
+					/// The method is assumed to perform all the appropriate
+					/// semantic actions, corresponding to the swap.
+					///
+					/// @param left     A pointer to the endpoint that has the
+					///                 left position in the list (head is assumed
+					///                 to be left most and tail rightmost).
+					/// @param right    A pointer to the endpoint that has the
+					///                 right position in the list.
+
+    void swapAction(ChEndPoint * left, ChEndPoint * right)
+				{
+				  ChMates<model_type>* mates = this->getChMates(left->m_model, right->m_model);
+				  if(mates==0)
+				  {
+					mates = this->addChMates(left->m_model,right->m_model);
+				  }
+
+				  if((left->m_type==1) && (right->m_type==0))
+				  {
+					++(mates->m_snp_axis_overlap_count);
+					if(mates->m_snp_axis_overlap_count==3)
+					{
+					  mates->m_snp_reported_overlap = m_reported.insert(m_reported.end(),mates);
+					  mates->m_snp_overlap_reported = true;
+					}
+				  }
+
+				  if((left->m_type==0) && (right->m_type==1))
+				  {
+					--(mates->m_snp_axis_overlap_count);
+					if(mates->m_snp_axis_overlap_count==2)
+					{
+					  if(mates->m_snp_overlap_reported)
+					  {
+						m_reported.erase(mates->m_snp_reported_overlap);
+						mates->m_snp_overlap_reported = false;
+					  }
+					}
+				  }
+				};
+
+  public:
+
+    const double getMin(ChAxisOfCoordinates & axis) {  return (axis.front())->m_value; };
+    const double getMax(ChAxisOfCoordinates & axis) {  return (axis.back())->m_value;  };
+
+
+					/// Debugging test tool:  consistency test method (for a single axis)
+    const bool isConsistent(ChAxisOfCoordinates & axis)
+				{
+				  if (axis.empty()) return true;
+				  typename ChAxisOfCoordinates::iterator scan = axis.begin();
+				  typename ChAxisOfCoordinates::iterator right = scan;
+				  ++right;
+				  for(;right!=axis.end();)
+				  {
+					if((*scan)->m_value > (*right)->m_value)
+					  return false;
+					scan = right;
+					++right;
+				  }
+				  return true;
+				};
+ 
+	const bool isConsistentX() {return isConsistent(this->m_axisX);}
+	const bool isConsistentY() {return isConsistent(this->m_axisY);}
+	const bool isConsistentZ() {return isConsistent(this->m_axisZ);}
+	int nEndpointsX() {return m_axisX.size();}
+	int nEndpointsY() {return m_axisY.size();}
+	int nEndpointsZ() {return m_axisZ.size();}
+	int nReported() {return m_reported.size();}
+	int nMates() {return m_mates.size();}
+
+
+}; // end of s&p class
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexBuilder.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexBuilder.cpp
new file mode 100644
index 0000000..94a4093
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexBuilder.cpp
@@ -0,0 +1,373 @@
+#include "float_math.h"
+#include "ConvexBuilder.h"
+#include "meshvolume.h"
+#include "bestfit.h"
+#include <assert.h>
+#include "cd_hull.h"
+
+#include "fitsphere.h"
+#include "bestfitobb.h"
+
+unsigned int MAXDEPTH = 8 ;
+float CONCAVE_PERCENT = 1.0f ;
+float MERGE_PERCENT   = 2.0f ;
+
+ChUll::ChUll(const ConvexResult &result)
+{
+	mResult = new ConvexResult(result);
+	mVolume = computeMeshVolume( result.mHullVertices, result.mHullTcount, result.mHullIndices );
+
+	mDiagonal = getBoundingRegion( result.mHullVcount, result.mHullVertices, sizeof(float)*3, mMin, mMax );
+
+	float dx = mMax[0] - mMin[0];
+	float dy = mMax[1] - mMin[1];
+	float dz = mMax[2] - mMin[2];
+
+	dx*=0.1f; // inflate 1/10th on each edge
+	dy*=0.1f; // inflate 1/10th on each edge
+	dz*=0.1f; // inflate 1/10th on each edge
+
+	mMin[0]-=dx;
+	mMin[1]-=dy;
+	mMin[2]-=dz;
+
+	mMax[0]+=dx;
+	mMax[1]+=dy;
+	mMax[2]+=dz;
+
+
+}
+
+ChUll::~ChUll(void)
+{
+	delete mResult;
+}
+
+bool ChUll::overlap(const ChUll &h) const
+{
+	return overlapAABB(mMin,mMax, h.mMin, h.mMax );
+}
+
+
+
+
+ConvexBuilder::ConvexBuilder(ConvexDecompInterface *callback)
+{
+	mCallback = callback;
+}
+
+ConvexBuilder::~ConvexBuilder(void)
+{
+	int i;
+	for (i=0;i<mChulls.size();i++)
+	{
+		ChUll *cr = mChulls[i];
+		delete cr;
+	}
+}
+
+bool ConvexBuilder::isDuplicate(unsigned int i1,unsigned int i2,unsigned int i3,
+								unsigned int ci1,unsigned int ci2,unsigned int ci3)
+{
+	unsigned int dcount = 0;
+
+	assert( i1 != i2 && i1 != i3 && i2 != i3 );
+	assert( ci1 != ci2 && ci1 != ci3 && ci2 != ci3 );
+
+	if ( i1 == ci1 || i1 == ci2 || i1 == ci3 ) dcount++;
+	if ( i2 == ci1 || i2 == ci2 || i2 == ci3 ) dcount++;
+	if ( i3 == ci1 || i3 == ci2 || i3 == ci3 ) dcount++;
+
+	return dcount == 3;
+}
+
+void ConvexBuilder::getMesh(const ConvexResult &cr,VertexLookup vc,UintVector &indices)
+{
+	unsigned int *src = cr.mHullIndices;
+
+	for (unsigned int i=0; i<cr.mHullTcount; i++)
+	{
+		unsigned int i1 = *src++;
+		unsigned int i2 = *src++;
+		unsigned int i3 = *src++;
+
+		const float *p1 = &cr.mHullVertices[i1*3];
+		const float *p2 = &cr.mHullVertices[i2*3];
+		const float *p3 = &cr.mHullVertices[i3*3];
+
+		i1 = Vl_getIndex(vc,p1);
+		i2 = Vl_getIndex(vc,p2);
+		i3 = Vl_getIndex(vc,p3);
+
+#if 0
+		bool duplicate = false;
+
+		unsigned int tcount = indices.size()/3;
+		for (unsigned int j=0; j<tcount; j++)
+		{
+			unsigned int ci1 = indices[j*3+0];
+			unsigned int ci2 = indices[j*3+1];
+			unsigned int ci3 = indices[j*3+2];
+			if ( isDuplicate(i1,i2,i3, ci1, ci2, ci3 ) )
+			{
+				duplicate = true;
+				break;
+			}
+		}
+
+		if ( !duplicate )
+		{
+			indices.push_back(i1);
+			indices.push_back(i2);
+			indices.push_back(i3);
+		}
+#endif
+
+	}
+}
+
+ChUll * ConvexBuilder::canMerge(ChUll *a,ChUll *b)
+{
+
+	if ( !a->overlap(*b) ) return 0; // if their AABB's (with a little slop) don't overlap, then return.
+
+	ChUll *ret = 0;
+
+	// ok..we are going to combine both meshes into a single mesh
+	// and then we are going to compute the concavity...
+
+	VertexLookup vc = Vl_createVertexLookup();
+
+	UintVector indices;
+
+	getMesh( *a->mResult, vc, indices );
+	getMesh( *b->mResult, vc, indices );
+
+	unsigned int vcount = Vl_getVcount(vc);
+	const float *vertices = Vl_getVertices(vc);
+	unsigned int tcount = indices.size()/3;
+	
+	//don't do anything if hull is empty
+	if (!tcount)
+	{
+		Vl_releaseVertexLookup (vc);
+		return 0;
+	}
+
+	HullResult hresult;
+	HullLibrary hl;
+	HullDesc   desc;
+
+	desc.SetHullFlag(QF_TRIANGLES);
+
+	desc.mVcount       = vcount;
+	desc.mVertices     = vertices;
+	desc.mVertexStride = sizeof(float)*3;
+
+	HullError hret = hl.CreateConvexHull(desc,hresult);
+
+	if ( hret == QE_OK )
+	{
+
+		float combineVolume  = computeMeshVolume( hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices );
+		float sumVolume      = a->mVolume + b->mVolume;
+
+		float percent = (sumVolume*100) / combineVolume;
+		if ( percent >= (100.0f-MERGE_PERCENT) )
+		{
+			ConvexResult cr(hresult.mNumOutputVertices, hresult.mOutputVertices, hresult.mNumFaces, hresult.mIndices);
+			ret = new ChUll(cr);
+		}
+	}
+
+
+	Vl_releaseVertexLookup(vc);
+
+	return ret;
+}
+
+bool ConvexBuilder::combineHulls(void)
+{
+
+	bool combine = false;
+
+	sortChulls(mChulls); // sort the convex hulls, largest volume to least...
+
+	ChUllVector output; // the output hulls...
+
+
+	int i;
+
+	for (i=0;i<mChulls.size() && !combine; ++i)
+	{
+		ChUll *cr = mChulls[i];
+
+		int j;
+		for (j=0;j<mChulls.size();j++)
+		{
+			ChUll *match = mChulls[j];
+
+			if ( cr != match ) // don't try to merge a hull with itself, that be stoopid
+			{
+
+				ChUll *merge = canMerge(cr,match); // if we can merge these two....
+
+				if ( merge )
+				{
+
+					output.push_back(merge);
+
+
+					++i;
+					while ( i != mChulls.size() )
+					{
+						ChUll *cr = mChulls[i];
+						if ( cr != match )
+						{
+							output.push_back(cr);
+						}
+						i++;
+					}
+
+					delete cr;
+					delete match;
+					combine = true;
+					break;
+				}
+			}
+		}
+
+		if ( combine )
+		{
+			break;
+		}
+		else
+		{
+			output.push_back(cr);
+		}
+
+	}
+
+	if ( combine )
+	{
+		mChulls.clear();
+		mChulls = output;
+		output.clear();
+	}
+
+
+	return combine;
+}
+
+unsigned int ConvexBuilder::process(const DecompDesc &desc)
+{
+
+	unsigned int ret = 0;
+
+	MAXDEPTH        = desc.mDepth;
+	CONCAVE_PERCENT = desc.mCpercent;
+	MERGE_PERCENT   = desc.mPpercent;
+
+
+	calcConvexDecomposition(desc.mVcount, desc.mVertices, desc.mTcount, desc.mIndices,this,0,0);
+
+
+	while ( combineHulls() ); // keep combinging hulls until I can't combine any more...
+
+	int i;
+	for (i=0;i<mChulls.size();i++)
+	{
+		ChUll *cr = mChulls[i];
+
+		// before we hand it back to the application, we need to regenerate the hull based on the
+		// limits given by the user.
+
+		const ConvexResult &c = *cr->mResult; // the high resolution hull...
+
+		HullResult result;
+		HullLibrary hl;
+		HullDesc   hdesc;
+
+		hdesc.SetHullFlag(QF_TRIANGLES);
+
+		hdesc.mVcount       = c.mHullVcount;
+		hdesc.mVertices     = c.mHullVertices;
+		hdesc.mVertexStride = sizeof(float)*3;
+		hdesc.mMaxVertices  = desc.mMaxVertices; // maximum number of vertices allowed in the output
+
+		if ( desc.mSkinWidth  )
+		{
+			hdesc.mSkinWidth = desc.mSkinWidth;
+			hdesc.SetHullFlag(QF_SKIN_WIDTH); // do skin width computation.
+		}
+
+		HullError ret = hl.CreateConvexHull(hdesc,result);
+
+		if ( ret == QE_OK )
+		{
+			ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);
+
+			r.mHullVolume = computeMeshVolume( result.mOutputVertices, result.mNumFaces, result.mIndices ); // the volume of the hull.
+
+			// compute the best fit OBB
+			computeBestFitOBB( result.mNumOutputVertices, result.mOutputVertices, sizeof(float)*3, r.mOBBSides, r.mOBBTransform );
+
+			r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] *r.mOBBSides[2]; // compute the OBB volume.
+
+			fm_getTranslation( r.mOBBTransform, r.mOBBCenter );      // get the translation component of the 4x4 matrix.
+
+			fm_matrixToQuat( r.mOBBTransform, r.mOBBOrientation );   // extract the orientation as a quaternion.
+
+			r.mSphereRadius = computeBoundingSphere( result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter );
+			r.mSphereVolume = fm_sphereVolume( r.mSphereRadius );
+
+
+			mCallback->ConvexDecompResult(r);
+		}
+
+		hl.ReleaseResult (result);
+
+
+		delete cr;
+	}
+
+	ret = mChulls.size();
+
+	mChulls.clear();
+
+	return ret;
+}
+
+
+void ConvexBuilder::ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color)
+{
+	mCallback->ConvexDebugTri(p1,p2,p3,color);
+}
+
+void ConvexBuilder::ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color)
+{
+	mCallback->ConvexDebugOBB(sides,matrix,color);
+}
+void ConvexBuilder::ConvexDebugPoint(const float *p,float dist,unsigned int color)
+{
+	mCallback->ConvexDebugPoint(p,dist,color);
+}
+
+void ConvexBuilder::ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color)
+{
+	mCallback->ConvexDebugBound(bmin,bmax,color);
+}
+
+void ConvexBuilder::ConvexDecompResult(ConvexResult &result)
+{
+	ChUll *ch = new ChUll(result);
+	mChulls.push_back(ch);
+}
+
+void ConvexBuilder::sortChulls(ChUllVector &hulls)
+{
+	hulls.quickSort(ChUllSort());
+	//hulls.heapSort(ChUllSort());
+}
+
+
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexBuilder.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexBuilder.h
new file mode 100644
index 0000000..37adb6c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexBuilder.h
@@ -0,0 +1,112 @@
+#ifndef CONVEX_BUILDER_H
+#define CONVEX_BUILDER_H
+
+/*----------------------------------------------------------------------
+Copyright (c) 2004 Open Dynamics Framework Group
+www.physicstools.org
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions
+and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+#include "ConvexDecomposition.h"
+#include "vlookup.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+using namespace ConvexDecomposition;
+
+
+class ChUll
+{
+public:
+	ChUll(const ConvexResult &result);
+
+	~ChUll(void);
+
+	bool overlap(const ChUll &h) const;
+
+	float          mMin[3];
+	float          mMax[3];
+	float          mVolume;
+	float          mDiagonal; // long edge..
+	ConvexResult  *mResult;
+};
+
+// Usage: std::sort( list.begin(), list.end(), StringSortRef() );
+class ChUllSort
+{
+public:
+
+	inline bool operator()(const ChUll *a,const ChUll *b) const
+	{
+		return a->mVolume < b->mVolume;
+	}
+};
+
+
+typedef btAlignedObjectArray< ChUll * > ChUllVector;
+
+
+
+class ConvexBuilder : public ConvexDecompInterface
+{
+public:
+	ConvexBuilder(ConvexDecompInterface *callback);
+
+	virtual ~ConvexBuilder(void);
+
+	bool isDuplicate(unsigned int i1,unsigned int i2,unsigned int i3,
+		unsigned int ci1,unsigned int ci2,unsigned int ci3);
+
+	void getMesh(const ConvexResult &cr,VertexLookup vc,UintVector &indices);
+
+	ChUll * canMerge(ChUll *a,ChUll *b);
+
+	bool combineHulls(void);
+
+	unsigned int process(const DecompDesc &desc);
+
+	virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color);
+
+	virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color);
+	virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color);
+
+	virtual void ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color);
+
+	virtual void ConvexDecompResult(ConvexResult &result);
+
+	void sortChulls(ChUllVector &hulls);
+
+	ChUllVector     mChulls;
+	ConvexDecompInterface *mCallback;
+};
+
+#endif //CONVEX_BUILDER_H
+
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexDecomposition.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexDecomposition.cpp
new file mode 100644
index 0000000..572d25f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexDecomposition.cpp
@@ -0,0 +1,375 @@
+#include "float_math.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+#include "ConvexDecomposition.h"
+#include "cd_vector.h"
+#include "cd_hull.h"
+#include "bestfit.h"
+#include "planetri.h"
+#include "vlookup.h"
+#include "splitplane.h"
+#include "meshvolume.h"
+#include "concavity.h"
+#include "bestfitobb.h"
+#include "float_math.h"
+#include "fitsphere.h"
+
+#define SHOW_MESH 0
+#define MAKE_MESH 1
+
+
+using namespace ConvexDecomposition;
+
+
+
+namespace ConvexDecomposition
+{
+
+class FaceTri
+{
+public:
+	FaceTri(void) { };
+  FaceTri(const float *vertices,unsigned int i1,unsigned int i2,unsigned int i3)
+  {
+  	mP1.Set( &vertices[i1*3] );
+  	mP2.Set( &vertices[i2*3] );
+  	mP3.Set( &vertices[i3*3] );
+  }
+
+  Vector3d	mP1;
+  Vector3d	mP2;
+  Vector3d	mP3;
+  Vector3d mNormal;
+
+};
+
+
+void addTri(VertexLookup vl,UintVector &list,const Vector3d &p1,const Vector3d &p2,const Vector3d &p3)
+{
+  unsigned int i1 = Vl_getIndex(vl, p1.Ptr() );
+  unsigned int i2 = Vl_getIndex(vl, p2.Ptr() );
+  unsigned int i3 = Vl_getIndex(vl, p3.Ptr() );
+
+  // do *not* process degenerate triangles!
+
+  if ( i1 != i2 && i1 != i3 && i2 != i3 )
+  {
+    list.push_back(i1);
+    list.push_back(i2);
+    list.push_back(i3);
+  }
+}
+
+
+void calcConvexDecomposition(unsigned int           vcount,
+                                const float           *vertices,
+                                unsigned int           tcount,
+                                const unsigned int    *indices,
+                                ConvexDecompInterface *callback,
+                                float                  masterVolume,
+                                unsigned int           depth)
+
+{
+
+  float plane[4];
+
+  bool split = false;
+
+
+  if ( depth < MAXDEPTH )
+  {
+
+		float volume;
+		float c = computeConcavity( vcount, vertices, tcount, indices, callback, plane, volume );
+
+    if ( depth == 0 )
+    {
+      masterVolume = volume;
+    }
+
+		float percent = (c*100.0f)/masterVolume;
+
+		if ( percent > CONCAVE_PERCENT ) // if great than 5% of the total volume is concave, go ahead and keep splitting.
+		{
+      split = true;
+    }
+
+  }
+
+  if ( depth >= MAXDEPTH || !split )
+  {
+
+#if 1
+
+    HullResult result;
+    HullLibrary hl;
+    HullDesc   desc;
+
+  	desc.SetHullFlag(QF_TRIANGLES);
+
+    desc.mVcount       = vcount;
+    desc.mVertices     = vertices;
+    desc.mVertexStride = sizeof(float)*3;
+
+    HullError ret = hl.CreateConvexHull(desc,result);
+
+    if ( ret == QE_OK )
+    {
+
+			ConvexResult r(result.mNumOutputVertices, result.mOutputVertices, result.mNumFaces, result.mIndices);
+
+
+			callback->ConvexDecompResult(r);
+    }
+
+
+#else
+
+		static unsigned int colors[8] =
+		{
+			0xFF0000,
+		  0x00FF00,
+			0x0000FF,
+			0xFFFF00,
+			0x00FFFF,
+			0xFF00FF,
+			0xFFFFFF,
+			0xFF8040
+		};
+
+		static int count = 0;
+
+		count++;
+
+		if ( count == 8 ) count = 0;
+
+		assert( count >= 0 && count < 8 );
+
+		unsigned int color = colors[count];
+
+    const unsigned int *source = indices;
+
+    for (unsigned int i=0; i<tcount; i++)
+    {
+
+      unsigned int i1 = *source++;
+      unsigned int i2 = *source++;
+      unsigned int i3 = *source++;
+
+			FaceTri t(vertices, i1, i2, i3 );
+
+      callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(), t.mP3.Ptr(), color );
+
+    }
+#endif
+
+    hl.ReleaseResult (result);
+    return;
+
+  }
+
+  UintVector ifront;
+  UintVector iback;
+
+  VertexLookup vfront = Vl_createVertexLookup();
+  VertexLookup vback  = Vl_createVertexLookup();
+
+
+	bool showmesh = false;
+  #if SHOW_MESH
+  showmesh = true;
+  #endif
+
+	if ( 0 )
+	{
+		showmesh = true;
+	  for (float x=-1; x<1; x+=0.10f)
+		{
+		  for (float y=0; y<1; y+=0.10f)
+			{
+			  for (float z=-1; z<1; z+=0.04f)
+				{
+				  float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3];
+					Vector3d p(x,y,z);
+				  if ( d >= 0 )
+					  callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0x00FF00);
+				  else
+					  callback->ConvexDebugPoint(p.Ptr(), 0.02f, 0xFF0000);
+				}
+			}
+		}
+	}
+
+	if ( 1 )
+	{
+		// ok..now we are going to 'split' all of the input triangles against this plane!
+		const unsigned int *source = indices;
+		for (unsigned int i=0; i<tcount; i++)
+		{
+			unsigned int i1 = *source++;
+			unsigned int i2 = *source++;
+			unsigned int i3 = *source++;
+
+			FaceTri t(vertices, i1, i2, i3 );
+
+			Vector3d front[4];
+			Vector3d back[4];
+
+			unsigned int fcount=0;
+			unsigned int bcount=0;
+
+			PlaneTriResult result;
+
+		  result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );
+
+			if( fcount > 4 || bcount > 4 )
+			{
+		    result = planeTriIntersection(plane,t.mP1.Ptr(),sizeof(Vector3d),0.00001f,front[0].Ptr(),fcount,back[0].Ptr(),bcount );
+			}
+
+			switch ( result )
+			{
+				case PTR_FRONT:
+
+					assert( fcount == 3 );
+
+          if ( showmesh )
+            callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00FF00 );
+
+          #if MAKE_MESH
+
+          addTri( vfront, ifront, front[0], front[1], front[2] );
+
+
+          #endif
+
+					break;
+				case PTR_BACK:
+					assert( bcount == 3 );
+
+          if ( showmesh )
+  					callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xFFFF00 );
+
+          #if MAKE_MESH
+
+          addTri( vback, iback, back[0], back[1], back[2] );
+
+          #endif
+
+					break;
+				case PTR_SPLIT:
+
+					assert( fcount >= 3 && fcount <= 4);
+					assert( bcount >= 3 && bcount <= 4);
+
+          #if MAKE_MESH
+
+          addTri( vfront, ifront, front[0], front[1], front[2] );
+          addTri( vback, iback, back[0], back[1], back[2] );
+
+
+          if ( fcount == 4 )
+          {
+            addTri( vfront, ifront, front[0], front[2], front[3] );
+          }
+
+          if ( bcount == 4  )
+          {
+            addTri( vback, iback, back[0], back[2], back[3] );
+          }
+
+          #endif
+
+          if ( showmesh )
+          {
+  					callback->ConvexDebugTri( front[0].Ptr(), front[1].Ptr(), front[2].Ptr(), 0x00D000 );
+  					callback->ConvexDebugTri( back[0].Ptr(), back[1].Ptr(), back[2].Ptr(), 0xD0D000 );
+
+  					if ( fcount == 4 )
+  					{
+  						callback->ConvexDebugTri( front[0].Ptr(), front[2].Ptr(), front[3].Ptr(), 0x00D000 );
+  					}
+  					if ( bcount == 4 )
+  					{
+  						callback->ConvexDebugTri( back[0].Ptr(), back[2].Ptr(), back[3].Ptr(), 0xD0D000 );
+  					}
+  				}
+
+					break;
+			}
+		}
+
+    // ok... here we recursively call
+    if ( ifront.size() )
+    {
+      unsigned int vcount   = Vl_getVcount(vfront);
+      const float *vertices = Vl_getVertices(vfront);
+      unsigned int tcount   = ifront.size()/3;
+
+      calcConvexDecomposition(vcount, vertices, tcount, &ifront[0], callback, masterVolume, depth+1);
+
+    }
+
+    ifront.clear();
+
+    Vl_releaseVertexLookup(vfront);
+
+    if ( iback.size() )
+    {
+      unsigned int vcount   = Vl_getVcount(vback);
+      const float *vertices = Vl_getVertices(vback);
+      unsigned int tcount   = iback.size()/3;
+
+      calcConvexDecomposition(vcount, vertices, tcount, &iback[0], callback, masterVolume, depth+1);
+
+    }
+
+    iback.clear();
+    Vl_releaseVertexLookup(vback);
+
+	}
+}
+
+
+
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexDecomposition.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexDecomposition.h
new file mode 100644
index 0000000..0904580
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/ConvexDecomposition.h
@@ -0,0 +1,220 @@
+#ifndef CONVEX_DECOMPOSITION_H
+
+#define CONVEX_DECOMPOSITION_H
+
+/*----------------------------------------------------------------------
+Copyright (c) 2004 Open Dynamics Framework Group
+www.physicstools.org
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list of conditions
+and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+#ifdef WIN32
+#include <memory.h> //memcpy
+#endif
+#include <string.h>
+#include <stdio.h>
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+
+extern unsigned int MAXDEPTH ;
+extern float CONCAVE_PERCENT ;
+extern float MERGE_PERCENT   ;
+
+
+typedef btAlignedObjectArray< unsigned int > UintVector;
+
+
+
+namespace ConvexDecomposition
+{
+
+	class ConvexResult
+	{
+	public:
+		ConvexResult(void)
+		{
+			mHullVcount = 0;
+			mHullVertices = 0;
+			mHullTcount = 0;
+			mHullIndices = 0;
+		}
+
+		ConvexResult(unsigned int hvcount,const float *hvertices,unsigned int htcount,const unsigned int *hindices)
+		{
+			mHullVcount = hvcount;
+			if ( mHullVcount )
+			{
+				mHullVertices = new float[mHullVcount*sizeof(float)*3];
+				memcpy(mHullVertices, hvertices, sizeof(float)*3*mHullVcount );
+			}
+			else
+			{
+				mHullVertices = 0;
+			}
+
+			mHullTcount = htcount;
+
+			if ( mHullTcount )
+			{
+				mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3];
+				memcpy(mHullIndices,hindices, sizeof(unsigned int)*mHullTcount*3 );
+			}
+			else
+			{
+				mHullIndices = 0;
+			}
+
+		}
+
+		ConvexResult(const ConvexResult &r)
+		{
+			mHullVcount = r.mHullVcount;
+			if ( mHullVcount )
+			{
+				mHullVertices = new float[mHullVcount*sizeof(float)*3];
+				memcpy(mHullVertices, r.mHullVertices, sizeof(float)*3*mHullVcount );
+			}
+			else
+			{
+				mHullVertices = 0;
+			}
+			mHullTcount = r.mHullTcount;
+			if ( mHullTcount )
+			{
+				mHullIndices = new unsigned int[sizeof(unsigned int)*mHullTcount*3];
+				memcpy(mHullIndices, r.mHullIndices, sizeof(unsigned int)*mHullTcount*3 );
+			}
+			else
+			{
+				mHullIndices = 0;
+			}
+		}
+
+		~ConvexResult(void)
+		{
+			delete [] mHullVertices;
+			delete [] mHullIndices;
+		}
+
+		// the convex hull.
+		unsigned int		    mHullVcount;
+		float *						  mHullVertices;
+		unsigned  int       mHullTcount;
+		unsigned int			 *mHullIndices;
+
+		float               mHullVolume;		    // the volume of the convex hull.
+
+		float               mOBBSides[3];			  // the width, height and breadth of the best fit OBB
+		float               mOBBCenter[3];      // the center of the OBB
+		float               mOBBOrientation[4]; // the quaternion rotation of the OBB.
+		float               mOBBTransform[16];  // the 4x4 transform of the OBB.
+		float               mOBBVolume;         // the volume of the OBB
+
+		float               mSphereRadius;      // radius and center of best fit sphere
+		float               mSphereCenter[3];
+		float               mSphereVolume;      // volume of the best fit sphere
+
+
+
+	};
+
+	class ConvexDecompInterface
+	{
+	public:
+		virtual ~ConvexDecompInterface() {};
+		virtual void ConvexDebugTri(const float *p1,const float *p2,const float *p3,unsigned int color) { };
+		virtual void ConvexDebugPoint(const float *p,float dist,unsigned int color) { };
+		virtual void ConvexDebugBound(const float *bmin,const float *bmax,unsigned int color) { };
+		virtual void ConvexDebugOBB(const float *sides, const float *matrix,unsigned int color) { };
+
+		virtual void ConvexDecompResult(ConvexResult &result) = 0;
+
+
+
+	};
+
+	// just to avoid passing a zillion parameters to the method the
+	// options are packed into this descriptor.
+	class DecompDesc
+	{
+	public:
+		DecompDesc(void)
+		{
+			mVcount = 0;
+			mVertices = 0;
+			mTcount   = 0;
+			mIndices  = 0;
+			mDepth    = 5;
+			mCpercent = 5;
+			mPpercent = 5;
+			mMaxVertices = 32;
+			mSkinWidth   = 0;
+			mCallback    = 0;
+		}
+
+		// describes the input triangle.
+		unsigned	int	mVcount;   // the number of vertices in the source mesh.
+		const float  *mVertices; // start of the vertex position array.  Assumes a stride of 3 floats.
+		unsigned int  mTcount;   // the number of triangles in the source mesh.
+		unsigned int *mIndices;  // the indexed triangle list array (zero index based)
+
+		// options
+		unsigned int  mDepth;    // depth to split, a maximum of 10, generally not over 7.
+		float         mCpercent; // the concavity threshold percentage.  0=20 is reasonable.
+		float         mPpercent; // the percentage volume conservation threshold to collapse hulls. 0-30 is reasonable.
+
+		// hull output limits.
+		unsigned int  mMaxVertices; // maximum number of vertices in the output hull. Recommended 32 or less.
+		float         mSkinWidth;   // a skin width to apply to the output hulls.
+
+		ConvexDecompInterface *mCallback; // the interface to receive back the results.
+
+	};
+
+	// perform approximate convex decomposition on a mesh.
+	unsigned int performConvexDecomposition(const DecompDesc &desc); // returns the number of hulls produced.
+
+
+	void calcConvexDecomposition(unsigned int           vcount,
+		const float           *vertices,
+		unsigned int           tcount,
+		const unsigned int    *indices,
+		ConvexDecompInterface *callback,
+		float                  masterVolume,
+		unsigned int           depth);
+
+
+}
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/Jamfile b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/Jamfile
new file mode 100644
index 0000000..2bf711f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/Jamfile
@@ -0,0 +1,12 @@
+SubDir TOP Extras ConvexDecomposition ;
+
+Library convexdecomposition : [ Wildcard *.h *.cpp ] : noinstall  ;
+
+CFlags convexdecomposition : [ FIncludes $(TOP)/Extras/Decomposition ] ;
+
+LibDepends convexdecomposition :  ;
+
+MsvcGenConfig ConvexDecomposition.INCDIRS : $(TOP)/Extras/ConvexDecomposition ;
+
+
+#InstallHeader [ Wildcard *.h ] : ConvexDecomposition ;
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfit.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfit.cpp
new file mode 100644
index 0000000..e6469f6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfit.cpp
@@ -0,0 +1,466 @@
+#include "float_math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+// Geometric Tools, Inc.
+// http://www.geometrictools.com
+// Copyright (c) 1998-2006.  All Rights Reserved
+//
+// The Wild Magic Library (WM3) source code is supplied under the terms of
+// the license agreement
+//     http://www.geometrictools.com/License/WildMagic3License.pdf
+// and may not be copied or disclosed except in accordance with the terms
+// of that agreement.
+
+#include "bestfit.h"
+
+namespace BestFit
+{
+
+class Vec3
+{
+public:
+  Vec3(void) { };
+  Vec3(float _x,float _y,float _z) { x = _x; y = _y; z = _z; };
+
+
+  float dot(const Vec3 &v)
+  {
+    return x*v.x + y*v.y + z*v.z; // the dot product
+  }
+
+  float x;
+  float y;
+  float z;
+};
+
+
+class Eigen
+{
+public:
+
+
+  void DecrSortEigenStuff(void)
+  {
+    Tridiagonal(); //diagonalize the matrix.
+    QLAlgorithm(); //
+    DecreasingSort();
+    GuaranteeRotation();
+  }
+
+  void Tridiagonal(void)
+  {
+    float fM00 = mElement[0][0];
+    float fM01 = mElement[0][1];
+    float fM02 = mElement[0][2];
+    float fM11 = mElement[1][1];
+    float fM12 = mElement[1][2];
+    float fM22 = mElement[2][2];
+
+    m_afDiag[0] = fM00;
+    m_afSubd[2] = 0;
+    if (fM02 != (float)0.0)
+    {
+      float fLength = sqrtf(fM01*fM01+fM02*fM02);
+      float fInvLength = ((float)1.0)/fLength;
+      fM01 *= fInvLength;
+      fM02 *= fInvLength;
+      float fQ = ((float)2.0)*fM01*fM12+fM02*(fM22-fM11);
+      m_afDiag[1] = fM11+fM02*fQ;
+      m_afDiag[2] = fM22-fM02*fQ;
+      m_afSubd[0] = fLength;
+      m_afSubd[1] = fM12-fM01*fQ;
+      mElement[0][0] = (float)1.0;
+      mElement[0][1] = (float)0.0;
+      mElement[0][2] = (float)0.0;
+      mElement[1][0] = (float)0.0;
+      mElement[1][1] = fM01;
+      mElement[1][2] = fM02;
+      mElement[2][0] = (float)0.0;
+      mElement[2][1] = fM02;
+      mElement[2][2] = -fM01;
+      m_bIsRotation = false;
+    }
+    else
+    {
+      m_afDiag[1] = fM11;
+      m_afDiag[2] = fM22;
+      m_afSubd[0] = fM01;
+      m_afSubd[1] = fM12;
+      mElement[0][0] = (float)1.0;
+      mElement[0][1] = (float)0.0;
+      mElement[0][2] = (float)0.0;
+      mElement[1][0] = (float)0.0;
+      mElement[1][1] = (float)1.0;
+      mElement[1][2] = (float)0.0;
+      mElement[2][0] = (float)0.0;
+      mElement[2][1] = (float)0.0;
+      mElement[2][2] = (float)1.0;
+      m_bIsRotation = true;
+    }
+  }
+
+  bool QLAlgorithm(void)
+  {
+    const int iMaxIter = 32;
+
+    for (int i0 = 0; i0 <3; i0++)
+    {
+      int i1;
+      for (i1 = 0; i1 < iMaxIter; i1++)
+      {
+        int i2;
+        for (i2 = i0; i2 <= (3-2); i2++)
+        {
+          float fTmp = fabsf(m_afDiag[i2]) + fabsf(m_afDiag[i2+1]);
+          if ( fabsf(m_afSubd[i2]) + fTmp == fTmp )
+            break;
+        }
+        if (i2 == i0)
+        {
+          break;
+        }
+
+        float fG = (m_afDiag[i0+1] - m_afDiag[i0])/(((float)2.0) * m_afSubd[i0]);
+        float fR = sqrtf(fG*fG+(float)1.0);
+        if (fG < (float)0.0)
+        {
+          fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG-fR);
+        }
+        else
+        {
+          fG = m_afDiag[i2]-m_afDiag[i0]+m_afSubd[i0]/(fG+fR);
+        }
+        float fSin = (float)1.0, fCos = (float)1.0, fP = (float)0.0;
+        for (int i3 = i2-1; i3 >= i0; i3--)
+        {
+          float fF = fSin*m_afSubd[i3];
+          float fB = fCos*m_afSubd[i3];
+          if (fabsf(fF) >= fabsf(fG))
+          {
+            fCos = fG/fF;
+            fR = sqrtf(fCos*fCos+(float)1.0);
+            m_afSubd[i3+1] = fF*fR;
+            fSin = ((float)1.0)/fR;
+            fCos *= fSin;
+          }
+          else
+          {
+            fSin = fF/fG;
+            fR = sqrtf(fSin*fSin+(float)1.0);
+            m_afSubd[i3+1] = fG*fR;
+            fCos = ((float)1.0)/fR;
+            fSin *= fCos;
+          }
+          fG = m_afDiag[i3+1]-fP;
+          fR = (m_afDiag[i3]-fG)*fSin+((float)2.0)*fB*fCos;
+          fP = fSin*fR;
+          m_afDiag[i3+1] = fG+fP;
+          fG = fCos*fR-fB;
+          for (int i4 = 0; i4 < 3; i4++)
+          {
+            fF = mElement[i4][i3+1];
+            mElement[i4][i3+1] = fSin*mElement[i4][i3]+fCos*fF;
+            mElement[i4][i3] = fCos*mElement[i4][i3]-fSin*fF;
+          }
+        }
+        m_afDiag[i0] -= fP;
+        m_afSubd[i0] = fG;
+        m_afSubd[i2] = (float)0.0;
+      }
+      if (i1 == iMaxIter)
+      {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void DecreasingSort(void)
+  {
+    //sort eigenvalues in decreasing order, e[0] >= ... >= e[iSize-1]
+    for (int i0 = 0, i1; i0 <= 3-2; i0++)
+    {
+      // locate maximum eigenvalue
+      i1 = i0;
+      float fMax = m_afDiag[i1];
+      int i2;
+      for (i2 = i0+1; i2 < 3; i2++)
+      {
+        if (m_afDiag[i2] > fMax)
+        {
+          i1 = i2;
+          fMax = m_afDiag[i1];
+        }
+      }
+
+      if (i1 != i0)
+      {
+        // swap eigenvalues
+        m_afDiag[i1] = m_afDiag[i0];
+        m_afDiag[i0] = fMax;
+        // swap eigenvectors
+        for (i2 = 0; i2 < 3; i2++)
+        {
+          float fTmp = mElement[i2][i0];
+          mElement[i2][i0] = mElement[i2][i1];
+          mElement[i2][i1] = fTmp;
+          m_bIsRotation = !m_bIsRotation;
+        }
+      }
+    }
+  }
+
+
+  void GuaranteeRotation(void)
+  {
+    if (!m_bIsRotation)
+    {
+      // change sign on the first column
+      for (int iRow = 0; iRow <3; iRow++)
+      {
+        mElement[iRow][0] = -mElement[iRow][0];
+      }
+    }
+  }
+
+  float mElement[3][3];
+  float m_afDiag[3];
+  float m_afSubd[3];
+  bool m_bIsRotation;
+};
+
+}
+
+
+using namespace BestFit;
+
+
+bool getBestFitPlane(unsigned int vcount,
+                     const float *points,
+                     unsigned int vstride,
+                     const float *weights,
+                     unsigned int wstride,
+                     float *plane)
+{
+  bool ret = false;
+
+  Vec3 kOrigin(0,0,0);
+
+  float wtotal = 0;
+
+  if ( 1 )
+  {
+    const char *source  = (const char *) points;
+    const char *wsource = (const char *) weights;
+
+    for (unsigned int i=0; i<vcount; i++)
+    {
+
+      const float *p = (const float *) source;
+
+      float w = 1;
+
+      if ( wsource )
+      {
+        const float *ws = (const float *) wsource;
+        w = *ws; //
+        wsource+=wstride;
+      }
+
+      kOrigin.x+=p[0]*w;
+      kOrigin.y+=p[1]*w;
+      kOrigin.z+=p[2]*w;
+
+      wtotal+=w;
+
+      source+=vstride;
+    }
+  }
+
+  float recip = 1.0f / wtotal; // reciprocol of total weighting
+
+  kOrigin.x*=recip;
+  kOrigin.y*=recip;
+  kOrigin.z*=recip;
+
+
+  float fSumXX=0;
+  float fSumXY=0;
+  float fSumXZ=0;
+
+  float fSumYY=0;
+  float fSumYZ=0;
+  float fSumZZ=0;
+
+
+  if ( 1 )
+  {
+    const char *source  = (const char *) points;
+    const char *wsource = (const char *) weights;
+
+    for (unsigned int i=0; i<vcount; i++)
+    {
+
+      const float *p = (const float *) source;
+
+      float w = 1;
+
+      if ( wsource )
+      {
+        const float *ws = (const float *) wsource;
+        w = *ws; //
+        wsource+=wstride;
+      }
+
+      Vec3 kDiff;
+
+      kDiff.x = w*(p[0] - kOrigin.x); // apply vertex weighting!
+      kDiff.y = w*(p[1] - kOrigin.y);
+      kDiff.z = w*(p[2] - kOrigin.z);
+
+      fSumXX+= kDiff.x * kDiff.x; // sume of the squares of the differences.
+      fSumXY+= kDiff.x * kDiff.y; // sume of the squares of the differences.
+      fSumXZ+= kDiff.x * kDiff.z; // sume of the squares of the differences.
+
+      fSumYY+= kDiff.y * kDiff.y;
+      fSumYZ+= kDiff.y * kDiff.z;
+      fSumZZ+= kDiff.z * kDiff.z;
+
+
+      source+=vstride;
+    }
+  }
+
+  fSumXX *= recip;
+  fSumXY *= recip;
+  fSumXZ *= recip;
+  fSumYY *= recip;
+  fSumYZ *= recip;
+  fSumZZ *= recip;
+
+  // setup the eigensolver
+  Eigen kES;
+
+  kES.mElement[0][0] = fSumXX;
+  kES.mElement[0][1] = fSumXY;
+  kES.mElement[0][2] = fSumXZ;
+
+  kES.mElement[1][0] = fSumXY;
+  kES.mElement[1][1] = fSumYY;
+  kES.mElement[1][2] = fSumYZ;
+
+  kES.mElement[2][0] = fSumXZ;
+  kES.mElement[2][1] = fSumYZ;
+  kES.mElement[2][2] = fSumZZ;
+
+  // compute eigenstuff, smallest eigenvalue is in last position
+  kES.DecrSortEigenStuff();
+
+  Vec3 kNormal;
+
+  kNormal.x = kES.mElement[0][2];
+  kNormal.y = kES.mElement[1][2];
+  kNormal.z = kES.mElement[2][2];
+
+  // the minimum energy
+  plane[0] = kNormal.x;
+  plane[1] = kNormal.y;
+  plane[2] = kNormal.z;
+
+  plane[3] = 0 - kNormal.dot(kOrigin);
+
+  return ret;
+}
+
+
+
+float getBoundingRegion(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax) // returns the diagonal distance
+{
+
+  const unsigned char *source = (const unsigned char *) points;
+
+	bmin[0] = points[0];
+	bmin[1] = points[1];
+	bmin[2] = points[2];
+
+	bmax[0] = points[0];
+	bmax[1] = points[1];
+	bmax[2] = points[2];
+
+
+  for (unsigned int i=1; i<vcount; i++)
+  {
+  	source+=pstride;
+  	const float *p = (const float *) source;
+
+  	if ( p[0] < bmin[0] ) bmin[0] = p[0];
+  	if ( p[1] < bmin[1] ) bmin[1] = p[1];
+  	if ( p[2] < bmin[2] ) bmin[2] = p[2];
+
+		if ( p[0] > bmax[0] ) bmax[0] = p[0];
+		if ( p[1] > bmax[1] ) bmax[1] = p[1];
+		if ( p[2] > bmax[2] ) bmax[2] = p[2];
+
+  }
+
+  float dx = bmax[0] - bmin[0];
+  float dy = bmax[1] - bmin[1];
+  float dz = bmax[2] - bmin[2];
+
+	return sqrtf( dx*dx + dy*dy + dz*dz );
+
+}
+
+
+bool  overlapAABB(const float *bmin1,const float *bmax1,const float *bmin2,const float *bmax2) // return true if the two AABB's overlap.
+{
+  if ( bmax2[0] < bmin1[0] ) return false; // if the maximum is less than our minimum on any axis
+  if ( bmax2[1] < bmin1[1] ) return false;
+  if ( bmax2[2] < bmin1[2] ) return false;
+
+  if ( bmin2[0] > bmax1[0] ) return false; // if the minimum is greater than our maximum on any axis
+  if ( bmin2[1] > bmax1[1] ) return false; // if the minimum is greater than our maximum on any axis
+  if ( bmin2[2] > bmax1[2] ) return false; // if the minimum is greater than our maximum on any axis
+
+
+  return true; // the extents overlap
+}
+
+
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfit.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfit.h
new file mode 100644
index 0000000..f2e78e5
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfit.h
@@ -0,0 +1,65 @@
+#ifndef BEST_FIT_H
+
+#define BEST_FIT_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+// This routine was released in 'snippet' form
+// by John W. Ratcliff mailto:jratcliff at infiniplex.net
+// on March 22, 2006.
+//
+// This routine computes the 'best fit' plane equation to
+// a set of input data points with an optional per vertex
+// weighting component.
+//
+// The implementation for this was lifted directly from
+// David Eberly's Magic Software implementation.
+
+// computes the best fit plane to a collection of data points.
+// returns the plane equation as A,B,C,D format. (Ax+By+Cz+D)
+
+bool getBestFitPlane(unsigned int vcount,     // number of input data points
+                     const float *points,     // starting address of points array.
+                     unsigned int vstride,    // stride between input points.
+                     const float *weights,    // *optional point weighting values.
+                     unsigned int wstride,    // weight stride for each vertex.
+                     float *plane);
+
+
+float getBoundingRegion(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax); // returns the diagonal distance
+bool  overlapAABB(const float *bmin1,const float *bmax1,const float *bmin2,const float *bmax2); // return true if the two AABB's overlap.
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfitobb.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfitobb.cpp
new file mode 100644
index 0000000..396450b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfitobb.cpp
@@ -0,0 +1,173 @@
+#include "float_math.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+#include "bestfitobb.h"
+#include "float_math.h"
+
+// computes the OBB for this set of points relative to this transform matrix.
+void computeOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,const float *matrix)
+{
+  const char *src = (const char *) points;
+
+  float bmin[3] = { 1e9, 1e9, 1e9 };
+  float bmax[3] = { -1e9, -1e9, -1e9 };
+
+  for (unsigned int i=0; i<vcount; i++)
+  {
+    const float *p = (const float *) src;
+    float t[3];
+
+    fm_inverseRT(matrix, p, t ); // inverse rotate translate
+
+    if ( t[0] < bmin[0] ) bmin[0] = t[0];
+    if ( t[1] < bmin[1] ) bmin[1] = t[1];
+    if ( t[2] < bmin[2] ) bmin[2] = t[2];
+
+    if ( t[0] > bmax[0] ) bmax[0] = t[0];
+    if ( t[1] > bmax[1] ) bmax[1] = t[1];
+    if ( t[2] > bmax[2] ) bmax[2] = t[2];
+
+    src+=pstride;
+  }
+
+
+  sides[0] = bmax[0];
+  sides[1] = bmax[1];
+  sides[2] = bmax[2];
+
+  if ( fabsf(bmin[0]) > sides[0] ) sides[0] = fabsf(bmin[0]);
+  if ( fabsf(bmin[1]) > sides[1] ) sides[1] = fabsf(bmin[1]);
+  if ( fabsf(bmin[2]) > sides[2] ) sides[2] = fabsf(bmin[2]);
+
+  sides[0]*=2.0f;
+  sides[1]*=2.0f;
+  sides[2]*=2.0f;
+
+}
+
+void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix)
+{
+
+  float bmin[3];
+  float bmax[3];
+
+  fm_getAABB(vcount,points,pstride,bmin,bmax);
+
+  float center[3];
+
+  center[0] = (bmax[0]-bmin[0])*0.5f + bmin[0];
+  center[1] = (bmax[1]-bmin[1])*0.5f + bmin[1];
+  center[2] = (bmax[2]-bmin[2])*0.5f + bmin[2];
+
+  float ax = 0;
+  float ay = 0;
+  float az = 0;
+
+  float sweep =  45.0f; // 180 degree sweep on all three axes.
+  float steps =   8.0f; // 16 steps on each axis.
+
+  float bestVolume = 1e9;
+  float angle[3];
+
+  while ( sweep >= 1 )
+  {
+
+    bool found = false;
+
+    float stepsize = sweep / steps;
+
+    for (float x=ax-sweep; x<=ax+sweep; x+=stepsize)
+    {
+      for (float y=ay-sweep; y<=ay+sweep; y+=stepsize)
+      {
+        for (float z=az-sweep; z<=az+sweep; z+=stepsize)
+        {
+          float pmatrix[16];
+
+          fm_eulerMatrix( x*FM_DEG_TO_RAD, y*FM_DEG_TO_RAD, z*FM_DEG_TO_RAD, pmatrix );
+
+          pmatrix[3*4+0] = center[0];
+          pmatrix[3*4+1] = center[1];
+          pmatrix[3*4+2] = center[2];
+
+          float psides[3];
+
+          computeOBB( vcount, points, pstride, psides, pmatrix );
+
+          float volume = psides[0]*psides[1]*psides[2]; // the volume of the cube
+
+          if ( volume <= bestVolume )
+          {
+            bestVolume = volume;
+
+            sides[0] = psides[0];
+            sides[1] = psides[1];
+            sides[2] = psides[2];
+
+            angle[0] = ax;
+            angle[1] = ay;
+            angle[2] = az;
+
+            memcpy(matrix,pmatrix,sizeof(float)*16);
+            found = true; // yes, we found an improvement.
+          }
+        }
+      }
+    }
+
+    if ( found )
+    {
+
+      ax = angle[0];
+      ay = angle[1];
+      az = angle[2];
+
+      sweep*=0.5f; // sweep 1/2 the distance as the last time.
+    }
+    else
+    {
+      break; // no improvement, so just
+    }
+
+  }
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfitobb.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfitobb.h
new file mode 100644
index 0000000..3141f58
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/bestfitobb.h
@@ -0,0 +1,43 @@
+#ifndef BEST_FIT_OBB_H
+
+#define BEST_FIT_OBB_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+
+void computeBestFitOBB(unsigned int vcount,const float *points,unsigned int pstride,float *sides,float *matrix);
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_hull.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_hull.cpp
new file mode 100644
index 0000000..b2f6d8b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_hull.cpp
@@ -0,0 +1,3257 @@
+#include "float_math.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+#include <float.h>
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+#include "cd_hull.h"
+
+using namespace ConvexDecomposition;
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+#define PI 3.14159264f
+
+//*****************************************************
+//*****************************************************
+//********* Stan Melax's vector math template needed
+//********* to use his hull building code.
+//*****************************************************
+//*****************************************************
+
+#define DEG2RAD (PI / 180.0f)
+#define RAD2DEG (180.0f / PI)
+#define SQRT_OF_2 (1.4142135f)
+#define OFFSET(Class,Member)  (((char*) (&(((Class*)NULL)-> Member )))- ((char*)NULL))
+
+namespace ConvexDecomposition
+{
+
+
+int    argmin(float a[],int n);
+float  sqr(float a);
+float  clampf(float a) ;
+float  Round(float a,float precision);
+float  Interpolate(const float &f0,const float &f1,float alpha) ;
+
+template <class T>
+void Swap(T &a,T &b)
+{
+	T tmp = a;
+	a=b;
+	b=tmp;
+}
+
+
+
+template <class T>
+T Max(const T &a,const T &b)
+{
+	return (a>b)?a:b;
+}
+
+template <class T>
+T Min(const T &a,const T &b) 
+{
+	return (a<b)?a:b;
+}
+
+//----------------------------------
+
+class int3  
+{
+public:
+	int x,y,z;
+	int3(){};
+	int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;}
+	const int& operator[](int i) const {return (&x)[i];}
+	int& operator[](int i) {return (&x)[i];}
+};
+
+
+//-------- 2D --------
+
+class float2
+{
+public:
+	float x,y;
+	float2(){x=0;y=0;};
+	float2(float _x,float _y){x=_x;y=_y;}
+	float& operator[](int i) {assert(i>=0&&i<2);return ((float*)this)[i];}
+	const float& operator[](int i) const {assert(i>=0&&i<2);return ((float*)this)[i];}
+};
+inline float2 operator-( const float2& a, const float2& b ){return float2(a.x-b.x,a.y-b.y);}
+inline float2 operator+( const float2& a, const float2& b ){return float2(a.x+b.x,a.y+b.y);}
+
+//--------- 3D ---------
+
+class float3 // 3D
+{
+	public:
+	float x,y,z;
+	float3(){x=0;y=0;z=0;};
+	float3(float _x,float _y,float _z){x=_x;y=_y;z=_z;};
+	//operator float *() { return &x;};
+	float& operator[](int i) {assert(i>=0&&i<3);return ((float*)this)[i];}
+	const float& operator[](int i) const {assert(i>=0&&i<3);return ((float*)this)[i];}
+#	ifdef PLUGIN_3DSMAX
+	float3(const Point3 &p):x(p.x),y(p.y),z(p.z){}
+	operator Point3(){return *((Point3*)this);}
+#	endif
+};
+
+
+float3& operator+=( float3 &a, const float3& b );
+float3& operator-=( float3 &a ,const float3& b );
+float3& operator*=( float3 &v ,const float s );
+float3& operator/=( float3 &v, const float s );
+
+float  magnitude( const float3& v );
+float3 normalize( const float3& v );
+float3 safenormalize(const float3 &v);
+float3 vabs(const float3 &v);
+float3 operator+( const float3& a, const float3& b );
+float3 operator-( const float3& a, const float3& b );
+float3 operator-( const float3& v );
+float3 operator*( const float3& v, const float s );
+float3 operator*( const float s, const float3& v );
+float3 operator/( const float3& v, const float s );
+inline int operator==( const float3 &a, const float3 &b ) { return (a.x==b.x && a.y==b.y && a.z==b.z); }
+inline int operator!=( const float3 &a, const float3 &b ) { return (a.x!=b.x || a.y!=b.y || a.z!=b.z); }
+// due to ambiguity and inconsistent standards ther are no overloaded operators for mult such as va*vb.
+float  dot( const float3& a, const float3& b );
+float3 cmul( const float3 &a, const float3 &b);
+float3 cross( const float3& a, const float3& b );
+float3 Interpolate(const float3 &v0,const float3 &v1,float alpha);
+float3 Round(const float3& a,float precision);
+float3	VectorMax(const float3 &a, const float3 &b);
+float3	VectorMin(const float3 &a, const float3 &b);
+
+
+
+class float3x3
+{
+	public:
+	float3 x,y,z;  // the 3 rows of the Matrix
+	float3x3(){}
+	float3x3(float xx,float xy,float xz,float yx,float yy,float yz,float zx,float zy,float zz):x(xx,xy,xz),y(yx,yy,yz),z(zx,zy,zz){}
+	float3x3(float3 _x,float3 _y,float3 _z):x(_x),y(_y),z(_z){}
+	float3&       operator[](int i)       {assert(i>=0&&i<3);return (&x)[i];}
+	const float3& operator[](int i) const {assert(i>=0&&i<3);return (&x)[i];}
+	float&        operator()(int r, int c)       {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];}
+	const float&  operator()(int r, int c) const {assert(r>=0&&r<3&&c>=0&&c<3);return ((&x)[r])[c];}
+}; 
+float3x3 Transpose( const float3x3& m );
+float3   operator*( const float3& v  , const float3x3& m  );
+float3   operator*( const float3x3& m , const float3& v   );
+float3x3 operator*( const float3x3& m , const float& s   );
+float3x3 operator*( const float3x3& ma, const float3x3& mb );
+float3x3 operator/( const float3x3& a, const float& s ) ;
+float3x3 operator+( const float3x3& a, const float3x3& b );
+float3x3 operator-( const float3x3& a, const float3x3& b );
+float3x3 &operator+=( float3x3& a, const float3x3& b );
+float3x3 &operator-=( float3x3& a, const float3x3& b );
+float3x3 &operator*=( float3x3& a, const float& s );
+float    Determinant(const float3x3& m );
+float3x3 Inverse(const float3x3& a);  // its just 3x3 so we simply do that cofactor method
+
+
+//-------- 4D Math --------
+
+class float4
+{
+public:
+	float x,y,z,w;
+	float4(){x=0;y=0;z=0;w=0;};
+	float4(float _x,float _y,float _z,float _w){x=_x;y=_y;z=_z;w=_w;}
+	float4(const float3 &v,float _w){x=v.x;y=v.y;z=v.z;w=_w;}
+	//operator float *() { return &x;};
+	float& operator[](int i) {assert(i>=0&&i<4);return ((float*)this)[i];}
+	const float& operator[](int i) const {assert(i>=0&&i<4);return ((float*)this)[i];}
+	const float3& xyz() const { return *((float3*)this);}
+	float3&       xyz()       { return *((float3*)this);}
+};
+
+
+struct D3DXMATRIX;
+
+class float4x4
+{
+	public:
+	float4 x,y,z,w;  // the 4 rows
+	float4x4(){}
+	float4x4(const float4 &_x, const float4 &_y, const float4 &_z, const float4 &_w):x(_x),y(_y),z(_z),w(_w){}
+	float4x4(float m00, float m01, float m02, float m03,
+						float m10, float m11, float m12, float m13,
+				float m20, float m21, float m22, float m23, 
+				float m30, float m31, float m32, float m33 )
+			:x(m00,m01,m02,m03),y(m10,m11,m12,m13),z(m20,m21,m22,m23),w(m30,m31,m32,m33){}
+	float&       operator()(int r, int c)       {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
+	const float& operator()(int r, int c) const {assert(r>=0&&r<4&&c>=0&&c<4);return ((&x)[r])[c];}
+		operator       float* ()       {return &x.x;}
+		operator const float* () const {return &x.x;}
+	operator       struct D3DXMATRIX* ()       { return (struct D3DXMATRIX*) this;}
+	operator const struct D3DXMATRIX* () const { return (struct D3DXMATRIX*) this;}
+};
+
+
+int     operator==( const float4 &a, const float4 &b );
+float4 Homogenize(const float3 &v3,const float &w=1.0f); // Turns a 3D float3 4D vector4 by appending w
+float4 cmul( const float4 &a, const float4 &b);
+float4 operator*( const float4 &v, float s);
+float4 operator*( float s, const float4 &v);
+float4 operator+( const float4 &a, const float4 &b);
+float4 operator-( const float4 &a, const float4 &b);
+float4x4 operator*( const float4x4& a, const float4x4& b );
+float4 operator*( const float4& v, const float4x4& m );
+float4x4 Inverse(const float4x4 &m);
+float4x4 MatrixRigidInverse(const float4x4 &m);
+float4x4 MatrixTranspose(const float4x4 &m);
+float4x4 MatrixPerspectiveFov(float fovy, float Aspect, float zn, float zf );
+float4x4 MatrixTranslation(const float3 &t);
+float4x4 MatrixRotationZ(const float angle_radians);
+float4x4 MatrixLookAt(const float3& eye, const float3& at, const float3& up);
+int     operator==( const float4x4 &a, const float4x4 &b );
+
+
+//-------- Quaternion ------------
+
+class Quaternion :public float4
+{
+ public:
+	Quaternion() { x = y = z = 0.0f; w = 1.0f; }
+	Quaternion( float3 v, float t ) { v = normalize(v); w = cosf(t/2.0f); v = v*sinf(t/2.0f); x = v.x; y = v.y; z = v.z; }
+	Quaternion(float _x, float _y, float _z, float _w){x=_x;y=_y;z=_z;w=_w;}
+	float angle() const { return acosf(w)*2.0f; }
+	float3 axis() const { float3 a(x,y,z); if(fabsf(angle())<0.0000001f) return float3(1,0,0); return a*(1/sinf(angle()/2.0f)); }
+	float3 xdir() const { return float3( 1-2*(y*y+z*z),  2*(x*y+w*z),  2*(x*z-w*y) ); }
+	float3 ydir() const { return float3(   2*(x*y-w*z),1-2*(x*x+z*z),  2*(y*z+w*x) ); }
+	float3 zdir() const { return float3(   2*(x*z+w*y),  2*(y*z-w*x),1-2*(x*x+y*y) ); }
+	float3x3 getmatrix() const { return float3x3( xdir(), ydir(), zdir() ); }
+	operator float3x3() { return getmatrix(); }
+	void Normalize();
+};
+
+Quaternion& operator*=(Quaternion& a, float s );
+Quaternion	operator*( const Quaternion& a, float s );
+Quaternion	operator*( const Quaternion& a, const Quaternion& b);
+Quaternion	operator+( const Quaternion& a, const Quaternion& b );
+Quaternion	normalize( Quaternion a );
+float		dot( const Quaternion &a, const Quaternion &b );
+float3		operator*( const Quaternion& q, const float3& v );
+float3		operator*( const float3& v, const Quaternion& q );
+Quaternion	slerp( Quaternion a, const Quaternion& b, float interp );
+Quaternion  Interpolate(const Quaternion &q0,const Quaternion &q1,float alpha); 
+Quaternion  RotationArc(float3 v0, float3 v1 );  // returns quat q where q*v0=v1
+Quaternion  Inverse(const Quaternion &q);
+float4x4     MatrixFromQuatVec(const Quaternion &q, const float3 &v);
+
+
+//------ Euler Angle -----
+
+Quaternion YawPitchRoll( float yaw, float pitch, float roll );
+float Yaw( const Quaternion& q );
+float Pitch( const Quaternion& q );
+float Roll( Quaternion q );
+float Yaw( const float3& v );
+float Pitch( const float3& v );
+
+
+//------- Plane ----------
+
+class Plane
+{
+	public:
+	float3	normal;
+	float	dist;   // distance below origin - the D from plane equasion Ax+By+Cz+D=0
+			Plane(const float3 &n,float d):normal(n),dist(d){}
+			Plane():normal(),dist(0){}
+	void	Transform(const float3 &position, const Quaternion &orientation);
+};
+
+inline Plane PlaneFlip(const Plane &plane){return Plane(-plane.normal,-plane.dist);}
+inline int operator==( const Plane &a, const Plane &b ) { return (a.normal==b.normal && a.dist==b.dist); }
+inline int coplanar( const Plane &a, const Plane &b ) { return (a==b || a==PlaneFlip(b)); }
+
+
+//--------- Utility Functions ------
+
+float3  PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1);
+float3  PlaneProject(const Plane &plane, const float3 &point);
+float3  LineProject(const float3 &p0, const float3 &p1, const float3 &a);  // projects a onto infinite line p0p1
+float   LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a);
+float3  ThreePlaneIntersection(const Plane &p0,const Plane &p1, const Plane &p2);
+int     PolyHit(const float3 *vert,const int n,const float3 &v0, const float3 &v1, float3 *impact=NULL, float3 *normal=NULL);
+int     BoxInside(const float3 &p,const float3 &bmin, const float3 &bmax) ;
+int     BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax, float3 *impact);
+float   DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint=NULL, float3 *vpoint=NULL);
+float3  TriNormal(const float3 &v0, const float3 &v1, const float3 &v2);
+float3  NormalOf(const float3 *vert, const int n);
+Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir0, const float3 &dir1);
+
+
+float   sqr(float a) {return a*a;}
+float   clampf(float a) {return Min(1.0f,Max(0.0f,a));}
+
+
+float Round(float a,float precision)
+{
+	return floorf(0.5f+a/precision)*precision;
+}
+
+
+float Interpolate(const float &f0,const float &f1,float alpha)
+{
+	return f0*(1-alpha) + f1*alpha;
+}
+
+
+int     argmin(float a[],int n)
+{
+	int r=0;
+	for(int i=1;i<n;i++) 
+		{
+		if(a[i]<a[r]) 
+				{
+			r = i;
+		}
+	}
+	return r;
+}
+
+
+
+//------------ float3 (3D) --------------
+
+
+
+float3 operator+( const float3& a, const float3& b ) 
+{
+	return float3(a.x+b.x, a.y+b.y, a.z+b.z); 
+}
+
+
+float3 operator-( const float3& a, const float3& b )
+{
+	return float3( a.x-b.x, a.y-b.y, a.z-b.z );
+}
+
+
+float3 operator-( const float3& v )                     
+{
+	return float3( -v.x, -v.y, -v.z );
+}
+
+
+float3 operator*( const float3& v, float s )      
+{
+	return float3( v.x*s, v.y*s, v.z*s );
+}
+
+
+float3 operator*( float s, const float3& v )      
+{
+	return float3( v.x*s, v.y*s, v.z*s ); 
+}
+
+
+float3 operator/( const float3& v, float s )
+{ 
+	return v*(1.0f/s); 
+}
+
+float  dot( const float3& a, const float3& b )    
+{
+	return a.x*b.x + a.y*b.y + a.z*b.z; 
+}
+
+float3 cmul( const float3 &v1, const float3 &v2) 
+{ 
+	return float3(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z); 
+}
+
+
+float3 cross( const float3& a, const float3& b )
+{
+		return float3( a.y*b.z - a.z*b.y,
+									 a.z*b.x - a.x*b.z,
+									 a.x*b.y - a.y*b.x );
+}
+
+
+
+
+float3& operator+=( float3& a , const float3& b )
+{
+		a.x += b.x;
+		a.y += b.y;
+		a.z += b.z;
+		return a;
+}
+
+
+float3& operator-=( float3& a , const float3& b )
+{
+		a.x -= b.x;
+		a.y -= b.y;
+		a.z -= b.z;
+		return a;
+}
+
+
+float3& operator*=(float3& v , float s )
+{
+		v.x *= s;
+		v.y *= s;
+		v.z *= s;
+		return v;
+}
+
+
+float3& operator/=(float3& v , float s )
+{
+		float sinv = 1.0f / s;
+		v.x *= sinv;
+		v.y *= sinv;
+		v.z *= sinv;
+		return v;
+}
+
+float3 vabs(const float3 &v)
+{
+	return float3(fabsf(v.x),fabsf(v.y),fabsf(v.z));
+}
+
+
+float magnitude( const float3& v )
+{
+		return sqrtf(sqr(v.x) + sqr( v.y)+ sqr(v.z));
+}
+
+
+
+float3 normalize( const float3 &v )
+{
+	// this routine, normalize, is ok, provided magnitude works!!
+		float d=magnitude(v);
+		if (d==0)
+		{
+		printf("Cant normalize ZERO vector\n");
+		assert(0);// yes this could go here
+		d=0.1f;
+	}
+	d = 1/d;
+	return float3(v.x*d,v.y*d,v.z*d);
+}
+
+float3 safenormalize(const float3 &v)
+{
+	if(magnitude(v)<=0.0f)
+	{
+		return float3(1,0,0);
+	}
+	return normalize(v);
+}
+
+float3 Round(const float3 &a,float precision)
+{
+	return float3(Round(a.x,precision),Round(a.y,precision),Round(a.z,precision));
+}
+
+
+float3 Interpolate(const float3 &v0,const float3 &v1,float alpha) 
+{
+	return v0*(1-alpha) + v1*alpha;
+}
+
+float3 VectorMin(const float3 &a,const float3 &b)
+{
+	return float3(Min(a.x,b.x),Min(a.y,b.y),Min(a.z,b.z));
+}
+float3 VectorMax(const float3 &a,const float3 &b)
+{
+	return float3(Max(a.x,b.x),Max(a.y,b.y),Max(a.z,b.z));
+}
+
+// the statement v1*v2 is ambiguous since there are 3 types
+// of vector multiplication
+//  - componantwise (for example combining colors)
+//  - dot product
+//  - cross product
+// Therefore we never declare/implement this function.
+// So we will never see:  float3 operator*(float3 a,float3 b) 
+
+
+
+
+//------------ float3x3 ---------------
+float Determinant(const float3x3 &m)
+{
+	return  m.x.x*m.y.y*m.z.z + m.y.x*m.z.y*m.x.z + m.z.x*m.x.y*m.y.z
+			 -m.x.x*m.z.y*m.y.z - m.y.x*m.x.y*m.z.z - m.z.x*m.y.y*m.x.z ;
+}
+
+float3x3 Inverse(const float3x3 &a)
+{
+	float3x3 b;
+	float d=Determinant(a);
+	assert(d!=0);
+	for(int i=0;i<3;i++) 
+		{
+		for(int j=0;j<3;j++) 
+				{
+			int i1=(i+1)%3;
+			int i2=(i+2)%3;
+			int j1=(j+1)%3;
+			int j2=(j+2)%3;
+			// reverse indexs i&j to take transpose
+			b[j][i] = (a[i1][j1]*a[i2][j2]-a[i1][j2]*a[i2][j1])/d;
+		}
+	}
+	// Matrix check=a*b; // Matrix 'check' should be the identity (or close to it)
+	return b;
+}
+
+
+float3x3 Transpose( const float3x3& m )
+{
+	return float3x3( float3(m.x.x,m.y.x,m.z.x),
+					float3(m.x.y,m.y.y,m.z.y),
+					float3(m.x.z,m.y.z,m.z.z));
+}
+
+
+float3 operator*(const float3& v , const float3x3 &m ) { 
+	return float3((m.x.x*v.x + m.y.x*v.y + m.z.x*v.z), 
+					(m.x.y*v.x + m.y.y*v.y + m.z.y*v.z), 
+					(m.x.z*v.x + m.y.z*v.y + m.z.z*v.z));
+}
+float3 operator*(const float3x3 &m,const float3& v  ) {
+	return float3(dot(m.x,v),dot(m.y,v),dot(m.z,v));
+}
+
+
+float3x3 operator*( const float3x3& a, const float3x3& b )
+{ 
+	return float3x3(a.x*b,a.y*b,a.z*b); 
+}
+
+float3x3 operator*( const float3x3& a, const float& s )  
+{ 
+	return float3x3(a.x*s, a.y*s ,a.z*s); 
+}
+float3x3 operator/( const float3x3& a, const float& s )  
+{ 
+	float t=1/s;
+	return float3x3(a.x*t, a.y*t ,a.z*t); 
+}
+float3x3 operator+( const float3x3& a, const float3x3& b )
+{
+	return float3x3(a.x+b.x, a.y+b.y, a.z+b.z);
+}
+float3x3 operator-( const float3x3& a, const float3x3& b )
+{
+	return float3x3(a.x-b.x, a.y-b.y, a.z-b.z);
+}
+float3x3 &operator+=( float3x3& a, const float3x3& b )
+{
+	a.x+=b.x;
+	a.y+=b.y;
+	a.z+=b.z;
+	return a;
+}
+float3x3 &operator-=( float3x3& a, const float3x3& b )
+{
+	a.x-=b.x;
+	a.y-=b.y;
+	a.z-=b.z;
+	return a;
+}
+float3x3 &operator*=( float3x3& a, const float& s )
+{
+	a.x*=s;
+	a.y*=s;
+	a.z*=s;
+	return a;
+}
+
+
+
+float3 ThreePlaneIntersection(const Plane &p0,const Plane &p1, const Plane &p2){
+	float3x3 mp =Transpose(float3x3(p0.normal,p1.normal,p2.normal));
+	float3x3 mi = Inverse(mp);
+	float3 b(p0.dist,p1.dist,p2.dist);
+	return -b * mi;
+}
+
+
+//--------------- 4D ----------------
+
+float4   operator*( const float4&   v, const float4x4& m )
+{
+	return v.x*m.x + v.y*m.y + v.z*m.z + v.w*m.w; // yes this actually works
+}
+
+int operator==( const float4 &a, const float4 &b ) 
+{
+	return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w); 
+}
+
+
+//  Dont implement m*v for now, since that might confuse us
+//  All our transforms are based on multiplying the "row" vector on the left
+//float4   operator*(const float4x4& m , const float4&   v )
+//{
+//	return float4(dot(v,m.x),dot(v,m.y),dot(v,m.z),dot(v,m.w));
+//}
+
+
+
+float4 cmul( const float4 &a, const float4 &b) 
+{
+	return float4(a.x*b.x,a.y*b.y,a.z*b.z,a.w*b.w);
+}
+
+
+float4 operator*( const float4 &v, float s) 
+{
+	return float4(v.x*s,v.y*s,v.z*s,v.w*s);
+}
+
+
+float4 operator*( float s, const float4 &v) 
+{
+	return float4(v.x*s,v.y*s,v.z*s,v.w*s);
+}
+
+
+float4 operator+( const float4 &a, const float4 &b) 
+{
+	return float4(a.x+b.x,a.y+b.y,a.z+b.z,a.w+b.w);
+}
+
+
+
+float4 operator-( const float4 &a, const float4 &b) 
+{
+	return float4(a.x-b.x,a.y-b.y,a.z-b.z,a.w-b.w);
+}
+
+
+float4 Homogenize(const float3 &v3,const float &w)
+{
+	return float4(v3.x,v3.y,v3.z,w);
+}
+
+
+
+float4x4 operator*( const float4x4& a, const float4x4& b )
+{
+	return float4x4(a.x*b,a.y*b,a.z*b,a.w*b);
+}
+
+float4x4 MatrixTranspose(const float4x4 &m)
+{
+	return float4x4(
+		m.x.x, m.y.x, m.z.x, m.w.x,
+		m.x.y, m.y.y, m.z.y, m.w.y,
+		m.x.z, m.y.z, m.z.z, m.w.z,
+		m.x.w, m.y.w, m.z.w, m.w.w );
+}
+
+float4x4 MatrixRigidInverse(const float4x4 &m)
+{
+	float4x4 trans_inverse = MatrixTranslation(-m.w.xyz());
+	float4x4 rot   = m;
+	rot.w = float4(0,0,0,1);
+	return trans_inverse * MatrixTranspose(rot);
+}
+
+
+float4x4 MatrixPerspectiveFov(float fovy, float aspect, float zn, float zf )
+{
+	float h = 1.0f/tanf(fovy/2.0f); // view space height
+	float w = h / aspect ;  // view space width
+	return float4x4(
+		w, 0, 0             ,   0,
+		0, h, 0             ,   0,
+		0, 0, zf/(zn-zf)    ,  -1,
+		0, 0, zn*zf/(zn-zf) ,   0 );
+}
+
+
+
+float4x4 MatrixLookAt(const float3& eye, const float3& at, const float3& up)
+{
+	float4x4 m;
+	m.w.w = 1.0f;
+	m.w.xyz() = eye;
+	m.z.xyz() = normalize(eye-at);
+	m.x.xyz() = normalize(cross(up,m.z.xyz()));
+	m.y.xyz() = cross(m.z.xyz(),m.x.xyz());
+	return MatrixRigidInverse(m);
+}
+
+
+float4x4 MatrixTranslation(const float3 &t)
+{
+	return float4x4(
+		1,  0,  0,  0,
+		0,  1,  0,  0,
+		0,  0,  1,  0,
+		t.x,t.y,t.z,1 );
+}
+
+
+float4x4 MatrixRotationZ(const float angle_radians)
+{
+	float s =  sinf(angle_radians);
+	float c =  cosf(angle_radians);
+	return float4x4(
+		c,  s,  0,  0,
+		-s, c,  0,  0,
+		0,  0,  1,  0,
+		0,  0,  0,  1 );
+}
+
+
+
+int operator==( const float4x4 &a, const float4x4 &b )
+{
+	return (a.x==b.x && a.y==b.y && a.z==b.z && a.w==b.w);
+}
+
+
+float4x4 Inverse(const float4x4 &m)
+{
+	float4x4 d;
+	float *dst = &d.x.x;
+	float tmp[12]; /* temp array for pairs */
+	float src[16]; /* array of transpose source matrix */
+	float det; /* determinant */
+	/* transpose matrix */
+	for ( int i = 0; i < 4; i++) {
+		src[i] = m(i,0) ;
+		src[i + 4] = m(i,1);
+		src[i + 8] = m(i,2);
+		src[i + 12] = m(i,3); 
+	}
+	/* calculate pairs for first 8 elements (cofactors) */
+	tmp[0]  = src[10] * src[15];
+	tmp[1]  = src[11] * src[14];
+	tmp[2]  = src[9] * src[15];
+	tmp[3]  = src[11] * src[13];
+	tmp[4]  = src[9] * src[14];
+	tmp[5]  = src[10] * src[13];
+	tmp[6]  = src[8] * src[15];
+	tmp[7]  = src[11] * src[12];
+	tmp[8]  = src[8] * src[14];
+	tmp[9]  = src[10] * src[12];
+	tmp[10] = src[8] * src[13];
+	tmp[11] = src[9] * src[12];
+	/* calculate first 8 elements (cofactors) */
+	dst[0]  = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
+	dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
+	dst[1]  = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
+	dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
+	dst[2]  = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
+	dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
+	dst[3]  = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
+	dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
+	dst[4]  = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
+	dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
+	dst[5]  = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
+	dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
+	dst[6]  = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
+	dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
+	dst[7]  = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
+	dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
+	/* calculate pairs for second 8 elements (cofactors) */
+	tmp[0]  = src[2]*src[7];
+	tmp[1]  = src[3]*src[6];
+	tmp[2]  = src[1]*src[7];
+	tmp[3]  = src[3]*src[5];
+	tmp[4]  = src[1]*src[6];
+	tmp[5]  = src[2]*src[5];
+	tmp[6]  = src[0]*src[7];
+	tmp[7]  = src[3]*src[4];
+	tmp[8]  = src[0]*src[6];
+	tmp[9]  = src[2]*src[4];
+	tmp[10] = src[0]*src[5];
+	tmp[11] = src[1]*src[4];
+	/* calculate second 8 elements (cofactors) */
+	dst[8]  = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
+	dst[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
+	dst[9]  = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
+	dst[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
+	dst[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
+	dst[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
+	dst[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
+	dst[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
+	dst[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
+	dst[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
+	dst[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
+	dst[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
+	dst[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
+	dst[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
+	dst[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
+	dst[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
+	/* calculate determinant */
+	det=src[0]*dst[0]+src[1]*dst[1]+src[2]*dst[2]+src[3]*dst[3];
+	/* calculate matrix inverse */
+	det = 1/det;
+	for ( int j = 0; j < 16; j++)
+	dst[j] *= det;
+	return d;
+}
+
+
+//--------- Quaternion --------------
+
+Quaternion operator*( const Quaternion& a, const Quaternion& b )
+{
+	Quaternion c;
+	c.w = a.w*b.w - a.x*b.x - a.y*b.y - a.z*b.z;
+	c.x = a.w*b.x + a.x*b.w + a.y*b.z - a.z*b.y; 
+	c.y = a.w*b.y - a.x*b.z + a.y*b.w + a.z*b.x; 
+	c.z = a.w*b.z + a.x*b.y - a.y*b.x + a.z*b.w; 
+	return c;
+}
+
+
+Quaternion operator*( const Quaternion& a, float b )
+{
+	return Quaternion(a.x*b, a.y*b, a.z*b ,a.w*b);
+}
+
+Quaternion  Inverse(const Quaternion &q)
+{
+	return Quaternion(-q.x,-q.y,-q.z,q.w);
+}
+
+Quaternion& operator*=( Quaternion& q, const float s )
+{
+		q.x *= s;
+		q.y *= s;
+		q.z *= s;
+		q.w *= s;
+		return q;
+}
+void Quaternion::Normalize()
+{
+	float m = sqrtf(sqr(w)+sqr(x)+sqr(y)+sqr(z));
+	if(m<0.000000001f) {
+		w=1.0f;
+		x=y=z=0.0f;
+		return;
+	}
+	(*this) *= (1.0f/m);
+}
+
+float3 operator*( const Quaternion& q, const float3& v )
+{
+	// The following is equivalent to:
+	//return (q.getmatrix() * v);
+	float qx2 = q.x*q.x;
+	float qy2 = q.y*q.y;
+	float qz2 = q.z*q.z;
+
+	float qxqy = q.x*q.y;
+	float qxqz = q.x*q.z;
+	float qxqw = q.x*q.w;
+	float qyqz = q.y*q.z;
+	float qyqw = q.y*q.w;
+	float qzqw = q.z*q.w;
+	return float3(
+		(1-2*(qy2+qz2))*v.x + (2*(qxqy-qzqw))*v.y + (2*(qxqz+qyqw))*v.z ,
+		(2*(qxqy+qzqw))*v.x + (1-2*(qx2+qz2))*v.y + (2*(qyqz-qxqw))*v.z ,
+		(2*(qxqz-qyqw))*v.x + (2*(qyqz+qxqw))*v.y + (1-2*(qx2+qy2))*v.z  );
+}
+
+float3 operator*( const float3& v, const Quaternion& q )
+{
+	assert(0);  // must multiply with the quat on the left
+	return float3(0.0f,0.0f,0.0f);
+}
+
+Quaternion operator+( const Quaternion& a, const Quaternion& b )
+{
+	return Quaternion(a.x+b.x, a.y+b.y, a.z+b.z, a.w+b.w);
+}
+
+float dot( const Quaternion &a,const Quaternion &b )
+{
+	return  (a.w*b.w + a.x*b.x + a.y*b.y + a.z*b.z);
+}
+
+Quaternion normalize( Quaternion a )
+{
+	float m = sqrtf(sqr(a.w)+sqr(a.x)+sqr(a.y)+sqr(a.z));
+	if(m<0.000000001) 
+		{    
+		a.w=1;
+		a.x=a.y=a.z=0;
+		return a;
+	}
+	return a * (1/m);
+}
+
+Quaternion slerp( Quaternion a, const Quaternion& b, float interp )
+{
+	if(dot(a,b) <0.0) 
+		{
+		a.w=-a.w;
+		a.x=-a.x;
+		a.y=-a.y;
+		a.z=-a.z;
+	}
+	float d = dot(a,b);
+	if(d>=1.0) {
+		return a;
+	}
+	float theta = acosf(d);
+	if(theta==0.0f) { return(a);}
+	return a*(sinf(theta-interp*theta)/sinf(theta)) + b*(sinf(interp*theta)/sinf(theta));
+}
+
+
+Quaternion Interpolate(const Quaternion &q0,const Quaternion &q1,float alpha) {
+	return slerp(q0,q1,alpha);
+}
+
+
+Quaternion YawPitchRoll( float yaw, float pitch, float roll ) 
+{
+	roll  *= DEG2RAD;
+	yaw   *= DEG2RAD;
+	pitch *= DEG2RAD;
+	return Quaternion(float3(0.0f,0.0f,1.0f),yaw)*Quaternion(float3(1.0f,0.0f,0.0f),pitch)*Quaternion(float3(0.0f,1.0f,0.0f),roll);
+}
+
+float Yaw( const Quaternion& q )
+{
+	static float3 v;
+	v=q.ydir();
+	return (v.y==0.0&&v.x==0.0) ? 0.0f: atan2f(-v.x,v.y)*RAD2DEG;
+}
+
+float Pitch( const Quaternion& q )
+{
+	static float3 v;
+	v=q.ydir();
+	return atan2f(v.z,sqrtf(sqr(v.x)+sqr(v.y)))*RAD2DEG;
+}
+
+float Roll( Quaternion q )
+{
+	q = Quaternion(float3(0.0f,0.0f,1.0f),-Yaw(q)*DEG2RAD)  *q;
+	q = Quaternion(float3(1.0f,0.0f,0.0f),-Pitch(q)*DEG2RAD)  *q;
+	return atan2f(-q.xdir().z,q.xdir().x)*RAD2DEG;
+}
+
+float Yaw( const float3& v )
+{
+	return (v.y==0.0&&v.x==0.0) ? 0.0f: atan2f(-v.x,v.y)*RAD2DEG;
+}
+
+float Pitch( const float3& v )
+{
+	return atan2f(v.z,sqrtf(sqr(v.x)+sqr(v.y)))*RAD2DEG;
+}
+
+
+//------------- Plane --------------
+
+
+void Plane::Transform(const float3 &position, const Quaternion &orientation) {
+	//   Transforms the plane to the space defined by the 
+	//   given position/orientation.
+	static float3 newnormal;
+	static float3 origin;
+
+	newnormal = Inverse(orientation)*normal;
+	origin = Inverse(orientation)*(-normal*dist - position);
+
+	normal = newnormal;
+	dist = -dot(newnormal, origin);
+}
+
+
+
+
+//--------- utility functions -------------
+
+//        RotationArc()
+// Given two vectors v0 and v1 this function
+// returns quaternion q where q*v0==v1.
+// Routine taken from game programming gems.
+Quaternion RotationArc(float3 v0,float3 v1){
+	static Quaternion q;
+	v0 = normalize(v0);  // Comment these two lines out if you know its not needed.
+	v1 = normalize(v1);  // If vector is already unit length then why do it again?
+	float3  c = cross(v0,v1);
+	float   d = dot(v0,v1);
+	if(d<=-1.0f) { return Quaternion(1,0,0,0);} // 180 about x axis
+	float   s = sqrtf((1+d)*2);
+	q.x = c.x / s;
+	q.y = c.y / s;
+	q.z = c.z / s;
+	q.w = s /2.0f;
+	return q;
+}
+
+
+float4x4 MatrixFromQuatVec(const Quaternion &q, const float3 &v) 
+{
+	// builds a 4x4 transformation matrix based on orientation q and translation v 
+	float qx2 = q.x*q.x;
+	float qy2 = q.y*q.y;
+	float qz2 = q.z*q.z;
+
+	float qxqy = q.x*q.y;
+	float qxqz = q.x*q.z;
+	float qxqw = q.x*q.w;
+	float qyqz = q.y*q.z;
+	float qyqw = q.y*q.w;
+	float qzqw = q.z*q.w;
+
+	return float4x4(
+		1-2*(qy2+qz2),  
+		2*(qxqy+qzqw),
+		2*(qxqz-qyqw),  
+		0            ,  
+		2*(qxqy-qzqw),  
+		1-2*(qx2+qz2),
+		2*(qyqz+qxqw),  
+		0            ,  
+		2*(qxqz+qyqw),  
+		2*(qyqz-qxqw),  
+		1-2*(qx2+qy2),  
+		0    , 
+		 v.x ,
+		 v.y ,
+		 v.z ,
+		 1.0f );
+}
+
+
+float3 PlaneLineIntersection(const Plane &plane, const float3 &p0, const float3 &p1)
+{
+	// returns the point where the line p0-p1 intersects the plane n&d
+				static float3 dif;
+		dif = p1-p0;
+				float dn= dot(plane.normal,dif);
+				float t = -(plane.dist+dot(plane.normal,p0) )/dn;
+				return p0 + (dif*t);
+}
+
+float3 PlaneProject(const Plane &plane, const float3 &point)
+{
+	return point - plane.normal * (dot(point,plane.normal)+plane.dist);
+}
+
+float3 LineProject(const float3 &p0, const float3 &p1, const float3 &a)
+{
+	float3 w;
+	w = p1-p0;
+	float t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z));
+	return p0+ w*t;
+}
+
+
+float LineProjectTime(const float3 &p0, const float3 &p1, const float3 &a)
+{
+	float3 w;
+	w = p1-p0;
+	float t= dot(w,(a-p0)) / (sqr(w.x)+sqr(w.y)+sqr(w.z));
+	return t;
+}
+
+
+
+float3 TriNormal(const float3 &v0, const float3 &v1, const float3 &v2)
+{
+	// return the normal of the triangle
+	// inscribed by v0, v1, and v2
+	float3 cp=cross(v1-v0,v2-v1);
+	float m=magnitude(cp);
+	if(m==0) return float3(1,0,0);
+	return cp*(1.0f/m);
+}
+
+
+
+int BoxInside(const float3 &p, const float3 &bmin, const float3 &bmax) 
+{
+	return (p.x >= bmin.x && p.x <=bmax.x && 
+			p.y >= bmin.y && p.y <=bmax.y && 
+			p.z >= bmin.z && p.z <=bmax.z );
+}
+
+
+int BoxIntersect(const float3 &v0, const float3 &v1, const float3 &bmin, const float3 &bmax,float3 *impact)
+{
+	if(BoxInside(v0,bmin,bmax))
+		{
+				*impact=v0;
+				return 1;
+		}
+	if(v0.x<=bmin.x && v1.x>=bmin.x) 
+		{
+		float a = (bmin.x-v0.x)/(v1.x-v0.x);
+		//v.x = bmin.x;
+		float vy =  (1-a) *v0.y + a*v1.y;
+		float vz =  (1-a) *v0.z + a*v1.z;
+		if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z) 
+				{
+			impact->x = bmin.x;
+			impact->y = vy;
+			impact->z = vz;
+			return 1;
+		}
+	}
+	else if(v0.x >= bmax.x  &&  v1.x <= bmax.x) 
+		{
+		float a = (bmax.x-v0.x)/(v1.x-v0.x);
+		//v.x = bmax.x;
+		float vy =  (1-a) *v0.y + a*v1.y;
+		float vz =  (1-a) *v0.z + a*v1.z;
+		if(vy>=bmin.y && vy<=bmax.y && vz>=bmin.z && vz<=bmax.z) 
+				{
+			impact->x = bmax.x;
+			impact->y = vy;
+			impact->z = vz;
+			return 1;
+		}
+	}
+	if(v0.y<=bmin.y && v1.y>=bmin.y) 
+		{
+		float a = (bmin.y-v0.y)/(v1.y-v0.y);
+		float vx =  (1-a) *v0.x + a*v1.x;
+		//v.y = bmin.y;
+		float vz =  (1-a) *v0.z + a*v1.z;
+		if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z) 
+				{
+			impact->x = vx;
+			impact->y = bmin.y;
+			impact->z = vz;
+			return 1;
+		}
+	}
+	else if(v0.y >= bmax.y  &&  v1.y <= bmax.y) 
+		{
+		float a = (bmax.y-v0.y)/(v1.y-v0.y);
+		float vx =  (1-a) *v0.x + a*v1.x;
+		// vy = bmax.y;
+		float vz =  (1-a) *v0.z + a*v1.z;
+		if(vx>=bmin.x && vx<=bmax.x && vz>=bmin.z && vz<=bmax.z)
+				{
+			impact->x = vx;
+			impact->y = bmax.y;
+			impact->z = vz;
+			return 1;
+		}
+	}
+	if(v0.z<=bmin.z && v1.z>=bmin.z) 
+		{
+		float a = (bmin.z-v0.z)/(v1.z-v0.z);
+		float vx =  (1-a) *v0.x + a*v1.x;
+		float vy =  (1-a) *v0.y + a*v1.y;
+		// v.z = bmin.z;
+		if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x) 
+				{
+			impact->x = vx;
+			impact->y = vy;
+			impact->z = bmin.z;
+			return 1;
+		}
+	}
+	else if(v0.z >= bmax.z  &&  v1.z <= bmax.z) 
+		{
+		float a = (bmax.z-v0.z)/(v1.z-v0.z);
+		float vx =  (1-a) *v0.x + a*v1.x;
+		float vy =  (1-a) *v0.y + a*v1.y;
+		// v.z = bmax.z;
+		if(vy>=bmin.y && vy<=bmax.y && vx>=bmin.x && vx<=bmax.x) 
+				{
+			impact->x = vx;
+			impact->y = vy;
+			impact->z = bmax.z;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+
+float DistanceBetweenLines(const float3 &ustart, const float3 &udir, const float3 &vstart, const float3 &vdir, float3 *upoint, float3 *vpoint)
+{
+	static float3 cp;
+	cp = normalize(cross(udir,vdir));
+
+	float distu = -dot(cp,ustart);
+	float distv = -dot(cp,vstart);
+	float dist = (float)fabs(distu-distv);
+	if(upoint) 
+		{
+		Plane plane;
+		plane.normal = normalize(cross(vdir,cp));
+		plane.dist = -dot(plane.normal,vstart);
+		*upoint = PlaneLineIntersection(plane,ustart,ustart+udir);
+	}
+	if(vpoint) 
+		{
+		Plane plane;
+		plane.normal = normalize(cross(udir,cp));
+		plane.dist = -dot(plane.normal,ustart);
+		*vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir);
+	}
+	return dist;
+}
+
+
+Quaternion VirtualTrackBall(const float3 &cop, const float3 &cor, const float3 &dir1, const float3 &dir2) 
+{
+	// routine taken from game programming gems.
+	// Implement track ball functionality to spin stuf on the screen
+	//  cop   center of projection
+	//  cor   center of rotation
+	//  dir1  old mouse direction 
+	//  dir2  new mouse direction
+	// pretend there is a sphere around cor.  Then find the points
+	// where dir1 and dir2 intersect that sphere.  Find the
+	// rotation that takes the first point to the second.
+	float m;
+	// compute plane 
+	float3 nrml = cor - cop;
+	float fudgefactor = 1.0f/(magnitude(nrml) * 0.25f); // since trackball proportional to distance from cop
+	nrml = normalize(nrml);
+	float dist = -dot(nrml,cor);
+	float3 u= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir1);
+	u=u-cor;
+	u=u*fudgefactor;
+	m= magnitude(u);
+	if(m>1)
+		{
+				u/=m;
+		}
+	else 
+		{
+		u=u - (nrml * sqrtf(1-m*m));
+	}
+	float3 v= PlaneLineIntersection(Plane(nrml,dist),cop,cop+dir2);
+	v=v-cor;
+	v=v*fudgefactor;
+	m= magnitude(v);
+	if(m>1) 
+		{
+				v/=m;
+		}
+	else 
+		{
+		v=v - (nrml * sqrtf(1-m*m));
+	}
+	return RotationArc(u,v);
+}
+
+
+int countpolyhit=0;
+int PolyHit(const float3 *vert, const int n, const float3 &v0, const float3 &v1, float3 *impact, float3 *normal)
+{
+	countpolyhit++;
+	int i;
+	float3 nrml(0,0,0);
+	for(i=0;i<n;i++) 
+		{
+		int i1=(i+1)%n;
+		int i2=(i+2)%n;
+		nrml = nrml + cross(vert[i1]-vert[i],vert[i2]-vert[i1]);
+	}
+
+	float m = magnitude(nrml);
+	if(m==0.0)
+		{
+				return 0;
+		}
+	nrml = nrml * (1.0f/m);
+	float dist = -dot(nrml,vert[0]);
+	float d0,d1;
+	if((d0=dot(v0,nrml)+dist) <0  ||  (d1=dot(v1,nrml)+dist) >0) 
+		{        
+				return 0;
+		}
+
+	static float3 the_point; 
+	// By using the cached plane distances d0 and d1
+	// we can optimize the following:
+	//     the_point = planelineintersection(nrml,dist,v0,v1);
+	float a = d0/(d0-d1);
+	the_point = v0*(1-a) + v1*a;
+
+
+	int inside=1;
+	for(int j=0;inside && j<n;j++) 
+		{
+			// let inside = 0 if outside
+			float3 pp1,pp2,side;
+			pp1 = vert[j] ;
+			pp2 = vert[(j+1)%n];
+			side = cross((pp2-pp1),(the_point-pp1));
+			inside = (dot(nrml,side) >= 0.0);
+	}
+	if(inside) 
+		{
+		if(normal){*normal=nrml;}
+		if(impact){*impact=the_point;}
+	}
+	return inside;
+}
+
+//**************************************************************************
+//**************************************************************************
+//*** Stan Melax's array template, needed to compile his hull generation code
+//**************************************************************************
+//**************************************************************************
+
+template <class Type> class ArrayRet;
+template <class Type> class Array {
+	public:
+				Array(int s=0);
+				Array(Array<Type> &array);
+				Array(ArrayRet<Type> &array);
+				~Array();
+	void		allocate(int s);
+	void		SetSize(int s);
+	void		Pack();
+	Type&		Add(Type);
+	void		AddUnique(Type);
+	int 		Contains(Type);
+	void		Insert(Type,int);
+	int			IndexOf(Type);
+	void		Remove(Type);
+	void		DelIndex(int i);
+	Type *		element;
+	int			count;
+	int			array_size;
+	const Type	&operator[](int i) const { assert(i>=0 && i<count);  return element[i]; }
+	Type		&operator[](int i)  { assert(i>=0 && i<count);  return element[i]; }
+	Type		&Pop() { assert(count); count--;  return element[count]; }
+	Array<Type> &operator=(Array<Type> &array);
+	Array<Type> &operator=(ArrayRet<Type> &array);
+	// operator ArrayRet<Type> &() { return *(ArrayRet<Type> *)this;} // this worked but i suspect could be dangerous
+};
+
+template <class Type> class ArrayRet:public Array<Type>
+{
+};
+
+template <class Type> Array<Type>::Array(int s)
+{
+	count=0;
+	array_size = 0;
+	element = NULL;
+	if(s) 
+	{
+		allocate(s);
+	}
+}
+
+
+template <class Type> Array<Type>::Array(Array<Type> &array)
+{
+	count=0;
+	array_size = 0;
+	element = NULL;
+	for(int i=0;i<array.count;i++)
+	{
+		Add(array[i]);
+	}
+}
+
+
+template <class Type> Array<Type>::Array(ArrayRet<Type> &array)
+{
+	*this = array;
+}
+template <class Type> Array<Type> &Array<Type>::operator=(ArrayRet<Type> &array)
+{
+	count=array.count;
+	array_size = array.array_size;
+	element = array.element;
+	array.element=NULL;
+	array.count=0;
+	array.array_size=0;
+	return *this;
+}
+
+
+template <class Type> Array<Type> &Array<Type>::operator=(Array<Type> &array)
+{
+	count=0;
+	for(int i=0;i<array.count;i++)
+	{
+		Add(array[i]);
+	}
+	return *this;
+}
+
+template <class Type> Array<Type>::~Array()
+{
+	if (element != NULL)
+	{
+	  free(element);
+	}
+	count=0;array_size=0;element=NULL;
+}
+
+template <class Type> void Array<Type>::allocate(int s)
+{
+	assert(s>0);
+	assert(s>=count);
+	Type *old = element;
+	array_size =s;
+	element = (Type *) malloc( sizeof(Type)*array_size);
+	assert(element);
+	for(int i=0;i<count;i++)
+	{
+		element[i]=old[i];
+	}
+	if(old)
+	{
+		free(old);
+	}
+}
+
+template <class Type> void Array<Type>::SetSize(int s)
+{
+	if(s==0)
+	{
+		if(element)
+		{
+			free(element);
+			element = NULL;
+		}
+ 	  array_size = s;
+	}
+	else
+	{
+		allocate(s);
+	}
+	count=s;
+}
+
+template <class Type> void Array<Type>::Pack()
+{
+	allocate(count);
+}
+
+template <class Type> Type& Array<Type>::Add(Type t)
+{
+	assert(count<=array_size);
+	if(count==array_size)
+	{
+		allocate((array_size)?array_size *2:16);
+	}
+	element[count++] = t;
+	return element[count-1];
+}
+
+template <class Type> int Array<Type>::Contains(Type t)
+{
+	int i;
+	int found=0;
+	for(i=0;i<count;i++)
+	{
+		if(element[i] == t) found++;
+	}
+	return found;
+}
+
+template <class Type> void Array<Type>::AddUnique(Type t)
+{
+	if(!Contains(t)) Add(t);
+}
+
+
+template <class Type> void Array<Type>::DelIndex(int i)
+{
+	assert(i<count);
+	count--;
+	while(i<count)
+	{
+		element[i] = element[i+1];
+		i++;
+	}
+}
+
+template <class Type> void Array<Type>::Remove(Type t)
+{
+	int i;
+	for(i=0;i<count;i++)
+	{
+		if(element[i] == t)
+		{
+			break;
+		}
+	}
+	assert(i<count); // assert object t is in the array.
+	DelIndex(i);
+	for(i=0;i<count;i++)
+	{
+		assert(element[i] != t);
+	}
+}
+
+template <class Type> void Array<Type>::Insert(Type t,int k)
+{
+	int i=count;
+	Add(t); // to allocate space
+	while(i>k)
+	{
+		element[i]=element[i-1];
+		i--;
+	}
+	assert(i==k);
+	element[k]=t;
+}
+
+
+template <class Type> int Array<Type>::IndexOf(Type t)
+{
+	int i;
+	for(i=0;i<count;i++)
+	{
+		if(element[i] == t)
+		{
+			return i;
+		}
+	}
+	assert(0);
+	return -1;
+}
+
+
+
+//*********************************************************************
+//*********************************************************************
+//********  Hull header
+//*********************************************************************
+//*********************************************************************
+
+class PHullResult
+{
+public:
+
+	PHullResult(void)
+	{
+		mVcount = 0;
+		mIndexCount = 0;
+		mFaceCount = 0;
+		mVertices = 0;
+		mIndices  = 0;
+	}
+
+	unsigned int mVcount;
+	unsigned int mIndexCount;
+	unsigned int mFaceCount;
+	float       *mVertices;
+	unsigned int *mIndices;
+};
+
+
+#define REAL3 float3
+#define REAL  float
+
+#define COPLANAR   (0)
+#define UNDER      (1)
+#define OVER       (2)
+#define SPLIT      (OVER|UNDER)
+#define PAPERWIDTH (0.001f)
+
+float planetestepsilon = PAPERWIDTH;
+
+
+class ConvexH 
+{
+  public:
+	class HalfEdge
+	{
+	  public:
+		short ea;         // the other half of the edge (index into edges list)
+		unsigned char v;  // the vertex at the start of this edge (index into vertices list)
+		unsigned char p;  // the facet on which this edge lies (index into facets list)
+		HalfEdge(){}
+		HalfEdge(short _ea,unsigned char _v, unsigned char _p):ea(_ea),v(_v),p(_p){}
+	};
+	Array<REAL3> vertices;
+	Array<HalfEdge> edges;
+	Array<Plane>  facets;
+	ConvexH(int vertices_size,int edges_size,int facets_size);
+};
+
+typedef ConvexH::HalfEdge HalfEdge;
+
+ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size)
+	:vertices(vertices_size)
+	,edges(edges_size)
+	,facets(facets_size)
+{
+	vertices.count=vertices_size;
+	edges.count   = edges_size;
+	facets.count  = facets_size;
+}
+
+ConvexH *ConvexHDup(ConvexH *src) {
+	ConvexH *dst = new ConvexH(src->vertices.count,src->edges.count,src->facets.count);
+	memcpy(dst->vertices.element,src->vertices.element,sizeof(float3)*src->vertices.count);
+	memcpy(dst->edges.element,src->edges.element,sizeof(HalfEdge)*src->edges.count);
+	memcpy(dst->facets.element,src->facets.element,sizeof(Plane)*src->facets.count);
+	return dst;
+}
+
+
+int PlaneTest(const Plane &p, const REAL3 &v) {
+	REAL a  = dot(v,p.normal)+p.dist;
+	int   flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR);
+	return flag;
+}
+
+int SplitTest(ConvexH &convex,const Plane &plane) {
+	int flag=0;
+	for(int i=0;i<convex.vertices.count;i++) {
+		flag |= PlaneTest(plane,convex.vertices[i]);
+	}
+	return flag;
+}
+
+class VertFlag
+{
+public:
+	unsigned char planetest;
+	unsigned char junk;
+	unsigned char undermap;
+	unsigned char overmap;
+};
+class EdgeFlag 
+{
+public:
+	unsigned char planetest;
+	unsigned char fixes;
+	short undermap;
+	short overmap;
+};
+class PlaneFlag
+{
+public:
+	unsigned char undermap;
+	unsigned char overmap;
+};
+class Coplanar{
+public:
+	unsigned short ea;
+	unsigned char v0;
+	unsigned char v1;
+};
+
+int AssertIntact(ConvexH &convex) {
+	int i;
+	int estart=0;
+	for(i=0;i<convex.edges.count;i++) {
+		if(convex.edges[estart].p!= convex.edges[i].p) {
+			estart=i;
+		}
+		int inext = i+1;
+		if(inext>= convex.edges.count || convex.edges[inext].p != convex.edges[i].p) {
+			inext = estart;
+		}
+		assert(convex.edges[inext].p == convex.edges[i].p);
+		int nb = convex.edges[i].ea;
+		assert(nb!=255);
+		if(nb==255 || nb==-1) return 0;
+		assert(nb!=-1);
+		assert(i== convex.edges[nb].ea);
+	}
+	for(i=0;i<convex.edges.count;i++) {
+		assert(COPLANAR==PlaneTest(convex.facets[convex.edges[i].p],convex.vertices[convex.edges[i].v]));
+		if(COPLANAR!=PlaneTest(convex.facets[convex.edges[i].p],convex.vertices[convex.edges[i].v])) return 0;
+		if(convex.edges[estart].p!= convex.edges[i].p) {
+			estart=i;
+		}
+		int i1 = i+1;
+		if(i1>= convex.edges.count || convex.edges[i1].p != convex.edges[i].p) {
+			i1 = estart;
+		}
+		int i2 = i1+1;
+		if(i2>= convex.edges.count || convex.edges[i2].p != convex.edges[i].p) {
+			i2 = estart;
+		}
+		if(i==i2) continue; // i sliced tangent to an edge and created 2 meaningless edges
+		REAL3 localnormal = TriNormal(convex.vertices[convex.edges[i ].v],
+			                           convex.vertices[convex.edges[i1].v],
+			                           convex.vertices[convex.edges[i2].v]);
+		assert(dot(localnormal,convex.facets[convex.edges[i].p].normal)>0);
+		if(dot(localnormal,convex.facets[convex.edges[i].p].normal)<=0)return 0;
+	}
+	return 1;
+}
+
+// back to back quads
+ConvexH *test_btbq() {
+	ConvexH *convex = new ConvexH(4,8,2);
+	convex->vertices[0] = REAL3(0,0,0);
+	convex->vertices[1] = REAL3(1,0,0);
+	convex->vertices[2] = REAL3(1,1,0);
+	convex->vertices[3] = REAL3(0,1,0);
+	convex->facets[0] = Plane(REAL3(0,0,1),0);
+	convex->facets[1] = Plane(REAL3(0,0,-1),0);
+	convex->edges[0]  = HalfEdge(7,0,0);
+	convex->edges[1]  = HalfEdge(6,1,0);
+	convex->edges[2]  = HalfEdge(5,2,0);
+	convex->edges[3]  = HalfEdge(4,3,0);
+
+	convex->edges[4]  = HalfEdge(3,0,1);
+	convex->edges[5]  = HalfEdge(2,3,1);
+	convex->edges[6]  = HalfEdge(1,2,1);
+	convex->edges[7]  = HalfEdge(0,1,1);
+	AssertIntact(*convex);
+	return convex;
+}
+ConvexH *test_cube() {
+	ConvexH *convex = new ConvexH(8,24,6);
+	convex->vertices[0] = REAL3(0,0,0);
+	convex->vertices[1] = REAL3(0,0,1);
+	convex->vertices[2] = REAL3(0,1,0);
+	convex->vertices[3] = REAL3(0,1,1);
+	convex->vertices[4] = REAL3(1,0,0);
+	convex->vertices[5] = REAL3(1,0,1);
+	convex->vertices[6] = REAL3(1,1,0);
+	convex->vertices[7] = REAL3(1,1,1);
+
+	convex->facets[0] = Plane(REAL3(-1,0,0),0);
+	convex->facets[1] = Plane(REAL3(1,0,0),-1);
+	convex->facets[2] = Plane(REAL3(0,-1,0),0);
+	convex->facets[3] = Plane(REAL3(0,1,0),-1);
+	convex->facets[4] = Plane(REAL3(0,0,-1),0);
+	convex->facets[5] = Plane(REAL3(0,0,1),-1);
+
+	convex->edges[0 ] = HalfEdge(11,0,0);
+	convex->edges[1 ] = HalfEdge(23,1,0);
+	convex->edges[2 ] = HalfEdge(15,3,0);
+	convex->edges[3 ] = HalfEdge(16,2,0);
+
+	convex->edges[4 ] = HalfEdge(13,6,1);
+	convex->edges[5 ] = HalfEdge(21,7,1);
+	convex->edges[6 ] = HalfEdge( 9,5,1);
+	convex->edges[7 ] = HalfEdge(18,4,1);
+
+	convex->edges[8 ] = HalfEdge(19,0,2);
+	convex->edges[9 ] = HalfEdge( 6,4,2);
+	convex->edges[10] = HalfEdge(20,5,2);
+	convex->edges[11] = HalfEdge( 0,1,2);
+
+	convex->edges[12] = HalfEdge(22,3,3);
+	convex->edges[13] = HalfEdge( 4,7,3);
+	convex->edges[14] = HalfEdge(17,6,3);
+	convex->edges[15] = HalfEdge( 2,2,3);
+
+	convex->edges[16] = HalfEdge( 3,0,4);
+	convex->edges[17] = HalfEdge(14,2,4);
+	convex->edges[18] = HalfEdge( 7,6,4);
+	convex->edges[19] = HalfEdge( 8,4,4);
+	
+	convex->edges[20] = HalfEdge(10,1,5);
+	convex->edges[21] = HalfEdge( 5,5,5);
+	convex->edges[22] = HalfEdge(12,7,5);
+	convex->edges[23] = HalfEdge( 1,3,5);
+
+	
+	return convex;
+}
+ConvexH *ConvexHMakeCube(const REAL3 &bmin, const REAL3 &bmax) {
+	ConvexH *convex = test_cube();
+	convex->vertices[0] = REAL3(bmin.x,bmin.y,bmin.z);
+	convex->vertices[1] = REAL3(bmin.x,bmin.y,bmax.z);
+	convex->vertices[2] = REAL3(bmin.x,bmax.y,bmin.z);
+	convex->vertices[3] = REAL3(bmin.x,bmax.y,bmax.z);
+	convex->vertices[4] = REAL3(bmax.x,bmin.y,bmin.z);
+	convex->vertices[5] = REAL3(bmax.x,bmin.y,bmax.z);
+	convex->vertices[6] = REAL3(bmax.x,bmax.y,bmin.z);
+	convex->vertices[7] = REAL3(bmax.x,bmax.y,bmax.z);
+
+	convex->facets[0] = Plane(REAL3(-1,0,0), bmin.x);
+	convex->facets[1] = Plane(REAL3(1,0,0), -bmax.x);
+	convex->facets[2] = Plane(REAL3(0,-1,0), bmin.y);
+	convex->facets[3] = Plane(REAL3(0,1,0), -bmax.y);
+	convex->facets[4] = Plane(REAL3(0,0,-1), bmin.z);
+	convex->facets[5] = Plane(REAL3(0,0,1), -bmax.z);
+	return convex;
+}
+ConvexH *ConvexHCrop(ConvexH &convex,const Plane &slice)
+{
+	int i;
+	int vertcountunder=0;
+	int vertcountover =0;
+	static Array<int> vertscoplanar;  // existing vertex members of convex that are coplanar
+	vertscoplanar.count=0;
+	static Array<int> edgesplit;  // existing edges that members of convex that cross the splitplane
+	edgesplit.count=0;
+
+	assert(convex.edges.count<480);
+
+	EdgeFlag  edgeflag[512];
+	VertFlag  vertflag[256];
+	PlaneFlag planeflag[128];
+	HalfEdge  tmpunderedges[512];
+	Plane	  tmpunderplanes[128];
+	Coplanar coplanaredges[512];
+	int coplanaredges_num=0;
+
+	Array<REAL3> createdverts;
+	// do the side-of-plane tests
+	for(i=0;i<convex.vertices.count;i++) {
+		vertflag[i].planetest = PlaneTest(slice,convex.vertices[i]);
+		if(vertflag[i].planetest == COPLANAR) {
+			// ? vertscoplanar.Add(i);
+			vertflag[i].undermap = vertcountunder++;
+			vertflag[i].overmap  = vertcountover++;
+		}
+		else if(vertflag[i].planetest == UNDER)	{
+			vertflag[i].undermap = vertcountunder++;
+		}
+		else {
+			assert(vertflag[i].planetest == OVER);
+			vertflag[i].overmap  = vertcountover++;
+			vertflag[i].undermap = 255; // for debugging purposes
+		}
+	}
+	int vertcountunderold = vertcountunder; // for debugging only
+
+	int under_edge_count =0;
+	int underplanescount=0;
+	int e0=0;
+
+	for(int currentplane=0; currentplane<convex.facets.count; currentplane++) {
+		int estart =e0;
+		int enextface = 0;
+		int planeside = 0;
+		int e1 = e0+1;
+		int vout=-1;
+		int vin =-1;
+		int coplanaredge = -1;
+		do{
+
+			if(e1 >= convex.edges.count || convex.edges[e1].p!=currentplane) {
+				enextface = e1;
+				e1=estart;
+			}
+			HalfEdge &edge0 = convex.edges[e0];
+			HalfEdge &edge1 = convex.edges[e1];
+			HalfEdge &edgea = convex.edges[edge0.ea];
+
+
+			planeside |= vertflag[edge0.v].planetest;
+			//if((vertflag[edge0.v].planetest & vertflag[edge1.v].planetest)  == COPLANAR) {
+			//	assert(ecop==-1);
+			//	ecop=e;
+			//}
+
+
+			if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == OVER){
+				// both endpoints over plane
+				edgeflag[e0].undermap  = -1;
+			}
+			else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest)  == UNDER) {
+				// at least one endpoint under, the other coplanar or under
+				
+				edgeflag[e0].undermap = under_edge_count;
+				tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap;
+				tmpunderedges[under_edge_count].p = underplanescount;
+				if(edge0.ea < e0) {
+					// connect the neighbors
+					assert(edgeflag[edge0.ea].undermap !=-1);
+					tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
+					tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count;
+				}
+				under_edge_count++;
+			}
+			else if((vertflag[edge0.v].planetest | vertflag[edge1.v].planetest)  == COPLANAR) {
+				// both endpoints coplanar 
+				// must check a 3rd point to see if UNDER
+				int e2 = e1+1;
+				if(e2>=convex.edges.count || convex.edges[e2].p!=currentplane) {
+					e2 = estart;
+				}
+				assert(convex.edges[e2].p==currentplane);
+				HalfEdge &edge2 = convex.edges[e2];
+				if(vertflag[edge2.v].planetest==UNDER) {
+					
+					edgeflag[e0].undermap = under_edge_count;
+					tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap;
+					tmpunderedges[under_edge_count].p = underplanescount;
+					tmpunderedges[under_edge_count].ea = -1;
+					// make sure this edge is added to the "coplanar" list
+					coplanaredge = under_edge_count;
+					vout = vertflag[edge0.v].undermap;
+					vin  = vertflag[edge1.v].undermap;
+					under_edge_count++;
+				}
+				else {
+					edgeflag[e0].undermap = -1;
+				}
+			}
+			else if(vertflag[edge0.v].planetest == UNDER && vertflag[edge1.v].planetest == OVER) {
+				// first is under 2nd is over 
+				
+				edgeflag[e0].undermap = under_edge_count;
+				tmpunderedges[under_edge_count].v = vertflag[edge0.v].undermap;
+				tmpunderedges[under_edge_count].p = underplanescount;
+				if(edge0.ea < e0) {
+					assert(edgeflag[edge0.ea].undermap !=-1);
+					// connect the neighbors
+					tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
+					tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count;
+					vout = tmpunderedges[edgeflag[edge0.ea].undermap].v;
+				}
+				else {
+					Plane &p0 = convex.facets[edge0.p];
+					Plane &pa = convex.facets[edgea.p];
+					createdverts.Add(ThreePlaneIntersection(p0,pa,slice));
+					//createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])));
+					//createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]));
+					vout = vertcountunder++;
+				}
+				under_edge_count++;
+				/// hmmm something to think about: i might be able to output this edge regarless of 
+				// wheter or not we know v-in yet.  ok i;ll try this now:
+				tmpunderedges[under_edge_count].v = vout;
+				tmpunderedges[under_edge_count].p = underplanescount;
+				tmpunderedges[under_edge_count].ea = -1;
+				coplanaredge = under_edge_count;
+				under_edge_count++;
+
+				if(vin!=-1) {
+					// we previously processed an edge  where we came under
+					// now we know about vout as well
+
+					// ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
+				}
+
+			}
+			else if(vertflag[edge0.v].planetest == COPLANAR && vertflag[edge1.v].planetest == OVER) {
+				// first is coplanar 2nd is over 
+				
+				edgeflag[e0].undermap = -1;
+				vout = vertflag[edge0.v].undermap;
+				// I hate this but i have to make sure part of this face is UNDER before ouputting this vert
+				int k=estart;
+				assert(edge0.p == currentplane);
+				while(!(planeside&UNDER) && k<convex.edges.count && convex.edges[k].p==edge0.p) {
+					planeside |= vertflag[convex.edges[k].v].planetest;
+					k++;
+				}
+				if(planeside&UNDER){
+					tmpunderedges[under_edge_count].v = vout;
+					tmpunderedges[under_edge_count].p = underplanescount;
+					tmpunderedges[under_edge_count].ea = -1;
+					coplanaredge = under_edge_count; // hmmm should make a note of the edge # for later on
+					under_edge_count++;
+					
+				}
+			}
+			else if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == UNDER) {
+				// first is over next is under 
+				// new vertex!!!
+				assert(vin==-1);
+				if(e0<edge0.ea) {
+					Plane &p0 = convex.facets[edge0.p];
+					Plane &pa = convex.facets[edgea.p];
+					createdverts.Add(ThreePlaneIntersection(p0,pa,slice));
+					//createdverts.Add(PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v]));
+					//createdverts.Add(PlaneProject(slice,PlaneLineIntersection(slice,convex.vertices[edge0.v],convex.vertices[edgea.v])));
+					vin = vertcountunder++;
+				}
+				else {
+					// find the new vertex that was created by edge[edge0.ea]
+					int nea = edgeflag[edge0.ea].undermap;
+					assert(tmpunderedges[nea].p==tmpunderedges[nea+1].p);
+					vin = tmpunderedges[nea+1].v;
+					assert(vin < vertcountunder);
+					assert(vin >= vertcountunderold);   // for debugging only
+				}
+				if(vout!=-1) {
+					// we previously processed an edge  where we went over
+					// now we know vin too
+					// ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
+				}
+				// output edge
+				tmpunderedges[under_edge_count].v = vin;
+				tmpunderedges[under_edge_count].p = underplanescount;
+				edgeflag[e0].undermap = under_edge_count;
+				if(e0>edge0.ea) {
+					assert(edgeflag[edge0.ea].undermap !=-1);
+					// connect the neighbors
+					tmpunderedges[under_edge_count].ea = edgeflag[edge0.ea].undermap;
+					tmpunderedges[edgeflag[edge0.ea].undermap].ea = under_edge_count;
+				}
+				assert(edgeflag[e0].undermap == under_edge_count);
+				under_edge_count++;
+			}
+			else if(vertflag[edge0.v].planetest == OVER && vertflag[edge1.v].planetest == COPLANAR) {
+				// first is over next is coplanar 
+				
+				edgeflag[e0].undermap = -1;
+				vin = vertflag[edge1.v].undermap;
+				assert(vin!=-1);
+				if(vout!=-1) {
+					// we previously processed an edge  where we came under
+					// now we know both endpoints
+					// ADD THIS EDGE TO THE LIST OF EDGES THAT NEED NEIGHBOR ON PARTITION PLANE!!
+				}
+
+			}
+			else {
+				assert(0);
+			}
+			
+
+			e0=e1;
+			e1++; // do the modulo at the beginning of the loop
+
+		} while(e0!=estart) ;
+		e0 = enextface;
+		if(planeside&UNDER) {
+			planeflag[currentplane].undermap = underplanescount;
+			tmpunderplanes[underplanescount] = convex.facets[currentplane];
+			underplanescount++;
+		}
+		else {
+			planeflag[currentplane].undermap = 0;
+		}
+		if(vout>=0 && (planeside&UNDER)) {
+			assert(vin>=0);
+			assert(coplanaredge>=0);
+			assert(coplanaredge!=511);
+			coplanaredges[coplanaredges_num].ea = coplanaredge;
+			coplanaredges[coplanaredges_num].v0 = vin;
+			coplanaredges[coplanaredges_num].v1 = vout;
+			coplanaredges_num++;
+		}
+	}
+
+	// add the new plane to the mix:
+	if(coplanaredges_num>0) {
+		tmpunderplanes[underplanescount++]=slice;
+	}
+	for(i=0;i<coplanaredges_num-1;i++) {
+		if(coplanaredges[i].v1 != coplanaredges[i+1].v0) {
+			int j = 0;
+			for(j=i+2;j<coplanaredges_num;j++) {
+				if(coplanaredges[i].v1 == coplanaredges[j].v0) {
+					Coplanar tmp = coplanaredges[i+1];
+					coplanaredges[i+1] = coplanaredges[j];
+					coplanaredges[j] = tmp;
+					break;
+				}
+			}
+			if(j>=coplanaredges_num)
+			{
+				assert(j<coplanaredges_num);
+				return NULL;
+			}
+		}
+	}
+	ConvexH *punder = new ConvexH(vertcountunder,under_edge_count+coplanaredges_num,underplanescount);
+	ConvexH &under = *punder;
+	int k=0;
+	for(i=0;i<convex.vertices.count;i++) {
+		if(vertflag[i].planetest != OVER){
+			under.vertices[k++] = convex.vertices[i];
+		}
+	}
+	i=0;
+	while(k<vertcountunder) {
+		under.vertices[k++] = createdverts[i++];
+	}
+	assert(i==createdverts.count);
+
+	for(i=0;i<coplanaredges_num;i++) {
+		under.edges[under_edge_count+i].p  = underplanescount-1;
+		under.edges[under_edge_count+i].ea = coplanaredges[i].ea;
+		tmpunderedges[coplanaredges[i].ea].ea = under_edge_count+i;
+		under.edges[under_edge_count+i].v  = coplanaredges[i].v0;
+	}
+	
+	memcpy(under.edges.element,tmpunderedges,sizeof(HalfEdge)*under_edge_count);
+	memcpy(under.facets.element,tmpunderplanes,sizeof(Plane)*underplanescount);
+	return punder;
+}
+
+
+
+static int candidateplane(Plane *planes,int planes_count,ConvexH *convex,float epsilon)
+{
+	int p = 0 ;
+	REAL md= 0 ;
+	int i;
+	for(i=0;i<planes_count;i++)
+	{
+		REAL d=0;
+		for(int j=0;j<convex->vertices.count;j++)
+		{
+			d = Max(d,dot(convex->vertices[j],planes[i].normal)+planes[i].dist);
+		}
+		if(i==0 || d>md)
+		{
+			p=i;
+			md=d;
+		}
+	}
+	return (md>epsilon)?p:-1;
+}
+
+template<class T>
+inline int maxdir(const T *p,int count,const T &dir)
+{
+	assert(count);
+	int m=0;
+	float currDotm = dot(p[0], dir);
+	for(int i=1;i<count;i++)
+	{
+		const float currDoti =  dot(p[i], dir);
+		if(currDoti > currDotm) 
+		{
+			currDotm = currDoti;
+			m=i;
+		}
+	}
+	return m;
+}
+
+
+template<class T>
+int maxdirfiltered(const T *p,int count,const T &dir,Array<int> &allow)
+{
+	assert(count);
+	int m=-1;
+	float currDotm = dot(p[0], dir);
+	for(int i=0;i<count;i++) 
+	{
+		if(allow[i])
+		{
+			if(m==-1 )
+			{
+				m=i;
+			}
+			else 
+			{
+				const float currDoti = dot(p[i], dir);
+				if (currDoti>currDotm)
+				{
+					currDotm = currDoti;
+					m=i;
+				}
+			}
+		}
+	}
+	assert(m!=-1);
+	return m;
+} 
+
+float3 orth(const float3 &v)
+{
+	float3 a=cross(v,float3(0,0,1));
+	float3 b=cross(v,float3(0,1,0));
+	return normalize((magnitude(a)>magnitude(b))?a:b);
+}
+
+
+template<class T>
+int maxdirsterid(const T *p,int count,const T &dir,Array<int> &allow)
+{
+	int m=-1;
+	while(m==-1)
+	{
+		m = maxdirfiltered(p,count,dir,allow);
+		if(allow[m]==3) return m;
+		T u = orth(dir);
+		T v = cross(u,dir);
+		int ma=-1;
+		for(float x = 0.0f ; x<= 360.0f ; x+= 45.0f)
+		{
+			float s = sinf(DEG2RAD*(x));
+			float c = cosf(DEG2RAD*(x));
+			int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow);
+			if(ma==m && mb==m)
+			{
+				allow[m]=3;
+				return m;
+			}
+			if(ma!=-1 && ma!=mb)  // Yuck - this is really ugly
+			{
+				int mc = ma;
+				for(float xx = x-40.0f ; xx <= x ; xx+= 5.0f)
+				{
+					float s = sinf(DEG2RAD*(xx));
+					float c = cosf(DEG2RAD*(xx));
+					int md = maxdirfiltered(p,count,dir+(u*s+v*c)*0.025f,allow);
+					if(mc==m && md==m)
+					{
+						allow[m]=3;
+						return m;
+					}
+					mc=md;
+				}
+			}
+			ma=mb;
+		}
+		allow[m]=0;
+		m=-1;
+	}
+	assert(0);
+	return m;
+} 
+
+
+
+
+int operator ==(const int3 &a,const int3 &b) 
+{
+	for(int i=0;i<3;i++) 
+	{
+		if(a[i]!=b[i]) return 0;
+	}
+	return 1;
+}
+
+int3 roll3(int3 a) 
+{
+	int tmp=a[0];
+	a[0]=a[1];
+	a[1]=a[2];
+	a[2]=tmp;
+	return a;
+}
+int isa(const int3 &a,const int3 &b) 
+{
+	return ( a==b || roll3(a)==b || a==roll3(b) );
+}
+int b2b(const int3 &a,const int3 &b) 
+{
+	return isa(a,int3(b[2],b[1],b[0]));
+}
+int above(float3* vertices,const int3& t, const float3 &p, float epsilon) 
+{
+	float3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]);
+	return (dot(n,p-vertices[t[0]]) > epsilon); // EPSILON???
+}
+int hasedge(const int3 &t, int a,int b)
+{
+	for(int i=0;i<3;i++)
+	{
+		int i1= (i+1)%3;
+		if(t[i]==a && t[i1]==b) return 1;
+	}
+	return 0;
+}
+int hasvert(const int3 &t, int v)
+{
+	return (t[0]==v || t[1]==v || t[2]==v) ;
+}
+int shareedge(const int3 &a,const int3 &b)
+{
+	int i;
+	for(i=0;i<3;i++)
+	{
+		int i1= (i+1)%3;
+		if(hasedge(a,b[i1],b[i])) return 1;
+	}
+	return 0;
+}
+
+class btHullTriangle;
+
+Array<btHullTriangle*> tris;
+
+class btHullTriangle : public int3
+{
+public:
+	int3 n;
+	int id;
+	int vmax;
+	float rise;
+	btHullTriangle(int a,int b,int c):int3(a,b,c),n(-1,-1,-1)
+	{
+		id = tris.count;
+		tris.Add(this);
+		vmax=-1;
+		rise = 0.0f;
+	}
+	~btHullTriangle()
+	{
+		assert(tris[id]==this);
+		tris[id]=NULL;
+	}
+	int &neib(int a,int b);
+};
+
+
+int &btHullTriangle::neib(int a,int b)
+{
+	static int er=-1;
+	int i;
+	for(i=0;i<3;i++) 
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		if((*this)[i]==a && (*this)[i1]==b) return n[i2];
+		if((*this)[i]==b && (*this)[i1]==a) return n[i2];
+	}
+	assert(0);
+	return er;
+}
+void b2bfix(btHullTriangle* s,btHullTriangle*t)
+{
+	int i;
+	for(i=0;i<3;i++) 
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		int a = (*s)[i1];
+		int b = (*s)[i2];
+		assert(tris[s->neib(a,b)]->neib(b,a) == s->id);
+		assert(tris[t->neib(a,b)]->neib(b,a) == t->id);
+		tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a);
+		tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b);
+	}
+}
+
+void removeb2b(btHullTriangle* s,btHullTriangle*t)
+{
+	b2bfix(s,t);
+	delete s;
+	delete t;
+}
+
+void checkit(btHullTriangle *t)
+{
+	int i;
+	assert(tris[t->id]==t);
+	for(i=0;i<3;i++)
+	{
+		int i1=(i+1)%3;
+		int i2=(i+2)%3;
+		int a = (*t)[i1];
+		int b = (*t)[i2];
+		assert(a!=b);
+		assert( tris[t->n[i]]->neib(b,a) == t->id);
+	}
+}
+void extrude(btHullTriangle *t0,int v)
+{
+	int3 t= *t0;
+	int n = tris.count;
+	btHullTriangle* ta = new btHullTriangle(v,t[1],t[2]);
+	ta->n = int3(t0->n[0],n+1,n+2);
+	tris[t0->n[0]]->neib(t[1],t[2]) = n+0;
+	btHullTriangle* tb = new btHullTriangle(v,t[2],t[0]);
+	tb->n = int3(t0->n[1],n+2,n+0);
+	tris[t0->n[1]]->neib(t[2],t[0]) = n+1;
+	btHullTriangle* tc = new btHullTriangle(v,t[0],t[1]);
+	tc->n = int3(t0->n[2],n+0,n+1);
+	tris[t0->n[2]]->neib(t[0],t[1]) = n+2;
+	checkit(ta);
+	checkit(tb);
+	checkit(tc);
+	if(hasvert(*tris[ta->n[0]],v)) removeb2b(ta,tris[ta->n[0]]);
+	if(hasvert(*tris[tb->n[0]],v)) removeb2b(tb,tris[tb->n[0]]);
+	if(hasvert(*tris[tc->n[0]],v)) removeb2b(tc,tris[tc->n[0]]);
+	delete t0;
+
+}
+
+btHullTriangle *extrudable(float epsilon)
+{
+	int i;
+	btHullTriangle *t=NULL;
+	for(i=0;i<tris.count;i++)
+	{
+		if(!t || (tris[i] && t->rise<tris[i]->rise))
+		{
+			t = tris[i];
+		}
+	}
+	return (t->rise >epsilon)?t:NULL ;
+}
+
+class int4
+{
+public:
+	int x,y,z,w;
+	int4(){};
+	int4(int _x,int _y, int _z,int _w){x=_x;y=_y;z=_z;w=_w;}
+	const int& operator[](int i) const {return (&x)[i];}
+	int& operator[](int i) {return (&x)[i];}
+};
+
+
+
+int4 FindSimplex(float3 *verts,int verts_count,Array<int> &allow)
+{
+	float3 basis[3];
+	basis[0] = float3( 0.01f, 0.02f, 1.0f );      
+	int p0 = maxdirsterid(verts,verts_count, basis[0],allow);   
+	int	p1 = maxdirsterid(verts,verts_count,-basis[0],allow);
+	basis[0] = verts[p0]-verts[p1];
+	if(p0==p1 || basis[0]==float3(0,0,0)) 
+		return int4(-1,-1,-1,-1);
+	basis[1] = cross(float3(     1, 0.02f, 0),basis[0]);
+	basis[2] = cross(float3(-0.02f,     1, 0),basis[0]);
+	basis[1] = normalize( (magnitude(basis[1])>magnitude(basis[2])) ? basis[1]:basis[2]);
+	int p2 = maxdirsterid(verts,verts_count,basis[1],allow);
+	if(p2 == p0 || p2 == p1)
+	{
+		p2 = maxdirsterid(verts,verts_count,-basis[1],allow);
+	}
+	if(p2 == p0 || p2 == p1) 
+		return int4(-1,-1,-1,-1);
+	basis[1] = verts[p2] - verts[p0];
+	basis[2] = normalize(cross(basis[1],basis[0]));
+	int p3 = maxdirsterid(verts,verts_count,basis[2],allow);
+	if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow);
+	if(p3==p0||p3==p1||p3==p2) 
+		return int4(-1,-1,-1,-1);
+	assert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3));
+	if(dot(verts[p3]-verts[p0],cross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);}
+	return int4(p0,p1,p2,p3);
+}
+
+int calchullgen(float3 *verts,int verts_count, int vlimit)
+{
+	if(verts_count <4) return 0;
+	if(vlimit==0) vlimit=1000000000;
+	int j;
+	float3 bmin(*verts),bmax(*verts);
+	Array<int> isextreme(verts_count);
+	Array<int> allow(verts_count);
+	for(j=0;j<verts_count;j++) 
+	{
+		allow.Add(1);
+		isextreme.Add(0);
+		bmin = VectorMin(bmin,verts[j]);
+		bmax = VectorMax(bmax,verts[j]);
+	}
+	float epsilon = magnitude(bmax-bmin) * 0.001f;
+
+
+	int4 p = FindSimplex(verts,verts_count,allow);
+	if(p.x==-1) return 0; // simplex failed
+
+
+
+	float3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) /4.0f;  // a valid interior point
+	btHullTriangle *t0 = new btHullTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1);
+	btHullTriangle *t1 = new btHullTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0);
+	btHullTriangle *t2 = new btHullTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3);
+	btHullTriangle *t3 = new btHullTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2);
+	isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
+	checkit(t0);checkit(t1);checkit(t2);checkit(t3);
+
+	for(j=0;j<tris.count;j++)
+	{
+		btHullTriangle *t=tris[j];
+		assert(t);
+		assert(t->vmax<0);
+		float3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+		t->vmax = maxdirsterid(verts,verts_count,n,allow);
+		t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
+	}
+	btHullTriangle *te;
+	vlimit-=4;
+	while(vlimit >0 && (te=extrudable(epsilon)))
+	{
+		int3 ti=*te;
+		int v=te->vmax;
+		assert(!isextreme[v]);  // wtf we've already done this vertex
+		isextreme[v]=1;
+		//if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
+		j=tris.count;
+		while(j--) {
+			if(!tris[j]) continue;
+			int3 t=*tris[j];
+			if(above(verts,t,verts[v],0.01f*epsilon)) 
+			{
+				extrude(tris[j],v);
+			}
+		}
+		// now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
+		j=tris.count;
+		while(j--)
+		{
+			if(!tris[j]) continue;
+			if(!hasvert(*tris[j],v)) break;
+			int3 nt=*tris[j];
+			if(above(verts,nt,center,0.01f*epsilon)  || magnitude(cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]))< epsilon*epsilon*0.1f )
+			{
+				btHullTriangle *nb = tris[tris[j]->n[0]];
+				assert(nb);assert(!hasvert(*nb,v));assert(nb->id<j);
+				extrude(nb,v);
+				j=tris.count; 
+			}
+		} 
+		j=tris.count;
+		while(j--)
+		{
+			btHullTriangle *t=tris[j];
+			if(!t) continue;
+			if(t->vmax>=0) break;
+			float3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+			t->vmax = maxdirsterid(verts,verts_count,n,allow);
+			if(isextreme[t->vmax]) 
+			{
+				t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
+			}
+			else
+			{
+				t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
+			}
+		}
+		vlimit --;
+	}
+	return 1;
+}
+
+int calchull(float3 *verts,int verts_count, int *&tris_out, int &tris_count,int vlimit) 
+{
+	int rc=calchullgen(verts,verts_count,  vlimit) ;
+	if(!rc) return 0;
+	Array<int> ts;
+	for(int i=0;i<tris.count;i++)if(tris[i])
+	{
+		for(int j=0;j<3;j++)ts.Add((*tris[i])[j]);
+		delete tris[i];
+	}
+	tris_count = ts.count/3;
+	tris_out   = ts.element;
+	ts.element=NULL; ts.count=ts.array_size=0;
+	tris.count=0;
+	return 1;
+}
+
+int calchullpbev(float3 *verts,int verts_count,int vlimit, Array<Plane> &planes,float bevangle) 
+{
+	int i,j;
+	planes.count=0;
+	int rc = calchullgen(verts,verts_count,vlimit);
+	if(!rc) return 0;
+	for(i=0;i<tris.count;i++)if(tris[i])
+	{
+		Plane p;
+		btHullTriangle *t = tris[i];
+		p.normal = TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
+		p.dist   = -dot(p.normal, verts[(*t)[0]]);
+		planes.Add(p);
+		for(j=0;j<3;j++)
+		{
+			if(t->n[j]<t->id) continue;
+			btHullTriangle *s = tris[t->n[j]];
+			REAL3 snormal = TriNormal(verts[(*s)[0]],verts[(*s)[1]],verts[(*s)[2]]);
+			if(dot(snormal,p.normal)>=cos(bevangle*DEG2RAD)) continue;
+			REAL3 n = normalize(snormal+p.normal);
+			planes.Add(Plane(n,-dot(n,verts[maxdir(verts,verts_count,n)])));
+		}
+	}
+
+	for(i=0;i<tris.count;i++)if(tris[i])
+	{
+		delete tris[i]; // delete tris[i];
+	}
+	tris.count=0;
+	return 1;
+}
+
+int overhull(Plane *planes,int planes_count,float3 *verts, int verts_count,int maxplanes, 
+			 float3 *&verts_out, int &verts_count_out,  int *&faces_out, int &faces_count_out ,float inflate)
+{
+	int i,j;
+	if(verts_count <4) return 0;
+	maxplanes = Min(maxplanes,planes_count);
+	float3 bmin(verts[0]),bmax(verts[0]);
+	for(i=0;i<verts_count;i++) 
+	{
+		bmin = VectorMin(bmin,verts[i]);
+		bmax = VectorMax(bmax,verts[i]);
+	}
+//	float diameter = magnitude(bmax-bmin);
+//	inflate *=diameter;   // RELATIVE INFLATION
+	bmin -= float3(inflate,inflate,inflate);
+	bmax += float3(inflate,inflate,inflate);
+	for(i=0;i<planes_count;i++)
+	{
+		planes[i].dist -= inflate;
+	}
+	float3 emin = bmin; // VectorMin(bmin,float3(0,0,0));
+	float3 emax = bmax; // VectorMax(bmax,float3(0,0,0));
+	float epsilon  = magnitude(emax-emin) * 0.025f;
+	planetestepsilon = magnitude(emax-emin) * PAPERWIDTH;
+	// todo: add bounding cube planes to force bevel. or try instead not adding the diameter expansion ??? must think.
+	// ConvexH *convex = ConvexHMakeCube(bmin - float3(diameter,diameter,diameter),bmax+float3(diameter,diameter,diameter));
+	ConvexH *c = ConvexHMakeCube(REAL3(bmin),REAL3(bmax)); 
+	int k;
+	while(maxplanes-- && (k=candidateplane(planes,planes_count,c,epsilon))>=0)
+	{
+		ConvexH *tmp = c;
+		c = ConvexHCrop(*tmp,planes[k]);
+		if(c==NULL) {c=tmp; break;} // might want to debug this case better!!!
+		if(!AssertIntact(*c)) {c=tmp; break;} // might want to debug this case better too!!!
+		delete tmp;
+	}
+
+	assert(AssertIntact(*c));
+	//return c;
+	faces_out = (int*)malloc(sizeof(int)*(1+c->facets.count+c->edges.count));     // new int[1+c->facets.count+c->edges.count];
+	faces_count_out=0;
+	i=0;
+	faces_out[faces_count_out++]=-1;
+	k=0;
+	while(i<c->edges.count)
+	{
+		j=1;
+		while(j+i<c->edges.count && c->edges[i].p==c->edges[i+j].p) { j++; }
+		faces_out[faces_count_out++]=j;
+		while(j--)
+		{
+			faces_out[faces_count_out++] = c->edges[i].v;
+			i++;
+		}
+		k++;
+	}
+	faces_out[0]=k; // number of faces.
+	assert(k==c->facets.count);
+	assert(faces_count_out == 1+c->facets.count+c->edges.count);
+	verts_out = c->vertices.element; // new float3[c->vertices.count]; 
+	verts_count_out = c->vertices.count;
+	for(i=0;i<c->vertices.count;i++)
+	{
+		verts_out[i] = float3(c->vertices[i]);
+	}
+	c->vertices.count=c->vertices.array_size=0;	c->vertices.element=NULL;
+	delete c;
+	return 1;
+}
+
+int overhullv(float3 *verts, int verts_count,int maxplanes, 
+			 float3 *&verts_out, int &verts_count_out,  int *&faces_out, int &faces_count_out ,float inflate,float bevangle,int vlimit)
+{
+	if(!verts_count) return 0;
+	extern int calchullpbev(float3 *verts,int verts_count,int vlimit, Array<Plane> &planes,float bevangle) ;
+	Array<Plane> planes;
+	int rc=calchullpbev(verts,verts_count,vlimit,planes,bevangle) ;
+	if(!rc) return 0;
+	return overhull(planes.element,planes.count,verts,verts_count,maxplanes,verts_out,verts_count_out,faces_out,faces_count_out,inflate);
+}
+
+
+bool ComputeHull(unsigned int vcount,const float *vertices,PHullResult &result,unsigned int vlimit,float inflate)
+{
+
+	int index_count;
+	int *faces;
+	float3 *verts_out;
+	int     verts_count_out;
+
+	if(inflate==0.0f)
+	{
+		int  *tris_out;
+		int    tris_count;
+		int ret = calchull( (float3 *) vertices, (int) vcount, tris_out, tris_count, vlimit );
+		if(!ret) return false;
+		result.mIndexCount = (unsigned int) (tris_count*3);
+		result.mFaceCount  = (unsigned int) tris_count;
+		result.mVertices   = (float*) vertices;
+		result.mVcount     = (unsigned int) vcount;
+		result.mIndices    = (unsigned int *) tris_out;
+		return true;
+	}
+
+	int ret = overhullv((float3*)vertices,vcount,35,verts_out,verts_count_out,faces,index_count,inflate,120.0f,vlimit);
+	if(!ret) return false;
+
+	Array<int3> tris;
+	int n=faces[0];
+	int k=1;
+	for(int i=0;i<n;i++)
+	{
+		int pn = faces[k++];
+		for(int j=2;j<pn;j++) tris.Add(int3(faces[k],faces[k+j-1],faces[k+j]));
+		k+=pn;
+	}
+	assert(tris.count == index_count-1-(n*3));
+
+	result.mIndexCount = (unsigned int) (tris.count*3);
+	result.mFaceCount  = (unsigned int) tris.count;
+	result.mVertices   = (float*) verts_out;
+	result.mVcount     = (unsigned int) verts_count_out;
+	result.mIndices    = (unsigned int *) tris.element;
+	tris.element=NULL; tris.count = tris.array_size=0;
+
+	return true;
+}
+
+
+void ReleaseHull(PHullResult &result)
+{
+	if ( result.mIndices )
+  {
+	  free(result.mIndices);
+	}
+
+	result.mVcount = 0;
+	result.mIndexCount = 0;
+	result.mIndices = 0;
+	result.mVertices = 0;
+	result.mIndices  = 0;
+}
+
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib header
+//*********************************************************************
+//*********************************************************************
+
+//*********************************************************************
+//*********************************************************************
+//********  HullLib implementation
+//*********************************************************************
+//*********************************************************************
+
+HullError HullLibrary::CreateConvexHull(const HullDesc       &desc,           // describes the input request
+																					HullResult           &result)         // contains the resulst
+{
+	HullError ret = QE_FAIL;
+
+
+	PHullResult hr;
+
+	unsigned int vcount = desc.mVcount;
+	if ( vcount < 8 ) vcount = 8;
+
+	float *vsource  = (float *) malloc( sizeof(float)*vcount*3);
+
+
+	float scale[3];
+
+	unsigned int ovcount;
+
+	bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, vsource, desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates!
+
+	if ( ok )
+	{
+
+
+		if ( 1 ) // scale vertices back to their original size.
+		{
+			for (unsigned int i=0; i<ovcount; i++)
+			{
+				float *v = &vsource[i*3];
+				v[0]*=scale[0];
+				v[1]*=scale[1];
+				v[2]*=scale[2];
+			}
+		}
+
+		float skinwidth = 0;
+		if ( desc.HasHullFlag(QF_SKIN_WIDTH) )
+			skinwidth = desc.mSkinWidth;
+
+		ok = ComputeHull(ovcount,vsource,hr,desc.mMaxVertices,skinwidth);
+
+		if ( ok )
+		{
+
+			// re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table.
+			float *vscratch = (float *) malloc( sizeof(float)*hr.mVcount*3);
+			BringOutYourDead(hr.mVertices,hr.mVcount, vscratch, ovcount, hr.mIndices, hr.mIndexCount );
+
+			ret = QE_OK;
+
+			if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle!
+			{
+				result.mPolygons          = false;
+				result.mNumOutputVertices = ovcount;
+				result.mOutputVertices    = (float *)malloc( sizeof(float)*ovcount*3);
+				result.mNumFaces          = hr.mFaceCount;
+				result.mNumIndices        = hr.mIndexCount;
+
+				result.mIndices           = (unsigned int *) malloc( sizeof(unsigned int)*hr.mIndexCount);
+
+				memcpy(result.mOutputVertices, vscratch, sizeof(float)*3*ovcount );
+
+  			if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+				{
+
+					const unsigned int *source = hr.mIndices;
+								unsigned int *dest   = result.mIndices;
+
+					for (unsigned int i=0; i<hr.mFaceCount; i++)
+					{
+						dest[0] = source[2];
+						dest[1] = source[1];
+						dest[2] = source[0];
+						dest+=3;
+						source+=3;
+					}
+
+				}
+				else
+				{
+					memcpy(result.mIndices, hr.mIndices, sizeof(unsigned int)*hr.mIndexCount);
+				}
+			}
+			else
+			{
+				result.mPolygons          = true;
+				result.mNumOutputVertices = ovcount;
+				result.mOutputVertices    = (float *)malloc( sizeof(float)*ovcount*3);
+				result.mNumFaces          = hr.mFaceCount;
+				result.mNumIndices        = hr.mIndexCount+hr.mFaceCount;
+				result.mIndices           = (unsigned int *) malloc( sizeof(unsigned int)*result.mNumIndices);
+				memcpy(result.mOutputVertices, vscratch, sizeof(float)*3*ovcount );
+
+				if ( 1 )
+				{
+					const unsigned int *source = hr.mIndices;
+								unsigned int *dest   = result.mIndices;
+					for (unsigned int i=0; i<hr.mFaceCount; i++)
+					{
+						dest[0] = 3;
+						if ( desc.HasHullFlag(QF_REVERSE_ORDER) )
+						{
+							dest[1] = source[2];
+							dest[2] = source[1];
+							dest[3] = source[0];
+						}
+						else
+						{
+							dest[1] = source[0];
+							dest[2] = source[1];
+							dest[3] = source[2];
+						}
+
+						dest+=4;
+						source+=3;
+					}
+				}
+			}
+			ReleaseHull(hr);
+			if ( vscratch )
+			{
+				free(vscratch);
+			}
+		}
+	}
+
+	if ( vsource )
+	{
+		free(vsource);
+	}
+
+
+	return ret;
+}
+
+
+
+HullError HullLibrary::ReleaseResult(HullResult &result) // release memory allocated for this result, we are done with it.
+{
+	if ( result.mOutputVertices )
+	{
+		free(result.mOutputVertices);
+		result.mOutputVertices = 0;
+	}
+	if ( result.mIndices )
+	{
+		free(result.mIndices);
+		result.mIndices = 0;
+	}
+	return QE_OK;
+}
+
+
+static void addPoint(unsigned int &vcount,float *p,float x,float y,float z)
+{
+	float *dest = &p[vcount*3];
+	dest[0] = x;
+	dest[1] = y;
+	dest[2] = z;
+	vcount++;
+}
+
+
+float GetDist(float px,float py,float pz,const float *p2)
+{
+
+	float dx = px - p2[0];
+	float dy = py - p2[1];
+	float dz = pz - p2[2];
+
+	return dx*dx+dy*dy+dz*dz;
+}
+
+
+
+bool  HullLibrary::CleanupVertices(unsigned int svcount,
+																const float *svertices,
+																unsigned int stride,
+																unsigned int &vcount,       // output number of vertices
+																float *vertices,                 // location to store the results.
+																float  normalepsilon,
+																float *scale)
+{
+	if ( svcount == 0 ) return false;
+
+
+#define EPSILON 0.000001f /* close enough to consider two floating point numbers to be 'the same'. */
+
+	vcount = 0;
+
+	float recip[3];
+
+	if ( scale )
+	{
+		scale[0] = 1;
+		scale[1] = 1;
+		scale[2] = 1;
+	}
+
+	float bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
+	float bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+	const char *vtx = (const char *) svertices;
+
+	if ( 1 )
+	{
+		for (unsigned int i=0; i<svcount; i++)
+		{
+			const float *p = (const float *) vtx;
+
+			vtx+=stride;
+
+			for (int j=0; j<3; j++)
+			{
+				if ( p[j] < bmin[j] ) bmin[j] = p[j];
+				if ( p[j] > bmax[j] ) bmax[j] = p[j];
+			}
+		}
+	}
+
+	float dx = bmax[0] - bmin[0];
+	float dy = bmax[1] - bmin[1];
+	float dz = bmax[2] - bmin[2];
+
+	float center[3];
+
+	center[0] = dx*0.5f + bmin[0];
+	center[1] = dy*0.5f + bmin[1];
+	center[2] = dz*0.5f + bmin[2];
+
+	if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 )
+	{
+
+		float len = FLT_MAX;
+
+		if ( dx > EPSILON && dx < len ) len = dx;
+		if ( dy > EPSILON && dy < len ) len = dy;
+		if ( dz > EPSILON && dz < len ) len = dz;
+
+		if ( len == FLT_MAX )
+		{
+			dx = dy = dz = 0.01f; // one centimeter
+		}
+		else
+		{
+			if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge.
+			if ( dy < EPSILON ) dy = len * 0.05f;
+			if ( dz < EPSILON ) dz = len * 0.05f;
+		}
+
+		float x1 = center[0] - dx;
+		float x2 = center[0] + dx;
+
+		float y1 = center[1] - dy;
+		float y2 = center[1] + dy;
+
+		float z1 = center[2] - dz;
+		float z2 = center[2] + dz;
+
+		addPoint(vcount,vertices,x1,y1,z1);
+		addPoint(vcount,vertices,x2,y1,z1);
+		addPoint(vcount,vertices,x2,y2,z1);
+		addPoint(vcount,vertices,x1,y2,z1);
+		addPoint(vcount,vertices,x1,y1,z2);
+		addPoint(vcount,vertices,x2,y1,z2);
+		addPoint(vcount,vertices,x2,y2,z2);
+		addPoint(vcount,vertices,x1,y2,z2);
+
+		return true; // return cube
+
+
+	}
+	else
+	{
+		if ( scale )
+		{
+			scale[0] = dx;
+			scale[1] = dy;
+			scale[2] = dz;
+
+			recip[0] = 1 / dx;
+			recip[1] = 1 / dy;
+			recip[2] = 1 / dz;
+
+			center[0]*=recip[0];
+			center[1]*=recip[1];
+			center[2]*=recip[2];
+
+		}
+
+	}
+
+
+
+	vtx = (const char *) svertices;
+
+	for (unsigned int i=0; i<svcount; i++)
+	{
+
+		const float *p = (const float *)vtx;
+		vtx+=stride;
+
+		float px = p[0];
+		float py = p[1];
+		float pz = p[2];
+
+		if ( scale )
+		{
+			px = px*recip[0]; // normalize
+			py = py*recip[1]; // normalize
+			pz = pz*recip[2]; // normalize
+		}
+
+		if ( 1 )
+		{
+			unsigned int j;
+
+			for (j=0; j<vcount; j++)
+			{
+				float *v = &vertices[j*3];
+
+				float x = v[0];
+				float y = v[1];
+				float z = v[2];
+
+				float dx = fabsf(x - px );
+				float dy = fabsf(y - py );
+				float dz = fabsf(z - pz );
+
+				if ( dx < normalepsilon && dy < normalepsilon && dz < normalepsilon )
+				{
+					// ok, it is close enough to the old one
+					// now let us see if it is further from the center of the point cloud than the one we already recorded.
+					// in which case we keep this one instead.
+
+					float dist1 = GetDist(px,py,pz,center);
+					float dist2 = GetDist(v[0],v[1],v[2],center);
+
+					if ( dist1 > dist2 )
+					{
+						v[0] = px;
+						v[1] = py;
+						v[2] = pz;
+					}
+
+					break;
+				}
+			}
+
+			if ( j == vcount )
+			{
+				float *dest = &vertices[vcount*3];
+				dest[0] = px;
+				dest[1] = py;
+				dest[2] = pz;
+				vcount++;
+			}
+		}
+	}
+
+	// ok..now make sure we didn't prune so many vertices it is now invalid.
+	if ( 1 )
+	{
+		float bmin[3] = {  FLT_MAX,  FLT_MAX,  FLT_MAX };
+		float bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX };
+
+		for (unsigned int i=0; i<vcount; i++)
+		{
+			const float *p = &vertices[i*3];
+			for (int j=0; j<3; j++)
+			{
+				if ( p[j] < bmin[j] ) bmin[j] = p[j];
+				if ( p[j] > bmax[j] ) bmax[j] = p[j];
+			}
+		}
+
+		float dx = bmax[0] - bmin[0];
+		float dy = bmax[1] - bmin[1];
+		float dz = bmax[2] - bmin[2];
+
+		if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3)
+		{
+			float cx = dx*0.5f + bmin[0];
+			float cy = dy*0.5f + bmin[1];
+			float cz = dz*0.5f + bmin[2];
+
+			float len = FLT_MAX;
+
+			if ( dx >= EPSILON && dx < len ) len = dx;
+			if ( dy >= EPSILON && dy < len ) len = dy;
+			if ( dz >= EPSILON && dz < len ) len = dz;
+
+			if ( len == FLT_MAX )
+			{
+				dx = dy = dz = 0.01f; // one centimeter
+			}
+			else
+			{
+				if ( dx < EPSILON ) dx = len * 0.05f; // 1/5th the shortest non-zero edge.
+				if ( dy < EPSILON ) dy = len * 0.05f;
+				if ( dz < EPSILON ) dz = len * 0.05f;
+			}
+
+			float x1 = cx - dx;
+			float x2 = cx + dx;
+
+			float y1 = cy - dy;
+			float y2 = cy + dy;
+
+			float z1 = cz - dz;
+			float z2 = cz + dz;
+
+			vcount = 0; // add box
+
+			addPoint(vcount,vertices,x1,y1,z1);
+			addPoint(vcount,vertices,x2,y1,z1);
+			addPoint(vcount,vertices,x2,y2,z1);
+			addPoint(vcount,vertices,x1,y2,z1);
+			addPoint(vcount,vertices,x1,y1,z2);
+			addPoint(vcount,vertices,x2,y1,z2);
+			addPoint(vcount,vertices,x2,y2,z2);
+			addPoint(vcount,vertices,x1,y2,z2);
+
+			return true;
+		}
+	}
+
+	return true;
+}
+
+void HullLibrary::BringOutYourDead(const float *verts,unsigned int vcount, float *overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount)
+{
+	unsigned int *used = (unsigned int *)malloc(sizeof(unsigned int)*vcount);
+	memset(used,0,sizeof(unsigned int)*vcount);
+
+	ocount = 0;
+
+	for (unsigned int i=0; i<indexcount; i++)
+	{
+		unsigned int v = indices[i]; // original array index
+
+		assert( v >= 0 && v < vcount );
+
+		if ( used[v] ) // if already remapped
+		{
+			indices[i] = used[v]-1; // index to new array
+		}
+		else
+		{
+
+			indices[i] = ocount;      // new index mapping
+
+			overts[ocount*3+0] = verts[v*3+0]; // copy old vert to new vert array
+			overts[ocount*3+1] = verts[v*3+1];
+			overts[ocount*3+2] = verts[v*3+2];
+
+			ocount++; // increment output vert count
+
+			assert( ocount >=0 && ocount <= vcount );
+
+			used[v] = ocount; // assign new index remapping
+		}
+	}
+
+	free(used);
+}
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_hull.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_hull.h
new file mode 100644
index 0000000..420e241
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_hull.h
@@ -0,0 +1,153 @@
+#ifndef CD_HULL_H
+
+#define CD_HULL_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+namespace ConvexDecomposition
+{
+
+class HullResult
+{
+public:
+	HullResult(void)
+	{
+		mPolygons = true;
+		mNumOutputVertices = 0;
+		mOutputVertices = 0;
+		mNumFaces = 0;
+		mNumIndices = 0;
+		mIndices = 0;
+	}
+	bool                    mPolygons;                  // true if indices represents polygons, false indices are triangles
+	unsigned int            mNumOutputVertices;         // number of vertices in the output hull
+	float                  *mOutputVertices;            // array of vertices, 3 floats each x,y,z
+	unsigned int            mNumFaces;                  // the number of faces produced
+	unsigned int            mNumIndices;                // the total number of indices
+	unsigned int           *mIndices;                   // pointer to indices.
+
+// If triangles, then indices are array indexes into the vertex list.
+// If polygons, indices are in the form (number of points in face) (p1, p2, p3, ..) etc..
+};
+
+enum HullFlag
+{
+	QF_TRIANGLES         = (1<<0),             // report results as triangles, not polygons.
+	QF_REVERSE_ORDER     = (1<<1),             // reverse order of the triangle indices.
+	QF_SKIN_WIDTH        = (1<<2),             // extrude hull based on this skin width
+	QF_DEFAULT           = 0
+};
+
+
+class HullDesc
+{
+public:
+	HullDesc(void)
+	{
+		mFlags          = QF_DEFAULT;
+		mVcount         = 0;
+		mVertices       = 0;
+		mVertexStride   = sizeof(float)*3;
+		mNormalEpsilon  = 0.001f;
+		mMaxVertices		= 4096; // maximum number of points to be considered for a convex hull.
+		mMaxFaces				= 4096;
+		mSkinWidth			= 0.01f; // default is one centimeter
+	};
+
+	HullDesc(HullFlag flag,
+					 unsigned int vcount,
+					 const float *vertices,
+					 unsigned int stride)
+	{
+		mFlags          = flag;
+		mVcount         = vcount;
+		mVertices       = vertices;
+		mVertexStride   = stride;
+		mNormalEpsilon  = 0.001f;
+		mMaxVertices    = 4096;
+		mSkinWidth = 0.01f; // default is one centimeter
+	}
+
+	bool HasHullFlag(HullFlag flag) const
+	{
+		if ( mFlags & flag ) return true;
+		return false;
+	}
+
+	void SetHullFlag(HullFlag flag)
+	{
+		mFlags|=flag;
+	}
+
+	void ClearHullFlag(HullFlag flag)
+	{
+		mFlags&=~flag;
+	}
+
+	unsigned int      mFlags;           // flags to use when generating the convex hull.
+	unsigned int      mVcount;          // number of vertices in the input point cloud
+	const float      *mVertices;        // the array of vertices.
+	unsigned int      mVertexStride;    // the stride of each vertex, in bytes.
+	float             mNormalEpsilon;   // the epsilon for removing duplicates.  This is a normalized value, if normalized bit is on.
+	float             mSkinWidth;
+	unsigned int      mMaxVertices;               // maximum number of vertices to be considered for the hull!
+	unsigned int      mMaxFaces;
+};
+
+enum HullError
+{
+	QE_OK,            // success!
+	QE_FAIL           // failed.
+};
+
+class HullLibrary
+{
+public:
+
+	HullError CreateConvexHull(const HullDesc       &desc,           // describes the input request
+															HullResult           &result);        // contains the resulst
+
+	HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it.
+
+private:
+
+	void BringOutYourDead(const float *verts,unsigned int vcount, float *overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount);
+
+	bool    CleanupVertices(unsigned int svcount,
+													const float *svertices,
+													unsigned int stride,
+													unsigned int &vcount,       // output number of vertices
+													float *vertices,                 // location to store the results.
+													float  normalepsilon,
+													float *scale);
+};
+
+}
+
+#endif
+
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_vector.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_vector.h
new file mode 100644
index 0000000..382ba75
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_vector.h
@@ -0,0 +1,1185 @@
+#ifndef CD_VECTOR_H
+
+#define CD_VECTOR_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+#pragma warning(disable:4786)
+
+#include <math.h>
+#include <float.h>
+#include <vector>
+
+namespace ConvexDecomposition
+{
+
+
+const float DEG_TO_RAD = ((2.0f * 3.14152654f) / 360.0f);
+const float RAD_TO_DEG = (360.0f / (2.0f * 3.141592654f));
+
+class Vector3d
+{
+public:
+	Vector3d(void) { };  // null constructor, does not inialize point.
+
+	Vector3d(const Vector3d &a) // constructor copies existing vector.
+	{
+		x = a.x;
+		y = a.y;
+		z = a.z;
+	};
+
+	Vector3d(float a,float b,float c) // construct with initial point.
+	{
+		x = a;
+		y = b;
+		z = c;
+	};
+
+	Vector3d(const float *t)
+	{
+		x = t[0];
+		y = t[1];
+		z = t[2];
+	};
+
+	Vector3d(const int *t)
+	{
+		x = t[0];
+		y = t[1];
+		z = t[2];
+	};
+
+	bool operator==(const Vector3d &a) const
+	{
+		return( a.x == x && a.y == y && a.z == z );
+	};
+
+	bool operator!=(const Vector3d &a) const
+	{
+		return( a.x != x || a.y != y || a.z != z );
+	};
+
+// Operators
+		Vector3d& operator = (const Vector3d& A)          // ASSIGNMENT (=)
+			{ x=A.x; y=A.y; z=A.z;
+				return(*this);  };
+
+		Vector3d operator + (const Vector3d& A) const     // ADDITION (+)
+			{ Vector3d Sum(x+A.x, y+A.y, z+A.z);
+				return(Sum); };
+
+		Vector3d operator - (const Vector3d& A) const     // SUBTRACTION (-)
+			{ Vector3d Diff(x-A.x, y-A.y, z-A.z);
+				return(Diff); };
+
+		Vector3d operator * (const float s) const       // MULTIPLY BY SCALAR (*)
+			{ Vector3d Scaled(x*s, y*s, z*s);
+				return(Scaled); };
+
+
+		Vector3d operator + (const float s) const       // ADD CONSTANT TO ALL 3 COMPONENTS (*)
+			{ Vector3d Scaled(x+s, y+s, z+s);
+				return(Scaled); };
+
+
+
+
+		Vector3d operator / (const float s) const       // DIVIDE BY SCALAR (/)
+		{
+			float r = 1.0f / s;
+				Vector3d Scaled(x*r, y*r, z*r);
+				return(Scaled);
+		};
+
+		void operator /= (float A)             // ACCUMULATED VECTOR ADDITION (/=)
+			{ x/=A; y/=A; z/=A; };
+
+		void operator += (const Vector3d A)             // ACCUMULATED VECTOR ADDITION (+=)
+			{ x+=A.x; y+=A.y; z+=A.z; };
+		void operator -= (const Vector3d A)             // ACCUMULATED VECTOR SUBTRACTION (+=)
+			{ x-=A.x; y-=A.y; z-=A.z; };
+		void operator *= (const float s)        // ACCUMULATED SCALAR MULTIPLICATION (*=) (bpc 4/24/2000)
+			{x*=s; y*=s; z*=s;}
+
+		void operator += (const float A)             // ACCUMULATED VECTOR ADDITION (+=)
+			{ x+=A; y+=A; z+=A; };
+
+
+		Vector3d operator - (void) const                // NEGATION (-)
+			{ Vector3d Negated(-x, -y, -z);
+				return(Negated); };
+
+		float operator [] (const int i) const         // ALLOWS VECTOR ACCESS AS AN ARRAY.
+			{ return( (i==0)?x:((i==1)?y:z) ); };
+		float & operator [] (const int i)
+			{ return( (i==0)?x:((i==1)?y:z) ); };
+//
+
+	// accessor methods.
+	float GetX(void) const { return x; };
+	float GetY(void) const { return y; };
+	float GetZ(void) const { return z; };
+
+	float X(void) const { return x; };
+	float Y(void) const { return y; };
+	float Z(void) const { return z; };
+
+	void SetX(float t)   { x   = t; };
+	void SetY(float t)   { y   = t; };
+	void SetZ(float t)   { z   = t; };
+
+	bool IsSame(const Vector3d &v,float epsilon) const
+	{
+		float dx = fabsf( x - v.x );
+		if ( dx > epsilon ) return false;
+		float dy = fabsf( y - v.y );
+		if ( dy > epsilon ) return false;
+		float dz = fabsf( z - v.z );
+		if ( dz > epsilon ) return false;
+		return true;
+	}
+
+
+	float ComputeNormal(const Vector3d &A,
+										 const Vector3d &B,
+										 const Vector3d &C)
+	{
+		float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag;
+
+		vx = (B.x - C.x);
+		vy = (B.y - C.y);
+		vz = (B.z - C.z);
+
+		wx = (A.x - B.x);
+		wy = (A.y - B.y);
+		wz = (A.z - B.z);
+
+		vw_x = vy * wz - vz * wy;
+		vw_y = vz * wx - vx * wz;
+		vw_z = vx * wy - vy * wx;
+
+		mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
+
+		if ( mag < 0.000001f )
+		{
+			mag = 0;
+		}
+		else
+		{
+			mag = 1.0f/mag;
+		}
+
+		x = vw_x * mag;
+		y = vw_y * mag;
+		z = vw_z * mag;
+
+		return mag;
+	}
+
+
+	void ScaleSumScale(float c0,float c1,const Vector3d &pos)
+	{
+		x = (x*c0) + (pos.x*c1);
+		y = (y*c0) + (pos.y*c1);
+		z = (z*c0) + (pos.z*c1);
+	}
+
+	void SwapYZ(void)
+	{
+		float t = y;
+		y = z;
+		z = t;
+	};
+
+	void Get(float *v) const
+	{
+		v[0] = x;
+		v[1] = y;
+		v[2] = z;
+	};
+
+	void Set(const int *p)
+	{
+		x = (float) p[0];
+		y = (float) p[1];
+		z = (float) p[2];
+	}
+
+	void Set(const float *p)
+	{
+		x = (float) p[0];
+		y = (float) p[1];
+		z = (float) p[2];
+	}
+
+
+	void Set(float a,float b,float c)
+	{
+		x = a;
+		y = b;
+		z = c;
+	};
+
+	void Zero(void)
+	{
+		x = y = z = 0;
+	};
+
+	const float* Ptr() const { return &x; }
+	float* Ptr() { return &x; }
+
+
+// return -(*this).
+	Vector3d negative(void) const
+	{
+		Vector3d result;
+		result.x = -x;
+		result.y = -y;
+		result.z = -z;
+		return result;
+	}
+
+	float Magnitude(void) const
+	{
+		return float(sqrt(x * x + y * y + z * z));
+	};
+
+	float FastMagnitude(void) const
+	{
+		return float(sqrtf(x * x + y * y + z * z));
+	};
+
+	float FasterMagnitude(void) const
+	{
+		return float(sqrtf(x * x + y * y + z * z));
+	};
+
+	void Lerp(const Vector3d& from,const Vector3d& to,float slerp)
+	{
+		x = ((to.x - from.x) * slerp) + from.x;
+		y = ((to.y - from.y) * slerp) + from.y;
+		z = ((to.z - from.z) * slerp) + from.z;
+	};
+
+	// Highly specialized interpolate routine.  Will compute the interpolated position
+	// shifted forward or backwards along the ray defined between (from) and (to).
+	// Reason for existance is so that when a bullet collides with a wall, for
+	// example, you can generate a graphic effect slightly *before* it hit the
+	// wall so that the effect doesn't sort into the wall itself.
+	void Interpolate(const Vector3d &from,const Vector3d &to,float offset)
+	{
+		x = to.x-from.x;
+		y = to.y-from.y;
+		z = to.z-from.z;
+		float d = sqrtf( x*x + y*y + z*z );
+		float recip = 1.0f / d;
+		x*=recip;
+		y*=recip;
+		z*=recip; // normalize vector
+		d+=offset; // shift along ray
+		x = x*d + from.x;
+		y = y*d + from.y;
+		z = z*d + from.z;
+	};
+
+	bool BinaryEqual(const Vector3d &p) const
+	{
+		const int *source = (const int *) &x;
+		const int *dest   = (const int *) &p.x;
+
+		if ( source[0] == dest[0] &&
+				 source[1] == dest[1] &&
+				 source[2] == dest[2] ) return true;
+
+		return false;
+	};
+
+	/*bool BinaryEqual(const Vector3d<int> &p) const
+	{
+		if ( x == p.x && y == p.y && z == p.z ) return true;
+		return false;
+	}
+	*/
+
+
+
+/** Computes the reflection vector between two vectors.*/
+	void Reflection(const Vector3d &a,const Vector3d &b)// compute reflection vector.
+	{
+		Vector3d c;
+		Vector3d d;
+
+		float dot = a.Dot(b) * 2.0f;
+
+		c = b * dot;
+
+		d = c - a;
+
+		x = -d.x;
+		y = -d.y;
+		z = -d.z;
+	};
+
+	void AngleAxis(float angle,const Vector3d& axis)
+	{
+		x = axis.x*angle;
+		y = axis.y*angle;
+		z = axis.z*angle;
+	};
+
+	float Length(void) const          // length of vector.
+	{
+		return float(sqrt( x*x + y*y + z*z ));
+	};
+
+
+	float ComputePlane(const Vector3d &A,
+										 const Vector3d &B,
+										 const Vector3d &C)
+	{
+		float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag;
+
+		vx = (B.x - C.x);
+		vy = (B.y - C.y);
+		vz = (B.z - C.z);
+
+		wx = (A.x - B.x);
+		wy = (A.y - B.y);
+		wz = (A.z - B.z);
+
+		vw_x = vy * wz - vz * wy;
+		vw_y = vz * wx - vx * wz;
+		vw_z = vx * wy - vy * wx;
+
+		mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
+
+		if ( mag < 0.000001f )
+		{
+			mag = 0;
+		}
+		else
+		{
+			mag = 1.0f/mag;
+		}
+
+		x = vw_x * mag;
+		y = vw_y * mag;
+		z = vw_z * mag;
+
+
+		float D = 0.0f - ((x*A.x)+(y*A.y)+(z*A.z));
+
+		return D;
+	}
+
+
+	float FastLength(void) const          // length of vector.
+	{
+		return float(sqrtf( x*x + y*y + z*z ));
+	};
+	
+
+	float FasterLength(void) const          // length of vector.
+	{
+		return float(sqrtf( x*x + y*y + z*z ));
+	};
+
+	float Length2(void) const         // squared distance, prior to square root.
+	{
+		float l2 = x*x+y*y+z*z;
+		return l2;
+	};
+
+	float Distance(const Vector3d &a) const   // distance between two points.
+	{
+		Vector3d d(a.x-x,a.y-y,a.z-z);
+		return d.Length();
+	}
+
+	float FastDistance(const Vector3d &a) const   // distance between two points.
+	{
+		Vector3d d(a.x-x,a.y-y,a.z-z);
+		return d.FastLength();
+	}
+	
+	float FasterDistance(const Vector3d &a) const   // distance between two points.
+	{
+		Vector3d d(a.x-x,a.y-y,a.z-z);
+		return d.FasterLength();
+	}
+
+
+	float DistanceXY(const Vector3d &a) const
+	{
+	float dx = a.x - x;
+	float dy = a.y - y;
+		float dist = dx*dx + dy*dy;
+	return dist;
+	}
+
+	float Distance2(const Vector3d &a) const  // squared distance.
+	{
+		float dx = a.x - x;
+		float dy = a.y - y;
+		float dz = a.z - z;
+		return dx*dx + dy*dy + dz*dz;
+	};
+
+	float Partial(const Vector3d &p) const
+	{
+		return (x*p.y) - (p.x*y);
+	}
+
+	float Area(const Vector3d &p1,const Vector3d &p2) const
+	{
+		float A = Partial(p1);
+		A+= p1.Partial(p2);
+		A+= p2.Partial(*this);
+		return A*0.5f;
+	}
+
+	inline float Normalize(void)       // normalize to a unit vector, returns distance.
+	{
+		float d = sqrtf( static_cast< float >( x*x + y*y + z*z ) );
+		if ( d > 0 )
+		{
+			float r = 1.0f / d;
+			x *= r;
+			y *= r;
+			z *= r;
+		}
+		else
+		{
+			x = y = z = 1;
+		}
+		return d;
+	};
+
+	inline float FastNormalize(void)       // normalize to a unit vector, returns distance.
+	{
+		float d = sqrt( static_cast< float >( x*x + y*y + z*z ) );
+		if ( d > 0 )
+		{
+			float r = 1.0f / d;
+			x *= r;
+			y *= r;
+			z *= r;
+		}
+		else
+		{
+			x = y = z = 1;
+		}
+		return d;
+	};
+
+	inline float FasterNormalize(void)       // normalize to a unit vector, returns distance.
+	{
+		float d = sqrtf( static_cast< float >( x*x + y*y + z*z ) );
+		if ( d > 0 )
+		{
+			float r = 1.0f / d;
+			x *= r;
+			y *= r;
+			z *= r;
+		}
+		else
+		{
+			x = y = z = 1;
+		}
+		return d;
+	};
+
+
+
+
+	float Dot(const Vector3d &a) const        // computes dot product.
+	{
+		return (x * a.x + y * a.y + z * a.z );
+	};
+
+
+	Vector3d Cross( const Vector3d& other ) const
+	{
+		Vector3d result( y*other.z - z*other.y,  z*other.x - x*other.z,  x*other.y - y*other.x );
+
+		return result;
+	}
+
+	void Cross(const Vector3d &a,const Vector3d &b)  // cross two vectors result in this one.
+	{
+		x = a.y*b.z - a.z*b.y;
+		y = a.z*b.x - a.x*b.z;
+		z = a.x*b.y - a.y*b.x;
+	};
+
+	/******************************************/
+	// Check if next edge (b to c) turns inward
+	//
+	//    Edge from a to b is already in face
+	//    Edge from b to c is being considered for addition to face
+	/******************************************/
+	bool Concave(const Vector3d& a,const Vector3d& b)
+	{
+		float vx,vy,vz,wx,wy,wz,vw_x,vw_y,vw_z,mag,nx,ny,nz,mag_a,mag_b;
+
+		wx = b.x - a.x;
+		wy = b.y - a.y;
+		wz = b.z - a.z;
+
+		mag_a = (float) sqrtf((wx * wx) + (wy * wy) + (wz * wz));
+
+		vx = x - b.x;
+		vy = y - b.y;
+		vz = z - b.z;
+
+		mag_b = (float) sqrtf((vx * vx) + (vy * vy) + (vz * vz));
+
+		vw_x = (vy * wz) - (vz * wy);
+		vw_y = (vz * wx) - (vx * wz);
+		vw_z = (vx * wy) - (vy * wx);
+
+		mag = (float) sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
+
+		// Check magnitude of cross product, which is a sine function
+		// i.e., mag (a x b) = mag (a) * mag (b) * sin (theta);
+		// If sin (theta) small, then angle between edges is very close to
+		// 180, which we may want to call a concavity.	Setting the
+		// CONCAVITY_TOLERANCE value greater than about 0.01 MAY cause
+		// face consolidation to get stuck on particular face.	Most meshes
+		// convert properly with a value of 0.0
+
+		if (mag/(mag_a*mag_b) <= 0.0f )	return true;
+
+		mag = 1.0f / mag;
+
+		nx = vw_x * mag;
+		ny = vw_y * mag;
+		nz = vw_z * mag;
+
+		// Dot product of tri normal with cross product result will
+		// yield positive number if edges are convex (+1.0 if two tris
+		// are coplanar), negative number if edges are concave (-1.0 if
+		// two tris are coplanar.)
+
+		mag = ( x * nx) + ( y * ny) + ( z * nz);
+
+		if (mag > 0.0f ) return false;
+
+		return(true);
+	};
+
+	bool PointTestXY(const Vector3d &i,const Vector3d &j) const
+	{
+		if (((( i.y <= y ) && ( y  < j.y )) ||
+				 (( j.y <= y ) && ( y  < i.y ))) &&
+					( x < (j.x - i.x) * (y - i.y) / (j.y - i.y) + i.x)) return true;
+		return false;
+	}
+
+	// test to see if this point is inside the triangle specified by
+	// these three points on the X/Y plane.
+	bool PointInTriXY(const Vector3d &p1,
+									const Vector3d &p2,
+									const Vector3d &p3) const
+	{
+		float ax  = p3.x - p2.x;
+		float ay  = p3.y - p2.y;
+		float bx  = p1.x - p3.x;
+		float by  = p1.y - p3.y;
+		float cx  = p2.x - p1.x;
+		float cy  = p2.y - p1.y;
+		float apx = x - p1.x;
+		float apy = y - p1.y;
+		float bpx = x - p2.x;
+		float bpy = y - p2.y;
+		float cpx = x - p3.x;
+		float cpy = y - p3.y;
+
+		float aCROSSbp = ax*bpy - ay*bpx;
+		float cCROSSap = cx*apy - cy*apx;
+		float bCROSScp = bx*cpy - by*cpx;
+
+		return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
+	};
+
+	// test to see if this point is inside the triangle specified by
+	// these three points on the X/Y plane.
+	bool PointInTriYZ(const Vector3d &p1,
+									const Vector3d &p2,
+									const Vector3d &p3) const
+	{
+		float ay  = p3.y - p2.y;
+		float az  = p3.z - p2.z;
+		float by  = p1.y - p3.y;
+		float bz  = p1.z - p3.z;
+		float cy  = p2.y - p1.y;
+		float cz  = p2.z - p1.z;
+		float apy = y - p1.y;
+		float apz = z - p1.z;
+		float bpy = y - p2.y;
+		float bpz = z - p2.z;
+		float cpy = y - p3.y;
+		float cpz = z - p3.z;
+
+		float aCROSSbp = ay*bpz - az*bpy;
+		float cCROSSap = cy*apz - cz*apy;
+		float bCROSScp = by*cpz - bz*cpy;
+
+		return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
+	};
+
+
+	// test to see if this point is inside the triangle specified by
+	// these three points on the X/Y plane.
+	bool PointInTriXZ(const Vector3d &p1,
+									const Vector3d &p2,
+									const Vector3d &p3) const
+	{
+		float az  = p3.z - p2.z;
+		float ax  = p3.x - p2.x;
+		float bz  = p1.z - p3.z;
+		float bx  = p1.x - p3.x;
+		float cz  = p2.z - p1.z;
+		float cx  = p2.x - p1.x;
+		float apz = z - p1.z;
+		float apx = x - p1.x;
+		float bpz = z - p2.z;
+		float bpx = x - p2.x;
+		float cpz = z - p3.z;
+		float cpx = x - p3.x;
+
+		float aCROSSbp = az*bpx - ax*bpz;
+		float cCROSSap = cz*apx - cx*apz;
+		float bCROSScp = bz*cpx - bx*cpz;
+
+		return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f));
+	};
+
+	// Given a point and a line (defined by two points), compute the closest point
+	// in the line.  (The line is treated as infinitely long.)
+	void NearestPointInLine(const Vector3d &point,
+													const Vector3d &line0,
+													const Vector3d &line1)
+	{
+		Vector3d &nearestPoint = *this;
+		Vector3d lineDelta     = line1 - line0;
+
+		// Handle degenerate lines
+		if ( lineDelta == Vector3d(0, 0, 0) )
+		{
+			nearestPoint = line0;
+		}
+		else
+		{
+			float delta = (point-line0).Dot(lineDelta) / (lineDelta).Dot(lineDelta);
+			nearestPoint = line0 + lineDelta*delta;
+		}
+	}
+
+	// Given a point and a line segment (defined by two points), compute the closest point
+	// in the line.  Cap the point at the endpoints of the line segment.
+	void NearestPointInLineSegment(const Vector3d &point,
+																 const Vector3d &line0,
+																 const Vector3d &line1)
+	{
+		Vector3d &nearestPoint = *this;
+		Vector3d lineDelta     = line1 - line0;
+
+		// Handle degenerate lines
+		if ( lineDelta == Vector3d(0, 0, 0) )
+		{
+			nearestPoint = line0;
+		}
+		else
+		{
+			float delta = (point-line0).Dot(lineDelta) / (lineDelta).Dot(lineDelta);
+
+			// Clamp the point to conform to the segment's endpoints
+			if ( delta < 0 )
+				delta = 0;
+			else if ( delta > 1 )
+				delta = 1;
+
+			nearestPoint = line0 + lineDelta*delta;
+		}
+	}
+
+	// Given a point and a plane (defined by three points), compute the closest point
+	// in the plane.  (The plane is unbounded.)
+	void NearestPointInPlane(const Vector3d &point,
+													 const Vector3d &triangle0,
+													 const Vector3d &triangle1,
+													 const Vector3d &triangle2)
+	{
+		Vector3d &nearestPoint = *this;
+		Vector3d lineDelta0    = triangle1 - triangle0;
+		Vector3d lineDelta1    = triangle2 - triangle0;
+		Vector3d pointDelta    = point - triangle0;
+		Vector3d normal;
+
+		// Get the normal of the polygon (doesn't have to be a unit vector)
+		normal.Cross(lineDelta0, lineDelta1);
+
+		float delta = normal.Dot(pointDelta) / normal.Dot(normal);
+		nearestPoint = point - normal*delta;
+	}
+
+	// Given a point and a plane (defined by a coplanar point and a normal), compute the closest point
+	// in the plane.  (The plane is unbounded.)
+	void NearestPointInPlane(const Vector3d &point,
+													 const Vector3d &planePoint,
+													 const Vector3d &planeNormal)
+	{
+		Vector3d &nearestPoint = *this;
+		Vector3d pointDelta    = point - planePoint;
+
+		float delta = planeNormal.Dot(pointDelta) / planeNormal.Dot(planeNormal);
+		nearestPoint = point - planeNormal*delta;
+	}
+
+	// Given a point and a triangle (defined by three points), compute the closest point
+	// in the triangle.  Clamp the point so it's confined to the area of the triangle.
+	void NearestPointInTriangle(const Vector3d &point,
+															const Vector3d &triangle0,
+															const Vector3d &triangle1,
+															const Vector3d &triangle2)
+	{
+		static const Vector3d zeroVector(0, 0, 0);
+
+		Vector3d &nearestPoint = *this;
+
+		Vector3d lineDelta0 = triangle1 - triangle0;
+		Vector3d lineDelta1 = triangle2 - triangle0;
+
+		// Handle degenerate triangles
+		if ( (lineDelta0 == zeroVector) || (lineDelta1 == zeroVector) )
+		{
+			nearestPoint.NearestPointInLineSegment(point, triangle1, triangle2);
+		}
+		else if ( lineDelta0 == lineDelta1 )
+		{
+			nearestPoint.NearestPointInLineSegment(point, triangle0, triangle1);
+		}
+
+		else
+		{
+			static Vector3d axis[3];
+			axis[0].NearestPointInLine(triangle0, triangle1, triangle2);
+			axis[1].NearestPointInLine(triangle1, triangle0, triangle2);
+			axis[2].NearestPointInLine(triangle2, triangle0, triangle1);
+
+			float axisDot[3];
+			axisDot[0] = (triangle0-axis[0]).Dot(point-axis[0]);
+			axisDot[1] = (triangle1-axis[1]).Dot(point-axis[1]);
+			axisDot[2] = (triangle2-axis[2]).Dot(point-axis[2]);
+
+			bool            bForce         = true;
+			float            bestMagnitude2 = 0;
+			float            closeMagnitude2;
+			Vector3d closePoint;
+
+			if ( axisDot[0] < 0 )
+			{
+				closePoint.NearestPointInLineSegment(point, triangle1, triangle2);
+				closeMagnitude2 = point.Distance2(closePoint);
+				if ( bForce || (bestMagnitude2 > closeMagnitude2) )
+				{
+					bForce         = false;
+					bestMagnitude2 = closeMagnitude2;
+					nearestPoint   = closePoint;
+				}
+			}
+			if ( axisDot[1] < 0 )
+			{
+				closePoint.NearestPointInLineSegment(point, triangle0, triangle2);
+				closeMagnitude2 = point.Distance2(closePoint);
+				if ( bForce || (bestMagnitude2 > closeMagnitude2) )
+				{
+					bForce         = false;
+					bestMagnitude2 = closeMagnitude2;
+					nearestPoint   = closePoint;
+				}
+			}
+			if ( axisDot[2] < 0 )
+			{
+				closePoint.NearestPointInLineSegment(point, triangle0, triangle1);
+				closeMagnitude2 = point.Distance2(closePoint);
+				if ( bForce || (bestMagnitude2 > closeMagnitude2) )
+				{
+					bForce         = false;
+					bestMagnitude2 = closeMagnitude2;
+					nearestPoint   = closePoint;
+				}
+			}
+
+			// If bForce is true at this point, it means the nearest point lies
+			// inside the triangle; use the nearest-point-on-a-plane equation
+			if ( bForce )
+			{
+				Vector3d normal;
+
+				// Get the normal of the polygon (doesn't have to be a unit vector)
+				normal.Cross(lineDelta0, lineDelta1);
+
+				Vector3d pointDelta = point - triangle0;
+				float delta = normal.Dot(pointDelta) / normal.Dot(normal);
+
+				nearestPoint = point - normal*delta;
+			}
+		}
+	}
+
+
+//private:
+
+	float x;
+	float y;
+	float z;
+};
+
+
+class Vector2d
+{
+public:
+	Vector2d(void) { };  // null constructor, does not inialize point.
+
+	Vector2d(const Vector2d &a) // constructor copies existing vector.
+	{
+		x = a.x;
+		y = a.y;
+	};
+
+	Vector2d(const float *t)
+	{
+		x = t[0];
+		y = t[1];
+	};
+
+
+	Vector2d(float a,float b) // construct with initial point.
+	{
+		x = a;
+		y = b;
+	};
+
+	const float* Ptr() const { return &x; }
+	float* Ptr() { return &x; }
+
+	Vector2d & operator+=(const Vector2d &a) // += operator.
+	{
+		x+=a.x;
+		y+=a.y;
+		return *this;
+	};
+
+	Vector2d & operator-=(const Vector2d &a)
+	{
+		x-=a.x;
+		y-=a.y;
+		return *this;
+	};
+
+	Vector2d & operator*=(const Vector2d &a)
+	{
+		x*=a.x;
+		y*=a.y;
+		return *this;
+	};
+
+	Vector2d & operator/=(const Vector2d &a)
+	{
+		x/=a.x;
+		y/=a.y;
+		return *this;
+	};
+
+	bool operator==(const Vector2d &a) const
+	{
+		if ( a.x == x && a.y == y ) return true;
+		return false;
+	};
+
+	bool operator!=(const Vector2d &a) const
+	{
+		if ( a.x != x || a.y != y ) return true;
+		return false;
+	};
+
+	Vector2d operator+(Vector2d a) const
+	{
+		a.x+=x;
+		a.y+=y;
+		return a;
+	};
+
+	Vector2d operator-(Vector2d a) const
+	{
+		a.x = x-a.x;
+		a.y = y-a.y;
+		return a;
+	};
+
+	Vector2d operator - (void) const
+	{
+		return negative();
+	};
+
+	Vector2d operator*(Vector2d a) const
+	{
+		a.x*=x;
+		a.y*=y;
+		return a;
+	};
+
+	Vector2d operator*(float c) const
+	{
+		Vector2d a;
+		
+		a.x = x * c;
+		a.y = y * c;
+
+		return a;
+	};
+
+	Vector2d operator/(Vector2d a) const
+	{
+		a.x = x/a.x;
+		a.y = y/a.y;
+		return a;
+	};
+
+
+	float Dot(const Vector2d &a) const        // computes dot product.
+	{
+		return (x * a.x + y * a.y );
+	};
+
+	float GetX(void) const { return x; };
+	float GetY(void) const { return y; };
+
+	void SetX(float t) { x   = t; };
+	void SetY(float t) { y   = t; };
+
+	void Set(float a,float b)
+	{
+		x = a;
+		y = b;
+	};
+
+	void Zero(void)
+	{
+		x = y = 0;
+	};
+
+	Vector2d negative(void) const
+	{
+		Vector2d result;
+		result.x = -x;
+		result.y = -y;
+		return result;
+	}
+
+	float magnitude(void) const
+	{
+		return (float) sqrtf(x * x + y * y );
+	}
+
+	float fastmagnitude(void) const
+	{
+		return (float) sqrtf(x * x + y * y );
+	}
+	
+	float fastermagnitude(void) const
+	{
+		return (float) sqrtf( x * x + y * y );
+	}
+
+	void Reflection(Vector2d &a,Vector2d &b); // compute reflection vector.
+
+	float Length(void) const          // length of vector.
+	{
+		return float(sqrtf( x*x + y*y ));
+	};
+
+	float FastLength(void) const          // length of vector.
+	{
+		return float(sqrtf( x*x + y*y ));
+	};
+
+	float FasterLength(void) const          // length of vector.
+	{
+		return float(sqrtf( x*x + y*y ));
+	};
+
+	float Length2(void)        // squared distance, prior to square root.
+	{
+		return x*x+y*y;
+	}
+
+	float Distance(const Vector2d &a) const   // distance between two points.
+	{
+		float dx = a.x - x;
+		float dy = a.y - y;
+		float d  = dx*dx+dy*dy;
+		return sqrtf(d);
+	};
+
+	float FastDistance(const Vector2d &a) const   // distance between two points.
+	{
+		float dx = a.x - x;
+		float dy = a.y - y;
+		float d  = dx*dx+dy*dy;
+		return sqrtf(d);
+	};
+
+	float FasterDistance(const Vector2d &a) const   // distance between two points.
+	{
+		float dx = a.x - x;
+		float dy = a.y - y;
+		float d  = dx*dx+dy*dy;
+		return sqrtf(d);
+	};
+
+	float Distance2(Vector2d &a) // squared distance.
+	{
+		float dx = a.x - x;
+		float dy = a.y - y;
+		return dx*dx + dy *dy;
+	};
+
+	void Lerp(const Vector2d& from,const Vector2d& to,float slerp)
+	{
+		x = ((to.x - from.x)*slerp) + from.x;
+		y = ((to.y - from.y)*slerp) + from.y;
+	};
+
+
+	void Cross(const Vector2d &a,const Vector2d &b)  // cross two vectors result in this one.
+	{
+		x = a.y*b.x - a.x*b.y;
+		y = a.x*b.x - a.x*b.x;
+	};
+
+	float Normalize(void)       // normalize to a unit vector, returns distance.
+	{
+		float l = Length();
+		if ( l != 0 )
+		{
+			l = float( 1 ) / l;
+			x*=l;
+			y*=l;
+		}
+		else
+		{
+			x = y = 0;
+		}
+		return l;
+	};
+
+	float FastNormalize(void)       // normalize to a unit vector, returns distance.
+	{
+		float l = FastLength();
+		if ( l != 0 )
+		{
+			l = float( 1 ) / l;
+			x*=l;
+			y*=l;
+		}
+		else
+		{
+			x = y = 0;
+		}
+		return l;
+	};
+
+	float FasterNormalize(void)       // normalize to a unit vector, returns distance.
+	{
+		float l = FasterLength();
+		if ( l != 0 )
+		{
+			l = float( 1 ) / l;
+			x*=l;
+			y*=l;
+		}
+		else
+		{
+			x = y = 0;
+		}
+		return l;
+	};
+
+
+	float x;
+	float y;
+};
+
+class Line
+{
+public:
+	Line(const Vector3d &from,const Vector3d &to)
+	{
+		mP1 = from;
+		mP2 = to;
+	};
+	// JWR  Test for the intersection of two lines.
+
+	bool Intersect(const Line& src,Vector3d &sect);
+private:
+	Vector3d mP1;
+	Vector3d mP2;
+
+};
+
+
+typedef std::vector< Vector3d > Vector3dVector;
+typedef std::vector< Vector2d > Vector2dVector;
+
+inline  Vector3d operator * (float s, const Vector3d &v )
+{ 
+	Vector3d	Scaled(v.x*s, v.y*s, v.z*s);
+	return(Scaled); 
+}
+
+inline  Vector2d	operator * (float s, const Vector2d &v )
+ { 
+	 Vector2d	Scaled(v.x*s, v.y*s);
+	return(Scaled); 
+ }
+
+}
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_wavefront.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_wavefront.cpp
new file mode 100644
index 0000000..786f438
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_wavefront.cpp
@@ -0,0 +1,860 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+#include "float_math.h"
+
+#include "cd_wavefront.h"
+
+
+using namespace ConvexDecomposition;
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+#include <vector>
+
+namespace ConvexDecomposition
+{
+
+typedef std::vector< int > IntVector;
+typedef std::vector< float > FloatVector;
+
+#if defined(__APPLE__) || defined(__CELLOS_LV2__)
+#define stricmp(a, b) strcasecmp((a), (b))
+#endif
+
+/*******************************************************************/
+/******************** InParser.h  ********************************/
+/*******************************************************************/
+class InPlaceParserInterface
+{
+public:
+  virtual ~InPlaceParserInterface () {} ;
+
+  virtual int ParseLine(int lineno,int argc,const char **argv) =0;  // return TRUE to continue parsing, return FALSE to abort parsing process
+};
+
+enum SeparatorType
+{
+	ST_DATA,        // is data
+	ST_HARD,        // is a hard separator
+	ST_SOFT,        // is a soft separator
+	ST_EOS          // is a comment symbol, and everything past this character should be ignored
+};
+
+class InPlaceParser
+{
+public:
+	InPlaceParser(void)
+	{
+		Init();
+	}
+
+	InPlaceParser(char *data,int len)
+	{
+		Init();
+		SetSourceData(data,len);
+	}
+
+	InPlaceParser(const char *fname)
+	{
+		Init();
+		SetFile(fname);
+	}
+
+	~InPlaceParser(void);
+
+	void Init(void)
+	{
+		mQuoteChar = 34;
+		mData = 0;
+		mLen  = 0;
+		mMyAlloc = false;
+		for (int i=0; i<256; i++)
+		{
+			mHard[i] = ST_DATA;
+			mHardString[i*2] = i;
+			mHardString[i*2+1] = 0;
+		}
+		mHard[0]  = ST_EOS;
+		mHard[32] = ST_SOFT;
+		mHard[9]  = ST_SOFT;
+		mHard[13] = ST_SOFT;
+		mHard[10] = ST_SOFT;
+	}
+
+	void SetFile(const char *fname); // use this file as source data to parse.
+
+	void SetSourceData(char *data,int len)
+	{
+		mData = data;
+		mLen  = len;
+		mMyAlloc = false;
+	};
+
+	int  Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason
+
+	int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback);
+
+	const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse.
+
+	void SetHardSeparator(char c) // add a hard separator
+	{
+		mHard[(int)c] = ST_HARD;
+	}
+
+	void SetHard(char c) // add a hard separator
+	{
+		mHard[(int)c] = ST_HARD;
+	}
+
+
+	void SetCommentSymbol(char c) // comment character, treated as 'end of string'
+	{
+		mHard[(int)c] = ST_EOS;
+	}
+
+	void ClearHardSeparator(char c)
+	{
+		mHard[(int)c] = ST_DATA;
+	}
+
+
+	void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character.
+
+	bool EOS(char c)
+	{
+		if ( mHard[(int)c] == ST_EOS )
+		{
+			return true;
+		}
+		return false;
+	}
+
+	void SetQuoteChar(char c)
+	{
+		mQuoteChar = c;
+	}
+
+private:
+
+
+	inline char * AddHard(int &argc,const char **argv,char *foo);
+	inline bool   IsHard(char c);
+	inline char * SkipSpaces(char *foo);
+	inline bool   IsWhiteSpace(char c);
+	inline bool   IsNonSeparator(char c); // non seperator,neither hard nor soft
+
+	bool   mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it.
+	char  *mData;  // ascii data to parse.
+	int    mLen;   // length of data
+	SeparatorType  mHard[256];
+	char   mHardString[256*2];
+	char           mQuoteChar;
+};
+
+/*******************************************************************/
+/******************** InParser.cpp  ********************************/
+/*******************************************************************/
+void InPlaceParser::SetFile(const char *fname)
+{
+	if ( mMyAlloc )
+	{
+		free(mData);
+	}
+	mData = 0;
+	mLen  = 0;
+	mMyAlloc = false;
+
+
+	FILE *fph = fopen(fname,"rb");
+	if ( fph )
+	{
+		fseek(fph,0L,SEEK_END);
+		mLen = ftell(fph);
+		fseek(fph,0L,SEEK_SET);
+		if ( mLen )
+		{
+			mData = (char *) malloc(sizeof(char)*(mLen+1));
+			int ok = fread(mData, mLen, 1, fph);
+			if ( !ok )
+			{
+				free(mData);
+				mData = 0;
+			}
+			else
+			{
+				mData[mLen] = 0; // zero byte terminate end of file marker.
+				mMyAlloc = true;
+			}
+		}
+		fclose(fph);
+	}
+}
+
+InPlaceParser::~InPlaceParser(void)
+{
+	if ( mMyAlloc )
+	{
+		free(mData);
+	}
+}
+
+#define MAXARGS 512
+
+bool InPlaceParser::IsHard(char c)
+{
+	return mHard[(int)c] == ST_HARD;
+}
+
+char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo)
+{
+	while ( IsHard(*foo) )
+	{
+		const char *hard = &mHardString[*foo*2];
+		if ( argc < MAXARGS )
+		{
+			argv[argc++] = hard;
+		}
+		foo++;
+	}
+	return foo;
+}
+
+bool   InPlaceParser::IsWhiteSpace(char c)
+{
+	return mHard[(int)c] == ST_SOFT;
+}
+
+char * InPlaceParser::SkipSpaces(char *foo)
+{
+	while ( !EOS(*foo) && IsWhiteSpace(*foo) ) foo++;
+	return foo;
+}
+
+bool InPlaceParser::IsNonSeparator(char c)
+{
+	if ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ) return true;
+	return false;
+}
+
+
+int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback)
+{
+	int ret = 0;
+
+	const char *argv[MAXARGS];
+	int argc = 0;
+
+	char *foo = line;
+
+	while ( !EOS(*foo) && argc < MAXARGS )
+	{
+
+		foo = SkipSpaces(foo); // skip any leading spaces
+
+		if ( EOS(*foo) ) break;
+
+		if ( *foo == mQuoteChar ) // if it is an open quote
+		{
+			foo++;
+			if ( argc < MAXARGS )
+			{
+				argv[argc++] = foo;
+			}
+			while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
+			if ( !EOS(*foo) )
+			{
+				*foo = 0; // replace close quote with zero byte EOS
+				foo++;
+			}
+		}
+		else
+		{
+
+			foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
+
+			if ( IsNonSeparator(*foo) )  // add non-hard argument.
+			{
+				bool quote  = false;
+				if ( *foo == mQuoteChar )
+				{
+					foo++;
+					quote = true;
+				}
+
+				if ( argc < MAXARGS )
+				{
+					argv[argc++] = foo;
+				}
+
+				if ( quote )
+				{
+					while (*foo && *foo != mQuoteChar ) foo++;
+					if ( *foo ) *foo = 32;
+				}
+
+				// continue..until we hit an eos ..
+				while ( !EOS(*foo) ) // until we hit EOS
+				{
+					if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
+					{
+						*foo = 0;
+						foo++;
+						break;
+					}
+					else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
+					{
+						const char *hard = &mHardString[*foo*2];
+						*foo = 0;
+						if ( argc < MAXARGS )
+						{
+							argv[argc++] = hard;
+						}
+						foo++;
+						break;
+					}
+					foo++;
+				} // end of while loop...
+			}
+		}
+	}
+
+	if ( argc )
+	{
+		ret = callback->ParseLine(lineno, argc, argv );
+	}
+
+	return ret;
+}
+
+int  InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason
+{
+	assert( callback );
+	if ( !mData ) return 0;
+
+	int ret = 0;
+
+	int lineno = 0;
+
+	char *foo   = mData;
+	char *begin = foo;
+
+
+	while ( *foo )
+	{
+		if ( *foo == 10 || *foo == 13 )
+		{
+			lineno++;
+			*foo = 0;
+
+			if ( *begin ) // if there is any data to parse at all...
+			{
+				int v = ProcessLine(lineno,begin,callback);
+				if ( v ) ret = v;
+			}
+
+			foo++;
+			if ( *foo == 10 ) foo++; // skip line feed, if it is in the carraige-return line-feed format...
+			begin = foo;
+		}
+		else
+		{
+			foo++;
+		}
+	}
+
+	lineno++; // lasst line.
+
+	int v = ProcessLine(lineno,begin,callback);
+	if ( v ) ret = v;
+	return ret;
+}
+
+
+void InPlaceParser::DefaultSymbols(void)
+{
+	SetHardSeparator(',');
+	SetHardSeparator('(');
+	SetHardSeparator(')');
+	SetHardSeparator('=');
+	SetHardSeparator('[');
+	SetHardSeparator(']');
+	SetHardSeparator('{');
+	SetHardSeparator('}');
+	SetCommentSymbol('#');
+}
+
+
+const char ** InPlaceParser::GetArglist(char *line,int &count) // convert source string into an arg list, this is a destructive parse.
+{
+	const char **ret = 0;
+
+	static const char *argv[MAXARGS];
+	int argc = 0;
+
+	char *foo = line;
+
+	while ( !EOS(*foo) && argc < MAXARGS )
+	{
+
+		foo = SkipSpaces(foo); // skip any leading spaces
+
+		if ( EOS(*foo) ) break;
+
+		if ( *foo == mQuoteChar ) // if it is an open quote
+		{
+			foo++;
+			if ( argc < MAXARGS )
+			{
+				argv[argc++] = foo;
+			}
+			while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
+			if ( !EOS(*foo) )
+			{
+				*foo = 0; // replace close quote with zero byte EOS
+				foo++;
+			}
+		}
+		else
+		{
+
+			foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
+
+			if ( IsNonSeparator(*foo) )  // add non-hard argument.
+			{
+				bool quote  = false;
+				if ( *foo == mQuoteChar )
+				{
+					foo++;
+					quote = true;
+				}
+
+				if ( argc < MAXARGS )
+				{
+					argv[argc++] = foo;
+				}
+
+				if ( quote )
+				{
+					while (*foo && *foo != mQuoteChar ) foo++;
+					if ( *foo ) *foo = 32;
+				}
+
+				// continue..until we hit an eos ..
+				while ( !EOS(*foo) ) // until we hit EOS
+				{
+					if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
+					{
+						*foo = 0;
+						foo++;
+						break;
+					}
+					else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
+					{
+						const char *hard = &mHardString[*foo*2];
+						*foo = 0;
+						if ( argc < MAXARGS )
+						{
+							argv[argc++] = hard;
+						}
+						foo++;
+						break;
+					}
+					foo++;
+				} // end of while loop...
+			}
+		}
+	}
+
+	count = argc;
+	if ( argc )
+	{
+		ret = argv;
+	}
+
+	return ret;
+}
+
+/*******************************************************************/
+/******************** Geometry.h  ********************************/
+/*******************************************************************/
+
+class GeometryVertex
+{
+public:
+	float        mPos[3];
+	float        mNormal[3];
+	float        mTexel[2];
+};
+
+
+class GeometryInterface
+{
+public:
+
+  virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3) {}
+
+  virtual ~GeometryInterface () {}
+};
+
+
+/*******************************************************************/
+/******************** Obj.h  ********************************/
+/*******************************************************************/
+
+
+class OBJ : public InPlaceParserInterface
+{
+public:
+  int          LoadMesh(const char *fname,GeometryInterface *callback);
+  int ParseLine(int lineno,int argc,const char **argv);  // return TRUE to continue parsing, return FALSE to abort parsing process
+private:
+
+  void getVertex(GeometryVertex &v,const char *face) const;
+
+  FloatVector     mVerts;
+  FloatVector     mTexels;
+  FloatVector     mNormals;
+
+  GeometryInterface *mCallback;
+};
+
+
+/*******************************************************************/
+/******************** Obj.cpp  ********************************/
+/*******************************************************************/
+
+int OBJ::LoadMesh(const char *fname,GeometryInterface *iface)
+{
+  int ret = 0;
+
+  mVerts.clear();
+  mTexels.clear();
+  mNormals.clear();
+
+  mCallback = iface;
+
+  InPlaceParser ipp(fname);
+
+  ipp.Parse(this);
+
+
+  return ret;
+}
+
+static const char * GetArg(const char **argv,int i,int argc)
+{
+  const char * ret = 0;
+  if ( i < argc ) ret = argv[i];
+  return ret;
+}
+
+void OBJ::getVertex(GeometryVertex &v,const char *face) const
+{
+  v.mPos[0] = 0;
+  v.mPos[1] = 0;
+  v.mPos[2] = 0;
+
+  v.mTexel[0] = 0;
+  v.mTexel[1] = 0;
+
+  v.mNormal[0] = 0;
+  v.mNormal[1] = 1;
+  v.mNormal[2] = 0;
+
+  int index = atoi( face )-1;
+
+  const char *texel = strstr(face,"/");
+
+  if ( texel )
+  {
+    int tindex = atoi( texel+1) - 1;
+
+    if ( tindex >=0 && tindex < (int)(mTexels.size()/2) )
+    {
+    	const float *t = &mTexels[tindex*2];
+
+      v.mTexel[0] = t[0];
+      v.mTexel[1] = t[1];
+
+    }
+
+    const char *normal = strstr(texel+1,"/");
+    if ( normal )
+    {
+      int nindex = atoi( normal+1 ) - 1;
+
+      if (nindex >= 0 && nindex < (int)(mNormals.size()/3) )
+      {
+      	const float *n = &mNormals[nindex*3];
+
+        v.mNormal[0] = n[0];
+        v.mNormal[1] = n[1];
+        v.mNormal[2] = n[2];
+      }
+    }
+  }
+
+  if ( index >= 0 && index < (int)(mVerts.size()/3) )
+  {
+
+    const float *p = &mVerts[index*3];
+
+    v.mPos[0] = p[0];
+    v.mPos[1] = p[1];
+    v.mPos[2] = p[2];
+  }
+
+}
+
+int OBJ::ParseLine(int lineno,int argc,const char **argv)  // return TRUE to continue parsing, return FALSE to abort parsing process
+{
+  int ret = 0;
+
+  if ( argc >= 1 )
+  {
+    const char *foo = argv[0];
+    if ( *foo != '#' )
+    {
+  if ( strcmp(argv[0],"v") == 0 && argc == 4 )
+
+      //if ( stricmp(argv[0],"v") == 0 && argc == 4 )
+      {
+        float vx = (float) atof( argv[1] );
+        float vy = (float) atof( argv[2] );
+        float vz = (float) atof( argv[3] );
+        mVerts.push_back(vx);
+        mVerts.push_back(vy);
+        mVerts.push_back(vz);
+      }
+  else if ( strcmp(argv[0],"vt") == 0 && argc == 3 )
+
+ //     else if ( stricmp(argv[0],"vt") == 0 && argc == 3 )
+      {
+        float tx = (float) atof( argv[1] );
+        float ty = (float) atof( argv[2] );
+        mTexels.push_back(tx);
+        mTexels.push_back(ty);
+      }
+	//  else if ( stricmp(argv[0],"vn") == 0 && argc == 4 )
+
+      else if ( strcmp(argv[0],"vn") == 0 && argc == 4 )
+      {
+        float normalx = (float) atof(argv[1]);
+        float normaly = (float) atof(argv[2]);
+        float normalz = (float) atof(argv[3]);
+        mNormals.push_back(normalx);
+        mNormals.push_back(normaly);
+        mNormals.push_back(normalz);
+      }
+//  else if ( stricmp(argv[0],"f") == 0 && argc >= 4 )
+
+      else if ( strcmp(argv[0],"f") == 0 && argc >= 4 )
+      {
+        GeometryVertex v[32];
+
+        int vcount = argc-1;
+
+        for (int i=1; i<argc; i++)
+        {
+          getVertex(v[i-1],argv[i] );
+        }
+
+        // need to generate a normal!
+#if 0 // not currently implemented
+        if ( mNormals.empty() )
+        {
+          Vector3d<float> p1( v[0].mPos );
+          Vector3d<float> p2( v[1].mPos );
+          Vector3d<float> p3( v[2].mPos );
+
+          Vector3d<float> n;
+          n.ComputeNormal(p3,p2,p1);
+
+          for (int i=0; i<vcount; i++)
+          {
+            v[i].mNormal[0] = n.x;
+            v[i].mNormal[1] = n.y;
+            v[i].mNormal[2] = n.z;
+          }
+
+        }
+#endif
+
+        mCallback->NodeTriangle(&v[0],&v[1],&v[2]);
+
+        if ( vcount >=3 ) // do the fan
+        {
+          for (int i=2; i<(vcount-1); i++)
+          {
+            mCallback->NodeTriangle(&v[0],&v[i],&v[i+1]);
+          }
+        }
+
+      }
+    }
+  }
+
+  return ret;
+}
+
+
+
+
+class BuildMesh : public GeometryInterface
+{
+public:
+
+	int getIndex(const float *p)
+	{
+
+		int vcount = mVertices.size()/3;
+
+		if(vcount>0)
+		{
+			//New MS STL library checks indices in debug build, so zero causes an assert if it is empty.
+			const float *v = &mVertices[0];
+
+			for (int i=0; i<vcount; i++)
+			{
+				if ( v[0] == p[0] && v[1] == p[1] && v[2] == p[2] ) return i;
+				v+=3;
+			}
+		}
+
+		mVertices.push_back( p[0] );
+		mVertices.push_back( p[1] );
+		mVertices.push_back( p[2] );
+
+		return vcount;
+	}
+
+	virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3)
+	{
+		mIndices.push_back( getIndex(v1->mPos) );
+		mIndices.push_back( getIndex(v2->mPos) );
+		mIndices.push_back( getIndex(v3->mPos) );
+	}
+
+  const FloatVector& GetVertices(void) const { return mVertices; };
+  const IntVector& GetIndices(void) const { return mIndices; };
+
+private:
+  FloatVector     mVertices;
+  IntVector		    mIndices;
+};
+
+
+WavefrontObj::WavefrontObj(void)
+{
+	mVertexCount = 0;
+	mTriCount    = 0;
+	mIndices     = 0;
+	mVertices    = 0;
+}
+
+WavefrontObj::~WavefrontObj(void)
+{
+	delete [] mIndices;
+	delete [] mVertices;
+}
+
+unsigned int WavefrontObj::loadObj(const char *fname) // load a wavefront obj returns number of triangles that were loaded.  Data is persists until the class is destructed.
+{
+
+	unsigned int ret = 0;
+
+	delete [] mVertices;
+	mVertices = 0;
+	delete [] mIndices;
+	mIndices = 0;
+	mVertexCount = 0;
+	mTriCount = 0;
+
+
+  BuildMesh bm;
+
+  OBJ obj;
+
+  obj.LoadMesh(fname,&bm);
+
+
+	const FloatVector &vlist = bm.GetVertices();
+	const IntVector &indices = bm.GetIndices();
+	if ( vlist.size() )
+	{
+		mVertexCount = vlist.size()/3;
+		mVertices = new float[mVertexCount*3];
+		memcpy( mVertices, &vlist[0], sizeof(float)*mVertexCount*3 );
+		mTriCount = indices.size()/3;
+		mIndices = new int[mTriCount*3*sizeof(int)];
+		memcpy(mIndices, &indices[0], sizeof(int)*mTriCount*3);
+		ret = mTriCount;
+	}
+
+
+	return ret;
+}
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_wavefront.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_wavefront.h
new file mode 100644
index 0000000..ba5f90b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/cd_wavefront.h
@@ -0,0 +1,62 @@
+#ifndef CD_WAVEFRONT_OBJ_H
+
+
+#define CD_WAVEFRONT_OBJ_H
+
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+namespace ConvexDecomposition
+{
+
+class WavefrontObj
+{
+public:
+
+  WavefrontObj(void);
+  ~WavefrontObj(void);
+
+	unsigned int loadObj(const char *fname); // load a wavefront obj returns number of triangles that were loaded.  Data is persists until the class is destructed.
+
+  int	          mVertexCount;
+  int	          mTriCount;
+  int          *mIndices;
+  float        *mVertices;
+};
+
+}
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/concavity.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/concavity.cpp
new file mode 100644
index 0000000..f1a4660
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/concavity.cpp
@@ -0,0 +1,795 @@
+#include "float_math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include <vector>
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+#include "concavity.h"
+#include "raytri.h"
+#include "bestfit.h"
+#include "cd_hull.h"
+#include "meshvolume.h"
+#include "cd_vector.h"
+#include "splitplane.h"
+#include "ConvexDecomposition.h"
+
+
+#define WSCALE 4
+#define CONCAVE_THRESH 0.05f
+
+namespace ConvexDecomposition
+{
+
+unsigned int getDebugColor(void)
+{
+	static unsigned int colors[8] =
+	{
+		0xFF0000,
+	  0x00FF00,
+		0x0000FF,
+		0xFFFF00,
+		0x00FFFF,
+		0xFF00FF,
+		0xFFFFFF,
+		0xFF8040
+	};
+
+	static int count = 0;
+
+	count++;
+
+	if ( count == 8 ) count = 0;
+
+	assert( count >= 0 && count < 8 );
+
+	unsigned int color = colors[count];
+
+  return color;
+
+}
+
+class Wpoint
+{
+public:
+  Wpoint(const Vector3d &p,float w)
+  {
+    mPoint = p;
+    mWeight = w;
+  }
+
+  Vector3d mPoint;
+  float           mWeight;
+};
+
+typedef std::vector< Wpoint > WpointVector;
+
+
+static inline float DistToPt(const float *p,const float *plane)
+{
+	float x = p[0];
+	float y = p[1];
+	float z = p[2];
+	float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3];
+	return d;
+}
+
+
+static void intersect(const float *p1,const float *p2,float *split,const float *plane)
+{
+
+  float dp1 = DistToPt(p1,plane);
+
+  float dir[3];
+
+  dir[0] = p2[0] - p1[0];
+  dir[1] = p2[1] - p1[1];
+  dir[2] = p2[2] - p1[2];
+
+  float dot1 = dir[0]*plane[0] + dir[1]*plane[1] + dir[2]*plane[2];
+  float dot2 = dp1 - plane[3];
+
+  float    t = -(plane[3] + dot2 ) / dot1;
+
+  split[0] = (dir[0]*t)+p1[0];
+  split[1] = (dir[1]*t)+p1[1];
+  split[2] = (dir[2]*t)+p1[2];
+}
+
+
+class CTri
+{
+public:
+	CTri(void) { };
+
+  CTri(const float *p1,const float *p2,const float *p3,unsigned int i1,unsigned int i2,unsigned int i3)
+  {
+    mProcessed = 0;
+    mI1 = i1;
+    mI2 = i2;
+    mI3 = i3;
+
+  	mP1.Set(p1);
+  	mP2.Set(p2);
+  	mP3.Set(p3);
+
+  	mPlaneD = mNormal.ComputePlane(mP1,mP2,mP3);
+	}
+
+  float Facing(const CTri &t)
+  {
+		float d = mNormal.Dot(t.mNormal);
+		return d;
+  }
+
+  // clip this line segment against this triangle.
+  bool clip(const Vector3d &start,Vector3d &end) const
+  {
+    Vector3d sect;
+
+    bool hit = lineIntersectsTriangle(start.Ptr(), end.Ptr(), mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), sect.Ptr() );
+
+    if ( hit )
+    {
+      end = sect;
+    }
+    return hit;
+  }
+
+	bool Concave(const Vector3d &p,float &distance,Vector3d &n) const
+	{
+		n.NearestPointInTriangle(p,mP1,mP2,mP3);
+		distance = p.Distance(n);
+		return true;
+	}
+
+	void addTri(unsigned int *indices,unsigned int i1,unsigned int i2,unsigned int i3,unsigned int &tcount) const
+	{
+		indices[tcount*3+0] = i1;
+		indices[tcount*3+1] = i2;
+		indices[tcount*3+2] = i3;
+		tcount++;
+	}
+
+	float getVolume(ConvexDecompInterface *callback) const
+	{
+		unsigned int indices[8*3];
+
+
+    unsigned int tcount = 0;
+
+    addTri(indices,0,1,2,tcount);
+    addTri(indices,3,4,5,tcount);
+
+    addTri(indices,0,3,4,tcount);
+    addTri(indices,0,4,1,tcount);
+
+    addTri(indices,1,4,5,tcount);
+    addTri(indices,1,5,2,tcount);
+
+    addTri(indices,0,3,5,tcount);
+    addTri(indices,0,5,2,tcount);
+
+    const float *vertices = mP1.Ptr();
+
+		if ( callback )
+		{
+			unsigned int color = getDebugColor();
+
+#if 0
+  		Vector3d d1 = mNear1;
+  		Vector3d d2 = mNear2;
+	  	Vector3d d3 = mNear3;
+
+  		callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
+  		callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00);
+  		callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00);
+  		callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000);
+  		callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000);
+  		callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000);
+
+  		callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(),  d1.Ptr(),0x00FF00);
+  		callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(),  d2.Ptr(),0x00FF00);
+  		callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(),  d3.Ptr(),0x00FF00);
+
+#else
+			for (unsigned int i=0; i<tcount; i++)
+			{
+				unsigned int i1 = indices[i*3+0];
+				unsigned int i2 = indices[i*3+1];
+				unsigned int i3 = indices[i*3+2];
+
+				const float *p1 = &vertices[ i1*3 ];
+				const float *p2 = &vertices[ i2*3 ];
+				const float *p3 = &vertices[ i3*3 ];
+
+				callback->ConvexDebugTri(p1,p2,p3,color);
+
+			}
+#endif
+		}
+
+		float v = computeMeshVolume(mP1.Ptr(), tcount, indices );
+
+		return v;
+
+	}
+
+	float raySect(const Vector3d &p,const Vector3d &dir,Vector3d &sect) const
+	{
+		float plane[4];
+
+    plane[0] = mNormal.x;
+    plane[1] = mNormal.y;
+    plane[2] = mNormal.z;
+    plane[3] = mPlaneD;
+
+		Vector3d dest = p+dir*100000;
+
+    intersect( p.Ptr(), dest.Ptr(), sect.Ptr(), plane );
+
+    return sect.Distance(p); // return the intersection distance.
+
+	}
+
+  float planeDistance(const Vector3d &p) const
+  {
+		float plane[4];
+
+    plane[0] = mNormal.x;
+    plane[1] = mNormal.y;
+    plane[2] = mNormal.z;
+    plane[3] = mPlaneD;
+
+		return DistToPt( p.Ptr(), plane );
+
+  }
+
+	bool samePlane(const CTri &t) const
+	{
+		const float THRESH = 0.001f;
+    float dd = fabsf( t.mPlaneD - mPlaneD );
+    if ( dd > THRESH ) return false;
+    dd = fabsf( t.mNormal.x - mNormal.x );
+    if ( dd > THRESH ) return false;
+    dd = fabsf( t.mNormal.y - mNormal.y );
+    if ( dd > THRESH ) return false;
+    dd = fabsf( t.mNormal.z - mNormal.z );
+    if ( dd > THRESH ) return false;
+    return true;
+	}
+
+	bool hasIndex(unsigned int i) const
+	{
+		if ( i == mI1 || i == mI2 || i == mI3 ) return true;
+		return false;
+	}
+
+  bool sharesEdge(const CTri &t) const
+  {
+    bool ret = false;
+    unsigned int count = 0;
+
+		if ( t.hasIndex(mI1) ) count++;
+	  if ( t.hasIndex(mI2) ) count++;
+		if ( t.hasIndex(mI3) ) count++;
+
+    if ( count >= 2 ) ret = true;
+
+    return ret;
+  }
+
+  void debug(unsigned int color,ConvexDecompInterface *callback)
+  {
+    callback->ConvexDebugTri( mP1.Ptr(), mP2.Ptr(), mP3.Ptr(), color );
+    callback->ConvexDebugTri( mP1.Ptr(), mP1.Ptr(), mNear1.Ptr(), 0xFF0000 );
+    callback->ConvexDebugTri( mP2.Ptr(), mP2.Ptr(), mNear2.Ptr(), 0xFF0000 );
+    callback->ConvexDebugTri( mP2.Ptr(), mP3.Ptr(), mNear3.Ptr(), 0xFF0000 );
+    callback->ConvexDebugPoint( mNear1.Ptr(), 0.01f, 0xFF0000 );
+    callback->ConvexDebugPoint( mNear2.Ptr(), 0.01f, 0xFF0000 );
+    callback->ConvexDebugPoint( mNear3.Ptr(), 0.01f, 0xFF0000 );
+  }
+
+  float area(void)
+  {
+		float a = mConcavity*mP1.Area(mP2,mP3);
+    return a;
+  }
+
+  void addWeighted(WpointVector &list,ConvexDecompInterface *callback)
+  {
+
+    Wpoint p1(mP1,mC1);
+    Wpoint p2(mP2,mC2);
+    Wpoint p3(mP3,mC3);
+
+		Vector3d d1 = mNear1 - mP1;
+		Vector3d d2 = mNear2 - mP2;
+		Vector3d d3 = mNear3 - mP3;
+
+		d1*=WSCALE;
+		d2*=WSCALE;
+		d3*=WSCALE;
+
+		d1 = d1 + mP1;
+		d2 = d2 + mP2;
+ 	  d3 = d3 + mP3;
+
+    Wpoint p4(d1,mC1);
+    Wpoint p5(d2,mC2);
+    Wpoint p6(d3,mC3);
+
+    list.push_back(p1);
+    list.push_back(p2);
+    list.push_back(p3);
+
+    list.push_back(p4);
+    list.push_back(p5);
+    list.push_back(p6);
+
+#if 0
+		callback->ConvexDebugPoint(mP1.Ptr(),0.01f,0x00FF00);
+		callback->ConvexDebugPoint(mP2.Ptr(),0.01f,0x00FF00);
+		callback->ConvexDebugPoint(mP3.Ptr(),0.01f,0x00FF00);
+		callback->ConvexDebugPoint(d1.Ptr(),0.01f,0xFF0000);
+		callback->ConvexDebugPoint(d2.Ptr(),0.01f,0xFF0000);
+		callback->ConvexDebugPoint(d3.Ptr(),0.01f,0xFF0000);
+
+		callback->ConvexDebugTri(mP1.Ptr(), d1.Ptr(),  d1.Ptr(),0x00FF00);
+		callback->ConvexDebugTri(mP2.Ptr(), d2.Ptr(),  d2.Ptr(),0x00FF00);
+		callback->ConvexDebugTri(mP3.Ptr(), d3.Ptr(),  d3.Ptr(),0x00FF00);
+
+		Vector3d np1 = mP1 + mNormal*0.05f;
+		Vector3d np2 = mP2 + mNormal*0.05f;
+		Vector3d np3 = mP3 + mNormal*0.05f;
+
+		callback->ConvexDebugTri(mP1.Ptr(), np1.Ptr(), np1.Ptr(), 0xFF00FF );
+		callback->ConvexDebugTri(mP2.Ptr(), np2.Ptr(), np2.Ptr(), 0xFF00FF );
+		callback->ConvexDebugTri(mP3.Ptr(), np3.Ptr(), np3.Ptr(), 0xFF00FF );
+
+		callback->ConvexDebugPoint( np1.Ptr(), 0.01F, 0XFF00FF );
+		callback->ConvexDebugPoint( np2.Ptr(), 0.01F, 0XFF00FF );
+		callback->ConvexDebugPoint( np3.Ptr(), 0.01F, 0XFF00FF );
+
+#endif
+
+
+
+  }
+
+  Vector3d	mP1;
+  Vector3d	mP2;
+  Vector3d	mP3;
+  Vector3d mNear1;
+  Vector3d mNear2;
+  Vector3d mNear3;
+  Vector3d mNormal;
+  float           mPlaneD;
+  float           mConcavity;
+  float           mC1;
+  float           mC2;
+  float           mC3;
+  unsigned int    mI1;
+  unsigned int    mI2;
+  unsigned int    mI3;
+  int             mProcessed; // already been added...
+};
+
+typedef std::vector< CTri > CTriVector;
+
+bool featureMatch(CTri &m,const CTriVector &tris,ConvexDecompInterface *callback,const CTriVector &input_mesh)
+{
+
+  bool ret = false;
+
+  float neardot = 0.707f;
+
+  m.mConcavity = 0;
+
+	//gLog->Display("*********** FEATURE MATCH *************\r\n");
+	//gLog->Display("Plane: %0.4f,%0.4f,%0.4f   %0.4f\r\n", m.mNormal.x, m.mNormal.y, m.mNormal.z, m.mPlaneD );
+	//gLog->Display("*********************************************\r\n");
+
+	CTriVector::const_iterator i;
+
+	CTri nearest;
+
+
+	for (i=tris.begin(); i!=tris.end(); ++i)
+	{
+		const CTri &t = (*i);
+
+
+  	//gLog->Display("   HullPlane: %0.4f,%0.4f,%0.4f   %0.4f\r\n", t.mNormal.x, t.mNormal.y, t.mNormal.z, t.mPlaneD );
+
+		if ( t.samePlane(m) )
+		{
+			//gLog->Display("*** PLANE MATCH!!!\r\n");
+			ret = false;
+			break;
+		}
+
+	  float dot = t.mNormal.Dot(m.mNormal);
+
+	  if ( dot > neardot )
+	  {
+
+      float d1 = t.planeDistance( m.mP1 );
+      float d2 = t.planeDistance( m.mP2 );
+      float d3 = t.planeDistance( m.mP3 );
+
+      if ( d1 > 0.001f || d2 > 0.001f || d3 > 0.001f ) // can't be near coplaner!
+      {
+
+  	  	neardot = dot;
+
+        Vector3d n1,n2,n3;
+
+        t.raySect( m.mP1, m.mNormal, m.mNear1 );
+        t.raySect( m.mP2, m.mNormal, m.mNear2 );
+        t.raySect( m.mP3, m.mNormal, m.mNear3 );
+
+				nearest = t;
+
+	  		ret = true;
+		  }
+
+	  }
+	}
+
+	if ( ret )
+	{
+    if ( 0 )
+    {
+      CTriVector::const_iterator i;
+      for (i=input_mesh.begin(); i!=input_mesh.end(); ++i)
+      {
+        const CTri &c = (*i);
+        if ( c.mI1 != m.mI1 && c.mI2 != m.mI2 && c.mI3 != m.mI3 )
+        {
+  			  c.clip( m.mP1, m.mNear1 );
+				  c.clip( m.mP2, m.mNear2 );
+				  c.clip( m.mP3, m.mNear3 );
+        }
+      }
+    }
+
+	  //gLog->Display("*********************************************\r\n");
+  	//gLog->Display("   HullPlaneNearest: %0.4f,%0.4f,%0.4f   %0.4f\r\n", nearest.mNormal.x, nearest.mNormal.y, nearest.mNormal.z, nearest.mPlaneD );
+
+		m.mC1 = m.mP1.Distance( m.mNear1 );
+		m.mC2 = m.mP2.Distance( m.mNear2 );
+		m.mC3 = m.mP3.Distance( m.mNear3 );
+
+		m.mConcavity = m.mC1;
+
+		if ( m.mC2 > m.mConcavity ) m.mConcavity = m.mC2;
+		if ( m.mC3 > m.mConcavity ) m.mConcavity = m.mC3;
+
+    #if 0
+		callback->ConvexDebugTri( m.mP1.Ptr(), m.mP2.Ptr(), m.mP3.Ptr(), 0x00FF00 );
+		callback->ConvexDebugTri( m.mNear1.Ptr(), m.mNear2.Ptr(), m.mNear3.Ptr(), 0xFF0000 );
+
+		callback->ConvexDebugTri( m.mP1.Ptr(), m.mP1.Ptr(), m.mNear1.Ptr(), 0xFFFF00 );
+		callback->ConvexDebugTri( m.mP2.Ptr(), m.mP2.Ptr(), m.mNear2.Ptr(), 0xFFFF00 );
+		callback->ConvexDebugTri( m.mP3.Ptr(), m.mP3.Ptr(), m.mNear3.Ptr(), 0xFFFF00 );
+    #endif
+
+	}
+	else
+	{
+		//gLog->Display("No match\r\n");
+	}
+
+	//gLog->Display("*********************************************\r\n");
+	return ret;
+}
+
+bool isFeatureTri(CTri &t,CTriVector &flist,float fc,ConvexDecompInterface *callback,unsigned int color)
+{
+  bool ret = false;
+
+  if ( t.mProcessed == 0 ) // if not already processed
+  {
+
+    float c = t.mConcavity / fc; // must be within 80% of the concavity of the parent.
+
+    if ( c > 0.85f )
+    {
+      // see if this triangle is a 'feature' triangle.  Meaning it shares an
+      // edge with any existing feature triangle and is within roughly the same
+      // concavity of the parent.
+			if ( flist.size() )
+			{
+			  CTriVector::iterator i;
+			  for (i=flist.begin(); i!=flist.end(); ++i)
+			  {
+				  CTri &ftri = (*i);
+				  if ( ftri.sharesEdge(t) )
+				  {
+					  t.mProcessed = 2; // it is now part of a feature.
+					  flist.push_back(t); // add it to the feature list.
+//					  callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
+					  ret = true;
+					  break;
+          }
+				}
+			}
+			else
+			{
+				t.mProcessed = 2;
+				flist.push_back(t); // add it to the feature list.
+//				callback->ConvexDebugTri( t.mP1.Ptr(), t.mP2.Ptr(),t.mP3.Ptr(), color );
+				ret = true;
+			}
+    }
+    else
+    {
+      t.mProcessed = 1; // eliminated for this feature, but might be valid for the next one..
+    }
+
+  }
+  return ret;
+}
+
+float computeConcavity(unsigned int vcount,
+                       const float *vertices,
+                       unsigned int tcount,
+                       const unsigned int *indices,
+                       ConvexDecompInterface *callback,
+                       float *plane,      // plane equation to split on
+                       float &volume)
+{
+
+
+	float cret = 0;
+	volume = 1;
+
+	HullResult  result;
+  HullLibrary hl;
+  HullDesc    desc;
+
+	desc.mMaxFaces = 256;
+	desc.mMaxVertices = 256;
+	desc.SetHullFlag(QF_TRIANGLES);
+
+
+  desc.mVcount       = vcount;
+  desc.mVertices     = vertices;
+  desc.mVertexStride = sizeof(float)*3;
+
+  HullError ret = hl.CreateConvexHull(desc,result);
+
+  if ( ret == QE_OK )
+  {
+#if 0
+		float bmin[3];
+		float bmax[3];
+
+		float dx = bmax[0] - bmin[0];
+		float dy = bmax[1] - bmin[1];
+		float dz = bmax[2] - bmin[2];
+
+		Vector3d center;
+
+		center.x = bmin[0] + dx*0.5f;
+		center.y = bmin[1] + dy*0.5f;
+		center.z = bmin[2] + dz*0.5f;
+#endif
+
+		volume = computeMeshVolume2( result.mOutputVertices, result.mNumFaces, result.mIndices );
+
+#if 1
+		// ok..now..for each triangle on the original mesh..
+		// we extrude the points to the nearest point on the hull.
+		const unsigned int *source = result.mIndices;
+
+		CTriVector tris;
+
+    for (unsigned int i=0; i<result.mNumFaces; i++)
+    {
+    	unsigned int i1 = *source++;
+    	unsigned int i2 = *source++;
+    	unsigned int i3 = *source++;
+
+    	const float *p1 = &result.mOutputVertices[i1*3];
+    	const float *p2 = &result.mOutputVertices[i2*3];
+    	const float *p3 = &result.mOutputVertices[i3*3];
+
+//			callback->ConvexDebugTri(p1,p2,p3,0xFFFFFF);
+
+			CTri t(p1,p2,p3,i1,i2,i3); //
+			tris.push_back(t);
+		}
+
+    // we have not pre-computed the plane equation for each triangle in the convex hull..
+
+		float totalVolume = 0;
+
+		CTriVector ftris; // 'feature' triangles.
+
+		const unsigned int *src = indices;
+
+
+    float maxc=0;
+
+
+		if ( 1 )
+		{
+      CTriVector input_mesh;
+      if ( 1 )
+      {
+		    const unsigned int *src = indices;
+  			for (unsigned int i=0; i<tcount; i++)
+  			{
+
+      		unsigned int i1 = *src++;
+      		unsigned int i2 = *src++;
+      		unsigned int i3 = *src++;
+
+      		const float *p1 = &vertices[i1*3];
+      		const float *p2 = &vertices[i2*3];
+      		const float *p3 = &vertices[i3*3];
+
+   				CTri t(p1,p2,p3,i1,i2,i3);
+          input_mesh.push_back(t);
+        }
+      }
+
+      CTri  maxctri;
+
+			for (unsigned int i=0; i<tcount; i++)
+			{
+
+    		unsigned int i1 = *src++;
+    		unsigned int i2 = *src++;
+    		unsigned int i3 = *src++;
+
+    		const float *p1 = &vertices[i1*3];
+    		const float *p2 = &vertices[i2*3];
+    		const float *p3 = &vertices[i3*3];
+
+ 				CTri t(p1,p2,p3,i1,i2,i3);
+
+				featureMatch(t, tris, callback, input_mesh );
+
+				if ( t.mConcavity > CONCAVE_THRESH )
+				{
+
+          if ( t.mConcavity > maxc )
+          {
+            maxc = t.mConcavity;
+            maxctri = t;
+          }
+
+  				float v = t.getVolume(0);
+  				totalVolume+=v;
+   				ftris.push_back(t);
+   			}
+
+			}
+		}
+
+	  if ( ftris.size()  && 0 )
+	  {
+
+      // ok..now we extract the triangles which form the maximum concavity.
+      CTriVector major_feature;
+      float maxarea = 0;
+
+      while ( maxc > CONCAVE_THRESH  )
+      {
+
+        unsigned int color = getDebugColor();  //
+
+        CTriVector flist;
+
+        bool found;
+
+        float totalarea = 0;
+
+        do
+        {
+          found = false;
+          CTriVector::iterator i;
+          for (i=ftris.begin(); i!=ftris.end(); ++i)
+          {
+            CTri &t = (*i);
+            if ( isFeatureTri(t,flist,maxc,callback,color) )
+            {
+              found = true;
+              totalarea+=t.area();
+            }
+  				}
+        } while ( found );
+
+
+        if ( totalarea > maxarea )
+        {
+          major_feature = flist;
+          maxarea = totalarea;
+        }
+
+        maxc = 0;
+
+        for (unsigned int i=0; i<ftris.size(); i++)
+        {
+          CTri &t = ftris[i];
+          if ( t.mProcessed != 2 )
+          {
+            t.mProcessed = 0;
+            if ( t.mConcavity > maxc )
+            {
+              maxc = t.mConcavity;
+            }
+          }
+        }
+      }
+
+      unsigned int color = getDebugColor();
+
+      WpointVector list;
+      for (unsigned int i=0; i<major_feature.size(); ++i)
+      {
+        major_feature[i].addWeighted(list,callback);
+        major_feature[i].debug(color,callback);
+      }
+
+      getBestFitPlane( list.size(), &list[0].mPoint.x, sizeof(Wpoint), &list[0].mWeight, sizeof(Wpoint), plane );
+
+	  	computeSplitPlane( vcount, vertices, tcount, indices, callback, plane );
+
+
+		}
+	  else
+	  {
+	  	computeSplitPlane( vcount, vertices, tcount, indices, callback, plane );
+	  }
+#endif
+
+		cret = totalVolume;
+
+	  hl.ReleaseResult(result);
+  }
+
+
+	return cret;
+}
+
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/concavity.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/concavity.h
new file mode 100644
index 0000000..012f8a3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/concavity.h
@@ -0,0 +1,60 @@
+#ifndef COMPUTE_CONCAVITY_H
+
+#define COMPUTE_CONCAVITY_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+
+namespace ConvexDecomposition
+{
+
+class ConvexDecompInterface;
+
+// compute's how 'concave' this object is and returns the total volume of the
+// convex hull as well as the volume of the 'concavity' which was found.
+float computeConcavity(unsigned int vcount,
+                       const float *vertices,
+                       unsigned int tcount,
+                       const unsigned int *indices,
+                       ConvexDecompInterface *callback,
+                       float *plane,
+                       float &volume);
+
+
+}
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/fitsphere.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/fitsphere.cpp
new file mode 100644
index 0000000..53e6e6d
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/fitsphere.cpp
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+#include "fitsphere.h"
+
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+/*
+An Efficient Bounding Sphere
+by Jack Ritter
+from "Graphics Gems", Academic Press, 1990
+*/
+
+/* Routine to calculate tight bounding sphere over    */
+/* a set of points in 3D */
+/* This contains the routine find_bounding_sphere(), */
+/* the struct definition, and the globals used for parameters. */
+/* The abs() of all coordinates must be < BIGNUMBER */
+/* Code written by Jack Ritter and Lyle Rains. */
+
+#define BIGNUMBER 100000000.0  		/* hundred million */
+
+static inline void Set(float *n,float x,float y,float z)
+{
+	n[0] = x;
+	n[1] = y;
+	n[2] = z;
+}
+
+static inline void Copy(float *dest,const float *source)
+{
+	dest[0] = source[0];
+	dest[1] = source[1];
+	dest[2] = source[2];
+}
+
+float computeBoundingSphere(unsigned int vcount,const float *points,float *center)
+{
+
+  float mRadius;
+  float mRadius2;
+
+	float xmin[3];
+	float xmax[3];
+	float ymin[3];
+	float ymax[3];
+	float zmin[3];
+	float zmax[3];
+	float dia1[3];
+	float dia2[3];
+
+  /* FIRST PASS: find 6 minima/maxima points */
+  Set(xmin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
+  Set(xmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
+  Set(ymin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
+  Set(ymax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
+  Set(zmin,BIGNUMBER,BIGNUMBER,BIGNUMBER);
+  Set(zmax,-BIGNUMBER,-BIGNUMBER,-BIGNUMBER);
+
+  for (unsigned i=0; i<vcount; i++)
+	{
+		const float *caller_p = &points[i*3];
+
+   	if (caller_p[0]<xmin[0])
+  	  Copy(xmin,caller_p); /* New xminimum point */
+  	if (caller_p[0]>xmax[0])
+  	  Copy(xmax,caller_p);
+  	if (caller_p[1]<ymin[1])
+  	  Copy(ymin,caller_p);
+  	if (caller_p[1]>ymax[1])
+  	  Copy(ymax,caller_p);
+  	if (caller_p[2]<zmin[2])
+  	  Copy(zmin,caller_p);
+  	if (caller_p[2]>zmax[2])
+  	  Copy(zmax,caller_p);
+	}
+
+  /* Set xspan = distance between the 2 points xmin & xmax (squared) */
+  float dx = xmax[0] - xmin[0];
+  float dy = xmax[1] - xmin[1];
+  float dz = xmax[2] - xmin[2];
+  float xspan = dx*dx + dy*dy + dz*dz;
+
+  /* Same for y & z spans */
+  dx = ymax[0] - ymin[0];
+  dy = ymax[1] - ymin[1];
+  dz = ymax[2] - ymin[2];
+  float yspan = dx*dx + dy*dy + dz*dz;
+
+  dx = zmax[0] - zmin[0];
+  dy = zmax[1] - zmin[1];
+  dz = zmax[2] - zmin[2];
+  float zspan = dx*dx + dy*dy + dz*dz;
+
+  /* Set points dia1 & dia2 to the maximally separated pair */
+  Copy(dia1,xmin);
+  Copy(dia2,xmax); /* assume xspan biggest */
+  float maxspan = xspan;
+
+  if (yspan>maxspan)
+	{
+	  maxspan = yspan;
+  	Copy(dia1,ymin);
+  	Copy(dia2,ymax);
+	}
+
+  if (zspan>maxspan)
+	{
+	  Copy(dia1,zmin);
+	  Copy(dia2,zmax);
+	}
+
+
+  /* dia1,dia2 is a diameter of initial sphere */
+  /* calc initial center */
+  center[0] = (dia1[0]+dia2[0])*0.5f;
+  center[1] = (dia1[1]+dia2[1])*0.5f;
+  center[2] = (dia1[2]+dia2[2])*0.5f;
+
+  /* calculate initial radius**2 and radius */
+
+  dx = dia2[0]-center[0]; /* x component of radius vector */
+  dy = dia2[1]-center[1]; /* y component of radius vector */
+  dz = dia2[2]-center[2]; /* z component of radius vector */
+
+  mRadius2 = dx*dx + dy*dy + dz*dz;
+  mRadius = float(sqrt(mRadius2));
+
+  /* SECOND PASS: increment current sphere */
+
+	if ( 1 )
+	{
+		for (unsigned i=0; i<vcount; i++)
+		{
+			const float *caller_p = &points[i*3];
+
+  		dx = caller_p[0]-center[0];
+			dy = caller_p[1]-center[1];
+  		dz = caller_p[2]-center[2];
+
+			float old_to_p_sq = dx*dx + dy*dy + dz*dz;
+
+  		if (old_to_p_sq > mRadius2) 	/* do r**2 test first */
+			{ 	/* this point is outside of current sphere */
+	  		float old_to_p = float(sqrt(old_to_p_sq));
+				/* calc radius of new sphere */
+  			mRadius = (mRadius + old_to_p) * 0.5f;
+	  		mRadius2 = mRadius*mRadius; 	/* for next r**2 compare */
+  			float old_to_new = old_to_p - mRadius;
+
+	  		/* calc center of new sphere */
+
+				float recip = 1.0f /old_to_p;
+
+  			float cx = (mRadius*center[0] + old_to_new*caller_p[0]) * recip;
+	  		float cy = (mRadius*center[1] + old_to_new*caller_p[1]) * recip;
+				float cz = (mRadius*center[2] + old_to_new*caller_p[2]) * recip;
+
+				Set(center,cx,cy,cz);
+			}
+		}
+	}
+
+  return mRadius;
+}
+
+
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/fitsphere.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/fitsphere.h
new file mode 100644
index 0000000..cd4a565
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/fitsphere.h
@@ -0,0 +1,43 @@
+#ifndef FIT_SPHERE_H
+
+#define FIT_SPHERE_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+
+float computeBoundingSphere(unsigned int vcount,const float *points,float *center);
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/float_math.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/float_math.cpp
new file mode 100644
index 0000000..38c699b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/float_math.cpp
@@ -0,0 +1,257 @@
+#include "float_math.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+void fm_inverseRT(const float *matrix,const float *pos,float *t) // inverse rotate translate the point.
+{
+
+	float _x = pos[0] - matrix[3*4+0];
+	float _y = pos[1] - matrix[3*4+1];
+	float _z = pos[2] - matrix[3*4+2];
+
+	// Multiply inverse-translated source vector by inverted rotation transform
+
+	t[0] = (matrix[0*4+0] * _x) + (matrix[0*4+1] * _y) + (matrix[0*4+2] * _z);
+	t[1] = (matrix[1*4+0] * _x) + (matrix[1*4+1] * _y) + (matrix[1*4+2] * _z);
+	t[2] = (matrix[2*4+0] * _x) + (matrix[2*4+1] * _y) + (matrix[2*4+2] * _z);
+
+}
+
+
+void fm_identity(float *matrix) // set 4x4 matrix to identity.
+{
+	matrix[0*4+0] = 1;
+	matrix[1*4+1] = 1;
+	matrix[2*4+2] = 1;
+	matrix[3*4+3] = 1;
+
+	matrix[1*4+0] = 0;
+	matrix[2*4+0] = 0;
+	matrix[3*4+0] = 0;
+
+	matrix[0*4+1] = 0;
+	matrix[2*4+1] = 0;
+	matrix[3*4+1] = 0;
+
+	matrix[0*4+2] = 0;
+	matrix[1*4+2] = 0;
+	matrix[3*4+2] = 0;
+
+	matrix[0*4+3] = 0;
+	matrix[1*4+3] = 0;
+	matrix[2*4+3] = 0;
+
+}
+
+void fm_eulerMatrix(float ax,float ay,float az,float *matrix) // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+{
+  float quat[4];
+  fm_eulerToQuat(ax,ay,az,quat);
+  fm_quatToMatrix(quat,matrix);
+}
+
+void fm_getAABB(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax)
+{
+
+  const unsigned char *source = (const unsigned char *) points;
+
+	bmin[0] = points[0];
+	bmin[1] = points[1];
+	bmin[2] = points[2];
+
+	bmax[0] = points[0];
+	bmax[1] = points[1];
+	bmax[2] = points[2];
+
+
+  for (unsigned int i=1; i<vcount; i++)
+  {
+  	source+=pstride;
+  	const float *p = (const float *) source;
+
+  	if ( p[0] < bmin[0] ) bmin[0] = p[0];
+  	if ( p[1] < bmin[1] ) bmin[1] = p[1];
+  	if ( p[2] < bmin[2] ) bmin[2] = p[2];
+
+		if ( p[0] > bmax[0] ) bmax[0] = p[0];
+		if ( p[1] > bmax[1] ) bmax[1] = p[1];
+		if ( p[2] > bmax[2] ) bmax[2] = p[2];
+
+  }
+}
+
+
+void fm_eulerToQuat(float roll,float pitch,float yaw,float *quat) // convert euler angles to quaternion.
+{
+	roll  *= 0.5f;
+	pitch *= 0.5f;
+	yaw   *= 0.5f;
+
+	float cr = cosf(roll);
+	float cp = cosf(pitch);
+	float cy = cosf(yaw);
+
+	float sr = sinf(roll);
+	float sp = sinf(pitch);
+	float sy = sinf(yaw);
+
+	float cpcy = cp * cy;
+	float spsy = sp * sy;
+	float spcy = sp * cy;
+	float cpsy = cp * sy;
+
+	quat[0]   = ( sr * cpcy - cr * spsy);
+	quat[1]   = ( cr * spcy + sr * cpsy);
+	quat[2]   = ( cr * cpsy - sr * spcy);
+	quat[3]   = cr * cpcy + sr * spsy;
+}
+
+void fm_quatToMatrix(const float *quat,float *matrix) // convert quaterinion rotation to matrix, zeros out the translation component.
+{
+
+	float xx = quat[0]*quat[0];
+	float yy = quat[1]*quat[1];
+	float zz = quat[2]*quat[2];
+	float xy = quat[0]*quat[1];
+	float xz = quat[0]*quat[2];
+	float yz = quat[1]*quat[2];
+	float wx = quat[3]*quat[0];
+	float wy = quat[3]*quat[1];
+	float wz = quat[3]*quat[2];
+
+	matrix[0*4+0] = 1 - 2 * ( yy + zz );
+	matrix[1*4+0] =     2 * ( xy - wz );
+	matrix[2*4+0] =     2 * ( xz + wy );
+
+	matrix[0*4+1] =     2 * ( xy + wz );
+	matrix[1*4+1] = 1 - 2 * ( xx + zz );
+	matrix[2*4+1] =     2 * ( yz - wx );
+
+	matrix[0*4+2] =     2 * ( xz - wy );
+	matrix[1*4+2] =     2 * ( yz + wx );
+	matrix[2*4+2] = 1 - 2 * ( xx + yy );
+
+	matrix[3*4+0] = matrix[3*4+1] = matrix[3*4+2] = 0.0f;
+	matrix[0*4+3] = matrix[1*4+3] = matrix[2*4+3] = 0.0f;
+	matrix[3*4+3] = 1.0f;
+
+}
+
+
+void fm_quatRotate(const float *quat,const float *v,float *r) // rotate a vector directly by a quaternion.
+{
+  float left[4];
+
+	left[0] =   quat[3]*v[0] + quat[1]*v[2] - v[1]*quat[2];
+	left[1] =   quat[3]*v[1] + quat[2]*v[0] - v[2]*quat[0];
+	left[2] =   quat[3]*v[2] + quat[0]*v[1] - v[0]*quat[1];
+	left[3] = - quat[0]*v[0] - quat[1]*v[1] - quat[2]*v[2];
+
+	r[0] = (left[3]*-quat[0]) + (quat[3]*left[0]) + (left[1]*-quat[2]) - (-quat[1]*left[2]);
+	r[1] = (left[3]*-quat[1]) + (quat[3]*left[1]) + (left[2]*-quat[0]) - (-quat[2]*left[0]);
+	r[2] = (left[3]*-quat[2]) + (quat[3]*left[2]) + (left[0]*-quat[1]) - (-quat[0]*left[1]);
+
+}
+
+
+void fm_getTranslation(const float *matrix,float *t)
+{
+	t[0] = matrix[3*4+0];
+	t[1] = matrix[3*4+1];
+	t[2] = matrix[3*4+2];
+}
+
+void fm_matrixToQuat(const float *matrix,float *quat) // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
+{
+
+	float tr = matrix[0*4+0] + matrix[1*4+1] + matrix[2*4+2];
+
+	// check the diagonal
+
+	if (tr > 0.0f )
+	{
+		float s = (float) sqrt ( (double) (tr + 1.0f) );
+		quat[3] = s * 0.5f;
+		s = 0.5f / s;
+		quat[0] = (matrix[1*4+2] - matrix[2*4+1]) * s;
+		quat[1] = (matrix[2*4+0] - matrix[0*4+2]) * s;
+		quat[2] = (matrix[0*4+1] - matrix[1*4+0]) * s;
+
+	}
+	else
+	{
+		// diagonal is negative
+		int nxt[3] = {1, 2, 0};
+		float  qa[4];
+
+		int i = 0;
+
+		if (matrix[1*4+1] > matrix[0*4+0]) i = 1;
+		if (matrix[2*4+2] > matrix[i*4+i]) i = 2;
+
+		int j = nxt[i];
+		int k = nxt[j];
+
+		float s = sqrtf ( ((matrix[i*4+i] - (matrix[j*4+j] + matrix[k*4+k])) + 1.0f) );
+
+		qa[i] = s * 0.5f;
+
+		if (s != 0.0f ) s = 0.5f / s;
+
+		qa[3] = (matrix[j*4+k] - matrix[k*4+j]) * s;
+		qa[j] = (matrix[i*4+j] + matrix[j*4+i]) * s;
+		qa[k] = (matrix[i*4+k] + matrix[k*4+i]) * s;
+
+		quat[0] = qa[0];
+		quat[1] = qa[1];
+		quat[2] = qa[2];
+		quat[3] = qa[3];
+	}
+
+
+}
+
+
+float fm_sphereVolume(float radius) // return's the volume of a sphere of this radius (4/3 PI * R cubed )
+{
+	return (4.0f / 3.0f ) * FM_PI * radius * radius * radius;
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/float_math.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/float_math.h
new file mode 100644
index 0000000..e5d6b26
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/float_math.h
@@ -0,0 +1,72 @@
+#ifndef FLOAT_MATH_H
+
+#define FLOAT_MATH_H
+
+#ifdef WIN32
+	#pragma warning(disable : 4324) // disable padding warning
+	#pragma warning(disable : 4244) // disable padding warning
+	#pragma warning(disable : 4267) //  possible loss of data
+	#pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
+	#pragma warning(disable:4996) //Turn off warnings about deprecated C routines
+	#pragma warning(disable:4786) // Disable the "debug name too long" warning
+#endif
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+// a set of routines that last you do common 3d math
+// operations without any vector, matrix, or quaternion
+// classes or templates.
+//
+// a vector (or point) is a 'float *' to 3 floating point numbers.
+// a matrix is a 'float *' to an array of 16 floating point numbers representing a 4x4 transformation matrix compatible with D3D or OGL
+// a quaternion is a 'float *' to 4 floats representing a quaternion x,y,z,w
+
+const float FM_PI = 3.141592654f;
+const float FM_DEG_TO_RAD = ((2.0f * FM_PI) / 360.0f);
+const float FM_RAD_TO_DEG = (360.0f / (2.0f * FM_PI));
+
+void  fm_identity(float *matrix); // set 4x4 matrix to identity.
+void  fm_inverseRT(const float *matrix,const float *pos,float *t); // inverse rotate translate the point.
+void  fm_eulerMatrix(float ax,float ay,float az,float *matrix); // convert euler (in radians) to a dest 4x4 matrix (translation set to zero)
+void  fm_getAABB(unsigned int vcount,const float *points,unsigned int pstride,float *bmin,float *bmax);
+void  fm_eulerToQuat(float roll,float pitch,float yaw,float *quat); // convert euler angles to quaternion.
+void  fm_quatToMatrix(const float *quat,float *matrix); // convert quaterinion rotation to matrix, translation set to zero.
+void  fm_quatRotate(const float *quat,const float *v,float *r); // rotate a vector directly by a quaternion.
+void  fm_getTranslation(const float *matrix,float *t);
+void  fm_matrixToQuat(const float *matrix,float *quat); // convert the 3x3 portion of a 4x4 matrix into a quaterion as x,y,z,w
+float fm_sphereVolume(float radius); // return's the volume of a sphere of this radius (4/3 PI * R cubed )
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/meshvolume.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/meshvolume.cpp
new file mode 100644
index 0000000..b9dfa17
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/meshvolume.cpp
@@ -0,0 +1,128 @@
+#include "float_math.h"
+#include "meshvolume.h"
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+inline float det(const float *p1,const float *p2,const float *p3)
+{
+  return  p1[0]*p2[1]*p3[2] + p2[0]*p3[1]*p1[2] + p3[0]*p1[1]*p2[2] -p1[0]*p3[1]*p2[2] - p2[0]*p1[1]*p3[2] - p3[0]*p2[1]*p1[2];
+}
+
+float computeMeshVolume(const float *vertices,unsigned int tcount,const unsigned int *indices)
+{
+	float volume = 0;
+
+	for (unsigned int i=0; i<tcount; i++,indices+=3)
+	{
+
+		const float *p1 = &vertices[ indices[0]*3 ];
+		const float *p2 = &vertices[ indices[1]*3 ];
+		const float *p3 = &vertices[ indices[2]*3 ];
+
+		volume+=det(p1,p2,p3); // compute the volume of the tetrahedran relative to the origin.
+	}
+
+	volume*=(1.0f/6.0f);
+	if ( volume < 0 ) 
+		volume*=-1;
+	return volume;
+}
+
+
+inline void CrossProduct(const float *a,const float *b,float *cross)
+{
+	cross[0] = a[1]*b[2] - a[2]*b[1];
+	cross[1] = a[2]*b[0] - a[0]*b[2];
+	cross[2] = a[0]*b[1] - a[1]*b[0];
+}
+
+inline float DotProduct(const float *a,const float *b)
+{
+	return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+}
+
+inline float tetVolume(const float *p0,const float *p1,const float *p2,const float *p3)
+{
+	float a[3];
+	float b[3];
+	float c[3];
+
+  a[0] = p1[0] - p0[0];
+  a[1] = p1[1] - p0[1];
+  a[2] = p1[2] - p0[2];
+
+	b[0] = p2[0] - p0[0];
+	b[1] = p2[1] - p0[1];
+	b[2] = p2[2] - p0[2];
+
+  c[0] = p3[0] - p0[0];
+  c[1] = p3[1] - p0[1];
+  c[2] = p3[2] - p0[2];
+
+  float cross[3];
+
+  CrossProduct( b, c, cross );
+
+	float volume = DotProduct( a, cross );
+
+  if ( volume < 0 )
+   return -volume;
+
+  return volume;
+}
+
+inline float det(const float *p0,const float *p1,const float *p2,const float *p3)
+{
+  return  p1[0]*p2[1]*p3[2] + p2[0]*p3[1]*p1[2] + p3[0]*p1[1]*p2[2] -p1[0]*p3[1]*p2[2] - p2[0]*p1[1]*p3[2] - p3[0]*p2[1]*p1[2];
+}
+
+float computeMeshVolume2(const float *vertices,unsigned int tcount,const unsigned int *indices)
+{
+	float volume = 0;
+
+	const float *p0 = vertices;
+	for (unsigned int i=0; i<tcount; i++,indices+=3)
+	{
+
+		const float *p1 = &vertices[ indices[0]*3 ];
+		const float *p2 = &vertices[ indices[1]*3 ];
+		const float *p3 = &vertices[ indices[2]*3 ];
+
+		volume+=tetVolume(p0,p1,p2,p3); // compute the volume of the tetrahdren relative to the root vertice
+	}
+
+  return volume * (1.0f / 6.0f );
+}
+
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/meshvolume.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/meshvolume.h
new file mode 100644
index 0000000..4fc62c8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/meshvolume.h
@@ -0,0 +1,45 @@
+#ifndef MESH_VOLUME_H
+
+#define MESH_VOLUME_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+
+float computeMeshVolume(const float *vertices,unsigned int tcount,const unsigned int *indices);
+float computeMeshVolume2(const float *vertices,unsigned int tcount,const unsigned int *indices);
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/planetri.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/planetri.cpp
new file mode 100644
index 0000000..c631722
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/planetri.cpp
@@ -0,0 +1,238 @@
+#include "float_math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "planetri.h"
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+static inline float DistToPt(const float *p,const float *plane)
+{
+	float x = p[0];
+	float y = p[1];
+	float z = p[2];
+	float d = x*plane[0] + y*plane[1] + z*plane[2] + plane[3];
+	return d;
+}
+
+
+static PlaneTriResult getSidePlane(const float *p,const float *plane,float epsilon)
+{
+
+  float d = DistToPt(p,plane);
+
+  if ( (d+epsilon) > 0 )
+		return PTR_FRONT; // it is 'in front' within the provided epsilon value.
+
+  return PTR_BACK;
+}
+
+static void add(const float *p,float *dest,unsigned int tstride,unsigned int &pcount)
+{
+  char *d = (char *) dest;
+  d = d + pcount*tstride;
+  dest = (float *) d;
+  dest[0] = p[0];
+  dest[1] = p[1];
+  dest[2] = p[2];
+  pcount++;
+	assert( pcount <= 4 );
+}
+
+
+// assumes that the points are on opposite sides of the plane!
+static void intersect(const float *p1,const float *p2,float *split,const float *plane)
+{
+
+  float dp1 = DistToPt(p1,plane);
+
+  float dir[3];
+
+  dir[0] = p2[0] - p1[0];
+  dir[1] = p2[1] - p1[1];
+  dir[2] = p2[2] - p1[2];
+
+  float dot1 = dir[0]*plane[0] + dir[1]*plane[1] + dir[2]*plane[2];
+  float dot2 = dp1 - plane[3];
+
+  float    t = -(plane[3] + dot2 ) / dot1;
+
+  split[0] = (dir[0]*t)+p1[0];
+  split[1] = (dir[1]*t)+p1[1];
+  split[2] = (dir[2]*t)+p1[2];
+
+}
+
+PlaneTriResult planeTriIntersection(const float *plane,    // the plane equation in Ax+By+Cz+D format
+                                    const float *triangle, // the source triangle.
+                                    unsigned int tstride,  // stride in bytes of the input and output triangles
+                                    float        epsilon,  // the co-planer epsilon value.
+                                    float       *front,    // the triangle in front of the
+                                    unsigned int &fcount,  // number of vertices in the 'front' triangle
+                                    float       *back,     // the triangle in back of the plane
+                                    unsigned int &bcount) // the number of vertices in the 'back' triangle.
+{
+  fcount = 0;
+  bcount = 0;
+
+  const char *tsource = (const char *) triangle;
+
+  // get the three vertices of the triangle.
+  const float *p1     = (const float *) (tsource);
+  const float *p2     = (const float *) (tsource+tstride);
+  const float *p3     = (const float *) (tsource+tstride*2);
+
+
+  PlaneTriResult r1   = getSidePlane(p1,plane,epsilon); // compute the side of the plane each vertex is on
+  PlaneTriResult r2   = getSidePlane(p2,plane,epsilon);
+  PlaneTriResult r3   = getSidePlane(p3,plane,epsilon);
+
+  if ( r1 == r2 && r1 == r3 ) // if all three vertices are on the same side of the plane.
+  {
+    if ( r1 == PTR_FRONT ) // if all three are in front of the plane, then copy to the 'front' output triangle.
+    {
+      add(p1,front,tstride,fcount);
+      add(p2,front,tstride,fcount);
+      add(p3,front,tstride,fcount);
+    }
+    else
+    {
+      add(p1,back,tstride,bcount); // if all three are in 'abck' then copy to the 'back' output triangle.
+      add(p2,back,tstride,bcount);
+      add(p3,back,tstride,bcount);
+    }
+    return r1; // if all three points are on the same side of the plane return result
+  }
+
+  // ok.. we need to split the triangle at the plane.
+
+  // First test ray segment P1 to P2
+  if ( r1 == r2 ) // if these are both on the same side...
+  {
+    if ( r1 == PTR_FRONT )
+    {
+      add( p1, front, tstride, fcount );
+      add( p2, front, tstride, fcount );
+    }
+    else
+    {
+      add( p1, back, tstride, bcount );
+      add( p2, back, tstride, bcount );
+    }
+  }
+  else
+  {
+    float split[3]; // split the point
+    intersect(p1,p2,split,plane);
+
+    if ( r1 == PTR_FRONT )
+    {
+
+      add(p1, front, tstride, fcount );
+      add(split, front, tstride, fcount );
+
+      add(split, back, tstride, bcount );
+      add(p2, back, tstride, bcount );
+
+    }
+    else
+    {
+      add(p1, back, tstride, bcount );
+      add(split, back, tstride, bcount );
+
+      add(split, front, tstride, fcount );
+      add(p2, front, tstride, fcount );
+    }
+
+  }
+
+  // Next test ray segment P2 to P3
+  if ( r2 == r3 ) // if these are both on the same side...
+  {
+    if ( r3 == PTR_FRONT )
+    {
+      add( p3, front, tstride, fcount );
+    }
+    else
+    {
+      add( p3, back, tstride, bcount );
+    }
+  }
+  else
+  {
+    float split[3]; // split the point
+    intersect(p2,p3,split,plane);
+
+    if ( r3 == PTR_FRONT )
+    {
+      add(split, front, tstride, fcount );
+      add(split, back, tstride, bcount );
+
+      add(p3, front, tstride, fcount );
+    }
+    else
+    {
+      add(split, front, tstride, fcount );
+      add(split, back, tstride, bcount );
+
+      add(p3, back, tstride, bcount );
+    }
+  }
+
+  // Next test ray segment P3 to P1
+  if ( r3 != r1 ) // if these are both on the same side...
+  {
+    float split[3]; // split the point
+
+    intersect(p3,p1,split,plane);
+
+    if ( r1 == PTR_FRONT )
+    {
+      add(split, front, tstride, fcount );
+      add(split, back, tstride, bcount );
+    }
+    else
+    {
+      add(split, front, tstride, fcount );
+      add(split, back, tstride, bcount );
+    }
+  }
+
+
+
+  return PTR_SPLIT;
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/planetri.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/planetri.h
new file mode 100644
index 0000000..780ac85
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/planetri.h
@@ -0,0 +1,58 @@
+#ifndef PLANE_TRI_H
+
+#define PLANE_TRI_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+
+enum PlaneTriResult
+{
+  PTR_FRONT,
+  PTR_BACK,
+  PTR_SPLIT
+};
+
+PlaneTriResult planeTriIntersection(const float *plane,    // the plane equation in Ax+By+Cz+D format
+                                    const float *triangle, // the source position triangle.
+                                    unsigned int tstride,  // stride in bytes between vertices of the triangle.
+                                    float        epsilon,  // the co-planer epsilon value.
+                                    float       *front,    // the triangle in front of the
+                                    unsigned int &fcount,  // number of vertices in the 'front' triangle.
+                                    float       *back,      // the triangle in back of the plane
+                                    unsigned int &bcount);  // the number of vertices in the 'back' triangle.
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/raytri.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/raytri.cpp
new file mode 100644
index 0000000..83b076a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/raytri.cpp
@@ -0,0 +1,134 @@
+#include "float_math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <math.h>
+
+#include "raytri.h"
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+/* a = b - c */
+#define vector(a,b,c) \
+	(a)[0] = (b)[0] - (c)[0];	\
+	(a)[1] = (b)[1] - (c)[1];	\
+	(a)[2] = (b)[2] - (c)[2];
+
+
+
+#define innerProduct(v,q) \
+		((v)[0] * (q)[0] + \
+		(v)[1] * (q)[1] + \
+		(v)[2] * (q)[2])
+
+#define crossProduct(a,b,c) \
+	(a)[0] = (b)[1] * (c)[2] - (c)[1] * (b)[2]; \
+	(a)[1] = (b)[2] * (c)[0] - (c)[2] * (b)[0]; \
+	(a)[2] = (b)[0] * (c)[1] - (c)[0] * (b)[1];
+
+bool rayIntersectsTriangle(const float *p,const float *d,const float *v0,const float *v1,const float *v2,float &t)
+{
+
+	float e1[3],e2[3],h[3],s[3],q[3];
+	float a,f,u,v;
+
+	vector(e1,v1,v0);
+	vector(e2,v2,v0);
+	crossProduct(h,d,e2);
+	a = innerProduct(e1,h);
+
+	if (a > -0.00001 && a < 0.00001)
+		return(false);
+
+	f = 1/a;
+	vector(s,p,v0);
+	u = f * (innerProduct(s,h));
+
+	if (u < 0.0 || u > 1.0)
+		return(false);
+
+	crossProduct(q,s,e1);
+	v = f * innerProduct(d,q);
+	if (v < 0.0 || u + v > 1.0)
+		return(false);
+	// at this stage we can compute t to find out where
+	// the intersection point is on the line
+	t = f * innerProduct(e2,q);
+	if (t > 0) // ray intersection
+		return(true);
+	else // this means that there is a line intersection
+		 // but not a ray intersection
+		 return (false);
+}
+
+
+bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const float *p1,const float *p2,const float *p3,float *sect)
+{
+	float dir[3];
+
+  dir[0] = rayEnd[0] - rayStart[0];
+  dir[1] = rayEnd[1] - rayStart[1];
+  dir[2] = rayEnd[2] - rayStart[2];
+
+  float d = sqrtf(dir[0]*dir[0] + dir[1]*dir[1] + dir[2]*dir[2]);
+  float r = 1.0f / d;
+
+  dir[0]*=r;
+  dir[1]*=r;
+  dir[2]*=r;
+
+
+  float t;
+
+	bool ret = rayIntersectsTriangle(rayStart, dir, p1, p2, p3, t );
+
+	if ( ret )
+	{
+		if ( t > d )
+		{
+			sect[0] = rayStart[0] + dir[0]*t;
+			sect[1] = rayStart[1] + dir[1]*t;
+			sect[2] = rayStart[2] + dir[2]*t;
+		}
+		else
+		{
+			ret = false;
+		}
+	}
+
+  return ret;
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/raytri.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/raytri.h
new file mode 100644
index 0000000..76370c6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/raytri.h
@@ -0,0 +1,45 @@
+#ifndef RAY_TRI_H
+
+#define RAY_TRI_H
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+
+// returns true if the ray intersects the triangle.
+bool lineIntersectsTriangle(const float *rayStart,const float *rayEnd,const float *p1,const float *p2,const float *p3,float *sect);
+bool rayIntersectsTriangle(const float *p,const float *d,const float *v0,const float *v1,const float *v2,float &t);
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/splitplane.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/splitplane.cpp
new file mode 100644
index 0000000..2ae408e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/splitplane.cpp
@@ -0,0 +1,306 @@
+#include "float_math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+#include "splitplane.h"
+#include "ConvexDecomposition.h"
+#include "cd_vector.h"
+#include "cd_hull.h"
+#include "cd_wavefront.h"
+#include "bestfit.h"
+#include "planetri.h"
+#include "vlookup.h"
+#include "meshvolume.h"
+
+namespace ConvexDecomposition
+{
+
+static void computePlane(const float *A,const float *B,const float *C,float *plane)
+{
+
+	float vx = (B[0] - C[0]);
+	float vy = (B[1] - C[1]);
+	float vz = (B[2] - C[2]);
+
+	float wx = (A[0] - B[0]);
+	float wy = (A[1] - B[1]);
+	float wz = (A[2] - B[2]);
+
+	float vw_x = vy * wz - vz * wy;
+	float vw_y = vz * wx - vx * wz;
+	float vw_z = vx * wy - vy * wx;
+
+	float mag = sqrtf((vw_x * vw_x) + (vw_y * vw_y) + (vw_z * vw_z));
+
+	if ( mag < 0.000001f )
+	{
+		mag = 0;
+	}
+	else
+	{
+		mag = 1.0f/mag;
+	}
+
+	float x = vw_x * mag;
+	float y = vw_y * mag;
+	float z = vw_z * mag;
+
+
+	float D = 0.0f - ((x*A[0])+(y*A[1])+(z*A[2]));
+
+  plane[0] = x;
+  plane[1] = y;
+  plane[2] = z;
+  plane[3] = D;
+
+}
+
+class Rect3d
+{
+public:
+  Rect3d(void) { };
+
+  Rect3d(const float *bmin,const float *bmax)
+  {
+
+    mMin[0] = bmin[0];
+    mMin[1] = bmin[1];
+    mMin[2] = bmin[2];
+
+    mMax[0] = bmax[0];
+    mMax[1] = bmax[1];
+    mMax[2] = bmax[2];
+
+  }
+
+  void SetMin(const float *bmin)
+  {
+    mMin[0] = bmin[0];
+    mMin[1] = bmin[1];
+    mMin[2] = bmin[2];
+  }
+
+  void SetMax(const float *bmax)
+  {
+    mMax[0] = bmax[0];
+    mMax[1] = bmax[1];
+    mMax[2] = bmax[2];
+  }
+
+	void SetMin(float x,float y,float z)
+	{
+		mMin[0] = x;
+		mMin[1] = y;
+		mMin[2] = z;
+	}
+
+	void SetMax(float x,float y,float z)
+	{
+		mMax[0] = x;
+		mMax[1] = y;
+		mMax[2] = z;
+	}
+
+  float mMin[3];
+  float mMax[3];
+};
+
+void splitRect(unsigned int axis,
+						   const Rect3d &source,
+							 Rect3d &b1,
+							 Rect3d &b2,
+							 const float *midpoint)
+{
+	switch ( axis )
+	{
+		case 0:
+			b1.SetMin(source.mMin);
+			b1.SetMax( midpoint[0], source.mMax[1], source.mMax[2] );
+
+			b2.SetMin( midpoint[0], source.mMin[1], source.mMin[2] );
+			b2.SetMax(source.mMax);
+
+			break;
+		case 1:
+			b1.SetMin(source.mMin);
+			b1.SetMax( source.mMax[0], midpoint[1], source.mMax[2] );
+
+			b2.SetMin( source.mMin[0], midpoint[1], source.mMin[2] );
+			b2.SetMax(source.mMax);
+
+			break;
+		case 2:
+			b1.SetMin(source.mMin);
+			b1.SetMax( source.mMax[0], source.mMax[1], midpoint[2] );
+
+			b2.SetMin( source.mMin[0], source.mMin[1], midpoint[2] );
+			b2.SetMax(source.mMax);
+
+			break;
+	}
+}
+
+bool computeSplitPlane(unsigned int vcount,
+                       const float *vertices,
+                       unsigned int tcount,
+                       const unsigned int *indices,
+                       ConvexDecompInterface *callback,
+                       float *plane)
+{
+  float bmin[3] = { 1e9, 1e9, 1e9 };
+  float bmax[3] = { -1e9, -1e9, -1e9 };
+
+ 	for (unsigned int i=0; i<vcount; i++)
+ 	{
+    const float *p = &vertices[i*3];
+
+ 		if ( p[0] < bmin[0] ) bmin[0] = p[0];
+ 		if ( p[1] < bmin[1] ) bmin[1] = p[1];
+ 		if ( p[2] < bmin[2] ) bmin[2] = p[2];
+
+ 		if ( p[0] > bmax[0] ) bmax[0] = p[0];
+ 		if ( p[1] > bmax[1] ) bmax[1] = p[1];
+ 		if ( p[2] > bmax[2] ) bmax[2] = p[2];
+
+  }
+
+  float dx = bmax[0] - bmin[0];
+  float dy = bmax[1] - bmin[1];
+  float dz = bmax[2] - bmin[2];
+
+
+	float laxis = dx;
+
+	unsigned int axis = 0;
+
+	if ( dy > dx )
+	{
+		axis = 1;
+		laxis = dy;
+	}
+
+	if ( dz > dx && dz > dy )
+	{
+		axis = 2;
+		laxis = dz;
+	}
+
+  float p1[3];
+  float p2[3];
+  float p3[3];
+
+  p3[0] = p2[0] = p1[0] = bmin[0] + dx*0.5f;
+  p3[1] = p2[1] = p1[1] = bmin[1] + dy*0.5f;
+  p3[2] = p2[2] = p1[2] = bmin[2] + dz*0.5f;
+
+  Rect3d b(bmin,bmax);
+
+  Rect3d b1,b2;
+
+  splitRect(axis,b,b1,b2,p1);
+
+
+//  callback->ConvexDebugBound(b1.mMin,b1.mMax,0x00FF00);
+//  callback->ConvexDebugBound(b2.mMin,b2.mMax,0xFFFF00);
+
+  switch ( axis )
+  {
+    case 0:
+      p2[1] = bmin[1];
+      p2[2] = bmin[2];
+
+      if ( dz > dy )
+      {
+        p3[1] = bmax[1];
+        p3[2] = bmin[2];
+      }
+      else
+      {
+        p3[1] = bmin[1];
+        p3[2] = bmax[2];
+      }
+
+      break;
+    case 1:
+      p2[0] = bmin[0];
+      p2[2] = bmin[2];
+
+      if ( dx > dz )
+      {
+        p3[0] = bmax[0];
+        p3[2] = bmin[2];
+      }
+      else
+      {
+        p3[0] = bmin[0];
+        p3[2] = bmax[2];
+      }
+
+      break;
+    case 2:
+      p2[0] = bmin[0];
+      p2[1] = bmin[1];
+
+      if ( dx > dy )
+      {
+        p3[0] = bmax[0];
+        p3[1] = bmin[1];
+      }
+      else
+      {
+        p3[0] = bmin[0];
+        p3[1] = bmax[1];
+      }
+
+      break;
+  }
+
+//  callback->ConvexDebugTri(p1,p2,p3,0xFF0000);
+
+	computePlane(p1,p2,p3,plane);
+
+  return true;
+
+}
+
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/splitplane.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/splitplane.h
new file mode 100644
index 0000000..26fe2e3
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/splitplane.h
@@ -0,0 +1,59 @@
+#ifndef SPLIT_PLANE_H
+
+#define SPLIT_PLANE_H
+
+//** Computes an 'optimal' split plane for the supplied mesh.
+//** needs much improvement since it currently just splits along
+//** the longest side of the AABB.
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+
+namespace ConvexDecomposition
+{
+
+class ConvexDecompInterface;
+
+bool computeSplitPlane(unsigned int vcount,
+                       const float *vertices,
+                       unsigned int tcount,
+                       const unsigned int *indices,
+                       ConvexDecompInterface *callback,
+                       float *plane);
+
+
+}
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/vlookup.cpp b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/vlookup.cpp
new file mode 100644
index 0000000..8ce4e45
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/vlookup.cpp
@@ -0,0 +1,307 @@
+#include "float_math.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#pragma warning(disable:4786)
+
+#include <vector>
+#include <map>
+#include <set>
+
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+// CodeSnippet provided by John W. Ratcliff
+// on March 23, 2006.
+//
+// mailto: jratcliff at infiniplex.net
+//
+// Personal website: http://jratcliffscarab.blogspot.com
+// Coding Website:   http://codesuppository.blogspot.com
+// FundRaising Blog: http://amillionpixels.blogspot.com
+// Fundraising site: http://www.amillionpixels.us
+// New Temple Site:  http://newtemple.blogspot.com
+//
+// This snippet shows how to 'hide' the complexity of
+// the STL by wrapping some useful piece of functionality
+// around a handful of discrete API calls.
+//
+// This API allows you to create an indexed triangle list
+// from a collection of raw input triangles.  Internally
+// it uses an STL set to build the lookup table very rapidly.
+//
+// Here is how you would use it to build an indexed triangle
+// list from a raw list of triangles.
+//
+// (1) create a 'VertexLookup' interface by calling
+//
+//     VertexLook vl = Vl_createVertexLookup();
+//
+// (2) For each vertice in each triangle call:
+//
+//     unsigned int i1 = Vl_getIndex(vl,p1);
+//     unsigned int i2 = Vl_getIndex(vl,p2);
+//     unsigned int i3 = Vl_getIndex(vl,p3);
+//
+//     save the 3 indices into your triangle list array.
+//
+// (3) Get the vertex array by calling:
+//
+//     const float *vertices = Vl_getVertices(vl);
+//
+// (4) Get the number of vertices so you can copy them into
+//     your own buffer.
+//     unsigned int vcount = Vl_getVcount(vl);
+//
+// (5) Release the VertexLookup interface when you are done with it.
+//     Vl_releaseVertexLookup(vl);
+//
+// Teaches the following lessons:
+//
+//    How to wrap the complexity of STL and C++ classes around a
+//    simple API interface.
+//
+//    How to use an STL set and custom comparator operator for
+//    a complex data type.
+//
+//    How to create a template class.
+//
+//    How to achieve significant performance improvements by
+//    taking advantage of built in STL containers in just
+//    a few lines of code.
+//
+//    You could easily modify this code to support other vertex
+//    formats with any number of interpolants.
+
+
+
+
+#include "vlookup.h"
+
+namespace Vlookup
+{
+
+class VertexPosition
+{
+public:
+  VertexPosition(void) { };
+  VertexPosition(const float *p)
+  {
+  	mPos[0] = p[0];
+  	mPos[1] = p[1];
+  	mPos[2] = p[2];
+  };
+
+	void Set(int index,const float *pos)
+	{
+		const float * p = &pos[index*3];
+
+		mPos[0]    = p[0];
+		mPos[1]    = p[1];
+		mPos[2]    = p[2];
+
+	};
+
+  float GetX(void) const { return mPos[0]; };
+  float GetY(void) const { return mPos[1]; };
+  float GetZ(void) const { return mPos[2]; };
+
+	float mPos[3];
+};
+
+
+class VertexLess
+{
+public:
+	typedef std::vector< VertexPosition > VertexVector;
+
+	bool operator()(int v1,int v2) const;
+
+	static void SetSearch(const VertexPosition& match,VertexVector *list)
+	{
+		mFind = match;
+		mList = list;
+	};
+
+private:
+	const VertexPosition& Get(int index) const
+	{
+		if ( index == -1 ) return mFind;
+		VertexVector &vlist = *mList;
+		return vlist[index];
+	}
+	static VertexPosition mFind; // vertice to locate.
+	static VertexVector  *mList;
+};
+
+template <class Type> class VertexPool
+{
+public:
+	typedef std::set<int, VertexLess > VertexSet;
+	typedef std::vector< Type > VertexVector;
+
+	int getVertex(const Type& vtx)
+	{
+		VertexLess::SetSearch(vtx,&mVtxs);
+		VertexSet::iterator found;
+		found = mVertSet.find( -1 );
+		if ( found != mVertSet.end() )
+		{
+			return *found;
+		}
+		int idx = (int)mVtxs.size();
+		mVtxs.push_back( vtx );
+		mVertSet.insert( idx );
+		return idx;
+	};
+
+
+	const float * GetPos(int idx) const
+	{
+		return mVtxs[idx].mPos;
+	}
+
+	const Type& Get(int idx) const
+	{
+		return mVtxs[idx];
+	};
+
+	unsigned int GetSize(void) const
+	{
+		return mVtxs.size();
+	};
+
+	void Clear(int reservesize)  // clear the vertice pool.
+	{
+		mVertSet.clear();
+		mVtxs.clear();
+		mVtxs.reserve(reservesize);
+	};
+
+	const VertexVector& GetVertexList(void) const { return mVtxs; };
+
+	void Set(const Type& vtx)
+	{
+		mVtxs.push_back(vtx);
+	}
+
+	unsigned int GetVertexCount(void) const
+	{
+		return mVtxs.size();
+	};
+
+
+	Type * getBuffer(void)
+	{
+		return &mVtxs[0];
+	};
+
+private:
+	VertexSet      mVertSet; // ordered list.
+	VertexVector   mVtxs;  // set of vertices.
+};
+
+
+VertexPosition VertexLess::mFind;
+std::vector<VertexPosition > *VertexLess::mList=0;
+
+bool VertexLess::operator()(int v1,int v2) const
+{
+
+	const VertexPosition& a = Get(v1);
+	const VertexPosition& b = Get(v2);
+
+  int ixA = (int) (a.GetX()*10000.0f);
+  int ixB = (int) (b.GetX()*10000.0f);
+
+	if ( ixA      < ixB      ) return true;
+	if ( ixA      > ixB      ) return false;
+
+  int iyA = (int) (a.GetY()*10000.0f);
+  int iyB = (int) (b.GetY()*10000.0f);
+
+	if ( iyA      < iyB      ) return true;
+	if ( iyA      > iyB      ) return false;
+
+  int izA = (int) (a.GetZ()*10000.0f);
+  int izB = (int) (b.GetZ()*10000.0f);
+
+	if ( izA      < izB      ) return true;
+	if ( izA      > izB      ) return false;
+
+
+	return false;
+}
+
+
+
+
+}
+
+using namespace Vlookup;
+
+VertexLookup Vl_createVertexLookup(void)
+{
+  VertexLookup ret = new VertexPool< VertexPosition >;
+  return ret;
+}
+
+void          Vl_releaseVertexLookup(VertexLookup vlook)
+{
+  VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
+  delete vp;
+}
+
+unsigned int  Vl_getIndex(VertexLookup vlook,const float *pos)  // get index.
+{
+  VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
+  VertexPosition p(pos);
+  return vp->getVertex(p);
+}
+
+const float * Vl_getVertices(VertexLookup vlook)
+{
+  VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
+  return vp->GetPos(0);
+}
+
+
+unsigned int  Vl_getVcount(VertexLookup vlook)
+{
+  VertexPool< VertexPosition > *vp = (VertexPool< VertexPosition > *) vlook;
+  return vp->GetVertexCount();
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/vlookup.h b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/vlookup.h
new file mode 100644
index 0000000..1a6e0a9
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/ConvexDecomposition/vlookup.h
@@ -0,0 +1,119 @@
+#ifndef VLOOKUP_H
+
+#define VLOOKUP_H
+
+
+/*----------------------------------------------------------------------
+		Copyright (c) 2004 Open Dynamics Framework Group
+					www.physicstools.org
+		All rights reserved.
+
+		Redistribution and use in source and binary forms, with or without modification, are permitted provided
+		that the following conditions are met:
+
+		Redistributions of source code must retain the above copyright notice, this list of conditions
+		and the following disclaimer.
+
+		Redistributions in binary form must reproduce the above copyright notice,
+		this list of conditions and the following disclaimer in the documentation
+		and/or other materials provided with the distribution.
+
+		Neither the name of the Open Dynamics Framework Group nor the names of its contributors may
+		be used to endorse or promote products derived from this software without specific prior written permission.
+
+		THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+		INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+		DISCLAIMED. IN NO EVENT SHALL THE INTEL OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+		EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+		LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+		IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+		THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-----------------------------------------------------------------------*/
+
+// http://codesuppository.blogspot.com
+//
+// mailto: jratcliff at infiniplex.net
+//
+// http://www.amillionpixels.us
+//
+
+
+// CodeSnippet provided by John W. Ratcliff
+// on March 23, 2006.
+//
+// mailto: jratcliff at infiniplex.net
+//
+// Personal website: http://jratcliffscarab.blogspot.com
+// Coding Website:   http://codesuppository.blogspot.com
+// FundRaising Blog: http://amillionpixels.blogspot.com
+// Fundraising site: http://www.amillionpixels.us
+// New Temple Site:  http://newtemple.blogspot.com
+//
+// This snippet shows how to 'hide' the complexity of
+// the STL by wrapping some useful piece of functionality
+// around a handful of discrete API calls.
+//
+// This API allows you to create an indexed triangle list
+// from a collection of raw input triangles.  Internally
+// it uses an STL set to build the lookup table very rapidly.
+//
+// Here is how you would use it to build an indexed triangle
+// list from a raw list of triangles.
+//
+// (1) create a 'VertexLookup' interface by calling
+//
+//     VertexLook vl = Vl_createVertexLookup();
+//
+// (2) For each vertice in each triangle call:
+//
+//     unsigned int i1 = Vl_getIndex(vl,p1);
+//     unsigned int i2 = Vl_getIndex(vl,p2);
+//     unsigned int i3 = Vl_getIndex(vl,p3);
+//
+//     save the 3 indices into your triangle list array.
+//
+// (3) Get the vertex array by calling:
+//
+//     const float *vertices = Vl_getVertices(vl);
+//
+// (4) Get the number of vertices so you can copy them into
+//     your own buffer.
+//     unsigned int vcount = Vl_getVcount(vl);
+//
+// (5) Release the VertexLookup interface when you are done with it.
+//     Vl_releaseVertexLookup(vl);
+//
+// Teaches the following lessons:
+//
+//    How to wrap the complexity of STL and C++ classes around a
+//    simple API interface.
+//
+//    How to use an STL set and custom comparator operator for
+//    a complex data type.
+//
+//    How to create a template class.
+//
+//    How to achieve significant performance improvements by
+//    taking advantage of built in STL containers in just
+//    a few lines of code.
+//
+//    You could easily modify this code to support other vertex
+//    formats with any number of interpolants.
+//
+//    Hide C++ classes from the rest of your application by
+//    keeping them in the CPP and wrapping them in a namespace
+// Uses an STL set to create an index table for a bunch of vertex positions
+// used typically to re-index a collection of raw triangle data.
+
+
+typedef void * VertexLookup;
+
+VertexLookup  Vl_createVertexLookup(void);
+void          Vl_releaseVertexLookup(VertexLookup vlook);
+
+unsigned int  Vl_getIndex(VertexLookup vlook,const float *pos);  // get index.
+const float * Vl_getVertices(VertexLookup vlook);
+unsigned int  Vl_getVcount(VertexLookup vlook);
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btBoxCollision.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btBoxCollision.h
new file mode 100644
index 0000000..827a3c8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btBoxCollision.h
@@ -0,0 +1,647 @@
+#ifndef BT_BOX_COLLISION_H_INCLUDED
+#define BT_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btTransform.h"
+
+
+///Swap numbers
+#define BT_SWAP_NUMBERS(a,b){ \
+    a = a+b; \
+    b = a-b; \
+    a = a-b; \
+}\
+
+
+#define BT_MAX(a,b) (a<b?b:a)
+#define BT_MIN(a,b) (a>b?b:a)
+
+#define BT_GREATER(x, y)	btFabs(x) > (y)
+
+#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c))
+#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c))
+
+
+
+
+
+
+enum eBT_PLANE_INTERSECTION_TYPE
+{
+	BT_CONST_BACK_PLANE = 0,
+	BT_CONST_COLLIDE_PLANE,
+	BT_CONST_FRONT_PLANE
+};
+
+//SIMD_FORCE_INLINE bool test_cross_edge_box(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, const btVector3 & extend,
+//	int dir_index0,
+//	int dir_index1
+//	int component_index0,
+//	int component_index1)
+//{
+//	// dir coords are -z and y
+//
+//	const btScalar dir0 = -edge[dir_index0];
+//	const btScalar dir1 = edge[dir_index1];
+//	btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
+//	btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
+//	//find minmax
+//	if(pmin>pmax)
+//	{
+//		BT_SWAP_NUMBERS(pmin,pmax);
+//	}
+//	//find extends
+//	const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
+//					extend[component_index1] * absolute_edge[dir_index1];
+//
+//	if(pmin>rad || -rad>pmax) return false;
+//	return true;
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
+//}
+//
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
+//}
+
+
+#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
+{\
+	const btScalar dir0 = -edge[i_dir_0];\
+	const btScalar dir1 = edge[i_dir_1];\
+	btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
+	btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
+	if(pmin>pmax)\
+	{\
+		BT_SWAP_NUMBERS(pmin,pmax); \
+	}\
+	const btScalar abs_dir0 = absolute_edge[i_dir_0];\
+	const btScalar abs_dir1 = absolute_edge[i_dir_1];\
+	const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
+	if(pmin>rad || -rad>pmax) return false;\
+}\
+
+
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
+}\
+
+
+//! Returns the dot product between a vec3f and the col of a matrix
+SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
+const btMatrix3x3 & mat, const btVector3 & vec3, int colindex)
+{
+	return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex];
+}
+
+
+//!  Class for transforming a model1 to the space of model0
+ATTRIBUTE_ALIGNED16	(class) BT_BOX_BOX_TRANSFORM_CACHE
+{
+public:
+    btVector3  m_T1to0;//!< Transforms translation of model1 to model 0
+	btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal  to R0' * R1
+	btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
+
+	SIMD_FORCE_INLINE void calc_absolute_matrix()
+	{
+//		static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
+//		m_AR[0] = vepsi + m_R1to0[0].absolute();
+//		m_AR[1] = vepsi + m_R1to0[1].absolute();
+//		m_AR[2] = vepsi + m_R1to0[2].absolute();
+
+		int i,j;
+
+        for(i=0;i<3;i++)
+        {
+            for(j=0;j<3;j++ )
+            {
+            	m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
+            }
+        }
+
+	}
+
+	BT_BOX_BOX_TRANSFORM_CACHE()
+	{
+	}
+
+
+
+	//! Calc the transformation relative  1 to 0. Inverts matrics by transposing
+	SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
+	{
+
+		btTransform temp_trans = trans0.inverse();
+		temp_trans = temp_trans * trans1;
+
+		m_T1to0 = temp_trans.getOrigin();
+		m_R1to0 = temp_trans.getBasis();
+
+
+		calc_absolute_matrix();
+	}
+
+	//! Calcs the full invertion of the matrices. Useful for scaling matrices
+	SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
+	{
+		m_R1to0 = trans0.getBasis().inverse();
+		m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+		m_T1to0 += m_R1to0*trans1.getOrigin();
+		m_R1to0 *= trans1.getBasis();
+
+		calc_absolute_matrix();
+	}
+
+	SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
+	{
+		return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
+			m_R1to0[1].dot(point) + m_T1to0.y(),
+			m_R1to0[2].dot(point) + m_T1to0.z());
+	}
+};
+
+
+#define BOX_PLANE_EPSILON 0.000001f
+
+//! Axis aligned box
+ATTRIBUTE_ALIGNED16	(class) btAABB
+{
+public:
+	btVector3 m_min;
+	btVector3 m_max;
+
+	btAABB()
+	{}
+
+
+	btAABB(const btVector3 & V1,
+			 const btVector3 & V2,
+			 const btVector3 & V3)
+	{
+		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+	}
+
+	btAABB(const btVector3 & V1,
+			 const btVector3 & V2,
+			 const btVector3 & V3,
+			 btScalar margin)
+	{
+		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	btAABB(const btAABB &other):
+		m_min(other.m_min),m_max(other.m_max)
+	{
+	}
+
+	btAABB(const btAABB &other,btScalar margin ):
+		m_min(other.m_min),m_max(other.m_max)
+	{
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	SIMD_FORCE_INLINE void invalidate()
+	{
+		m_min[0] = SIMD_INFINITY;
+		m_min[1] = SIMD_INFINITY;
+		m_min[2] = SIMD_INFINITY;
+		m_max[0] = -SIMD_INFINITY;
+		m_max[1] = -SIMD_INFINITY;
+		m_max[2] = -SIMD_INFINITY;
+	}
+
+	SIMD_FORCE_INLINE void increment_margin(btScalar margin)
+	{
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
+	{
+		m_min[0] = other.m_min[0] - margin;
+		m_min[1] = other.m_min[1] - margin;
+		m_min[2] = other.m_min[2] - margin;
+
+		m_max[0] = other.m_max[0] + margin;
+		m_max[1] = other.m_max[1] + margin;
+		m_max[2] = other.m_max[2] + margin;
+	}
+
+	template<typename CLASS_POINT>
+	SIMD_FORCE_INLINE void calc_from_triangle(
+							const CLASS_POINT & V1,
+							const CLASS_POINT & V2,
+							const CLASS_POINT & V3)
+	{
+		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+	}
+
+	template<typename CLASS_POINT>
+	SIMD_FORCE_INLINE void calc_from_triangle_margin(
+							const CLASS_POINT & V1,
+							const CLASS_POINT & V2,
+							const CLASS_POINT & V3, btScalar margin)
+	{
+		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
+
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	//! Apply a transform to an AABB
+	SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
+	{
+		btVector3 center = (m_max+m_min)*0.5f;
+		btVector3 extends = m_max - center;
+		// Compute new center
+		center = trans(center);
+
+		btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
+ 				 extends.dot(trans.getBasis().getRow(1).absolute()),
+				 extends.dot(trans.getBasis().getRow(2).absolute()));
+
+		m_min = center - textends;
+		m_max = center + textends;
+	}
+
+
+	//! Apply a transform to an AABB
+	SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans)
+	{
+		btVector3 center = (m_max+m_min)*0.5f;
+		btVector3 extends = m_max - center;
+		// Compute new center
+		center = trans.transform(center);
+
+		btVector3 textends(extends.dot(trans.m_R1to0.getRow(0).absolute()),
+ 				 extends.dot(trans.m_R1to0.getRow(1).absolute()),
+				 extends.dot(trans.m_R1to0.getRow(2).absolute()));
+
+		m_min = center - textends;
+		m_max = center + textends;
+	}
+
+	//! Merges a Box
+	SIMD_FORCE_INLINE void merge(const btAABB & box)
+	{
+		m_min[0] = BT_MIN(m_min[0],box.m_min[0]);
+		m_min[1] = BT_MIN(m_min[1],box.m_min[1]);
+		m_min[2] = BT_MIN(m_min[2],box.m_min[2]);
+
+		m_max[0] = BT_MAX(m_max[0],box.m_max[0]);
+		m_max[1] = BT_MAX(m_max[1],box.m_max[1]);
+		m_max[2] = BT_MAX(m_max[2],box.m_max[2]);
+	}
+
+	//! Merges a point
+	template<typename CLASS_POINT>
+	SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
+	{
+		m_min[0] = BT_MIN(m_min[0],point[0]);
+		m_min[1] = BT_MIN(m_min[1],point[1]);
+		m_min[2] = BT_MIN(m_min[2],point[2]);
+
+		m_max[0] = BT_MAX(m_max[0],point[0]);
+		m_max[1] = BT_MAX(m_max[1],point[1]);
+		m_max[2] = BT_MAX(m_max[2],point[2]);
+	}
+
+	//! Gets the extend and center
+	SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend)  const
+	{
+		center = (m_max+m_min)*0.5f;
+		extend = m_max - center;
+	}
+
+	//! Finds the intersecting box between this box and the other.
+	SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection)  const
+	{
+		intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]);
+		intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]);
+		intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]);
+
+		intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]);
+		intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]);
+		intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]);
+	}
+
+
+	SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const
+	{
+		if(m_min[0] > other.m_max[0] ||
+		   m_max[0] < other.m_min[0] ||
+		   m_min[1] > other.m_max[1] ||
+		   m_max[1] < other.m_min[1] ||
+		   m_min[2] > other.m_max[2] ||
+		   m_max[2] < other.m_min[2])
+		{
+			return false;
+		}
+		return true;
+	}
+
+	/*! \brief Finds the Ray intersection parameter.
+	\param aabb Aligned box
+	\param vorigin A vec3f with the origin of the ray
+	\param vdir A vec3f with the direction of the ray
+	*/
+	SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)  const
+	{
+		btVector3 extents,center;
+		this->get_center_extend(center,extents);;
+
+		btScalar Dx = vorigin[0] - center[0];
+		if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f)	return false;
+		btScalar Dy = vorigin[1] - center[1];
+		if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f)	return false;
+		btScalar Dz = vorigin[2] - center[2];
+		if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f)	return false;
+
+
+		btScalar f = vdir[1] * Dz - vdir[2] * Dy;
+		if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
+		f = vdir[2] * Dx - vdir[0] * Dz;
+		if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
+		f = vdir[0] * Dy - vdir[1] * Dx;
+		if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
+		return true;
+	}
+
+
+	SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
+	{
+		btVector3 center = (m_max+m_min)*0.5f;
+		btVector3 extend = m_max-center;
+
+		btScalar _fOrigin =  direction.dot(center);
+		btScalar _fMaximumExtent = extend.dot(direction.absolute());
+		vmin = _fOrigin - _fMaximumExtent;
+		vmax = _fOrigin + _fMaximumExtent;
+	}
+
+	SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
+	{
+		btScalar _fmin,_fmax;
+		this->projection_interval(plane,_fmin,_fmax);
+
+		if(plane[3] > _fmax + BOX_PLANE_EPSILON)
+		{
+			return BT_CONST_BACK_PLANE; // 0
+		}
+
+		if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
+		{
+			return BT_CONST_COLLIDE_PLANE; //1
+		}
+		return BT_CONST_FRONT_PLANE;//2
+	}
+
+	SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const
+	{
+		btAABB tbox = box;
+		tbox.appy_transform(trans1_to_0);
+		return has_collision(tbox);
+	}
+
+	SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box,
+		const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const
+	{
+		btAABB tbox = box;
+		tbox.appy_transform_trans_cache(trans1_to_0);
+		return has_collision(tbox);
+	}
+
+	//! transcache is the transformation cache from box to this AABB
+	SIMD_FORCE_INLINE bool overlapping_trans_cache(
+		const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const
+	{
+
+		//Taken from OPCODE
+		btVector3 ea,eb;//extends
+		btVector3 ca,cb;//extends
+		get_center_extend(ca,ea);
+		box.get_center_extend(cb,eb);
+
+
+		btVector3 T;
+		btScalar t,t2;
+		int i;
+
+		// Class I : A's basis vectors
+		for(i=0;i<3;i++)
+		{
+			T[i] =  transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+			t = transcache.m_AR[i].dot(eb) + ea[i];
+			if(BT_GREATER(T[i], t))	return false;
+		}
+		// Class II : B's basis vectors
+		for(i=0;i<3;i++)
+		{
+			t = bt_mat3_dot_col(transcache.m_R1to0,T,i);
+			t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i];
+			if(BT_GREATER(t,t2))	return false;
+		}
+		// Class III : 9 cross products
+		if(fulltest)
+		{
+			int j,m,n,o,p,q,r;
+			for(i=0;i<3;i++)
+			{
+				m = (i+1)%3;
+				n = (i+2)%3;
+				o = i==0?1:0;
+				p = i==2?1:2;
+				for(j=0;j<3;j++)
+				{
+					q = j==2?1:2;
+					r = j==0?1:0;
+					t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
+					t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
+						eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
+					if(BT_GREATER(t,t2))	return false;
+				}
+			}
+		}
+		return true;
+	}
+
+	//! Simple test for planes.
+	SIMD_FORCE_INLINE bool collide_plane(
+		const btVector4 & plane) const
+	{
+		eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
+		return (classify == BT_CONST_COLLIDE_PLANE);
+	}
+
+	//! test for a triangle, with edges
+	SIMD_FORCE_INLINE bool collide_triangle_exact(
+		const btVector3 & p1,
+		const btVector3 & p2,
+		const btVector3 & p3,
+		const btVector4 & triangle_plane) const
+	{
+		if(!collide_plane(triangle_plane)) return false;
+
+		btVector3 center,extends;
+		this->get_center_extend(center,extends);
+
+		const btVector3 v1(p1 - center);
+		const btVector3 v2(p2 - center);
+		const btVector3 v3(p3 - center);
+
+		//First axis
+		btVector3 diff(v2 - v1);
+		btVector3 abs_diff = diff.absolute();
+		//Test With X axis
+		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+		//Test With Y axis
+		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+		//Test With Z axis
+		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+
+
+		diff = v3 - v2;
+		abs_diff = diff.absolute();
+		//Test With X axis
+		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+		//Test With Y axis
+		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+		//Test With Z axis
+		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+
+		diff = v1 - v3;
+		abs_diff = diff.absolute();
+		//Test With X axis
+		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+		//Test With Y axis
+		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+		//Test With Z axis
+		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+
+		return true;
+	}
+};
+
+
+//! Compairison of transformation objects
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
+{
+	if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
+
+	if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
+	if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
+	if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
+	return true;
+}
+
+
+
+#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btClipPolygon.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btClipPolygon.h
new file mode 100644
index 0000000..5de391a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btClipPolygon.h
@@ -0,0 +1,182 @@
+#ifndef BT_CLIP_POLYGON_H_INCLUDED
+#define BT_CLIP_POLYGON_H_INCLUDED
+
+/*! \file btClipPolygon.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btGeometryUtil.h"
+
+
+SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point)
+{
+	return point.dot(plane) - plane[3];
+}
+
+/*! Vector blending
+Takes two vectors a, b, blends them together*/
+SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor)
+{
+	vr = (1-blend_factor)*va + blend_factor*vb;
+}
+
+//! This function calcs the distance from a 3D plane
+SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect(
+						const btVector3 & point0,
+						const btVector3 & point1,
+						btScalar dist0,
+						btScalar dist1,
+						btVector3 * clipped,
+						int & clipped_count)
+{
+	bool _prevclassif = (dist0>SIMD_EPSILON);
+	bool _classif = (dist1>SIMD_EPSILON);
+	if(_classif!=_prevclassif)
+	{
+		btScalar blendfactor = -dist0/(dist1-dist0);
+		bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor);
+		clipped_count++;
+	}
+	if(!_classif)
+	{
+		clipped[clipped_count] = point1;
+		clipped_count++;
+	}
+}
+
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+SIMD_FORCE_INLINE int bt_plane_clip_polygon(
+						const btVector4 & plane,
+						const btVector3 * polygon_points,
+						int polygon_point_count,
+						btVector3 * clipped)
+{
+    int clipped_count = 0;
+
+
+    //clip first point
+	btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);;
+	if(!(firstdist>SIMD_EPSILON))
+	{
+		clipped[clipped_count] = polygon_points[0];
+		clipped_count++;
+	}
+
+	btScalar olddist = firstdist;
+	for(int i=1;i<polygon_point_count;i++)
+	{
+		btScalar dist = bt_distance_point_plane(plane,polygon_points[i]);
+
+		bt_plane_clip_polygon_collect(
+						polygon_points[i-1],polygon_points[i],
+						olddist,
+						dist,
+						clipped,
+						clipped_count);
+
+
+		olddist = dist;
+	}
+
+	//RETURN TO FIRST  point
+
+	bt_plane_clip_polygon_collect(
+					polygon_points[polygon_point_count-1],polygon_points[0],
+					olddist,
+					firstdist,
+					clipped,
+					clipped_count);
+
+	return clipped_count;
+}
+
+//! Clips a polygon by a plane
+/*!
+*\param clipped must be an array of 16 points.
+*\return The count of the clipped counts
+*/
+SIMD_FORCE_INLINE int bt_plane_clip_triangle(
+						const btVector4 & plane,
+						const btVector3 & point0,
+						const btVector3 & point1,
+						const btVector3& point2,
+						btVector3 * clipped // an allocated array of 16 points at least
+						)
+{
+    int clipped_count = 0;
+
+    //clip first point0
+	btScalar firstdist = bt_distance_point_plane(plane,point0);;
+	if(!(firstdist>SIMD_EPSILON))
+	{
+		clipped[clipped_count] = point0;
+		clipped_count++;
+	}
+
+	// point 1
+	btScalar olddist = firstdist;
+	btScalar dist = bt_distance_point_plane(plane,point1);
+
+	bt_plane_clip_polygon_collect(
+					point0,point1,
+					olddist,
+					dist,
+					clipped,
+					clipped_count);
+
+	olddist = dist;
+
+
+	// point 2
+	dist = bt_distance_point_plane(plane,point2);
+
+	bt_plane_clip_polygon_collect(
+					point1,point2,
+					olddist,
+					dist,
+					clipped,
+					clipped_count);
+	olddist = dist;
+
+
+
+	//RETURN TO FIRST  point0
+	bt_plane_clip_polygon_collect(
+					point2,point0,
+					olddist,
+					firstdist,
+					clipped,
+					clipped_count);
+
+	return clipped_count;
+}
+
+
+
+
+
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btContactProcessing.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btContactProcessing.cpp
new file mode 100644
index 0000000..c3b697b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btContactProcessing.cpp
@@ -0,0 +1,181 @@
+
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "btContactProcessing.h"
+
+#define MAX_COINCIDENT 8
+
+struct CONTACT_KEY_TOKEN
+{
+	unsigned int m_key;
+	int m_value;
+	CONTACT_KEY_TOKEN()
+    {
+    }
+
+    CONTACT_KEY_TOKEN(unsigned int key,int token)
+    {
+    	m_key = key;
+    	m_value =  token;
+    }
+
+    CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken)
+    {
+    	m_key = rtoken.m_key;
+    	m_value = rtoken.m_value;
+    }
+
+    inline bool operator <(const CONTACT_KEY_TOKEN& other) const
+	{
+		return (m_key < other.m_key);
+	}
+
+	inline bool operator >(const CONTACT_KEY_TOKEN& other) const
+	{
+		return (m_key > other.m_key);
+	}
+
+};
+
+class CONTACT_KEY_TOKEN_COMP
+{
+	public:
+
+		bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b )
+		{
+			return ( a < b );
+		}
+};
+
+
+void btContactArray::merge_contacts(
+	const btContactArray & contacts, bool normal_contact_average)
+{
+	clear();
+
+	int i;
+	if(contacts.size()==0) return;
+
+
+	if(contacts.size()==1)
+	{
+		push_back(contacts[0]);
+		return;
+	}
+
+	btAlignedObjectArray<CONTACT_KEY_TOKEN> keycontacts;
+
+	keycontacts.reserve(contacts.size());
+
+	//fill key contacts
+
+	for ( i = 0;i<contacts.size() ;i++ )
+	{
+		keycontacts.push_back(CONTACT_KEY_TOKEN(contacts[i].calc_key_contact(),i));
+	}
+
+	//sort keys
+	keycontacts.quickSort(CONTACT_KEY_TOKEN_COMP());
+
+	// Merge contacts
+	int coincident_count=0;
+	btVector3 coincident_normals[MAX_COINCIDENT];
+
+	unsigned int last_key = keycontacts[0].m_key;
+	unsigned int key = 0;
+
+	push_back(contacts[keycontacts[0].m_value]);
+
+	GIM_CONTACT * pcontact = &(*this)[0];
+
+	for( i=1;i<keycontacts.size();i++)
+	{
+	    key = keycontacts[i].m_key;
+		const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
+
+		if(last_key ==  key)//same points
+		{
+			//merge contact
+			if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
+			{
+				*pcontact = *scontact;
+                coincident_count = 0;
+			}
+			else if(normal_contact_average)
+			{
+				if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
+                {
+                    if(coincident_count<MAX_COINCIDENT)
+                    {
+                    	coincident_normals[coincident_count] = scontact->m_normal;
+                        coincident_count++;
+                    }
+                }
+			}
+		}
+		else
+		{//add new contact
+
+		    if(normal_contact_average && coincident_count>0)
+		    {
+		    	pcontact->interpolate_normals(coincident_normals,coincident_count);
+		        coincident_count = 0;
+		    }
+
+		    push_back(*scontact);
+		    pcontact = &(*this)[this->size()-1];
+        }
+		last_key = key;
+	}
+}
+
+void btContactArray::merge_contacts_unique(const btContactArray & contacts)
+{
+	clear();
+
+	if(contacts.size()==0) return;
+
+	if(contacts.size()==1)
+	{
+		push_back(contacts[0]);
+		return;
+	}
+
+	GIM_CONTACT average_contact = contacts[0];
+
+	for (int i=1;i<contacts.size() ;i++ )
+	{
+		average_contact.m_point += contacts[i].m_point;
+		average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
+	}
+
+	//divide
+	btScalar divide_average = 1.0f/((btScalar)contacts.size());
+
+	average_contact.m_point *= divide_average;
+
+	average_contact.m_normal *= divide_average;
+
+	average_contact.m_depth = average_contact.m_normal.length();
+
+	average_contact.m_normal /= average_contact.m_depth;
+
+}
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btContactProcessing.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btContactProcessing.h
new file mode 100644
index 0000000..4b0b702
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btContactProcessing.h
@@ -0,0 +1,145 @@
+#ifndef BT_CONTACT_H_INCLUDED
+#define BT_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btAlignedObjectArray.h"
+#include "btTriangleShapeEx.h"
+
+
+
+/**
+Configuration var for applying interpolation of  contact normals
+*/
+#define NORMAL_CONTACT_AVERAGE 1
+
+#define CONTACT_DIFF_EPSILON 0.00001f
+
+///The GIM_CONTACT is an internal GIMPACT structure, similar to btManifoldPoint.
+///@todo: remove and replace GIM_CONTACT by btManifoldPoint.
+class GIM_CONTACT
+{
+public:
+    btVector3 m_point;
+    btVector3 m_normal;
+    btScalar m_depth;//Positive value indicates interpenetration
+    btScalar m_distance;//Padding not for use
+    int m_feature1;//Face number
+    int m_feature2;//Face number
+public:
+    GIM_CONTACT()
+    {
+    }
+
+    GIM_CONTACT(const GIM_CONTACT & contact):
+				m_point(contact.m_point),
+				m_normal(contact.m_normal),
+				m_depth(contact.m_depth),
+				m_feature1(contact.m_feature1),
+				m_feature2(contact.m_feature2)
+    {
+    }
+
+    GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
+    	 			btScalar depth, int feature1, int feature2):
+				m_point(point),
+				m_normal(normal),
+				m_depth(depth),
+				m_feature1(feature1),
+				m_feature2(feature2)
+    {
+    }
+
+	//! Calcs key for coord classification
+    SIMD_FORCE_INLINE unsigned int calc_key_contact() const
+    {
+    	int _coords[] = {
+    		(int)(m_point[0]*1000.0f+1.0f),
+    		(int)(m_point[1]*1333.0f),
+    		(int)(m_point[2]*2133.0f+3.0f)};
+		unsigned int _hash=0;
+		unsigned int *_uitmp = (unsigned int *)(&_coords[0]);
+		_hash = *_uitmp;
+		_uitmp++;
+		_hash += (*_uitmp)<<4;
+		_uitmp++;
+		_hash += (*_uitmp)<<8;
+		return _hash;
+    }
+
+    SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,int normal_count)
+    {
+    	btVector3 vec_sum(m_normal);
+		for(int i=0;i<normal_count;i++)
+		{
+			vec_sum += normals[i];
+		}
+
+		btScalar vec_sum_len = vec_sum.length2();
+		if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
+
+		//GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
+
+		m_normal = vec_sum/btSqrt(vec_sum_len);
+    }
+
+};
+
+
+class btContactArray:public btAlignedObjectArray<GIM_CONTACT>
+{
+public:
+	btContactArray()
+	{
+		reserve(64);
+	}
+
+	SIMD_FORCE_INLINE void push_contact(
+		const btVector3 &point,const btVector3 & normal,
+		btScalar depth, int feature1, int feature2)
+	{
+		push_back( GIM_CONTACT(point,normal,depth,feature1,feature2) );
+	}
+
+	SIMD_FORCE_INLINE void push_triangle_contacts(
+		const GIM_TRIANGLE_CONTACT & tricontact,
+		int feature1,int feature2)
+	{
+		for(int i = 0;i<tricontact.m_point_count ;i++ )
+		{
+			push_contact(
+				tricontact.m_points[i],
+				tricontact.m_separating_normal,
+				tricontact.m_penetration_depth,feature1,feature2);
+		}
+	}
+
+	void merge_contacts(const btContactArray & contacts, bool normal_contact_average = true);
+
+	void merge_contacts_unique(const btContactArray & contacts);
+};
+
+
+#endif // GIM_CONTACT_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactBvh.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactBvh.cpp
new file mode 100644
index 0000000..38fed6b
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactBvh.cpp
@@ -0,0 +1,498 @@
+/*! \file gim_box_set.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+#include "btGImpactBvh.h"
+#include "LinearMath/btQuickprof.h"
+
+#ifdef TRI_COLLISION_PROFILING
+
+btClock g_tree_clock;
+
+float g_accum_tree_collision_time = 0;
+int g_count_traversing = 0;
+
+
+void bt_begin_gim02_tree_time()
+{
+	g_tree_clock.reset();
+}
+
+void bt_end_gim02_tree_time()
+{
+	g_accum_tree_collision_time += g_tree_clock.getTimeMicroseconds();
+	g_count_traversing++;
+}
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactBvh::getAverageTreeCollisionTime()
+{
+	if(g_count_traversing == 0) return 0;
+
+	float avgtime = g_accum_tree_collision_time;
+	avgtime /= (float)g_count_traversing;
+
+	g_accum_tree_collision_time = 0;
+	g_count_traversing = 0;
+	return avgtime;
+
+//	float avgtime = g_count_traversing;
+//	g_count_traversing = 0;
+//	return avgtime;
+
+}
+
+#endif //TRI_COLLISION_PROFILING
+
+/////////////////////// btBvhTree /////////////////////////////////
+
+int btBvhTree::_calc_splitting_axis(
+	GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex)
+{
+
+	int i;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+	int numIndices = endIndex-startIndex;
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		btVector3 diff2 = center-means;
+		diff2 = diff2 * diff2;
+		variance += diff2;
+	}
+	variance *= (btScalar(1.)/	((btScalar)numIndices-1)	);
+
+	return variance.maxAxis();
+}
+
+
+int btBvhTree::_sort_and_calc_splitting_index(
+	GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
+	int endIndex, int splitAxis)
+{
+	int i;
+	int splitIndex =startIndex;
+	int numIndices = endIndex - startIndex;
+
+	// average of centers
+	btScalar splitValue = 0.0f;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+
+	splitValue = means[splitAxis];
+
+
+	//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		if (center[splitAxis] > splitValue)
+		{
+			//swap
+			primitive_boxes.swap(i,splitIndex);
+			//swapLeafNodes(i,splitIndex);
+			splitIndex++;
+		}
+	}
+
+	//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+	//otherwise the tree-building might fail due to stack-overflows in certain cases.
+	//unbalanced1 is unsafe: it can cause stack overflows
+	//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+	//unbalanced2 should work too: always use center (perfect balanced trees)
+	//bool unbalanced2 = true;
+
+	//this should be safe too:
+	int rangeBalancedIndices = numIndices/3;
+	bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+	if (unbalanced)
+	{
+		splitIndex = startIndex+ (numIndices>>1);
+	}
+
+	btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+
+	return splitIndex;
+
+}
+
+
+void btBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex)
+{
+	int curIndex = m_num_nodes;
+	m_num_nodes++;
+
+	btAssert((endIndex-startIndex)>0);
+
+	if ((endIndex-startIndex)==1)
+	{
+	    //We have a leaf node
+	    setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
+		m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
+
+		return;
+	}
+	//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+	//split axis
+	int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+
+	splitIndex = _sort_and_calc_splitting_index(
+			primitive_boxes,startIndex,endIndex,
+			splitIndex//split axis
+			);
+
+
+	//calc this node bounding box
+
+	btAABB node_bound;
+	node_bound.invalidate();
+
+	for (int i=startIndex;i<endIndex;i++)
+	{
+		node_bound.merge(primitive_boxes[i].m_bound);
+	}
+
+	setNodeBound(curIndex,node_bound);
+
+
+	//build left branch
+	_build_sub_tree(primitive_boxes, startIndex, splitIndex );
+
+
+	//build right branch
+	 _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+
+	m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
+
+
+}
+
+//! stackless build tree
+void btBvhTree::build_tree(
+	GIM_BVH_DATA_ARRAY & primitive_boxes)
+{
+	// initialize node count to 0
+	m_num_nodes = 0;
+	// allocate nodes
+	m_node_array.resize(primitive_boxes.size()*2);
+
+	_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+////////////////////////////////////class btGImpactBvh
+
+void btGImpactBvh::refit()
+{
+	int nodecount = getNodeCount();
+	while(nodecount--)
+	{
+		if(isLeafNode(nodecount))
+		{
+			btAABB leafbox;
+			m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
+			setNodeBound(nodecount,leafbox);
+		}
+		else
+		{
+			//const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
+			//get left bound
+			btAABB bound;
+			bound.invalidate();
+
+			btAABB temp_box;
+
+			int child_node = getLeftNode(nodecount);
+			if(child_node)
+			{
+				getNodeBound(child_node,temp_box);
+				bound.merge(temp_box);
+			}
+
+			child_node = getRightNode(nodecount);
+			if(child_node)
+			{
+				getNodeBound(child_node,temp_box);
+				bound.merge(temp_box);
+			}
+
+			setNodeBound(nodecount,bound);
+		}
+	}
+}
+
+//! this rebuild the entire set
+void btGImpactBvh::buildSet()
+{
+	//obtain primitive boxes
+	GIM_BVH_DATA_ARRAY primitive_boxes;
+	primitive_boxes.resize(m_primitive_manager->get_primitive_count());
+
+	for (int i = 0;i<primitive_boxes.size() ;i++ )
+	{
+		 m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
+		 primitive_boxes[i].m_data = i;
+	}
+
+	m_box_tree.build_tree(primitive_boxes);
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
+{
+	int curIndex = 0;
+	int numNodes = getNodeCount();
+
+	while (curIndex < numNodes)
+	{
+		btAABB bound;
+		getNodeBound(curIndex,bound);
+
+		//catch bugs in tree data
+
+		bool aabbOverlap = bound.has_collision(box);
+		bool isleafnode = isLeafNode(curIndex);
+
+		if (isleafnode && aabbOverlap)
+		{
+			collided_results.push_back(getNodeData(curIndex));
+		}
+
+		if (aabbOverlap || isleafnode)
+		{
+			//next subnode
+			curIndex++;
+		}
+		else
+		{
+			//skip node
+			curIndex+= getEscapeNodeIndex(curIndex);
+		}
+	}
+	if(collided_results.size()>0) return true;
+	return false;
+}
+
+
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactBvh::rayQuery(
+	const btVector3 & ray_dir,const btVector3 & ray_origin ,
+	btAlignedObjectArray<int> & collided_results) const
+{
+	int curIndex = 0;
+	int numNodes = getNodeCount();
+
+	while (curIndex < numNodes)
+	{
+		btAABB bound;
+		getNodeBound(curIndex,bound);
+
+		//catch bugs in tree data
+
+		bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+		bool isleafnode = isLeafNode(curIndex);
+
+		if (isleafnode && aabbOverlap)
+		{
+			collided_results.push_back(getNodeData( curIndex));
+		}
+
+		if (aabbOverlap || isleafnode)
+		{
+			//next subnode
+			curIndex++;
+		}
+		else
+		{
+			//skip node
+			curIndex+= getEscapeNodeIndex(curIndex);
+		}
+	}
+	if(collided_results.size()>0) return true;
+	return false;
+}
+
+
+SIMD_FORCE_INLINE bool _node_collision(
+	btGImpactBvh * boxset0, btGImpactBvh * boxset1,
+	const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+	int node0 ,int node1, bool complete_primitive_tests)
+{
+	btAABB box0;
+	boxset0->getNodeBound(node0,box0);
+	btAABB box1;
+	boxset1->getNodeBound(node1,box1);
+
+	return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
+//	box1.appy_transform_trans_cache(trans_cache_1to0);
+//	return box0.has_collision(box1);
+
+}
+
+
+//stackless recursive collision routine
+static void _find_collision_pairs_recursive(
+	btGImpactBvh * boxset0, btGImpactBvh * boxset1,
+	btPairSet * collision_pairs,
+	const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+	int node0, int node1, bool complete_primitive_tests)
+{
+
+
+
+	if( _node_collision(
+		boxset0,boxset1,trans_cache_1to0,
+		node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
+
+	if(boxset0->isLeafNode(node0))
+	{
+		if(boxset1->isLeafNode(node1))
+		{
+			// collision result
+			collision_pairs->push_pair(
+				boxset0->getNodeData(node0),boxset1->getNodeData(node1));
+			return;
+		}
+		else
+		{
+
+			//collide left recursive
+
+			_find_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								node0,boxset1->getLeftNode(node1),false);
+
+			//collide right recursive
+			_find_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								node0,boxset1->getRightNode(node1),false);
+
+
+		}
+	}
+	else
+	{
+		if(boxset1->isLeafNode(node1))
+		{
+
+			//collide left recursive
+			_find_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								boxset0->getLeftNode(node0),node1,false);
+
+
+			//collide right recursive
+
+			_find_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								boxset0->getRightNode(node0),node1,false);
+
+
+		}
+		else
+		{
+			//collide left0 left1
+
+
+
+			_find_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
+
+			//collide left0 right1
+
+			_find_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
+
+
+			//collide right0 left1
+
+			_find_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
+
+			//collide right0 right1
+
+			_find_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
+
+		}// else if node1 is not a leaf
+	}// else if node0 is not a leaf
+}
+
+
+void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0,
+		btGImpactBvh * boxset1, const btTransform & trans1,
+		btPairSet & collision_pairs)
+{
+
+	if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
+
+	BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+
+	trans_cache_1to0.calc_from_homogenic(trans0,trans1);
+
+#ifdef TRI_COLLISION_PROFILING
+	bt_begin_gim02_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+	_find_collision_pairs_recursive(
+		boxset0,boxset1,
+		&collision_pairs,trans_cache_1to0,0,0,true);
+#ifdef TRI_COLLISION_PROFILING
+	bt_end_gim02_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+}
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactBvh.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactBvh.h
new file mode 100644
index 0000000..074de4a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactBvh.h
@@ -0,0 +1,396 @@
+#ifndef GIM_BOX_SET_H_INCLUDED
+#define GIM_BOX_SET_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btBoxCollision.h"
+#include "btTriangleShapeEx.h"
+
+
+
+
+
+//! Overlapping pair
+struct GIM_PAIR
+{
+    int m_index1;
+    int m_index2;
+    GIM_PAIR()
+    {}
+
+    GIM_PAIR(const GIM_PAIR & p)
+    {
+    	m_index1 = p.m_index1;
+    	m_index2 = p.m_index2;
+	}
+
+	GIM_PAIR(int index1, int index2)
+    {
+    	m_index1 = index1;
+    	m_index2 = index2;
+	}
+};
+
+//! A pairset array
+class btPairSet: public btAlignedObjectArray<GIM_PAIR>
+{
+public:
+	btPairSet()
+	{
+		reserve(32);
+	}
+	inline void push_pair(int index1,int index2)
+	{
+		push_back(GIM_PAIR(index1,index2));
+	}
+
+	inline void push_pair_inv(int index1,int index2)
+	{
+		push_back(GIM_PAIR(index2,index1));
+	}
+};
+
+
+///GIM_BVH_DATA is an internal GIMPACT collision structure to contain axis aligned bounding box
+struct GIM_BVH_DATA
+{
+	btAABB m_bound;
+	int m_data;
+};
+
+//! Node Structure for trees
+class GIM_BVH_TREE_NODE
+{
+public:
+	btAABB m_bound;
+protected:
+	int	m_escapeIndexOrDataIndex;
+public:
+	GIM_BVH_TREE_NODE()
+	{
+		m_escapeIndexOrDataIndex = 0;
+	}
+
+	SIMD_FORCE_INLINE bool isLeafNode() const
+	{
+		//skipindex is negative (internal node), triangleindex >=0 (leafnode)
+		return (m_escapeIndexOrDataIndex>=0);
+	}
+
+	SIMD_FORCE_INLINE int getEscapeIndex() const
+	{
+		//btAssert(m_escapeIndexOrDataIndex < 0);
+		return -m_escapeIndexOrDataIndex;
+	}
+
+	SIMD_FORCE_INLINE void setEscapeIndex(int index)
+	{
+		m_escapeIndexOrDataIndex = -index;
+	}
+
+	SIMD_FORCE_INLINE int getDataIndex() const
+	{
+		//btAssert(m_escapeIndexOrDataIndex >= 0);
+
+		return m_escapeIndexOrDataIndex;
+	}
+
+	SIMD_FORCE_INLINE void setDataIndex(int index)
+	{
+		m_escapeIndexOrDataIndex = index;
+	}
+
+};
+
+
+class GIM_BVH_DATA_ARRAY:public btAlignedObjectArray<GIM_BVH_DATA>
+{
+};
+
+
+class GIM_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray<GIM_BVH_TREE_NODE>
+{
+};
+
+
+
+
+//! Basic Box tree structure
+class btBvhTree
+{
+protected:
+	int m_num_nodes;
+	GIM_BVH_TREE_NODE_ARRAY m_node_array;
+protected:
+	int _sort_and_calc_splitting_index(
+		GIM_BVH_DATA_ARRAY & primitive_boxes,
+		 int startIndex,  int endIndex, int splitAxis);
+
+	int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+
+	void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+public:
+	btBvhTree()
+	{
+		m_num_nodes = 0;
+	}
+
+	//! prototype functions for box tree management
+	//!@{
+	void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
+
+	SIMD_FORCE_INLINE void clearNodes()
+	{
+		m_node_array.clear();
+		m_num_nodes = 0;
+	}
+
+	//! node count
+	SIMD_FORCE_INLINE int getNodeCount() const
+	{
+		return m_num_nodes;
+	}
+
+	//! tells if the node is a leaf
+	SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+	{
+		return m_node_array[nodeindex].isLeafNode();
+	}
+
+	SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+	{
+		return m_node_array[nodeindex].getDataIndex();
+	}
+
+	SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+	{
+		bound = m_node_array[nodeindex].m_bound;
+	}
+
+	SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+	{
+		m_node_array[nodeindex].m_bound = bound;
+	}
+
+	SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+	{
+		return nodeindex+1;
+	}
+
+	SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+	{
+		if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
+		return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
+	}
+
+	SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+	{
+		return m_node_array[nodeindex].getEscapeIndex();
+	}
+
+	SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
+	{
+		return &m_node_array[index];
+	}
+
+	//!@}
+};
+
+
+//! Prototype Base class for primitive classification
+/*!
+This class is a wrapper for primitive collections.
+This tells relevant info for the Bounding Box set classes, which take care of space classification.
+This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the  Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
+*/
+class btPrimitiveManagerBase
+{
+public:
+
+	virtual ~btPrimitiveManagerBase() {}
+
+	//! determines if this manager consist on only triangles, which special case will be optimized
+	virtual bool is_trimesh() const = 0;
+	virtual int get_primitive_count() const = 0;
+	virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0;
+	//! retrieves only the points of the triangle, and the collision margin
+	virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0;
+};
+
+
+//! Structure for containing Boxes
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like btPrimitiveManagerBase )
+*/
+class btGImpactBvh
+{
+protected:
+	btBvhTree m_box_tree;
+	btPrimitiveManagerBase * m_primitive_manager;
+
+protected:
+	//stackless refit
+	void refit();
+public:
+
+	//! this constructor doesn't build the tree. you must call	buildSet
+	btGImpactBvh()
+	{
+		m_primitive_manager = NULL;
+	}
+
+	//! this constructor doesn't build the tree. you must call	buildSet
+	btGImpactBvh(btPrimitiveManagerBase * primitive_manager)
+	{
+		m_primitive_manager = primitive_manager;
+	}
+
+	SIMD_FORCE_INLINE btAABB getGlobalBox()  const
+	{
+		btAABB totalbox;
+		getNodeBound(0, totalbox);
+		return totalbox;
+	}
+
+	SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
+	{
+		m_primitive_manager = primitive_manager;
+	}
+
+	SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
+	{
+		return m_primitive_manager;
+	}
+
+
+//! node manager prototype functions
+///@{
+
+	//! this attemps to refit the box set.
+	SIMD_FORCE_INLINE void update()
+	{
+		refit();
+	}
+
+	//! this rebuild the entire set
+	void buildSet();
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
+		 const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
+	{
+		btAABB transbox=box;
+		transbox.appy_transform(transform);
+		return boxQuery(transbox,collided_results);
+	}
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	bool rayQuery(
+		const btVector3 & ray_dir,const btVector3 & ray_origin ,
+		btAlignedObjectArray<int> & collided_results) const;
+
+	//! tells if this set has hierarcht
+	SIMD_FORCE_INLINE bool hasHierarchy() const
+	{
+		return true;
+	}
+
+	//! tells if this set is a trimesh
+	SIMD_FORCE_INLINE bool isTrimesh()  const
+	{
+		return m_primitive_manager->is_trimesh();
+	}
+
+	//! node count
+	SIMD_FORCE_INLINE int getNodeCount() const
+	{
+		return m_box_tree.getNodeCount();
+	}
+
+	//! tells if the node is a leaf
+	SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+	{
+		return m_box_tree.isLeafNode(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+	{
+		return m_box_tree.getNodeData(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound)  const
+	{
+		m_box_tree.getNodeBound(nodeindex, bound);
+	}
+
+	SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+	{
+		m_box_tree.setNodeBound(nodeindex, bound);
+	}
+
+
+	SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+	{
+		return m_box_tree.getLeftNode(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+	{
+		return m_box_tree.getRightNode(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+	{
+		return m_box_tree.getEscapeNodeIndex(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
+	{
+		m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
+	}
+
+
+	SIMD_FORCE_INLINE const GIM_BVH_TREE_NODE * get_node_pointer(int index = 0) const
+	{
+		return m_box_tree.get_node_pointer(index);
+	}
+
+
+	static float getAverageTreeCollisionTime();
+
+
+	static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1,
+		btGImpactBvh * boxset2, const btTransform & trans2,
+		btPairSet & collision_pairs);
+};
+
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.cpp
new file mode 100644
index 0000000..e6da8f9
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.cpp
@@ -0,0 +1,902 @@
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+/*
+Author: Francisco Len N�jera
+Concave-Concave Collision
+
+*/
+
+#include "BulletCollision/CollisionDispatch/btManifoldResult.h"
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+#include "BulletCollision/CollisionShapes/btBoxShape.h"
+#include "btGImpactCollisionAlgorithm.h"
+#include "btContactProcessing.h"
+#include "LinearMath/btQuickprof.h"
+
+
+//! Class for accessing the plane equation
+class btPlaneShape : public btStaticPlaneShape
+{
+public:
+
+	btPlaneShape(const btVector3& v, float f)
+		:btStaticPlaneShape(v,f)
+	{
+	}
+
+	void get_plane_equation(btVector4 &equation)
+	{
+		equation[0] = m_planeNormal[0];
+		equation[1] = m_planeNormal[1];
+		equation[2] = m_planeNormal[2];
+		equation[3] = m_planeConstant;
+	}
+
+
+	void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation)
+	{
+		equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal);
+		equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal);
+		equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal);
+		equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant;
+	}
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef TRI_COLLISION_PROFILING
+
+btClock g_triangle_clock;
+
+float g_accum_triangle_collision_time = 0;
+int g_count_triangle_collision = 0;
+
+void bt_begin_gim02_tri_time()
+{
+	g_triangle_clock.reset();
+}
+
+void bt_end_gim02_tri_time()
+{
+	g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds();
+	g_count_triangle_collision++;
+}
+#endif //TRI_COLLISION_PROFILING
+//! Retrieving shapes shapes
+/*!
+Declared here due of insuficent space on Pool allocators
+*/
+//!@{
+class GIM_ShapeRetriever
+{
+public:
+	btGImpactShapeInterface * m_gim_shape;
+	btTriangleShapeEx m_trishape;
+	btTetrahedronShapeEx m_tetrashape;
+
+public:
+	class ChildShapeRetriever
+	{
+	public:
+		GIM_ShapeRetriever * m_parent;
+		virtual btCollisionShape * getChildShape(int index)
+		{
+			return m_parent->m_gim_shape->getChildShape(index);
+		}
+		virtual ~ChildShapeRetriever() {}
+	};
+
+	class TriangleShapeRetriever:public ChildShapeRetriever
+	{
+	public:
+
+		virtual btCollisionShape * getChildShape(int index)
+		{
+			m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape);
+			return &m_parent->m_trishape;
+		}
+		virtual ~TriangleShapeRetriever() {}
+	};
+
+	class TetraShapeRetriever:public ChildShapeRetriever
+	{
+	public:
+
+		virtual btCollisionShape * getChildShape(int index)
+		{
+			m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape);
+			return &m_parent->m_tetrashape;
+		}
+	};
+public:
+	ChildShapeRetriever m_child_retriever;
+	TriangleShapeRetriever m_tri_retriever;
+	TetraShapeRetriever  m_tetra_retriever;
+	ChildShapeRetriever * m_current_retriever;
+
+	GIM_ShapeRetriever(btGImpactShapeInterface * gim_shape)
+	{
+		m_gim_shape = gim_shape;
+		//select retriever
+		if(m_gim_shape->needsRetrieveTriangles())
+		{
+			m_current_retriever = &m_tri_retriever;
+		}
+		else if(m_gim_shape->needsRetrieveTetrahedrons())
+		{
+			m_current_retriever = &m_tetra_retriever;
+		}
+		else
+		{
+			m_current_retriever = &m_child_retriever;
+		}
+
+		m_current_retriever->m_parent = this;
+	}
+
+	btCollisionShape * getChildShape(int index)
+	{
+		return m_current_retriever->getChildShape(index);
+	}
+
+
+};
+
+
+
+//!@}
+
+
+#ifdef TRI_COLLISION_PROFILING
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime()
+{
+	return btGImpactBoxSet::getAverageTreeCollisionTime();
+
+}
+
+//! Gets the average time in miliseconds of triangle collisions
+float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime()
+{
+	if(g_count_triangle_collision == 0) return 0;
+
+	float avgtime = g_accum_triangle_collision_time;
+	avgtime /= (float)g_count_triangle_collision;
+
+	g_accum_triangle_collision_time = 0;
+	g_count_triangle_collision = 0;
+
+	return avgtime;
+}
+
+#endif //TRI_COLLISION_PROFILING
+
+
+
+btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+: btActivatingCollisionAlgorithm(ci,body0,body1)
+{
+	m_manifoldPtr = NULL;
+	m_convex_algorithm = NULL;
+}
+
+btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm()
+{
+	clearCache();
+}
+
+
+
+
+
+void btGImpactCollisionAlgorithm::addContactPoint(btCollisionObject * body0,
+				btCollisionObject * body1,
+				const btVector3 & point,
+				const btVector3 & normal,
+				btScalar distance)
+{
+	m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
+	m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
+	checkManifold(body0,body1);
+	m_resultOut->addContactPoint(normal,point,distance);
+}
+
+
+void btGImpactCollisionAlgorithm::shape_vs_shape_collision(
+					  btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btCollisionShape * shape0,
+					  btCollisionShape * shape1)
+{
+
+	btCollisionShape* tmpShape0 = body0->getCollisionShape();
+	btCollisionShape* tmpShape1 = body1->getCollisionShape();
+	
+	body0->internalSetTemporaryCollisionShape(shape0);
+	body1->internalSetTemporaryCollisionShape(shape1);
+
+	{
+		btCollisionAlgorithm* algor = newAlgorithm(body0,body1);
+		// post :	checkManifold is called
+
+		m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
+		m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
+
+		algor->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
+
+		algor->~btCollisionAlgorithm();
+		m_dispatcher->freeCollisionAlgorithm(algor);
+	}
+
+	body0->internalSetTemporaryCollisionShape(tmpShape0);
+	body1->internalSetTemporaryCollisionShape(tmpShape1);
+}
+
+void btGImpactCollisionAlgorithm::convex_vs_convex_collision(
+					  btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btCollisionShape * shape0,
+					  btCollisionShape * shape1)
+{
+
+	btCollisionShape* tmpShape0 = body0->getCollisionShape();
+	btCollisionShape* tmpShape1 = body1->getCollisionShape();
+	
+	body0->internalSetTemporaryCollisionShape(shape0);
+	body1->internalSetTemporaryCollisionShape(shape1);
+
+
+	m_resultOut->setShapeIdentifiersA(m_part0,m_triface0);
+	m_resultOut->setShapeIdentifiersB(m_part1,m_triface1);
+
+	checkConvexAlgorithm(body0,body1);
+	m_convex_algorithm->processCollision(body0,body1,*m_dispatchInfo,m_resultOut);
+
+	body0->internalSetTemporaryCollisionShape(tmpShape0);
+	body1->internalSetTemporaryCollisionShape(tmpShape1);
+
+}
+
+
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs(
+					  const btTransform & trans0,
+					  const btTransform & trans1,
+					  btGImpactShapeInterface * shape0,
+					  btGImpactShapeInterface * shape1,btPairSet & pairset)
+{
+	if(shape0->hasBoxSet() && shape1->hasBoxSet())
+	{
+		btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset);
+	}
+	else
+	{
+		btAABB boxshape0;
+		btAABB boxshape1;
+		int i = shape0->getNumChildShapes();
+
+		while(i--)
+		{
+			shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
+
+			int j = shape1->getNumChildShapes();
+			while(j--)
+			{
+				shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max);
+
+				if(boxshape1.has_collision(boxshape0))
+				{
+					pairset.push_pair(i,j);
+				}
+			}
+		}
+	}
+
+
+}
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs(
+					  const btTransform & trans0,
+					  const btTransform & trans1,
+					  btGImpactShapeInterface * shape0,
+					  btCollisionShape * shape1,
+					  btAlignedObjectArray<int> & collided_primitives)
+{
+
+	btAABB boxshape;
+
+
+	if(shape0->hasBoxSet())
+	{
+		btTransform trans1to0 = trans0.inverse();
+		trans1to0 *= trans1;
+
+		shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max);
+
+		shape0->getBoxSet()->boxQuery(boxshape, collided_primitives);
+	}
+	else
+	{
+		shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max);
+
+		btAABB boxshape0;
+		int i = shape0->getNumChildShapes();
+
+		while(i--)
+		{
+			shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max);
+
+			if(boxshape.has_collision(boxshape0))
+			{
+				collided_primitives.push_back(i);
+			}
+		}
+
+	}
+
+}
+
+
+void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body0,
+				  btCollisionObject * body1,
+				  btGImpactMeshShapePart * shape0,
+				  btGImpactMeshShapePart * shape1,
+				  const int * pairs, int pair_count)
+{
+	btTriangleShapeEx tri0;
+	btTriangleShapeEx tri1;
+
+	shape0->lockChildShapes();
+	shape1->lockChildShapes();
+
+	const int * pair_pointer = pairs;
+
+	while(pair_count--)
+	{
+
+		m_triface0 = *(pair_pointer);
+		m_triface1 = *(pair_pointer+1);
+		pair_pointer+=2;
+
+
+
+		shape0->getBulletTriangle(m_triface0,tri0);
+		shape1->getBulletTriangle(m_triface1,tri1);
+
+
+		//collide two convex shapes
+		if(tri0.overlap_test_conservative(tri1))
+		{
+			convex_vs_convex_collision(body0,body1,&tri0,&tri1);
+		}
+
+	}
+
+	shape0->unlockChildShapes();
+	shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactMeshShapePart * shape0,
+					  btGImpactMeshShapePart * shape1,
+					  const int * pairs, int pair_count)
+{
+	btTransform orgtrans0 = body0->getWorldTransform();
+	btTransform orgtrans1 = body1->getWorldTransform();
+
+	btPrimitiveTriangle ptri0;
+	btPrimitiveTriangle ptri1;
+	GIM_TRIANGLE_CONTACT contact_data;
+
+	shape0->lockChildShapes();
+	shape1->lockChildShapes();
+
+	const int * pair_pointer = pairs;
+
+	while(pair_count--)
+	{
+
+		m_triface0 = *(pair_pointer);
+		m_triface1 = *(pair_pointer+1);
+		pair_pointer+=2;
+
+
+		shape0->getPrimitiveTriangle(m_triface0,ptri0);
+		shape1->getPrimitiveTriangle(m_triface1,ptri1);
+
+		#ifdef TRI_COLLISION_PROFILING
+		bt_begin_gim02_tri_time();
+		#endif
+
+		ptri0.applyTransform(orgtrans0);
+		ptri1.applyTransform(orgtrans1);
+
+
+		//build planes
+		ptri0.buildTriPlane();
+		ptri1.buildTriPlane();
+		// test conservative
+
+
+
+		if(ptri0.overlap_test_conservative(ptri1))
+		{
+			if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data))
+			{
+
+				int j = contact_data.m_point_count;
+				while(j--)
+				{
+
+					addContactPoint(body0, body1,
+								contact_data.m_points[j],
+								contact_data.m_separating_normal,
+								-contact_data.m_penetration_depth);
+				}
+			}
+		}
+
+		#ifdef TRI_COLLISION_PROFILING
+		bt_end_gim02_tri_time();
+		#endif
+
+	}
+
+	shape0->unlockChildShapes();
+	shape1->unlockChildShapes();
+
+}
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_gimpact(
+						btCollisionObject * body0,
+					   	btCollisionObject * body1,
+					  	btGImpactShapeInterface * shape0,
+					  	btGImpactShapeInterface * shape1)
+{
+
+	if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+	{
+		btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
+		m_part0 = meshshape0->getMeshPartCount();
+
+		while(m_part0--)
+		{
+			gimpact_vs_gimpact(body0,body1,meshshape0->getMeshPart(m_part0),shape1);
+		}
+
+		return;
+	}
+
+	if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+	{
+		btGImpactMeshShape * meshshape1 = static_cast<btGImpactMeshShape *>(shape1);
+		m_part1 = meshshape1->getMeshPartCount();
+
+		while(m_part1--)
+		{
+
+			gimpact_vs_gimpact(body0,body1,shape0,meshshape1->getMeshPart(m_part1));
+
+		}
+
+		return;
+	}
+
+
+	btTransform orgtrans0 = body0->getWorldTransform();
+	btTransform orgtrans1 = body1->getWorldTransform();
+
+	btPairSet pairset;
+
+	gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset);
+
+	if(pairset.size()== 0) return;
+
+	if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+		shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART)
+	{
+		btGImpactMeshShapePart * shapepart0 = static_cast<btGImpactMeshShapePart * >(shape0);
+		btGImpactMeshShapePart * shapepart1 = static_cast<btGImpactMeshShapePart * >(shape1);
+		//specialized function
+		#ifdef BULLET_TRIANGLE_COLLISION
+		collide_gjk_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
+		#else
+		collide_sat_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size());
+		#endif
+
+		return;
+	}
+
+	//general function
+
+	shape0->lockChildShapes();
+	shape1->lockChildShapes();
+
+	GIM_ShapeRetriever retriever0(shape0);
+	GIM_ShapeRetriever retriever1(shape1);
+
+	bool child_has_transform0 = shape0->childrenHasTransform();
+	bool child_has_transform1 = shape1->childrenHasTransform();
+
+	int i = pairset.size();
+	while(i--)
+	{
+		GIM_PAIR * pair = &pairset[i];
+		m_triface0 = pair->m_index1;
+		m_triface1 = pair->m_index2;
+		btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0);
+		btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1);
+
+		if(child_has_transform0)
+		{
+			body0->setWorldTransform(orgtrans0*shape0->getChildTransform(m_triface0));
+		}
+
+		if(child_has_transform1)
+		{
+			body1->setWorldTransform(orgtrans1*shape1->getChildTransform(m_triface1));
+		}
+
+		//collide two convex shapes
+		convex_vs_convex_collision(body0,body1,colshape0,colshape1);
+
+
+		if(child_has_transform0)
+		{
+			body0->setWorldTransform(orgtrans0);
+		}
+
+		if(child_has_transform1)
+		{
+			body1->setWorldTransform(orgtrans1);
+		}
+
+	}
+
+	shape0->unlockChildShapes();
+	shape1->unlockChildShapes();
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0,
+				  btCollisionObject * body1,
+				  btGImpactShapeInterface * shape0,
+				  btCollisionShape * shape1,bool swapped)
+{
+	if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE)
+	{
+		btGImpactMeshShape * meshshape0 = static_cast<btGImpactMeshShape *>(shape0);
+		int& part = swapped ? m_part1 : m_part0;
+		part = meshshape0->getMeshPartCount();
+
+		while(part--)
+		{
+
+			gimpact_vs_shape(body0,
+				  body1,
+				  meshshape0->getMeshPart(part),
+				  shape1,swapped);
+
+		}
+
+		return;
+	}
+
+	#ifdef GIMPACT_VS_PLANE_COLLISION
+	if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART &&
+		shape1->getShapeType() == STATIC_PLANE_PROXYTYPE)
+	{
+		btGImpactMeshShapePart * shapepart = static_cast<btGImpactMeshShapePart *>(shape0);
+		btStaticPlaneShape * planeshape = static_cast<btStaticPlaneShape * >(shape1);
+		gimpacttrimeshpart_vs_plane_collision(body0,body1,shapepart,planeshape,swapped);
+		return;
+	}
+
+	#endif
+
+
+
+	if(shape1->isCompound())
+	{
+		btCompoundShape * compoundshape = static_cast<btCompoundShape *>(shape1);
+		gimpact_vs_compoundshape(body0,body1,shape0,compoundshape,swapped);
+		return;
+	}
+	else if(shape1->isConcave())
+	{
+		btConcaveShape * concaveshape = static_cast<btConcaveShape *>(shape1);
+		gimpact_vs_concave(body0,body1,shape0,concaveshape,swapped);
+		return;
+	}
+
+
+	btTransform orgtrans0 = body0->getWorldTransform();
+
+	btTransform orgtrans1 = body1->getWorldTransform();
+
+	btAlignedObjectArray<int> collided_results;
+
+	gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results);
+
+	if(collided_results.size() == 0) return;
+
+
+	shape0->lockChildShapes();
+
+	GIM_ShapeRetriever retriever0(shape0);
+
+
+	bool child_has_transform0 = shape0->childrenHasTransform();
+
+
+	int i = collided_results.size();
+
+	while(i--)
+	{
+		int child_index = collided_results[i];
+        if(swapped)
+    		m_triface1 = child_index;
+        else
+            m_triface0 = child_index;
+
+		btCollisionShape * colshape0 = retriever0.getChildShape(child_index);
+
+		if(child_has_transform0)
+		{
+			body0->setWorldTransform(orgtrans0*shape0->getChildTransform(child_index));
+		}
+
+		//collide two shapes
+		if(swapped)
+		{
+			shape_vs_shape_collision(body1,body0,shape1,colshape0);
+		}
+		else
+		{
+			shape_vs_shape_collision(body0,body1,colshape0,shape1);
+		}
+
+		//restore transforms
+		if(child_has_transform0)
+		{
+			body0->setWorldTransform(orgtrans0);
+		}
+
+	}
+
+	shape0->unlockChildShapes();
+
+}
+
+void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(btCollisionObject * body0,
+				  btCollisionObject * body1,
+				  btGImpactShapeInterface * shape0,
+				  btCompoundShape * shape1,bool swapped)
+{
+	btTransform orgtrans1 = body1->getWorldTransform();
+
+	int i = shape1->getNumChildShapes();
+	while(i--)
+	{
+
+		btCollisionShape * colshape1 = shape1->getChildShape(i);
+		btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i);
+
+		body1->setWorldTransform(childtrans1);
+
+		//collide child shape
+		gimpact_vs_shape(body0, body1,
+					  shape0,colshape1,swapped);
+
+
+		//restore transforms
+		body1->setWorldTransform(orgtrans1);
+	}
+}
+
+void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision(
+					  btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactMeshShapePart * shape0,
+					  btStaticPlaneShape * shape1,bool swapped)
+{
+
+
+	btTransform orgtrans0 = body0->getWorldTransform();
+	btTransform orgtrans1 = body1->getWorldTransform();
+
+	btPlaneShape * planeshape = static_cast<btPlaneShape *>(shape1);
+	btVector4 plane;
+	planeshape->get_plane_equation_transformed(orgtrans1,plane);
+
+	//test box against plane
+
+	btAABB tribox;
+	shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max);
+	tribox.increment_margin(planeshape->getMargin());
+
+	if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return;
+
+	shape0->lockChildShapes();
+
+	btScalar margin = shape0->getMargin() + planeshape->getMargin();
+
+	btVector3 vertex;
+	int vi = shape0->getVertexCount();
+	while(vi--)
+	{
+		shape0->getVertex(vi,vertex);
+		vertex = orgtrans0(vertex);
+
+		btScalar distance = vertex.dot(plane) - plane[3] - margin;
+
+		if(distance<0.0)//add contact
+		{
+			if(swapped)
+			{
+				addContactPoint(body1, body0,
+					vertex,
+					-plane,
+					distance);
+			}
+			else
+			{
+				addContactPoint(body0, body1,
+					vertex,
+					plane,
+					distance);
+			}
+		}
+	}
+
+	shape0->unlockChildShapes();
+}
+
+
+
+
+class btGImpactTriangleCallback: public btTriangleCallback
+{
+public:
+	btGImpactCollisionAlgorithm * algorithm;
+	btCollisionObject * body0;
+	btCollisionObject * body1;
+	btGImpactShapeInterface * gimpactshape0;
+	bool swapped;
+	btScalar margin;
+
+	virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex)
+	{
+		btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]);
+		tri1.setMargin(margin);
+        if(swapped)
+        {
+            algorithm->setPart0(partId);
+            algorithm->setFace0(triangleIndex);
+        }
+        else
+        {
+            algorithm->setPart1(partId);
+            algorithm->setFace1(triangleIndex);
+        }
+		algorithm->gimpact_vs_shape(
+							body0,body1,gimpactshape0,&tri1,swapped);
+	}
+};
+
+
+
+
+void btGImpactCollisionAlgorithm::gimpact_vs_concave(
+				  btCollisionObject * body0,
+				  btCollisionObject * body1,
+				  btGImpactShapeInterface * shape0,
+				  btConcaveShape * shape1,bool swapped)
+{
+	//create the callback
+	btGImpactTriangleCallback tricallback;
+	tricallback.algorithm = this;
+	tricallback.body0 = body0;
+	tricallback.body1 = body1;
+	tricallback.gimpactshape0 = shape0;
+	tricallback.swapped = swapped;
+	tricallback.margin = shape1->getMargin();
+
+	//getting the trimesh AABB
+	btTransform gimpactInConcaveSpace;
+
+	gimpactInConcaveSpace = body1->getWorldTransform().inverse() * body0->getWorldTransform();
+
+	btVector3 minAABB,maxAABB;
+	shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB);
+
+	shape1->processAllTriangles(&tricallback,minAABB,maxAABB);
+
+}
+
+
+
+void btGImpactCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+    clearCache();
+
+    m_resultOut = resultOut;
+	m_dispatchInfo = &dispatchInfo;
+    btGImpactShapeInterface * gimpactshape0;
+    btGImpactShapeInterface * gimpactshape1;
+
+	if (body0->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE)
+	{
+		gimpactshape0 = static_cast<btGImpactShapeInterface *>(body0->getCollisionShape());
+
+		if( body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+		{
+			gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
+
+			gimpact_vs_gimpact(body0,body1,gimpactshape0,gimpactshape1);
+		}
+		else
+		{
+			gimpact_vs_shape(body0,body1,gimpactshape0,body1->getCollisionShape(),false);
+		}
+
+	}
+	else if (body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE )
+	{
+		gimpactshape1 = static_cast<btGImpactShapeInterface *>(body1->getCollisionShape());
+
+		gimpact_vs_shape(body1,body0,gimpactshape1,body0->getCollisionShape(),true);
+	}
+}
+
+
+btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut)
+{
+	return 1.f;
+
+}
+
+///////////////////////////////////// REGISTERING ALGORITHM //////////////////////////////////////////////
+
+btGImpactCollisionAlgorithm::CreateFunc g_gimpact_cf;
+
+//! Use this function for register the algorithm externally
+void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher)
+{
+
+	int i;
+
+	for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+	{
+		dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&g_gimpact_cf);
+	}
+
+	for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ )
+	{
+		dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&g_gimpact_cf);
+	}
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h
new file mode 100644
index 0000000..050fbdb
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactCollisionAlgorithm.h
@@ -0,0 +1,306 @@
+/*! \file btGImpactShape.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BVH_CONCAVE_COLLISION_ALGORITHM_H
+#define BVH_CONCAVE_COLLISION_ALGORITHM_H
+
+#include "BulletCollision/CollisionDispatch/btActivatingCollisionAlgorithm.h"
+#include "BulletCollision/BroadphaseCollision/btDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h"
+class btDispatcher;
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btGImpactShape.h"
+#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h"
+#include "BulletCollision/CollisionShapes/btCompoundShape.h"
+#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h"
+#include "LinearMath/btIDebugDraw.h"
+
+
+
+//! Collision Algorithm for GImpact Shapes
+/*!
+For register this algorithm in Bullet, proceed as following:
+ \code
+btCollisionDispatcher * dispatcher = static_cast<btCollisionDispatcher *>(m_dynamicsWorld ->getDispatcher());
+btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher);
+ \endcode
+*/
+class btGImpactCollisionAlgorithm : public btActivatingCollisionAlgorithm
+{
+protected:
+	btCollisionAlgorithm * m_convex_algorithm;
+    btPersistentManifold * m_manifoldPtr;
+	btManifoldResult* m_resultOut;
+	const btDispatcherInfo * m_dispatchInfo;
+	int m_triface0;
+	int m_part0;
+	int m_triface1;
+	int m_part1;
+
+
+	//! Creates a new contact point
+	SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1)
+	{
+		m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1);
+		return m_manifoldPtr;
+	}
+
+	SIMD_FORCE_INLINE void destroyConvexAlgorithm()
+	{
+		if(m_convex_algorithm)
+		{
+			m_convex_algorithm->~btCollisionAlgorithm();
+			m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm);
+			m_convex_algorithm = NULL;
+		}
+	}
+
+	SIMD_FORCE_INLINE void destroyContactManifolds()
+	{
+		if(m_manifoldPtr == NULL) return;
+		m_dispatcher->releaseManifold(m_manifoldPtr);
+		m_manifoldPtr = NULL;
+	}
+
+	SIMD_FORCE_INLINE void clearCache()
+	{
+		destroyContactManifolds();
+		destroyConvexAlgorithm();
+
+		m_triface0 = -1;
+		m_part0 = -1;
+		m_triface1 = -1;
+		m_part1 = -1;
+	}
+
+	SIMD_FORCE_INLINE btPersistentManifold* getLastManifold()
+	{
+		return m_manifoldPtr;
+	}
+
+
+	// Call before process collision
+	SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1)
+	{
+		if(getLastManifold() == 0)
+		{
+			newContactManifold(body0,body1);
+		}
+
+		m_resultOut->setPersistentManifold(getLastManifold());
+	}
+
+	// Call before process collision
+	SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
+	{
+		checkManifold(body0,body1);
+
+		btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm(
+				body0,body1,getLastManifold());
+		return convex_algorithm ;
+	}
+
+	// Call before process collision
+	SIMD_FORCE_INLINE void checkConvexAlgorithm(btCollisionObject* body0,btCollisionObject* body1)
+	{
+		if(m_convex_algorithm) return;
+		m_convex_algorithm = newAlgorithm(body0,body1);
+	}
+
+
+
+
+	void addContactPoint(btCollisionObject * body0,
+					btCollisionObject * body1,
+					const btVector3 & point,
+					const btVector3 & normal,
+					btScalar distance);
+
+//! Collision routines
+//!@{
+
+	void collide_gjk_triangles(btCollisionObject * body0,
+				  btCollisionObject * body1,
+				  btGImpactMeshShapePart * shape0,
+				  btGImpactMeshShapePart * shape1,
+				  const int * pairs, int pair_count);
+
+	void collide_sat_triangles(btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactMeshShapePart * shape0,
+					  btGImpactMeshShapePart * shape1,
+					  const int * pairs, int pair_count);
+
+
+
+
+	void shape_vs_shape_collision(
+					  btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btCollisionShape * shape0,
+					  btCollisionShape * shape1);
+
+	void convex_vs_convex_collision(btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btCollisionShape * shape0,
+					  btCollisionShape * shape1);
+
+
+
+	void gimpact_vs_gimpact_find_pairs(
+					  const btTransform & trans0,
+					  const btTransform & trans1,
+					  btGImpactShapeInterface * shape0,
+					  btGImpactShapeInterface * shape1,btPairSet & pairset);
+
+	void gimpact_vs_shape_find_pairs(
+					  const btTransform & trans0,
+					  const btTransform & trans1,
+					  btGImpactShapeInterface * shape0,
+					  btCollisionShape * shape1,
+					  btAlignedObjectArray<int> & collided_primitives);
+
+
+	void gimpacttrimeshpart_vs_plane_collision(
+					  btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactMeshShapePart * shape0,
+					  btStaticPlaneShape * shape1,bool swapped);
+
+
+public:
+
+	btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1);
+
+	virtual ~btGImpactCollisionAlgorithm();
+
+	virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	btScalar	calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut);
+
+	virtual	void	getAllContactManifolds(btManifoldArray&	manifoldArray)
+	{
+		if (m_manifoldPtr)
+			manifoldArray.push_back(m_manifoldPtr);
+	}
+
+
+	struct CreateFunc :public 	btCollisionAlgorithmCreateFunc
+	{
+		virtual	btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1)
+		{
+			void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm));
+			return new(mem) btGImpactCollisionAlgorithm(ci,body0,body1);
+		}
+	};
+
+	//! Use this function for register the algorithm externally
+	static void registerAlgorithm(btCollisionDispatcher * dispatcher);
+
+	//! Gets the average time in miliseconds of tree collisions
+	static float getAverageTreeCollisionTime();
+
+	//! Gets the average time in miliseconds of triangle collisions
+	static float getAverageTriangleCollisionTime();
+
+
+	//! Collides two gimpact shapes
+	/*!
+	\pre shape0 and shape1 couldn't be btGImpactMeshShape objects
+	*/
+
+
+	void gimpact_vs_gimpact(btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactShapeInterface * shape0,
+					  btGImpactShapeInterface * shape1);
+
+	void gimpact_vs_shape(btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactShapeInterface * shape0,
+					  btCollisionShape * shape1,bool swapped);
+
+	void gimpact_vs_compoundshape(btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactShapeInterface * shape0,
+					  btCompoundShape * shape1,bool swapped);
+
+	void gimpact_vs_concave(
+					  btCollisionObject * body0,
+					  btCollisionObject * body1,
+					  btGImpactShapeInterface * shape0,
+					  btConcaveShape * shape1,bool swapped);
+
+
+
+
+		/// Accessor/Mutator pairs for Part and triangleID
+    void 	setFace0(int value) 
+    { 
+    	m_triface0 = value; 
+    }
+    int getFace0() 
+    { 
+    	return m_triface0; 
+    }
+    void setFace1(int value) 
+    { 
+    	m_triface1 = value; 
+    }
+    int getFace1() 
+    { 
+    	return m_triface1; 
+    }
+    void setPart0(int value) 
+    { 
+    	m_part0 = value; 
+    }
+    int getPart0() 
+    { 
+    	return m_part0; 
+    }
+    void setPart1(int value) 
+    { 
+    	m_part1 = value; 
+		}
+    int getPart1() 
+    { 
+    	return m_part1; 
+    }
+
+};
+
+
+//algorithm details
+//#define BULLET_TRIANGLE_COLLISION 1
+#define GIMPACT_VS_PLANE_COLLISION 1  //***ALEX***
+
+
+
+#endif //BVH_CONCAVE_COLLISION_ALGORITHM_H
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactMassUtil.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactMassUtil.h
new file mode 100644
index 0000000..0a10f3c
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactMassUtil.h
@@ -0,0 +1,60 @@
+/*! \file btGImpactMassUtil.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef GIMPACT_MASS_UTIL_H
+#define GIMPACT_MASS_UTIL_H
+
+#include "LinearMath/btTransform.h"
+
+
+
+SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed(
+	const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform)
+{
+	btMatrix3x3  rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose();
+
+	btScalar x2 = transform.getOrigin()[0];
+	x2*= x2;
+	btScalar y2 = transform.getOrigin()[1];
+	y2*= y2;
+	btScalar z2 = transform.getOrigin()[2];
+	z2*= z2;
+
+	btScalar ix = rotatedTensor[0][0]*(y2+z2);
+	btScalar iy = rotatedTensor[1][1]*(x2+z2);
+	btScalar iz = rotatedTensor[2][2]*(x2+y2);
+
+	return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz);
+}
+
+SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass)
+{
+	btScalar x2 = point[0]*point[0];
+	btScalar y2 = point[1]*point[1];
+	btScalar z2 = point[2]*point[2];
+	return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2));
+}
+
+
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.cpp
new file mode 100644
index 0000000..ea1647a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.cpp
@@ -0,0 +1,528 @@
+/*! \file gim_box_set.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGImpactQuantizedBvh.h"
+#include "LinearMath/btQuickprof.h"
+
+#ifdef TRI_COLLISION_PROFILING
+btClock g_q_tree_clock;
+
+
+float g_q_accum_tree_collision_time = 0;
+int g_q_count_traversing = 0;
+
+
+void bt_begin_gim02_q_tree_time()
+{
+	g_q_tree_clock.reset();
+}
+
+void bt_end_gim02_q_tree_time()
+{
+	g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds();
+	g_q_count_traversing++;
+}
+
+
+//! Gets the average time in miliseconds of tree collisions
+float btGImpactQuantizedBvh::getAverageTreeCollisionTime()
+{
+	if(g_q_count_traversing == 0) return 0;
+
+	float avgtime = g_q_accum_tree_collision_time;
+	avgtime /= (float)g_q_count_traversing;
+
+	g_q_accum_tree_collision_time = 0;
+	g_q_count_traversing = 0;
+	return avgtime;
+
+//	float avgtime = g_q_count_traversing;
+//	g_q_count_traversing = 0;
+//	return avgtime;
+
+}
+
+#endif //TRI_COLLISION_PROFILING
+
+/////////////////////// btQuantizedBvhTree /////////////////////////////////
+
+void btQuantizedBvhTree::calc_quantization(
+	GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin)
+{
+	//calc globa box
+	btAABB global_bound;
+	global_bound.invalidate();
+
+	for (int i=0;i<primitive_boxes.size() ;i++ )
+	{
+		global_bound.merge(primitive_boxes[i].m_bound);
+	}
+
+	bt_calc_quantization_parameters(
+		m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization,global_bound.m_min,global_bound.m_max,boundMargin);
+
+}
+
+
+
+int btQuantizedBvhTree::_calc_splitting_axis(
+	GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex)
+{
+
+	int i;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+	int numIndices = endIndex-startIndex;
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		btVector3 diff2 = center-means;
+		diff2 = diff2 * diff2;
+		variance += diff2;
+	}
+	variance *= (btScalar(1.)/	((btScalar)numIndices-1)	);
+
+	return variance.maxAxis();
+}
+
+
+int btQuantizedBvhTree::_sort_and_calc_splitting_index(
+	GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,
+	int endIndex, int splitAxis)
+{
+	int i;
+	int splitIndex =startIndex;
+	int numIndices = endIndex - startIndex;
+
+	// average of centers
+	btScalar splitValue = 0.0f;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+
+	splitValue = means[splitAxis];
+
+
+	//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		if (center[splitAxis] > splitValue)
+		{
+			//swap
+			primitive_boxes.swap(i,splitIndex);
+			//swapLeafNodes(i,splitIndex);
+			splitIndex++;
+		}
+	}
+
+	//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+	//otherwise the tree-building might fail due to stack-overflows in certain cases.
+	//unbalanced1 is unsafe: it can cause stack overflows
+	//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+	//unbalanced2 should work too: always use center (perfect balanced trees)
+	//bool unbalanced2 = true;
+
+	//this should be safe too:
+	int rangeBalancedIndices = numIndices/3;
+	bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+	if (unbalanced)
+	{
+		splitIndex = startIndex+ (numIndices>>1);
+	}
+
+	btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+
+	return splitIndex;
+
+}
+
+
+void btQuantizedBvhTree::_build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex)
+{
+	int curIndex = m_num_nodes;
+	m_num_nodes++;
+
+	btAssert((endIndex-startIndex)>0);
+
+	if ((endIndex-startIndex)==1)
+	{
+	    //We have a leaf node
+	    setNodeBound(curIndex,primitive_boxes[startIndex].m_bound);
+		m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data);
+
+		return;
+	}
+	//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+	//split axis
+	int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+
+	splitIndex = _sort_and_calc_splitting_index(
+			primitive_boxes,startIndex,endIndex,
+			splitIndex//split axis
+			);
+
+
+	//calc this node bounding box
+
+	btAABB node_bound;
+	node_bound.invalidate();
+
+	for (int i=startIndex;i<endIndex;i++)
+	{
+		node_bound.merge(primitive_boxes[i].m_bound);
+	}
+
+	setNodeBound(curIndex,node_bound);
+
+
+	//build left branch
+	_build_sub_tree(primitive_boxes, startIndex, splitIndex );
+
+
+	//build right branch
+	 _build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+
+	m_node_array[curIndex].setEscapeIndex(m_num_nodes - curIndex);
+
+
+}
+
+//! stackless build tree
+void btQuantizedBvhTree::build_tree(
+	GIM_BVH_DATA_ARRAY & primitive_boxes)
+{
+	calc_quantization(primitive_boxes);
+	// initialize node count to 0
+	m_num_nodes = 0;
+	// allocate nodes
+	m_node_array.resize(primitive_boxes.size()*2);
+
+	_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+////////////////////////////////////class btGImpactQuantizedBvh
+
+void btGImpactQuantizedBvh::refit()
+{
+	int nodecount = getNodeCount();
+	while(nodecount--)
+	{
+		if(isLeafNode(nodecount))
+		{
+			btAABB leafbox;
+			m_primitive_manager->get_primitive_box(getNodeData(nodecount),leafbox);
+			setNodeBound(nodecount,leafbox);
+		}
+		else
+		{
+			//const GIM_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount);
+			//get left bound
+			btAABB bound;
+			bound.invalidate();
+
+			btAABB temp_box;
+
+			int child_node = getLeftNode(nodecount);
+			if(child_node)
+			{
+				getNodeBound(child_node,temp_box);
+				bound.merge(temp_box);
+			}
+
+			child_node = getRightNode(nodecount);
+			if(child_node)
+			{
+				getNodeBound(child_node,temp_box);
+				bound.merge(temp_box);
+			}
+
+			setNodeBound(nodecount,bound);
+		}
+	}
+}
+
+//! this rebuild the entire set
+void btGImpactQuantizedBvh::buildSet()
+{
+	//obtain primitive boxes
+	GIM_BVH_DATA_ARRAY primitive_boxes;
+	primitive_boxes.resize(m_primitive_manager->get_primitive_count());
+
+	for (int i = 0;i<primitive_boxes.size() ;i++ )
+	{
+		 m_primitive_manager->get_primitive_box(i,primitive_boxes[i].m_bound);
+		 primitive_boxes[i].m_data = i;
+	}
+
+	m_box_tree.build_tree(primitive_boxes);
+}
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const
+{
+	int curIndex = 0;
+	int numNodes = getNodeCount();
+
+	//quantize box
+
+	unsigned short quantizedMin[3];
+	unsigned short quantizedMax[3];
+
+	m_box_tree.quantizePoint(quantizedMin,box.m_min);
+	m_box_tree.quantizePoint(quantizedMax,box.m_max);
+
+
+	while (curIndex < numNodes)
+	{
+
+		//catch bugs in tree data
+
+		bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax);
+		bool isleafnode = isLeafNode(curIndex);
+
+		if (isleafnode && aabbOverlap)
+		{
+			collided_results.push_back(getNodeData(curIndex));
+		}
+
+		if (aabbOverlap || isleafnode)
+		{
+			//next subnode
+			curIndex++;
+		}
+		else
+		{
+			//skip node
+			curIndex+= getEscapeNodeIndex(curIndex);
+		}
+	}
+	if(collided_results.size()>0) return true;
+	return false;
+}
+
+
+
+//! returns the indices of the primitives in the m_primitive_manager
+bool btGImpactQuantizedBvh::rayQuery(
+	const btVector3 & ray_dir,const btVector3 & ray_origin ,
+	btAlignedObjectArray<int> & collided_results) const
+{
+	int curIndex = 0;
+	int numNodes = getNodeCount();
+
+	while (curIndex < numNodes)
+	{
+		btAABB bound;
+		getNodeBound(curIndex,bound);
+
+		//catch bugs in tree data
+
+		bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+		bool isleafnode = isLeafNode(curIndex);
+
+		if (isleafnode && aabbOverlap)
+		{
+			collided_results.push_back(getNodeData( curIndex));
+		}
+
+		if (aabbOverlap || isleafnode)
+		{
+			//next subnode
+			curIndex++;
+		}
+		else
+		{
+			//skip node
+			curIndex+= getEscapeNodeIndex(curIndex);
+		}
+	}
+	if(collided_results.size()>0) return true;
+	return false;
+}
+
+
+SIMD_FORCE_INLINE bool _quantized_node_collision(
+	btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1,
+	const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+	int node0 ,int node1, bool complete_primitive_tests)
+{
+	btAABB box0;
+	boxset0->getNodeBound(node0,box0);
+	btAABB box1;
+	boxset1->getNodeBound(node1,box1);
+
+	return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests );
+//	box1.appy_transform_trans_cache(trans_cache_1to0);
+//	return box0.has_collision(box1);
+
+}
+
+
+//stackless recursive collision routine
+static void _find_quantized_collision_pairs_recursive(
+	btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1,
+	btPairSet * collision_pairs,
+	const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0,
+	int node0, int node1, bool complete_primitive_tests)
+{
+
+
+
+	if( _quantized_node_collision(
+		boxset0,boxset1,trans_cache_1to0,
+		node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes
+
+	if(boxset0->isLeafNode(node0))
+	{
+		if(boxset1->isLeafNode(node1))
+		{
+			// collision result
+			collision_pairs->push_pair(
+				boxset0->getNodeData(node0),boxset1->getNodeData(node1));
+			return;
+		}
+		else
+		{
+
+			//collide left recursive
+
+			_find_quantized_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								node0,boxset1->getLeftNode(node1),false);
+
+			//collide right recursive
+			_find_quantized_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								node0,boxset1->getRightNode(node1),false);
+
+
+		}
+	}
+	else
+	{
+		if(boxset1->isLeafNode(node1))
+		{
+
+			//collide left recursive
+			_find_quantized_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								boxset0->getLeftNode(node0),node1,false);
+
+
+			//collide right recursive
+
+			_find_quantized_collision_pairs_recursive(
+								boxset0,boxset1,
+								collision_pairs,trans_cache_1to0,
+								boxset0->getRightNode(node0),node1,false);
+
+
+		}
+		else
+		{
+			//collide left0 left1
+
+
+
+			_find_quantized_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false);
+
+			//collide left0 right1
+
+			_find_quantized_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false);
+
+
+			//collide right0 left1
+
+			_find_quantized_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false);
+
+			//collide right0 right1
+
+			_find_quantized_collision_pairs_recursive(
+				boxset0,boxset1,
+				collision_pairs,trans_cache_1to0,
+				boxset0->getRightNode(node0),boxset1->getRightNode(node1),false);
+
+		}// else if node1 is not a leaf
+	}// else if node0 is not a leaf
+}
+
+
+void btGImpactQuantizedBvh::find_collision(btGImpactQuantizedBvh * boxset0, const btTransform & trans0,
+		btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
+		btPairSet & collision_pairs)
+{
+
+	if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return;
+
+	BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+
+	trans_cache_1to0.calc_from_homogenic(trans0,trans1);
+
+#ifdef TRI_COLLISION_PROFILING
+	bt_begin_gim02_q_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+	_find_quantized_collision_pairs_recursive(
+		boxset0,boxset1,
+		&collision_pairs,trans_cache_1to0,0,0,true);
+#ifdef TRI_COLLISION_PROFILING
+	bt_end_gim02_q_tree_time();
+#endif //TRI_COLLISION_PROFILING
+
+}
+
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.h
new file mode 100644
index 0000000..e9cccac
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactQuantizedBvh.h
@@ -0,0 +1,372 @@
+#ifndef GIM_QUANTIZED_SET_H_INCLUDED
+#define GIM_QUANTIZED_SET_H_INCLUDED
+
+/*! \file btGImpactQuantizedBvh.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGImpactBvh.h"
+#include "btQuantization.h"
+
+
+
+
+
+///btQuantizedBvhNode is a compressed aabb node, 16 bytes.
+///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range).
+ATTRIBUTE_ALIGNED16	(struct) BT_QUANTIZED_BVH_NODE
+{
+	//12 bytes
+	unsigned short int	m_quantizedAabbMin[3];
+	unsigned short int	m_quantizedAabbMax[3];
+	//4 bytes
+	int	m_escapeIndexOrDataIndex;
+
+	BT_QUANTIZED_BVH_NODE()
+	{
+		m_escapeIndexOrDataIndex = 0;
+	}
+
+	SIMD_FORCE_INLINE bool isLeafNode() const
+	{
+		//skipindex is negative (internal node), triangleindex >=0 (leafnode)
+		return (m_escapeIndexOrDataIndex>=0);
+	}
+
+	SIMD_FORCE_INLINE int getEscapeIndex() const
+	{
+		//btAssert(m_escapeIndexOrDataIndex < 0);
+		return -m_escapeIndexOrDataIndex;
+	}
+
+	SIMD_FORCE_INLINE void setEscapeIndex(int index)
+	{
+		m_escapeIndexOrDataIndex = -index;
+	}
+
+	SIMD_FORCE_INLINE int getDataIndex() const
+	{
+		//btAssert(m_escapeIndexOrDataIndex >= 0);
+
+		return m_escapeIndexOrDataIndex;
+	}
+
+	SIMD_FORCE_INLINE void setDataIndex(int index)
+	{
+		m_escapeIndexOrDataIndex = index;
+	}
+
+	SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
+		unsigned short * quantizedMin,unsigned short * quantizedMax) const
+	{
+		if(m_quantizedAabbMin[0] > quantizedMax[0] ||
+		   m_quantizedAabbMax[0] < quantizedMin[0] ||
+		   m_quantizedAabbMin[1] > quantizedMax[1] ||
+		   m_quantizedAabbMax[1] < quantizedMin[1] ||
+		   m_quantizedAabbMin[2] > quantizedMax[2] ||
+		   m_quantizedAabbMax[2] < quantizedMin[2])
+		{
+			return false;
+		}
+		return true;
+	}
+
+};
+
+
+
+class GIM_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray<BT_QUANTIZED_BVH_NODE>
+{
+};
+
+
+
+
+//! Basic Box tree structure
+class btQuantizedBvhTree
+{
+protected:
+	int m_num_nodes;
+	GIM_QUANTIZED_BVH_NODE_ARRAY m_node_array;
+	btAABB m_global_bound;
+	btVector3 m_bvhQuantization;
+protected:
+	void calc_quantization(GIM_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) );
+
+	int _sort_and_calc_splitting_index(
+		GIM_BVH_DATA_ARRAY & primitive_boxes,
+		 int startIndex,  int endIndex, int splitAxis);
+
+	int _calc_splitting_axis(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+
+	void _build_sub_tree(GIM_BVH_DATA_ARRAY & primitive_boxes, int startIndex,  int endIndex);
+public:
+	btQuantizedBvhTree()
+	{
+		m_num_nodes = 0;
+	}
+
+	//! prototype functions for box tree management
+	//!@{
+	void build_tree(GIM_BVH_DATA_ARRAY & primitive_boxes);
+
+	SIMD_FORCE_INLINE void quantizePoint(
+		unsigned short * quantizedpoint, const btVector3 & point) const
+	{
+		bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization);
+	}
+
+
+	SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp(
+		int node_index,
+		unsigned short * quantizedMin,unsigned short * quantizedMax) const
+	{
+		return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax);
+	}
+
+	SIMD_FORCE_INLINE void clearNodes()
+	{
+		m_node_array.clear();
+		m_num_nodes = 0;
+	}
+
+	//! node count
+	SIMD_FORCE_INLINE int getNodeCount() const
+	{
+		return m_num_nodes;
+	}
+
+	//! tells if the node is a leaf
+	SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+	{
+		return m_node_array[nodeindex].isLeafNode();
+	}
+
+	SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+	{
+		return m_node_array[nodeindex].getDataIndex();
+	}
+
+	SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const
+	{
+		bound.m_min = bt_unquantize(
+			m_node_array[nodeindex].m_quantizedAabbMin,
+			m_global_bound.m_min,m_bvhQuantization);
+
+		bound.m_max = bt_unquantize(
+			m_node_array[nodeindex].m_quantizedAabbMax,
+			m_global_bound.m_min,m_bvhQuantization);
+	}
+
+	SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+	{
+		bt_quantize_clamp(	m_node_array[nodeindex].m_quantizedAabbMin,
+							bound.m_min,
+							m_global_bound.m_min,
+							m_global_bound.m_max,
+							m_bvhQuantization);
+
+		bt_quantize_clamp(	m_node_array[nodeindex].m_quantizedAabbMax,
+							bound.m_max,
+							m_global_bound.m_min,
+							m_global_bound.m_max,
+							m_bvhQuantization);
+	}
+
+	SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+	{
+		return nodeindex+1;
+	}
+
+	SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+	{
+		if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2;
+		return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex();
+	}
+
+	SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+	{
+		return m_node_array[nodeindex].getEscapeIndex();
+	}
+
+	SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
+	{
+		return &m_node_array[index];
+	}
+
+	//!@}
+};
+
+
+
+//! Structure for containing Boxes
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like btPrimitiveManagerBase )
+*/
+class btGImpactQuantizedBvh
+{
+protected:
+	btQuantizedBvhTree m_box_tree;
+	btPrimitiveManagerBase * m_primitive_manager;
+
+protected:
+	//stackless refit
+	void refit();
+public:
+
+	//! this constructor doesn't build the tree. you must call	buildSet
+	btGImpactQuantizedBvh()
+	{
+		m_primitive_manager = NULL;
+	}
+
+	//! this constructor doesn't build the tree. you must call	buildSet
+	btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager)
+	{
+		m_primitive_manager = primitive_manager;
+	}
+
+	SIMD_FORCE_INLINE btAABB getGlobalBox()  const
+	{
+		btAABB totalbox;
+		getNodeBound(0, totalbox);
+		return totalbox;
+	}
+
+	SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager)
+	{
+		m_primitive_manager = primitive_manager;
+	}
+
+	SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const
+	{
+		return m_primitive_manager;
+	}
+
+
+//! node manager prototype functions
+///@{
+
+	//! this attemps to refit the box set.
+	SIMD_FORCE_INLINE void update()
+	{
+		refit();
+	}
+
+	//! this rebuild the entire set
+	void buildSet();
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	bool boxQuery(const btAABB & box, btAlignedObjectArray<int> & collided_results) const;
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box,
+		 const btTransform & transform, btAlignedObjectArray<int> & collided_results) const
+	{
+		btAABB transbox=box;
+		transbox.appy_transform(transform);
+		return boxQuery(transbox,collided_results);
+	}
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	bool rayQuery(
+		const btVector3 & ray_dir,const btVector3 & ray_origin ,
+		btAlignedObjectArray<int> & collided_results) const;
+
+	//! tells if this set has hierarcht
+	SIMD_FORCE_INLINE bool hasHierarchy() const
+	{
+		return true;
+	}
+
+	//! tells if this set is a trimesh
+	SIMD_FORCE_INLINE bool isTrimesh()  const
+	{
+		return m_primitive_manager->is_trimesh();
+	}
+
+	//! node count
+	SIMD_FORCE_INLINE int getNodeCount() const
+	{
+		return m_box_tree.getNodeCount();
+	}
+
+	//! tells if the node is a leaf
+	SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const
+	{
+		return m_box_tree.isLeafNode(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE int getNodeData(int nodeindex) const
+	{
+		return m_box_tree.getNodeData(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound)  const
+	{
+		m_box_tree.getNodeBound(nodeindex, bound);
+	}
+
+	SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound)
+	{
+		m_box_tree.setNodeBound(nodeindex, bound);
+	}
+
+
+	SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const
+	{
+		return m_box_tree.getLeftNode(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE int getRightNode(int nodeindex) const
+	{
+		return m_box_tree.getRightNode(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const
+	{
+		return m_box_tree.getEscapeNodeIndex(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const
+	{
+		m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle);
+	}
+
+
+	SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const
+	{
+		return m_box_tree.get_node_pointer(index);
+	}
+
+
+	static float getAverageTreeCollisionTime();
+
+
+	static void find_collision(btGImpactQuantizedBvh * boxset1, const btTransform & trans1,
+		btGImpactQuantizedBvh * boxset2, const btTransform & trans2,
+		btPairSet & collision_pairs);
+};
+
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactShape.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactShape.cpp
new file mode 100644
index 0000000..da6a4db
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactShape.cpp
@@ -0,0 +1,183 @@
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#include "btGImpactShape.h"
+#include "btGImpactMassUtil.h"
+
+
+#define CALC_EXACT_INERTIA 1
+
+void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	lockChildShapes();
+#ifdef CALC_EXACT_INERTIA
+	inertia.setValue(0.f,0.f,0.f);
+
+	int i = this->getNumChildShapes();
+	btScalar shapemass = mass/btScalar(i);
+
+	while(i--)
+	{
+		btVector3 temp_inertia;
+		m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia);
+		if(childrenHasTransform())
+		{
+			inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]);
+		}
+		else
+		{
+			inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity());
+		}
+
+	}
+
+#else
+
+	// Calc box inertia
+
+	btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
+	btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
+	btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(0.08333333);
+
+	inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+#endif
+	unlockChildShapes();
+}
+
+
+
+void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+	lockChildShapes();
+
+
+#ifdef CALC_EXACT_INERTIA
+	inertia.setValue(0.f,0.f,0.f);
+
+	int i = this->getVertexCount();
+	btScalar pointmass = mass/btScalar(i);
+
+	while(i--)
+	{
+		btVector3 pointintertia;
+		this->getVertex(i,pointintertia);
+		pointintertia = gim_get_point_inertia(pointintertia,pointmass);
+		inertia+=pointintertia;
+	}
+
+#else
+
+	// Calc box inertia
+
+	btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
+	btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
+	btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(0.08333333);
+
+	inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+#endif
+
+	unlockChildShapes();
+}
+
+void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const
+{
+
+#ifdef CALC_EXACT_INERTIA
+	inertia.setValue(0.f,0.f,0.f);
+
+	int i = this->getMeshPartCount();
+	btScalar partmass = mass/btScalar(i);
+
+	while(i--)
+	{
+		btVector3 partinertia;
+		getMeshPart(i)->calculateLocalInertia(partmass,partinertia);
+		inertia+=partinertia;
+	}
+
+#else
+
+	// Calc box inertia
+
+	btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0];
+	btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1];
+	btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2];
+	const btScalar x2 = lx*lx;
+	const btScalar y2 = ly*ly;
+	const btScalar z2 = lz*lz;
+	const btScalar scaledmass = mass * btScalar(0.08333333);
+
+	inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2));
+
+#endif
+}
+
+void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
+{
+}
+
+
+void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	lockChildShapes();
+	btAABB box;
+	box.m_min = aabbMin;
+	box.m_max = aabbMax;
+
+	btAlignedObjectArray<int> collided;
+	m_box_set.boxQuery(box,collided);
+
+	if(collided.size()==0)
+	{
+		unlockChildShapes();
+		return;
+	}
+
+	int part = (int)getPart();
+	btPrimitiveTriangle triangle;
+	int i = collided.size();
+	while(i--)
+	{
+		this->getPrimitiveTriangle(collided[i],triangle);
+		callback->processTriangle(triangle.m_vertices,part,collided[i]);
+	}
+	unlockChildShapes();
+
+}
+
+void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+	int i = m_mesh_parts.size();
+	while(i--)
+	{
+		m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax);
+	}
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactShape.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactShape.h
new file mode 100644
index 0000000..ea57f21
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGImpactShape.h
@@ -0,0 +1,1124 @@
+/*! \file btGImpactShape.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef GIMPACT_SHAPE_H
+#define GIMPACT_SHAPE_H
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
+#include "BulletCollision/CollisionShapes/btCollisionMargin.h"
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletCollision/CollisionShapes/btConcaveShape.h"
+#include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btTransform.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+#include "btGImpactQuantizedBvh.h" // box tree class
+
+
+//! declare Quantized trees, (you can change to float based trees)
+typedef btGImpactQuantizedBvh btGImpactBoxSet;
+
+enum eGIMPACT_SHAPE_TYPE
+{
+	CONST_GIMPACT_COMPOUND_SHAPE = 0,
+	CONST_GIMPACT_TRIMESH_SHAPE_PART,
+	CONST_GIMPACT_TRIMESH_SHAPE
+};
+
+
+//! Helper class for tetrahedrons
+class btTetrahedronShapeEx:public btBU_Simplex1to4
+{
+public:
+	btTetrahedronShapeEx()
+	{
+		m_numVertices = 4;
+	}
+
+
+	SIMD_FORCE_INLINE void setVertices(
+		const btVector3 & v0,const btVector3 & v1,
+		const btVector3 & v2,const btVector3 & v3)
+	{
+		m_vertices[0] = v0;
+		m_vertices[1] = v1;
+		m_vertices[2] = v2;
+		m_vertices[3] = v3;
+		recalcLocalAabb();
+	}
+};
+
+
+//! Base class for gimpact shapes
+class btGImpactShapeInterface : public btConcaveShape
+{
+protected:
+    btAABB m_localAABB;
+    bool m_needs_update;
+    btVector3  localScaling;
+    btGImpactBoxSet m_box_set;// optionally boxset
+
+	//! use this function for perfofm refit in bounding boxes
+    //! use this function for perfofm refit in bounding boxes
+    virtual void calcLocalAABB()
+    {
+		lockChildShapes();
+    	if(m_box_set.getNodeCount() == 0)
+    	{
+    		m_box_set.buildSet();
+    	}
+    	else
+    	{
+    		m_box_set.update();
+    	}
+    	unlockChildShapes();
+
+    	m_localAABB = m_box_set.getGlobalBox();
+    }
+
+
+public:
+	btGImpactShapeInterface()
+	{
+		m_shapeType=GIMPACT_SHAPE_PROXYTYPE;
+		m_localAABB.invalidate();
+		m_needs_update = true;
+		localScaling.setValue(1.f,1.f,1.f);
+	}
+
+
+	//! performs refit operation
+	/*!
+	Updates the entire Box set of this shape.
+	\pre postUpdate() must be called for attemps to calculating the box set, else this function
+		will does nothing.
+	\post if m_needs_update == true, then it calls calcLocalAABB();
+	*/
+    SIMD_FORCE_INLINE void updateBound()
+    {
+    	if(!m_needs_update) return;
+    	calcLocalAABB();
+    	m_needs_update  = false;
+    }
+
+    //! If the Bounding box is not updated, then this class attemps to calculate it.
+    /*!
+    \post Calls updateBound() for update the box set.
+    */
+    void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+    {
+        btAABB transformedbox = m_localAABB;
+        transformedbox.appy_transform(t);
+        aabbMin = transformedbox.m_min;
+        aabbMax = transformedbox.m_max;
+    }
+
+    //! Tells to this object that is needed to refit the box set
+    virtual void postUpdate()
+    {
+    	m_needs_update = true;
+    }
+
+	//! Obtains the local box, which is the global calculated box of the total of subshapes
+	SIMD_FORCE_INLINE const btAABB & getLocalBox()
+	{
+		return m_localAABB;
+	}
+
+
+    virtual int	getShapeType() const
+    {
+        return GIMPACT_SHAPE_PROXYTYPE;
+    }
+
+    /*!
+	\post You must call updateBound() for update the box set.
+	*/
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		localScaling = scaling;
+		postUpdate();
+	}
+
+	virtual const btVector3& getLocalScaling() const
+	{
+		return localScaling;
+	}
+
+
+	virtual void setMargin(btScalar margin)
+    {
+    	m_collisionMargin = margin;
+    	int i = getNumChildShapes();
+    	while(i--)
+    	{
+			btCollisionShape* child = getChildShape(i);
+			child->setMargin(margin);
+    	}
+
+		m_needs_update = true;
+    }
+
+
+	//! Subshape member functions
+	//!@{
+
+	//! Base method for determinig which kind of GIMPACT shape we get
+	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() = 0;
+
+	//! gets boxset
+	SIMD_FORCE_INLINE btGImpactBoxSet * getBoxSet()
+	{
+		return &m_box_set;
+	}
+
+	//! Determines if this class has a hierarchy structure for sorting its primitives
+	SIMD_FORCE_INLINE bool hasBoxSet()  const
+	{
+		if(m_box_set.getNodeCount() == 0) return false;
+		return true;
+	}
+
+	//! Obtains the primitive manager
+	virtual const btPrimitiveManagerBase * getPrimitiveManager()  const = 0;
+
+
+	//! Gets the number of children
+	virtual int	getNumChildShapes() const  = 0;
+
+	//! if true, then its children must get transforms.
+	virtual bool childrenHasTransform() const = 0;
+
+	//! Determines if this shape has triangles
+	virtual bool needsRetrieveTriangles() const = 0;
+
+	//! Determines if this shape has tetrahedrons
+	virtual bool needsRetrieveTetrahedrons() const = 0;
+
+	virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0;
+
+	virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0;
+
+
+
+	//! call when reading child shapes
+	virtual void lockChildShapes() const
+	{
+	}
+
+	virtual void unlockChildShapes() const
+	{
+	}
+
+	//! if this trimesh
+	SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const
+	{
+		getPrimitiveManager()->get_primitive_triangle(index,triangle);
+	}
+
+
+	//! Retrieves the bound from a child
+    /*!
+    */
+    virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+    {
+        btAABB child_aabb;
+        getPrimitiveManager()->get_primitive_box(child_index,child_aabb);
+        child_aabb.appy_transform(t);
+        aabbMin = child_aabb.m_min;
+        aabbMax = child_aabb.m_max;
+    }
+
+	//! Gets the children
+	virtual btCollisionShape* getChildShape(int index) = 0;
+
+
+	//! Gets the child
+	virtual const btCollisionShape* getChildShape(int index) const = 0;
+
+	//! Gets the children transform
+	virtual btTransform	getChildTransform(int index) const = 0;
+
+	//! Sets the children transform
+	/*!
+	\post You must call updateBound() for update the box set.
+	*/
+	virtual void setChildTransform(int index, const btTransform & transform) = 0;
+
+	//!@}
+
+
+	//! virtual method for ray collision
+	virtual void rayTest(const btVector3& , const btVector3& , btCollisionWorld::RayResultCallback& )  const
+	{
+	}
+
+	//! Function for retrieve triangles.
+	/*!
+	It gives the triangles in local space
+	*/
+	virtual void	processAllTriangles(btTriangleCallback* ,const btVector3& ,const btVector3& ) const
+	{
+	}
+
+	//!@}
+
+};
+
+
+//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
+/*!
+This class only can manage Convex subshapes
+*/
+class btGImpactCompoundShape	: public btGImpactShapeInterface
+{
+public:
+	//! compound primitive manager
+	class CompoundPrimitiveManager:public btPrimitiveManagerBase
+	{
+	public:
+		virtual ~CompoundPrimitiveManager() {}
+		btGImpactCompoundShape * m_compoundShape;
+
+
+		CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
+		{
+			m_compoundShape = compound.m_compoundShape;
+		}
+
+		CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)
+		{
+			m_compoundShape = compoundShape;
+		}
+
+		CompoundPrimitiveManager()
+		{
+			m_compoundShape = NULL;
+		}
+
+		virtual bool is_trimesh() const
+		{
+			return false;
+		}
+
+		virtual int get_primitive_count() const
+		{
+			return (int )m_compoundShape->getNumChildShapes();
+		}
+
+		virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
+		{
+			btTransform prim_trans;
+			if(m_compoundShape->childrenHasTransform())
+			{
+				prim_trans = m_compoundShape->getChildTransform(prim_index);
+			}
+			else
+			{
+				prim_trans.setIdentity();
+			}
+			const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
+			shape->getAabb(prim_trans,primbox.m_min,primbox.m_max);
+		}
+
+		virtual void get_primitive_triangle(int, btPrimitiveTriangle & ) const
+		{
+			btAssert(0);
+		}
+
+	};
+
+
+
+protected:
+	CompoundPrimitiveManager m_primitive_manager;
+	btAlignedObjectArray<btTransform>		m_childTransforms;
+	btAlignedObjectArray<btCollisionShape*>	m_childShapes;
+
+
+public:
+
+	btGImpactCompoundShape(bool  = true)
+	{
+		m_primitive_manager.m_compoundShape = this;
+		m_box_set.setPrimitiveManager(&m_primitive_manager);
+	}
+
+	virtual ~btGImpactCompoundShape()
+	{
+	}
+
+
+	//! if true, then its children must get transforms.
+	virtual bool childrenHasTransform() const
+	{
+		if(m_childTransforms.size()==0) return false;
+		return true;
+	}
+
+
+	//! Obtains the primitive manager
+	virtual const btPrimitiveManagerBase * getPrimitiveManager()  const
+	{
+		return &m_primitive_manager;
+	}
+
+	//! Obtains the compopund primitive manager
+	SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager()
+	{
+		return &m_primitive_manager;
+	}
+
+	//! Gets the number of children
+	virtual int	getNumChildShapes() const
+	{
+		return m_childShapes.size();
+	}
+
+
+	//! Use this method for adding children. Only Convex shapes are allowed.
+	void addChildShape(const btTransform& localTransform,btCollisionShape* shape)
+	{
+		btAssert(shape->isConvex());
+		m_childTransforms.push_back(localTransform);
+		m_childShapes.push_back(shape);
+	}
+
+	//! Use this method for adding children. Only Convex shapes are allowed.
+	void addChildShape(btCollisionShape* shape)
+	{
+		btAssert(shape->isConvex());
+		m_childShapes.push_back(shape);
+	}
+
+	//! Gets the children
+	virtual btCollisionShape* getChildShape(int index)
+	{
+		return m_childShapes[index];
+	}
+
+	//! Gets the children
+	virtual const btCollisionShape* getChildShape(int index) const
+	{
+		return m_childShapes[index];
+	}
+
+	//! Retrieves the bound from a child
+    /*!
+    */
+    virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const
+    {
+
+    	if(childrenHasTransform())
+    	{
+    		m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax);
+    	}
+    	else
+    	{
+    		m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax);
+    	}
+    }
+
+
+	//! Gets the children transform
+	virtual btTransform	getChildTransform(int index) const
+	{
+		btAssert(m_childTransforms.size() == m_childShapes.size());
+		return m_childTransforms[index];
+	}
+
+	//! Sets the children transform
+	/*!
+	\post You must call updateBound() for update the box set.
+	*/
+	virtual void setChildTransform(int index, const btTransform & transform)
+	{
+		btAssert(m_childTransforms.size() == m_childShapes.size());
+		m_childTransforms[index] = transform;
+		postUpdate();
+	}
+
+	//! Determines if this shape has triangles
+	virtual bool needsRetrieveTriangles() const
+	{
+		return false;
+	}
+
+	//! Determines if this shape has tetrahedrons
+	virtual bool needsRetrieveTetrahedrons() const
+	{
+		return false;
+	}
+
+
+	virtual void getBulletTriangle(int ,btTriangleShapeEx & ) const
+	{
+		btAssert(0);
+	}
+
+	virtual void getBulletTetrahedron(int, btTetrahedronShapeEx & ) const
+	{
+		btAssert(0);
+	}
+
+
+	//! Calculates the exact inertia tensor for this shape
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+	virtual const char*	getName()const
+	{
+		return "GImpactCompound";
+	}
+
+	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
+	{
+		return CONST_GIMPACT_COMPOUND_SHAPE;
+	}
+
+};
+
+
+
+//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
+/*!
+- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
+- When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
+- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
+
+*/
+class btGImpactMeshShapePart : public btGImpactShapeInterface
+{
+public:
+	//! Trimesh primitive manager
+	/*!
+	Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
+	*/
+	class TrimeshPrimitiveManager:public btPrimitiveManagerBase
+	{
+	public:
+		btScalar m_margin;
+		btStridingMeshInterface * m_meshInterface;
+		btVector3 m_scale;
+		int m_part;
+		int m_lock_count;
+		const unsigned char *vertexbase;
+		int numverts;
+		PHY_ScalarType type;
+		int stride;
+		const unsigned char *indexbase;
+		int indexstride;
+		int  numfaces;
+		PHY_ScalarType indicestype;
+
+		TrimeshPrimitiveManager()
+		{
+			m_meshInterface = NULL;
+			m_part = 0;
+			m_margin = 0.01f;
+			m_scale = btVector3(1.f,1.f,1.f);
+			m_lock_count = 0;
+			vertexbase = 0;
+			numverts = 0;
+			stride = 0;
+			indexbase = 0;
+			indexstride = 0;
+			numfaces = 0;
+		}
+
+ 		TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)
+		{
+			m_meshInterface = manager.m_meshInterface;
+			m_part = manager.m_part;
+			m_margin = manager.m_margin;
+			m_scale = manager.m_scale;
+			m_lock_count = 0;
+			vertexbase = 0;
+			numverts = 0;
+			stride = 0;
+			indexbase = 0;
+			indexstride = 0;
+			numfaces = 0;
+
+		}
+
+		TrimeshPrimitiveManager(
+			btStridingMeshInterface * meshInterface,	int part)
+		{
+			m_meshInterface = meshInterface;
+			m_part = part;
+			m_scale = m_meshInterface->getScaling();
+			m_margin = 0.1f;
+			m_lock_count = 0;
+			vertexbase = 0;
+			numverts = 0;
+			stride = 0;
+			indexbase = 0;
+			indexstride = 0;
+			numfaces = 0;
+
+		}
+
+		virtual ~TrimeshPrimitiveManager() {}
+
+		void lock()
+		{
+			if(m_lock_count>0)
+			{
+				m_lock_count++;
+				return;
+			}
+			m_meshInterface->getLockedReadOnlyVertexIndexBase(
+				&vertexbase,numverts,
+				type, stride,&indexbase, indexstride, numfaces,indicestype,m_part);
+
+			m_lock_count = 1;
+		}
+
+		void unlock()
+		{
+			if(m_lock_count == 0) return;
+			if(m_lock_count>1)
+			{
+				--m_lock_count;
+				return;
+			}
+			m_meshInterface->unLockReadOnlyVertexBase(m_part);
+			vertexbase = NULL;
+			m_lock_count = 0;
+		}
+
+		virtual bool is_trimesh() const
+		{
+			return true;
+		}
+
+		virtual int get_primitive_count() const
+		{
+			return (int )numfaces;
+		}
+
+		SIMD_FORCE_INLINE int get_vertex_count() const
+		{
+			return (int )numverts;
+		}
+
+		SIMD_FORCE_INLINE void get_indices(int face_index,int &i0,int &i1,int &i2) const
+		{
+			if(indicestype == PHY_SHORT)
+			{
+				short * s_indices = (short *)(indexbase + face_index*indexstride);
+				i0 = s_indices[0];
+				i1 = s_indices[1];
+				i2 = s_indices[2];
+			}
+			else
+			{
+				int * i_indices = (int *)(indexbase + face_index*indexstride);
+				i0 = i_indices[0];
+				i1 = i_indices[1];
+				i2 = i_indices[2];
+			}
+		}
+
+		SIMD_FORCE_INLINE void get_vertex(int vertex_index, btVector3 & vertex) const
+		{
+			if(type == PHY_DOUBLE)
+			{
+				double * dvertices = (double *)(vertexbase + vertex_index*stride);
+				vertex[0] = btScalar(dvertices[0]*m_scale[0]);
+				vertex[1] = btScalar(dvertices[1]*m_scale[1]);
+				vertex[2] = btScalar(dvertices[2]*m_scale[2]);
+			}
+			else
+			{
+				float * svertices = (float *)(vertexbase + vertex_index*stride);
+				vertex[0] = svertices[0]*m_scale[0];
+				vertex[1] = svertices[1]*m_scale[1];
+				vertex[2] = svertices[2]*m_scale[2];
+			}
+		}
+
+		virtual void get_primitive_box(int prim_index ,btAABB & primbox) const
+		{
+			btPrimitiveTriangle  triangle;
+			get_primitive_triangle(prim_index,triangle);
+			primbox.calc_from_triangle_margin(
+				triangle.m_vertices[0],
+				triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin);
+		}
+
+		virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const
+		{
+			int indices[3];
+			get_indices(prim_index,indices[0],indices[1],indices[2]);
+			get_vertex(indices[0],triangle.m_vertices[0]);
+			get_vertex(indices[1],triangle.m_vertices[1]);
+			get_vertex(indices[2],triangle.m_vertices[2]);
+			triangle.m_margin = m_margin;
+		}
+
+		SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const
+		{
+			int indices[3];
+			get_indices(prim_index,indices[0],indices[1],indices[2]);
+			get_vertex(indices[0],triangle.m_vertices1[0]);
+			get_vertex(indices[1],triangle.m_vertices1[1]);
+			get_vertex(indices[2],triangle.m_vertices1[2]);
+			triangle.setMargin(m_margin);
+		}
+
+	};
+
+
+protected:
+	TrimeshPrimitiveManager m_primitive_manager;
+public:
+
+	btGImpactMeshShapePart()
+	{
+		m_box_set.setPrimitiveManager(&m_primitive_manager);
+	}
+
+
+	btGImpactMeshShapePart(btStridingMeshInterface * meshInterface,	int part)
+	{
+		m_primitive_manager.m_meshInterface = meshInterface;
+		m_primitive_manager.m_part = part;
+		m_box_set.setPrimitiveManager(&m_primitive_manager);
+	}
+
+	virtual ~btGImpactMeshShapePart()
+	{
+	}
+
+	//! if true, then its children must get transforms.
+	virtual bool childrenHasTransform() const
+	{
+		return false;
+	}
+
+
+	//! call when reading child shapes
+	virtual void lockChildShapes() const
+	{
+		void * dummy = (void*)(m_box_set.getPrimitiveManager());
+		TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
+		dummymanager->lock();
+	}
+
+	virtual void unlockChildShapes()  const
+	{
+		void * dummy = (void*)(m_box_set.getPrimitiveManager());
+		TrimeshPrimitiveManager * dummymanager = static_cast<TrimeshPrimitiveManager *>(dummy);
+		dummymanager->unlock();
+	}
+
+	//! Gets the number of children
+	virtual int	getNumChildShapes() const
+	{
+		return m_primitive_manager.get_primitive_count();
+	}
+
+
+	//! Gets the children
+	virtual btCollisionShape* getChildShape(int)
+	{
+		btAssert(0);
+		return NULL;
+	}
+
+
+
+	//! Gets the child
+	virtual const btCollisionShape* getChildShape(int) const
+	{
+		btAssert(0);
+		return NULL;
+	}
+
+	//! Gets the children transform
+	virtual btTransform	getChildTransform(int ) const
+	{
+		btAssert(0);
+		return btTransform();
+	}
+
+	//! Sets the children transform
+	/*!
+	\post You must call updateBound() for update the box set.
+	*/
+	virtual void setChildTransform(int , const btTransform &)
+	{
+		btAssert(0);
+	}
+
+
+	//! Obtains the primitive manager
+	virtual const btPrimitiveManagerBase * getPrimitiveManager()  const
+	{
+		return &m_primitive_manager;
+	}
+
+	SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager()
+	{
+		return &m_primitive_manager;
+	}
+
+
+
+
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+
+
+	virtual const char*	getName()const
+	{
+		return "GImpactMeshShapePart";
+	}
+
+	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
+	{
+		return CONST_GIMPACT_TRIMESH_SHAPE_PART;
+	}
+
+	//! Determines if this shape has triangles
+	virtual bool needsRetrieveTriangles() const
+	{
+		return true;
+	}
+
+	//! Determines if this shape has tetrahedrons
+	virtual bool needsRetrieveTetrahedrons() const
+	{
+		return false;
+	}
+
+	virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const
+	{
+		m_primitive_manager.get_bullet_triangle(prim_index,triangle);
+	}
+
+	virtual void getBulletTetrahedron(int, btTetrahedronShapeEx &) const
+	{
+		btAssert(0);
+	}
+
+
+
+	SIMD_FORCE_INLINE int getVertexCount() const
+	{
+		return m_primitive_manager.get_vertex_count();
+	}
+
+	SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const
+	{
+		m_primitive_manager.get_vertex(vertex_index,vertex);
+	}
+
+	SIMD_FORCE_INLINE void setMargin(btScalar margin)
+    {
+    	m_primitive_manager.m_margin = margin;
+    	postUpdate();
+    }
+
+    SIMD_FORCE_INLINE btScalar getMargin() const
+    {
+    	return m_primitive_manager.m_margin;
+    }
+
+    virtual void	setLocalScaling(const btVector3& scaling)
+    {
+    	m_primitive_manager.m_scale = scaling;
+    	postUpdate();
+    }
+
+    virtual const btVector3& getLocalScaling() const
+    {
+    	return m_primitive_manager.m_scale;
+    }
+
+    SIMD_FORCE_INLINE int getPart() const
+    {
+    	return (int)m_primitive_manager.m_part;
+    }
+
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+};
+
+
+//! This class manages a mesh supplied by the btStridingMeshInterface interface.
+/*!
+Set of btGImpactMeshShapePart parts
+- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
+
+- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
+
+*/
+class btGImpactMeshShape : public btGImpactShapeInterface
+{
+	btStridingMeshInterface* m_meshInterface;
+
+protected:
+	btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
+	void buildMeshParts(btStridingMeshInterface * meshInterface)
+	{
+		for (int i=0;i<meshInterface->getNumSubParts() ;++i )
+		{
+			btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i);
+			m_mesh_parts.push_back(newpart);
+		}
+	}
+
+	//! use this function for perfofm refit in bounding boxes
+    virtual void calcLocalAABB()
+    {
+    	m_localAABB.invalidate();
+    	int i = m_mesh_parts.size();
+    	while(i--)
+    	{
+    		m_mesh_parts[i]->updateBound();
+    		m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
+    	}
+    }
+
+public:
+	btGImpactMeshShape(btStridingMeshInterface * meshInterface)
+	{
+		m_meshInterface = meshInterface;
+		buildMeshParts(meshInterface);
+	}
+
+	virtual ~btGImpactMeshShape()
+	{
+		int i = m_mesh_parts.size();
+    	while(i--)
+    	{
+			btGImpactMeshShapePart * part = m_mesh_parts[i];
+			delete part;
+    	}
+		m_mesh_parts.clear();
+	}
+
+
+	btStridingMeshInterface* getMeshInterface()
+	{
+		return m_meshInterface;
+	}
+
+	const btStridingMeshInterface* getMeshInterface() const
+	{
+		return m_meshInterface;
+	}
+
+	int getMeshPartCount() const
+	{
+		return m_mesh_parts.size();
+	}
+
+	btGImpactMeshShapePart * getMeshPart(int index)
+	{
+		return m_mesh_parts[index];
+	}
+
+
+
+	const btGImpactMeshShapePart * getMeshPart(int index) const
+	{
+		return m_mesh_parts[index];
+	}
+
+
+	virtual void	setLocalScaling(const btVector3& scaling)
+	{
+		localScaling = scaling;
+
+		int i = m_mesh_parts.size();
+    	while(i--)
+    	{
+			btGImpactMeshShapePart * part = m_mesh_parts[i];
+			part->setLocalScaling(scaling);
+    	}
+
+		m_needs_update = true;
+	}
+
+	virtual void setMargin(btScalar margin)
+    {
+    	m_collisionMargin = margin;
+
+		int i = m_mesh_parts.size();
+    	while(i--)
+    	{
+			btGImpactMeshShapePart * part = m_mesh_parts[i];
+			part->setMargin(margin);
+    	}
+
+		m_needs_update = true;
+    }
+
+	//! Tells to this object that is needed to refit all the meshes
+    virtual void postUpdate()
+    {
+		int i = m_mesh_parts.size();
+    	while(i--)
+    	{
+			btGImpactMeshShapePart * part = m_mesh_parts[i];
+			part->postUpdate();
+    	}
+
+    	m_needs_update = true;
+    }
+
+	virtual void	calculateLocalInertia(btScalar mass,btVector3& inertia) const;
+
+
+	//! Obtains the primitive manager
+	virtual const btPrimitiveManagerBase * getPrimitiveManager()  const
+	{
+		btAssert(0);
+		return NULL;
+	}
+
+
+	//! Gets the number of children
+	virtual int	getNumChildShapes() const
+	{
+		btAssert(0);
+		return 0;
+	}
+
+
+	//! if true, then its children must get transforms.
+	virtual bool childrenHasTransform() const
+	{
+		btAssert(0);
+		return false;
+	}
+
+	//! Determines if this shape has triangles
+	virtual bool needsRetrieveTriangles() const
+	{
+		btAssert(0);
+		return false;
+	}
+
+	//! Determines if this shape has tetrahedrons
+	virtual bool needsRetrieveTetrahedrons() const
+	{
+		btAssert(0);
+		return false;
+	}
+
+	virtual void getBulletTriangle(int, btTriangleShapeEx &) const
+	{
+		btAssert(0);
+	}
+
+	virtual void getBulletTetrahedron(int, btTetrahedronShapeEx &) const
+	{
+		btAssert(0);
+	}
+
+	//! call when reading child shapes
+	virtual void lockChildShapes() const
+	{
+		btAssert(0);
+	}
+
+	virtual void unlockChildShapes() const
+	{
+		btAssert(0);
+	}
+
+
+
+
+	//! Retrieves the bound from a child
+    /*!
+    */
+    virtual void getChildAabb(int, const btTransform&, btVector3&, btVector3&) const
+    {
+        btAssert(0);
+    }
+
+	//! Gets the children
+	virtual btCollisionShape* getChildShape(int index)
+	{
+		btAssert(0);
+		return NULL;
+	}
+
+
+	//! Gets the child
+	virtual const btCollisionShape* getChildShape(int index) const
+	{
+		btAssert(0);
+		return NULL;
+	}
+
+	//! Gets the children transform
+	virtual btTransform	getChildTransform(int index) const
+	{
+		btAssert(0);
+		return btTransform();
+	}
+
+	//! Sets the children transform
+	/*!
+	\post You must call updateBound() for update the box set.
+	*/
+	virtual void setChildTransform(int index, const btTransform & transform)
+	{
+		btAssert(0);
+	}
+
+
+	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType()
+	{
+		return CONST_GIMPACT_TRIMESH_SHAPE;
+	}
+
+
+	virtual const char*	getName()const
+	{
+		return "GImpactMesh";
+	}
+
+	virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback)  const;
+
+	//! Function for retrieve triangles.
+	/*!
+	It gives the triangles in local space
+	*/
+	virtual void	processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+};
+
+
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.cpp
new file mode 100644
index 0000000..956fa04
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.cpp
@@ -0,0 +1,283 @@
+/*! \file btGenericPoolAllocator.cpp
+\author Francisco Len N�jera. email projectileman at yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGenericPoolAllocator.h"
+
+
+
+/// *************** btGenericMemoryPool ******************///////////
+
+size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements)
+{
+	size_t ptr = BT_UINT_MAX;
+
+	if(m_free_nodes_count == 0) return BT_UINT_MAX;
+	// find an avaliable free node with the correct size
+	size_t revindex = m_free_nodes_count;
+
+	while(revindex-- && ptr == BT_UINT_MAX)
+	{
+		if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements)
+		{
+			ptr = revindex;
+		}
+	}
+	if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found
+
+
+	revindex = ptr;
+	ptr = m_free_nodes[revindex];
+	// post: ptr contains the node index, and revindex the index in m_free_nodes
+
+	size_t  finalsize = m_allocated_sizes[ptr];
+	finalsize -= num_elements;
+
+	m_allocated_sizes[ptr] = num_elements;
+
+	// post: finalsize>=0, m_allocated_sizes[ptr] has the requested size
+
+	if(finalsize>0) // preserve free node, there are some free memory
+	{
+		m_free_nodes[revindex] = ptr + num_elements;
+		m_allocated_sizes[ptr + num_elements] = finalsize;
+	}
+	else // delete free node
+	{
+		// swap with end
+		m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1];
+		m_free_nodes_count--;
+	}
+
+	return ptr;
+}
+
+size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements)
+{
+	if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX;
+
+	size_t ptr = m_allocated_count;
+
+	m_allocated_sizes[m_allocated_count] = num_elements;
+	m_allocated_count+=num_elements;
+
+	return ptr;
+}
+
+
+void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count)
+{
+	m_allocated_count = 0;
+	m_free_nodes_count = 0;
+
+	m_element_size = element_size;
+	m_max_element_count = element_count;
+
+
+
+
+	m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16);
+	m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
+	m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16);
+
+	for (size_t i = 0;i< m_max_element_count;i++ )
+	{
+		m_allocated_sizes[i] = 0;
+	}
+}
+
+void btGenericMemoryPool::end_pool()
+{
+	btAlignedFree(m_pool);
+	btAlignedFree(m_free_nodes);
+	btAlignedFree(m_allocated_sizes);
+	m_allocated_count = 0;
+	m_free_nodes_count = 0;
+}
+
+
+//! Allocates memory in pool
+/*!
+\param size_bytes size in bytes of the buffer
+*/
+void * btGenericMemoryPool::allocate(size_t size_bytes)
+{
+
+	size_t module = size_bytes%m_element_size;
+	size_t element_count = size_bytes/m_element_size;
+	if(module>0) element_count++;
+
+	size_t alloc_pos = allocate_from_free_nodes(element_count);
+	// a free node is found
+	if(alloc_pos != BT_UINT_MAX)
+	{
+		return get_element_data(alloc_pos);
+	}
+	// allocate directly on pool
+	alloc_pos = allocate_from_pool(element_count);
+
+	if(alloc_pos == BT_UINT_MAX) return NULL; // not space
+	return get_element_data(alloc_pos);
+}
+
+bool btGenericMemoryPool::freeMemory(void * pointer)
+{
+	unsigned char * pointer_pos = (unsigned char *)pointer;
+	unsigned char * pool_pos = (unsigned char *)m_pool;
+	// calc offset
+	if(pointer_pos<pool_pos) return false;//other pool
+	size_t offset = size_t(pointer_pos - pool_pos);
+	if(offset>=get_pool_capacity()) return false;// far away
+
+	// find free position
+	m_free_nodes[m_free_nodes_count] = offset/m_element_size;
+	m_free_nodes_count++;
+	return true;
+}
+
+
+/// *******************! btGenericPoolAllocator *******************!///
+
+
+btGenericPoolAllocator::~btGenericPoolAllocator()
+{
+	// destroy pools
+	size_t i;
+	for (i=0;i<m_pool_count;i++)
+	{
+		m_pools[i]->end_pool();
+		btAlignedFree(m_pools[i]);
+	}
+}
+
+
+// creates a pool
+btGenericMemoryPool * btGenericPoolAllocator::push_new_pool()
+{
+	if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL;
+
+	btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16);
+
+	m_pools[m_pool_count] = newptr;
+
+	m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count);
+
+	m_pool_count++;
+	return newptr;
+}
+
+void * btGenericPoolAllocator::failback_alloc(size_t size_bytes)
+{
+
+	btGenericMemoryPool * pool = NULL;
+
+
+	if(size_bytes<=get_pool_capacity())
+	{
+		pool = 	push_new_pool();
+	}
+
+	if(pool==NULL) // failback
+	{
+		return btAlignedAlloc(size_bytes,16);
+	}
+
+	return pool->allocate(size_bytes);
+}
+
+bool btGenericPoolAllocator::failback_free(void * pointer)
+{
+	btAlignedFree(pointer);
+	return true;
+}
+
+
+//! Allocates memory in pool
+/*!
+\param size_bytes size in bytes of the buffer
+*/
+void * btGenericPoolAllocator::allocate(size_t size_bytes)
+{
+	void * ptr = NULL;
+
+	size_t i = 0;
+	while(i<m_pool_count && ptr == NULL)
+	{
+		ptr = m_pools[i]->allocate(size_bytes);
+		++i;
+	}
+
+	if(ptr) return ptr;
+
+	return failback_alloc(size_bytes);
+}
+
+bool btGenericPoolAllocator::freeMemory(void * pointer)
+{
+	bool result = false;
+
+	size_t i = 0;
+	while(i<m_pool_count && result == false)
+	{
+		result = m_pools[i]->freeMemory(pointer);
+		++i;
+	}
+
+	if(result) return true;
+
+	return failback_free(pointer);
+}
+
+/// ************** STANDARD ALLOCATOR ***************************///
+
+
+#define BT_DEFAULT_POOL_SIZE 32768
+#define BT_DEFAULT_POOL_ELEMENT_SIZE 8
+
+// main allocator
+class GIM_STANDARD_ALLOCATOR: public btGenericPoolAllocator
+{
+public:
+	GIM_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE)
+	{
+	}
+};
+
+// global allocator
+GIM_STANDARD_ALLOCATOR g_main_allocator;
+
+
+void * btPoolAlloc(size_t size)
+{
+	return g_main_allocator.allocate(size);
+}
+
+void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize)
+{
+	void * newptr = btPoolAlloc(newsize);
+    size_t copysize = oldsize<newsize?oldsize:newsize;
+    memcpy(newptr,ptr,copysize);
+    btPoolFree(ptr);
+    return newptr;
+}
+
+void btPoolFree(void *ptr)
+{
+	g_main_allocator.freeMemory(ptr);
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.h
new file mode 100644
index 0000000..dc81431
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGenericPoolAllocator.h
@@ -0,0 +1,163 @@
+/*! \file btGenericPoolAllocator.h
+\author Francisco Len N�jera. email projectileman at yahoo.com
+
+General purpose allocator class
+*/
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef BT_GENERIC_POOL_ALLOCATOR_H
+#define BT_GENERIC_POOL_ALLOCATOR_H
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include "LinearMath/btAlignedAllocator.h"
+
+#define BT_UINT_MAX UINT_MAX
+#define BT_DEFAULT_MAX_POOLS 16
+
+
+//! Generic Pool class
+class btGenericMemoryPool
+{
+public:
+	unsigned char * m_pool; //[m_element_size*m_max_element_count];
+	size_t * m_free_nodes; //[m_max_element_count];//! free nodes
+	size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node
+	size_t m_allocated_count;
+	size_t m_free_nodes_count;
+protected:
+	size_t m_element_size;
+	size_t m_max_element_count;
+
+	size_t allocate_from_free_nodes(size_t num_elements);
+	size_t allocate_from_pool(size_t num_elements);
+
+public:
+
+	void init_pool(size_t element_size, size_t element_count);
+
+	void end_pool();
+
+
+	btGenericMemoryPool(size_t element_size, size_t element_count)
+	{
+		init_pool(element_size, element_count);
+	}
+
+	~btGenericMemoryPool()
+	{
+		end_pool();
+	}
+
+
+	inline size_t get_pool_capacity()
+	{
+		return m_element_size*m_max_element_count;
+	}
+
+	inline size_t gem_element_size()
+	{
+		return m_element_size;
+	}
+
+	inline size_t get_max_element_count()
+	{
+		return m_max_element_count;
+	}
+
+	inline size_t get_allocated_count()
+	{
+		return m_allocated_count;
+	}
+
+	inline size_t get_free_positions_count()
+	{
+		return m_free_nodes_count;
+	}
+
+	inline void * get_element_data(size_t element_index)
+	{
+		return &m_pool[element_index*m_element_size];
+	}
+
+	//! Allocates memory in pool
+	/*!
+	\param size_bytes size in bytes of the buffer
+	*/
+	void * allocate(size_t size_bytes);
+
+	bool freeMemory(void * pointer);
+};
+
+
+
+
+//! Generic Allocator with pools
+/*!
+General purpose Allocator which can create Memory Pools dynamiacally as needed.
+*/
+class btGenericPoolAllocator
+{
+protected:
+	size_t m_pool_element_size;
+	size_t m_pool_element_count;
+public:
+	btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS];
+	size_t m_pool_count;
+
+
+	inline size_t get_pool_capacity()
+	{
+		return m_pool_element_size*m_pool_element_count;
+	}
+
+
+protected:
+	// creates a pool
+	btGenericMemoryPool * push_new_pool();
+
+	void * failback_alloc(size_t size_bytes);
+
+	bool failback_free(void * pointer);
+public:
+
+	btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count)
+	{
+		m_pool_count = 0;
+		m_pool_element_size = pool_element_size;
+		m_pool_element_count = pool_element_count;
+	}
+
+	virtual ~btGenericPoolAllocator();
+
+	//! Allocates memory in pool
+	/*!
+	\param size_bytes size in bytes of the buffer
+	*/
+	void * allocate(size_t size_bytes);
+
+	bool freeMemory(void * pointer);
+};
+
+
+
+void * btPoolAlloc(size_t size);
+void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize);
+void btPoolFree(void *ptr);
+
+
+#endif
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGeometryOperations.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGeometryOperations.h
new file mode 100644
index 0000000..bc5a416
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btGeometryOperations.h
@@ -0,0 +1,212 @@
+#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file btGeometryOperations.h
+*\author Francisco Len N�jera
+
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btBoxCollision.h"
+
+
+
+
+
+#define PLANEDIREPSILON 0.0000001f
+#define PARALELENORMALS 0.000001f
+
+
+#define BT_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
+
+/// Calc a plane from a triangle edge an a normal. plane is a vec4f
+SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 &  e2, const btVector3 & normal,btVector4 & plane)
+{
+	btVector3 planenormal = (e2-e1).cross(normal);
+	planenormal.normalize();
+	plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal));
+}
+
+
+
+//***************** SEGMENT and LINE FUNCTIONS **********************************///
+
+/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
+ */
+SIMD_FORCE_INLINE void bt_closest_point_on_segment(
+	btVector3 & cp, const btVector3 & v,
+	const btVector3  &e1,const btVector3 &e2)
+{
+    btVector3 n = e2-e1;
+    cp = v - e1;
+	btScalar _scalar = cp.dot(n)/n.dot(n);
+	if(_scalar <0.0f)
+	{
+	    cp = e1;
+	}
+	else if(_scalar >1.0f)
+	{
+	    cp = e2;
+	}
+	else
+	{
+		cp = _scalar*n + e1;
+	}
+}
+
+
+//! line plane collision
+/*!
+*\return
+	-0  if the ray never intersects
+	-1 if the ray collides in front
+	-2 if the ray collides in back
+*/
+
+SIMD_FORCE_INLINE int bt_line_plane_collision(
+	const btVector4 & plane,
+	const btVector3 & vDir,
+	const btVector3 & vPoint,
+	btVector3 & pout,
+	btScalar &tparam,
+	btScalar tmin, btScalar tmax)
+{
+
+	btScalar _dotdir = vDir.dot(plane);
+
+	if(btFabs(_dotdir)<PLANEDIREPSILON)
+	{
+		tparam = tmax;
+	    return 0;
+	}
+
+	btScalar _dis = bt_distance_point_plane(plane,vPoint);
+	char returnvalue = _dis<0.0f? 2:1;
+	tparam = -_dis/_dotdir;
+
+	if(tparam<tmin)
+	{
+		returnvalue = 0;
+		tparam = tmin;
+	}
+	else if(tparam>tmax)
+	{
+		returnvalue = 0;
+		tparam = tmax;
+	}
+	pout = tparam*vDir + vPoint;
+	return returnvalue;
+}
+
+
+//! Find closest points on segments
+SIMD_FORCE_INLINE void bt_segment_collision(
+	const btVector3 & vA1,
+	const btVector3 & vA2,
+	const btVector3 & vB1,
+	const btVector3 & vB2,
+	btVector3 & vPointA,
+	btVector3 & vPointB)
+{
+    btVector3 AD = vA2 - vA1;
+    btVector3 BD = vB2 - vB1;
+    btVector3 N = AD.cross(BD);
+    btScalar tp = N.length2();
+
+    btVector4 _M;//plane
+
+    if(tp<SIMD_EPSILON)//ARE PARALELE
+    {
+    	//project B over A
+    	bool invert_b_order = false;
+    	_M[0] = vB1.dot(AD);
+    	_M[1] = vB2.dot(AD);
+
+    	if(_M[0]>_M[1])
+    	{
+    		invert_b_order  = true;
+    		BT_SWAP_NUMBERS(_M[0],_M[1]);
+    	}
+    	_M[2] = vA1.dot(AD);
+    	_M[3] = vA2.dot(AD);
+    	//mid points
+    	N[0] = (_M[0]+_M[1])*0.5f;
+    	N[1] = (_M[2]+_M[3])*0.5f;
+
+    	if(N[0]<N[1])
+    	{
+    		if(_M[1]<_M[2])
+    		{
+    			vPointB = invert_b_order?vB1:vB2;
+    			vPointA = vA1;
+    		}
+    		else if(_M[1]<_M[3])
+    		{
+    			vPointB = invert_b_order?vB1:vB2;
+    			bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
+    		}
+    		else
+    		{
+    			vPointA = vA2;
+    			bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
+    		}
+    	}
+    	else
+    	{
+    		if(_M[3]<_M[0])
+    		{
+    			vPointB = invert_b_order?vB2:vB1;
+    			vPointA = vA2;
+    		}
+    		else if(_M[3]<_M[1])
+    		{
+    			vPointA = vA2;
+    			bt_closest_point_on_segment(vPointB,vPointA,vB1,vB2);
+    		}
+    		else
+    		{
+    			vPointB = invert_b_order?vB1:vB2;
+    			bt_closest_point_on_segment(vPointA,vPointB,vA1,vA2);
+    		}
+    	}
+    	return;
+    }
+
+    N = N.cross(BD);
+    _M.setValue(N[0],N[1],N[2],vB1.dot(N));
+
+	// get point A as the plane collision point
+    bt_line_plane_collision(_M,AD,vA1,vPointA,tp,btScalar(0), btScalar(1));
+
+    /*Closest point on segment*/
+    vPointB = vPointA - vB1;
+	tp = vPointB.dot(BD);
+	tp/= BD.dot(BD);
+	tp = BT_CLAMP(tp,0.0f,1.0f);
+
+	vPointB = tp*BD + vB1;
+}
+
+
+
+
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btQuantization.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btQuantization.h
new file mode 100644
index 0000000..7faada6
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btQuantization.h
@@ -0,0 +1,88 @@
+#ifndef BT_QUANTIZATION_H_INCLUDED
+#define BT_QUANTIZATION_H_INCLUDED
+
+/*! \file btQuantization.h
+*\author Francisco Len N�jera
+
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "LinearMath/btTransform.h"
+
+
+
+
+
+
+SIMD_FORCE_INLINE void bt_calc_quantization_parameters(
+	btVector3 & outMinBound,
+	btVector3 & outMaxBound,
+	btVector3 & bvhQuantization,
+	const btVector3& srcMinBound,const btVector3& srcMaxBound,
+	btScalar quantizationMargin)
+{
+	//enlarge the AABB to avoid division by zero when initializing the quantization values
+	btVector3 clampValue(quantizationMargin,quantizationMargin,quantizationMargin);
+	outMinBound = srcMinBound - clampValue;
+	outMaxBound = srcMaxBound + clampValue;
+	btVector3 aabbSize = outMaxBound - outMinBound;
+	bvhQuantization = btVector3(btScalar(65535.0),
+								btScalar(65535.0),
+								btScalar(65535.0)) / aabbSize;
+}
+
+
+SIMD_FORCE_INLINE void bt_quantize_clamp(
+	unsigned short* out,
+	const btVector3& point,
+	const btVector3 & min_bound,
+	const btVector3 & max_bound,
+	const btVector3 & bvhQuantization)
+{
+
+	btVector3 clampedPoint(point);
+	clampedPoint.setMax(min_bound);
+	clampedPoint.setMin(max_bound);
+
+	btVector3 v = (clampedPoint - min_bound) * bvhQuantization;
+	out[0] = (unsigned short)(v.getX()+0.5f);
+	out[1] = (unsigned short)(v.getY()+0.5f);
+	out[2] = (unsigned short)(v.getZ()+0.5f);
+}
+
+
+SIMD_FORCE_INLINE btVector3 bt_unquantize(
+	const unsigned short* vecIn,
+	const btVector3 & offset,
+	const btVector3 & bvhQuantization)
+{
+	btVector3	vecOut;
+	vecOut.setValue(
+		(btScalar)(vecIn[0]) / (bvhQuantization.getX()),
+		(btScalar)(vecIn[1]) / (bvhQuantization.getY()),
+		(btScalar)(vecIn[2]) / (bvhQuantization.getZ()));
+	vecOut += offset;
+	return vecOut;
+}
+
+
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.cpp
new file mode 100644
index 0000000..7869627
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.cpp
@@ -0,0 +1,218 @@
+/*! \file btGImpactTriangleShape.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btTriangleShapeEx.h"
+
+
+
+void GIM_TRIANGLE_CONTACT::merge_points(const btVector4 & plane,
+                                       btScalar margin, const btVector3 * points, int point_count)
+{
+    m_point_count = 0;
+    m_penetration_depth= -1000.0f;
+
+    int point_indices[MAX_TRI_CLIPPING];
+
+	int _k;
+
+    for ( _k=0;_k<point_count;_k++)
+    {
+        btScalar _dist = - bt_distance_point_plane(plane,points[_k]) + margin;
+
+        if (_dist>=0.0f)
+        {
+            if (_dist>m_penetration_depth)
+            {
+                m_penetration_depth = _dist;
+                point_indices[0] = _k;
+                m_point_count=1;
+            }
+            else if ((_dist+SIMD_EPSILON)>=m_penetration_depth)
+            {
+                point_indices[m_point_count] = _k;
+                m_point_count++;
+            }
+        }
+    }
+
+    for ( _k=0;_k<m_point_count;_k++)
+    {
+        m_points[_k] = points[point_indices[_k]];
+    }
+}
+
+///class btPrimitiveTriangle
+bool btPrimitiveTriangle::overlap_test_conservative(const btPrimitiveTriangle& other)
+{
+    btScalar total_margin = m_margin + other.m_margin;
+    // classify points on other triangle
+    btScalar dis0 = bt_distance_point_plane(m_plane,other.m_vertices[0]) - total_margin;
+
+    btScalar dis1 = bt_distance_point_plane(m_plane,other.m_vertices[1]) - total_margin;
+
+    btScalar dis2 = bt_distance_point_plane(m_plane,other.m_vertices[2]) - total_margin;
+
+    if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+    // classify points on this triangle
+    dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin;
+
+    dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin;
+
+    dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin;
+
+    if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+    return true;
+}
+
+int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points )
+{
+    // edge 0
+
+    btVector3 temp_points[MAX_TRI_CLIPPING];
+
+
+    btVector4 edgeplane;
+
+    get_edge_plane(0,edgeplane);
+
+
+    int clipped_count = bt_plane_clip_triangle(
+                            edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points);
+
+    if (clipped_count == 0) return 0;
+
+    btVector3 temp_points1[MAX_TRI_CLIPPING];
+
+
+    // edge 1
+    get_edge_plane(1,edgeplane);
+
+
+    clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1);
+
+    if (clipped_count == 0) return 0;
+
+    // edge 2
+    get_edge_plane(2,edgeplane);
+
+    clipped_count = bt_plane_clip_polygon(
+                        edgeplane,temp_points1,clipped_count,clipped_points);
+
+    return clipped_count;
+}
+
+bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts)
+{
+    btScalar margin = m_margin + other.m_margin;
+
+    btVector3 clipped_points[MAX_TRI_CLIPPING];
+    int clipped_count;
+    //create planes
+    // plane v vs U points
+
+    GIM_TRIANGLE_CONTACT contacts1;
+
+    contacts1.m_separating_normal = m_plane;
+
+
+    clipped_count = clip_triangle(other,clipped_points);
+
+    if (clipped_count == 0 )
+    {
+        return false;//Reject
+    }
+
+    //find most deep interval face1
+    contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
+    if (contacts1.m_point_count == 0) return false; // too far
+    //Normal pointing to this triangle
+    contacts1.m_separating_normal *= -1.f;
+
+
+    //Clip tri1 by tri2 edges
+    GIM_TRIANGLE_CONTACT contacts2;
+    contacts2.m_separating_normal = other.m_plane;
+
+    clipped_count = other.clip_triangle(*this,clipped_points);
+
+    if (clipped_count == 0 )
+    {
+        return false;//Reject
+    }
+
+    //find most deep interval face1
+    contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
+    if (contacts2.m_point_count == 0) return false; // too far
+
+
+
+
+    ////check most dir for contacts
+    if (contacts2.m_penetration_depth<contacts1.m_penetration_depth)
+    {
+        contacts.copy_from(contacts2);
+    }
+    else
+    {
+        contacts.copy_from(contacts1);
+    }
+    return true;
+}
+
+
+
+///class btTriangleShapeEx: public btTriangleShape
+
+bool btTriangleShapeEx::overlap_test_conservative(const btTriangleShapeEx& other)
+{
+    btScalar total_margin = getMargin() + other.getMargin();
+
+    btVector4 plane0;
+    buildTriPlane(plane0);
+    btVector4 plane1;
+    other.buildTriPlane(plane1);
+
+    // classify points on other triangle
+    btScalar dis0 = bt_distance_point_plane(plane0,other.m_vertices1[0]) - total_margin;
+
+    btScalar dis1 = bt_distance_point_plane(plane0,other.m_vertices1[1]) - total_margin;
+
+    btScalar dis2 = bt_distance_point_plane(plane0,other.m_vertices1[2]) - total_margin;
+
+    if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+    // classify points on this triangle
+    dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin;
+
+    dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin;
+
+    dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin;
+
+    if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false;
+
+    return true;
+}
+
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.h
new file mode 100644
index 0000000..bbd6b63
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/Bullet/btTriangleShapeEx.h
@@ -0,0 +1,180 @@
+/*! \file btGImpactShape.h
+\author Francisco Len N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+#ifndef TRIANGLE_SHAPE_EX_H
+#define TRIANGLE_SHAPE_EX_H
+
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+#include "btBoxCollision.h"
+#include "btClipPolygon.h"
+#include "btGeometryOperations.h"
+
+
+#define MAX_TRI_CLIPPING 16
+
+//! Structure for collision
+struct GIM_TRIANGLE_CONTACT
+{
+    btScalar m_penetration_depth;
+    int m_point_count;
+    btVector4 m_separating_normal;
+    btVector3 m_points[MAX_TRI_CLIPPING];
+
+	SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT& other)
+	{
+		m_penetration_depth = other.m_penetration_depth;
+		m_separating_normal = other.m_separating_normal;
+		m_point_count = other.m_point_count;
+		int i = m_point_count;
+		while(i--)
+		{
+			m_points[i] = other.m_points[i];
+		}
+	}
+
+	GIM_TRIANGLE_CONTACT()
+	{
+	}
+
+	GIM_TRIANGLE_CONTACT(const GIM_TRIANGLE_CONTACT& other)
+	{
+		copy_from(other);
+	}
+
+    //! classify points that are closer
+    void merge_points(const btVector4 & plane,
+    				btScalar margin, const btVector3 * points, int point_count);
+
+};
+
+
+
+class btPrimitiveTriangle
+{
+public:
+	btVector3 m_vertices[3];
+	btVector4 m_plane;
+	btScalar m_margin;
+	btScalar m_dummy;
+	btPrimitiveTriangle():m_margin(0.01f)
+	{
+
+	}
+
+
+	SIMD_FORCE_INLINE void buildTriPlane()
+	{
+		btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]);
+		normal.normalize();
+		m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal));
+	}
+
+	//! Test if triangles could collide
+	bool overlap_test_conservative(const btPrimitiveTriangle& other);
+
+	//! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane
+	/*!
+	\pre this triangle must have its plane calculated.
+	*/
+	SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane)  const
+    {
+		const btVector3 & e0 = m_vertices[edge_index];
+		const btVector3 & e1 = m_vertices[(edge_index+1)%3];
+		bt_edge_plane(e0,e1,m_plane,plane);
+    }
+
+    void applyTransform(const btTransform& t)
+	{
+		m_vertices[0] = t(m_vertices[0]);
+		m_vertices[1] = t(m_vertices[1]);
+		m_vertices[2] = t(m_vertices[2]);
+	}
+
+	//! Clips the triangle against this
+	/*!
+	\pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated.
+	\return the number of clipped points
+	*/
+    int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points );
+
+	//! Find collision using the clipping method
+	/*!
+	\pre this triangle and other must have their triangles calculated
+	*/
+    bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, GIM_TRIANGLE_CONTACT & contacts);
+};
+
+
+
+//! Helper class for colliding Bullet Triangle Shapes
+/*!
+This class implements a better getAabb method than the previous btTriangleShape class
+*/
+class btTriangleShapeEx: public btTriangleShape
+{
+public:
+
+	btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0))
+	{
+	}
+
+	btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2):	btTriangleShape(p0,p1,p2)
+	{
+	}
+
+	btTriangleShapeEx(const btTriangleShapeEx & other):	btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2])
+	{
+	}
+
+	virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const
+	{
+		btVector3 tv0 = t(m_vertices1[0]);
+		btVector3 tv1 = t(m_vertices1[1]);
+		btVector3 tv2 = t(m_vertices1[2]);
+
+		btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin);
+		aabbMin = trianglebox.m_min;
+		aabbMax = trianglebox.m_max;
+	}
+
+	void applyTransform(const btTransform& t)
+	{
+		m_vertices1[0] = t(m_vertices1[0]);
+		m_vertices1[1] = t(m_vertices1[1]);
+		m_vertices1[2] = t(m_vertices1[2]);
+	}
+
+	SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const
+	{
+		btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]);
+		normal.normalize();
+		plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal));
+	}
+
+	bool overlap_test_conservative(const btTriangleShapeEx& other);
+};
+
+
+#endif //TRIANGLE_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_array.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_array.h
new file mode 100644
index 0000000..c8161d2
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_array.h
@@ -0,0 +1,326 @@
+#ifndef GIM_ARRAY_H_INCLUDED
+#define GIM_ARRAY_H_INCLUDED
+/*! \file gim_array.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_memory.h"
+
+
+#define GIM_ARRAY_GROW_INCREMENT 2
+#define GIM_ARRAY_GROW_FACTOR 2
+
+//!	Very simple array container with fast access and simd memory
+template<typename T>
+class gim_array
+{
+public:
+//! properties
+//!@{
+    T *m_data;
+    GUINT m_size;
+    GUINT m_allocated_size;
+//!@}
+//! protected operations
+//!@{
+
+    inline void destroyData()
+	{
+	    m_allocated_size = 0;
+		if(m_data==NULL) return;
+		gim_free(m_data);
+		m_data = NULL;
+	}
+
+	inline bool resizeData(GUINT newsize)
+	{
+		if(newsize==0)
+		{
+			destroyData();
+			return true;
+		}
+
+		if(m_size>0)
+		{
+            m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T));
+		}
+		else
+		{
+		    m_data = (T*)gim_alloc(newsize*sizeof(T));
+		}
+		m_allocated_size = newsize;
+		return true;
+	}
+
+	inline bool growingCheck()
+	{
+		if(m_allocated_size<=m_size)
+		{
+		    GUINT requestsize = m_size;
+		    m_size = m_allocated_size;
+			if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false;
+		}
+		return true;
+	}
+
+//!@}
+//! public operations
+//!@{
+    inline  bool reserve(GUINT size)
+    {
+        if(m_allocated_size>=size) return false;
+        return resizeData(size);
+    }
+
+    inline void clear_range(GUINT start_range)
+    {
+        while(m_size>start_range)
+        {
+            m_data[--m_size].~T();
+        }
+    }
+
+    inline void clear()
+    {
+        if(m_size==0)return;
+        clear_range(0);
+    }
+
+    inline void clear_memory()
+    {
+        clear();
+        destroyData();
+    }
+
+    gim_array()
+    {
+        m_data = 0;
+        m_size = 0;
+        m_allocated_size = 0;
+    }
+
+    gim_array(GUINT reservesize)
+    {
+        m_data = 0;
+        m_size = 0;
+
+        m_allocated_size = 0;
+        reserve(reservesize);
+    }
+
+    ~gim_array()
+    {
+        clear_memory();
+    }
+
+    inline GUINT size() const
+    {
+        return m_size;
+    }
+
+    inline GUINT max_size() const
+    {
+        return m_allocated_size;
+    }
+
+    inline T & operator[](size_t i)
+	{
+		return m_data[i];
+	}
+	inline  const T & operator[](size_t i) const
+	{
+		return m_data[i];
+	}
+
+    inline T * pointer(){ return m_data;}
+    inline const T * pointer() const
+    { return m_data;}
+
+
+    inline T * get_pointer_at(GUINT i)
+	{
+		return m_data + i;
+	}
+
+	inline const T * get_pointer_at(GUINT i) const
+	{
+		return m_data + i;
+	}
+
+	inline T & at(GUINT i)
+	{
+		return m_data[i];
+	}
+
+	inline const T & at(GUINT i) const
+	{
+		return m_data[i];
+	}
+
+	inline T & front()
+	{
+		return *m_data;
+	}
+
+	inline const T & front() const
+	{
+		return *m_data;
+	}
+
+	inline T & back()
+	{
+		return m_data[m_size-1];
+	}
+
+	inline const T & back() const
+	{
+		return m_data[m_size-1];
+	}
+
+
+	inline void swap(GUINT i, GUINT j)
+	{
+	    gim_swap_elements(m_data,i,j);
+	}
+
+	inline void push_back(const T & obj)
+	{
+	    this->growingCheck();
+	    m_data[m_size] = obj;
+	    m_size++;
+	}
+
+	//!Simply increase the m_size, doesn't call the new element constructor
+	inline void push_back_mem()
+	{
+	    this->growingCheck();
+	    m_size++;
+	}
+
+	inline void push_back_memcpy(const T & obj)
+	{
+	    this->growingCheck();
+	    irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T));
+	    m_size++;
+	}
+
+	inline void pop_back()
+	{
+	    m_size--;
+        m_data[m_size].~T();
+	}
+
+	//!Simply decrease the m_size, doesn't call the deleted element destructor
+	inline void pop_back_mem()
+	{
+	    m_size--;
+	}
+
+    //! fast erase
+	inline void erase(GUINT index)
+	{
+	    if(index<m_size-1)
+	    {
+	        swap(index,m_size-1);
+	    }
+	    pop_back();
+	}
+
+	inline void erase_sorted_mem(GUINT index)
+	{
+	    m_size--;
+	    for(GUINT i = index;i<m_size;i++)
+	    {
+	        gim_simd_memcpy(m_data+i,m_data+i+1,sizeof(T));
+	    }
+	}
+
+	inline void erase_sorted(GUINT index)
+	{
+	    m_data[index].~T();
+	    erase_sorted_mem(index);
+	}
+
+	inline void insert_mem(GUINT index)
+	{
+	    this->growingCheck();
+	    for(GUINT i = m_size;i>index;i--)
+	    {
+	        gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T));
+	    }
+	    m_size++;
+	}
+
+	inline void insert(const T & obj,GUINT index)
+	{
+	    insert_mem(index);
+	    m_data[index] = obj;
+	}
+
+	inline void resize(GUINT size, bool call_constructor = true)
+	{
+
+	    if(size>m_size)
+	    {
+            reserve(size);
+            if(call_constructor)
+            {
+            	T obj;
+                while(m_size<size)
+                {
+                    m_data[m_size] = obj;
+                    m_size++;
+                }
+            }
+            else
+            {
+            	m_size = size;
+            }
+	    }
+	    else if(size<m_size)
+	    {
+	        if(call_constructor) clear_range(size);
+	        m_size = size;
+	    }
+	}
+
+	inline void refit()
+	{
+	    resizeData(m_size);
+	}
+
+};
+
+
+
+
+
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_basic_geometry_operations.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_basic_geometry_operations.h
new file mode 100644
index 0000000..666abf7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_basic_geometry_operations.h
@@ -0,0 +1,543 @@
+#ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+#define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
+
+/*! \file gim_basic_geometry_operations.h
+*\author Francisco Len N�jera
+type independant geometry routines
+
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_linear_math.h"
+
+
+
+
+
+#define PLANEDIREPSILON 0.0000001f
+#define PARALELENORMALS 0.000001f
+
+
+#define TRIANGLE_NORMAL(v1,v2,v3,n)\
+{\
+	vec3f _dif1,_dif2;\
+    VEC_DIFF(_dif1,v2,v1);\
+    VEC_DIFF(_dif2,v3,v1);\
+    VEC_CROSS(n,_dif1,_dif2);\
+    VEC_NORMALIZE(n);\
+}\
+
+#define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
+    vec3f _dif1,_dif2; \
+    VEC_DIFF(_dif1,v2,v1); \
+    VEC_DIFF(_dif2,v3,v1); \
+    VEC_CROSS(n,_dif1,_dif2); \
+}\
+
+/// plane is a vec4f
+#define TRIANGLE_PLANE(v1,v2,v3,plane) {\
+    TRIANGLE_NORMAL(v1,v2,v3,plane);\
+    plane[3] = VEC_DOT(v1,plane);\
+}\
+
+/// plane is a vec4f
+#define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
+    TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
+    plane[3] = VEC_DOT(v1,plane);\
+}\
+
+/// Calc a plane from an edge an a normal. plane is a vec4f
+#define EDGE_PLANE(e1,e2,n,plane) {\
+    vec3f _dif; \
+    VEC_DIFF(_dif,e2,e1); \
+    VEC_CROSS(plane,_dif,n); \
+    VEC_NORMALIZE(plane); \
+    plane[3] = VEC_DOT(e1,plane);\
+}\
+
+#define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
+
+#define PROJECT_POINT_PLANE(point,plane,projected) {\
+	GREAL _dis;\
+	_dis = DISTANCE_PLANE_POINT(plane,point);\
+	VEC_SCALE(projected,-_dis,plane);\
+	VEC_SUM(projected,projected,point);	\
+}\
+
+//! Verifies if a point is in the plane hull
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool POINT_IN_HULL(
+	const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
+{
+	GREAL _dis;
+	for (GUINT _i = 0;_i< plane_count;++_i)
+	{
+		_dis = DISTANCE_PLANE_POINT(planes[_i],point);
+	    if(_dis>0.0f) return false;
+	}
+	return true;
+}
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
+	const CLASS_POINT& s1,
+	const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
+{
+	GREAL _dis1,_dis2;
+	_dis1 = DISTANCE_PLANE_POINT(plane,s1);
+	VEC_DIFF(clipped,s2,s1);
+	_dis2 = VEC_DOT(clipped,plane);
+	VEC_SCALE(clipped,-_dis1/_dis2,clipped);
+	VEC_SUM(clipped,clipped,s1);
+}
+
+enum ePLANE_INTERSECTION_TYPE
+{
+	G_BACK_PLANE = 0,
+	G_COLLIDE_PLANE,
+	G_FRONT_PLANE
+};
+
+enum eLINE_PLANE_INTERSECTION_TYPE
+{
+	G_FRONT_PLANE_S1 = 0,
+	G_FRONT_PLANE_S2,
+	G_BACK_PLANE_S1,
+	G_BACK_PLANE_S2,
+	G_COLLIDE_PLANE_S1,
+	G_COLLIDE_PLANE_S2
+};
+
+//! Confirms if the plane intersect the edge or nor
+/*!
+intersection type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
+	const CLASS_POINT& s1,
+	const CLASS_POINT &s2,
+	const CLASS_PLANE &plane,CLASS_POINT &clipped)
+{
+	GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
+	GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
+	if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
+	{
+	    if(_dis1<_dis2) return G_FRONT_PLANE_S1;
+	    return G_FRONT_PLANE_S2;
+	}
+	else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
+	{
+	    if(_dis1>_dis2) return G_BACK_PLANE_S1;
+	    return G_BACK_PLANE_S2;
+	}
+
+	VEC_DIFF(clipped,s2,s1);
+	_dis2 = VEC_DOT(clipped,plane);
+	VEC_SCALE(clipped,-_dis1/_dis2,clipped);
+	VEC_SUM(clipped,clipped,s1);
+	if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
+	return G_COLLIDE_PLANE_S2;
+}
+
+//! Confirms if the plane intersect the edge or not
+/*!
+clipped1 and clipped2 are the vertices behind the plane.
+clipped1 is the closest
+
+intersection_type must have the following values
+<ul>
+<li> 0 : Segment in front of plane, s1 closest
+<li> 1 : Segment in front of plane, s2 closest
+<li> 2 : Segment in back of plane, s1 closest
+<li> 3 : Segment in back of plane, s2 closest
+<li> 4 : Segment collides plane, s1 in back
+<li> 5 : Segment collides plane, s2 in back
+</ul>
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
+	const CLASS_POINT& s1,
+	const CLASS_POINT &s2,
+	const CLASS_PLANE &plane,
+	CLASS_POINT &clipped1,CLASS_POINT &clipped2)
+{
+	eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
+	switch(intersection_type)
+	{
+	case G_FRONT_PLANE_S1:
+		VEC_COPY(clipped1,s1);
+	    VEC_COPY(clipped2,s2);
+		break;
+	case G_FRONT_PLANE_S2:
+		VEC_COPY(clipped1,s2);
+	    VEC_COPY(clipped2,s1);
+		break;
+	case G_BACK_PLANE_S1:
+		VEC_COPY(clipped1,s1);
+	    VEC_COPY(clipped2,s2);
+		break;
+	case G_BACK_PLANE_S2:
+		VEC_COPY(clipped1,s2);
+	    VEC_COPY(clipped2,s1);
+		break;
+	case G_COLLIDE_PLANE_S1:
+		VEC_COPY(clipped2,s1);
+		break;
+	case G_COLLIDE_PLANE_S2:
+		VEC_COPY(clipped2,s2);
+		break;
+	}
+	return intersection_type;
+}
+
+
+//! Finds the 2 smallest cartesian coordinates of a plane normal
+#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
+
+//! Ray plane collision in one way
+/*!
+Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).<br/>
+It uses the PLANEDIREPSILON constant.
+*/
+template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
+	const CLASS_PLANE & plane,
+	const CLASS_POINT & vDir,
+	const CLASS_POINT & vPoint,
+	CLASS_POINT & pout,T &tparam)
+{
+	GREAL _dis,_dotdir;
+	_dotdir = VEC_DOT(plane,vDir);
+	if(_dotdir<PLANEDIREPSILON)
+	{
+	    return false;
+	}
+	_dis = DISTANCE_PLANE_POINT(plane,vPoint);
+	tparam = -_dis/_dotdir;
+	VEC_SCALE(pout,tparam,vDir);
+	VEC_SUM(pout,vPoint,pout);
+	return true;
+}
+
+//! line collision
+/*!
+*\return
+	-0  if the ray never intersects
+	-1 if the ray collides in front
+	-2 if the ray collides in back
+*/
+template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
+	const CLASS_PLANE & plane,
+	const CLASS_POINT & vDir,
+	const CLASS_POINT & vPoint,
+	CLASS_POINT & pout,
+	T &tparam,
+	T tmin, T tmax)
+{
+	GREAL _dis,_dotdir;
+	_dotdir = VEC_DOT(plane,vDir);
+	if(btFabs(_dotdir)<PLANEDIREPSILON)
+	{
+		tparam = tmax;
+	    return 0;
+	}
+	_dis = DISTANCE_PLANE_POINT(plane,vPoint);
+	char returnvalue = _dis<0.0f?2:1;
+	tparam = -_dis/_dotdir;
+
+	if(tparam<tmin)
+	{
+		returnvalue = 0;
+		tparam = tmin;
+	}
+	else if(tparam>tmax)
+	{
+		returnvalue = 0;
+		tparam = tmax;
+	}
+
+	VEC_SCALE(pout,tparam,vDir);
+	VEC_SUM(pout,vPoint,pout);
+	return returnvalue;
+}
+
+/*! \brief Returns the Ray on which 2 planes intersect if they do.
+    Written by Rodrigo Hernandez on ODE convex collision
+
+  \param p1 Plane 1
+  \param p2 Plane 2
+  \param p Contains the origin of the ray upon returning if planes intersect
+  \param d Contains the direction of the ray upon returning if planes intersect
+  \return true if the planes intersect, 0 if paralell.
+
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE bool INTERSECT_PLANES(
+		const CLASS_PLANE &p1,
+		const CLASS_PLANE &p2,
+		CLASS_POINT &p,
+		CLASS_POINT &d)
+{
+	VEC_CROSS(d,p1,p2);
+  	GREAL denom = VEC_DOT(d, d);
+  	if(GIM_IS_ZERO(denom)) return false;
+	vec3f _n;
+	_n[0]=p1[3]*p2[0] - p2[3]*p1[0];
+	_n[1]=p1[3]*p2[1] - p2[3]*p1[1];
+	_n[2]=p1[3]*p2[2] - p2[3]*p1[2];
+	VEC_CROSS(p,_n,d);
+	p[0]/=denom;
+	p[1]/=denom;
+	p[2]/=denom;
+	return true;
+}
+
+//***************** SEGMENT and LINE FUNCTIONS **********************************///
+
+/*! Finds the closest point(cp) to (v) on a segment (e1,e2)
+ */
+template<typename CLASS_POINT>
+SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
+	CLASS_POINT & cp, const CLASS_POINT & v,
+	const CLASS_POINT &e1,const CLASS_POINT &e2)
+{
+    vec3f _n;
+    VEC_DIFF(_n,e2,e1);
+    VEC_DIFF(cp,v,e1);
+	GREAL _scalar = VEC_DOT(cp, _n);
+	_scalar/= VEC_DOT(_n, _n);
+	if(_scalar <0.0f)
+	{
+	    VEC_COPY(cp,e1);
+	}
+	else if(_scalar >1.0f)
+	{
+	    VEC_COPY(cp,e2);
+	}
+	else
+	{
+        VEC_SCALE(cp,_scalar,_n);
+        VEC_SUM(cp,cp,e1);
+	}
+}
+
+
+/*! \brief Finds the line params where these lines intersect.
+
+\param dir1 Direction of line 1
+\param point1 Point of line 1
+\param dir2 Direction of line 2
+\param point2 Point of line 2
+\param t1 Result Parameter for line 1
+\param t2 Result Parameter for line 2
+\param dointersect  0  if the lines won't intersect, else 1
+
+*/
+template<typename T,typename CLASS_POINT>
+SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
+	const CLASS_POINT & dir1,
+	CLASS_POINT & point1,
+	const CLASS_POINT & dir2,
+	CLASS_POINT &  point2,
+	T& t1,T& t2)
+{
+    GREAL det;
+	GREAL e1e1 = VEC_DOT(dir1,dir1);
+	GREAL e1e2 = VEC_DOT(dir1,dir2);
+	GREAL e2e2 = VEC_DOT(dir2,dir2);
+	vec3f p1p2;
+    VEC_DIFF(p1p2,point1,point2);
+    GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
+	GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
+	det = e1e2*e1e2 - e1e1*e2e2;
+	if(GIM_IS_ZERO(det)) return false;
+	t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
+	t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
+	return true;
+}
+
+//! Find closest points on segments
+template<typename CLASS_POINT>
+SIMD_FORCE_INLINE void SEGMENT_COLLISION(
+	const CLASS_POINT & vA1,
+	const CLASS_POINT & vA2,
+	const CLASS_POINT & vB1,
+	const CLASS_POINT & vB2,
+	CLASS_POINT & vPointA,
+	CLASS_POINT & vPointB)
+{
+    CLASS_POINT _AD,_BD,_N;
+    vec4f _M;//plane
+    VEC_DIFF(_AD,vA2,vA1);
+    VEC_DIFF(_BD,vB2,vB1);
+    VEC_CROSS(_N,_AD,_BD);
+    GREAL _tp = VEC_DOT(_N,_N);
+    if(_tp<G_EPSILON)//ARE PARALELE
+    {
+    	//project B over A
+    	bool invert_b_order = false;
+    	_M[0] = VEC_DOT(vB1,_AD);
+    	_M[1] = VEC_DOT(vB2,_AD);
+    	if(_M[0]>_M[1])
+    	{
+    		invert_b_order  = true;
+    		GIM_SWAP_NUMBERS(_M[0],_M[1]);
+    	}
+    	_M[2] = VEC_DOT(vA1,_AD);
+    	_M[3] = VEC_DOT(vA2,_AD);
+    	//mid points
+    	_N[0] = (_M[0]+_M[1])*0.5f;
+    	_N[1] = (_M[2]+_M[3])*0.5f;
+
+    	if(_N[0]<_N[1])
+    	{
+    		if(_M[1]<_M[2])
+    		{
+    			vPointB = invert_b_order?vB1:vB2;
+    			vPointA = vA1;
+    		}
+    		else if(_M[1]<_M[3])
+    		{
+    			vPointB = invert_b_order?vB1:vB2;
+    			CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
+    		}
+    		else
+    		{
+    			vPointA = vA2;
+    			CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
+    		}
+    	}
+    	else
+    	{
+    		if(_M[3]<_M[0])
+    		{
+    			vPointB = invert_b_order?vB2:vB1;
+    			vPointA = vA2;
+    		}
+    		else if(_M[3]<_M[1])
+    		{
+    			vPointA = vA2;
+    			CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
+    		}
+    		else
+    		{
+    			vPointB = invert_b_order?vB1:vB2;
+    			CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
+    		}
+    	}
+    	return;
+    }
+
+
+    VEC_CROSS(_M,_N,_BD);
+    _M[3] = VEC_DOT(_M,vB1);
+
+    LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1));
+    /*Closest point on segment*/
+    VEC_DIFF(vPointB,vPointA,vB1);
+	_tp = VEC_DOT(vPointB, _BD);
+	_tp/= VEC_DOT(_BD, _BD);
+	_tp = GIM_CLAMP(_tp,0.0f,1.0f);
+    VEC_SCALE(vPointB,_tp,_BD);
+    VEC_SUM(vPointB,vPointB,vB1);
+}
+
+
+
+
+//! Line box intersection in one dimension
+/*!
+
+*\param pos Position of the ray
+*\param dir Projection of the Direction of the ray
+*\param bmin Minimum bound of the box
+*\param bmax Maximum bound of the box
+*\param tfirst the minimum projection. Assign to 0 at first.
+*\param tlast the maximum projection. Assign to INFINITY at first.
+*\return true if there is an intersection.
+*/
+template<typename T>
+SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
+{
+	if(GIM_IS_ZERO(dir))
+	{
+        return !(pos < bmin || pos > bmax);
+	}
+	GREAL a0 = (bmin - pos) / dir;
+	GREAL a1 = (bmax - pos) / dir;
+	if(a0 > a1)   GIM_SWAP_NUMBERS(a0, a1);
+	tfirst = GIM_MAX(a0, tfirst);
+	tlast = GIM_MIN(a1, tlast);
+	if (tlast < tfirst) return false;
+	return true;
+}
+
+
+//! Sorts 3 componets
+template<typename T>
+SIMD_FORCE_INLINE void SORT_3_INDICES(
+		const T * values,
+		GUINT * order_indices)
+{
+	//get minimum
+	order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
+
+	//get second and third
+	GUINT i0 = (order_indices[0] + 1)%3;
+	GUINT i1 = (i0 + 1)%3;
+
+	if(values[i0] < values[i1])
+	{
+		order_indices[1] = i0;
+		order_indices[2] = i1;
+	}
+	else
+	{
+		order_indices[1] = i1;
+		order_indices[2] = i0;
+	}
+}
+
+
+
+
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_bitset.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_bitset.h
new file mode 100644
index 0000000..322004a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_bitset.h
@@ -0,0 +1,123 @@
+#ifndef GIM_BITSET_H_INCLUDED
+#define GIM_BITSET_H_INCLUDED
+/*! \file gim_bitset.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_array.h"
+
+
+#define GUINT_BIT_COUNT 32
+#define GUINT_EXPONENT 5
+
+class gim_bitset
+{
+public:
+    gim_array<GUINT> m_container;
+
+    gim_bitset()
+    {
+
+    }
+
+    gim_bitset(GUINT bits_count)
+    {
+        resize(bits_count);
+    }
+
+    ~gim_bitset()
+    {
+    }
+
+	inline bool resize(GUINT newsize)
+	{
+		GUINT oldsize = m_container.size();
+		m_container.resize(newsize/GUINT_BIT_COUNT + 1,false);
+		while(oldsize<m_container.size())
+		{
+			m_container[oldsize] = 0;
+		}
+		return true;
+	}
+
+	inline GUINT size()
+	{
+		return m_container.size()*GUINT_BIT_COUNT;
+	}
+
+	inline void set_all()
+	{
+		for(GUINT i = 0;i<m_container.size();++i)
+		{
+			m_container[i] = 0xffffffff;
+		}
+	}
+
+	inline void clear_all()
+	{
+	    for(GUINT i = 0;i<m_container.size();++i)
+		{
+			m_container[i] = 0;
+		}
+	}
+
+	inline void set(GUINT bit_index)
+	{
+		if(bit_index>=size())
+		{
+			resize(bit_index);
+		}
+		m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1)));
+	}
+
+	///Return 0 or 1
+	inline char get(GUINT bit_index)
+	{
+		if(bit_index>=size())
+		{
+			return 0;
+		}
+		char value = m_container[bit_index >> GUINT_EXPONENT] &
+					 (1 << (bit_index & (GUINT_BIT_COUNT-1)));
+		return value;
+	}
+
+	inline void clear(GUINT bit_index)
+	{
+	    m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1)));
+	}
+};
+
+
+
+
+
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_collision.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_collision.h
new file mode 100644
index 0000000..0add5e4
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_collision.h
@@ -0,0 +1,590 @@
+#ifndef GIM_BOX_COLLISION_H_INCLUDED
+#define GIM_BOX_COLLISION_H_INCLUDED
+
+/*! \file gim_box_collision.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+#include "gim_basic_geometry_operations.h"
+#include "LinearMath/btTransform.h"
+
+
+
+//SIMD_FORCE_INLINE bool test_cross_edge_box(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, const btVector3 & extend,
+//	int dir_index0,
+//	int dir_index1
+//	int component_index0,
+//	int component_index1)
+//{
+//	// dir coords are -z and y
+//
+//	const btScalar dir0 = -edge[dir_index0];
+//	const btScalar dir1 = edge[dir_index1];
+//	btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
+//	btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
+//	//find minmax
+//	if(pmin>pmax)
+//	{
+//		GIM_SWAP_NUMBERS(pmin,pmax);
+//	}
+//	//find extends
+//	const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
+//					extend[component_index1] * absolute_edge[dir_index1];
+//
+//	if(pmin>rad || -rad>pmax) return false;
+//	return true;
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
+//}
+//
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
+//}
+//
+//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
+//	const btVector3 & edge,
+//	const btVector3 & absolute_edge,
+//	const btVector3 & pointa,
+//	const btVector3 & pointb, btVector3 & extend)
+//{
+//
+//	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
+//}
+
+#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
+{\
+	const btScalar dir0 = -edge[i_dir_0];\
+	const btScalar dir1 = edge[i_dir_1];\
+	btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
+	btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
+	if(pmin>pmax)\
+	{\
+		GIM_SWAP_NUMBERS(pmin,pmax); \
+	}\
+	const btScalar abs_dir0 = absolute_edge[i_dir_0];\
+	const btScalar abs_dir1 = absolute_edge[i_dir_1];\
+	const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
+	if(pmin>rad || -rad>pmax) return false;\
+}\
+
+
+#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
+}\
+
+#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
+{\
+	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
+}\
+
+
+
+//!  Class for transforming a model1 to the space of model0
+class GIM_BOX_BOX_TRANSFORM_CACHE
+{
+public:
+    btVector3  m_T1to0;//!< Transforms translation of model1 to model 0
+	btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal  to R0' * R1
+	btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
+
+	SIMD_FORCE_INLINE void calc_absolute_matrix()
+	{
+		static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
+		m_AR[0] = vepsi + m_R1to0[0].absolute();
+		m_AR[1] = vepsi + m_R1to0[1].absolute();
+		m_AR[2] = vepsi + m_R1to0[2].absolute();
+	}
+
+	GIM_BOX_BOX_TRANSFORM_CACHE()
+	{
+	}
+
+
+	GIM_BOX_BOX_TRANSFORM_CACHE(mat4f  trans1_to_0)
+	{
+		COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
+        MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
+		calc_absolute_matrix();
+	}
+
+	//! Calc the transformation relative  1 to 0. Inverts matrics by transposing
+	SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
+	{
+
+		m_R1to0 = trans0.getBasis().transpose();
+		m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+		m_T1to0 += m_R1to0*trans1.getOrigin();
+		m_R1to0 *= trans1.getBasis();
+
+		calc_absolute_matrix();
+	}
+
+	//! Calcs the full invertion of the matrices. Useful for scaling matrices
+	SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
+	{
+		m_R1to0 = trans0.getBasis().inverse();
+		m_T1to0 = m_R1to0 * (-trans0.getOrigin());
+
+		m_T1to0 += m_R1to0*trans1.getOrigin();
+		m_R1to0 *= trans1.getBasis();
+
+		calc_absolute_matrix();
+	}
+
+	SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
+	{
+		return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
+			m_R1to0[1].dot(point) + m_T1to0.y(),
+			m_R1to0[2].dot(point) + m_T1to0.z());
+	}
+};
+
+
+#define BOX_PLANE_EPSILON 0.000001f
+
+//! Axis aligned box
+class GIM_AABB
+{
+public:
+	btVector3 m_min;
+	btVector3 m_max;
+
+	GIM_AABB()
+	{}
+
+
+	GIM_AABB(const btVector3 & V1,
+			 const btVector3 & V2,
+			 const btVector3 & V3)
+	{
+		m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+	}
+
+	GIM_AABB(const btVector3 & V1,
+			 const btVector3 & V2,
+			 const btVector3 & V3,
+			 GREAL margin)
+	{
+		m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	GIM_AABB(const GIM_AABB &other):
+		m_min(other.m_min),m_max(other.m_max)
+	{
+	}
+
+	GIM_AABB(const GIM_AABB &other,btScalar margin ):
+		m_min(other.m_min),m_max(other.m_max)
+	{
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	SIMD_FORCE_INLINE void invalidate()
+	{
+		m_min[0] = G_REAL_INFINITY;
+		m_min[1] = G_REAL_INFINITY;
+		m_min[2] = G_REAL_INFINITY;
+		m_max[0] = -G_REAL_INFINITY;
+		m_max[1] = -G_REAL_INFINITY;
+		m_max[2] = -G_REAL_INFINITY;
+	}
+
+	SIMD_FORCE_INLINE void increment_margin(btScalar margin)
+	{
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
+	{
+		m_min[0] = other.m_min[0] - margin;
+		m_min[1] = other.m_min[1] - margin;
+		m_min[2] = other.m_min[2] - margin;
+
+		m_max[0] = other.m_max[0] + margin;
+		m_max[1] = other.m_max[1] + margin;
+		m_max[2] = other.m_max[2] + margin;
+	}
+
+	template<typename CLASS_POINT>
+	SIMD_FORCE_INLINE void calc_from_triangle(
+							const CLASS_POINT & V1,
+							const CLASS_POINT & V2,
+							const CLASS_POINT & V3)
+	{
+		m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+	}
+
+	template<typename CLASS_POINT>
+	SIMD_FORCE_INLINE void calc_from_triangle_margin(
+							const CLASS_POINT & V1,
+							const CLASS_POINT & V2,
+							const CLASS_POINT & V3, btScalar margin)
+	{
+		m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
+		m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
+		m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
+
+		m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
+		m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
+		m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
+
+		m_min[0] -= margin;
+		m_min[1] -= margin;
+		m_min[2] -= margin;
+		m_max[0] += margin;
+		m_max[1] += margin;
+		m_max[2] += margin;
+	}
+
+	//! Apply a transform to an AABB
+	SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
+	{
+		btVector3 center = (m_max+m_min)*0.5f;
+		btVector3 extends = m_max - center;
+		// Compute new center
+		center = trans(center);
+
+		btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
+ 				 extends.dot(trans.getBasis().getRow(1).absolute()),
+				 extends.dot(trans.getBasis().getRow(2).absolute()));
+
+		m_min = center - textends;
+		m_max = center + textends;
+	}
+
+	//! Merges a Box
+	SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
+	{
+		m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
+		m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
+		m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
+
+		m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
+		m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
+		m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
+	}
+
+	//! Merges a point
+	template<typename CLASS_POINT>
+	SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
+	{
+		m_min[0] = GIM_MIN(m_min[0],point[0]);
+		m_min[1] = GIM_MIN(m_min[1],point[1]);
+		m_min[2] = GIM_MIN(m_min[2],point[2]);
+
+		m_max[0] = GIM_MAX(m_max[0],point[0]);
+		m_max[1] = GIM_MAX(m_max[1],point[1]);
+		m_max[2] = GIM_MAX(m_max[2],point[2]);
+	}
+
+	//! Gets the extend and center
+	SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend)  const
+	{
+		center = (m_max+m_min)*0.5f;
+		extend = m_max - center;
+	}
+
+	//! Finds the intersecting box between this box and the other.
+	SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection)  const
+	{
+		intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
+		intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
+		intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
+
+		intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
+		intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
+		intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
+	}
+
+
+	SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
+	{
+		if(m_min[0] > other.m_max[0] ||
+		   m_max[0] < other.m_min[0] ||
+		   m_min[1] > other.m_max[1] ||
+		   m_max[1] < other.m_min[1] ||
+		   m_min[2] > other.m_max[2] ||
+		   m_max[2] < other.m_min[2])
+		{
+			return false;
+		}
+		return true;
+	}
+
+	/*! \brief Finds the Ray intersection parameter.
+	\param aabb Aligned box
+	\param vorigin A vec3f with the origin of the ray
+	\param vdir A vec3f with the direction of the ray
+	*/
+	SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
+	{
+		btVector3 extents,center;
+		this->get_center_extend(center,extents);;
+
+		btScalar Dx = vorigin[0] - center[0];
+		if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f)	return false;
+		btScalar Dy = vorigin[1] - center[1];
+		if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f)	return false;
+		btScalar Dz = vorigin[2] - center[2];
+		if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f)	return false;
+
+
+		btScalar f = vdir[1] * Dz - vdir[2] * Dy;
+		if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
+		f = vdir[2] * Dx - vdir[0] * Dz;
+		if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
+		f = vdir[0] * Dy - vdir[1] * Dx;
+		if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
+		return true;
+	}
+
+
+	SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
+	{
+		btVector3 center = (m_max+m_min)*0.5f;
+		btVector3 extend = m_max-center;
+
+		btScalar _fOrigin =  direction.dot(center);
+		btScalar _fMaximumExtent = extend.dot(direction.absolute());
+		vmin = _fOrigin - _fMaximumExtent;
+		vmax = _fOrigin + _fMaximumExtent;
+	}
+
+	SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
+	{
+		btScalar _fmin,_fmax;
+		this->projection_interval(plane,_fmin,_fmax);
+
+		if(plane[3] > _fmax + BOX_PLANE_EPSILON)
+		{
+			return G_BACK_PLANE; // 0
+		}
+
+		if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
+		{
+			return G_COLLIDE_PLANE; //1
+		}
+		return G_FRONT_PLANE;//2
+	}
+
+	SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
+	{
+		GIM_AABB tbox = box;
+		tbox.appy_transform(trans1_to_0);
+		return has_collision(tbox);
+	}
+
+	//! transcache is the transformation cache from box to this AABB
+	SIMD_FORCE_INLINE bool overlapping_trans_cache(
+		const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
+	{
+
+		//Taken from OPCODE
+		btVector3 ea,eb;//extends
+		btVector3 ca,cb;//extends
+		get_center_extend(ca,ea);
+		box.get_center_extend(cb,eb);
+
+
+		btVector3 T;
+		btScalar t,t2;
+		int i;
+
+		// Class I : A's basis vectors
+		for(i=0;i<3;i++)
+		{
+			T[i] =  transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
+			t = transcache.m_AR[i].dot(eb) + ea[i];
+			if(GIM_GREATER(T[i], t))	return false;
+		}
+		// Class II : B's basis vectors
+		for(i=0;i<3;i++)
+		{
+			t = MAT_DOT_COL(transcache.m_R1to0,T,i);
+			t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
+			if(GIM_GREATER(t,t2))	return false;
+		}
+		// Class III : 9 cross products
+		if(fulltest)
+		{
+			int j,m,n,o,p,q,r;
+			for(i=0;i<3;i++)
+			{
+				m = (i+1)%3;
+				n = (i+2)%3;
+				o = i==0?1:0;
+				p = i==2?1:2;
+				for(j=0;j<3;j++)
+				{
+					q = j==2?1:2;
+					r = j==0?1:0;
+					t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
+					t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
+						eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
+					if(GIM_GREATER(t,t2))	return false;
+				}
+			}
+		}
+		return true;
+	}
+
+	//! Simple test for planes.
+	SIMD_FORCE_INLINE bool collide_plane(
+		const btVector4 & plane)
+	{
+		ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
+		return (classify == G_COLLIDE_PLANE);
+	}
+
+	//! test for a triangle, with edges
+	SIMD_FORCE_INLINE bool collide_triangle_exact(
+		const btVector3 & p1,
+		const btVector3 & p2,
+		const btVector3 & p3,
+		const btVector4 & triangle_plane)
+	{
+		if(!collide_plane(triangle_plane)) return false;
+
+		btVector3 center,extends;
+		this->get_center_extend(center,extends);
+
+		const btVector3 v1(p1 - center);
+		const btVector3 v2(p2 - center);
+		const btVector3 v3(p3 - center);
+
+		//First axis
+		btVector3 diff(v2 - v1);
+		btVector3 abs_diff = diff.absolute();
+		//Test With X axis
+		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+		//Test With Y axis
+		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+		//Test With Z axis
+		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
+
+
+		diff = v3 - v2;
+		abs_diff = diff.absolute();
+		//Test With X axis
+		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+		//Test With Y axis
+		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+		//Test With Z axis
+		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
+
+		diff = v1 - v3;
+		abs_diff = diff.absolute();
+		//Test With X axis
+		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+		//Test With Y axis
+		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+		//Test With Z axis
+		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
+
+		return true;
+	}
+};
+
+
+//! Compairison of transformation objects
+SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
+{
+	if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
+
+	if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
+	if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
+	if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
+	return true;
+}
+
+
+
+#endif // GIM_BOX_COLLISION_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_set.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_set.cpp
new file mode 100644
index 0000000..0c3d7ba
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_set.cpp
@@ -0,0 +1,182 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_box_set.h"
+
+
+GUINT GIM_BOX_TREE::_calc_splitting_axis(
+	gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,  GUINT endIndex)
+{
+	GUINT i;
+
+	btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.));
+	btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.));
+	GUINT numIndices = endIndex-startIndex;
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		means+=center;
+	}
+	means *= (btScalar(1.)/(btScalar)numIndices);
+
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btVector3 center = btScalar(0.5)*(primitive_boxes[i].m_bound.m_max +
+					 primitive_boxes[i].m_bound.m_min);
+		btVector3 diff2 = center-means;
+		diff2 = diff2 * diff2;
+		variance += diff2;
+	}
+	variance *= (btScalar(1.)/	((btScalar)numIndices-1)	);
+
+	return variance.maxAxis();
+}
+
+
+GUINT GIM_BOX_TREE::_sort_and_calc_splitting_index(
+	gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,
+	GUINT endIndex, GUINT splitAxis)
+{
+	GUINT i;
+	GUINT splitIndex =startIndex;
+	GUINT numIndices = endIndex - startIndex;
+
+	// average of centers
+	btScalar splitValue = 0.0f;
+	for (i=startIndex;i<endIndex;i++)
+	{
+		splitValue+= 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
+					 primitive_boxes[i].m_bound.m_min[splitAxis]);
+	}
+	splitValue /= (btScalar)numIndices;
+
+	//sort leafNodes so all values larger then splitValue comes first, and smaller values start from 'splitIndex'.
+	for (i=startIndex;i<endIndex;i++)
+	{
+		btScalar center = 0.5f*(primitive_boxes[i].m_bound.m_max[splitAxis] +
+					 primitive_boxes[i].m_bound.m_min[splitAxis]);
+		if (center > splitValue)
+		{
+			//swap
+			primitive_boxes.swap(i,splitIndex);
+			splitIndex++;
+		}
+	}
+
+	//if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex
+	//otherwise the tree-building might fail due to stack-overflows in certain cases.
+	//unbalanced1 is unsafe: it can cause stack overflows
+	//bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1)));
+
+	//unbalanced2 should work too: always use center (perfect balanced trees)
+	//bool unbalanced2 = true;
+
+	//this should be safe too:
+	GUINT rangeBalancedIndices = numIndices/3;
+	bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices)));
+
+	if (unbalanced)
+	{
+		splitIndex = startIndex+ (numIndices>>1);
+	}
+
+	btAssert(!((splitIndex==startIndex) || (splitIndex == (endIndex))));
+
+	return splitIndex;
+}
+
+
+void GIM_BOX_TREE::_build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,  GUINT endIndex)
+{
+	GUINT current_index = m_num_nodes++;
+
+	btAssert((endIndex-startIndex)>0);
+
+	if((endIndex-startIndex) == 1) //we got a leaf
+	{		
+		m_node_array[current_index].m_left = 0;
+		m_node_array[current_index].m_right = 0;
+		m_node_array[current_index].m_escapeIndex = 0;
+
+		m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound;
+		m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data;
+		return;
+	}
+
+	//configure inner node
+
+	GUINT splitIndex;
+
+	//calc this node bounding box
+	m_node_array[current_index].m_bound.invalidate();	
+	for (splitIndex=startIndex;splitIndex<endIndex;splitIndex++)
+	{
+		m_node_array[current_index].m_bound.merge(primitive_boxes[splitIndex].m_bound);
+	}
+
+	//calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'.
+
+	//split axis
+	splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex);
+
+	splitIndex = _sort_and_calc_splitting_index(
+			primitive_boxes,startIndex,endIndex,splitIndex);
+
+	//configure this inner node : the left node index
+	m_node_array[current_index].m_left = m_num_nodes;
+	//build left child tree
+	_build_sub_tree(primitive_boxes, startIndex, splitIndex );
+
+	//configure this inner node : the right node index
+	m_node_array[current_index].m_right = m_num_nodes;
+
+	//build right child tree
+	_build_sub_tree(primitive_boxes, splitIndex ,endIndex);
+
+	//configure this inner node : the escape index
+	m_node_array[current_index].m_escapeIndex  = m_num_nodes - current_index;
+}
+
+//! stackless build tree
+void GIM_BOX_TREE::build_tree(
+	gim_array<GIM_AABB_DATA> & primitive_boxes)
+{
+	// initialize node count to 0
+	m_num_nodes = 0;
+	// allocate nodes
+	m_node_array.resize(primitive_boxes.size()*2);
+	
+	_build_sub_tree(primitive_boxes, 0, primitive_boxes.size());
+}
+
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_set.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_set.h
new file mode 100644
index 0000000..1058a08
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_box_set.h
@@ -0,0 +1,671 @@
+#ifndef GIM_BOX_SET_H_INCLUDED
+#define GIM_BOX_SET_H_INCLUDED
+
+/*! \file gim_box_set.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_array.h"
+#include "gim_radixsort.h"
+#include "gim_box_collision.h"
+#include "gim_tri_collision.h"
+
+
+
+//! Overlapping pair
+struct GIM_PAIR
+{
+    GUINT m_index1;
+    GUINT m_index2;
+    GIM_PAIR()
+    {}
+
+    GIM_PAIR(const GIM_PAIR & p)
+    {
+    	m_index1 = p.m_index1;
+    	m_index2 = p.m_index2;
+	}
+
+	GIM_PAIR(GUINT index1, GUINT index2)
+    {
+    	m_index1 = index1;
+    	m_index2 = index2;
+	}
+};
+
+//! A pairset array
+class gim_pair_set: public gim_array<GIM_PAIR>
+{
+public:
+	gim_pair_set():gim_array<GIM_PAIR>(32)
+	{
+	}
+	inline void push_pair(GUINT index1,GUINT index2)
+	{
+		push_back(GIM_PAIR(index1,index2));
+	}
+
+	inline void push_pair_inv(GUINT index1,GUINT index2)
+	{
+		push_back(GIM_PAIR(index2,index1));
+	}
+};
+
+
+//! Prototype Base class for primitive classification
+/*!
+This class is a wrapper for primitive collections.
+This tells relevant info for the Bounding Box set classes, which take care of space classification.
+This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the  Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons.
+*/
+class GIM_PRIMITIVE_MANAGER_PROTOTYPE
+{
+public:
+
+	//! determines if this manager consist on only triangles, which special case will be optimized
+	virtual bool is_trimesh() = 0;
+	virtual GUINT get_primitive_count() = 0;
+	virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0;
+	virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0;
+};
+
+
+struct GIM_AABB_DATA
+{
+	GIM_AABB m_bound;
+	GUINT m_data;
+};
+
+//! Node Structure for trees
+struct GIM_BOX_TREE_NODE
+{
+	GIM_AABB m_bound;
+	GUINT m_left;//!< Left subtree
+	GUINT m_right;//!< Right subtree
+	GUINT m_escapeIndex;//!< Scape index for traversing
+	GUINT m_data;//!< primitive index if apply
+
+	GIM_BOX_TREE_NODE()
+	{
+	    m_left = 0;
+	    m_right = 0;
+	    m_escapeIndex = 0;
+	    m_data = 0;
+	}
+
+	SIMD_FORCE_INLINE bool is_leaf_node() const
+	{
+	    return  (!m_left && !m_right);
+	}
+};
+
+//! Basic Box tree structure
+class GIM_BOX_TREE
+{
+protected:
+	GUINT m_num_nodes;
+	gim_array<GIM_BOX_TREE_NODE> m_node_array;
+protected:
+	GUINT _sort_and_calc_splitting_index(
+		gim_array<GIM_AABB_DATA> & primitive_boxes,
+		 GUINT startIndex,  GUINT endIndex, GUINT splitAxis);
+
+	GUINT _calc_splitting_axis(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,  GUINT endIndex);
+
+	void _build_sub_tree(gim_array<GIM_AABB_DATA> & primitive_boxes, GUINT startIndex,  GUINT endIndex);
+public:
+	GIM_BOX_TREE()
+	{
+		m_num_nodes = 0;
+	}
+
+	//! prototype functions for box tree management
+	//!@{
+	void build_tree(gim_array<GIM_AABB_DATA> & primitive_boxes);
+
+	SIMD_FORCE_INLINE void clearNodes()
+	{
+		m_node_array.clear();
+		m_num_nodes = 0;
+	}
+
+	//! node count
+	SIMD_FORCE_INLINE GUINT getNodeCount() const
+	{
+		return m_num_nodes;
+	}
+
+	//! tells if the node is a leaf
+	SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
+	{
+		return m_node_array[nodeindex].is_leaf_node();
+	}
+
+	SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
+	{
+		return m_node_array[nodeindex].m_data;
+	}
+
+	SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const
+	{
+		bound = m_node_array[nodeindex].m_bound;
+	}
+
+	SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
+	{
+		m_node_array[nodeindex].m_bound = bound;
+	}
+
+	SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex)  const
+	{
+		return m_node_array[nodeindex].m_left;
+	}
+
+	SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex)  const
+	{
+		return m_node_array[nodeindex].m_right;
+	}
+
+	SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
+	{
+		return m_node_array[nodeindex].m_escapeIndex;
+	}
+
+	//!@}
+};
+
+
+//! Generic Box Tree Template
+/*!
+This class offers an structure for managing a box tree of primitives.
+Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and
+a Box tree structure ( like GIM_BOX_TREE).
+*/
+template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE, typename _GIM_BOX_TREE_PROTOTYPE>
+class GIM_BOX_TREE_TEMPLATE_SET
+{
+protected:
+	_GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager;
+	_GIM_BOX_TREE_PROTOTYPE m_box_tree;
+protected:
+	//stackless refit
+	SIMD_FORCE_INLINE void refit()
+	{
+		GUINT nodecount = getNodeCount();
+		while(nodecount--)
+		{
+			if(isLeafNode(nodecount))
+			{
+				GIM_AABB leafbox;
+				m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox);
+				setNodeBound(nodecount,leafbox);
+			}
+			else
+			{
+				//get left bound
+				GUINT childindex = getLeftNodeIndex(nodecount);
+				GIM_AABB bound;
+				getNodeBound(childindex,bound);
+				//get right bound
+				childindex = getRightNodeIndex(nodecount);
+				GIM_AABB bound2;
+				getNodeBound(childindex,bound2);
+				bound.merge(bound2);
+
+				setNodeBound(nodecount,bound);
+			}
+		}
+	}
+public:
+
+	GIM_BOX_TREE_TEMPLATE_SET()
+	{
+	}
+
+	SIMD_FORCE_INLINE GIM_AABB getGlobalBox()  const
+	{
+		GIM_AABB totalbox;
+		getNodeBound(0, totalbox);
+		return totalbox;
+	}
+
+	SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager)
+	{
+		m_primitive_manager = primitive_manager;
+	}
+
+	const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const
+	{
+		return m_primitive_manager;
+	}
+
+	_GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager()
+	{
+		return m_primitive_manager;
+	}
+
+//! node manager prototype functions
+///@{
+
+	//! this attemps to refit the box set.
+	SIMD_FORCE_INLINE void update()
+	{
+		refit();
+	}
+
+	//! this rebuild the entire set
+	SIMD_FORCE_INLINE void buildSet()
+	{
+		//obtain primitive boxes
+		gim_array<GIM_AABB_DATA> primitive_boxes;
+		primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false);
+
+		for (GUINT i = 0;i<primitive_boxes.size() ;i++ )
+		{
+			 m_primitive_manager.get_primitive_box(i,primitive_boxes[i].m_bound);
+			 primitive_boxes[i].m_data = i;
+		}
+
+		m_box_tree.build_tree(primitive_boxes);
+	}
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	SIMD_FORCE_INLINE bool boxQuery(const GIM_AABB & box, gim_array<GUINT> & collided_results) const
+	{
+		GUINT curIndex = 0;
+		GUINT numNodes = getNodeCount();
+
+		while (curIndex < numNodes)
+		{
+			GIM_AABB bound;
+			getNodeBound(curIndex,bound);
+
+			//catch bugs in tree data
+
+			bool aabbOverlap = bound.has_collision(box);
+			bool isleafnode = isLeafNode(curIndex);
+
+			if (isleafnode && aabbOverlap)
+			{
+				collided_results.push_back(getNodeData(curIndex));
+			}
+
+			if (aabbOverlap || isleafnode)
+			{
+				//next subnode
+				curIndex++;
+			}
+			else
+			{
+				//skip node
+				curIndex+= getScapeNodeIndex(curIndex);
+			}
+		}
+		if(collided_results.size()>0) return true;
+		return false;
+	}
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box,
+		 const btTransform & transform, gim_array<GUINT> & collided_results) const
+	{
+		GIM_AABB transbox=box;
+		transbox.appy_transform(transform);
+		return boxQuery(transbox,collided_results);
+	}
+
+	//! returns the indices of the primitives in the m_primitive_manager
+	SIMD_FORCE_INLINE bool rayQuery(
+		const btVector3 & ray_dir,const btVector3 & ray_origin ,
+		gim_array<GUINT> & collided_results) const
+	{
+		GUINT curIndex = 0;
+		GUINT numNodes = getNodeCount();
+
+		while (curIndex < numNodes)
+		{
+			GIM_AABB bound;
+			getNodeBound(curIndex,bound);
+
+			//catch bugs in tree data
+
+			bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir);
+			bool isleafnode = isLeafNode(curIndex);
+
+			if (isleafnode && aabbOverlap)
+			{
+				collided_results.push_back(getNodeData( curIndex));
+			}
+
+			if (aabbOverlap || isleafnode)
+			{
+				//next subnode
+				curIndex++;
+			}
+			else
+			{
+				//skip node
+				curIndex+= getScapeNodeIndex(curIndex);
+			}
+		}
+		if(collided_results.size()>0) return true;
+		return false;
+	}
+
+	//! tells if this set has hierarcht
+	SIMD_FORCE_INLINE bool hasHierarchy() const
+	{
+		return true;
+	}
+
+	//! tells if this set is a trimesh
+	SIMD_FORCE_INLINE bool isTrimesh()  const
+	{
+		return m_primitive_manager.is_trimesh();
+	}
+
+	//! node count
+	SIMD_FORCE_INLINE GUINT getNodeCount() const
+	{
+		return m_box_tree.getNodeCount();
+	}
+
+	//! tells if the node is a leaf
+	SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const
+	{
+		return m_box_tree.isLeafNode(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const
+	{
+		return m_box_tree.getNodeData(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound)  const
+	{
+		m_box_tree.getNodeBound(nodeindex, bound);
+	}
+
+	SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound)
+	{
+		m_box_tree.setNodeBound(nodeindex, bound);
+	}
+
+	SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const
+	{
+		return m_box_tree.getLeftNodeIndex(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const
+	{
+		return m_box_tree.getRightNodeIndex(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const
+	{
+		return m_box_tree.getScapeNodeIndex(nodeindex);
+	}
+
+	SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const
+	{
+		m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle);
+	}
+
+};
+
+//! Class for Box Tree Sets
+/*!
+this has the GIM_BOX_TREE implementation for bounding boxes.
+*/
+template<typename _GIM_PRIMITIVE_MANAGER_PROTOTYPE>
+class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE>
+{
+public:
+
+};
+
+
+
+
+
+/// GIM_BOX_SET collision methods
+template<typename BOX_SET_CLASS0,typename BOX_SET_CLASS1>
+class GIM_TREE_TREE_COLLIDER
+{
+public:
+	gim_pair_set * m_collision_pairs;
+	BOX_SET_CLASS0 * m_boxset0;
+	BOX_SET_CLASS1 * m_boxset1;
+	GUINT current_node0;
+	GUINT current_node1;
+	bool node0_is_leaf;
+	bool node1_is_leaf;
+	bool t0_is_trimesh;
+	bool t1_is_trimesh;
+	bool node0_has_triangle;
+	bool node1_has_triangle;
+	GIM_AABB m_box0;
+	GIM_AABB m_box1;
+	GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0;
+	btTransform trans_cache_0to1;
+	GIM_TRIANGLE m_tri0;
+	btVector4 m_tri0_plane;
+	GIM_TRIANGLE m_tri1;
+	btVector4 m_tri1_plane;
+
+
+public:
+	GIM_TREE_TREE_COLLIDER()
+	{
+		current_node0 = G_UINT_INFINITY;
+		current_node1 = G_UINT_INFINITY;
+	}
+protected:
+	SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0)
+	{
+		if(node0_has_triangle) return;
+		m_boxset0->getNodeTriangle(node0,m_tri0);
+		//transform triangle
+		m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]);
+		m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]);
+		m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]);
+		m_tri0.get_plane(m_tri0_plane);
+
+		node0_has_triangle = true;
+	}
+
+	SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1)
+	{
+		if(node1_has_triangle) return;
+		m_boxset1->getNodeTriangle(node1,m_tri1);
+		//transform triangle
+		m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]);
+		m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]);
+		m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]);
+		m_tri1.get_plane(m_tri1_plane);
+
+		node1_has_triangle = true;
+	}
+
+	SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0)
+	{
+		if(node0 == current_node0) return;
+		m_boxset0->getNodeBound(node0,m_box0);
+		node0_is_leaf = m_boxset0->isLeafNode(node0);
+		node0_has_triangle = false;
+		current_node0 = node0;
+	}
+
+	SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1)
+	{
+		if(node1 == current_node1) return;
+		m_boxset1->getNodeBound(node1,m_box1);
+		node1_is_leaf = m_boxset1->isLeafNode(node1);
+		node1_has_triangle = false;
+		current_node1 = node1;
+	}
+
+	SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1)
+	{
+		retrieve_node0_info(node0);
+		retrieve_node1_info(node1);
+		bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true);
+		if(!result) return false;
+
+		if(t0_is_trimesh && node0_is_leaf)
+		{
+			//perform primitive vs box collision
+			retrieve_node0_triangle(node0);
+			//do triangle vs box collision
+			m_box1.increment_margin(m_tri0.m_margin);
+
+			result = m_box1.collide_triangle_exact(
+				m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane);
+
+			m_box1.increment_margin(-m_tri0.m_margin);
+
+			if(!result) return false;
+			return true;
+		}
+		else if(t1_is_trimesh && node1_is_leaf)
+		{
+			//perform primitive vs box collision
+			retrieve_node1_triangle(node1);
+			//do triangle vs box collision
+			m_box0.increment_margin(m_tri1.m_margin);
+
+			result = m_box0.collide_triangle_exact(
+				m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane);
+
+			m_box0.increment_margin(-m_tri1.m_margin);
+
+			if(!result) return false;
+			return true;
+		}
+		return true;
+	}
+
+	//stackless collision routine
+	void find_collision_pairs()
+	{
+		gim_pair_set stack_collisions;
+		stack_collisions.reserve(32);
+
+		//add the first pair
+		stack_collisions.push_pair(0,0);
+
+
+		while(stack_collisions.size())
+		{
+			//retrieve the last pair and pop
+			GUINT node0 = stack_collisions.back().m_index1;
+			GUINT node1 = stack_collisions.back().m_index2;
+			stack_collisions.pop_back();
+			if(node_collision(node0,node1)) // a collision is found
+			{
+				if(node0_is_leaf)
+				{
+					if(node1_is_leaf)
+					{
+						m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1));
+					}
+					else
+					{
+						//collide left
+						stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1));
+
+						//collide right
+						stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1));
+					}
+				}
+				else
+				{
+					if(node1_is_leaf)
+					{
+						//collide left
+						stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1);
+						//collide right
+						stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1);
+					}
+					else
+					{
+						GUINT left0 = m_boxset0->getLeftNodeIndex(node0);
+						GUINT right0 = m_boxset0->getRightNodeIndex(node0);
+						GUINT left1 = m_boxset1->getLeftNodeIndex(node1);
+						GUINT right1 = m_boxset1->getRightNodeIndex(node1);
+						//collide left
+						stack_collisions.push_pair(left0,left1);
+						//collide right
+						stack_collisions.push_pair(left0,right1);
+						//collide left
+						stack_collisions.push_pair(right0,left1);
+						//collide right
+						stack_collisions.push_pair(right0,right1);
+
+					}// else if node1 is not a leaf
+				}// else if node0 is not a leaf
+
+			}// if(node_collision(node0,node1))
+		}//while(stack_collisions.size())
+	}
+public:
+	void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1,
+		BOX_SET_CLASS1 * boxset2, const btTransform & trans2,
+		gim_pair_set & collision_pairs, bool complete_primitive_tests = true)
+	{
+		m_collision_pairs = &collision_pairs;
+		m_boxset0 = boxset1;
+		m_boxset1 = boxset2;
+
+		trans_cache_1to0.calc_from_homogenic(trans1,trans2);
+
+		trans_cache_0to1 =  trans2.inverse();
+		trans_cache_0to1 *= trans1;
+
+
+		if(complete_primitive_tests)
+		{
+			t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh();
+			t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh();
+		}
+		else
+		{
+			t0_is_trimesh = false;
+			t1_is_trimesh = false;
+		}
+
+		find_collision_pairs();
+	}
+};
+
+
+#endif // GIM_BOXPRUNING_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_clip_polygon.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_clip_polygon.h
new file mode 100644
index 0000000..a91fd3a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_clip_polygon.h
@@ -0,0 +1,210 @@
+#ifndef GIM_CLIP_POLYGON_H_INCLUDED
+#define GIM_CLIP_POLYGON_H_INCLUDED
+
+/*! \file gim_tri_collision.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+//! This function calcs the distance from a 3D plane
+class DISTANCE_PLANE_3D_FUNC
+{
+public:
+	template<typename CLASS_POINT,typename CLASS_PLANE>
+	inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point)
+	{
+		return DISTANCE_PLANE_POINT(plane, point);
+	}
+};
+
+
+
+template<typename CLASS_POINT>
+SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT(
+						const CLASS_POINT & point0,
+						const CLASS_POINT & point1,
+						GREAL dist0,
+						GREAL dist1,
+						CLASS_POINT * clipped,
+						GUINT & clipped_count)
+{
+	GUINT _prevclassif = (dist0>G_EPSILON);
+	GUINT _classif = (dist1>G_EPSILON);
+	if(_classif!=_prevclassif)
+	{
+		GREAL blendfactor = -dist0/(dist1-dist0);
+		VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor);
+		clipped_count++;
+	}
+	if(!_classif)
+	{
+		VEC_COPY(clipped[clipped_count],point1);
+		clipped_count++;
+	}
+}
+
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC(
+						const CLASS_PLANE & plane,
+						const CLASS_POINT * polygon_points,
+						GUINT polygon_point_count,
+						CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
+{
+    GUINT clipped_count = 0;
+
+
+    //clip first point
+	GREAL firstdist = distance_func(plane,polygon_points[0]);;
+	if(!(firstdist>G_EPSILON))
+	{
+		VEC_COPY(clipped[clipped_count],polygon_points[0]);
+		clipped_count++;
+	}
+
+	GREAL olddist = firstdist;
+	for(GUINT _i=1;_i<polygon_point_count;_i++)
+	{		
+		GREAL dist = distance_func(plane,polygon_points[_i]);
+
+		PLANE_CLIP_POLYGON_COLLECT(
+						polygon_points[_i-1],polygon_points[_i],
+						olddist,
+						dist,
+						clipped,
+						clipped_count);
+
+
+		olddist = dist;		
+	}
+
+	//RETURN TO FIRST  point	
+
+	PLANE_CLIP_POLYGON_COLLECT(
+					polygon_points[polygon_point_count-1],polygon_points[0],
+					olddist,
+					firstdist,
+					clipped,
+					clipped_count);
+
+	return clipped_count;
+}
+
+//! Clips a polygon by a plane
+/*!
+*\return The count of the clipped counts
+*/
+template<typename CLASS_POINT,typename CLASS_PLANE, typename DISTANCE_PLANE_FUNC>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC(
+						const CLASS_PLANE & plane,
+						const CLASS_POINT & point0,
+						const CLASS_POINT & point1,
+						const CLASS_POINT & point2,
+						CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func)
+{
+    GUINT clipped_count = 0;
+
+    //clip first point
+	GREAL firstdist = distance_func(plane,point0);;
+	if(!(firstdist>G_EPSILON))
+	{
+		VEC_COPY(clipped[clipped_count],point0);
+		clipped_count++;
+	}
+
+	// point 1
+	GREAL olddist = firstdist;
+	GREAL dist = distance_func(plane,point1);
+
+	PLANE_CLIP_POLYGON_COLLECT(
+					point0,point1,
+					olddist,
+					dist,
+					clipped,
+					clipped_count);
+
+	olddist = dist;
+
+
+	// point 2
+	dist = distance_func(plane,point2);
+
+	PLANE_CLIP_POLYGON_COLLECT(
+					point1,point2,
+					olddist,
+					dist,
+					clipped,
+					clipped_count);
+	olddist = dist;
+
+
+
+	//RETURN TO FIRST  point
+	PLANE_CLIP_POLYGON_COLLECT(
+					point2,point0,
+					olddist,
+					firstdist,
+					clipped,
+					clipped_count);
+
+	return clipped_count;
+}
+
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D(
+						const CLASS_PLANE & plane,
+						const CLASS_POINT * polygon_points,
+						GUINT polygon_point_count,
+						CLASS_POINT * clipped)
+{
+	return PLANE_CLIP_POLYGON_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC());
+}
+
+
+template<typename CLASS_POINT,typename CLASS_PLANE>
+SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D(
+						const CLASS_PLANE & plane,
+						const CLASS_POINT & point0,
+						const CLASS_POINT & point1,
+						const CLASS_POINT & point2,
+						CLASS_POINT * clipped)
+{
+	return PLANE_CLIP_TRIANGLE_GENERIC<CLASS_POINT,CLASS_PLANE>(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC());
+}
+
+
+
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_contact.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_contact.cpp
new file mode 100644
index 0000000..20e41de
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_contact.cpp
@@ -0,0 +1,146 @@
+
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_contact.h"
+
+#define MAX_COINCIDENT 8
+
+void gim_contact_array::merge_contacts(
+	const gim_contact_array & contacts, bool normal_contact_average)
+{
+	clear();
+
+	if(contacts.size()==1)
+	{
+		push_back(contacts.back());
+		return;
+	}
+
+	gim_array<GIM_RSORT_TOKEN> keycontacts(contacts.size());
+	keycontacts.resize(contacts.size(),false);
+
+	//fill key contacts
+
+	GUINT i;
+
+	for (i = 0;i<contacts.size() ;i++ )
+	{
+		keycontacts[i].m_key = contacts[i].calc_key_contact();
+		keycontacts[i].m_value = i;
+	}
+
+	//sort keys
+	gim_heap_sort(keycontacts.pointer(),keycontacts.size(),GIM_RSORT_TOKEN_COMPARATOR());
+
+	// Merge contacts
+
+	GUINT coincident_count=0;
+	btVector3 coincident_normals[MAX_COINCIDENT];
+
+	GUINT last_key = keycontacts[0].m_key;
+	GUINT key = 0;
+
+	push_back(contacts[keycontacts[0].m_value]);
+	GIM_CONTACT * pcontact = &back();
+
+
+
+	for( i=1;i<keycontacts.size();i++)
+	{
+	    key = keycontacts[i].m_key;
+		const GIM_CONTACT * scontact = &contacts[keycontacts[i].m_value];
+
+		if(last_key ==  key)//same points
+		{
+			//merge contact
+			if(pcontact->m_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//)
+			{
+				*pcontact = *scontact;
+                coincident_count = 0;
+			}
+			else if(normal_contact_average)
+			{
+				if(btFabs(pcontact->m_depth - scontact->m_depth)<CONTACT_DIFF_EPSILON)
+                {
+                    if(coincident_count<MAX_COINCIDENT)
+                    {
+                    	coincident_normals[coincident_count] = scontact->m_normal;
+                        coincident_count++;
+                    }
+                }
+			}
+		}
+		else
+		{//add new contact
+
+		    if(normal_contact_average && coincident_count>0)
+		    {
+		    	pcontact->interpolate_normals(coincident_normals,coincident_count);
+		        coincident_count = 0;
+		    }
+
+		    push_back(*scontact);
+		    pcontact = &back();
+        }
+		last_key = key;
+	}
+}
+
+void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts)
+{
+	clear();
+
+	if(contacts.size()==1)
+	{
+		push_back(contacts.back());
+		return;
+	}
+
+	GIM_CONTACT average_contact = contacts.back();
+
+	for (GUINT i=1;i<contacts.size() ;i++ )
+	{
+		average_contact.m_point += contacts[i].m_point;
+		average_contact.m_normal += contacts[i].m_normal * contacts[i].m_depth;
+	}
+
+	//divide
+	GREAL divide_average = 1.0f/((GREAL)contacts.size());
+
+	average_contact.m_point *= divide_average;
+
+	average_contact.m_normal *= divide_average;
+
+	average_contact.m_depth = average_contact.m_normal.length();
+
+	average_contact.m_normal /= average_contact.m_depth;
+
+}
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_contact.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_contact.h
new file mode 100644
index 0000000..ad3e122
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_contact.h
@@ -0,0 +1,164 @@
+#ifndef GIM_CONTACT_H_INCLUDED
+#define GIM_CONTACT_H_INCLUDED
+
+/*! \file gim_contact.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+#include "gim_geometry.h"
+#include "gim_radixsort.h"
+#include "gim_array.h"
+
+
+/**
+Configuration var for applying interpolation of  contact normals
+*/
+#define NORMAL_CONTACT_AVERAGE 1
+#define CONTACT_DIFF_EPSILON 0.00001f
+
+/// Structure for collision results
+///Functions for managing and sorting contacts resulting from a collision query.
+///Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST
+///After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY
+///Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts
+class GIM_CONTACT
+{
+public:
+    btVector3 m_point;
+    btVector3 m_normal;
+    GREAL m_depth;//Positive value indicates interpenetration
+    GREAL m_distance;//Padding not for use
+    GUINT m_feature1;//Face number
+    GUINT m_feature2;//Face number
+public:
+    GIM_CONTACT()
+    {
+    }
+
+    GIM_CONTACT(const GIM_CONTACT & contact):
+				m_point(contact.m_point),
+				m_normal(contact.m_normal),
+				m_depth(contact.m_depth),
+				m_feature1(contact.m_feature1),
+				m_feature2(contact.m_feature2)
+    {
+    	m_point = contact.m_point;
+    	m_normal = contact.m_normal;
+    	m_depth = contact.m_depth;
+    	m_feature1 = contact.m_feature1;
+    	m_feature2 = contact.m_feature2;
+    }
+
+    GIM_CONTACT(const btVector3 &point,const btVector3 & normal,
+    	 			GREAL depth, GUINT feature1, GUINT feature2):
+				m_point(point),
+				m_normal(normal),
+				m_depth(depth),
+				m_feature1(feature1),
+				m_feature2(feature2)
+    {
+    }
+
+	//! Calcs key for coord classification
+    SIMD_FORCE_INLINE GUINT calc_key_contact() const
+    {
+    	GINT _coords[] = {
+    		(GINT)(m_point[0]*1000.0f+1.0f),
+    		(GINT)(m_point[1]*1333.0f),
+    		(GINT)(m_point[2]*2133.0f+3.0f)};
+		GUINT _hash=0;
+		GUINT *_uitmp = (GUINT *)(&_coords[0]);
+		_hash = *_uitmp;
+		_uitmp++;
+		_hash += (*_uitmp)<<4;
+		_uitmp++;
+		_hash += (*_uitmp)<<8;
+		return _hash;
+    }
+
+    SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,GUINT normal_count)
+    {
+    	btVector3 vec_sum(m_normal);
+		for(GUINT i=0;i<normal_count;i++)
+		{
+			vec_sum += normals[i];
+		}
+
+		GREAL vec_sum_len = vec_sum.length2();
+		if(vec_sum_len <CONTACT_DIFF_EPSILON) return;
+
+		GIM_INV_SQRT(vec_sum_len,vec_sum_len); // 1/sqrt(vec_sum_len)
+
+		m_normal = vec_sum*vec_sum_len;
+    }
+
+};
+
+
+class gim_contact_array:public gim_array<GIM_CONTACT>
+{
+public:
+	gim_contact_array():gim_array<GIM_CONTACT>(64)
+	{
+	}
+
+	SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal,
+    	 			GREAL depth, GUINT feature1, GUINT feature2)
+	{
+		push_back_mem();
+		GIM_CONTACT & newele = back();
+		newele.m_point = point;
+		newele.m_normal = normal;
+		newele.m_depth = depth;
+		newele.m_feature1 = feature1;
+		newele.m_feature2 = feature2;
+	}
+
+	SIMD_FORCE_INLINE void push_triangle_contacts(
+		const GIM_TRIANGLE_CONTACT_DATA & tricontact,
+		GUINT feature1,GUINT feature2)
+	{
+		for(GUINT i = 0;i<tricontact.m_point_count ;i++ )
+		{
+			push_back_mem();
+			GIM_CONTACT & newele = back();
+			newele.m_point = tricontact.m_points[i];
+			newele.m_normal = tricontact.m_separating_normal;
+			newele.m_depth = tricontact.m_penetration_depth;
+			newele.m_feature1 = feature1;
+			newele.m_feature2 = feature2;
+		}
+	}
+
+	void merge_contacts(const gim_contact_array & contacts, bool normal_contact_average = true);
+	void merge_contacts_unique(const gim_contact_array & contacts);
+};
+
+#endif // GIM_CONTACT_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_geom_types.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_geom_types.h
new file mode 100644
index 0000000..2fb1e3f
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_geom_types.h
@@ -0,0 +1,97 @@
+#ifndef GIM_GEOM_TYPES_H_INCLUDED
+#define GIM_GEOM_TYPES_H_INCLUDED
+
+/*! \file gim_geom_types.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_math.h"
+
+
+
+//! Short Integer vector 2D
+typedef GSHORT vec2s[2];
+//! Integer vector 3D
+typedef GSHORT vec3s[3];
+//! Integer vector 4D
+typedef GSHORT vec4s[4];
+
+//! Short Integer vector 2D
+typedef GUSHORT vec2us[2];
+//! Integer vector 3D
+typedef GUSHORT vec3us[3];
+//! Integer vector 4D
+typedef GUSHORT vec4us[4];
+
+//! Integer vector 2D
+typedef GINT vec2i[2];
+//! Integer vector 3D
+typedef GINT vec3i[3];
+//! Integer vector 4D
+typedef GINT vec4i[4];
+
+//! Unsigned Integer vector 2D
+typedef GUINT vec2ui[2];
+//! Unsigned Integer vector 3D
+typedef GUINT vec3ui[3];
+//! Unsigned Integer vector 4D
+typedef GUINT vec4ui[4];
+
+//! Float vector 2D
+typedef GREAL vec2f[2];
+//! Float vector 3D
+typedef GREAL vec3f[3];
+//! Float vector 4D
+typedef GREAL vec4f[4];
+
+//! Double vector 2D
+typedef GREAL2 vec2d[2];
+//! Float vector 3D
+typedef GREAL2 vec3d[3];
+//! Float vector 4D
+typedef GREAL2 vec4d[4];
+
+//! Matrix 2D, row ordered
+typedef GREAL mat2f[2][2];
+//! Matrix 3D, row ordered
+typedef GREAL mat3f[3][3];
+//! Matrix 4D, row ordered
+typedef GREAL mat4f[4][4];
+
+//! Quaternion
+typedef GREAL quatf[4];
+
+//typedef struct _aabb3f aabb3f;
+
+
+
+#endif // GIM_GEOM_TYPES_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_geometry.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_geometry.h
new file mode 100644
index 0000000..6cc4167
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_geometry.h
@@ -0,0 +1,42 @@
+#ifndef GIM_GEOMETRY_H_INCLUDED
+#define GIM_GEOMETRY_H_INCLUDED
+
+/*! \file gim_geometry.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+///Additional Headers for Collision
+#include "gim_basic_geometry_operations.h"
+#include "gim_clip_polygon.h"
+#include "gim_box_collision.h"
+#include "gim_tri_collision.h"
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_hash_table.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_hash_table.h
new file mode 100644
index 0000000..93c66f8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_hash_table.h
@@ -0,0 +1,902 @@
+#ifndef GIM_HASH_TABLE_H_INCLUDED
+#define GIM_HASH_TABLE_H_INCLUDED
+/*! \file gim_trimesh_data.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_radixsort.h"
+
+
+#define GIM_INVALID_HASH 0xffffffff //!< A very very high value
+#define GIM_DEFAULT_HASH_TABLE_SIZE 380
+#define GIM_DEFAULT_HASH_TABLE_NODE_SIZE 4
+#define GIM_HASH_TABLE_GROW_FACTOR 2
+
+#define GIM_MIN_RADIX_SORT_SIZE 860 //!< calibrated on a PIII
+
+template<typename T>
+struct GIM_HASH_TABLE_NODE
+{
+    GUINT m_key;
+    T m_data;
+    GIM_HASH_TABLE_NODE()
+    {
+    }
+
+    GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value)
+    {
+        m_key = value.m_key;
+        m_data = value.m_data;
+    }
+
+    GIM_HASH_TABLE_NODE(GUINT key, const T & data)
+    {
+        m_key = key;
+        m_data = data;
+    }
+
+    bool operator <(const GIM_HASH_TABLE_NODE<T> & other) const
+	{
+		///inverse order, further objects are first
+		if(m_key <  other.m_key) return true;
+		return false;
+	}
+
+	bool operator >(const GIM_HASH_TABLE_NODE<T> & other) const
+	{
+		///inverse order, further objects are first
+		if(m_key >  other.m_key) return true;
+		return false;
+	}
+
+	bool operator ==(const GIM_HASH_TABLE_NODE<T> & other) const
+	{
+		///inverse order, further objects are first
+		if(m_key ==  other.m_key) return true;
+		return false;
+	}
+};
+
+///Macro for getting the key
+class GIM_HASH_NODE_GET_KEY
+{
+public:
+	template<class T>
+	inline GUINT operator()( const T& a)
+	{
+		return a.m_key;
+	}
+};
+
+
+
+///Macro for comparing the key and the element
+class GIM_HASH_NODE_CMP_KEY_MACRO
+{
+public:
+	template<class T>
+	inline int operator() ( const T& a, GUINT key)
+	{
+		return ((int)(a.m_key - key));
+	}
+};
+
+///Macro for comparing Hash nodes
+class GIM_HASH_NODE_CMP_MACRO
+{
+public:
+	template<class T>
+	inline int operator() ( const T& a, const T& b )
+	{
+		return ((int)(a.m_key - b.m_key));
+	}
+};
+
+
+
+
+
+//! Sorting for hash table
+/*!
+switch automatically between quicksort and radixsort
+*/
+template<typename T>
+void gim_sort_hash_node_array(T * array, GUINT array_count)
+{
+    if(array_count<GIM_MIN_RADIX_SORT_SIZE)
+    {
+    	gim_heap_sort(array,array_count,GIM_HASH_NODE_CMP_MACRO());
+    }
+    else
+    {
+    	memcopy_elements_func cmpfunc;
+    	gim_radix_sort(array,array_count,GIM_HASH_NODE_GET_KEY(),cmpfunc);
+    }
+}
+
+
+
+
+
+
+// Note: assumes long is at least 32 bits.
+#define GIM_NUM_PRIME 28
+
+static const GUINT gim_prime_list[GIM_NUM_PRIME] =
+{
+  53ul,         97ul,         193ul,       389ul,       769ul,
+  1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
+  49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
+  1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
+  50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,
+  1610612741ul, 3221225473ul, 4294967291ul
+};
+
+inline GUINT gim_next_prime(GUINT number)
+{
+    //Find nearest upper prime
+    GUINT result_ind = 0;
+    gim_binary_search(gim_prime_list,0,(GIM_NUM_PRIME-2),number,result_ind);
+
+    // inv: result_ind < 28
+    return gim_prime_list[result_ind];
+}
+
+
+
+//! A compact hash table implementation
+/*!
+A memory aligned compact hash table that coud be treated as an array.
+It could be a simple sorted array without the overhead of the hash key bucked, or could
+be a formely hash table with an array of keys.
+You can use switch_to_hashtable() and switch_to_sorted_array for saving space or increase speed.
+</br>
+
+<ul>
+<li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
+When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
+<li> If node_size != 0, then this container becomes a hash table for ever
+</ul>
+
+*/
+template<class T>
+class gim_hash_table
+{
+protected:
+    typedef GIM_HASH_TABLE_NODE<T> _node_type;
+
+    //!The nodes
+    //array< _node_type, SuperAllocator<_node_type> > m_nodes;
+    gim_array< _node_type > m_nodes;
+    //SuperBufferedArray< _node_type > m_nodes;
+    bool m_sorted;
+
+    ///Hash table data management. The hash table has the indices to the corresponding m_nodes array
+    GUINT * m_hash_table;//!<
+    GUINT m_table_size;//!<
+    GUINT m_node_size;//!<
+    GUINT m_min_hash_table_size;
+
+
+
+    //! Returns the cell index
+    inline GUINT _find_cell(GUINT hashkey)
+    {
+        _node_type * nodesptr = m_nodes.pointer();
+        GUINT start_index = (hashkey%m_table_size)*m_node_size;
+        GUINT end_index = start_index + m_node_size;
+
+        while(start_index<end_index)
+        {
+            GUINT value = m_hash_table[start_index];
+            if(value != GIM_INVALID_HASH)
+            {
+                if(nodesptr[value].m_key == hashkey) return start_index;
+            }
+            start_index++;
+        }
+        return GIM_INVALID_HASH;
+    }
+
+    //! Find the avaliable cell for the hashkey, and return an existing cell if it has the same hash key
+    inline GUINT _find_avaliable_cell(GUINT hashkey)
+    {
+        _node_type * nodesptr = m_nodes.pointer();
+        GUINT avaliable_index = GIM_INVALID_HASH;
+        GUINT start_index = (hashkey%m_table_size)*m_node_size;
+        GUINT end_index = start_index + m_node_size;
+
+        while(start_index<end_index)
+        {
+            GUINT value = m_hash_table[start_index];
+            if(value == GIM_INVALID_HASH)
+            {
+                if(avaliable_index==GIM_INVALID_HASH)
+                {
+                    avaliable_index = start_index;
+                }
+            }
+            else if(nodesptr[value].m_key == hashkey)
+            {
+                return start_index;
+            }
+            start_index++;
+        }
+        return avaliable_index;
+    }
+
+
+
+    //! reserves the memory for the hash table.
+    /*!
+    \pre hash table must be empty
+    \post reserves the memory for the hash table, an initializes all elements to GIM_INVALID_HASH.
+    */
+    inline void _reserve_table_memory(GUINT newtablesize)
+    {
+        if(newtablesize==0) return;
+        if(m_node_size==0) return;
+
+        //Get a Prime size
+
+        m_table_size = gim_next_prime(newtablesize);
+
+        GUINT datasize = m_table_size*m_node_size;
+        //Alloc the data buffer
+        m_hash_table =  (GUINT *)gim_alloc(datasize*sizeof(GUINT));
+    }
+
+    inline void _invalidate_keys()
+    {
+        GUINT datasize = m_table_size*m_node_size;
+        for(GUINT i=0;i<datasize;i++)
+        {
+            m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
+        }
+    }
+
+    //! Clear all memory for the hash table
+    inline void _clear_table_memory()
+    {
+        if(m_hash_table==NULL) return;
+        gim_free(m_hash_table);
+        m_hash_table = NULL;
+        m_table_size = 0;
+    }
+
+    //! Invalidates the keys (Assigning GIM_INVALID_HASH to all) Reorders the hash keys
+    inline void _rehash()
+    {
+        _invalidate_keys();
+
+        _node_type * nodesptr = m_nodes.pointer();
+        for(GUINT i=0;i<(GUINT)m_nodes.size();i++)
+        {
+            GUINT nodekey = nodesptr[i].m_key;
+            if(nodekey != GIM_INVALID_HASH)
+            {
+                //Search for the avaliable cell in buffer
+                GUINT index = _find_avaliable_cell(nodekey);
+
+
+				if(m_hash_table[index]!=GIM_INVALID_HASH)
+				{//The new index is alreade used... discard this new incomming object, repeated key
+				    btAssert(m_hash_table[index]==nodekey);
+					nodesptr[i].m_key = GIM_INVALID_HASH;
+				}
+				else
+				{
+					//;
+					//Assign the value for alloc
+					m_hash_table[index] = i;
+				}
+            }
+        }
+    }
+
+    //! Resize hash table indices
+    inline void _resize_table(GUINT newsize)
+    {
+        //Clear memory
+        _clear_table_memory();
+        //Alloc the data
+        _reserve_table_memory(newsize);
+        //Invalidate keys and rehash
+        _rehash();
+    }
+
+    //! Destroy hash table memory
+    inline void _destroy()
+    {
+        if(m_hash_table==NULL) return;
+        _clear_table_memory();
+    }
+
+    //! Finds an avaliable hash table cell, and resizes the table if there isn't space
+    inline GUINT _assign_hash_table_cell(GUINT hashkey)
+    {
+        GUINT cell_index = _find_avaliable_cell(hashkey);
+
+        if(cell_index==GIM_INVALID_HASH)
+        {
+            //rehashing
+            _resize_table(m_table_size+1);
+            GUINT cell_index = _find_avaliable_cell(hashkey);
+            btAssert(cell_index!=GIM_INVALID_HASH);
+        }
+        return cell_index;
+    }
+
+    //! erase by index in hash table
+    inline bool _erase_by_index_hash_table(GUINT index)
+    {
+        if(index >= m_nodes.size()) return false;
+        if(m_nodes[index].m_key != GIM_INVALID_HASH)
+        {
+            //Search for the avaliable cell in buffer
+            GUINT cell_index = _find_cell(m_nodes[index].m_key);
+
+            btAssert(cell_index!=GIM_INVALID_HASH);
+            btAssert(m_hash_table[cell_index]==index);
+
+            m_hash_table[cell_index] = GIM_INVALID_HASH;
+        }
+
+        return this->_erase_unsorted(index);
+    }
+
+    //! erase by key in hash table
+    inline bool _erase_hash_table(GUINT hashkey)
+    {
+        if(hashkey == GIM_INVALID_HASH) return false;
+
+        //Search for the avaliable cell in buffer
+        GUINT cell_index = _find_cell(hashkey);
+        if(cell_index ==GIM_INVALID_HASH) return false;
+
+        GUINT index = m_hash_table[cell_index];
+        m_hash_table[cell_index] = GIM_INVALID_HASH;
+
+        return this->_erase_unsorted(index);
+    }
+
+
+
+    //! insert an element in hash table
+    /*!
+    If the element exists, this won't insert the element
+    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+    If so, the element has been inserted at the last position of the array.
+    */
+    inline GUINT _insert_hash_table(GUINT hashkey, const T & value)
+    {
+        if(hashkey==GIM_INVALID_HASH)
+        {
+            //Insert anyway
+            _insert_unsorted(hashkey,value);
+            return GIM_INVALID_HASH;
+        }
+
+        GUINT cell_index = _assign_hash_table_cell(hashkey);
+
+        GUINT value_key = m_hash_table[cell_index];
+
+        if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited
+
+        m_hash_table[cell_index] = m_nodes.size();
+
+        _insert_unsorted(hashkey,value);
+        return GIM_INVALID_HASH;
+    }
+
+    //! insert an element in hash table.
+    /*!
+    If the element exists, this replaces the element.
+    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+    If so, the element has been inserted at the last position of the array.
+    */
+    inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value)
+    {
+        if(hashkey==GIM_INVALID_HASH)
+        {
+            //Insert anyway
+            _insert_unsorted(hashkey,value);
+            return GIM_INVALID_HASH;
+        }
+
+        GUINT cell_index = _assign_hash_table_cell(hashkey);
+
+        GUINT value_key = m_hash_table[cell_index];
+
+        if(value_key!= GIM_INVALID_HASH)
+        {//replaces the existing
+            m_nodes[value_key] = _node_type(hashkey,value);
+            return value_key;// index of the replaced element
+        }
+
+        m_hash_table[cell_index] = m_nodes.size();
+
+        _insert_unsorted(hashkey,value);
+        return GIM_INVALID_HASH;
+
+    }
+
+    
+    ///Sorted array data management. The hash table has the indices to the corresponding m_nodes array
+    inline bool _erase_sorted(GUINT index)
+    {
+        if(index>=(GUINT)m_nodes.size()) return false;
+        m_nodes.erase_sorted(index);
+		if(m_nodes.size()<2) m_sorted = false;
+        return true;
+    }
+
+    //! faster, but unsorted
+    inline bool _erase_unsorted(GUINT index)
+    {
+        if(index>=m_nodes.size()) return false;
+
+        GUINT lastindex = m_nodes.size()-1;
+        if(index<lastindex && m_hash_table!=0)
+        {
+			GUINT hashkey =  m_nodes[lastindex].m_key;
+			if(hashkey!=GIM_INVALID_HASH)
+			{
+				//update the new position of the last element
+				GUINT cell_index = _find_cell(hashkey);
+				btAssert(cell_index!=GIM_INVALID_HASH);
+				//new position of the last element which will be swaped
+				m_hash_table[cell_index] = index;
+			}
+        }
+        m_nodes.erase(index);
+        m_sorted = false;
+        return true;
+    }
+
+    //! Insert in position ordered
+    /*!
+    Also checks if it is needed to transform this container to a hash table, by calling check_for_switching_to_hashtable
+    */
+    inline void _insert_in_pos(GUINT hashkey, const T & value, GUINT pos)
+    {
+        m_nodes.insert(_node_type(hashkey,value),pos);
+        this->check_for_switching_to_hashtable();
+    }
+
+    //! Insert an element in an ordered array
+    inline GUINT _insert_sorted(GUINT hashkey, const T & value)
+    {
+        if(hashkey==GIM_INVALID_HASH || size()==0)
+        {
+            m_nodes.push_back(_node_type(hashkey,value));
+            return GIM_INVALID_HASH;
+        }
+        //Insert at last position
+        //Sort element
+
+
+        GUINT result_ind=0;
+        GUINT last_index = m_nodes.size()-1;
+        _node_type * ptr = m_nodes.pointer();
+
+        bool found = gim_binary_search_ex(
+        	ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
+
+
+        //Insert before found index
+        if(found)
+        {
+            return result_ind;
+        }
+        else
+        {
+            _insert_in_pos(hashkey, value, result_ind);
+        }
+        return GIM_INVALID_HASH;
+    }
+
+    inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value)
+    {
+        if(hashkey==GIM_INVALID_HASH || size()==0)
+        {
+            m_nodes.push_back(_node_type(hashkey,value));
+            return GIM_INVALID_HASH;
+        }
+        //Insert at last position
+        //Sort element
+        GUINT result_ind;
+        GUINT last_index = m_nodes.size()-1;
+        _node_type * ptr = m_nodes.pointer();
+
+        bool found = gim_binary_search_ex(
+        	ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
+
+        //Insert before found index
+        if(found)
+        {
+            m_nodes[result_ind] = _node_type(hashkey,value);
+        }
+        else
+        {
+            _insert_in_pos(hashkey, value, result_ind);
+        }
+        return result_ind;
+    }
+
+    //! Fast insertion in m_nodes array
+    inline GUINT  _insert_unsorted(GUINT hashkey, const T & value)
+    {
+        m_nodes.push_back(_node_type(hashkey,value));
+        m_sorted = false;
+        return GIM_INVALID_HASH;
+    }
+
+    
+
+public:
+
+    /*!
+        <li> if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes.
+        When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable.
+        <li> If node_size != 0, then this container becomes a hash table for ever
+        </ul>
+    */
+    gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE,
+                     GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE,
+                     GUINT min_hash_table_size = GIM_INVALID_HASH)
+    {
+        m_hash_table = NULL;
+        m_table_size = 0;
+        m_sorted = false;
+        m_node_size = node_size;
+        m_min_hash_table_size = min_hash_table_size;
+
+        if(m_node_size!=0)
+        {
+            if(reserve_size!=0)
+            {
+                m_nodes.reserve(reserve_size);
+                _reserve_table_memory(reserve_size);
+                _invalidate_keys();
+            }
+            else
+            {
+                m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE);
+                _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE);
+                _invalidate_keys();
+            }
+        }
+        else if(reserve_size!=0)
+        {
+            m_nodes.reserve(reserve_size);
+        }
+
+    }
+
+    ~gim_hash_table()
+    {
+        _destroy();
+    }
+
+    inline bool is_hash_table()
+    {
+        if(m_hash_table) return true;
+        return false;
+    }
+
+    inline bool is_sorted()
+    {
+        if(size()<2) return true;
+        return m_sorted;
+    }
+
+    bool sort()
+    {
+        if(is_sorted()) return true;
+        if(m_nodes.size()<2) return false;
+
+
+        _node_type * ptr = m_nodes.pointer();
+        GUINT siz = m_nodes.size();
+        gim_sort_hash_node_array(ptr,siz);
+        m_sorted=true;
+
+
+
+        if(m_hash_table)
+        {
+            _rehash();
+        }
+        return true;
+    }
+
+    bool switch_to_hashtable()
+    {
+        if(m_hash_table) return false;
+        if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+        if(m_nodes.size()<GIM_DEFAULT_HASH_TABLE_SIZE)
+        {
+            _resize_table(GIM_DEFAULT_HASH_TABLE_SIZE);
+        }
+        else
+        {
+            _resize_table(m_nodes.size()+1);
+        }
+
+        return true;
+    }
+
+    bool switch_to_sorted_array()
+    {
+        if(m_hash_table==NULL) return true;
+        _clear_table_memory();
+        return sort();
+    }
+
+    //!If the container reaches the
+    bool check_for_switching_to_hashtable()
+    {
+        if(this->m_hash_table) return true;
+
+        if(!(m_nodes.size()< m_min_hash_table_size))
+        {
+            if(m_node_size == 0)
+            {
+                m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE;
+            }
+
+            _resize_table(m_nodes.size()+1);
+            return true;
+        }
+        return false;
+    }
+
+    inline void set_sorted(bool value)
+    {
+    	m_sorted = value;
+    }
+
+    //! Retrieves the amount of keys.
+    inline GUINT size() const
+    {
+        return m_nodes.size();
+    }
+
+    //! Retrieves the hash key.
+    inline GUINT get_key(GUINT index) const
+    {
+        return m_nodes[index].m_key;
+    }
+
+    //! Retrieves the value by index
+    /*!
+    */
+    inline T * get_value_by_index(GUINT index)
+    {
+        return &m_nodes[index].m_data;
+    }
+
+    inline const T& operator[](GUINT index) const
+    {
+        return m_nodes[index].m_data;
+    }
+
+    inline T& operator[](GUINT index)
+    {
+        return m_nodes[index].m_data;
+    }
+
+    //! Finds the index of the element with the key
+    /*!
+    \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted
+    If so, the element has been inserted at the last position of the array.
+    */
+    inline GUINT find(GUINT hashkey)
+    {
+        if(m_hash_table)
+        {
+            GUINT cell_index = _find_cell(hashkey);
+            if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH;
+            return m_hash_table[cell_index];
+        }
+		GUINT last_index = m_nodes.size();
+        if(last_index<2)
+        {
+			if(last_index==0) return GIM_INVALID_HASH;
+            if(m_nodes[0].m_key == hashkey) return 0;
+            return GIM_INVALID_HASH;
+        }
+        else if(m_sorted)
+        {
+            //Binary search
+            GUINT result_ind = 0;
+			last_index--;
+            _node_type *  ptr =  m_nodes.pointer();
+
+            bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO());
+
+
+            if(found) return result_ind;
+        }
+        return GIM_INVALID_HASH;
+    }
+
+    //! Retrieves the value associated with the index
+    /*!
+    \return the found element, or null
+    */
+    inline T * get_value(GUINT hashkey)
+    {
+        GUINT index = find(hashkey);
+        if(index == GIM_INVALID_HASH) return NULL;
+        return &m_nodes[index].m_data;
+    }
+
+
+    /*!
+    */
+    inline bool erase_by_index(GUINT index)
+    {
+        if(index > m_nodes.size()) return false;
+
+        if(m_hash_table == NULL)
+        {
+            if(is_sorted())
+            {
+                return this->_erase_sorted(index);
+            }
+            else
+            {
+                return this->_erase_unsorted(index);
+            }
+        }
+        else
+        {
+            return this->_erase_by_index_hash_table(index);
+        }
+        return false;
+    }
+
+
+
+    inline bool erase_by_index_unsorted(GUINT index)
+    {
+        if(index > m_nodes.size()) return false;
+
+        if(m_hash_table == NULL)
+        {
+            return this->_erase_unsorted(index);
+        }
+        else
+        {
+            return this->_erase_by_index_hash_table(index);
+        }
+        return false;
+    }
+
+
+
+    /*!
+
+    */
+    inline bool erase_by_key(GUINT hashkey)
+    {
+        if(size()==0) return false;
+
+        if(m_hash_table)
+        {
+            return this->_erase_hash_table(hashkey);
+        }
+        //Binary search
+
+        if(is_sorted()==false) return false;
+
+        GUINT result_ind = find(hashkey);
+        if(result_ind!= GIM_INVALID_HASH)
+        {
+            return this->_erase_sorted(result_ind);
+        }
+        return false;
+    }
+
+    void clear()
+    {
+        m_nodes.clear();
+
+        if(m_hash_table==NULL) return;
+        GUINT datasize = m_table_size*m_node_size;
+        //Initialize the hashkeys.
+        GUINT i;
+        for(i=0;i<datasize;i++)
+        {
+            m_hash_table[i] = GIM_INVALID_HASH;// invalidate keys
+        }
+		m_sorted = false;
+    }
+
+    //! Insert an element into the hash
+    /*!
+    \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
+    of the existing element.
+    */
+    inline GUINT insert(GUINT hashkey, const T & element)
+    {
+        if(m_hash_table)
+        {
+            return this->_insert_hash_table(hashkey,element);
+        }
+        if(this->is_sorted())
+        {
+            return this->_insert_sorted(hashkey,element);
+        }
+        return this->_insert_unsorted(hashkey,element);
+    }
+
+    //! Insert an element into the hash, and could overrite an existing object with the same hash.
+    /*!
+    \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position
+    of the replaced element.
+    */
+    inline GUINT insert_override(GUINT hashkey, const T & element)
+    {
+        if(m_hash_table)
+        {
+            return this->_insert_hash_table_replace(hashkey,element);
+        }
+        if(this->is_sorted())
+        {
+            return this->_insert_sorted_replace(hashkey,element);
+        }
+        this->_insert_unsorted(hashkey,element);
+        return m_nodes.size();
+    }
+
+
+
+    //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted
+    /*!
+    */
+    inline GUINT insert_unsorted(GUINT hashkey,const T & element)
+    {
+        if(m_hash_table)
+        {
+            return this->_insert_hash_table(hashkey,element);
+        }
+        return this->_insert_unsorted(hashkey,element);
+    }
+
+
+};
+
+
+
+#endif // GIM_CONTAINERS_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_linear_math.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_linear_math.h
new file mode 100644
index 0000000..0247d4e
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_linear_math.h
@@ -0,0 +1,1573 @@
+#ifndef GIM_LINEAR_H_INCLUDED
+#define GIM_LINEAR_H_INCLUDED
+
+/*! \file gim_linear_math.h
+*\author Francisco Len N�jera
+Type Independant Vector and matrix operations.
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_math.h"
+#include "gim_geom_types.h"
+
+
+
+
+//! Zero out a 2D vector
+#define VEC_ZERO_2(a)				\
+{						\
+   (a)[0] = (a)[1] = 0.0f;			\
+}\
+
+
+//! Zero out a 3D vector
+#define VEC_ZERO(a)				\
+{						\
+   (a)[0] = (a)[1] = (a)[2] = 0.0f;		\
+}\
+
+
+/// Zero out a 4D vector
+#define VEC_ZERO_4(a)				\
+{						\
+   (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f;	\
+}\
+
+
+/// Vector copy
+#define VEC_COPY_2(b,a)				\
+{						\
+   (b)[0] = (a)[0];				\
+   (b)[1] = (a)[1];				\
+}\
+
+
+/// Copy 3D vector
+#define VEC_COPY(b,a)				\
+{						\
+   (b)[0] = (a)[0];				\
+   (b)[1] = (a)[1];				\
+   (b)[2] = (a)[2];				\
+}\
+
+
+/// Copy 4D vector
+#define VEC_COPY_4(b,a)				\
+{						\
+   (b)[0] = (a)[0];				\
+   (b)[1] = (a)[1];				\
+   (b)[2] = (a)[2];				\
+   (b)[3] = (a)[3];				\
+}\
+
+/// VECTOR SWAP
+#define VEC_SWAP(b,a)				\
+{  \
+    GIM_SWAP_NUMBERS((b)[0],(a)[0]);\
+    GIM_SWAP_NUMBERS((b)[1],(a)[1]);\
+    GIM_SWAP_NUMBERS((b)[2],(a)[2]);\
+}\
+
+/// Vector difference
+#define VEC_DIFF_2(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] - (v1)[0];		\
+   (v21)[1] = (v2)[1] - (v1)[1];		\
+}\
+
+
+/// Vector difference
+#define VEC_DIFF(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] - (v1)[0];		\
+   (v21)[1] = (v2)[1] - (v1)[1];		\
+   (v21)[2] = (v2)[2] - (v1)[2];		\
+}\
+
+
+/// Vector difference
+#define VEC_DIFF_4(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] - (v1)[0];		\
+   (v21)[1] = (v2)[1] - (v1)[1];		\
+   (v21)[2] = (v2)[2] - (v1)[2];		\
+   (v21)[3] = (v2)[3] - (v1)[3];		\
+}\
+
+
+/// Vector sum
+#define VEC_SUM_2(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] + (v1)[0];		\
+   (v21)[1] = (v2)[1] + (v1)[1];		\
+}\
+
+
+/// Vector sum
+#define VEC_SUM(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] + (v1)[0];		\
+   (v21)[1] = (v2)[1] + (v1)[1];		\
+   (v21)[2] = (v2)[2] + (v1)[2];		\
+}\
+
+
+/// Vector sum
+#define VEC_SUM_4(v21,v2,v1)			\
+{						\
+   (v21)[0] = (v2)[0] + (v1)[0];		\
+   (v21)[1] = (v2)[1] + (v1)[1];		\
+   (v21)[2] = (v2)[2] + (v1)[2];		\
+   (v21)[3] = (v2)[3] + (v1)[3];		\
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE_2(c,a,b)			\
+{						\
+   (c)[0] = (a)*(b)[0];				\
+   (c)[1] = (a)*(b)[1];				\
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE(c,a,b)			\
+{						\
+   (c)[0] = (a)*(b)[0];				\
+   (c)[1] = (a)*(b)[1];				\
+   (c)[2] = (a)*(b)[2];				\
+}\
+
+
+/// scalar times vector
+#define VEC_SCALE_4(c,a,b)			\
+{						\
+   (c)[0] = (a)*(b)[0];				\
+   (c)[1] = (a)*(b)[1];				\
+   (c)[2] = (a)*(b)[2];				\
+   (c)[3] = (a)*(b)[3];				\
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM_2(c,a,b)			\
+{						\
+   (c)[0] += (a)*(b)[0];			\
+   (c)[1] += (a)*(b)[1];			\
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM(c,a,b)			\
+{						\
+   (c)[0] += (a)*(b)[0];			\
+   (c)[1] += (a)*(b)[1];			\
+   (c)[2] += (a)*(b)[2];			\
+}\
+
+
+/// accumulate scaled vector
+#define VEC_ACCUM_4(c,a,b)			\
+{						\
+   (c)[0] += (a)*(b)[0];			\
+   (c)[1] += (a)*(b)[1];			\
+   (c)[2] += (a)*(b)[2];			\
+   (c)[3] += (a)*(b)[3];			\
+}\
+
+
+/// Vector dot product
+#define VEC_DOT_2(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1])
+
+
+/// Vector dot product
+#define VEC_DOT(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2])
+
+/// Vector dot product
+#define VEC_DOT_4(a,b)	((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3])
+
+/// vector impact parameter (squared)
+#define VEC_IMPACT_SQ(bsq,direction,position) {\
+   GREAL _llel_ = VEC_DOT(direction, position);\
+   bsq = VEC_DOT(position, position) - _llel_*_llel_;\
+}\
+
+
+/// vector impact parameter
+#define VEC_IMPACT(bsq,direction,position)	{\
+   VEC_IMPACT_SQ(bsq,direction,position);		\
+   GIM_SQRT(bsq,bsq);					\
+}\
+
+/// Vector length
+#define VEC_LENGTH_2(a,l)\
+{\
+    GREAL _pp = VEC_DOT_2(a,a);\
+    GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_LENGTH(a,l)\
+{\
+    GREAL _pp = VEC_DOT(a,a);\
+    GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_LENGTH_4(a,l)\
+{\
+    GREAL _pp = VEC_DOT_4(a,a);\
+    GIM_SQRT(_pp,l);\
+}\
+
+/// Vector inv length
+#define VEC_INV_LENGTH_2(a,l)\
+{\
+    GREAL _pp = VEC_DOT_2(a,a);\
+    GIM_INV_SQRT(_pp,l);\
+}\
+
+
+/// Vector inv length
+#define VEC_INV_LENGTH(a,l)\
+{\
+    GREAL _pp = VEC_DOT(a,a);\
+    GIM_INV_SQRT(_pp,l);\
+}\
+
+
+/// Vector inv length
+#define VEC_INV_LENGTH_4(a,l)\
+{\
+    GREAL _pp = VEC_DOT_4(a,a);\
+    GIM_INV_SQRT(_pp,l);\
+}\
+
+
+
+/// distance between two points
+#define VEC_DISTANCE(_len,_va,_vb) {\
+    vec3f _tmp_;				\
+    VEC_DIFF(_tmp_, _vb, _va);			\
+    VEC_LENGTH(_tmp_,_len);			\
+}\
+
+
+/// Vector length
+#define VEC_CONJUGATE_LENGTH(a,l)\
+{\
+    GREAL _pp = 1.0 - a[0]*a[0] - a[1]*a[1] - a[2]*a[2];\
+    GIM_SQRT(_pp,l);\
+}\
+
+
+/// Vector length
+#define VEC_NORMALIZE(a) {	\
+    GREAL len;\
+    VEC_INV_LENGTH(a,len); \
+    if(len<G_REAL_INFINITY)\
+    {\
+        a[0] *= len;				\
+        a[1] *= len;				\
+        a[2] *= len;				\
+    }						\
+}\
+
+/// Set Vector size
+#define VEC_RENORMALIZE(a,newlen) {	\
+    GREAL len;\
+    VEC_INV_LENGTH(a,len); \
+    if(len<G_REAL_INFINITY)\
+    {\
+        len *= newlen;\
+        a[0] *= len;				\
+        a[1] *= len;				\
+        a[2] *= len;				\
+    }						\
+}\
+
+/// Vector cross
+#define VEC_CROSS(c,a,b)		\
+{						\
+   c[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1];	\
+   c[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2];	\
+   c[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0];	\
+}\
+
+
+/*! Vector perp -- assumes that n is of unit length
+ * accepts vector v, subtracts out any component parallel to n */
+#define VEC_PERPENDICULAR(vp,v,n)			\
+{						\
+   GREAL dot = VEC_DOT(v, n);			\
+   vp[0] = (v)[0] - dot*(n)[0];		\
+   vp[1] = (v)[1] - dot*(n)[1];		\
+   vp[2] = (v)[2] - dot*(n)[2];		\
+}\
+
+
+/*! Vector parallel -- assumes that n is of unit length */
+#define VEC_PARALLEL(vp,v,n)			\
+{						\
+   GREAL dot = VEC_DOT(v, n);			\
+   vp[0] = (dot) * (n)[0];			\
+   vp[1] = (dot) * (n)[1];			\
+   vp[2] = (dot) * (n)[2];			\
+}\
+
+/*! Same as Vector parallel --  n can have any length
+ * accepts vector v, subtracts out any component perpendicular to n */
+#define VEC_PROJECT(vp,v,n)			\
+{ \
+	GREAL scalar = VEC_DOT(v, n);			\
+	scalar/= VEC_DOT(n, n); \
+	vp[0] = (scalar) * (n)[0];			\
+    vp[1] = (scalar) * (n)[1];			\
+    vp[2] = (scalar) * (n)[2];			\
+}\
+
+
+/*! accepts vector v*/
+#define VEC_UNPROJECT(vp,v,n)			\
+{ \
+	GREAL scalar = VEC_DOT(v, n);			\
+	scalar = VEC_DOT(n, n)/scalar; \
+	vp[0] = (scalar) * (n)[0];			\
+    vp[1] = (scalar) * (n)[1];			\
+    vp[2] = (scalar) * (n)[2];			\
+}\
+
+
+/*! Vector reflection -- assumes n is of unit length
+ Takes vector v, reflects it against reflector n, and returns vr */
+#define VEC_REFLECT(vr,v,n)			\
+{						\
+   GREAL dot = VEC_DOT(v, n);			\
+   vr[0] = (v)[0] - 2.0 * (dot) * (n)[0];	\
+   vr[1] = (v)[1] - 2.0 * (dot) * (n)[1];	\
+   vr[2] = (v)[2] - 2.0 * (dot) * (n)[2];	\
+}\
+
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with two scalars */
+#define VEC_BLEND_AB(vr,sa,a,sb,b)			\
+{						\
+   vr[0] = (sa) * (a)[0] + (sb) * (b)[0];	\
+   vr[1] = (sa) * (a)[1] + (sb) * (b)[1];	\
+   vr[2] = (sa) * (a)[2] + (sb) * (b)[2];	\
+}\
+
+/*! Vector blending
+Takes two vectors a, b, blends them together with s <=1 */
+#define VEC_BLEND(vr,a,b,s) VEC_BLEND_AB(vr,(1-s),a,s,b)
+
+#define VEC_SET3(a,b,op,c) a[0]=b[0] op c[0]; a[1]=b[1] op c[1]; a[2]=b[2] op c[2];
+
+//! Finds the bigger cartesian coordinate from a vector
+#define VEC_MAYOR_COORD(vec, maxc)\
+{\
+	GREAL A[] = {fabs(vec[0]),fabs(vec[1]),fabs(vec[2])};\
+    maxc =  A[0]>A[1]?(A[0]>A[2]?0:2):(A[1]>A[2]?1:2);\
+}\
+
+//! Finds the 2 smallest cartesian coordinates from a vector
+#define VEC_MINOR_AXES(vec, i0, i1)\
+{\
+	VEC_MAYOR_COORD(vec,i0);\
+	i0 = (i0+1)%3;\
+	i1 = (i0+1)%3;\
+}\
+
+
+
+
+#define VEC_EQUAL(v1,v2) (v1[0]==v2[0]&&v1[1]==v2[1]&&v1[2]==v2[2])
+
+#define VEC_NEAR_EQUAL(v1,v2) (GIM_NEAR_EQUAL(v1[0],v2[0])&&GIM_NEAR_EQUAL(v1[1],v2[1])&&GIM_NEAR_EQUAL(v1[2],v2[2]))
+
+
+/// Vector cross
+#define X_AXIS_CROSS_VEC(dst,src)\
+{					   \
+	dst[0] = 0.0f;     \
+	dst[1] = -src[2];  \
+	dst[2] = src[1];  \
+}\
+
+#define Y_AXIS_CROSS_VEC(dst,src)\
+{					   \
+	dst[0] = src[2];     \
+	dst[1] = 0.0f;  \
+	dst[2] = -src[0];  \
+}\
+
+#define Z_AXIS_CROSS_VEC(dst,src)\
+{					   \
+	dst[0] = -src[1];     \
+	dst[1] = src[0];  \
+	dst[2] = 0.0f;  \
+}\
+
+
+
+
+
+
+/// initialize matrix
+#define IDENTIFY_MATRIX_3X3(m)			\
+{						\
+   m[0][0] = 1.0;				\
+   m[0][1] = 0.0;				\
+   m[0][2] = 0.0;				\
+						\
+   m[1][0] = 0.0;				\
+   m[1][1] = 1.0;				\
+   m[1][2] = 0.0;				\
+						\
+   m[2][0] = 0.0;				\
+   m[2][1] = 0.0;				\
+   m[2][2] = 1.0;				\
+}\
+
+/*! initialize matrix */
+#define IDENTIFY_MATRIX_4X4(m)			\
+{						\
+   m[0][0] = 1.0;				\
+   m[0][1] = 0.0;				\
+   m[0][2] = 0.0;				\
+   m[0][3] = 0.0;				\
+						\
+   m[1][0] = 0.0;				\
+   m[1][1] = 1.0;				\
+   m[1][2] = 0.0;				\
+   m[1][3] = 0.0;				\
+						\
+   m[2][0] = 0.0;				\
+   m[2][1] = 0.0;				\
+   m[2][2] = 1.0;				\
+   m[2][3] = 0.0;				\
+						\
+   m[3][0] = 0.0;				\
+   m[3][1] = 0.0;				\
+   m[3][2] = 0.0;				\
+   m[3][3] = 1.0;				\
+}\
+
+/*! initialize matrix */
+#define ZERO_MATRIX_4X4(m)			\
+{						\
+   m[0][0] = 0.0;				\
+   m[0][1] = 0.0;				\
+   m[0][2] = 0.0;				\
+   m[0][3] = 0.0;				\
+						\
+   m[1][0] = 0.0;				\
+   m[1][1] = 0.0;				\
+   m[1][2] = 0.0;				\
+   m[1][3] = 0.0;				\
+						\
+   m[2][0] = 0.0;				\
+   m[2][1] = 0.0;				\
+   m[2][2] = 0.0;				\
+   m[2][3] = 0.0;				\
+						\
+   m[3][0] = 0.0;				\
+   m[3][1] = 0.0;				\
+   m[3][2] = 0.0;				\
+   m[3][3] = 0.0;				\
+}\
+
+/*! matrix rotation  X */
+#define ROTX_CS(m,cosine,sine)		\
+{					\
+   /* rotation about the x-axis */	\
+					\
+   m[0][0] = 1.0;			\
+   m[0][1] = 0.0;			\
+   m[0][2] = 0.0;			\
+   m[0][3] = 0.0;			\
+					\
+   m[1][0] = 0.0;			\
+   m[1][1] = (cosine);			\
+   m[1][2] = (sine);			\
+   m[1][3] = 0.0;			\
+					\
+   m[2][0] = 0.0;			\
+   m[2][1] = -(sine);			\
+   m[2][2] = (cosine);			\
+   m[2][3] = 0.0;			\
+					\
+   m[3][0] = 0.0;			\
+   m[3][1] = 0.0;			\
+   m[3][2] = 0.0;			\
+   m[3][3] = 1.0;			\
+}\
+
+/*! matrix rotation  Y */
+#define ROTY_CS(m,cosine,sine)		\
+{					\
+   /* rotation about the y-axis */	\
+					\
+   m[0][0] = (cosine);			\
+   m[0][1] = 0.0;			\
+   m[0][2] = -(sine);			\
+   m[0][3] = 0.0;			\
+					\
+   m[1][0] = 0.0;			\
+   m[1][1] = 1.0;			\
+   m[1][2] = 0.0;			\
+   m[1][3] = 0.0;			\
+					\
+   m[2][0] = (sine);			\
+   m[2][1] = 0.0;			\
+   m[2][2] = (cosine);			\
+   m[2][3] = 0.0;			\
+					\
+   m[3][0] = 0.0;			\
+   m[3][1] = 0.0;			\
+   m[3][2] = 0.0;			\
+   m[3][3] = 1.0;			\
+}\
+
+/*! matrix rotation  Z */
+#define ROTZ_CS(m,cosine,sine)		\
+{					\
+   /* rotation about the z-axis */	\
+					\
+   m[0][0] = (cosine);			\
+   m[0][1] = (sine);			\
+   m[0][2] = 0.0;			\
+   m[0][3] = 0.0;			\
+					\
+   m[1][0] = -(sine);			\
+   m[1][1] = (cosine);			\
+   m[1][2] = 0.0;			\
+   m[1][3] = 0.0;			\
+					\
+   m[2][0] = 0.0;			\
+   m[2][1] = 0.0;			\
+   m[2][2] = 1.0;			\
+   m[2][3] = 0.0;			\
+					\
+   m[3][0] = 0.0;			\
+   m[3][1] = 0.0;			\
+   m[3][2] = 0.0;			\
+   m[3][3] = 1.0;			\
+}\
+
+/*! matrix copy */
+#define COPY_MATRIX_2X2(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+				\
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_2X3(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+   b[0][2] = a[0][2];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[1][2];		\
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_3X3(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+   b[0][2] = a[0][2];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[1][2];		\
+				\
+   b[2][0] = a[2][0];		\
+   b[2][1] = a[2][1];		\
+   b[2][2] = a[2][2];		\
+}\
+
+
+/*! matrix copy */
+#define COPY_MATRIX_4X4(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[0][1];		\
+   b[0][2] = a[0][2];		\
+   b[0][3] = a[0][3];		\
+				\
+   b[1][0] = a[1][0];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[1][2];		\
+   b[1][3] = a[1][3];		\
+				\
+   b[2][0] = a[2][0];		\
+   b[2][1] = a[2][1];		\
+   b[2][2] = a[2][2];		\
+   b[2][3] = a[2][3];		\
+				\
+   b[3][0] = a[3][0];		\
+   b[3][1] = a[3][1];		\
+   b[3][2] = a[3][2];		\
+   b[3][3] = a[3][3];		\
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_2X2(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[1][0];		\
+				\
+   b[1][0] = a[0][1];		\
+   b[1][1] = a[1][1];		\
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_3X3(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[1][0];		\
+   b[0][2] = a[2][0];		\
+				\
+   b[1][0] = a[0][1];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[2][1];		\
+				\
+   b[2][0] = a[0][2];		\
+   b[2][1] = a[1][2];		\
+   b[2][2] = a[2][2];		\
+}\
+
+
+/*! matrix transpose */
+#define TRANSPOSE_MATRIX_4X4(b,a)	\
+{				\
+   b[0][0] = a[0][0];		\
+   b[0][1] = a[1][0];		\
+   b[0][2] = a[2][0];		\
+   b[0][3] = a[3][0];		\
+				\
+   b[1][0] = a[0][1];		\
+   b[1][1] = a[1][1];		\
+   b[1][2] = a[2][1];		\
+   b[1][3] = a[3][1];		\
+				\
+   b[2][0] = a[0][2];		\
+   b[2][1] = a[1][2];		\
+   b[2][2] = a[2][2];		\
+   b[2][3] = a[3][2];		\
+				\
+   b[3][0] = a[0][3];		\
+   b[3][1] = a[1][3];		\
+   b[3][2] = a[2][3];		\
+   b[3][3] = a[3][3];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_2X2(b,s,a)		\
+{					\
+   b[0][0] = (s) * a[0][0];		\
+   b[0][1] = (s) * a[0][1];		\
+					\
+   b[1][0] = (s) * a[1][0];		\
+   b[1][1] = (s) * a[1][1];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_3X3(b,s,a)		\
+{					\
+   b[0][0] = (s) * a[0][0];		\
+   b[0][1] = (s) * a[0][1];		\
+   b[0][2] = (s) * a[0][2];		\
+					\
+   b[1][0] = (s) * a[1][0];		\
+   b[1][1] = (s) * a[1][1];		\
+   b[1][2] = (s) * a[1][2];		\
+					\
+   b[2][0] = (s) * a[2][0];		\
+   b[2][1] = (s) * a[2][1];		\
+   b[2][2] = (s) * a[2][2];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_MATRIX_4X4(b,s,a)		\
+{					\
+   b[0][0] = (s) * a[0][0];		\
+   b[0][1] = (s) * a[0][1];		\
+   b[0][2] = (s) * a[0][2];		\
+   b[0][3] = (s) * a[0][3];		\
+					\
+   b[1][0] = (s) * a[1][0];		\
+   b[1][1] = (s) * a[1][1];		\
+   b[1][2] = (s) * a[1][2];		\
+   b[1][3] = (s) * a[1][3];		\
+					\
+   b[2][0] = (s) * a[2][0];		\
+   b[2][1] = (s) * a[2][1];		\
+   b[2][2] = (s) * a[2][2];		\
+   b[2][3] = (s) * a[2][3];		\
+					\
+   b[3][0] = s * a[3][0];		\
+   b[3][1] = s * a[3][1];		\
+   b[3][2] = s * a[3][2];		\
+   b[3][3] = s * a[3][3];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_VEC_MATRIX_2X2(b,svec,a)		\
+{					\
+   b[0][0] = svec[0] * a[0][0];		\
+   b[1][0] = svec[0] * a[1][0];		\
+					\
+   b[0][1] = svec[1] * a[0][1];		\
+   b[1][1] = svec[1] * a[1][1];		\
+}\
+
+
+/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */
+#define SCALE_VEC_MATRIX_3X3(b,svec,a)		\
+{					\
+   b[0][0] = svec[0] * a[0][0];		\
+   b[1][0] = svec[0] * a[1][0];		\
+   b[2][0] = svec[0] * a[2][0];		\
+					\
+   b[0][1] = svec[1] * a[0][1];		\
+   b[1][1] = svec[1] * a[1][1];		\
+   b[2][1] = svec[1] * a[2][1];		\
+					\
+   b[0][2] = svec[2] * a[0][2];		\
+   b[1][2] = svec[2] * a[1][2];		\
+   b[2][2] = svec[2] * a[2][2];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define SCALE_VEC_MATRIX_4X4(b,svec,a)		\
+{					\
+   b[0][0] = svec[0] * a[0][0];		\
+   b[1][0] = svec[0] * a[1][0];		\
+   b[2][0] = svec[0] * a[2][0];		\
+   b[3][0] = svec[0] * a[3][0];		\
+					\
+   b[0][1] = svec[1] * a[0][1];		\
+   b[1][1] = svec[1] * a[1][1];		\
+   b[2][1] = svec[1] * a[2][1];		\
+   b[3][1] = svec[1] * a[3][1];		\
+					\
+   b[0][2] = svec[2] * a[0][2];		\
+   b[1][2] = svec[2] * a[1][2];		\
+   b[2][2] = svec[2] * a[2][2];		\
+   b[3][2] = svec[2] * a[3][2];		\
+   \
+   b[0][3] = svec[3] * a[0][3];		\
+   b[1][3] = svec[3] * a[1][3];		\
+   b[2][3] = svec[3] * a[2][3];		\
+   b[3][3] = svec[3] * a[3][3];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_2X2(b,s,a)		\
+{					\
+   b[0][0] += (s) * a[0][0];		\
+   b[0][1] += (s) * a[0][1];		\
+					\
+   b[1][0] += (s) * a[1][0];		\
+   b[1][1] += (s) * a[1][1];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_3X3(b,s,a)		\
+{					\
+   b[0][0] += (s) * a[0][0];		\
+   b[0][1] += (s) * a[0][1];		\
+   b[0][2] += (s) * a[0][2];		\
+					\
+   b[1][0] += (s) * a[1][0];		\
+   b[1][1] += (s) * a[1][1];		\
+   b[1][2] += (s) * a[1][2];		\
+					\
+   b[2][0] += (s) * a[2][0];		\
+   b[2][1] += (s) * a[2][1];		\
+   b[2][2] += (s) * a[2][2];		\
+}\
+
+
+/*! multiply matrix by scalar */
+#define ACCUM_SCALE_MATRIX_4X4(b,s,a)		\
+{					\
+   b[0][0] += (s) * a[0][0];		\
+   b[0][1] += (s) * a[0][1];		\
+   b[0][2] += (s) * a[0][2];		\
+   b[0][3] += (s) * a[0][3];		\
+					\
+   b[1][0] += (s) * a[1][0];		\
+   b[1][1] += (s) * a[1][1];		\
+   b[1][2] += (s) * a[1][2];		\
+   b[1][3] += (s) * a[1][3];		\
+					\
+   b[2][0] += (s) * a[2][0];		\
+   b[2][1] += (s) * a[2][1];		\
+   b[2][2] += (s) * a[2][2];		\
+   b[2][3] += (s) * a[2][3];		\
+					\
+   b[3][0] += (s) * a[3][0];		\
+   b[3][1] += (s) * a[3][1];		\
+   b[3][2] += (s) * a[3][2];		\
+   b[3][3] += (s) * a[3][3];		\
+}\
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_2X2(c,a,b)		\
+{						\
+   c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0];	\
+   c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1];	\
+						\
+   c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0];	\
+   c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1];	\
+						\
+}\
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_3X3(c,a,b)				\
+{								\
+   c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0];	\
+   c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1];	\
+   c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2];	\
+								\
+   c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0];	\
+   c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1];	\
+   c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2];	\
+								\
+   c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0];	\
+   c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1];	\
+   c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2];	\
+}\
+
+
+/*! matrix product */
+/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/
+#define MATRIX_PRODUCT_4X4(c,a,b)		\
+{						\
+   c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];\
+   c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]+a[0][3]*b[3][1];\
+   c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]+a[0][3]*b[3][2];\
+   c[0][3] = a[0][0]*b[0][3]+a[0][1]*b[1][3]+a[0][2]*b[2][3]+a[0][3]*b[3][3];\
+						\
+   c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]+a[1][3]*b[3][0];\
+   c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]+a[1][3]*b[3][1];\
+   c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]+a[1][3]*b[3][2];\
+   c[1][3] = a[1][0]*b[0][3]+a[1][1]*b[1][3]+a[1][2]*b[2][3]+a[1][3]*b[3][3];\
+						\
+   c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]+a[2][3]*b[3][0];\
+   c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]+a[2][3]*b[3][1];\
+   c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]+a[2][3]*b[3][2];\
+   c[2][3] = a[2][0]*b[0][3]+a[2][1]*b[1][3]+a[2][2]*b[2][3]+a[2][3]*b[3][3];\
+						\
+   c[3][0] = a[3][0]*b[0][0]+a[3][1]*b[1][0]+a[3][2]*b[2][0]+a[3][3]*b[3][0];\
+   c[3][1] = a[3][0]*b[0][1]+a[3][1]*b[1][1]+a[3][2]*b[2][1]+a[3][3]*b[3][1];\
+   c[3][2] = a[3][0]*b[0][2]+a[3][1]*b[1][2]+a[3][2]*b[2][2]+a[3][3]*b[3][2];\
+   c[3][3] = a[3][0]*b[0][3]+a[3][1]*b[1][3]+a[3][2]*b[2][3]+a[3][3]*b[3][3];\
+}\
+
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_2X2(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1];				\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1];				\
+}\
+
+
+/*! matrix times vector */
+#define MAT_DOT_VEC_3X3(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2];		\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2];		\
+   p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2];		\
+}\
+
+
+/*! matrix times vector
+v is a vec4f
+*/
+#define MAT_DOT_VEC_4X4(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]*v[3];	\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]*v[3];	\
+   p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]*v[3];	\
+   p[3] = m[3][0]*v[0] + m[3][1]*v[1] + m[3][2]*v[2] + m[3][3]*v[3];	\
+}\
+
+/*! matrix times vector
+v is a vec3f
+and m is a mat4f<br>
+Last column is added as the position
+*/
+#define MAT_DOT_VEC_3X4(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3];	\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3];	\
+   p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3];	\
+}\
+
+
+/*! vector transpose times matrix */
+/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */
+#define VEC_DOT_MAT_3X3(p,v,m)					\
+{								\
+   p[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0];		\
+   p[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1];		\
+   p[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2];		\
+}\
+
+
+/*! affine matrix times vector */
+/** The matrix is assumed to be an affine matrix, with last two
+ * entries representing a translation */
+#define MAT_DOT_VEC_2X3(p,m,v)					\
+{								\
+   p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2];		\
+   p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2];		\
+}\
+
+//! Transform a plane
+#define MAT_TRANSFORM_PLANE_4X4(pout,m,plane)\
+{								\
+   pout[0] = m[0][0]*plane[0] + m[0][1]*plane[1]  + m[0][2]*plane[2];\
+   pout[1] = m[1][0]*plane[0] + m[1][1]*plane[1]  + m[1][2]*plane[2];\
+   pout[2] = m[2][0]*plane[0] + m[2][1]*plane[1]  + m[2][2]*plane[2];\
+   pout[3] = m[0][3]*pout[0] + m[1][3]*pout[1]  + m[2][3]*pout[2] + plane[3];\
+}\
+
+
+
+/** inverse transpose of matrix times vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ *
+ * DANGER !!! Do Not use this on normal vectors!!!
+ * It will leave normals the wrong length !!!
+ * See macro below for use on normals.
+ */
+#define INV_TRANSP_MAT_DOT_VEC_2X2(p,m,v)			\
+{								\
+   GREAL det;						\
+								\
+   det = m[0][0]*m[1][1] - m[0][1]*m[1][0];			\
+   p[0] = m[1][1]*v[0] - m[1][0]*v[1];				\
+   p[1] = - m[0][1]*v[0] + m[0][0]*v[1];			\
+								\
+   /* if matrix not singular, and not orthonormal, then renormalize */ \
+   if ((det!=1.0f) && (det != 0.0f)) {				\
+      det = 1.0f / det;						\
+      p[0] *= det;						\
+      p[1] *= det;						\
+   }								\
+}\
+
+
+/** transform normal vector by inverse transpose of matrix
+ * and then renormalize the vector
+ *
+ * This macro computes inverse transpose of matrix m,
+ * and multiplies vector v into it, to yeild vector p
+ * Vector p is then normalized.
+ */
+#define NORM_XFORM_2X2(p,m,v)					\
+{								\
+   GREAL len;							\
+								\
+   /* do nothing if off-diagonals are zero and diagonals are 	\
+    * equal */							\
+   if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) { \
+      p[0] = m[1][1]*v[0] - m[1][0]*v[1];			\
+      p[1] = - m[0][1]*v[0] + m[0][0]*v[1];			\
+								\
+      len = p[0]*p[0] + p[1]*p[1];				\
+      GIM_INV_SQRT(len,len);					\
+      p[0] *= len;						\
+      p[1] *= len;						\
+   } else {							\
+      VEC_COPY_2 (p, v);					\
+   }								\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_2X2(m,v,t)				\
+{								\
+   m[0][0] = v[0] * t[0];					\
+   m[0][1] = v[0] * t[1];					\
+								\
+   m[1][0] = v[1] * t[0];					\
+   m[1][1] = v[1] * t[1];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_3X3(m,v,t)				\
+{								\
+   m[0][0] = v[0] * t[0];					\
+   m[0][1] = v[0] * t[1];					\
+   m[0][2] = v[0] * t[2];					\
+								\
+   m[1][0] = v[1] * t[0];					\
+   m[1][1] = v[1] * t[1];					\
+   m[1][2] = v[1] * t[2];					\
+								\
+   m[2][0] = v[2] * t[0];					\
+   m[2][1] = v[2] * t[1];					\
+   m[2][2] = v[2] * t[2];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define OUTER_PRODUCT_4X4(m,v,t)				\
+{								\
+   m[0][0] = v[0] * t[0];					\
+   m[0][1] = v[0] * t[1];					\
+   m[0][2] = v[0] * t[2];					\
+   m[0][3] = v[0] * t[3];					\
+								\
+   m[1][0] = v[1] * t[0];					\
+   m[1][1] = v[1] * t[1];					\
+   m[1][2] = v[1] * t[2];					\
+   m[1][3] = v[1] * t[3];					\
+								\
+   m[2][0] = v[2] * t[0];					\
+   m[2][1] = v[2] * t[1];					\
+   m[2][2] = v[2] * t[2];					\
+   m[2][3] = v[2] * t[3];					\
+								\
+   m[3][0] = v[3] * t[0];					\
+   m[3][1] = v[3] * t[1];					\
+   m[3][2] = v[3] * t[2];					\
+   m[3][3] = v[3] * t[3];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_2X2(m,v,t)				\
+{								\
+   m[0][0] += v[0] * t[0];					\
+   m[0][1] += v[0] * t[1];					\
+								\
+   m[1][0] += v[1] * t[0];					\
+   m[1][1] += v[1] * t[1];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_3X3(m,v,t)				\
+{								\
+   m[0][0] += v[0] * t[0];					\
+   m[0][1] += v[0] * t[1];					\
+   m[0][2] += v[0] * t[2];					\
+								\
+   m[1][0] += v[1] * t[0];					\
+   m[1][1] += v[1] * t[1];					\
+   m[1][2] += v[1] * t[2];					\
+								\
+   m[2][0] += v[2] * t[0];					\
+   m[2][1] += v[2] * t[1];					\
+   m[2][2] += v[2] * t[2];					\
+}\
+
+
+/** outer product of vector times vector transpose
+ *
+ * The outer product of vector v and vector transpose t yeilds
+ * dyadic matrix m.
+ */
+#define ACCUM_OUTER_PRODUCT_4X4(m,v,t)				\
+{								\
+   m[0][0] += v[0] * t[0];					\
+   m[0][1] += v[0] * t[1];					\
+   m[0][2] += v[0] * t[2];					\
+   m[0][3] += v[0] * t[3];					\
+								\
+   m[1][0] += v[1] * t[0];					\
+   m[1][1] += v[1] * t[1];					\
+   m[1][2] += v[1] * t[2];					\
+   m[1][3] += v[1] * t[3];					\
+								\
+   m[2][0] += v[2] * t[0];					\
+   m[2][1] += v[2] * t[1];					\
+   m[2][2] += v[2] * t[2];					\
+   m[2][3] += v[2] * t[3];					\
+								\
+   m[3][0] += v[3] * t[0];					\
+   m[3][1] += v[3] * t[1];					\
+   m[3][2] += v[3] * t[2];					\
+   m[3][3] += v[3] * t[3];					\
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_2X2(d,m)					\
+{								\
+   d = m[0][0] * m[1][1] - m[0][1] * m[1][0];			\
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_3X3(d,m)					\
+{								\
+   d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]);		\
+   d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]);	\
+   d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]);	\
+}\
+
+
+/** i,j,th cofactor of a 4x4 matrix
+ *
+ */
+#define COFACTOR_4X4_IJ(fac,m,i,j) 				\
+{								\
+   GUINT __ii[4], __jj[4], __k;						\
+								\
+   for (__k=0; __k<i; __k++) __ii[__k] = __k;				\
+   for (__k=i; __k<3; __k++) __ii[__k] = __k+1;				\
+   for (__k=0; __k<j; __k++) __jj[__k] = __k;				\
+   for (__k=j; __k<3; __k++) __jj[__k] = __k+1;				\
+								\
+   (fac) = m[__ii[0]][__jj[0]] * (m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[2]] 	\
+                            - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[1]]); \
+   (fac) -= m[__ii[0]][__jj[1]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[2]]	\
+                             - m[__ii[1]][__jj[2]]*m[__ii[2]][__jj[0]]);\
+   (fac) += m[__ii[0]][__jj[2]] * (m[__ii[1]][__jj[0]]*m[__ii[2]][__jj[1]]	\
+                             - m[__ii[1]][__jj[1]]*m[__ii[2]][__jj[0]]);\
+								\
+   __k = i+j;							\
+   if ( __k != (__k/2)*2) {						\
+      (fac) = -(fac);						\
+   }								\
+}\
+
+
+/** determinant of matrix
+ *
+ * Computes determinant of matrix m, returning d
+ */
+#define DETERMINANT_4X4(d,m)					\
+{								\
+   GREAL cofac;						\
+   COFACTOR_4X4_IJ (cofac, m, 0, 0);				\
+   d = m[0][0] * cofac;						\
+   COFACTOR_4X4_IJ (cofac, m, 0, 1);				\
+   d += m[0][1] * cofac;					\
+   COFACTOR_4X4_IJ (cofac, m, 0, 2);				\
+   d += m[0][2] * cofac;					\
+   COFACTOR_4X4_IJ (cofac, m, 0, 3);				\
+   d += m[0][3] * cofac;					\
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_2X2(a,m)					\
+{								\
+   a[0][0] = (m)[1][1];						\
+   a[0][1] = - (m)[1][0];						\
+   a[1][0] = - (m)[0][1];						\
+   a[1][1] = (m)[0][0];						\
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_3X3(a,m)					\
+{								\
+   a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1];			\
+   a[0][1] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]);		\
+   a[0][2] = m[1][0]*m[2][1] - m[1][1]*m[2][0];			\
+   a[1][0] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]);		\
+   a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0];			\
+   a[1][2] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]);		\
+   a[2][0] = m[0][1]*m[1][2] - m[0][2]*m[1][1];			\
+   a[2][1] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]);		\
+   a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]);		\
+}\
+
+
+/** cofactor of matrix
+ *
+ * Computes cofactor of matrix m, returning a
+ */
+#define COFACTOR_4X4(a,m)					\
+{								\
+   int i,j;							\
+								\
+   for (i=0; i<4; i++) {					\
+      for (j=0; j<4; j++) {					\
+         COFACTOR_4X4_IJ (a[i][j], m, i, j);			\
+      }								\
+   }								\
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_2X2(a,m)					\
+{								\
+   a[0][0] = (m)[1][1];						\
+   a[1][0] = - (m)[1][0];						\
+   a[0][1] = - (m)[0][1];						\
+   a[1][1] = (m)[0][0];						\
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_3X3(a,m)					\
+{								\
+   a[0][0] = m[1][1]*m[2][2] - m[1][2]*m[2][1];			\
+   a[1][0] = - (m[1][0]*m[2][2] - m[2][0]*m[1][2]);		\
+   a[2][0] = m[1][0]*m[2][1] - m[1][1]*m[2][0];			\
+   a[0][1] = - (m[0][1]*m[2][2] - m[0][2]*m[2][1]);		\
+   a[1][1] = m[0][0]*m[2][2] - m[0][2]*m[2][0];			\
+   a[2][1] = - (m[0][0]*m[2][1] - m[0][1]*m[2][0]);		\
+   a[0][2] = m[0][1]*m[1][2] - m[0][2]*m[1][1];			\
+   a[1][2] = - (m[0][0]*m[1][2] - m[0][2]*m[1][0]);		\
+   a[2][2] = m[0][0]*m[1][1] - m[0][1]*m[1][0]);		\
+}\
+
+
+/** adjoint of matrix
+ *
+ * Computes adjoint of matrix m, returning a
+ * (Note that adjoint is just the transpose of the cofactor matrix)
+ */
+#define ADJOINT_4X4(a,m)					\
+{								\
+   char _i_,_j_;							\
+								\
+   for (_i_=0; _i_<4; _i_++) {					\
+      for (_j_=0; _j_<4; _j_++) {					\
+         COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_);			\
+      }								\
+   }								\
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_2X2(a,s,m)				\
+{								\
+   a[0][0] = (s) * m[1][1];					\
+   a[1][0] = - (s) * m[1][0];					\
+   a[0][1] = - (s) * m[0][1];					\
+   a[1][1] = (s) * m[0][0];					\
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_3X3(a,s,m)				\
+{								\
+   a[0][0] = (s) * (m[1][1] * m[2][2] - m[1][2] * m[2][1]);	\
+   a[1][0] = (s) * (m[1][2] * m[2][0] - m[1][0] * m[2][2]);	\
+   a[2][0] = (s) * (m[1][0] * m[2][1] - m[1][1] * m[2][0]);	\
+								\
+   a[0][1] = (s) * (m[0][2] * m[2][1] - m[0][1] * m[2][2]);	\
+   a[1][1] = (s) * (m[0][0] * m[2][2] - m[0][2] * m[2][0]);	\
+   a[2][1] = (s) * (m[0][1] * m[2][0] - m[0][0] * m[2][1]);	\
+								\
+   a[0][2] = (s) * (m[0][1] * m[1][2] - m[0][2] * m[1][1]);	\
+   a[1][2] = (s) * (m[0][2] * m[1][0] - m[0][0] * m[1][2]);	\
+   a[2][2] = (s) * (m[0][0] * m[1][1] - m[0][1] * m[1][0]);	\
+}\
+
+
+/** compute adjoint of matrix and scale
+ *
+ * Computes adjoint of matrix m, scales it by s, returning a
+ */
+#define SCALE_ADJOINT_4X4(a,s,m)				\
+{								\
+   char _i_,_j_; \
+   for (_i_=0; _i_<4; _i_++) {					\
+      for (_j_=0; _j_<4; _j_++) {					\
+         COFACTOR_4X4_IJ (a[_j_][_i_], m, _i_, _j_);			\
+         a[_j_][_i_] *= s;						\
+      }								\
+   }								\
+}\
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_2X2(b,det,a)			\
+{						\
+   GREAL _tmp_;					\
+   DETERMINANT_2X2 (det, a);			\
+   _tmp_ = 1.0 / (det);				\
+   SCALE_ADJOINT_2X2 (b, _tmp_, a);		\
+}\
+
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_3X3(b,det,a)			\
+{						\
+   GREAL _tmp_;					\
+   DETERMINANT_3X3 (det, a);			\
+   _tmp_ = 1.0 / (det);				\
+   SCALE_ADJOINT_3X3 (b, _tmp_, a);		\
+}\
+
+
+/** inverse of matrix
+ *
+ * Compute inverse of matrix a, returning determinant m and
+ * inverse b
+ */
+#define INVERT_4X4(b,det,a)			\
+{						\
+   GREAL _tmp_;					\
+   DETERMINANT_4X4 (det, a);			\
+   _tmp_ = 1.0 / (det);				\
+   SCALE_ADJOINT_4X4 (b, _tmp_, a);		\
+}\
+
+//! Get the triple(3) row of a transform matrix
+#define MAT_GET_ROW(mat,vec3,rowindex)\
+{\
+    vec3[0] = mat[rowindex][0];\
+    vec3[1] = mat[rowindex][1];\
+    vec3[2] = mat[rowindex][2]; \
+}\
+
+//! Get the tuple(2) row of a transform matrix
+#define MAT_GET_ROW2(mat,vec2,rowindex)\
+{\
+    vec2[0] = mat[rowindex][0];\
+    vec2[1] = mat[rowindex][1];\
+}\
+
+
+//! Get the quad (4) row of a transform matrix
+#define MAT_GET_ROW4(mat,vec4,rowindex)\
+{\
+    vec4[0] = mat[rowindex][0];\
+    vec4[1] = mat[rowindex][1];\
+    vec4[2] = mat[rowindex][2];\
+    vec4[3] = mat[rowindex][3];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_COL(mat,vec3,colindex)\
+{\
+    vec3[0] = mat[0][colindex];\
+    vec3[1] = mat[1][colindex];\
+    vec3[2] = mat[2][colindex]; \
+}\
+
+//! Get the tuple(2) col of a transform matrix
+#define MAT_GET_COL2(mat,vec2,colindex)\
+{\
+    vec2[0] = mat[0][colindex];\
+    vec2[1] = mat[1][colindex];\
+}\
+
+
+//! Get the quad (4) col of a transform matrix
+#define MAT_GET_COL4(mat,vec4,colindex)\
+{\
+    vec4[0] = mat[0][colindex];\
+    vec4[1] = mat[1][colindex];\
+    vec4[2] = mat[2][colindex];\
+    vec4[3] = mat[3][colindex];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_X(mat,vec3)\
+{\
+    MAT_GET_COL(mat,vec3,0);\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_Y(mat,vec3)\
+{\
+    MAT_GET_COL(mat,vec3,1);\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_Z(mat,vec3)\
+{\
+    MAT_GET_COL(mat,vec3,2);\
+}\
+
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_X(mat,vec3)\
+{\
+    mat[0][0] = vec3[0];\
+    mat[1][0] = vec3[1];\
+    mat[2][0] = vec3[2];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_Y(mat,vec3)\
+{\
+    mat[0][1] = vec3[0];\
+    mat[1][1] = vec3[1];\
+    mat[2][1] = vec3[2];\
+}\
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_SET_Z(mat,vec3)\
+{\
+    mat[0][2] = vec3[0];\
+    mat[1][2] = vec3[1];\
+    mat[2][2] = vec3[2];\
+}\
+
+
+//! Get the triple(3) col of a transform matrix
+#define MAT_GET_TRANSLATION(mat,vec3)\
+{\
+    vec3[0] = mat[0][3];\
+    vec3[1] = mat[1][3];\
+    vec3[2] = mat[2][3]; \
+}\
+
+//! Set the triple(3) col of a transform matrix
+#define MAT_SET_TRANSLATION(mat,vec3)\
+{\
+    mat[0][3] = vec3[0];\
+    mat[1][3] = vec3[1];\
+    mat[2][3] = vec3[2]; \
+}\
+
+
+
+//! Returns the dot product between a vec3f and the row of a matrix
+#define MAT_DOT_ROW(mat,vec3,rowindex) (vec3[0]*mat[rowindex][0] + vec3[1]*mat[rowindex][1] + vec3[2]*mat[rowindex][2])
+
+//! Returns the dot product between a vec2f and the row of a matrix
+#define MAT_DOT_ROW2(mat,vec2,rowindex) (vec2[0]*mat[rowindex][0] + vec2[1]*mat[rowindex][1])
+
+//! Returns the dot product between a vec4f and the row of a matrix
+#define MAT_DOT_ROW4(mat,vec4,rowindex) (vec4[0]*mat[rowindex][0] + vec4[1]*mat[rowindex][1] + vec4[2]*mat[rowindex][2] + vec4[3]*mat[rowindex][3])
+
+
+//! Returns the dot product between a vec3f and the col of a matrix
+#define MAT_DOT_COL(mat,vec3,colindex) (vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex])
+
+//! Returns the dot product between a vec2f and the col of a matrix
+#define MAT_DOT_COL2(mat,vec2,colindex) (vec2[0]*mat[0][colindex] + vec2[1]*mat[1][colindex])
+
+//! Returns the dot product between a vec4f and the col of a matrix
+#define MAT_DOT_COL4(mat,vec4,colindex) (vec4[0]*mat[0][colindex] + vec4[1]*mat[1][colindex] + vec4[2]*mat[2][colindex] + vec4[3]*mat[3][colindex])
+
+/*!Transpose matrix times vector
+v is a vec3f
+and m is a mat4f<br>
+*/
+#define INV_MAT_DOT_VEC_3X3(p,m,v)					\
+{								\
+   p[0] = MAT_DOT_COL(m,v,0); \
+   p[1] = MAT_DOT_COL(m,v,1);	\
+   p[2] = MAT_DOT_COL(m,v,2);	\
+}\
+
+
+
+#endif // GIM_VECTOR_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_math.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_math.h
new file mode 100644
index 0000000..8b9e680
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_math.h
@@ -0,0 +1,157 @@
+#ifndef GIM_MATH_H_INCLUDED
+#define GIM_MATH_H_INCLUDED
+/*! \file gim_math.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "LinearMath/btScalar.h"
+
+
+
+#define GREAL btScalar
+#define GREAL2 double
+#define GINT int
+#define GUINT unsigned int
+#define GSHORT short
+#define GUSHORT unsigned short
+#define GINT64 long long
+#define GUINT64 unsigned long long
+
+
+
+#define G_PI 3.14159265358979f
+#define G_HALF_PI 1.5707963f
+//267948966
+#define G_TWO_PI 6.28318530f
+//71795864
+#define G_ROOT3 1.73205f
+#define G_ROOT2 1.41421f
+#define G_UINT_INFINITY 0xffffffff //!< A very very high value
+#define G_REAL_INFINITY FLT_MAX
+#define	G_SIGN_BITMASK			0x80000000
+#define G_EPSILON SIMD_EPSILON
+
+
+
+enum GIM_SCALAR_TYPES
+{
+	G_STYPE_REAL =0,
+	G_STYPE_REAL2,
+	G_STYPE_SHORT,
+	G_STYPE_USHORT,
+	G_STYPE_INT,
+	G_STYPE_UINT,
+	G_STYPE_INT64,
+	G_STYPE_UINT64
+};
+
+
+
+#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f)
+#define G_RADTODEG(X) ((X)*180.0f/3.1415926f)
+
+//! Integer representation of a floating-point value.
+#define GIM_IR(x)					((GUINT&)(x))
+
+//! Signed integer representation of a floating-point value.
+#define GIM_SIR(x)					((GINT&)(x))
+
+//! Absolute integer representation of a floating-point value
+#define GIM_AIR(x)					(GIM_IR(x)&0x7fffffff)
+
+//! Floating-point representation of an integer value.
+#define GIM_FR(x)					((GREAL&)(x))
+
+#define GIM_MAX(a,b) (a<b?b:a)
+#define GIM_MIN(a,b) (a>b?b:a)
+
+#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c))
+#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c))
+
+#define GIM_IS_ZERO(value) (value < G_EPSILON &&  value > -G_EPSILON)
+
+#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON)
+
+#define GIM_IS_POSISITVE(value) (value >= G_EPSILON)
+
+#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2))
+
+///returns a clamped number
+#define GIM_CLAMP(number,minval,maxval) (number<minval?minval:(number>maxval?maxval:number))
+
+#define GIM_GREATER(x, y)	btFabs(x) > (y)
+
+///Swap numbers
+#define GIM_SWAP_NUMBERS(a,b){ \
+    a = a+b; \
+    b = a-b; \
+    a = a-b; \
+}\
+
+#define GIM_INV_SQRT(va,isva)\
+{\
+    if(va<=0.0000001f)\
+    {\
+        isva = G_REAL_INFINITY;\
+    }\
+    else\
+    {\
+        GREAL _x = va * 0.5f;\
+        GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\
+        isva = GIM_FR(_y);\
+        isva  = isva * ( 1.5f - ( _x * isva * isva ) );\
+    }\
+}\
+
+#define GIM_SQRT(va,sva)\
+{\
+    GIM_INV_SQRT(va,sva);\
+    sva = 1.0f/sva;\
+}\
+
+//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html
+inline GREAL gim_inv_sqrt(GREAL f)
+{
+    GREAL r;
+    GIM_INV_SQRT(f,r);
+    return r;
+}
+
+inline GREAL gim_sqrt(GREAL f)
+{
+    GREAL r;
+    GIM_SQRT(f,r);
+    return r;
+}
+
+
+
+#endif // GIM_MATH_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_memory.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_memory.cpp
new file mode 100644
index 0000000..1636eb7
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_memory.cpp
@@ -0,0 +1,135 @@
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_memory.h"
+#include "stdlib.h"
+
+#ifdef GIM_SIMD_MEMORY
+#include "LinearMath/btAlignedAllocator.h"
+#endif
+
+static gim_alloc_function *g_allocfn = 0;
+static gim_alloca_function *g_allocafn = 0;
+static gim_realloc_function *g_reallocfn = 0;
+static gim_free_function *g_freefn = 0;
+
+void gim_set_alloc_handler (gim_alloc_function *fn)
+{
+  g_allocfn = fn;
+}
+
+void gim_set_alloca_handler (gim_alloca_function *fn)
+{
+  g_allocafn = fn;
+}
+
+void gim_set_realloc_handler (gim_realloc_function *fn)
+{
+  g_reallocfn = fn;
+}
+
+void gim_set_free_handler (gim_free_function *fn)
+{
+  g_freefn = fn;
+}
+
+gim_alloc_function *gim_get_alloc_handler()
+{
+  return g_allocfn;
+}
+
+gim_alloca_function *gim_get_alloca_handler()
+{
+  return g_allocafn;
+}
+
+
+gim_realloc_function *gim_get_realloc_handler ()
+{
+  return g_reallocfn;
+}
+
+
+gim_free_function  *gim_get_free_handler ()
+{
+  return g_freefn;
+}
+
+
+void * gim_alloc(size_t size)
+{
+	void * ptr;
+	if (g_allocfn)
+	{
+		ptr = g_allocfn(size);
+	}
+	else
+	{
+#ifdef GIM_SIMD_MEMORY
+		ptr = btAlignedAlloc(size,16);
+#else
+		ptr = malloc(size);
+#endif
+	}
+  	return ptr;
+}
+
+void * gim_alloca(size_t size)
+{
+  if (g_allocafn) return g_allocafn(size); else return gim_alloc(size);
+}
+
+
+void * gim_realloc(void *ptr, size_t oldsize, size_t newsize)
+{
+ 	void * newptr = gim_alloc(newsize);
+    size_t copysize = oldsize<newsize?oldsize:newsize;
+    gim_simd_memcpy(newptr,ptr,copysize);
+    gim_free(ptr);
+    return newptr;
+}
+
+void gim_free(void *ptr)
+{
+	if (!ptr) return;
+	if (g_freefn)
+	{
+	   g_freefn(ptr);
+	}
+	else
+	{
+	#ifdef GIM_SIMD_MEMORY
+		btAlignedFree(ptr);
+	#else
+		free(ptr);
+	#endif
+	}
+}
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_memory.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_memory.h
new file mode 100644
index 0000000..ef396c8
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_memory.h
@@ -0,0 +1,190 @@
+#ifndef GIM_MEMORY_H_INCLUDED
+#define GIM_MEMORY_H_INCLUDED
+/*! \file gim_memory.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+
+#include "gim_math.h"
+#include <string.h>
+
+#ifdef PREFETCH
+#include <xmmintrin.h>	// for prefetch
+#define pfval	64
+#define pfval2	128
+//! Prefetch 64
+#define pf(_x,_i)	_mm_prefetch((void *)(_x + _i + pfval), 0)
+//! Prefetch 128
+#define pf2(_x,_i)	_mm_prefetch((void *)(_x + _i + pfval2), 0)
+#else
+//! Prefetch 64
+#define pf(_x,_i)
+//! Prefetch 128
+#define pf2(_x,_i)
+#endif
+
+
+///Functions for manip packed arrays of numbers
+#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\
+{\
+    for (GUINT _i_=0;_i_<element_count ;++_i_)\
+    {\
+    	dest_array[_i_] = source_array[_i_];\
+    }\
+}\
+
+#define GIM_COPY_ARRAYS_1(dest_array,source_array,element_count,copy_macro)\
+{\
+    for (GUINT _i_=0;_i_<element_count ;++_i_)\
+    {\
+    	copy_macro(dest_array[_i_],source_array[_i_]);\
+    }\
+}\
+
+
+#define GIM_ZERO_ARRAY(array,element_count)\
+{\
+    for (GUINT _i_=0;_i_<element_count ;++_i_)\
+    {\
+    	array[_i_] = 0;\
+    }\
+}\
+
+#define GIM_CONSTANT_ARRAY(array,element_count,constant)\
+{\
+    for (GUINT _i_=0;_i_<element_count ;++_i_)\
+    {\
+    	array[_i_] = constant;\
+    }\
+}\
+
+
+///Function prototypes to allocate and free memory.
+typedef void * gim_alloc_function (size_t size);
+typedef void * gim_alloca_function (size_t size);//Allocs on the heap
+typedef void * gim_realloc_function (void *ptr, size_t oldsize, size_t newsize);
+typedef void gim_free_function (void *ptr);
+
+
+///Memory Function Handlers
+///set new memory management functions. if fn is 0, the default handlers are used.
+void gim_set_alloc_handler (gim_alloc_function *fn);
+void gim_set_alloca_handler (gim_alloca_function *fn);
+void gim_set_realloc_handler (gim_realloc_function *fn);
+void gim_set_free_handler (gim_free_function *fn);
+
+
+///get current memory management functions.
+gim_alloc_function *gim_get_alloc_handler (void);
+gim_alloca_function *gim_get_alloca_handler(void);
+gim_realloc_function *gim_get_realloc_handler (void);
+gim_free_function  *gim_get_free_handler (void);
+
+
+///Standar Memory functions
+void * gim_alloc(size_t size);
+void * gim_alloca(size_t size);
+void * gim_realloc(void *ptr, size_t oldsize, size_t newsize);
+void gim_free(void *ptr);
+
+
+
+#if defined (WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
+    #define GIM_SIMD_MEMORY 1
+#endif
+
+//! SIMD POINTER INTEGER
+#define SIMD_T GUINT64
+//! SIMD INTEGER SIZE
+#define SIMD_T_SIZE sizeof(SIMD_T)
+
+
+inline void gim_simd_memcpy(void * dst, const void * src, size_t copysize)
+{
+#ifdef GIM_SIMD_MEMORY
+/*
+//'long long int' is incompatible with visual studio 6...
+    //copy words
+    SIMD_T * ui_src_ptr = (SIMD_T *)src;
+    SIMD_T * ui_dst_ptr = (SIMD_T *)dst;
+    while(copysize>=SIMD_T_SIZE)
+    {
+        *(ui_dst_ptr++) = *(ui_src_ptr++);
+        copysize-=SIMD_T_SIZE;
+    }
+    if(copysize==0) return;
+*/
+
+    char * c_src_ptr = (char *)src;
+    char * c_dst_ptr = (char *)dst;
+    while(copysize>0)
+    {
+        *(c_dst_ptr++) = *(c_src_ptr++);
+        copysize--;
+    }
+    return;
+#else
+    memcpy(dst,src,copysize);
+#endif
+}
+
+
+
+template<class T>
+inline void gim_swap_elements(T* _array,size_t _i,size_t _j)
+{
+	T _e_tmp_ = _array[_i];
+	_array[_i] = _array[_j];
+	_array[_j] = _e_tmp_;
+}
+
+
+template<class T>
+inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j)
+{
+	char _e_tmp_[sizeof(T)];
+	gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T));
+	gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T));
+	gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T));
+}
+
+template <int SIZE>
+inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j)
+{
+	char _e_tmp_[SIZE];
+	_i*=SIZE;
+	_j*=SIZE;
+	gim_simd_memcpy(_e_tmp_,_array+_i,SIZE);
+	gim_simd_memcpy(_array+_i,_array+_j,SIZE);
+	gim_simd_memcpy(_array+_j,_e_tmp_,SIZE);
+}
+
+#endif // GIM_MEMORY_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_radixsort.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_radixsort.h
new file mode 100644
index 0000000..f7dadbb
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_radixsort.h
@@ -0,0 +1,406 @@
+#ifndef GIM_RADIXSORT_H_INCLUDED
+#define GIM_RADIXSORT_H_INCLUDED
+/*! \file gim_radixsort.h
+\author Francisco Len N�jera.
+Based on the work of Michael Herf : "fast floating-point radix sort"
+Avaliable on http://www.stereopsis.com/radix.html
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_memory.h"
+
+///Macros for sorting.
+//! Prototype for comparators
+class less_comparator
+{
+	public:
+
+	template<class T,class Z>
+	inline int operator() ( const T& a, const Z& b )
+	{
+		return ( a<b?-1:(a>b?1:0));
+	}
+};
+
+//! Prototype for comparators
+class integer_comparator
+{
+	public:
+
+	template<class T>
+	inline int operator() ( const T& a, const T& b )
+	{
+		return (int)(a-b);
+	}
+};
+
+//!Prototype for getting the integer representation of an object
+class uint_key_func
+{
+public:
+	template<class T>
+	inline GUINT operator()( const T& a)
+	{
+		return (GUINT)a;
+	}
+};
+
+
+//!Prototype for copying elements
+class copy_elements_func
+{
+public:
+	template<class T>
+	inline void operator()(T& a,T& b)
+	{
+		a = b;
+	}
+};
+
+//!Prototype for copying elements
+class memcopy_elements_func
+{
+public:
+	template<class T>
+	inline void operator()(T& a,T& b)
+	{
+		gim_simd_memcpy(&a,&b,sizeof(T));
+	}
+};
+
+
+//! @{
+struct GIM_RSORT_TOKEN
+{
+    GUINT m_key;
+    GUINT m_value;
+    GIM_RSORT_TOKEN()
+    {
+    }
+    GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken)
+    {
+    	m_key = rtoken.m_key;
+    	m_value = rtoken.m_value;
+    }
+
+    inline bool operator <(const GIM_RSORT_TOKEN& other) const
+	{
+		return (m_key < other.m_key);
+	}
+
+	inline bool operator >(const GIM_RSORT_TOKEN& other) const
+	{
+		return (m_key > other.m_key);
+	}
+};
+
+//! Prototype for comparators
+class GIM_RSORT_TOKEN_COMPARATOR
+{
+	public:
+
+	inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b )
+	{
+		return (int)((a.m_key) - (b.m_key));
+	}
+};
+
+
+
+#define kHist 2048
+// ---- utils for accessing 11-bit quantities
+#define D11_0(x)	(x & 0x7FF)
+#define D11_1(x)	(x >> 11 & 0x7FF)
+#define D11_2(x)	(x >> 22 )
+
+
+
+///Radix sort for unsigned integer keys
+inline void gim_radix_sort_rtokens(
+				GIM_RSORT_TOKEN * array,
+				GIM_RSORT_TOKEN * sorted, GUINT element_count)
+{
+	GUINT i;
+	GUINT b0[kHist * 3];
+	GUINT *b1 = b0 + kHist;
+	GUINT *b2 = b1 + kHist;
+	for (i = 0; i < kHist * 3; ++i)
+	{
+		b0[i] = 0;
+	}
+	GUINT fi;
+	GUINT pos;
+	for (i = 0; i < element_count; ++i)
+	{
+	    fi = array[i].m_key;
+		b0[D11_0(fi)] ++;
+		b1[D11_1(fi)] ++;
+		b2[D11_2(fi)] ++;
+	}
+	{
+		GUINT sum0 = 0, sum1 = 0, sum2 = 0;
+		GUINT tsum;
+		for (i = 0; i < kHist; ++i)
+		{
+			tsum = b0[i] + sum0;
+			b0[i] = sum0 - 1;
+			sum0 = tsum;
+			tsum = b1[i] + sum1;
+			b1[i] = sum1 - 1;
+			sum1 = tsum;
+			tsum = b2[i] + sum2;
+			b2[i] = sum2 - 1;
+			sum2 = tsum;
+		}
+	}
+	for (i = 0; i < element_count; ++i)
+	{
+        fi = array[i].m_key;
+		pos = D11_0(fi);
+		pos = ++b0[pos];
+		sorted[pos].m_key = array[i].m_key;
+		sorted[pos].m_value = array[i].m_value;
+	}
+	for (i = 0; i < element_count; ++i)
+	{
+        fi = sorted[i].m_key;
+		pos = D11_1(fi);
+		pos = ++b1[pos];
+		array[pos].m_key = sorted[i].m_key;
+		array[pos].m_value = sorted[i].m_value;
+	}
+	for (i = 0; i < element_count; ++i)
+	{
+        fi = array[i].m_key;
+		pos = D11_2(fi);
+		pos = ++b2[pos];
+		sorted[pos].m_key = array[i].m_key;
+		sorted[pos].m_value = array[i].m_value;
+	}
+}
+
+
+
+
+/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN
+/*!
+*\param array Array of elements to sort
+*\param sorted_tokens Tokens of sorted elements
+*\param element_count element count
+*\param uintkey_macro Functor which retrieves the integer representation of an array element
+*/
+template<typename T, class GETKEY_CLASS>
+void gim_radix_sort_array_tokens(
+			T* array ,
+			GIM_RSORT_TOKEN * sorted_tokens,
+			GUINT element_count,GETKEY_CLASS uintkey_macro)
+{
+	GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
+    for (GUINT _i=0;_i<element_count;++_i)
+    {
+        _unsorted[_i].m_key = uintkey_macro(array[_i]);
+        _unsorted[_i].m_value = _i;
+    }
+    gim_radix_sort_rtokens(_unsorted,sorted_tokens,element_count);
+    gim_free(_unsorted);
+    gim_free(_unsorted);
+}
+
+/// Sorts array in place. For generic use
+/*!
+\param type Type of the array
+\param array
+\param element_count
+\param get_uintkey_macro Macro for extract the Integer value of the element. Similar to SIMPLE_GET_UINTKEY
+\param copy_elements_macro Macro for copy elements, similar to SIMPLE_COPY_ELEMENTS
+*/
+template<typename T, class GETKEY_CLASS, class COPY_CLASS>
+void gim_radix_sort(
+	T * array, GUINT element_count,
+	GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro)
+{
+	GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN  *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count);
+    gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro);
+    T * _original_array = (T *) gim_alloc(sizeof(T)*element_count);
+    gim_simd_memcpy(_original_array,array,sizeof(T)*element_count);
+    for (GUINT _i=0;_i<element_count;++_i)
+    {
+        copy_elements_macro(array[_i],_original_array[_sorted[_i].m_value]);
+    }
+    gim_free(_original_array);
+    gim_free(_sorted);
+}
+
+//! Failsafe Iterative binary search,
+/*!
+If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
+\param _array
+\param _start_i the beginning of the array
+\param _end_i the ending  index of the array
+\param _search_key Value to find
+\param _comp_macro macro for comparing elements
+\param _found If true the value has found. Boolean
+\param _result_index the index of the found element, or if not found then it will get the index of the  closest bigger value
+*/
+template<class T, typename KEYCLASS, typename COMP_CLASS>
+bool  gim_binary_search_ex(
+		const T* _array, GUINT _start_i,
+		GUINT _end_i,GUINT & _result_index,
+		const KEYCLASS & _search_key,
+		COMP_CLASS _comp_macro)
+{
+	GUINT _k;
+	int _comp_result;
+	GUINT _i = _start_i;
+	GUINT _j = _end_i+1;
+	while (_i < _j)
+	{
+		_k = (_j+_i-1)/2;
+		_comp_result = _comp_macro(_array[_k], _search_key);
+		if (_comp_result == 0)
+		{
+			_result_index = _k;
+			return true;
+		}
+		else if (_comp_result < 0)
+		{
+			_i = _k+1;
+		}
+		else
+		{
+			_j = _k;
+		}
+	}
+	_result_index = _i;
+	return false;
+}
+
+
+
+//! Failsafe Iterative binary search,Template version
+/*!
+If the element is not found, it returns the nearest upper element position, may be the further position after the last element.
+\param _array
+\param _start_i the beginning of the array
+\param _end_i the ending  index of the array
+\param _search_key Value to find
+\param _result_index the index of the found element, or if not found then it will get the index of the  closest bigger value
+\return true if found, else false
+*/
+template<class T>
+bool gim_binary_search(
+	const T*_array,GUINT _start_i,
+	GUINT _end_i,const T & _search_key,
+	GUINT & _result_index)
+{
+	GUINT _i = _start_i;
+	GUINT _j = _end_i+1;
+	GUINT _k;
+	while(_i < _j)
+	{
+		_k = (_j+_i-1)/2;
+		if(_array[_k]==_search_key)
+		{
+			_result_index = _k;
+			return true;
+		}
+		else if (_array[_k]<_search_key)
+		{
+			_i = _k+1;
+		}
+		else
+		{
+			_j = _k;
+		}
+	}
+	_result_index = _i;
+	return false;
+}
+
+
+
+///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
+template <typename T, typename COMP_CLASS>
+void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc)
+{
+	/*  PRE: a[k+1..N] is a heap */
+	/* POST:  a[k..N]  is a heap */
+
+	T temp = pArr[k - 1];
+	/* k has child(s) */
+	while (k <= n/2)
+	{
+		int child = 2*k;
+
+		if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0)
+		{
+			child++;
+		}
+		/* pick larger child */
+		if (CompareFunc(temp , pArr[child - 1])<0)
+		{
+			/* move child up */
+			pArr[k - 1] = pArr[child - 1];
+			k = child;
+		}
+		else
+		{
+			break;
+		}
+	}
+	pArr[k - 1] = temp;
+} /*downHeap*/
+
+
+template <typename T, typename COMP_CLASS>
+void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc)
+{
+	/* sort a[0..N-1],  N.B. 0 to N-1 */
+	GUINT k;
+	GUINT n = element_count;
+	for (k = n/2; k > 0; k--)
+	{
+		gim_down_heap(pArr, k, n, CompareFunc);
+	}
+
+	/* a[1..N] is now a heap */
+	while ( n>=2 )
+	{
+		gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */
+		--n;
+		/* restore a[1..i-1] heap */
+		gim_down_heap(pArr, 1, n, CompareFunc);
+	}
+}
+
+
+
+
+#endif // GIM_RADIXSORT_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_tri_collision.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_tri_collision.cpp
new file mode 100644
index 0000000..74d7341
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_tri_collision.cpp
@@ -0,0 +1,640 @@
+
+/*! \file gim_tri_collision.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_tri_collision.h"
+
+
+#define TRI_LOCAL_EPSILON 0.000001f
+#define MIN_EDGE_EDGE_DIS 0.00001f
+
+
+class GIM_TRIANGLE_CALCULATION_CACHE
+{
+public:
+	GREAL margin;	
+	btVector3 tu_vertices[3];
+	btVector3 tv_vertices[3];
+	btVector4 tu_plane;
+	btVector4 tv_plane;
+	btVector3 closest_point_u;
+	btVector3 closest_point_v;
+	btVector3 edge_edge_dir;
+	btVector3 distances;
+	GREAL du[4];
+	GREAL du0du1;
+	GREAL du0du2;
+	GREAL dv[4];
+	GREAL dv0dv1;
+	GREAL dv0dv2;	
+	btVector3 temp_points[MAX_TRI_CLIPPING];
+	btVector3 temp_points1[MAX_TRI_CLIPPING];
+	btVector3 contact_points[MAX_TRI_CLIPPING];
+	
+
+
+	//! if returns false, the faces are paralele
+	SIMD_FORCE_INLINE bool compute_intervals(
+					const GREAL &D0,
+					const GREAL &D1,
+					const GREAL &D2,
+					const GREAL &D0D1,
+					const GREAL &D0D2,
+					GREAL & scale_edge0,
+					GREAL & scale_edge1,
+					GUINT &edge_index0,
+					GUINT &edge_index1)
+	{
+		if(D0D1>0.0f)
+		{
+			/* here we know that D0D2<=0.0 */
+			/* that is D0, D1 are on the same side, D2 on the other or on the plane */
+			scale_edge0 = -D2/(D0-D2);
+			scale_edge1 = -D1/(D2-D1);
+			edge_index0 = 2;edge_index1 = 1;
+		}
+		else if(D0D2>0.0f)
+		{
+			/* here we know that d0d1<=0.0 */
+			scale_edge0 = -D0/(D1-D0);
+			scale_edge1 = -D1/(D2-D1);
+			edge_index0 = 0;edge_index1 = 1;
+		}
+		else if(D1*D2>0.0f || D0!=0.0f)
+		{
+			/* here we know that d0d1<=0.0 or that D0!=0.0 */
+			scale_edge0 = -D0/(D1-D0);
+			scale_edge1 = -D2/(D0-D2);
+			edge_index0 = 0 ;edge_index1 = 2;
+		}
+		else
+		{
+			return false;
+		}
+		return true;
+	}
+
+
+	//! clip triangle
+	/*!
+	*/
+	SIMD_FORCE_INLINE GUINT clip_triangle(
+		const btVector4 & tri_plane,
+		const btVector3 * tripoints,
+		const btVector3 * srcpoints,
+		btVector3 * clip_points)
+	{
+		// edge 0
+
+		btVector4 edgeplane;
+
+		EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
+
+		GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
+			edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
+
+		if(clipped_count == 0) return 0;
+
+		// edge 1
+
+		EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
+
+		clipped_count = PLANE_CLIP_POLYGON3D(
+			edgeplane,temp_points,clipped_count,temp_points1);
+
+		if(clipped_count == 0) return 0;
+
+		// edge 2
+
+		EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
+
+		clipped_count = PLANE_CLIP_POLYGON3D(
+			edgeplane,temp_points1,clipped_count,clip_points);
+
+		return clipped_count;
+
+
+		/*GUINT i0 = (tri_plane.closestAxis()+1)%3;
+		GUINT i1 = (i0+1)%3;
+		// edge 0
+		btVector3 temp_points[MAX_TRI_CLIPPING];
+		btVector3 temp_points1[MAX_TRI_CLIPPING];
+
+		GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC(
+			0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points,
+			DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1));
+		
+		
+		if(clipped_count == 0) return 0;
+
+		// edge 1
+		clipped_count = PLANE_CLIP_POLYGON_GENERIC(
+			0,temp_points,clipped_count,temp_points1,
+			DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1));
+
+		if(clipped_count == 0) return 0;
+
+		// edge 2
+		clipped_count = PLANE_CLIP_POLYGON_GENERIC(
+			0,temp_points1,clipped_count,clipped_points,
+			DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1));
+
+		return clipped_count;*/
+	}
+
+	SIMD_FORCE_INLINE void sort_isect(
+		GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1)
+	{
+		if(isect1<isect0)
+		{
+			//swap
+			GIM_SWAP_NUMBERS(isect0,isect1);
+			GIM_SWAP_NUMBERS(e0,e1);
+			btVector3 tmp = vec0;
+			vec0 = vec1;
+			vec1 = tmp;
+		}
+	}
+
+	//! Test verifying interval intersection with the direction between planes
+	/*!
+	\pre tv_plane and tu_plane must be set
+	\post
+	distances[2] is set with the distance
+	closest_point_u, closest_point_v, edge_edge_dir are set too
+	\return
+	- 0: faces are paralele
+	- 1: face U casts face V
+	- 2: face V casts face U
+	- 3: nearest edges
+	*/
+	SIMD_FORCE_INLINE GUINT cross_line_intersection_test()
+	{
+		// Compute direction of intersection line
+		edge_edge_dir = tu_plane.cross(tv_plane);
+		GREAL Dlen;
+		VEC_LENGTH(edge_edge_dir,Dlen);
+
+		if(Dlen<0.0001)
+		{
+			return 0; //faces near paralele
+		}
+
+		edge_edge_dir*= 1/Dlen;//normalize
+
+
+		// Compute interval for triangle 1
+		GUINT tu_e0,tu_e1;//edge indices
+		GREAL tu_scale_e0,tu_scale_e1;//edge scale
+		if(!compute_intervals(du[0],du[1],du[2],
+			du0du1,du0du2,tu_scale_e0,tu_scale_e1,tu_e0,tu_e1)) return 0;
+
+		// Compute interval for triangle 2
+		GUINT tv_e0,tv_e1;//edge indices
+		GREAL tv_scale_e0,tv_scale_e1;//edge scale
+
+		if(!compute_intervals(dv[0],dv[1],dv[2],
+			dv0dv1,dv0dv2,tv_scale_e0,tv_scale_e1,tv_e0,tv_e1)) return 0;
+
+		//proyected vertices
+		btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0+1)%3],tu_scale_e0);
+		btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1+1)%3],tu_scale_e1);
+
+		btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0+1)%3],tv_scale_e0);
+		btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1+1)%3],tv_scale_e1);
+
+		//proyected intervals
+		GREAL isect_u[] = {up_e0.dot(edge_edge_dir),up_e1.dot(edge_edge_dir)};
+		GREAL isect_v[] = {vp_e0.dot(edge_edge_dir),vp_e1.dot(edge_edge_dir)};
+
+		sort_isect(isect_u[0],isect_u[1],tu_e0,tu_e1,up_e0,up_e1);
+		sort_isect(isect_v[0],isect_v[1],tv_e0,tv_e1,vp_e0,vp_e1);
+
+		const GREAL midpoint_u = 0.5f*(isect_u[0]+isect_u[1]); // midpoint
+		const GREAL midpoint_v = 0.5f*(isect_v[0]+isect_v[1]); // midpoint
+
+		if(midpoint_u<midpoint_v)
+		{
+			if(isect_u[1]>=isect_v[1]) // face U casts face V
+			{
+				return 1;
+			}
+			else if(isect_v[0]<=isect_u[0]) // face V casts face U
+			{
+				return 2;
+			}
+			// closest points
+			closest_point_u = up_e1;
+			closest_point_v = vp_e0;
+			// calc edges and separation
+
+			if(isect_u[1]+ MIN_EDGE_EDGE_DIS<isect_v[0]) //calc distance between two lines instead
+			{
+				SEGMENT_COLLISION(
+					tu_vertices[tu_e1],tu_vertices[(tu_e1+1)%3],
+					tv_vertices[tv_e0],tv_vertices[(tv_e0+1)%3],
+					closest_point_u,
+					closest_point_v);
+
+				edge_edge_dir = closest_point_u-closest_point_v;
+				VEC_LENGTH(edge_edge_dir,distances[2]);
+				edge_edge_dir *= 1.0f/distances[2];// normalize
+			}
+			else
+			{
+				distances[2] = isect_v[0]-isect_u[1];//distance negative
+				//edge_edge_dir *= -1.0f; //normal pointing from V to U
+			}
+
+		}
+		else
+		{
+			if(isect_v[1]>=isect_u[1]) // face V casts face U
+			{
+				return 2;
+			}
+			else if(isect_u[0]<=isect_v[0]) // face U casts face V
+			{
+				return 1;
+			}
+			// closest points
+			closest_point_u = up_e0;
+			closest_point_v = vp_e1;
+			// calc edges and separation
+
+			if(isect_v[1]+MIN_EDGE_EDGE_DIS<isect_u[0]) //calc distance between two lines instead
+			{
+				SEGMENT_COLLISION(
+					tu_vertices[tu_e0],tu_vertices[(tu_e0+1)%3],
+					tv_vertices[tv_e1],tv_vertices[(tv_e1+1)%3],
+					closest_point_u,
+					closest_point_v);
+
+				edge_edge_dir = closest_point_u-closest_point_v;
+				VEC_LENGTH(edge_edge_dir,distances[2]);
+				edge_edge_dir *= 1.0f/distances[2];// normalize
+			}
+			else
+			{
+				distances[2] = isect_u[0]-isect_v[1];//distance negative
+				//edge_edge_dir *= -1.0f; //normal pointing from V to U
+			}
+		}
+		return 3;
+	}
+
+
+	//! collides by two sides
+	SIMD_FORCE_INLINE bool triangle_collision(
+					const btVector3 & u0,
+					const btVector3 & u1,
+					const btVector3 & u2,
+					GREAL margin_u,
+					const btVector3 & v0,
+					const btVector3 & v1,
+					const btVector3 & v2,
+					GREAL margin_v,
+					GIM_TRIANGLE_CONTACT_DATA & contacts)
+	{
+
+		margin = margin_u + margin_v;
+
+		tu_vertices[0] = u0;
+		tu_vertices[1] = u1;
+		tu_vertices[2] = u2;
+
+		tv_vertices[0] = v0;
+		tv_vertices[1] = v1;
+		tv_vertices[2] = v2;
+
+		//create planes
+		// plane v vs U points
+
+		TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],tv_plane);
+
+		du[0] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[0]);
+		du[1] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[1]);
+		du[2] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[2]);
+
+
+		du0du1 = du[0] * du[1];
+		du0du2 = du[0] * du[2];
+
+
+		if(du0du1>0.0f && du0du2>0.0f)	// same sign on all of them + not equal 0 ?
+		{
+			if(du[0]<0) //we need test behind the triangle plane
+			{
+				distances[0] = GIM_MAX3(du[0],du[1],du[2]);
+				distances[0] = -distances[0];
+				if(distances[0]>margin) return false; //never intersect
+
+				//reorder triangle v
+				VEC_SWAP(tv_vertices[0],tv_vertices[1]);
+				VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
+			}
+			else
+			{
+				distances[0] = GIM_MIN3(du[0],du[1],du[2]);
+				if(distances[0]>margin) return false; //never intersect
+			}
+		}
+		else
+		{
+			//Look if we need to invert the triangle
+			distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid
+
+			if(distances[0]<0.0f)
+			{
+				//reorder triangle v
+				VEC_SWAP(tv_vertices[0],tv_vertices[1]);
+				VEC_SCALE_4(tv_plane,-1.0f,tv_plane);
+
+				distances[0] = GIM_MAX3(du[0],du[1],du[2]);
+				distances[0] = -distances[0];
+			}
+			else
+			{
+				distances[0] = GIM_MIN3(du[0],du[1],du[2]);
+			}
+		}
+
+
+		// plane U vs V points
+
+		TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane);
+
+		dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]);
+		dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]);
+		dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]);
+
+		dv0dv1 = dv[0] * dv[1];
+		dv0dv2 = dv[0] * dv[2];
+
+
+		if(dv0dv1>0.0f && dv0dv2>0.0f)	// same sign on all of them + not equal 0 ?
+		{
+			if(dv[0]<0) //we need test behind the triangle plane
+			{
+				distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
+				distances[1] = -distances[1];
+				if(distances[1]>margin) return false; //never intersect
+
+				//reorder triangle u
+				VEC_SWAP(tu_vertices[0],tu_vertices[1]);
+				VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
+			}
+			else
+			{
+				distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
+				if(distances[1]>margin) return false; //never intersect
+			}
+		}
+		else
+		{
+			//Look if we need to invert the triangle
+			distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid
+
+			if(distances[1]<0.0f)
+			{
+				//reorder triangle v
+				VEC_SWAP(tu_vertices[0],tu_vertices[1]);
+				VEC_SCALE_4(tu_plane,-1.0f,tu_plane);
+
+				distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]);
+				distances[1] = -distances[1];
+			}
+			else
+			{
+				distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]);
+			}
+		}
+
+		GUINT bl;
+		/* bl = cross_line_intersection_test();
+		if(bl==3)
+		{
+			//take edge direction too
+			bl = distances.maxAxis();
+		}
+		else
+		{*/
+			bl = 0;
+			if(distances[0]<distances[1]) bl = 1;
+		//}
+
+		if(bl==2) //edge edge separation
+		{
+			if(distances[2]>margin) return false;
+
+			contacts.m_penetration_depth = -distances[2] + margin;
+			contacts.m_points[0] = closest_point_v;
+			contacts.m_point_count = 1;
+			VEC_COPY(contacts.m_separating_normal,edge_edge_dir);
+
+			return true;
+		}
+
+		//clip face against other
+
+		
+		GUINT point_count;
+		//TODO
+		if(bl == 0) //clip U points against V
+		{
+			point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points);
+			if(point_count == 0) return false;						
+			contacts.merge_points(tv_plane,margin,contact_points,point_count);			
+		}
+		else //clip V points against U
+		{
+			point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points);
+			if(point_count == 0) return false;			
+			contacts.merge_points(tu_plane,margin,contact_points,point_count);
+			contacts.m_separating_normal *= -1.f;
+		}
+		if(contacts.m_point_count == 0) return false;
+		return true;
+	}
+
+};
+
+
+/*class GIM_TRIANGLE_CALCULATION_CACHE
+{
+public:
+	GREAL margin;
+	GUINT clipped_count;
+	btVector3 tu_vertices[3];
+	btVector3 tv_vertices[3];
+	btVector3 temp_points[MAX_TRI_CLIPPING];
+	btVector3 temp_points1[MAX_TRI_CLIPPING];
+	btVector3 clipped_points[MAX_TRI_CLIPPING];
+	GIM_TRIANGLE_CONTACT_DATA contacts1;
+	GIM_TRIANGLE_CONTACT_DATA contacts2;
+
+
+	//! clip triangle
+	GUINT clip_triangle(
+		const btVector4 & tri_plane,
+		const btVector3 * tripoints,
+		const btVector3 * srcpoints,
+		btVector3 * clipped_points)
+	{
+		// edge 0
+
+		btVector4 edgeplane;
+
+		EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane);
+
+		GUINT clipped_count = PLANE_CLIP_TRIANGLE3D(
+			edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points);
+
+		if(clipped_count == 0) return 0;
+
+		// edge 1
+
+		EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane);
+
+		clipped_count = PLANE_CLIP_POLYGON3D(
+			edgeplane,temp_points,clipped_count,temp_points1);
+
+		if(clipped_count == 0) return 0;
+
+		// edge 2
+
+		EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane);
+
+		clipped_count = PLANE_CLIP_POLYGON3D(
+			edgeplane,temp_points1,clipped_count,clipped_points);
+
+		return clipped_count;
+	}
+
+
+
+
+	//! collides only on one side
+	bool triangle_collision(
+					const btVector3 & u0,
+					const btVector3 & u1,
+					const btVector3 & u2,
+					GREAL margin_u,
+					const btVector3 & v0,
+					const btVector3 & v1,
+					const btVector3 & v2,
+					GREAL margin_v,
+					GIM_TRIANGLE_CONTACT_DATA & contacts)
+	{
+
+		margin = margin_u + margin_v;
+
+		
+		tu_vertices[0] = u0;
+		tu_vertices[1] = u1;
+		tu_vertices[2] = u2;
+
+		tv_vertices[0] = v0;
+		tv_vertices[1] = v1;
+		tv_vertices[2] = v2;
+
+		//create planes
+		// plane v vs U points
+
+
+		TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal);
+
+		clipped_count = clip_triangle(
+			contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points);
+
+		if(clipped_count == 0 )
+		{
+			 return false;//Reject
+		}
+
+		//find most deep interval face1
+		contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count);
+		if(contacts1.m_point_count == 0) return false; // too far
+
+		//Normal pointing to triangle1
+		//contacts1.m_separating_normal *= -1.f;
+
+		//Clip tri1 by tri2 edges
+
+		TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal);
+
+		clipped_count = clip_triangle(
+			contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points);
+
+		if(clipped_count == 0 )
+		{
+			 return false;//Reject
+		}
+
+		//find most deep interval face1
+		contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count);
+		if(contacts2.m_point_count == 0) return false; // too far
+
+		contacts2.m_separating_normal *= -1.f;
+
+		////check most dir for contacts
+		if(contacts2.m_penetration_depth<contacts1.m_penetration_depth)
+		{
+			contacts.copy_from(contacts2);
+		}
+		else
+		{
+			contacts.copy_from(contacts1);
+		}
+		return true;
+	}
+
+
+};*/
+
+
+
+bool GIM_TRIANGLE::collide_triangle_hard_test(
+		const GIM_TRIANGLE & other,
+		GIM_TRIANGLE_CONTACT_DATA & contact_data) const
+{
+	GIM_TRIANGLE_CALCULATION_CACHE calc_cache;	
+	return calc_cache.triangle_collision(
+					m_vertices[0],m_vertices[1],m_vertices[2],m_margin,
+					other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin,
+					contact_data);
+
+}
+
+
+
+
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_tri_collision.h b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_tri_collision.h
new file mode 100644
index 0000000..2d6e43a
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACT/core/gim_tri_collision.h
@@ -0,0 +1,379 @@
+#ifndef GIM_TRI_COLLISION_H_INCLUDED
+#define GIM_TRI_COLLISION_H_INCLUDED
+
+/*! \file gim_tri_collision.h
+\author Francisco Len N�jera
+*/
+/*
+-----------------------------------------------------------------------------
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of EITHER:
+   (1) The GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 2.1 of the License, or (at
+       your option) any later version. The text of the GNU Lesser
+       General Public License is included with this library in the
+       file GIMPACT-LICENSE-LGPL.TXT.
+   (2) The BSD-style license that is included with this library in
+       the file GIMPACT-LICENSE-BSD.TXT.
+   (3) The zlib/libpng license that is included with this library in
+       the file GIMPACT-LICENSE-ZLIB.TXT.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
+ GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
+
+-----------------------------------------------------------------------------
+*/
+
+#include "gim_box_collision.h"
+#include "gim_clip_polygon.h"
+
+
+
+
+#define MAX_TRI_CLIPPING 16
+
+//! Structure for collision
+struct GIM_TRIANGLE_CONTACT_DATA
+{
+    GREAL m_penetration_depth;
+    GUINT m_point_count;
+    btVector4 m_separating_normal;
+    btVector3 m_points[MAX_TRI_CLIPPING];
+
+	SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA& other)
+	{
+		m_penetration_depth = other.m_penetration_depth;
+		m_separating_normal = other.m_separating_normal;
+		m_point_count = other.m_point_count;
+		GUINT i = m_point_count;
+		while(i--)
+		{
+			m_points[i] = other.m_points[i];
+		}
+	}
+
+	GIM_TRIANGLE_CONTACT_DATA()
+	{
+	}
+
+	GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA& other)
+	{
+		copy_from(other);
+	}
+
+	
+	
+
+    //! classify points that are closer
+    template<typename DISTANCE_FUNC,typename CLASS_PLANE>
+    SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane,
+    				GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func)
+    {	
+    	m_point_count = 0;
+    	m_penetration_depth= -1000.0f;
+
+		GUINT point_indices[MAX_TRI_CLIPPING];
+
+		GUINT _k;
+
+		for(_k=0;_k<point_count;_k++)
+		{
+			GREAL _dist = -distance_func(plane,points[_k]) + margin;
+
+			if(_dist>=0.0f)
+			{
+				if(_dist>m_penetration_depth)
+				{
+					m_penetration_depth = _dist;
+					point_indices[0] = _k;
+					m_point_count=1;
+				}
+				else if((_dist+G_EPSILON)>=m_penetration_depth)
+				{
+					point_indices[m_point_count] = _k;
+					m_point_count++;
+				}
+			}
+		}
+
+		for( _k=0;_k<m_point_count;_k++)
+		{
+			m_points[_k] = points[point_indices[_k]];
+		}
+	}
+
+	//! classify points that are closer
+	SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
+										 const btVector3 * points, GUINT point_count)
+	{
+		m_separating_normal = plane;
+		mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
+	}
+};
+
+
+//! Class for colliding triangles
+class GIM_TRIANGLE
+{
+public:
+	btScalar m_margin;
+    btVector3 m_vertices[3];
+
+    GIM_TRIANGLE():m_margin(0.1f)
+    {
+    }
+
+    SIMD_FORCE_INLINE GIM_AABB get_box()  const
+    {
+    	return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
+    }
+
+    SIMD_FORCE_INLINE void get_normal(btVector3 &normal)  const
+    {
+    	TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
+    }
+
+    SIMD_FORCE_INLINE void get_plane(btVector4 &plane)  const
+    {
+    	TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
+    }
+
+    SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
+    {
+    	m_vertices[0] = trans(m_vertices[0]);
+    	m_vertices[1] = trans(m_vertices[1]);
+    	m_vertices[2] = trans(m_vertices[2]);
+    }
+
+    SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane)  const
+    {
+		const btVector3 & e0 = m_vertices[edge_index];
+		const btVector3 & e1 = m_vertices[(edge_index+1)%3];
+		EDGE_PLANE(e0,e1,triangle_normal,plane);
+    }
+
+    //! Gets the relative transformation of this triangle
+    /*!
+    The transformation is oriented to the triangle normal , and aligned to the 1st edge of this triangle. The position corresponds to vertice 0:
+    - triangle normal corresponds to Z axis.
+    - 1st normalized edge corresponds to X axis,
+
+    */
+    SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform)  const
+    {
+    	btMatrix3x3 & matrix = triangle_transform.getBasis();
+
+    	btVector3 zaxis;
+    	get_normal(zaxis);
+    	MAT_SET_Z(matrix,zaxis);
+
+    	btVector3 xaxis = m_vertices[1] - m_vertices[0];
+    	VEC_NORMALIZE(xaxis);
+    	MAT_SET_X(matrix,xaxis);
+
+    	//y axis
+    	xaxis = zaxis.cross(xaxis);
+    	MAT_SET_Y(matrix,xaxis);
+
+    	triangle_transform.setOrigin(m_vertices[0]);
+    }
+
+
+	//! Test triangles by finding separating axis
+	/*!
+	\param other Triangle for collide
+	\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
+	*/
+	bool collide_triangle_hard_test(
+		const GIM_TRIANGLE & other,
+		GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
+
+	//! Test boxes before doing hard test
+	/*!
+	\param other Triangle for collide
+	\param contact_data Structure for holding contact points, normal and penetration depth; The normal is pointing toward this triangle from the other triangle
+	\
+	*/
+	SIMD_FORCE_INLINE bool collide_triangle(
+		const GIM_TRIANGLE & other,
+		GIM_TRIANGLE_CONTACT_DATA & contact_data) const
+	{
+		//test box collisioin
+		GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
+		GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
+		if(!boxu.has_collision(boxv)) return false;
+
+		//do hard test
+		return collide_triangle_hard_test(other,contact_data);
+	}
+
+	/*!
+
+	Solve the System for u,v parameters:
+
+	u*axe1[i1] + v*axe2[i1] = vecproj[i1]
+	u*axe1[i2] + v*axe2[i2] = vecproj[i2]
+
+	sustitute:
+	v = (vecproj[i2] - u*axe1[i2])/axe2[i2]
+
+	then the first equation in terms of 'u':
+
+	--> u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1]
+
+	--> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1]
+
+	--> u*(axe1[i1]  - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2]
+
+	--> u*((axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2]
+
+	--> u*(axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]
+
+	--> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2]  - axe1[i2]*axe2[i1])
+
+if 0.0<= u+v <=1.0 then they are inside of triangle
+
+	\return false if the point is outside of triangle.This function  doesn't take the margin
+	*/
+	SIMD_FORCE_INLINE bool get_uv_parameters(
+			const btVector3 & point,
+			const btVector3 & tri_plane,
+			GREAL & u, GREAL & v) const
+	{
+		btVector3 _axe1 = m_vertices[1]-m_vertices[0];
+		btVector3 _axe2 = m_vertices[2]-m_vertices[0];
+		btVector3 _vecproj = point - m_vertices[0];
+		GUINT _i1 = (tri_plane.closestAxis()+1)%3;
+		GUINT _i2 = (_i1+1)%3;
+		if(btFabs(_axe2[_i2])<G_EPSILON)
+		{
+			u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1]  - _axe1[_i1]*_axe2[_i2]);
+			v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
+		}
+		else
+		{
+			u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2]  - _axe1[_i2]*_axe2[_i1]);
+			v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
+		}
+
+		if(u<-G_EPSILON)
+		{
+			return false;
+		}
+		else if(v<-G_EPSILON)
+		{
+			return false;
+		}
+		else
+		{
+			btScalar sumuv;
+			sumuv = u+v;
+			if(sumuv<-G_EPSILON)
+			{
+				return false;
+			}
+			else if(sumuv-1.0f>G_EPSILON)
+			{
+				return false;
+			}
+		}
+		return true;
+	}
+
+	//! is point in triangle beam?
+	/*!
+	Test if point is in triangle, with m_margin tolerance
+	*/
+	SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const
+	{
+		//Test with edge 0
+		btVector4 edge_plane;
+		this->get_edge_plane(0,tri_normal,edge_plane);
+		GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point);
+		if(dist-m_margin>0.0f) return false; // outside plane
+
+		this->get_edge_plane(1,tri_normal,edge_plane);
+		dist = DISTANCE_PLANE_POINT(edge_plane,point);
+		if(dist-m_margin>0.0f) return false; // outside plane
+
+		this->get_edge_plane(2,tri_normal,edge_plane);
+		dist = DISTANCE_PLANE_POINT(edge_plane,point);
+		if(dist-m_margin>0.0f) return false; // outside plane
+		return true;
+	}
+
+
+	//! Bidireccional ray collision
+	SIMD_FORCE_INLINE bool ray_collision(
+		const btVector3 & vPoint,
+		const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
+		GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
+	{
+		btVector4 faceplane;
+		{
+			btVector3 dif1 = m_vertices[1] - m_vertices[0];
+			btVector3 dif2 = m_vertices[2] - m_vertices[0];
+    		VEC_CROSS(faceplane,dif1,dif2);
+    		faceplane[3] = m_vertices[0].dot(faceplane);
+		}
+
+		GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
+		if(res == 0) return false;
+		if(! is_point_inside(pout,faceplane)) return false;
+
+		if(res==2) //invert normal
+		{
+			triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
+		}
+		else
+		{
+			triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
+		}
+
+		VEC_NORMALIZE(triangle_normal);
+
+		return true;
+	}
+
+
+	//! one direccion ray collision
+	SIMD_FORCE_INLINE bool ray_collision_front_side(
+		const btVector3 & vPoint,
+		const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
+		GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
+	{
+		btVector4 faceplane;
+		{
+			btVector3 dif1 = m_vertices[1] - m_vertices[0];
+			btVector3 dif2 = m_vertices[2] - m_vertices[0];
+    		VEC_CROSS(faceplane,dif1,dif2);
+    		faceplane[3] = m_vertices[0].dot(faceplane);
+		}
+
+		GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
+		if(res != 1) return false;
+
+		if(!is_point_inside(pout,faceplane)) return false;
+
+		triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
+
+		VEC_NORMALIZE(triangle_normal);
+
+		return true;
+	}
+
+};
+
+
+
+
+#endif // GIM_TRI_COLLISION_H_INCLUDED
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp b/SRC/ChronoEngine/collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp
new file mode 100644
index 0000000..4f0be59
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.cpp
@@ -0,0 +1,240 @@
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "btGImpactConvexDecompositionShape.h"
+#include "BulletCollision/CollisionShapes/btConvexHullShape.h"
+
+#include "ConvexDecomposition/ConvexBuilder.h"
+
+class GIM_ConvexDecomposition : public ConvexDecomposition::ConvexDecompInterface
+{
+protected:
+	btGImpactConvexDecompositionShape * m_compoundShape;
+
+	btAlignedObjectArray<btCollisionShape*> m_convexShapes;
+
+
+public:
+	int   	mBaseCount;
+	int		mHullCount;
+	bool m_transformSubShapes;
+
+	GIM_ConvexDecomposition(btGImpactConvexDecompositionShape * compoundShape,bool transformSubShapes)
+	{
+		mBaseCount = 0;
+		mHullCount = 0;
+		m_compoundShape = compoundShape;
+		m_transformSubShapes = transformSubShapes;
+	}
+
+	virtual ~GIM_ConvexDecomposition()
+	{
+		int i;
+		for (i=0;i<m_convexShapes.size();i++)
+		{
+			btCollisionShape* shape = m_convexShapes[i];
+			delete shape;
+		}
+
+	}
+
+	virtual void ConvexDecompResult(ConvexDecomposition::ConvexResult &result)
+	{
+
+		//calc centroid, to shift vertices around center of mass
+		btVector3 centroid(0,0,0);
+		btAlignedObjectArray<btVector3> vertices;
+
+		if(m_transformSubShapes)
+		{
+
+			//const unsigned int *src = result.mHullIndices;
+			for (unsigned int i=0; i<result.mHullVcount; i++)
+			{
+				btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
+
+				centroid += vertex;
+
+			}
+			centroid *= 1.f/(float(result.mHullVcount) );
+		}
+
+		// collect vertices
+		for (unsigned int i=0; i<result.mHullVcount; i++)
+		{
+			btVector3 vertex(result.mHullVertices[i*3],result.mHullVertices[i*3+1],result.mHullVertices[i*3+2]);
+
+			if(m_transformSubShapes)
+			{
+				vertex -= centroid ;
+			}
+			vertices.push_back(vertex);
+		}
+
+		// build convex shape
+
+		btCollisionShape* convexShape = new btConvexHullShape(
+				&(vertices[0].getX()),vertices.size(),sizeof(btVector3));
+		m_convexShapes.push_back(convexShape);
+
+		convexShape->setMargin(m_compoundShape->getMargin());
+
+		if(m_transformSubShapes)
+		{
+			btTransform trans;
+			trans.setIdentity();
+			trans.setOrigin(centroid);
+
+			// add convex shape
+
+			m_compoundShape->addChildShape(trans,convexShape);
+		}
+		else
+		{
+			btTransform trans;
+			trans.setIdentity();
+			//trans.setOrigin(centroid);
+
+			// add convex shape
+
+			m_compoundShape->addChildShape(trans,convexShape);
+
+			//m_compoundShape->addChildShape(convexShape);
+		}
+	}
+
+	void processDecomposition(int part)
+	{
+		btGImpactMeshShapePart::TrimeshPrimitiveManager * trimeshInterface =
+				m_compoundShape->getTrimeshInterface(part);
+
+
+		trimeshInterface->lock();
+
+		//collect vertices
+		btAlignedObjectArray<float> vertices;
+		vertices.reserve(trimeshInterface->get_vertex_count()*3);
+
+		for(int vi = 0;vi<trimeshInterface->get_vertex_count();vi++)
+		{
+			btVector3 vec;
+			trimeshInterface->get_vertex(vi,vec);
+			vertices.push_back(vec[0]);
+			vertices.push_back(vec[1]);
+			vertices.push_back(vec[2]);
+		}
+
+
+		//collect indices
+		btAlignedObjectArray<unsigned int> indices;
+		indices.reserve(trimeshInterface->get_primitive_count()*3);
+
+
+		for(int i = 0;i<trimeshInterface->get_primitive_count();i++)
+		{
+			int i0, i1,i2;
+			trimeshInterface->get_indices(i,i0,i1,i2);
+			indices.push_back(i0);
+			indices.push_back(i1);
+			indices.push_back(i2);
+		}
+
+		trimeshInterface->unlock();
+
+
+
+		unsigned int depth = 5;
+		float cpercent     = 5;
+		float ppercent     = 15;
+		unsigned int maxv  = 16;
+		float skinWidth    = 0.0;
+
+
+		ConvexDecomposition::DecompDesc desc;
+		desc.mVcount       = trimeshInterface->get_vertex_count();
+		desc.mVertices     = &vertices[0];
+		desc.mTcount       = trimeshInterface->get_primitive_count();
+		desc.mIndices      = &indices[0];
+		desc.mDepth        = depth;
+		desc.mCpercent     = cpercent;
+		desc.mPpercent     = ppercent;
+		desc.mMaxVertices  = maxv;
+		desc.mSkinWidth    = skinWidth;
+		desc.mCallback = this;
+
+		//convexDecomposition.performConvexDecomposition(desc);
+
+		ConvexBuilder cb(desc.mCallback);
+		cb.process(desc);
+	}
+
+
+
+
+};
+
+
+
+void btGImpactConvexDecompositionShape::buildConvexDecomposition(bool transformSubShapes)
+{
+
+	m_decomposition = new GIM_ConvexDecomposition(this,transformSubShapes);
+
+	int part_count = m_trimeshInterfaces.size();
+	for (int i = 0;i<part_count ;i++ )
+	{
+		m_decomposition->processDecomposition(i);
+	}
+
+	postUpdate();
+}
+
+btGImpactConvexDecompositionShape::~btGImpactConvexDecompositionShape()
+{
+	delete m_decomposition;
+}
+void btGImpactConvexDecompositionShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const
+{
+
+	int part_count = m_trimeshInterfaces.size();
+	for (int part = 0;part<part_count ;part++ )
+	{
+		void * ptr = (void * )&m_trimeshInterfaces[part];
+
+		btGImpactMeshShapePart::TrimeshPrimitiveManager * trimeshInterface =
+			static_cast<btGImpactMeshShapePart::TrimeshPrimitiveManager *>(ptr);
+
+		trimeshInterface->lock();
+
+		btPrimitiveTriangle triangle;
+
+
+		int i = trimeshInterface->get_primitive_count();
+		while(i--)
+		{
+			trimeshInterface->get_primitive_triangle(i,triangle);
+			callback->processTriangle(triangle.m_vertices,part,i);
+		}
+
+		trimeshInterface->unlock();
+	}
+
+
+}
diff --git a/SRC/ChronoEngine/collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.h b/SRC/ChronoEngine/collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.h
new file mode 100644
index 0000000..a2e7102
--- /dev/null
+++ b/SRC/ChronoEngine/collision/gimpact/GIMPACTUtils/btGImpactConvexDecompositionShape.h
@@ -0,0 +1,87 @@
+/*! \file btGImpactConvexDecompositionShape.h
+\author Francisco Le�n N�jera
+*/
+/*
+This source file is part of GIMPACT Library.
+
+For the latest info, see http://gimpact.sourceforge.net/
+
+Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
+email: projectileman at yahoo.com
+
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it freely,
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H
+#define GIMPACT_CONVEX_DECOMPOSITION_SHAPE_H
+
+
+#include "collision/gimpact/GIMPACT/Bullet/btGImpactShape.h" // box tree class
+
+
+
+//! This class creates a decomposition from a trimesh.
+/*!
+
+*/
+class btGImpactConvexDecompositionShape	: public btGImpactCompoundShape
+{
+protected:
+	btAlignedObjectArray<btGImpactMeshShapePart::TrimeshPrimitiveManager> m_trimeshInterfaces;
+
+	class GIM_ConvexDecomposition*	m_decomposition;
+
+	void buildConvexDecomposition(bool transformSubShapes);
+public:
+
+	btGImpactConvexDecompositionShape(
+			btStridingMeshInterface * meshInterface,
+			const btVector3 & mesh_scale,
+			btScalar margin = btScalar(0.01),bool children_has_transform = true)
+			:btGImpactCompoundShape(children_has_transform)
+	{
+
+		m_collisionMargin = margin;
+
+		btGImpactMeshShapePart::TrimeshPrimitiveManager triInterface;
+		triInterface.m_meshInterface = meshInterface;
+		triInterface.m_scale = mesh_scale;
+		triInterface.m_margin = btScalar(1.0);
+
+		//add parts
+		int part_count = meshInterface->getNumSubParts();
+		for (int i=0;i< part_count;i++ )
+		{
+			triInterface.m_part = i;
+			m_trimeshInterfaces.push_back(triInterface);
+		}
+
+		m_decomposition = 0;
+
+		buildConvexDecomposition(children_has_transform);
+	}
+
+	virtual ~btGImpactConvexDecompositionShape();
+
+	SIMD_FORCE_INLINE btGImpactMeshShapePart::TrimeshPrimitiveManager * getTrimeshInterface(int part)
+	{
+		return &m_trimeshInterfaces[part];
+	}
+
+	virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
+
+};
+
+
+
+
+#endif //GIMPACT_MESH_SHAPE_H
diff --git a/SRC/ChronoEngine/core/ChApiCE.h b/SRC/ChronoEngine/core/ChApiCE.h
new file mode 100644
index 0000000..b4dbbd0
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChApiCE.h
@@ -0,0 +1,58 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHAPICE_H
+#define CHAPICE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChApiCE.h
+//
+//   Base header for all headers that have symbols
+//   that can be exported.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include <cstddef>
+#include <stddef.h>
+#include "core/ChPlatform.h"
+
+
+// Chrono::Engine version
+//
+// This is an integer, as 0xaabbccdd where
+// for example version 1.2.0 is 0x00010200
+
+#define CH_VERSION 0x00010300
+
+
+// When compiling this library, remember to define CH_API_COMPILE
+// (so that the symbols with 'ChApi' in front of them will be
+// marked as exported). Otherwise, just do not define it if you 
+// link the library to your code, and the symbols will be imported.
+
+#if defined(CH_API_COMPILE)
+	#define ChApi ChApiEXPORT
+#else
+	#define ChApi ChApiINPORT	
+#endif
+
+
+
+
+#endif  // END of header
+
diff --git a/SRC/ChronoEngine/core/ChChrono.h b/SRC/ChronoEngine/core/ChChrono.h
new file mode 100644
index 0000000..548e01f
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChChrono.h
@@ -0,0 +1,97 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCHRONO_H
+#define CHCHRONO_H
+
+//////////////////////////////////////////////////
+//  
+//   ChChrono.h
+//
+//   Generic header for Chrono API/SDK,
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+//
+// Following is documentation for 1st page of SDK help, aimed at the Doxygen 
+// tool which builds the html/pdf/help by automatically scanning these
+// headers.
+//
+/*! \mainpage Chrono Engine API/SDK documentation
+ *
+ * <div align="center"><img src="logo_chronoengine_middle.png" ></div>
+ *
+ * \section intro Introduction
+ *
+ * Welcome to the Chrono::Engine API/SDK documentation.
+ * Here you'll find any information you'll need to develop applications with
+ * the Chrono Engine. 
+ *
+ * The Chrono::Engine is a C++ library of tools for physics simulation (multibody
+ * dynamics, kinematics, etc.). This documentation is an important part of it. 
+ * If you have any questions or suggestions, just send a email to the author 
+ * of the engine, Alessandro Tasora (tasora (at) deltaknowledge.com).
+ *
+ *
+ * \section links Links
+ *
+ * <A HREF="namespaces.html">Namespaces</A>: An interesting place to start reading
+ * the documentation.<BR>
+ * <A HREF="annotated.html">Class list</A>: List of all classes with descriptions.<BR>
+ * <A HREF="functions.html">Class members</A>: Nice place to find forgotten features.<BR>
+ *
+ * Everything in the engine is
+ * placed into the namespace 'chrono'. All Chrono classes and functions should be
+ * accessed with th e:: syntax, as: chrono::[class or functions here] . Of course, in 
+ * sake of a more compact syntax, you could avoid all the chrono::... typing by adding at the
+ * beginning of your source code the following statement:
+ *
+ * \code
+ * using namespace chrono;
+ * \endcode
+ *
+ * There are also other namespaces.
+ * You can find a list of all namespaces with descriptions at the 
+ * <A HREF="namespaces.html"> namespaces page</A>. 
+ * This is also a good place to start reading the documentation. 
+ * If you don't want to write the namespace names all the time, just use all namespaces,
+ * like in this example:
+ * \code
+ * using namespace collision;
+ * using namespace pneumatics;
+ * using namespace geometry;
+ * \endcode
+ *
+ * There is a lot more the engine can do, but we hope this gave a short
+ * overview over the basic features of the engine. For some examples, please take
+ * a look into the 'demos' directory of the SDK, and read the tutorials.
+ */
+
+
+namespace chrono
+{
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of header
+
diff --git a/SRC/ChronoEngine/core/ChClassRegister.cpp b/SRC/ChronoEngine/core/ChClassRegister.cpp
new file mode 100644
index 0000000..887043d
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChClassRegister.cpp
@@ -0,0 +1,51 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//   
+//   ChClassRegister.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "core/ChClassRegister.h"
+     
+        
+namespace chrono
+{    
+   
+/// The root of the list of ChClassRegister<t> objects, each 
+/// will contain the name ID of the class,and other useful things
+/// such as the method which can create a 't' object in runtime.
+    
+
+ChClassRegisterCommon** ChClassRegisterCommon::GetStaticHeadAddr()
+{
+	static ChClassRegisterCommon* mlocalHead = 0;		// A STATIC DATA
+	return &mlocalHead;//&m_pHead;
+}
+
+
+
+
+
+}  // END_OF_NAMESPACE____
+
+
+
+
+
+
+
+
+
diff --git a/SRC/ChronoEngine/core/ChClassRegister.h b/SRC/ChronoEngine/core/ChClassRegister.h
new file mode 100644
index 0000000..c418ef2
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChClassRegister.h
@@ -0,0 +1,240 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCLASSREGISTER_H
+#define CHCLASSREGISTER_H
+
+
+//////////////////////////////////////////////////
+//  
+//   ChClassRegister.h
+//
+//   A class factory to register C++ classes. This can
+//   be used, for example, for dynamic object creation 
+//   from a type ID textual name, in serialization etc.
+//   (the so called 'class factory' mechanism).
+//
+//   These classes are based on a modified version of 
+//   the "Eternity" persistence library, copyright 
+//   1999-2003 Nicola Santi.
+//
+//   This functionality can be applied ONLY to classes 
+//   which implement the custom Chrono Run-time type 
+//   information (RTTI), that is classes with the 
+//   CH_RTTI_xxx macros from the file ChRunTimeType.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+///////////////////////////////////////////////////
+//
+//  HOW TO REGISTER A CLASS IN THE CLASS FACTORY
+//
+//   Remember: you can register only classes which have the 
+//  'chrono run-time-type-checking' enabled, that is classes
+//  which have the macro  CH_RTTI(...) inside their class{...}
+//  declaration!!!
+//   Assuming you have such a class, say it is named 'myEmployee',
+//  you just have to put the following line in your .cpp code
+//  (for example in myEmployee.cpp, but not in myEmployee.h!):
+//
+//  chrono::ChClassRegister<myEmployee> my_registration;
+//
+/////////////////////////////////////////////////////
+
+
+
+#include <stdio.h>
+#include <string>
+#include <typeinfo>
+#include "core/ChLog.h"
+#include "core/ChRunTimeType.h"
+
+namespace chrono
+{
+
+
+
+
+/// ChClassRegisterCommon is a base abstract class which allows
+/// a common management of all template classes ChClassRegister<t>.
+
+class ChApi ChClassRegisterCommon
+{
+public:
+
+			//
+			// DATA
+			//
+
+				/// Each item in the gloabl list of ChClassRegister<t>
+				/// object has a pointer to the next item
+				/// named m_pNext. The last element has a NULL
+				/// value inside m_pNext.
+	ChClassRegisterCommon	*m_pNext;
+		
+			//
+			// METHODS
+			//
+
+				/// All instancied ChClassRegister<t> are collect inside
+				/// an unique global list. this 'head' is the head of
+				/// that STATIC list.
+	static ChClassRegisterCommon** GetStaticHeadAddr();
+
+				/// The signature of create method for derived classes.
+	virtual void* create( std::string& class_name ) = 0 ;
+
+				/// The signature of get_conventional_name method for derived classes.
+	virtual std::string get_conventional_name (std::string& compiler_name ) = 0 ;
+
+};
+
+
+
+
+/// ChClassRegisterABSTRACT<t> is like the more specialized 
+/// ChClassRegister<t>, which you will use more often, but the 
+/// ..ABSTRACT version is needed to register abstract classes (those
+/// with some pure virutal member, which cannot be instantiated with 'new'. )
+
+template <class t>
+class ChClassRegisterABSTRACT: public ChClassRegisterCommon
+{
+protected:
+
+		//
+		// DATA
+		//
+
+			/// Name of the class for dynamic creation
+	std::string		 m_sConventionalName;
+												  
+public:
+
+		//
+		// CONSTRUCTORS
+		//
+
+			/// Default constructor: uses the chrono simulated RTTI 
+			/// features to get a name for the class. 
+			/// IT CAN BE USED ONLY ON CHRONO CLASSES WITH RTTI MACROS 
+	
+	 ChClassRegisterABSTRACT()
+					{
+						m_pNext = *GetStaticHeadAddr(); 
+						*GetStaticHeadAddr() = this;
+
+						// set name using the 'fake' RTTI system of Chrono
+						this->m_sConventionalName = t::GetClassRTTI()->GetName(); 
+					}
+
+ 			/// Destructor (removes this from the global list of 
+			/// ChClassRegister<t> object.
+	virtual ~ChClassRegisterABSTRACT()
+					{
+						ChClassRegisterCommon	**ppNext = GetStaticHeadAddr();
+						for( ; *ppNext ; ppNext = &(*ppNext)->m_pNext )
+						{
+							if( *ppNext == this )
+							{
+								*ppNext = (*ppNext)->m_pNext;
+								break;
+							}
+						}
+					}
+	
+
+		//
+		// METHODS
+		//
+
+	virtual bool IsAbstract() {return true;}
+
+	virtual void* create( std::string& class_name )
+					{
+						assert(this->m_sConventionalName!=class_name); // cannot instance an abstract class 
+						return 0;
+					}
+
+			/// Return the conventional name ID of class t if 
+			/// typeid(t).name() match with compiler_name.
+			///	Otherwise return an empty.
+	virtual std::string get_conventional_name (std::string& compiler_name )
+					{
+ 						return ( compiler_name==typeid(t).name() ) 
+								? this->m_sConventionalName
+								: std::string("")	;
+					}
+
+};
+
+/// ChClassRegister<t> is responsable for registration of C++ classes
+/// at compile time (each class name ID enters a static list of 
+/// items when the program starts). 
+/// During run time, it can be used in whatever moment to create
+/// classes given their name ID.
+
+template <class t>
+class ChClassRegister: public ChClassRegisterABSTRACT <t>
+{
+												  
+public:
+
+	virtual bool IsAbstract() {return false;}
+
+			/// Create an instance from class t if the name ID is the same 
+			/// specified in class_name. If the name does not match, returns NULL.
+	virtual void* create( std::string& class_name )
+					{
+ 						return (this->m_sConventionalName==class_name)
+								? (void*)( new t )
+								: 0	;
+					}
+
+};
+
+
+
+/// This function return a pointer to an object
+///	that belong to the class specified by the
+///	string cls_name. If success put in *ppObj
+///	that pointer, otherwise put a NULL value
+///	in *ppObj.
+
+template<class T>
+void create( std::string cls_name, T** ppObj)
+{
+	ChClassRegisterCommon* pCurrent = *ChClassRegisterCommon::GetStaticHeadAddr();
+
+		//the follow line reinterpret several times
+		//invalid null pointer so compilers could
+		//warn about type mismatch.
+	for( ; pCurrent ; pCurrent = pCurrent->m_pNext )
+    if( (*ppObj = reinterpret_cast<T*>( pCurrent->create(cls_name)))!=NULL ) break;
+
+}
+
+
+
+
+
+
+};  // END_OF_NAMESPACE____
+
+#endif 
+
+
diff --git a/SRC/ChronoEngine/core/ChCoordsys.cpp b/SRC/ChronoEngine/core/ChCoordsys.cpp
new file mode 100644
index 0000000..88560dc
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChCoordsys.cpp
@@ -0,0 +1,59 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChCoordsys.cpp
+//
+//	 CHRONO
+//   ------
+//   Multibody dinamics engine
+//
+//   Math functions for:
+//
+//	 - COORDINATES
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChCoordsys.h"
+
+namespace chrono
+{
+
+
+
+///////////////////////////////////////////////
+////  COORDSYS  OPERATIONS
+
+Coordsys  Force2Dcsys (Coordsys* cs)
+{
+	Coordsys res;
+	res = *cs;
+	res.pos.z = 0;
+	res.rot.e1 = 0;
+	res.rot.e2 = 0;
+	return (res);
+}
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/core/ChCoordsys.h b/SRC/ChronoEngine/core/ChCoordsys.h
new file mode 100644
index 0000000..8115ca6
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChCoordsys.h
@@ -0,0 +1,224 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCOORDSYS_H
+#define CHCOORDSYS_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCoordsys.h
+//
+//   Basic math functions for 3d coordinates (position
+//   and rotation). 
+//   For more advanced features, look into headers
+//   ChFrame.h or ChFrameMoving.h.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "core/ChVector.h"
+#include "core/ChQuaternion.h"
+
+
+namespace chrono
+{
+
+
+
+///
+/// COORDSYS:	
+///
+///  This class contains both traslational variable 
+/// (the origin of the axis) and the rotational variable
+/// (that is the unitary quaternion which represent the 
+/// special-orthogonal transformation matrix).
+///   Basic features for point-coordinate transformations
+/// are provided. However, for more advanced features, the 
+/// heavier classes ChFrame() or ChFrameMoving() may suit better.
+///  The coordsys object comes either with the template "ChCoordsys<type>" mode,
+/// either in the 'shortcut' flavour, that is "Coordsys", which assumes
+/// the type of the four scalars is double precision, so it is faster to type.
+///
+
+template <class Real = double>
+class ChCoordsys 
+{
+public:
+
+			//
+			// DATA
+			//
+
+	ChVector<Real>		pos;
+	ChQuaternion<Real>  rot;
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChCoordsys(): pos(VNULL), rot(QUNIT) {};
+
+	explicit ChCoordsys(const ChVector<Real> mv, const ChQuaternion<Real> mq = QUNIT): pos(mv), rot(mq) {};
+
+
+					/// Copy constructor 
+	ChCoordsys(const ChCoordsys<Real>& other) : pos(other.pos), rot(other.rot)  {};
+
+			//
+			// OPERATORS OVERLOADING
+			//
+					/// Assignment operator: copy from another coordsys
+	ChCoordsys<Real>& operator=(const ChCoordsys<Real>& other)	
+					{if (&other == this) return *this; pos = other.pos;  rot = other.rot; return *this; }
+
+				
+	bool operator<=(const ChCoordsys<Real>&other) const { return rot<=other.rot && pos<=other.pos;};
+	bool operator>=(const ChCoordsys<Real>&other) const { return rot>=other.rot && pos>=other.pos;};
+
+	bool operator==(const ChCoordsys<Real>& other) const { return rot==other.rot && pos==other.pos;}
+	bool operator!=(const ChCoordsys<Real>& other) const { return rot!=other.rot || pos!=other.pos;}
+	
+
+
+			//
+			// FUNCTIONS
+			//
+
+					/// Force to z=0, and z rotation only. No normalization to quaternion, however.
+	void Force2D () 	{
+							pos.z = 0;
+							rot.e1 = 0;
+							rot.e2 = 0;
+						}
+
+					/// Returns true if coordsys is identical to other coordsys
+	bool	Equals ( const ChCoordsys<Real>& other) const { return rot.Equals(other.rot) && pos.Equals(other.pos);}
+
+					/// Returns true if coordsys is equal to other coordsys, within a tolerance 'tol'
+	bool	Equals ( const ChCoordsys<Real>& other, Real tol) const
+						{
+							return rot.Equals(other.rot, tol) && pos.Equals(other.pos, tol);
+						}
+
+					/// Sets to no translation and no rotation
+	void    SetIdentity()
+						{
+							pos=VNULL; rot=QUNIT;
+						}
+
+				// POINT TRANSFORMATIONS, USING POSITION AND ROTATION QUATERNION
+
+					/// This function transforms a point from the parent coordinate
+					/// system to a local coordinate system, whose relative position 
+					/// is given by this coodsys, i.e. 'origin' translation and 'alignment' quaternion.
+					/// \return The point in local coordinate, as local=q'*[0,(parent-origin)]*q
+
+	ChVector<Real> TrasformParentToLocal (
+								const ChVector<Real>& parent		///< point to transform, given in parent coordinates
+								) const
+						{
+							return rot.RotateBack(parent - pos);
+						}
+
+					/// This function transforms a point from the local coordinate
+					/// system to the parent coordinate system. Relative position of local respect
+					/// to parent is given by this coordys, i.e. 'origin' translation and 'alignment' quaternion.
+					/// \return The point in parent coordinate, as parent=origin +q*[0,(local)]*q'
+
+	ChVector<Real> TrasformLocalToParent (
+								const ChVector<Real>& local			///< point to transform, given in local coordinates
+								) const
+						{
+							return pos + rot.Rotate(local);
+						}
+
+
+
+			//
+			// STREAMING
+			//
+					/// Method to allow serializing transient data into in ascii
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream)
+						{
+							mstream << "\n" << pos;
+							mstream << "\n" << rot;
+						}
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream)
+						{
+							mstream << pos;
+							mstream << rot;
+						}
+
+					/// Operator to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream)
+						{
+							mstream >> pos;
+							mstream >> rot;
+						}
+
+
+};
+
+
+
+/// Shortcut for faster use of typical double-precision coordsys.
+///  Instead of writing    "ChCoordsys<double> foo;"   you can write 
+///  the shorter version   "Coordsys foo;"
+///
+typedef ChCoordsys<double> Coordsys;
+
+/// Shortcut for faster use of typical single-precision coordsys.
+///
+typedef ChCoordsys<float>  CoordsysF;
+
+
+
+//
+// STATIC COORDSYS OPERATIONS
+//
+
+			/// Force 3d coordsys to lie on a XY plane (note: no normaliz. on quat)
+ChApi 
+Coordsys  Force2Dcsys (Coordsys* cs); 
+
+
+
+
+
+//
+// CONSTANTS
+//
+
+
+static const Coordsys CSYSNULL (VNULL,QNULL);
+static const Coordsys CSYSNORM (VNULL,QUNIT); 
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChCoordsys.h 
diff --git a/SRC/ChronoEngine/core/ChException.h b/SRC/ChronoEngine/core/ChException.h
new file mode 100644
index 0000000..5a2d6c8
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChException.h
@@ -0,0 +1,77 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHEXCEPTION_H
+#define CHEXCEPTION_H
+
+
+//////////////////////////////////////////////////
+//
+//   ChException.h
+//
+//   Custom exception class, for the
+//   throw() catch() mechanism.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <string>
+
+namespace chrono
+{
+
+
+/// Class for exceptions for throw() catch() mechanism.
+/// Each class can contain a message in form of text.
+
+class ChException : public std::exception
+{
+protected:
+	std::string m_swhat;
+
+public:
+
+			/// Constructor for a basic exception: sets the exception
+			/// message as a string 'swhat'.
+	ChException(std::string swhat ) :m_swhat(swhat) {};
+
+			/// Copy constructor
+	ChException(const ChException& right)
+					:m_swhat(right.what()) {};
+
+			/// Assignment = operator
+	ChException& operator=(const ChException& right)
+				{
+					m_swhat=right.what();
+					return *this;
+				}
+
+	virtual ~ChException( ) throw() {};
+
+	virtual const char *what( ) const throw()
+				{
+					return m_swhat.c_str();
+				}
+};
+
+
+
+
+};  // END_OF_NAMESPACE____
+
+#endif
+
diff --git a/SRC/ChronoEngine/core/ChFrame.h b/SRC/ChronoEngine/core/ChFrame.h
new file mode 100644
index 0000000..f08775e
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChFrame.h
@@ -0,0 +1,559 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFRAME_H
+#define CHFRAME_H
+
+//////////////////////////////////////////////////
+//
+//   ChFrame.h
+//
+//   Math functions for FRAME, that is a coordinate
+//   system with translation and rotation.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChCoordsys.h"
+#include "core/ChTrasform.h"
+#include "core/ChTransform.h"
+
+
+namespace chrono
+{
+
+
+
+/// ChFrame: a class for coordinate systems in 3D space.
+///
+///  A 'frame' coordinate system has a translation and
+/// a rotation respect to a 'parent' coordinate system,
+/// usually the absolute (world) coordinates.
+///
+///  Differently from a simple ChCoordsys() object, however,
+/// the ChFrame implements some optimizations because
+/// each ChFrame stores also a 3x3 rotation matrix, which
+/// can speed up coordinate transformations when a large
+/// amount of vectors must be transfomed by the same
+/// coordinate frame.
+///
+
+template <class Real = double>
+class ChFrame
+{
+public:
+			//
+			// DATA
+			//
+						/// Rotation and position, as vector+quaternion
+	ChCoordsys<Real> coord;
+
+						/// Rotation as 3x3 orthogonal matrix (auxiliary, for faster
+						/// transformation of many coordinates )
+	ChMatrix33<Real> Amatrix;
+
+
+			//
+			// CONSTRUCTORS
+			//
+
+						/// Default constructor, or construct from pos and rot (as a quaternion)
+	ChFrame(const ChVector<Real>& mv = VNULL, const ChQuaternion<Real>& mq = QUNIT)
+			: coord(mv,mq), Amatrix(mq) {};
+
+						/// Construct from pos and rotation (as a 3x3 matrix)
+	ChFrame(const ChVector<Real>& mv, ChMatrix33<Real>& ma)
+			: coord(mv,ma.Get_A_quaternion()), Amatrix(ma) {};
+
+						/// Construct from a coordsys
+	explicit ChFrame(const ChCoordsys<Real>& mc)
+			: coord(mc), Amatrix(mc.rot) {};
+
+
+						/// Copy constructor, build from another frame
+	ChFrame(const ChFrame<Real>& other) : coord(other.coord), Amatrix(other.Amatrix) {}
+
+
+
+			//
+			// OPERATORS OVERLOADING
+			//
+
+					/// Assignment operator: copy from another frame
+	ChFrame<Real>& operator=(const ChFrame<Real>& other)
+					{if (&other == this) return *this; coord = other.coord;  Amatrix = other.Amatrix; return *this; }
+
+					/// Returns true for identical frames.
+	virtual bool operator==(const ChFrame<Real>& other) const { return Equals(other); }
+
+					/// Returns true for different frames.
+	virtual bool operator!=(const ChFrame<Real>& other) const { return !Equals(other); }
+
+
+					/// The '>>' operator transforms a coordinate system, so
+					/// transformations can be represented with this syntax:
+					///  new_frame = old_frame >> tr_frame;
+					/// For a sequence of transformations, i.e. a chain of coordinate
+					/// systems, you can also write this (like you would do with
+					/// a sequence of Denavitt-Hartemberg matrix multiplications,
+					/// but in the _opposite_ order...)
+					///  new_frame = old_frame >> frame3to2 >> frame2to1 >> frame1to0;
+					/// This operation is not commutative.
+	ChFrame<Real> operator >> (const ChFrame<Real>& Fb) const
+		{
+				ChFrame<Real> res; Fb.TrasformLocalToParent(*this,res);
+				return res;
+		}
+					/// The '>>' operator transforms a vector, so transformations
+					/// can be represented with this syntax:
+					///  new_v = old_v >> tr_frame;
+					/// For a sequence of transformations, i.e. a chain of coordinate
+					/// systems, you can also write this (like you would do with
+					/// a sequence of Denavitt-Hartemberg matrix multiplications,
+					/// but in the opposite order...)
+					///  new_v = old_v >> frame3to2 >> frame2to1 >> frame1to0;
+					/// This operation is not commutative.
+	friend ChVector<Real> operator >> (const ChVector<Real>& V, const ChFrame<Real>& mframe)
+		{
+				return mframe.TrasformLocalToParent(V);
+		}
+
+					/// The '*' operator transforms a coordinate system, so
+					/// transformations can be represented with this syntax:
+					///  new_frame = tr_frame * old_frame;
+					/// For a sequence of transformations, i.e. a chain of coordinate
+					/// systems, you can also write this (just like you would do with
+					/// a sequence of Denavitt-Hartemberg matrix multiplications!)
+					///  new_frame = frame1to0 * frame2to1 * frame3to2 * old_frame;
+					/// This operation is not commutative.
+					///  NOTE: since c++ operator execution is from left to right, in
+					/// case of multiple transformations like w=A*B*C*v, the >> operator
+					/// performs faster, like  w=v>>C>>B>>A;
+	ChFrame<Real> operator * (const ChFrame<Real>& Fb) const
+		{
+				ChFrame<Real> res; TrasformLocalToParent(Fb,res);
+				return res;
+		}
+					/// The '*' operator transforms a vector, so
+					/// transformations can be represented with this syntax:
+					///  new_v = tr_frame * old_v;
+					/// For a sequence of transformations, i.e. a chain of coordinate
+					/// systems, you can also write this (just like you would do with
+					/// a sequence of Denavitt-Hartemberg matrix multiplications!)
+					///  new_v = frame1to0 * frame2to1 * frame3to2 * old_v;
+					/// This operation is not commutative.
+					///  NOTE: since c++ operator execution is from left to right, in
+					/// case of multiple transformations like w=A*B*C*v, the >> operator
+					/// performs faster, like  w=v>>C>>B>>A;
+	ChVector<Real> operator * (const ChVector<Real>& V) const
+		{
+				return TrasformLocalToParent(V);
+		}
+
+					/// The '/' is like the '*' operator (see), but uses the inverse
+					/// transformation for A, in A/b. (with A ChFrame, b ChVector)
+					/// That is: c=A*b ; b=A/c;
+	ChVector<Real> operator / (const ChVector<Real>& V) const
+		{
+				return TrasformParentToLocal(V);
+		}
+
+					/// Performs pre-multiplication of this frame by another
+					/// frame, for example: A%=T means  A'=T*A ; or A'=A >> T
+	ChFrame<Real>& operator %= (const ChFrame<Real>& T)
+		{
+				ConcatenatePreTransformation(T);
+				return *this;
+		}
+					/// Performs post-multiplication of this frame by another
+					/// frame, for example: A*=T means  A'=A*T ; or A'=T >> A
+	ChFrame<Real>& operator *= (const ChFrame<Real>& T)
+		{
+				ConcatenatePostTransformation(T);
+				return *this;
+		}
+
+
+			//
+			// FUNCTIONS
+			//
+
+				// GET-FUNCTIONS
+
+					/// Return both current rotation and translation as
+					/// a coordsystem object, with vector and quaternion
+	ChCoordsys<Real> GetCoord()
+						{ return coord; }
+
+					/// Return the current translation as a 3d vector
+	ChVector<Real> GetPos()
+						{ return coord.pos; }
+
+					/// Return the current rotation as a quaternion
+	ChQuaternion<Real> GetRot()
+						{ return coord.rot; }
+
+					/// Return the current rotation as a 3x3 matrix
+	ChMatrix33<Real>* GetA()
+						{ return &Amatrix; }
+
+					/// Get axis of finite rotation, in parent space
+	ChVector<Real> GetRotAxis ()
+						{
+							ChVector<Real> vtmp; double angle;
+							Q_to_AngAxis(&coord.rot, &angle, &vtmp);
+							return (vtmp);
+						}
+
+					/// Get angle of rotation about axis of finite rotation
+	double GetRotAngle ()
+						{
+							ChVector<Real> vtmp; double angle;
+							Q_to_AngAxis(&coord.rot, &angle, &vtmp);
+							return (angle);
+						}
+
+
+				// SET-FUNCTIONS
+
+
+					/// Impose both translation and rotation as a
+					/// single ChCoordsys. Note: the quaternion part must be
+					/// already normalized!
+	virtual void SetCoord(const ChCoordsys<Real>& mcoord)
+						{
+							coord = mcoord;
+							Amatrix.Set_A_quaternion(mcoord.rot);
+						}
+
+					/// Impose both translation and rotation.
+					/// Note: the quaternion part must be already normalized!
+	virtual void SetCoord(const ChVector<Real>& mv, const ChQuaternion<Real>& mq)
+						{
+							coord.pos = mv; coord.rot = mq;
+							Amatrix.Set_A_quaternion(mq);
+						}
+
+					/// Impose the rotation as a quaternion.
+					/// Note: the quaternion must be already normalized!
+	virtual void SetRot(const ChQuaternion<Real>& mrot)
+						{
+							coord.rot = mrot;
+							Amatrix.Set_A_quaternion(mrot);
+						}
+
+					/// Impose the rotation as a 3x3 matrix.
+					/// Note: the rotation matrix must be already orthogonal!
+	virtual void SetRot(ChMatrix33<Real>& mA)
+						{
+							coord.rot = mA.Get_A_quaternion();
+							Amatrix.CopyFromMatrix(mA);
+						}
+
+					/// Impose the translation
+	virtual void SetPos(const ChVector<Real>& mpos)
+						{
+							coord.pos = mpos;
+						}
+
+
+
+
+				// FUNCTIONS TO TRANSFORMATE THE FRAME ITSELF
+
+
+					/// Apply a transformation (rotation and translation) represented by
+					/// another ChFrame T. This is equivalent to pre-multiply this frame
+					/// by the other frame T:   this'= T * this; or this' = this >> T
+	void ConcatenatePreTransformation(const ChFrame<Real>& T)
+						{
+							this->SetCoord(T.TrasformLocalToParent(coord.pos),
+										   T.coord.rot % coord.rot);
+						}
+
+					/// Apply a transformation (rotation and translation) represented by
+					/// another ChFrame T in local coordinate. This is equivalent to
+					/// post-multiply this frame by the other frame T:   this'= this * T; or this'= T >> this
+	void ConcatenatePostTransformation(const ChFrame<Real>& T)
+						{
+							this->SetCoord( TrasformLocalToParent(T.coord.pos),
+											coord.rot % T.coord.rot);
+						}
+
+
+
+
+					/// An easy way to move the frame by the amount specified by vector V,
+					/// (assuming V expressed in parent coordinates)
+	void Move (const ChVector<Real>& V)
+						{
+							this->coord.pos += V;
+						}
+
+					/// Apply both translation and rotation, assuming both expressed in parent
+					/// coordinates, as a vector for translation and quaternion for rotation,
+	void Move (ChCoordsys<Real>& VR)
+						{
+							this->SetCoord(VR.TrasformLocalToParent(coord.pos),
+										   VR.rot % coord.rot);
+						}
+
+
+
+				// FUNCTIONS FOR COORDINATE TRANSFORMATIONS
+
+
+					/// This function transforms a point from the local frame coordinate
+					/// system to the parent coordinate system.
+					/// OPTIMIZED FOR SPEED.
+					/// Since it will use the auxiliary rotation matrix of the ChFrame
+					/// object, this function is about 50% faster than TrasformParentToLocal
+					/// of a ChCoordsys.
+					/// \return The point in parent coordinate
+
+	virtual ChVector<Real> TrasformLocalToParent (
+								const ChVector<Real>& local	///< point to transform, given in local frame coordinates
+								)  const
+						{
+							return ChTrasform<Real>::TrasformLocalToParent(local, coord.pos, Amatrix);
+						}
+
+					/// This function transforms a point from the parent coordinate
+					/// system to local frame coordinate system.
+					/// OPTIMIZED FOR SPEED.
+					/// Since it will use the auxiliary rotation matrix of the ChFrame
+					/// object, this function is about 50% faster than TrasformParentToLocal
+					/// method of a ChCoordsys.
+					/// \return The point in local frame coordinate
+
+	virtual ChVector<Real> TrasformParentToLocal (
+								const ChVector<Real>& parent		///< point to transform, given in parent coordinates
+								)  const
+						{
+							return ChTrasform<Real>::TrasformParentToLocal(parent, coord.pos, Amatrix);
+						}
+
+
+
+					/// This function transforms a frame from 'this' local coordinate
+					/// system to parent frame coordinate system.
+					/// \return The frame in parent frame coordinate
+
+	virtual void TrasformLocalToParent (
+								const ChFrame<Real>& local,	///< frame to transform, given in local frame coordinates
+								ChFrame<Real>& parent		///< transformed frame, in parent coordinates, will be stored here
+								)  const
+						{
+							parent.SetCoord(
+								TrasformLocalToParent(local.coord.pos),
+								coord.rot % local.coord.rot  );
+						}
+
+					/// This function transforms a frame from the parent coordinate
+					/// system to 'this' local frame coordinate system.
+					/// \return The frame in local frame coordinate
+
+	virtual void TrasformParentToLocal (
+								const ChFrame<Real>& parent,///< frame to transform, given in parent coordinates
+								ChFrame<Real>& local		///< transformed frame, in local coordinates, will be stored here
+								)  const
+						{
+							local.SetCoord (
+								TrasformParentToLocal(parent.coord.pos),
+								coord.rot.GetConjugate() % parent.coord.rot  );
+						}
+
+
+
+				// OTHER FUNCTIONS
+
+					/// Returns true if coordsys is identical to other coordsys
+	bool	Equals ( const ChFrame<Real>& other) const { return coord.Equals(other.coord);}
+
+					/// Returns true if coordsys is equal to other coordsys, within a tolerance 'tol'
+	bool	Equals ( const ChFrame<Real>& other, Real tol) const { return coord.Equals(other.coord, tol);}
+
+					/// Normalize the rotation, so that quaternion has unit length
+	void	Normalize ()
+						{
+							coord.rot.Normalize();
+							Amatrix.Set_A_quaternion(coord.rot);
+						}
+
+					/// Sets to no translation and no rotation
+	virtual void SetIdentity ()
+						{
+							coord.SetIdentity();
+							Amatrix.SetIdentity();
+						}
+
+
+					/// The trasformation is inverted in place.
+					/// That is if w=A*v, then A.Invert();v=A*w;
+	virtual void Invert()
+						{
+							coord.rot.Conjugate();
+							Amatrix.MatrTranspose();
+							coord.pos = - Amatrix.Matr_x_Vect(coord.pos);
+						}
+
+	ChFrame<Real> GetInverse() const
+						{
+							ChFrame<Real> tmp(*this);
+							tmp.Invert(); return tmp;
+						}
+
+
+					/// Fills a 3x4 matrix [Fp(q)], as in  [Fp(q)]*[Fm(q)]' = [A(q)]
+	static void SetMatrix_Fp(ChMatrixNM<Real,3,4>& Fp, const ChQuaternion<Real>& mq)
+						{
+							assert ((Fp.GetRows() ==3) && (Fp.GetColumns() ==4));
+							Fp(0)= mq.e1;	Fp(1)= mq.e0;	Fp(2)= -mq.e3;	Fp(3)=  mq.e2;
+							Fp(4)= mq.e2;	Fp(5)= mq.e3;	Fp(6)=  mq.e0;	Fp(7)= -mq.e1;
+							Fp(8)= mq.e3;	Fp(9)=-mq.e2;	Fp(10)= mq.e1;	Fp(11)= mq.e0;
+						}
+					/// Fills a 3x4 matrix [Fm(q)], as in  [Fp(q)]*[Fm(q)]' = [A(q)]
+	static void SetMatrix_Fm(ChMatrixNM<Real,3,4>& Fm, const ChQuaternion<Real>& mq)
+						{
+							assert ((Fm.GetRows() ==3) && (Fm.GetColumns() ==4));
+							Fm(0)= mq.e1;	Fm(1)= mq.e0;	Fm(2)=  mq.e3;	Fm(3)= -mq.e2;
+							Fm(4)= mq.e2;	Fm(5)=-mq.e3;	Fm(6)=  mq.e0;	Fm(7)=  mq.e1;
+							Fm(8)= mq.e3;	Fm(9)= mq.e2;	Fm(10)=-mq.e1;	Fm(11)= mq.e0;
+						}
+
+					/// Fast fill a 3x4 matrix [Gl(q)], as in local angular speed conversion
+					/// Wl=[Gl]*q_dt   (btw: [Gl(q)] = 2*[Fp(q')] = 2*[G] with G matrix as in Shabana)
+	static void SetMatrix_Gl(ChMatrixNM<Real,3,4>& Gl, const ChQuaternion<Real>& mq)
+						{
+							assert ((Gl.GetRows() ==3) && (Gl.GetColumns() ==4));
+							double de0 = 2 * mq.e0; double de1 = 2 * mq.e1;
+							double de2 = 2 * mq.e2; double de3 = 2 * mq.e3;
+							Gl(0)=-de1;		Gl(1)= de0;		Gl(2)=  de3;	Gl(3)= -de2;
+							Gl(4)=-de2;		Gl(5)=-de3;		Gl(6)=  de0;	Gl(7)=  de1;
+							Gl(8)=-de3;		Gl(9)= de2;		Gl(10)=-de1;	Gl(11)= de0;
+						}
+
+					/// Fast fill a 3x4 matrix [Gw(q)], as in absolute angular speed conversion
+					/// Ww=[Gw]*q_dt   (btw: [Gw(q)] = 2*[Fm(q')] = 2*[E] with E matrix as in Shabana)
+	static void SetMatrix_Gw(ChMatrixNM<Real,3,4>& Gw, const ChQuaternion<Real>& mq)
+						{
+							assert ((Gw.GetRows() ==3) && (Gw.GetColumns() ==4));
+							double de0 = 2 * mq.e0; double de1 = 2 * mq.e1;
+							double de2 = 2 * mq.e2; double de3 = 2 * mq.e3;
+							Gw(0)=-de1;		Gw(1)= de0;		Gw(2)= -de3;	Gw(3)=  de2;
+							Gw(4)=-de2;		Gw(5)= de3;		Gw(6)=  de0;	Gw(7)= -de1;
+							Gw(8)=-de3;		Gw(9)=-de2;		Gw(10)= de1;	Gw(11)= de0;
+						}
+
+					/// Computes the product v=[Gl(mq)]*qb  without the need of having
+					/// the [Gl] matrix (just pass the mq quaternion, since Gl is function of mq)
+	static ChVector<Real> Gl_x_Quat(const ChQuaternion<Real>& mq, const ChQuaternion<Real>& qb)
+						{
+							double de0 = 2 * mq.e0; double de1 = 2 * mq.e1;
+							double de2 = 2 * mq.e2; double de3 = 2 * mq.e3;
+							return ChVector<Real>(
+								-de1*qb.e0 + de0*qb.e1 + de3*qb.e2 - de2*qb.e3,
+								-de2*qb.e0 - de3*qb.e1 + de0*qb.e2 + de1*qb.e3,
+								-de3*qb.e0 + de2*qb.e1 - de1*qb.e2 + de0*qb.e3);
+						}
+
+					/// Computes the product q=[Gl(mq)]*v  without the need of having
+					/// the [Gl] matrix (just pass the mq quaternion, since Gl is function of mq)
+	static ChQuaternion<Real> GlT_x_Vect(const ChQuaternion<Real>& mq, const ChVector<Real>& v)
+						{
+							double de0 = 2 * mq.e0; double de1 = 2 * mq.e1;
+							double de2 = 2 * mq.e2; double de3 = 2 * mq.e3;
+							return ChQuaternion<Real>(
+								-de1*v.x - de2*v.y - de3*v.z,
+								+de0*v.x - de3*v.y + de2*v.z,
+								+de3*v.x + de0*v.y - de1*v.z,
+								-de2*v.x + de1*v.y + de0*v.z);
+						}
+
+			//
+			// STREAMING
+			//
+					/// Method to allow serializing transient data into in ascii
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii& mstream)
+						{
+							mstream << "\n" << coord.pos;
+							mstream << "\n" << coord.rot;
+						}
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream)
+						{
+							mstream << coord;
+						}
+
+					/// Operator to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream)
+						{
+							mstream >> coord;
+							Amatrix.Set_A_quaternion(coord.rot);
+						}
+
+
+virtual ChVector<Real> TransformLocalToParent(const ChVector<Real>& local) const {
+  return ChTransform<Real>::TransformLocalToParent(local, coord.pos, Amatrix);
+}
+
+virtual ChVector<Real> TransformPointLocalToParent(const ChVector<Real>& local) const {
+  return ChTransform<Real>::TransformLocalToParent(local, coord.pos, Amatrix);
+}
+
+virtual void TransformLocalToParent(
+        const ChFrame<Real>& local,  ///< frame to transform, given in local frame coordinates
+        ChFrame<Real>& parent        ///< transformed frame, in parent coordinates, will be stored here
+        ) const {
+        parent.SetCoord(TransformLocalToParent(local.coord.pos), coord.rot % local.coord.rot);
+    }
+
+ virtual ChVector<Real> TransformParentToLocal(const ChVector<Real>& parent) const {
+        return ChTransform<Real>::TransformParentToLocal(parent, coord.pos, Amatrix);
+    }
+
+    virtual ChVector<Real> TransformPointParentToLocal(const ChVector<Real>& parent) const {
+        return ChTransform<Real>::TransformParentToLocal(parent, coord.pos, Amatrix);
+    }
+
+ virtual void TransformParentToLocal(
+        const ChFrame<Real>& parent,  ///< frame to transform, given in parent coordinates
+        ChFrame<Real>& local          ///< transformed frame, in local coordinates, will be stored here
+        ) const {
+        local.SetCoord(TransformParentToLocal(parent.coord.pos), coord.rot.GetConjugate() % parent.coord.rot);
+    }
+
+};
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChFrame.h
diff --git a/SRC/ChronoEngine/core/ChFrameMoving.h b/SRC/ChronoEngine/core/ChFrameMoving.h
new file mode 100644
index 0000000..20ab23d
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChFrameMoving.h
@@ -0,0 +1,592 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2005, 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFRAMEMOVING_H
+#define CHFRAMEMOVING_H
+
+//////////////////////////////////////////////////
+//
+//   ChFrameMoving.h
+//
+//   Math functions for FRAMES WHICH HAVE SPEED AND
+//   ACCELERATION, that is a coordinate
+//   system with translation and rotation etc-
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChFrame.h"
+
+
+
+namespace chrono
+{
+
+
+
+/// ChFrame: a class for coordinate systems in 3D space.
+///
+///  A 'frame' coordinate system has a translation and
+/// a rotation respect to a 'parent' coordinate system,
+/// usually the absolute (world) coordinates.
+///
+///  Differently from a simple ChCoordsys() object, however,
+/// the ChFrame implements some optimizations because
+/// each ChFrame stores also a 3x3 rotation matrix, which
+/// can speed up coordinate transformations when a large
+/// amount of vectors must be transfomed by the same
+/// coordinate frame.
+///
+
+template <class Real = double>
+class ChFrameMoving : public ChFrame<Real>
+{
+public:
+			//
+			// DATA
+			//
+						/// Rotation and position speed, as vector+quaternion
+	ChCoordsys<Real> coord_dt;
+						/// Rotation and position acceleration, as vector+quaternion
+	ChCoordsys<Real> coord_dtdt;
+
+
+			//
+			// CONSTRUCTORS
+			//
+
+						/// Construct from pos and rot (as a quaternion)
+	explicit ChFrameMoving(const ChVector<Real>& mv = VNULL, const ChQuaternion<Real>& mq = QUNIT)
+		: ChFrame<Real>(mv,mq) { coord_dt.rot = coord_dtdt.rot = QNULL; };
+
+						/// Construct from pos and rotation (as a 3x3 matrix)
+	explicit ChFrameMoving(const ChVector<Real>& mv, ChMatrix33<Real>& ma)
+		: ChFrame<Real>(mv,ma) { coord_dt.rot = coord_dtdt.rot = QNULL; };
+
+						/// Construct from a coordsys
+	explicit ChFrameMoving(const ChCoordsys<Real>& mc)
+		: ChFrame<Real>(mc) { coord_dt.rot = coord_dtdt.rot = QNULL; };
+
+						/// Construct from a frame
+	explicit ChFrameMoving(const ChFrame<Real>& mc)
+		: ChFrame<Real>(mc) { coord_dt.rot = coord_dtdt.rot = QNULL; };
+
+						/// Copy constructor, build from another frame
+	ChFrameMoving(const ChFrameMoving<Real>& other) :
+					ChFrame<Real>(other),
+					coord_dt(other.coord_dt),
+					coord_dtdt(other.coord_dtdt)
+					{}
+
+
+
+			//
+			// OPERATORS OVERLOADING
+			//
+
+
+					/// Assignment operator: copy from another moving frame
+	ChFrameMoving<Real>& operator=(const ChFrameMoving<Real>& other)
+		{
+				if (&other == this) return *this;
+				ChFrame<Real>::operator=(other);
+				coord_dt = other.coord_dt;
+				coord_dtdt = other.coord_dtdt;
+				return *this;
+		}
+
+					/// Assignment operator: copy from another frame
+	ChFrameMoving<Real>& operator=(const ChFrame<Real>& other)
+		{
+				if (&other == this) return *this;
+				ChFrame<Real>::operator=(other);
+				coord_dt.rot = coord_dtdt.rot = QNULL;
+				return *this;
+		}
+
+					/// Returns true for identical frames.
+	bool operator==(const ChFrameMoving<Real>& other) const { return Equals(other);}
+
+					/// Returns true for different frames.
+	bool operator!=(const ChFrameMoving<Real>& other) const { return !Equals(other);}
+
+
+					/// The '>>' operator transforms a coordinate system, so
+					/// transformations can be represented with this syntax:
+					///  new_frame = old_frame >> tr_frame;
+					/// For a sequence of transformations, i.e. a chain of coordinate
+					/// systems, you can also write this (like you would do with
+					/// a sequence of Denavitt-Hartemberg matrix multiplications,
+					/// but in the _opposite_ order...)
+					///  new_frame = old_frame >> frame3to2 >> frame2to1 >> frame1to0;
+					/// This operation is not commutative.
+					/// Also speeds and accelerations are transformed.
+	ChFrameMoving<Real> operator >> (const ChFrameMoving<Real>& Fb) const
+		{
+				static ChFrameMoving<Real> res;
+				Fb.TrasformLocalToParent(*this, res);
+				return res;
+		}
+
+					/// The '*' operator transforms a coordinate system, so
+					/// transformations can be represented with this syntax:
+					///  new_frame = tr_frame * old_frame;
+					/// For a sequence of transformations, i.e. a chain of coordinate
+					/// systems, you can also write this (just like you would do with
+					/// a sequence of Denavitt-Hartemberg matrix multiplications!)
+					///  new_frame = frame1to0 * frame2to1 * frame3to2 * old_frame;
+					/// This operation is not commutative.
+					/// Also speeds and accelerations are transformed.
+	ChFrameMoving<Real> operator * (const ChFrameMoving<Real>& Fb) const
+		{
+				static ChFrameMoving<Real> res;
+				TrasformLocalToParent(Fb,res);
+				return res;
+		}
+
+
+					/// Performs pre-multiplication of this frame by another
+					/// frame, for example: A%=T means  A'=T*A ; or A'=A >> T
+	ChFrameMoving<Real>& operator %= (const ChFrameMoving<Real>& T)
+		{
+				ConcatenatePreTransformation(T);
+				return *this;
+		}
+
+					/// Performs post-multiplication of this frame by another
+					/// frame, for example: A*=T means  A'=A*T ; or A'=T >> A
+	ChFrameMoving<Real>& operator *= (const ChFrameMoving<Real>& T)
+		{
+				ConcatenatePostTransformation(T);
+				return *this;
+		}
+
+
+			//
+			// FUNCTIONS
+			//
+
+				// GET-FUNCTIONS
+
+					/// Return both current rotation and translation speeds as
+					/// a coordsystem object, with vector and quaternion
+	ChCoordsys<Real> GetCoord_dt()
+						{ return coord_dt; }
+					/// Return both current rotation and translation accelerations as
+					/// a coordsystem object, with vector and quaternion
+	ChCoordsys<Real> GetCoord_dtdt()
+						{ return coord_dtdt; }
+
+					/// Return the current speed as a 3d vector
+	ChVector<Real> GetPos_dt()
+						{ return coord_dt.pos; }
+					/// Return the current acceleration as a 3d vector
+	ChVector<Real> GetPos_dtdt()
+						{ return coord_dtdt.pos; }
+
+					/// Return the current rotation speed as a quaternion
+	ChQuaternion<Real> GetRot_dt()
+						{ return coord_dt.rot; }
+					/// Return the current rotation acceleration as a quaternion
+	ChQuaternion<Real> GetRot_dtdt()
+						{ return coord_dtdt.rot; }
+
+
+					/// Computes the actual angular speed (expressed in local coords)
+	ChVector<Real>	GetWvel_loc() const
+						{
+							ChMatrixNM<Real,3,4> tempGl;
+							ChFrame<Real>::SetMatrix_Gl(tempGl, this->coord.rot);
+							return tempGl.Matr34_x_Quat(coord_dt.rot); // wl=[Gl]*q_dt
+						}
+					/// Computes the actual angular speed (expressed in parent coords)
+	ChVector<Real>	GetWvel_par() const
+						{
+							ChMatrixNM<Real,3,4> tempGw;
+							ChFrame<Real>::SetMatrix_Gw(tempGw, this->coord.rot);
+							return tempGw.Matr34_x_Quat(coord_dt.rot); // ww=[Gw]*q_dt
+						}
+
+					/// Computes the actual angular acceleration (expressed in local coords)
+	ChVector<Real>	GetWacc_loc() const
+						{
+							ChMatrixNM<Real,3,4> tempGl;
+							ChFrame<Real>::SetMatrix_Gl(tempGl, this->coord.rot);
+							return tempGl.Matr34_x_Quat(coord_dtdt.rot); // al=[Gl]*q_dtdt
+						}
+					/// Computes the actual angular acceleration (expressed in parent coords)
+	ChVector<Real>	GetWacc_par() const
+						{
+							ChMatrixNM<Real,3,4> tempGw;
+							ChFrame<Real>::SetMatrix_Gw(tempGw, this->coord.rot);
+							return tempGw.Matr34_x_Quat(coord_dtdt.rot); // aw=[Gw]*q_dtdt
+						}
+
+
+				// SET-FUNCTIONS
+
+					/// Set both linear speed and rotation speed as a
+					/// single ChCoordsys derivative.
+	virtual void SetCoord_dt(const ChCoordsys<Real>& mcoord_dt)
+						{
+							coord_dt = mcoord_dt;
+						}
+
+					/// Set the linear speed
+	virtual void SetPos_dt(const ChVector<Real>& mvel)
+						{
+							coord_dt.pos = mvel;
+						}
+
+					/// Set the rotation speed as a quaternion.
+					/// Note: the quaternion must already satisfy  dot(q,q_dt)=0
+	virtual void SetRot_dt(const ChQuaternion<Real>& mrot_dt)
+						{
+							coord_dt.rot = mrot_dt;
+						}
+
+					/// Set the rotation speed from given angular speed
+					/// (expressed in local csys)
+	virtual void SetWvel_loc(const ChVector<Real>& wl)
+						{
+							coord_dt.rot.Cross(this->coord.rot, ChQuaternion<Real>(0,wl));
+							coord_dt.rot*=0.5;	// q_dt = 1/2 * q * (0,wl)
+						}
+
+					/// Set the rotation speed from given angular speed
+					/// (expressed in parent csys)
+	virtual void SetWvel_par(const ChVector<Real>& wp)
+						{
+							coord_dt.rot.Cross(ChQuaternion<Real>(0,wp), this->coord.rot);
+							coord_dt.rot*=0.5;	// q_dt = 1/2 * (0,wp) * q
+						}
+
+
+					/// Set both linear acceleration and rotation acceleration as a
+					/// single ChCoordsys derivative.
+	virtual void SetCoord_dtdt(const ChCoordsys<Real>& mcoord_dtdt)
+						{
+							coord_dtdt = mcoord_dtdt;
+						}
+
+
+					/// Set the linear acceleration
+	virtual void SetPos_dtdt(const ChVector<Real>& macc)
+						{
+							coord_dtdt.pos = macc;
+						}
+
+					/// Set the rotation acceleration as a quaternion derivative.
+					/// Note: the quaternion must already satisfy  dot(q,q_dt)=0
+	virtual void SetRot_dtdt(const ChQuaternion<Real>& mrot_dtdt)
+						{
+							coord_dtdt.rot = mrot_dtdt;
+						}
+
+					/// Set the rotation acceleration from given angular acceleration
+					/// (expressed in local csys)
+	virtual void SetWacc_loc(const ChVector<Real>& al)
+						{
+								// q_dtdt = q_dt * q' * q_dt + 1/2 * q * (0,al)
+							coord_dtdt.rot = (coord_dt.rot % this->coord.rot.GetConjugate() % coord_dt.rot)
+											+ (this->coord.rot % ChQuaternion<Real>(0,al) *0.5);
+						}
+
+					/// Set the rotation speed from given angular speed
+					/// (expressed in parent csys)
+	virtual void SetWacc_par(ChVector<Real>& ap)
+						{
+								// q_dtdt = q_dt * q' * q_dt + 1/2 * (0,ap) * q
+							coord_dtdt.rot = (coord_dt.rot % this->coord.rot.GetConjugate() % coord_dt.rot)
+											+ (ChQuaternion<Real>(0,ap) % this->coord.rot * 0.5);
+						}
+
+					/// Computes the time derivative of rotation matrix, mAdt.
+	void Compute_Adt(ChMatrix33<Real>& mA_dt) const
+						{
+							//  [A_dt]=2[dFp/dt][Fm]'=2[Fp(q_dt)][Fm(q)]'
+							ChMatrixNM<Real,3,4> Fpdt;
+							ChMatrixNM<Real,3,4> Fm;
+							ChFrame<Real>::SetMatrix_Fp (Fpdt, coord_dt.rot);
+							ChFrame<Real>::SetMatrix_Fm (Fm,   this->coord.rot);
+							mA_dt.MatrMultiplyT(Fpdt, Fm);
+							mA_dt.MatrScale(2.);
+						}
+
+					/// Computes the 2nd time derivative of rotation matrix, mAdtdt.
+	void Compute_Adtdt(ChMatrix33<Real>& mA_dtdt)
+						{
+							//  [A_dtdt]=2[Fp(q_dtdt)][Fm(q)]'+2[Fp(q_dt)][Fm(q_dt)]'
+							ChMatrixNM<Real,3,4> ma;
+							ChMatrixNM<Real,3,4> mb;
+							ChMatrix33<Real> mr;
+
+							ChFrame<Real>::SetMatrix_Fp (ma, coord_dtdt.rot);
+							ChFrame<Real>::SetMatrix_Fm (mb, this->coord.rot);
+							mr.MatrMultiplyT(ma,mb);
+							ChFrame<Real>::SetMatrix_Fp (ma, coord_dt.rot);
+							ChFrame<Real>::SetMatrix_Fm (mb, coord_dt.rot);
+							mA_dtdt.MatrMultiplyT(ma, mb);
+							mA_dtdt.MatrInc(mr);
+							mA_dtdt.MatrScale(2.);
+						}
+
+					/// Computes and returns an Adt matrix (-note: prefer using
+					/// Compute_Adt() directly for better performance)
+	ChMatrix33<Real> GetA_dt()
+						{
+							ChMatrix33<Real> res; Compute_Adt(res); return res;
+						}
+
+					/// Computes and returns an Adt matrix (-note: prefer using
+					/// Compute_Adtdt() directly for better performance)
+	ChMatrix33<Real> GetA_dtdt()
+						{
+							ChMatrix33<Real> res; Compute_Adtdt(res); return res;
+						}
+
+				// FUNCTIONS TO TRANSFORMATE THE FRAME ITSELF
+
+					/// Apply a transformation (rotation and translation) represented by
+					/// another ChFrameMoving T. This is equivalent to pre-multiply this frame
+					/// by the other frame T:   this'= T * this;  or this' = this >> T
+	void ConcatenatePreTransformation(const ChFrameMoving<Real>& T)
+						{
+							ChFrameMoving<Real> res;
+							T.TrasformLocalToParent(*this, res);
+							*this = res;
+						}
+
+					/// Apply a transformation (rotation and translation) represented by
+					/// another ChFrameMoving T in local coordinate. This is equivalent to
+					/// post-multiply this frame by the other frame T:   this'= this * T; or this' = T >> this
+	void ConcatenatePostTransformation(const ChFrameMoving<Real>& T)
+						{
+							ChFrameMoving<Real> res;
+							this->TrasformLocalToParent(T, res);
+							*this = res;
+						}
+
+
+
+
+				// FUNCTIONS FOR COORDINATE TRANSFORMATIONS
+
+					/// Given the position of a point in local frame coords, and
+					/// assuming it is sticky to frame, return the speed in parent coords.
+	ChVector<Real> PointSpeedLocalToParent(const ChVector<Real>& localpos) const
+						{
+							return coord_dt.pos +
+									((coord_dt.rot % ChQuaternion<Real>(0,localpos) % this->coord.rot.GetConjugate()).GetVector()*2) ;
+						}
+
+					/// Given the position of a point in local frame coords, and
+					/// assuming it has a frame-relative speed localspeed,
+					/// return the speed in parent coords.
+	ChVector<Real> PointSpeedLocalToParent(const ChVector<Real>& localpos, const ChVector<Real>& localspeed) const
+						{
+							return coord_dt.pos +
+									this->Amatrix.Matr_x_Vect(localspeed) +
+									((coord_dt.rot % ChQuaternion<Real>(0,localpos) % this->coord.rot.GetConjugate()).GetVector()*2) ;
+						}
+
+					/// Given the position of a point in local frame coords, and
+					/// assuming it is sticky to frame, return the acceleration in parent coords.
+	ChVector<Real> PointAccelerationLocalToParent(const ChVector<Real>& localpos) const
+						{
+							return coord_dtdt.pos +
+									((coord_dtdt.rot % ChQuaternion<Real>(0,localpos) % this->coord.rot.GetConjugate()).GetVector()*2) +
+									((coord_dt.rot % ChQuaternion<Real>(0,localpos) % coord_dt.rot.GetConjugate()).GetVector()*2);
+						}
+
+					/// Given the position of a point in local frame coords, and
+					/// assuming it has a frame-relative speed localspeed and frame-relative
+					/// acceleration localacc, return the acceleration in parent coords.
+	ChVector<Real> PointAccelerationLocalToParent(const ChVector<Real>& localpos, const ChVector<Real>& localspeed, const ChVector<Real>& localacc) const
+						{
+							return coord_dtdt.pos +
+									this->Amatrix.Matr_x_Vect(localacc) +
+									((coord_dtdt.rot % ChQuaternion<Real>(0,localpos) % this->coord.rot.GetConjugate()).GetVector()*2) +
+									((coord_dt.rot % ChQuaternion<Real>(0,localpos) % coord_dt.rot.GetConjugate()).GetVector()*2) +
+									((coord_dt.rot % ChQuaternion<Real>(0,localspeed) % this->coord.rot.GetConjugate()).GetVector()*4);
+						}
+
+					/// Given the position of a point in parent frame coords, and
+					/// assuming it has an absolute speed parentspeed,
+					/// return the speed in local coords.
+	ChVector<Real> PointSpeedParentToLocal(const ChVector<Real>& parentpos, const ChVector<Real>& parentspeed) const
+						{
+							ChVector<Real> localpos = ChFrame<Real>::TrasformParentToLocal(parentpos);
+							return this->Amatrix.MatrT_x_Vect( parentspeed - coord_dt.pos -
+								((coord_dt.rot % ChQuaternion<Real>(0,localpos) % this->coord.rot.GetConjugate()).GetVector()*2) );
+						}
+
+					/// Given the position of a point in parent frame coords, and
+					/// assuming it has an absolute speed parentspeed and absolute
+					/// acceleration parentacc, return the acceleration in local coords.
+	ChVector<Real> PointAccelerationParentToLocal(const ChVector<Real>& parentpos, const ChVector<Real>& parentspeed, const ChVector<Real>& parentacc) const
+						{
+							ChVector<Real> localpos = ChFrame<Real>::TrasformParentToLocal(parentpos);
+							ChVector<Real> localspeed = PointSpeedParentToLocal(parentpos, parentspeed);
+							return this->Amatrix.MatrT_x_Vect( parentacc - coord_dtdt.pos -
+									(coord_dtdt.rot % ChQuaternion<Real>(0,localpos) % this->coord.rot.GetConjugate()).GetVector()*2 -
+									(coord_dt.rot % ChQuaternion<Real>(0,localpos) % coord_dt.rot.GetConjugate()).GetVector()*2 -
+									(coord_dt.rot % ChQuaternion<Real>(0,localspeed) % this->coord.rot.GetConjugate()).GetVector()*4  );
+						}
+
+
+
+					/// This function transforms a frame from 'this' local coordinate
+					/// system to parent frame coordinate system, and also transforms the speed
+					/// and acceleration of the frame.
+	void TrasformLocalToParent (
+								const ChFrameMoving<Real>& local,	///< frame to transform, given in local frame coordinates
+								ChFrameMoving<Real>& parent			///< transformed frame, in parent coordinates, will be stored here
+								)  const
+						{
+								// pos & rot
+								ChFrame<Real>::TrasformLocalToParent(local,parent);
+
+								// pos_dt
+								parent.coord_dt.pos = PointSpeedLocalToParent(local.coord.pos, local.coord_dt.pos);
+
+								// pos_dtdt
+								parent.coord_dtdt.pos = PointAccelerationLocalToParent(local.coord.pos, local.coord_dt.pos, local.coord_dtdt.pos);
+
+								// rot_dt
+								parent.coord_dt.rot =
+										coord_dt.rot % local.coord.rot +
+										this->coord.rot % local.coord_dt.rot;
+
+								// rot_dtdt
+								parent.coord_dtdt.rot =
+										coord_dtdt.rot % local.coord.rot +
+										(coord_dt.rot % local.coord_dt.rot)*2 +
+										this->coord.rot % local.coord_dtdt.rot;
+
+						}
+
+
+					/// This function transforms a frame from the parent coordinate
+					/// system to 'this' local frame coordinate system.
+	void TrasformParentToLocal (
+								const ChFrameMoving<Real>& parent,	///< frame to transform, given in parent coordinates
+								ChFrameMoving<Real>& local			///< transformed frame, in local coordinates, will be stored here
+								)  const
+						{
+								// pos & rot
+								ChFrame<Real>::TrasformParentToLocal(parent,local);
+
+								// pos_dt
+								local.coord_dt.pos = PointSpeedParentToLocal(parent.coord.pos, parent.coord_dt.pos);
+
+								// pos_dtdt
+								local.coord_dtdt.pos = PointAccelerationParentToLocal(parent.coord.pos, parent.coord_dt.pos, parent.coord_dtdt.pos);
+
+								// rot_dt
+								local.coord_dt.rot = this->coord.rot.GetConjugate() %
+									(parent.coord_dt.rot - coord_dt.rot % local.coord.rot);
+
+								// rot_dtdt
+								local.coord_dtdt.rot =  this->coord.rot.GetConjugate() %
+										(parent.coord_dtdt.rot - coord_dtdt.rot % local.coord.rot - (coord_dt.rot % local.coord_dt.rot)*2 );
+						}
+
+
+				// OTHER FUNCTIONS
+
+					/// Returns true if coordsys is identical to other coordsys
+	bool	Equals ( const ChFrameMoving<Real>& other) const { return this->coord.Equals(other.coord) && coord_dt.Equals(other.coord_dt) && coord_dtdt.Equals(other.coord_dtdt);}
+
+					/// Returns true if coordsys is equal to other coordsys, within a tolerance 'tol'
+	bool	Equals ( const ChFrameMoving<Real>& other, Real tol) const { return this->coord.Equals(other.coord,tol) && coord_dt.Equals(other.coord_dt,tol) && coord_dtdt.Equals(other.coord_dtdt,tol);}
+
+
+					/// The trasformation (also for speeds, accelerations) is
+					/// inverted in place.
+					/// That is if w=A*v, then A.Invert();v=A*w;
+	virtual void Invert()
+						{
+							static ChFrameMoving<Real> tmp;
+							static ChFrameMoving<Real> unit;
+							tmp = *this;
+							tmp.TrasformParentToLocal(unit, *this);
+						}
+
+	ChFrameMoving<Real> GetInverse()
+						{
+							ChFrameMoving<Real> tmp(*this);
+							tmp.Invert(); return tmp;
+						}
+			//
+			// STREAMING
+			//
+
+
+					/// Method to allow serializing transient data into in ascii
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii& mstream)
+						{
+							ChFrame<Real>::StreamOUT(mstream);
+							ChVector<Real> mwl = GetWvel_loc();
+							ChVector<Real> mal = GetWacc_loc();
+							mstream << "\n   speed:     "<<  coord_dt.pos.x << "  " <<  coord_dt.pos.y << "  " <<  coord_dt.pos.z;
+							mstream << "\n   ang.speed: "<<  mwl.x << "  " <<  mwl.y << "  " <<  mwl.z;
+							mstream << "\n   accel:     "<<  coord_dtdt.pos.x << "  " <<  coord_dtdt.pos.y << "  " <<  coord_dtdt.pos.z;
+							mstream << "\n   ang.accel: "<<  mal.x << "  " <<  mal.y << "  " <<  mal.z;
+							mstream << "\n ";
+						}
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream)
+						{
+							// Serialize parent class
+							ChFrame<Real>::StreamOUT(mstream);
+
+							// Serialize other data
+							mstream << coord_dt;
+							mstream << coord_dtdt;
+						}
+
+					/// Operator to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream)
+						{
+							// Deserialize parent class
+							ChFrame<Real>::StreamIN(mstream);
+
+							// Deserialize other data
+							mstream >> coord_dt;
+							mstream >> coord_dtdt;
+						}
+
+
+};
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChFrame.h
diff --git a/SRC/ChronoEngine/core/ChHashFunction.h b/SRC/ChronoEngine/core/ChHashFunction.h
new file mode 100644
index 0000000..95ebacc
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChHashFunction.h
@@ -0,0 +1,125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHHASHFUNCTION__H
+#define CHHASHFUNCTION__H
+
+//////////////////////////////////////////////////
+//
+//   ChHashFunction.h
+//
+//   Basic hash function to be used with the 
+//   ChHashTable class. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <string>
+#include "core/ChLog.h"
+
+
+namespace chrono
+{
+
+// Note.
+// Hash functions to be used with the ChHashTable do NOT need to
+// return the result wrapped in the 0..maxValue range (where maxValue
+// is the number of bins in table) because this will be automatically done 
+// by the ChHashTable.
+
+
+
+/// A very simple hash function for integer keys and such..
+///
+
+template <class K>
+struct HashFunction_Generic
+{
+	unsigned operator()(const K key) const 
+	{ 
+		return key * 0xf4243;  // no need to wrap with ... % maxValue;
+	}
+};
+
+
+/// Specialized hash function for strings
+///
+
+struct HashFunction_String1
+{
+	unsigned operator()(const std::string& key) const 
+	{ 
+		unsigned h = 0;
+		for (unsigned int i = 0; i < key.length(); ++i)
+		{
+			h = h * 0xf4243 ^ key[i];
+		}
+		return h;
+	}
+};
+
+
+
+/// Specialized hash function for strings (other version)
+///
+
+struct HashFunction_String2
+{
+	unsigned operator()(const std::string& key) const 
+	{ 
+		unsigned int n = key.length();
+		const char* d = key.c_str();
+		unsigned h = 0; 
+	      
+		for (unsigned int i = 0; i < n; ++i, ++d)
+			  h = (h << 2) + *d;
+
+		return ((h >= 0) ? (h ) : (-h ));
+	}
+};
+
+
+
+/// Specialized hash function for strings (other version)
+///
+
+struct HashFunction_String3
+{
+	unsigned operator()(const std::string& key) const 
+	{ 
+		int n = key.length();
+		const char* d = key.c_str();
+		long h = n; 
+      
+		for (int i = 0; i < n; ++i, ++d)
+			h = 613*h + *d;
+
+		return ((h >= 0) ? (h ) : (-h )); 
+	}
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChHashFunction.h
diff --git a/SRC/ChronoEngine/core/ChHashTable.h b/SRC/ChronoEngine/core/ChHashTable.h
new file mode 100644
index 0000000..cf292dc
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChHashTable.h
@@ -0,0 +1,920 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHHASHTABLE__H
+#define CHHASHTABLE__H
+
+//////////////////////////////////////////////////
+//
+//   ChHashTable.h
+//
+//   A simple chained hash table.
+//
+//   This hash table is inspired by the hash code in
+//   the STLplus code - see Andy Rushton, 2004, 
+//   but it is adapted to the needs of the  core
+//   Chrono::Engine SDK.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChException.h"
+#include "ChHashFunction.h"
+
+namespace chrono
+{
+
+
+
+// Forward declarations
+
+template<typename K, typename T, class H, class E, typename V>class ch_hash_iterator;
+template<typename K, typename T> class hash_element;
+
+
+
+
+
+/// The ChHashTable class. This container is most useful when you need
+/// a quasi-constant-time retrieval of a value, given its key. In fact,
+/// this container stores 'pairs' of values-keys, where keys should be 
+/// unique (an example: a key could be the credit card number, and the 
+/// value could be a structure with name, age and address of the credit 
+/// card owner). 
+/// When the hash table is filled too much, the performance get worse.
+/// Also, when you fill it beyond the initial suggested number of bins, 
+/// an automatic table resizing (with rehashing) is performed. This may
+/// be a time-consuming cpu operation! So, choose initial size as close
+/// as possible to the maximum number of elements that you foresee to 
+/// insert, plus some more space (es: +50%) to avoid performance degradation.
+///
+/// K = key type
+/// T = value type
+/// H = hash function object with the profile 'unsigned H(const K&)'
+/// E = equal function object with the profile 'bool E(const K&, const K&)' defaults to equal_to which in turn calls '=='
+
+template<typename K, typename T, class H = HashFunction_Generic<K>, class E = std::equal_to<K> >
+class ChHashTable
+{
+public:
+  typedef unsigned                                size_type;
+  typedef K                                       key_type;
+  typedef T                                       data_type;
+  typedef T                                       mapped_type;
+  typedef std::pair<const K, T>                   value_type;
+  typedef ch_hash_iterator<K,T,H,E,value_type>       iterator;
+  typedef ch_hash_iterator<K,T,H,E,const value_type> const_iterator;
+
+		/// Construct a ChHashTable table with specified number of bins.
+		/// The default 0 bins means leave it to the table to decide.
+		/// Specifying 0 bins also enables auto-rehashing, otherwise auto-rehashing defaults off
+  ChHashTable(unsigned bins = 0);
+  ~ChHashTable(void);
+
+		/// Copy and equality copy the data elements but not the size of the copied table
+  ChHashTable(const ChHashTable&);
+  ChHashTable& operator = (const ChHashTable&);
+
+		/// Test for an empty table and for the size of a table
+		/// Efficient because the size is stored separately from the table contents
+  bool empty(void) const;
+  unsigned size(void) const;
+
+		/// Test for equality - two hashes are equal if they contain equal values
+  bool operator == (const ChHashTable&) const;
+  bool operator != (const ChHashTable&) const;
+
+		/// Switch auto-rehash on
+  void auto_rehash(void);
+		/// Switch auto-rehash off
+  void manual_rehash(void);
+		/// Force a rehash now
+		/// Default of 0 means implement built-in size calculation for rehashing 
+		/// (recommended - it doubles the number of bins)
+  void rehash(unsigned bins = 0);
+
+		/// Test the loading ratio, which is the size divided by the number of bins.
+		/// Use this if you are doing your own rehashing.
+  float loading(void) const;
+
+
+		/// Test for the presence of a key
+  bool present(const K& key) const;
+
+		/// Provide map equivalent key count function (0 or 1, as not a multimap)
+  size_type count(const K& key) const;
+
+		/// Insert a new key/data pair - replaces any previous value for this key
+  iterator insert(const K& key, const T& data);
+  
+		/// Insert a copy of the pair into the table (std::map compatible)
+  std::pair<iterator, bool> insert(const value_type& value);
+
+		/// Insert a new key and return the iterator so that the data can be filled in
+  iterator insert(const K& key);
+
+		/// Remove a key/data pair from the hash table
+  bool erase(const K& key);
+		
+		/// Remove all elements from the hash table
+  void erase(void);
+
+		/// Provide the std::map equivalent clear function
+  void clear(void);
+
+		/// Find a key and return an iterator to it
+		/// The iterator is like a pointer to a pair<const K,T>
+		/// end() is returned if the find fails
+  const_iterator find(const K& key) const;
+  iterator find(const K& key);
+
+		/// Returns the data corresponding to the key
+		/// the const version is used by the compiler on const hashes and cannot change the hash, so find failure causes an exception
+		/// the non-const version is used by the compiler on non-const hashes and is like map - it creates a new key/data pair if find fails
+  const T& operator[] (const K& key) const;
+  T& operator[] (const K& key);
+
+		/// Iterators allow the hash table to be traversed
+		/// Iterators remain valid unless an item is removed or unless a rehash happens
+  const_iterator begin(void) const;
+  iterator begin(void);
+  const_iterator end(void) const;
+  iterator end(void);
+
+		
+private:
+		
+	//
+	// DATA
+	//
+
+  friend class hash_element<K,T>;
+  friend class ch_hash_iterator<K,T,H,E,std::pair<const K,T> >;
+  friend class ch_hash_iterator<K,T,H,E,const std::pair<const K,T> >;
+
+  unsigned m_rehash;
+  unsigned m_bins;
+  unsigned m_size;
+  hash_element<K,T>** m_values;
+};
+
+
+
+
+
+
+
+//
+// Iterator class for the ChHashTable class
+//
+
+template<typename K, typename T, class H, class E, typename V>
+class ch_hash_iterator
+{
+public:
+  friend class ChHashTable<K,T,H,E>;
+
+	  // Local type definitions
+	  // An iterator points to a value whilst a const_iterator points to a const value
+  typedef V                                                  value_type;
+  typedef ch_hash_iterator<K,T,H,E,std::pair<const K,T> >       iterator;
+  typedef ch_hash_iterator<K,T,H,E,const std::pair<const K,T> > const_iterator;
+  typedef ch_hash_iterator<K,T,H,E,V>                           this_iterator;
+  typedef V&                                                 reference;
+  typedef V*                                                 pointer;
+
+	  /// Constructor to create a null iterator - you must assign a valid value to 
+	  /// this iterator before using it
+	  /// Any attempt to dereference or use a null iterator is an error
+	  /// the only valid thing you can do is assign an iterator to it
+  ch_hash_iterator(void);
+
+      /// Destructor
+  ~ch_hash_iterator(void);
+
+
+	  /// A null iterator is one that has not been initialised with a value yet
+	  /// i.e. you just declared it but didn't assign to it
+  bool null(void) const;
+
+	  /// An end iterator is one that points to the end element of the list of nodes
+	  /// in STL conventions this is one past the last valid element and must not be dereferenced
+  bool end(void) const;
+
+	  /// A valid iterator is one that can be dereferenced
+	  /// i.e. non-null and non-end
+  bool valid(void) const;
+
+	  /// Get the hash container that created this iterator
+	  /// a null iterator doesn't have an owner so returns a null pointer
+  const ChHashTable<K,T,H,E>* owner(void) const;
+
+	  /// Type conversion methods allow const_iterator and iterator to be converted
+	  /// convert an iterator/const_iterator to a const_iterator
+  const_iterator constify(void) const;
+
+	  /// Convert an iterator/const_iterator to an iterator
+  iterator deconstify(void) const;
+
+	  /// increment operators used to step through the set of all values in a hash
+	  /// it is only legal to increment a valid iterator
+	  /// there's no decrement - I've only implemented this as a unidirectional iterator
+	  /// pre-increment.
+	  /// Throws ChException if unsuccesful.
+  this_iterator& operator ++ (void);
+
+	  /// Post-increment
+	  /// Throws ChException if unsuccesful.
+  this_iterator operator ++ (int);
+  
+	  /// Tests, for putting iterators into other STL structures and 
+	  /// for testing whether iteration has completed.
+  bool operator == (const this_iterator& r) const;
+  bool operator != (const this_iterator& r) const;
+  bool operator < (const this_iterator& r) const;
+
+	  /// Access the value - a const_iterator gives you a const value, an iterator a non-const value
+	  /// it is illegal to dereference an invalid (i.e. null or end) iterator
+  reference operator*(void) const;
+  pointer operator->(void) const;
+
+  
+private:
+  friend class hash_element<K,T>;
+
+  const ChHashTable<K,T,H,E>* m_owner;
+  unsigned m_bin;
+  hash_element<K,T>* m_element;
+
+  void check_owner(const ChHashTable<K,T,H,E>* owner) const;
+
+  void check_non_null(void) const;
+
+  void check_non_end(void) const;
+
+  void check_valid(void) const;
+
+  void check(const ChHashTable<K,T,H,E>* owner) const;
+
+  // Constructor used by ChHashTable.
+  // (You cannot create a valid iterator except by calling a ChHashTable method that returns one)
+  ch_hash_iterator(const ChHashTable<K,T,H,E>* owner, unsigned bin, hash_element<K,T>* element);
+};
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// the element stored in the ChHashTable
+
+template<typename K, typename T>
+class hash_element
+{
+public:
+  std::pair<const K, T> m_value;
+  hash_element<K,T>* m_next;
+  unsigned m_hash;
+
+  hash_element(const K& key, const T& data, unsigned hash) : m_value(key,data), m_next(0), m_hash(hash) {}
+  hash_element(const std::pair<const K,T>& value, unsigned hash) : m_value(value), m_next(0), m_hash(hash) {}
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// iterator
+
+// checks
+
+template<typename K, typename T, class H, class E, typename V>
+void ch_hash_iterator<K,T,H,E,V>::check_owner(const ChHashTable<K,T,H,E>* owner) const
+{
+  if (owner != m_owner)
+    throw ChException("hash iterator");
+}
+
+template<typename K, typename T, class H, class E, typename V>
+void ch_hash_iterator<K,T,H,E,V>::check_non_null(void) const
+{
+  if (null())
+    throw ChException("hash iterator");
+}
+
+template<typename K, typename T, class H, class E, typename V>
+void ch_hash_iterator<K,T,H,E,V>::check_non_end(void) const
+{
+  if (end())
+    throw ChException("hash iterator");
+}
+ 
+template<typename K, typename T, class H, class E, typename V>
+void ch_hash_iterator<K,T,H,E,V>::check_valid(void) const
+{
+  check_non_null();
+  check_non_end(); 
+}
+
+template<typename K, typename T, class H, class E, typename V>
+void ch_hash_iterator<K,T,H,E,V>::check(const ChHashTable<K,T,H,E>* owner) const
+{
+  check_valid();
+  if (owner) check_owner(owner);
+}
+
+// null constructor
+
+template<typename K, typename T, class H, class E, typename V>
+ch_hash_iterator<K,T,H,E,V>::ch_hash_iterator(void) :
+  m_owner(0), m_bin(0), m_element(0) 
+{
+}
+
+// this iterator points to a specific element and so allows an iterator to be constructed from a list node
+// if the bin is set to bins and the element to null, then this is an end() iterator
+// if the element parameter is null it scans for the first element so implements the begin() behaviour
+// if the ChHashTable is empty, m_bin gets set to m_bins, so this becomes an end() iterator
+
+template<typename K, typename T, class H, class E, typename V>
+ch_hash_iterator<K,T,H,E,V>::ch_hash_iterator(const ChHashTable<K,T,H,E>* owner, unsigned bin, hash_element<K,T>* element) :
+  m_owner(owner), m_bin(bin), m_element(element)
+{
+  //DEBUG_ASSERT(owner);
+  if (!element)
+  {
+    for (; m_bin < m_owner->m_bins; m_bin++)
+    {
+      if (m_owner->m_values[m_bin])
+      {
+        m_element = m_owner->m_values[m_bin];
+        break;
+      }
+    }
+  }
+}
+
+// destructor
+
+template<typename K, typename T, class H, class E, typename V>
+ch_hash_iterator<K,T,H,E,V>::~ch_hash_iterator(void)
+{
+}
+
+// validity tests
+
+template<typename K, typename T, class H, class E, typename V>
+bool ch_hash_iterator<K,T,H,E,V>::null(void) const
+{
+  return m_owner == 0;
+}
+
+template<typename K, typename T, class H, class E, typename V>
+bool ch_hash_iterator<K,T,H,E,V>::end(void) const
+{
+  if (null()) return false;
+  return (m_bin == m_owner->m_bins) && m_element == 0;
+}
+
+template<typename K, typename T, class H, class E, typename V>
+bool ch_hash_iterator<K,T,H,E,V>::valid(void) const
+{
+  return !null() && !end();
+}
+
+// owner method
+
+template<typename K, typename T, class H, class E, typename V>
+const ChHashTable<K,T,H,E>* ch_hash_iterator<K,T,H,E,V>::owner(void) const
+{
+  return m_owner;
+}
+
+// mode conversions
+
+template<typename K, typename T, class H, class E, typename V>
+typename ch_hash_iterator<K,T,H,E,V>::const_iterator ch_hash_iterator<K,T,H,E,V>::constify(void) const
+{
+  return ch_hash_iterator<K,T,H,E,V>::const_iterator(m_owner, m_bin, m_element);
+}
+
+template<typename K, typename T, class H, class E, typename V>
+typename ch_hash_iterator<K,T,H,E,V>::iterator ch_hash_iterator<K,T,H,E,V>::deconstify(void) const
+{
+  return ch_hash_iterator<K,T,H,E,V>::iterator(m_owner, m_bin, m_element);
+}
+
+// increment operator looks for the next element in the table
+// if there isn't one, then this becomes an end() iterator - m_bin = m_bins and m_element = null
+
+template<typename K, typename T, class H, class E, typename V>
+typename ch_hash_iterator<K,T,H,E,V>::this_iterator& ch_hash_iterator<K,T,H,E,V>::operator ++ (void)
+{
+  check_valid();
+  if (m_element->m_next)
+    m_element = m_element->m_next;
+  else
+  {
+    // failing that, subsequent hash values are tried until either an element is found or there are no more bins
+    // in which case it becomes an end() iterator (bin == bins and element = null)
+    m_element = 0;
+    if (m_bin < m_owner->m_bins)
+    {
+      for(m_bin++; m_bin < m_owner->m_bins; m_bin++)
+      {
+        if (m_owner->m_values[m_bin])
+        {
+          m_element = m_owner->m_values[m_bin];
+          break;
+        }
+      }
+    }
+  }
+  return *this;
+}
+
+// post-increment is defined in terms of pre-increment
+
+template<typename K, typename T, class H, class E, typename V>
+typename ch_hash_iterator<K,T,H,E,V>::this_iterator ch_hash_iterator<K,T,H,E,V>::operator ++ (int)
+{
+  typename ch_hash_iterator<K,T,H,E,V>::this_iterator old = *this;
+  ++(*this);
+  return old;
+}
+
+// two iterators are equal if they point to the same element
+// both iterators must be non-null and belong to the same table
+
+template<typename K, typename T, class H, class E, typename V>
+bool ch_hash_iterator<K,T,H,E,V>::operator == (const ch_hash_iterator<K,T,H,E,V>& r) const
+{
+  return m_element == r.m_element;
+}
+
+template<typename K, typename T, class H, class E, typename V>
+bool ch_hash_iterator<K,T,H,E,V>::operator != (const ch_hash_iterator<K,T,H,E,V>& r) const
+{
+  return !operator==(r);
+}
+
+template<typename K, typename T, class H, class E, typename V>
+bool ch_hash_iterator<K,T,H,E,V>::operator < (const ch_hash_iterator<K,T,H,E,V>& r) const
+{
+  return m_element < r.m_element;
+}
+
+// iterator dereferencing is only legal on a non-null iterator
+
+template<typename K, typename T, class H, class E, typename V>
+V& ch_hash_iterator<K,T,H,E,V>::operator*(void) const
+{
+  check_valid();
+  return m_element->m_value;
+}
+
+template<typename K, typename T, class H, class E, typename V>
+V* ch_hash_iterator<K,T,H,E,V>::operator->(void) const
+{
+  check_valid();
+  return &(m_element->m_value);
+}
+
+
+
+
+
+
+
+
+//
+//  ChHashTable
+// 
+
+
+
+
+
+// totally arbitrary initial size used for auto-rehashed tables
+static unsigned hash_default_bins = 127;
+
+// constructor
+// tests whether the user wants auto-rehash
+// sets the rehash point to be a loading of 1.0 by setting it to the number of bins
+// uses the user's size unless this is zero, in which case implement the default
+
+template<typename K, typename T, class H, class E>
+ChHashTable<K,T,H,E>::ChHashTable(unsigned bins) :
+  m_rehash(bins), m_bins(bins > 0 ? bins : hash_default_bins), m_size(0), m_values(0)
+{ 
+  m_values = new hash_element<K,T>*[m_bins];
+  for (unsigned i = 0; i < m_bins; i++)
+    m_values[i] = 0;
+}
+
+template<typename K, typename T, class H, class E>
+ChHashTable<K,T,H,E>::~ChHashTable(void)
+{
+  // delete all the elements
+  clear();
+  // and delete the data structure
+  delete[] m_values;
+  m_values = 0;
+}
+
+// as usual, implement the copy constructor i.t.o. the assignment operator
+
+template<typename K, typename T, class H, class E>
+ChHashTable<K,T,H,E>::ChHashTable(const ChHashTable<K,T,H,E>& right) :
+  m_rehash(right.m_rehash), m_bins(right.m_bins), m_size(0), m_values(0)
+{
+  m_values = new hash_element<K,T>*[right.m_bins];
+  // copy the rehash behaviour as well as the size
+  for (unsigned i = 0; i < m_bins; i++)
+    m_values[i] = 0;
+  *this = right;
+}
+
+// assignment operator
+// this is done by copying the elements
+// the source and target hashes can be different sizes
+// the hash is self-copy safe, i.e. it is legal to say x = x;
+
+template<typename K, typename T, class H, class E>
+ChHashTable<K,T,H,E>& ChHashTable<K,T,H,E>::operator = (const ChHashTable<K,T,H,E>& r)
+{
+  // make self-copy safe
+  if (&r == this) return *this;
+  // remove all the existing elements
+  clear();
+  // copy the elements across - remember that this is rehashing because the two
+  // tables can be different sizes so there is no quick way of doing this by
+  // copying the lists
+  for (typename ChHashTable<K,T,H,E>::const_iterator i = r.begin(); i != r.end(); ++i)
+    insert(i->first, i->second);
+  return *this;
+}
+
+// number of values in the hash
+
+template<typename K, typename T, class H, class E>
+bool ChHashTable<K,T,H,E>::empty(void) const
+{
+  return m_size == 0;
+}
+
+template<typename K, typename T, class H, class E>
+unsigned ChHashTable<K,T,H,E>::size(void) const
+{
+  return m_size;
+}
+
+// equality
+
+template<typename K, typename T, class H, class E>
+bool ChHashTable<K,T,H,E>::operator == (const ChHashTable<K,T,H,E>& right) const
+{
+  // this table is the same as the right table if they are the same table!
+  if (&right == this) return true;
+  // they must be the same size to be equal
+  if (m_size != right.m_size) return false;
+  // now every key in this must be in right and have the same data
+  for (typename ChHashTable<K,T,H,E>::const_iterator i = begin(); i != end(); i++)
+  {
+    typename ChHashTable<K,T,H,E>::const_iterator found = right.find(i->first);
+    if (found == right.end()) return false;
+    if (!(i->second == found->second)) return false;
+  }
+  return true;
+}
+
+template<typename K, typename T, class H, class E>
+bool ChHashTable<K,T,H,E>::operator != (const ChHashTable<K,T,H,E>& right) const
+{
+  return !operator==(right);
+}
+
+// set up the ChHashTable to auto-rehash at a specific size
+// setting the rehash size to 0 forces manual rehashing
+
+template<typename K, typename T, class H, class E>
+void ChHashTable<K,T,H,E>::auto_rehash(void)
+{
+  m_rehash = m_bins;
+}
+
+template<typename K, typename T, class H, class E>
+void ChHashTable<K,T,H,E>::manual_rehash(void)
+{
+  m_rehash = 0;
+}
+
+// the rehash function
+// builds a new hash table and moves the elements (without copying) from the old to the new
+// I store the un-modulused hash value in the element for more efficient rehashing
+// passing 0 to the bins parameter does auto-rehashing
+// passing any other value forces the number of bins
+
+template<typename K, typename T, class H, class E>
+void ChHashTable<K,T,H,E>::rehash(unsigned bins)
+{
+  // user specified size: just take the user's value
+  // auto calculate: if the load is high, increase the size; else do nothing
+  unsigned new_bins = bins ? bins : m_bins;
+  if (bins == 0 && m_size > 0)
+  {
+    // these numbers are pretty arbitrary
+    // TODO - make them user-customisable?
+    float load = loading();
+    if (load > 2.0)
+      new_bins = (unsigned)(m_bins * load);
+    else if (load > 1.0)
+      new_bins = m_bins * 2;
+  }
+  if (new_bins == m_bins) return;
+  // set the new rehashing point if auto-rehashing is on
+  if (m_rehash) m_rehash = new_bins;
+  // move aside the old structure
+  hash_element<K,T>** old_values = m_values;
+  unsigned old_bins = m_bins;
+  // create a replacement structure
+  m_values = new hash_element<K,T>*[new_bins];
+  for (unsigned i = 0; i < new_bins; i++)
+    m_values[i] = 0;
+  m_bins = new_bins;
+  // move all the old elements across, rehashing each one
+  for (unsigned j = 0; j < old_bins; j++)
+  {
+    while(old_values[j])
+    {
+      // unhook from the old structure
+      hash_element<K,T>* current = old_values[j];
+      old_values[j] = current->m_next;
+      // rehash using the stored un-modulused hash value
+      unsigned hash_value = current->m_hash % m_bins;
+      // hook it into the new structure
+      current->m_next = m_values[hash_value];
+      m_values[hash_value] = current;
+    }
+  }
+  // now delete the old structure
+  delete[] old_values;
+}
+
+// the loading is the average number of elements per bin
+// this simplifies to the total elements divided by the number of bins
+
+template<typename K, typename T, class H, class E>
+float ChHashTable<K,T,H,E>::loading(void) const
+{
+  return (float)m_size / (float)m_bins;
+}
+
+// remove all elements from the table
+
+template<typename K, typename T, class H, class E>
+void ChHashTable<K,T,H,E>::erase(void)
+{
+  // unhook the list elements and destroy them
+  for (unsigned i = 0; i < m_bins; i++)
+  {
+    hash_element<K,T>* current = m_values[i];
+    while(current)
+    {
+      hash_element<K,T>* next = current->m_next;
+      delete current;
+      current = next;
+    }
+    m_values[i] = 0;
+  }
+  m_size = 0;
+}
+
+// test for whether a key is present in the table
+
+template<typename K, typename T, class H, class E>
+bool ChHashTable<K,T,H,E>::present(const K& key) const
+{
+  return find(key) != end();
+}
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::size_type ChHashTable<K,T,H,E>::count(const K& key) const
+{
+  return present() ? 1 : 0;
+}
+
+// add a key and data element to the table - defined in terms of the general-purpose pair insert function
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::iterator ChHashTable<K,T,H,E>::insert(const K& key, const T& data)
+{
+  return insert(std::pair<const K,T>(key,data)).first;
+}
+
+// insert a key/data pair into the table
+// this removes any old value with the same key since there is no multihash functionality
+
+template<typename K, typename T, class H, class E>
+std::pair<typename ChHashTable<K,T,H,E>::iterator, bool> ChHashTable<K,T,H,E>::insert(const std::pair<const K,T>& value)
+{
+  // if auto-rehash is enabled, implement the auto-rehash before inserting the new value
+  // the table is rehashed if this insertion makes the loading exceed 1.0
+  if (m_rehash && (m_size >= m_rehash)) rehash();
+  // calculate the new hash value
+  unsigned hash_value_full = H()(value.first);
+  unsigned hash_value = hash_value_full % m_bins;
+  bool inserted = true;
+  // unhook any previous value with this key
+  // this has been inlined from erase(key) so that the hash value is not calculated twice
+  hash_element<K,T>* previous = 0;
+  for (hash_element<K,T>* current = m_values[hash_value]; current; previous = current, current = current->m_next)
+  {
+    // first check the full stored hash value
+    if (current->m_hash != hash_value_full) continue;
+
+    // next try the equality operator
+    if (!E()(current->m_value.first, value.first)) continue;
+
+    // unhook this value and destroy it
+    if (previous)
+      previous->m_next = current->m_next;
+    else
+      m_values[hash_value] = current->m_next;
+    delete current;
+    m_size--;
+
+    // we've overwritten a previous value
+    inserted = false;
+    
+    // assume there can only be one match so we can give up now
+    break;
+  }
+  // now hook in a new list element at the start of the list for this hash value
+  hash_element<K,T>* new_item = new hash_element<K,T>(value, hash_value_full);
+  new_item->m_next = m_values[hash_value];
+  m_values[hash_value] = new_item;
+  // remember to increment the size count
+  m_size++;
+  // construct an iterator from the list node, and return whether inserted
+  return std::make_pair(typename ChHashTable<K,T,H,E>::iterator(this,hash_value,new_item), inserted);
+}
+
+// insert a key with an empty data field ready to be filled in later
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::iterator ChHashTable<K,T,H,E>::insert(const K& key)
+{
+  return insert(key,T());
+}
+
+// remove a key from the table - return true if the key was found and removed, false if it wasn't present
+
+template<typename K, typename T, class H, class E>
+bool ChHashTable<K,T,H,E>::erase(const K& key)
+{
+  unsigned hash_value_full = H()(key);
+  unsigned hash_value = hash_value_full % m_bins;
+  // scan the list for an element with this key
+  // need to keep a previous pointer because the lists are single-linked
+  hash_element<K,T>* previous = 0;
+  for (hash_element<K,T>* current = m_values[hash_value]; current; previous = current, current = current->m_next)
+  {
+    // first check the full stored hash value
+    if (current->m_hash != hash_value_full) continue;
+    
+    // next try the equality operator
+    if (!E()(current->m_value.first, key)) continue;
+
+    // found this key, so unhook the element from the list
+    if (previous)
+      previous->m_next = current->m_next;
+    else
+      m_values[hash_value] = current->m_next;
+    // destroy it
+    delete current;
+    // remember to maintain the size count
+    m_size--;
+    return true;
+  }
+  return false;
+}
+
+
+template<typename K, typename T, class H, class E>
+void ChHashTable<K,T,H,E>::clear(void)
+{
+  erase();
+}
+
+// search for a key in the table and return an iterator to it
+// if the search fails, returns an end() iterator
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::const_iterator ChHashTable<K,T,H,E>::find(const K& key) const
+{
+  // scan the list for this key's hash value for the element with a matching key
+  unsigned hash_value_full = H()(key);
+  unsigned hash_value = hash_value_full % m_bins;
+  for (hash_element<K,T>* current = m_values[hash_value]; current; current = current->m_next)
+  {
+    if (current->m_hash == hash_value_full && E()(current->m_value.first, key))
+      return typename ChHashTable<K,T,H,E>::const_iterator(this, hash_value, current);
+  }
+  return end();
+}
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::iterator ChHashTable<K,T,H,E>::find(const K& key)
+{
+  // scan the list for this key's hash value for the element with a matching key
+  unsigned hash_value_full = H()(key);
+  unsigned hash_value = hash_value_full % m_bins;
+  for (hash_element<K,T>* current = m_values[hash_value]; current; current = current->m_next)
+  {
+    if (current->m_hash == hash_value_full && E()(current->m_value.first, key))
+      return typename ChHashTable<K,T,H,E>::iterator(this, hash_value, current);
+  }
+  return end();
+}
+
+// table lookup by key using the index operator[], returning a reference to the data field, not an iterator
+// this is rather like the std::map's [] operator
+// the difference is that I have a const and non-const version
+// the const version will not create the element if not present already, but the non-const version will
+// the non-const version is compatible with the behaviour of the map
+
+template<typename K, typename T, class H, class E>
+const T& ChHashTable<K,T,H,E>::operator[] (const K& key) const
+{
+  // this const version cannot change the hash, so has to raise an exception if the key is missing
+  // TODO make this a proper exception with a throw declaration
+  typename ChHashTable<K,T,H,E>::const_iterator found = find(key);
+  DEBUG_ASSERT(found != end());
+  return found->second;
+}
+
+template<typename K, typename T, class H, class E>
+T& ChHashTable<K,T,H,E>::operator[] (const K& key)
+{
+  // this non-const version can change the ChHashTable, so creates a new element if the key is missing
+  typename ChHashTable<K,T,H,E>::iterator found = find(key);
+  if (found == end())
+    found = insert(key);
+  return found->second;
+}
+
+// iterators
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::const_iterator ChHashTable<K,T,H,E>::begin(void) const
+{
+  return typename ChHashTable<K,T,H,E>::const_iterator(this,0,0);
+}
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::iterator ChHashTable<K,T,H,E>::begin(void)
+{
+  return typename ChHashTable<K,T,H,E>::iterator(this,0,0);
+}
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::const_iterator ChHashTable<K,T,H,E>::end(void) const
+{
+  return typename ChHashTable<K,T,H,E>::const_iterator(this,m_bins,0);
+}
+
+template<typename K, typename T, class H, class E>
+typename ChHashTable<K,T,H,E>::iterator ChHashTable<K,T,H,E>::end(void)
+{
+  return typename ChHashTable<K,T,H,E>::iterator(this,m_bins,0);
+}
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChHashTable.h
diff --git a/SRC/ChronoEngine/core/ChLinearAlgebra.h b/SRC/ChronoEngine/core/ChLinearAlgebra.h
new file mode 100644
index 0000000..c5be01b
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChLinearAlgebra.h
@@ -0,0 +1,944 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2008, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINEARALGEBRA_H
+#define CHLINEARALGEBRA_H
+
+//////////////////////////////////////////////////
+//  
+//   ChLinearAlgebra.h
+//
+//   Math functions for :
+//      - LINEAR ALGEBRA
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "core/ChMatrix.h"
+
+
+#define PIVOT_ACCEPT_TRESHOLD 0.8
+#define ACCEPT_PIVOT	0.001
+#define MIN_PIVOT  0.00000001
+#define INFINITE_PIVOT  1.e+34
+
+#define EIG_ROTATE(a,i,j,k,l) g=a->Get33Element(i,j); h=a->Get33Element(k,l); a->Set33Element(i,j,g-s*(h+g*tau)); a->Set33Element(k,l,h+s*(g-h*tau));
+
+namespace chrono
+{
+
+
+
+
+//template <class Real = double>
+class ChLinearAlgebra 
+{
+
+public:
+
+					/// Gets the best row index to swap with the "i"current, i.e
+					/// the one with highest element in the "i" column.				
+	static int BestPivotRow (ChMatrix<>& A, int current)
+	{
+		double temp = 0;
+		int i;
+		int pivotrow = current;
+
+		for (i = current; i < A.GetRows(); i++)
+		{
+			if (fabs(A.GetElement (i,current)) > temp)
+			{
+				temp = fabs(A.GetElement (i,current));
+				pivotrow = i;
+			}
+			if (temp >= PIVOT_ACCEPT_TRESHOLD) break;
+		}
+		return pivotrow;
+	}
+
+					/// Gets the best row-col index to swap with the "i"current, 
+					/// using the diagonal pivot.
+	static int BestPivotDiag (ChMatrix<>& A, int current)
+	{
+		double temp = 0;
+		int i;
+		int pivotrow = current;
+
+		for (i = current; i < A.GetRows(); i++)
+		{
+			if (fabs(A.GetElement (i,i)) > temp)
+			{
+				temp = fabs(A.GetElement (i,i));
+				pivotrow = i;
+			}
+			if (temp >= PIVOT_ACCEPT_TRESHOLD) break;
+		}
+		return pivotrow;
+	}
+
+
+					/// Performs a diagonal pivot on a generic square matrix.
+	static void DiagPivot(ChMatrix<>& A, int rowA, int rowB)
+	{
+		A.SwapColumns (rowA, rowB);
+		A.SwapRows (rowA,rowB);
+	}
+
+					/// Performs a diagonal pivot on a _symmetric_ square matrix,
+					/// acting only on the _UPPER_ triangle, for storage convenience
+					/// and speed optimizations.
+	static void DiagPivotSymmetric(ChMatrix<>& A, int rowA, int rowB)
+	{
+		int elcol, elrow;
+		double temp;
+		for (elrow=0; elrow<rowA; elrow++)
+		{
+			temp = A.GetElement(elrow, rowA);
+			A.SetElement(elrow,rowA, A.GetElement(elrow, rowB));
+			A.SetElement(elrow,rowB, temp);
+		}
+		for (elcol=rowB+1; elcol< A.GetColumns(); elcol++)
+		{
+			temp = A.GetElement(rowA, elcol);
+			A.SetElement(rowA, elcol, A.GetElement(rowB, elcol));
+			A.SetElement(rowB, elcol, temp);
+		}
+		for (elcol=rowA+1; elcol<rowB; elcol++)
+		{
+			temp = A.GetElement(rowA, elcol);
+			A.SetElement(rowA, elcol, A.GetElement(elcol,rowB));
+			A.SetElement(elcol, rowB, temp);
+		}
+		temp = A.GetElement(rowA, rowA);
+		A.SetElement (rowA,rowA, A.GetElement(rowB,rowB));
+		A.SetElement (rowB,rowB, temp);
+	}
+
+					/// Gauss resolution of the system [A]x=b, with square [A] as "this" object.
+					/// Returns error code (0 = ok, >0 number of equations with zero pivot)
+					/// It must get an array of integers as "int* pivarray", where the pivot
+					/// ordering is written. (that array must be freed and allocated by the user,
+					/// or must be a NULL pointer if the user is not interested).
+					/// Computes the determinant too.
+					/// Speed optimized for null-headed rows.
+	static int  Solve_LinSys (ChMatrix<>& A, ChMatrix<>* B, ChMatrix<>* X, int* pivarray, double* det)
+	{
+		int i,j,k, pivrow, eqpivoted;
+		double r, bi, aj, x, sum, pivot, pivlast;
+		int err = 0;
+
+		if (pivarray)	// initialize pivot index array
+		{
+			for (int ind = 0; ind < A.GetRows(); ind++)
+			{ pivarray[ind] = ind;}
+		}
+
+		*det = 1;
+	 
+				// FORWARD reduction
+		for (k=1; k < A.GetRows(); k++)
+		{
+			pivot = A.GetElement((k-1),(k-1));
+
+			if (fabs(pivot) < ACCEPT_PIVOT)
+			{
+				// pivoting is needed, so swap equations
+				pivrow = BestPivotRow(A, k-1);
+				A.SwapRows ((k-1), pivrow );
+				B->SwapRows ((k-1), pivrow );
+				*det = - *det;
+				if (pivarray)
+				{
+					eqpivoted = pivarray[pivrow]; // swap eq.ids in pivot array
+					pivarray[pivrow] =pivarray[k-1];
+					pivarray[k-1] = eqpivoted;
+				}
+				pivot = A.GetElement((k-1),(k-1)); // fetch new pivot
+			}
+			if (fabs(pivot) <= MIN_PIVOT)	// was unable to find better pivot: force solution to zero.and go ahead
+			{
+				*det = 0; 
+				pivot = INFINITE_PIVOT;
+				A.SetElement(k-1, k-1 , pivot);
+				if (!err)
+					err = (1+A.GetRows()-k);	// report deficiency
+			} 
+			else
+				*det = *det * pivot;
+
+			for (i=k; i < A.GetRows(); i++)
+			{
+				r= (A.GetElement(i,(k-1))) / pivot;
+
+				if (r)
+				{
+				 bi= B->GetElement(i,0) - r * B->GetElement((k-1),0);
+				 B->SetElement(i,0, bi);
+
+				 for (j=k; j < A.GetRows(); j++)
+				 {
+					aj= A.GetElement(i,j)  - r * A.GetElement((k-1),j);
+					A.SetElement(i,j,aj);
+				 }
+				}
+			}
+		}
+
+		pivlast = A.GetElement((A.GetRows()-1),(A.GetRows()-1));
+		if (fabs(pivlast) <= MIN_PIVOT)
+		{
+			*det = 0; 
+			pivlast = INFINITE_PIVOT;
+			A.SetElement(A.GetRows()-1, A.GetRows()-1 , pivlast);
+			if (!err)
+				err = (1);	// report deficiency
+		} 
+		else
+			*det = *det * pivlast;
+
+				// BACKWARD substitution
+		double xlast = B->GetElement(A.GetRows()-1,0) / pivlast;
+		X->SetElement((A.GetRows()-1),0,xlast);
+
+		for (k=(A.GetRows()-2); k>= 0; k--)
+		{
+			sum = 0; 
+			for (j=(k+1); j< A.GetRows(); j++)
+			{
+				sum += (A.GetElement(k,j))*(X->GetElement(j,0));
+			}
+			x = (B->GetElement(k,0) - sum) / A.GetElement(k,k);
+			X->SetElement(k,0, x);
+		}
+
+		return err;
+	}
+
+
+					/// As before, but simplified, without needing the pivot vector. 
+	static void Solve_LinSys (ChMatrix<>& A, ChMatrix<>* B, ChMatrix<>* X)
+	{
+		double det; 
+		Solve_LinSys (A, B, X, (int*)NULL, &det);
+	}
+
+					/// LU decomposition: [A]=[L][U], with square [A] as "this" object.
+					/// Decomposition happens in place. (matrix [A] is overwritten) 
+					/// Pivot array must exist! (it will be filled with the _row_ pivots, if any)
+	static int	 Decompose_LU(ChMatrix<>& A, int* pivarray, double* det)
+	{
+		int i,j,k, pivrow, eqpivoted;
+		double r, aj, pivot;
+		int err = 0;
+		int rows = A.GetRows();
+
+		if (pivarray)	// initialize pivot index array
+		{
+			for (int ind = 0; ind < rows; ind++)
+			{ pivarray[ind] = ind;}
+		}
+		else return TRUE; // error: no pivot array.
+
+		*det = 1;
+
+		for (k=1; k < rows; k++)
+		{
+			pivot = A.GetElement((k-1),(k-1));
+
+			if (fabs(pivot) < ACCEPT_PIVOT)
+			{
+				// pivoting is needed, so swap equations
+				pivrow = BestPivotRow(A, k-1);
+				A.SwapRows ((k-1), pivrow );
+				*det = - *det;
+
+				eqpivoted = pivarray[pivrow]; // swap eq.ids in pivot array
+				pivarray[pivrow] =pivarray[k-1];
+				pivarray[k-1] = eqpivoted;
+
+				pivot = A.GetElement((k-1),(k-1)); // fetch new pivot
+			}
+
+			if (fabs(pivot) <= MIN_PIVOT)	// was unable to find better pivot: force solution to zero.and go ahead
+			{
+				*det = 0; 
+				pivot = INFINITE_PIVOT;
+				A.SetElement(k-1, k-1 , pivot);
+				if (!err)
+					err = (1+rows-k);	// report deficiency
+			} 
+			else
+				*det = *det * pivot;
+
+			for (i=k; i < rows; i++)
+			{
+				r= (A.GetElement(i,(k-1))) / pivot;	// compute multiplier 
+				
+				A.SetElement(i,(k-1),r);				// store the multiplier in L part
+				
+				if (r)
+				{
+				 for (j=k; j < rows; j++)
+				 {
+					aj= A.GetElement(i,j)  - r * A.GetElement((k-1),j);		// the U part
+					A.SetElement(i,j,aj);
+				 }
+				}
+			}
+		}
+
+		pivot = A.GetElement((rows-1),(rows-1));
+		if (fabs(pivot) <= MIN_PIVOT)
+		{
+			*det = 0; 
+			pivot = INFINITE_PIVOT;
+			A.SetElement(rows-1, rows-1 , pivot);
+			if (!err)
+				err = (1);	// report deficiency
+		} 
+		else
+			*det = *det * pivot;
+		
+		return err;
+	}
+
+					/// After LU decomposition, with Decompose_LU(), 
+					/// call this to solve [A]X=B, as [L][U]X=B
+	static int	 Solve_LU(ChMatrix<>& A, ChMatrix<>* B, ChMatrix<>* X, int* pivarray)
+	{
+		int k,j;
+		double sum, x;
+		int rows = A.GetRows();
+
+		// BACKWARD substitution - L
+		double xlast = B->GetElement(pivarray[0],0); //  ../ GetElement(0,0) => ../1;
+		X->SetElement(0,0,xlast);
+
+		for (k=1; k<rows; k++)
+		{
+			sum = 0;
+			for (j=0; j<k; j++)
+			{
+				sum += (A.GetElement(k,j))*(X->GetElement(j,0));
+			}
+			x = (B->GetElement(pivarray[k],0) - sum); //  ../ GetElement(k,k) => ../1;
+			X->SetElement(k,0, x);
+		}	
+
+		// BACKWARD substitution - U
+		xlast = X->GetElement((rows-1),0) / A.GetElement(rows-1, rows-1);
+		X->SetElement((rows-1),0,xlast);
+
+		for (k=(rows-2); k>= 0; k--)
+		{
+			sum = 0; 
+			for (j=(k+1); j< rows; j++)
+			{
+				sum += (A.GetElement(k,j))*(X->GetElement(j,0));
+			}
+			x = (X->GetElement(k,0) - sum) / A.GetElement(k,k);
+			X->SetElement(k,0, x);
+		}
+
+		return TRUE;
+	}
+
+					/// From this matrix, decomposed 'in place' with Decompose_LU(), fills the separate [L] and [U] 
+	static int  Extract_LU(ChMatrix<>& A, ChMatrix<>* mL, ChMatrix<>* mU)
+	{
+		int i,j;
+		int rows = A.GetRows();
+		int columns = A.GetColumns();
+
+		if (mL) {
+			mL->Reset(rows, columns);
+			for (i=0; i<rows; i++)
+				mL->SetElement(i,i, 1.0); // diagonal = 1;
+			for (i=1; i<rows; i++)
+				for (j=0; j<i; j++)
+					mL->SetElement(i,j, A.GetElement(i,j)); 
+		}
+		if (mU) {
+			mU->Reset(rows, columns);
+			for (i=0; i<rows; i++)
+				for (j=i; j<columns; j++)
+					mU->SetElement(i,j, A.GetElement(i,j)); 
+		}
+		return TRUE;
+	}
+
+					/// LDLt decomposition: [A]=[L][D][L]', i.e. diagonal values [D], triangular matrice [L] and
+					/// its transpose [L]'. The square [A] matrix is "this" object.
+					/// Decomposition happens in place. (matrix [A] is overwritten) 
+					/// It works only for symmetric matrices [A].
+					/// Pivot array must exist! (it will be filled with the full-diagonal pivots, if any)
+					/// Note: only the upper part of [A] is used! That is, after decomposition, the diagonal
+					/// of [A] ('this' matrix) will contain the [D] values, and the upper part will contain the [L]' values.
+	static int	 Decompose_LDL(ChMatrix<>& A, int* pivarray, double* det)	
+	{
+		int i,j,k, pivrow, eqpivoted;
+		double r, leader, aj, pivot;
+		int err = 0;
+		int rows = A.GetRows();
+
+		if (pivarray)	// initialize pivot index array
+		{
+			for (int ind = 0; ind < rows; ind++)
+			{ pivarray[ind] = ind;}
+		}
+		else return TRUE; // error: no pivot array.
+
+		*det = 1;
+
+		for (k=1; k < rows; k++)
+		{
+			pivot = A.GetElement((k-1),(k-1));
+
+			if (fabs(pivot) < ACCEPT_PIVOT)
+			{
+				// pivoting is needed, so ... 
+				pivrow = BestPivotDiag(A, k-1);
+				DiagPivotSymmetric(A, k-1,pivrow);	// swap both column and row (only upper right!)
+				*det = - *det;					// invert determ.sign
+				
+				eqpivoted = pivarray[pivrow];	// swap diagonal pivot indexes
+				pivarray[pivrow] =pivarray[k-1];
+				pivarray[k-1] = eqpivoted;
+
+				pivot = A.GetElement((k-1),(k-1));
+			}
+
+			if (fabs(pivot) <= MIN_PIVOT)	// was unable to find better pivot: force solution to zero.and go ahead
+			{
+				*det = 0.0; 
+				pivot = INFINITE_PIVOT;
+				A.SetElement(k-1, k-1 , pivot);
+				if (!err)
+					err = (1+rows-k);	// report deficiency
+			} 
+			else
+				*det = *det * pivot;
+
+			for (i=k; i < rows; i++)
+			{
+				leader = A.GetElement((k-1), i);
+				if (leader)
+				{
+				  r= (leader / pivot);	// compute multiplier (mirror look A) 
+				  
+				  for (j=i; j < rows; j++)	// only upper right part
+				  {
+					aj= A.GetElement(i,j)  - r * A.GetElement((k-1),j);		// fill the remaining part (upper right)
+					A.SetElement(i,j,aj);
+				  }
+				  
+				  A.SetElement((k-1),i, r); // store the multiplier in L part (mirror look! is up)
+				}
+
+			}
+		}
+
+		pivot = A.GetElement((rows-1),(rows-1));
+		if (fabs(pivot) <= MIN_PIVOT)
+		{
+			*det = 0; 
+			pivot = INFINITE_PIVOT;
+			A.SetElement(rows-1, rows-1 , pivot);
+			if (!err)
+				err = (1);	// report deficiency
+		} 
+		else
+			*det = *det * pivot;
+		
+		return err;
+	}
+					/// After LDL decomposition with Decompose_LDL(),
+					/// call this to solve [A]X=B, as [L][D][L]'X=B
+	static int	 Solve_LDL(ChMatrix<>& A, ChMatrix<>* B, ChMatrix<>* X, int* pivarray)
+	{
+		double sum, x;
+		int j,k;
+		int rows = A.GetRows();
+
+			// BACKWARD substitution - L
+		double xlast = B->GetElement(pivarray[0],0); //  ../ GetElement(0,0) => ../1;
+		X->SetElement(pivarray[0],0,xlast);
+
+		for (k=1; k<rows; k++)
+		{
+			sum = 0;
+			for (j=0; j<k; j++)
+			{
+				sum += (A.GetElement(j,k))*(X->GetElement(pivarray[j],0));
+			}
+			x = (B->GetElement(pivarray[k],0) - sum); //  ../ GetElement(k,k) => ../1;
+			X->SetElement(pivarray[k],0, x);
+		}	
+			// BACKWARD substitution - D
+		for (k=0; k<rows; k++)
+		{
+			x = X->GetElement(pivarray[k],0) / A.GetElement(k,k);
+			X->SetElement(pivarray[k],0,x);
+		}
+			// BACKWARD substitution - L'
+		for (k=(rows-2); k>= 0; k--)
+		{
+			sum = 0; 
+			for (j=(k+1); j< rows; j++)
+			{
+				sum += (A.GetElement(k,j))*(X->GetElement(pivarray[j],0));
+			}
+			x = (X->GetElement(pivarray[k],0) - sum);  // .../ GetElement(k,k); -> ../1 ;
+			X->SetElement(pivarray[k],0, x);
+		}
+
+		return TRUE;
+	}
+
+
+					/// From this matrix, decomposed 'in place' with Decompose_LDL(), fills the separate upper [L]' and [D] 
+	static int  Extract_LDL(ChMatrix<>& A, ChMatrix<>* L, ChMatrix<>* D, ChMatrix<>* Lu)
+	{
+		int i,j;
+		int rows = A.GetRows();
+		int columns = A.GetColumns();
+
+		if (L) {
+			L->Reset(rows, columns);
+			for (i=0; i<rows; i++)
+				L->SetElement(i,i, 1.0); // diagonal = 1;
+			for (i=1; i<rows; i++)
+				for (j=0; j<i; j++)
+					L->SetElement(i,j, A.GetElement(j,i)); 
+		}
+		if (D) {
+			D->Reset(rows, columns);
+			for (i=0; i<rows; i++)
+				D->SetElement(i,i, A.GetElement(i,i)); 
+		}
+		if (Lu) {
+			Lu->Reset(rows, columns);
+			for (i=0; i<rows; i++)
+				Lu->SetElement(i,i, 1.0); // diagonal = 1;
+			for (i=0; i<(rows-1); i++)
+				for (j=i+1; j<columns; j++)
+					Lu->SetElement(i,j, A.GetElement(i,j)); 
+		}
+		return TRUE;
+	}
+
+					/// Gets the determinant (0 if singular, or rows not equal to columns)
+					/// This is expensive as a LU decomposition, so better get determinant as a side effect of Decompose_LU() or such..
+	static double Det(ChMatrix<>& A)
+	{
+		if (A.GetRows()!=A.GetColumns()) return 0;
+		ChMatrixDynamic<double>* mtemp = new ChMatrixDynamic<double>;
+		mtemp->CopyFromMatrix(A);
+		double mdet = 0;
+		int* pivarray = (int*) calloc ((mtemp->GetRows()), sizeof(int));
+		Decompose_LU(A, pivarray, &mdet);
+		free(pivarray);
+		delete mtemp;
+		return mdet;
+	}
+					/// Inverts a square matrix using a LU decomposition (expensive computation!).
+					/// so that   this = (mA)^-1
+					/// If matrix is 3x3, use FastInvert() for better performance. 
+					/// \return Returns determinant.
+	static double Invert(ChMatrix<>& A, ChMatrix<>* mA)
+	{
+		A.Reset(mA->GetRows(), mA->GetColumns());
+
+		int rows = A.GetRows();
+		int columns = A.GetColumns();
+
+		if (rows!=columns) return 0;
+
+		int n = A.GetRows();
+		double mdet = 0;
+		ChMatrixDynamic<double> tempB(n,1);
+		ChMatrixDynamic<double> tempX(n,1);
+		int i,j;
+		int* pivarray = (int*) calloc (n, sizeof(int));
+		Decompose_LU(A, pivarray, &mdet);
+		for (j=0; j<n;j++)
+		{
+			for (i=0; i<n; i++) tempB.SetElement(i,0, 0.0); 
+			tempB.SetElement(j,0, 1.0);
+			Solve_LU(A, &tempB, &tempX, pivarray);
+			for (i=0; i<n; i++) A.SetElement(i,j, tempX.GetElement(i,0));
+		}
+		free (pivarray);
+		return mdet;
+	}
+
+
+					/// In-place inversion of a square matrix.
+	static double Invert(ChMatrix<>& A)
+	{
+		ChMatrixDynamic<>* mA = new ChMatrixDynamic<>(A.GetRows(), A.GetColumns());
+		mA->CopyFromMatrix(A);
+		double mdet = Invert(A,mA);
+		delete mA;
+		return mdet;
+	}
+
+
+
+	static inline double ch_sign (double a, double b)
+	{
+	  if (b >= 0.0)
+		return(fabs(a));
+	  else
+	  return(-fabs(a));
+	}
+
+					/// Performs SVD decomposition. Matrices U,W,V are automatically resized
+					/// if passed with wrong size.
+					/// [A] is 'this' matrix. so that [A]=[U][W][V]'
+					/// Also computes condition number (near 1= well cond, if ->infinite, A tend to simgularity)
+	static int SVD(ChMatrix<>& mA, ChMatrix<> &U, ChMatrix<> &W, ChMatrix<> &V, double &cond_num)
+	{
+		  const double MACHEP=1.4e-17;      // measure of machine precision for SVD
+		  const double MAXCN=1.0e+12;
+
+		  ChMatrix<double>* A = &mA;
+		  int i,j,k,l,mn,its,n,m;
+		  double c,f,g,h,s,x,y,z,eps,scale,machep;
+		  double *rv1;
+		  double u,v,w;//cond_num;
+	   
+		  machep = MACHEP;
+	  
+		  // get dimension of input matrix 
+		  n=A->GetRows();
+		  m=A->GetColumns();
+
+		  rv1 = new double [m]; // work space
+	  
+		  // Redimension return matrices
+		  U.Reset(n,m);
+		  V.Reset(m,m);
+		  W.Reset(m,m);
+
+		  // U=A' <=== ??????
+		  //	U=CopyFromMatrixT(A); ???
+		   U.CopyFromMatrix(*A);
+	  
+		  // Begin housholder reduction
+	  
+		  g = x = scale = 0.0;        
+	  
+		  for(i=0; i<m; i++) {
+			l = i + 1;
+			rv1[i] = scale * g;
+			g = s = scale = 0.0;
+	    
+			if(i < n)
+			  for(k=i; k<n; k++) {
+				if (U(k,i) > 0.0) scale +=U(k,i);
+			  else scale -= U(k,i);
+			}
+	    
+			if(scale != 0.0) {
+			  for(k=i; k<n; k++) U(k,i)/=scale;
+			  for(k=i; k<n; k++) s += U(k,i) * U(k,i);
+			  f = U(i,i);
+			  g = -ch_sign(sqrt(s),f);
+			  h = f * g - s;
+			  U(i,i)=f-g;
+			  if(i != m-1)
+				for(j=l; j<m; j++) {
+				  s = 0.0;
+				for(k=i; k<n; k++) s += U(k,i) * U(k,j);
+				f = s / h;
+				for(k=i; k<n; k++) U(k,j)+=f * U(k,i);
+			  }
+			  for(k=i; k<n; k++) U(k,i)*=scale;
+			}
+	    
+			W(i,i)=scale * g;
+			g = s = scale = 0.0;
+	    
+			if(i<n && i!=m-1) {
+			  for(k=l; k<m; k++) {
+				if (U(i,k) > 0.0)
+				  scale += U(i,k);
+				else scale -= U(i,k);
+			  }
+			  if(scale != 0.0) {
+				for(k=l; k<m; k++) U(i,k)/=scale;
+				for(k=l; k<m; k++) s += U(i,k) * U(i,k);
+				f = U(i,l);
+				g = -ch_sign(sqrt(s),f);
+				h = f * g - s;
+				U(i,l)=f-g;
+				for(k=l; k<m; k++) 
+				  rv1[k]=U(i,k) / h;			
+	        
+				if(i != n-1)
+				  for(j=l; j<n; j++) {
+					s = 0.0;
+				  for(k=l; k<m; k++) s += U(j,k) * U(i,k);
+				  for(k=l; k<m; k++) U(j,k)+=s * rv1[k];
+				}
+				for(k=l;k<m; k++) U(i,k)*=scale;
+			  }
+			}
+	    
+			y = fabs(W(i,i))+fabs(rv1[i]);
+			if(y > x) x = y;
+		  }
+	  
+		  for(i=m-1; i >= 0; i--) {
+			if(i != m-1) {
+			  if(g != 0.0) {
+				// double division avoids possible underflow 
+				for(j=l; j<m; j++) V(j,i)=(U(i,j) / U(i,l) ) / g;
+				for(j=l; j<m; j++) {
+				  s = 0.0;
+				  for(k=l; k<m; k++) s += U(i,k) * V(k,j);
+				  for(k=l; k<m; k++) V(k,j)+=s * V(k,i);
+				}
+			  }
+			  for(j=l; j<m; j++) V(i,j)=0.0;
+			  for(j=l; j<m; j++) V(j,i)=0.0;
+			}
+			V(i,i)=1.0;
+			g = rv1[i];
+			l = i;
+		  }
+	  
+		  mn = n;
+		  if (m < n) mn = m;             /* mn = min(m,n) */
+			for(i= mn-1; i>= 0; i--) {
+			  l = i + 1;
+			g = W(i,i);
+			if(i != m-1)
+			  for(j=l; j<m; j++) U(i,j)=0.;
+	    
+			if(g != 0.0) {
+			  if(i != mn-1) {
+				for(j=l; j<m; j++) {
+				  s = 0.0;
+				  for(k=l; k<n; k++) s += U(k,i) * U(k,j);
+				  /* double division avoids possible underflow */
+				  f = (s / U(i,i)) / g;
+				  for(k=i; k<n; k++) U(k,j)+=f * U(k,i);
+				}
+			  }
+			  for(j=i; j<n; j++) U(j,i)/=g;
+			}
+			else
+			for(j=i; j<n; j++) U(i,j)=0.0;
+			U(i,i)+=1.0;
+		  }
+	  
+		  eps = machep * x; 
+		  for(k = m-1; k >= 0; k--) {
+	    
+			its = 0;
+	    
+			testsplit:	// test for splitting 
+	    
+			for(l=k; l>=0; l--) {
+			  if(fabs(rv1[l]) <= eps) goto testcon;
+			  /* rv1[0] is always zero, so there is no exit
+			  through the bottom of the loop  */
+			  if(fabs(W(l-1,l-1)) <= eps) goto cancellation;
+			}
+	    
+			cancellation:  // cancellation of rv1[l] if l greater than 0 
+	    
+			c = 0.0;
+			s = 1.0;
+			for(i=l; i<=k; i++) {
+			  f = s * rv1[i];
+			  rv1[i] = c * rv1[i];
+			  if(fabs(f) <= eps) goto testcon;
+			  g = W(i,i);
+			  // h = sqrt(f*f+g*g); modified to avoid underflow 
+			  if(fabs(f) > fabs(g))
+				h = fabs(f)*sqrt(1.0+(g/f)*(g/f));
+			  else if(fabs(g) > fabs(f))
+			  h = fabs(g)*sqrt(1.0+(f/g)*(f/g));
+			  else
+			  h = fabs(f)*sqrt(2.0);
+	      
+			  W(i,i)=h;
+			  c = g / h;
+			  s = -f / h;
+	      
+			  for(j=0; j<n; j++) {
+				y = U(j,l-1);
+				z = U(j,i);
+				U(j,l-1)=y * c + z * s;
+				U(j,i)=-y * s + z * c;
+			  }
+			}
+	    
+			testcon:                  // test for convergence 
+	    
+			z = W(k,k);
+			if (l == k) goto convergence;
+			if (its == 30) return(k+1);    /* no convergence to k'th */
+			  /* singular value */
+	      
+			  /* shift from bottom 2 by 2 minor */
+			  its++;           
+			x = W(l,l);
+			y = W(k-1,k-1);
+			g = rv1[k-1];
+			h = rv1[k];
+			f = ((y - z) * (y + z) + (g - h) * (g + h)) / (2.0 * h * y);
+			/* g = sqrt(f*f+1.0); modified to avoid over flow */
+	    
+			if(fabs(f) > 1.0)
+			  g = fabs(f)*sqrt(1.0+(1.0/f)*(1.0/f));
+			else
+			g = sqrt(f*f+1.0);
+	    
+			f = ((x - z) * (x + z) + h * (y / (f + ch_sign(g,f)) - h)) / x;
+	    
+			/* next qr transformation */
+			c = s = 1.0;
+			for(i=l+1; i<=k; i++) {
+			  g = rv1[i];
+			  y = W(i,i);
+			  h = s * g;
+			  g = c * g;
+			  /* z = sqrt(f*f+h*h); modified to avoid underflow */
+			  if(fabs(f) > fabs(h))
+				z = fabs(f)*sqrt(1.0+(h/f)*(h/f));
+			  else if(fabs(h) > fabs(f))
+			  z = fabs(h)*sqrt(1.0+(f/h)*(f/h));
+			  else
+			  z = fabs(f)*sqrt(2.0);
+	      
+			  rv1[i-1] = z;
+			  c = f / z;
+			  s = h / z;
+			  f = x * c + g * s;
+			  g = -x * s + g * c;
+			  h = y * s;
+			  y = y * c;
+	      
+			  for(j=0; j<m; j++) {
+				x = V(j,i-1);
+				z = V(j,i);
+				V(j,i-1)=x * c + z * s;
+				V(j,i)=-x * s + z * c;
+			  }
+	      
+			  /* z = sqrt(f*f+h*h); modified to avoid underflow */
+			  if(fabs(f) > fabs(h))
+				z = fabs(f)*sqrt(1.0+(h/f)*(h/f));
+			  else if(fabs(h) > fabs(f))
+			  z = fabs(h)*sqrt(1.0+(f/h)*(f/h));
+			  else
+			  z = fabs(f)*sqrt(2.0);
+	      
+			  W(i-1,i-1)=z;
+			  if (z != 0.0) {   /* rotation can be arbitrary if z is zero */
+				c = f / z;
+			  s = h / z;
+			}
+			f = c * g + s * y;
+			x = -s * g + c * y;
+			for(j=0; j<n; j++) {
+			  y = U(j,i-1);
+			  z = U(j,i);
+			  U(j,i-1)=y * c + z * s;
+			  U(j,i)=-y * s + z * c;
+			}
+		  }
+		  rv1[l] = 0.0;
+		  rv1[k] = f;
+		  W(k,k)=x;
+		  goto testsplit;
+	  
+		  convergence:
+	  
+		  if (z < 0.0) {   /* w[k] is made non-negative */
+			W(k,k)=-z;
+		  for(j=0; j<m; j++) V(j,k)=-V(j,k);
+		}
+		}
+		delete rv1;
+
+		// sort by singular values
+		for(i=0;i<m-1;i++) {
+		k=i;
+		w=W(i,i);
+		for(j=i+1;j<m;j++)
+		  if(W(j,j)>=w) {
+			k=j;
+		  w=W(j,j);
+		}
+
+		if(k!=i) {
+		  W(k,k)=W(i,i);
+		  W(i,i)=w;
+		  for(j=0;j<m;j++) {
+			v=V(i,j);
+			V(i,j)=V(j,k);
+			V(j,k)=v;
+		  }
+		  for(j=0;j<n;j++) {
+			u=U(j,i);
+			U(j,i)=U(j,k);
+			U(j,k)=u;
+		  }
+	  
+		}
+		}
+
+		if(W(m-1,m-1)==0.0) { 
+			cond_num = 1E30;
+		}
+		else {
+			cond_num=W(0,0)/W(m-1,m-1);
+		}
+
+		return(0);
+	}
+
+					/// Computes and returns the condition number, by SVD decomposition 
+					/// Warning: this may be an expensive computation.
+	static double ConditionNumber(ChMatrix<>& A)
+	{
+		ChMatrixDynamic<double> U; 
+		ChMatrixDynamic<double> W; 
+		ChMatrixDynamic<double> V;
+		double cond = 0;
+		SVD(A,U,W,V,cond);
+		return cond;
+	}
+
+
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#endif  // END of ChMatrix.h 
diff --git a/SRC/ChronoEngine/core/ChLists.h b/SRC/ChronoEngine/core/ChLists.h
new file mode 100644
index 0000000..d71d376
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChLists.h
@@ -0,0 +1,288 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLISTS_H
+#define CHLISTS_H
+
+//////////////////////////////////////////////////
+// 
+//   ChLists.h
+//
+//   Base class for Chrono lists of pointers to 
+//   objects. This has a different meaning from STL
+//   lists (which are lists of objects), because ours
+//   can manage the deletion of all pointed objects.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include <stdlib.h>
+#include <memory.h>
+
+
+namespace chrono 
+{
+#ifndef TRUE
+  #define TRUE  1
+#endif
+#ifndef FALSE
+  #define FALSE 0
+#endif
+//////////////////////////////////////////////////////////////////
+//
+// GENERIC LISTS AND NODES
+//
+ 
+
+/// Node for linked list. 
+/// This will be used by ChList<>
+
+template<class dt>
+class ChNode {
+public:
+	dt* data;			///< pointer to data
+	ChNode* prev;		///< previous node
+	ChNode* next;		///< next node
+	
+			/// Constructor for node
+	ChNode() {data = NULL; next = prev = NULL;}; 
+
+			/// Constructor for node
+	ChNode(dt* mydata)	{data = mydata; next = prev = NULL;}; 
+
+	//~Ch_node();
+};
+
+
+///
+/// Class for linked list. 
+///
+/// This linked list class can be used to 
+/// build lists of pointers to objects.
+/// This has a different meaning from STL
+/// lists (which are lists of objects), because ours
+/// can manage the deletion of all pointed objects.
+///
+
+template<class dt>
+class ChList {
+private:
+	ChNode<dt>* head;  
+	ChNode<dt>* tail;
+public: 
+			/// Constructor
+	ChList();
+			/// Deletion
+	~ChList();
+
+			/// Returns the data at the head of the list
+	dt* GetHeadData() {if (head) return head->data; else return NULL;}
+
+			/// Returns the data at the tail of the list
+	dt* GetTailData() {if (tail) return tail->data; else return NULL;}
+
+			/// Returns the head node
+	ChNode<dt>* GetHead() {return head;}
+
+			/// Returns the tail node
+	ChNode<dt>* GetTail() {return tail;}
+
+			/// Returns a node at given position in list. Returns null 
+			/// if num exceeds num of nodes. Note: num=1 gets first	element,
+	ChNode<dt>* GetNum(int num); 
+
+			/// Insert data at the head of the list
+	int AddHead(dt* mdata);
+
+			/// Insert data at the tail of the list
+	int AddTail(dt* mdata);
+
+			/// Removes the head of list.
+	int RemHead();
+
+			/// Removes the tail of list.
+	int RemTail();
+
+	int InsertAfter(ChNode<dt>* mnode, ChNode<dt>* newnode);
+	int InsertBefore(ChNode<dt>* mnode, ChNode<dt>* newnode);
+	int InsertAfter(ChNode<dt>* mnode, dt* mdata);
+	int InsertBefore(ChNode<dt>* mnode, dt* mdata);
+
+			/// Removes a node.
+			/// Note the Remove() command delete just the Ch_node, not the pointed 'data' object
+	int Remove(ChNode<dt>* mnode);
+		
+			/// Removes all nodes.
+	int RemoveAll();
+
+			/// Removes a node and deletes its data.
+			/// Note the Kill() commands remove and also use delete(data) to free the objects pointed by nodes!,
+	int Kill(ChNode<dt>* mnode);
+			
+			/// Kills all nodes.
+	int KillAll();
+
+			/// Returns number of elements in list.
+	int Count();
+};
+
+
+
+
+
+template<class dt>
+ChList<dt>::ChList()
+	{ head = tail = NULL;}; 
+template<class dt> 
+ChList<dt>::~ChList()
+	{ RemoveAll();};
+
+template <class dt> int ChList<dt>::AddHead(dt* mdata)
+{
+	ChNode<dt>* nnode = new ChNode<dt>; 
+	nnode->data = mdata;
+	nnode->prev = NULL; 
+	nnode->next = head;
+	if (head == NULL) // first elem 
+		{head = nnode; tail = nnode;} 
+	else
+		{head->prev = nnode; head = nnode;}
+	return TRUE;
+};
+
+template <class dt> int ChList<dt>::AddTail(dt* mdata)
+{ 
+	ChNode<dt>* nnode = new ChNode<dt>; 
+	nnode->data = mdata;
+	nnode->prev = tail; 
+	nnode->next = NULL;
+	if (head == NULL) // first elem 
+		{head = nnode; tail = nnode;} 
+	else
+		{tail->next = nnode; tail = nnode;}
+	return TRUE;
+}; 
+
+template <class dt> int ChList<dt>::RemHead()
+{ 
+	if (head == NULL) return FALSE;
+	return Remove(head);
+}; 
+
+template <class dt> int ChList<dt>::RemTail()
+{ 
+	if (tail == NULL) return FALSE;
+	return Remove(tail);
+}; 
+
+template <class dt> int ChList<dt>::InsertAfter(ChNode<dt>* mnode, ChNode<dt>* newnode)
+{ 
+	newnode->next = mnode->next;
+	newnode->prev = mnode;
+	if (mnode->next)
+		mnode->next->prev = newnode;
+	else tail = newnode;
+	mnode->next = newnode;
+	return TRUE;
+}; 
+
+template <class dt> int ChList<dt>::InsertBefore(ChNode<dt>* mnode, ChNode<dt>* newnode)
+{ 
+	newnode->next = mnode;
+	newnode->prev = mnode->prev;
+	if (mnode->prev)
+		mnode->prev->next = newnode;
+	else head = newnode;
+	mnode->prev = newnode;
+	return TRUE;
+};
+
+template <class dt> int ChList<dt>::InsertAfter(ChNode<dt>* mnode, dt* mdata)
+{ 
+	ChNode<dt>* nenode = new ChNode<dt>(mdata);
+	return InsertAfter(mnode, nenode);
+};
+template <class dt> int ChList<dt>::InsertBefore(ChNode<dt>* mnode, dt* mdata)
+{ 
+	ChNode<dt>* nenode = new ChNode<dt>(mdata);
+	return InsertBefore(mnode, nenode);
+};
+
+template <class dt> int ChList<dt>::Remove(ChNode<dt>* mnode)
+{ 
+	if (mnode == head)
+		head = mnode->next;
+	if (mnode == tail)
+		tail = mnode->prev;
+	if (mnode->next)
+		mnode->next->prev = mnode->prev;
+	if (mnode->prev)
+		mnode->prev->next = mnode->next;
+	delete mnode;
+	return TRUE;
+};
+
+template <class dt> int ChList<dt>::RemoveAll()
+{ 
+	for (ChNode<dt>* mnode = head; mnode != NULL; mnode= head)
+		Remove(mnode);
+	return TRUE;
+};
+
+template <class dt> int ChList<dt>::Kill(ChNode<dt>* mnode)
+{
+	if (mnode->data)
+		delete(mnode->data);
+	Remove(mnode);
+	return TRUE;
+};
+
+template <class dt> int ChList<dt>::KillAll()
+{ 
+	for (ChNode<dt>* mnode = head; mnode != NULL; mnode= head)
+	{
+		if (mnode->data) delete(mnode->data);
+		Remove(mnode);
+	}
+	return TRUE;
+}; 
+
+template <class dt> int ChList<dt>::Count()
+{ 
+	int sum = 0;
+	for (ChNode<dt>* mnode = head; mnode != NULL; mnode= mnode->next)
+	{
+		sum++;
+	}
+	return sum;
+}; 
+
+template <class dt> ChNode<dt>* ChList<dt>::GetNum(int num)
+{ 
+	int sum = 1;
+	for (ChNode<dt>* mnode = head; mnode != NULL; mnode= mnode->next)
+	{
+		if (sum == num) return mnode;
+		sum++;
+	}
+	return NULL;
+}; 
+
+
+} // END_OF_NAMESPACE____
+
+#endif
+
diff --git a/SRC/ChronoEngine/core/ChLog.cpp b/SRC/ChronoEngine/core/ChLog.cpp
new file mode 100644
index 0000000..008fdf5
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChLog.cpp
@@ -0,0 +1,110 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLog.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <stdarg.h>
+
+#include "ChLog.h"
+
+
+// // This check is here, but could be in any other C::E cpp source.
+// #ifndef CH_API_COMPILE
+// #error Warning! You are compiling the Chrono::Engine library, \
+// 	so you need to define CH_API_COMPILE (add that symbol \
+// 	to the compiler defines, for all compiled files in this unit). 
+// #endif 
+
+
+namespace chrono
+{
+
+
+//
+// The pointer to the global logger
+//
+
+static ChLog*     GlobalLog = NULL ;
+
+
+
+// Functions to set/get the global logger
+
+ChLog& GetLog()
+{
+	if ( GlobalLog != NULL )
+        return (*GlobalLog);
+	else
+	{
+		static ChLogConsole static_cout_logger;
+		return static_cout_logger;
+	}
+}
+
+void  SetLog(ChLog& new_logobject)
+{
+	GlobalLog = &new_logobject;
+}
+
+void  SetLogDefault()
+{
+	GlobalLog = NULL;
+}
+
+
+
+
+//
+// Logger class
+//
+
+ChLog::ChLog()
+{
+	default_level = CHMESSAGE;
+	current_level = CHMESSAGE;
+}
+
+ChLog& ChLog::operator - (eChLogLevel mnewlev)
+{
+	SetCurrentLevel(mnewlev);
+	return *this;
+}
+
+/*
+void ChLog::PrintCurTime()
+{
+    char dateString[52];
+    SYSTEMTIME cur;
+    GetSystemTime(&cur);
+
+    sprintf(dateString,"%d/%d/%d, %d:%d:%d - \n\n", cur.wYear, cur.wMonth,
+            cur.wDay, cur.wHour, cur.wMinute, cur.wSecond);
+
+    Output(dateString);
+}
+*/
+
+
+
+
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/core/ChLog.h b/SRC/ChronoEngine/core/ChLog.h
new file mode 100644
index 0000000..fbae492
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChLog.h
@@ -0,0 +1,173 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLOG_H
+#define CHLOG_H
+
+//////////////////////////////////////////////////
+//  
+//   ChLog.h
+//
+//   Console output for debugging/logging purposes,
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include <assert.h>
+#include "ChStream.h"
+#include "ChApiCE.h"
+
+
+namespace chrono
+{
+
+
+
+
+//////////////////////////////////////////////////////////////////
+//  LOG
+//
+/// Base class for output of errors, messages, warnings, etc.
+/// (logging class). Must be specialized for specific output,
+/// for example output to console, to windows, etc. by inheriting
+/// custom classes. See below, an example for logging to std::cout
+
+class ChApi ChLog : public ChStreamOutAscii  
+{
+public:
+
+			/// There are different levels of log messages. This is 
+			/// indifferent for the base class, but more sophisticated
+			/// specializations of the ChLog class may handle message output
+			/// in different ways (for example a ChLogForGUIapplication may
+			/// print logs in STATUS level only to the bottom of the window, etc.)
+	enum eChLogLevel {
+		CHERROR = 0,			
+		CHWARNING,
+		CHMESSAGE,
+		CHSTATUS,	
+		CHQUIET		 
+	};
+
+protected: 
+	eChLogLevel current_level;
+	eChLogLevel default_level;
+
+			/// Creates the ChLog, and sets the level at MESSAGE
+	ChLog();
+public:
+
+			/// Forces output of message buffers, if any.
+			/// Also, should restore the default eChLogLevel
+			/// This base class does pretty nothing, but inherited classes
+			/// should override this method with more specific implementations.
+	virtual void Flush() { RestoreDefaultLevel(); };
+
+
+			/// Sets the default level, to be used from now on.
+	void SetDefaultLevel(eChLogLevel mlev) {default_level = mlev;};
+
+			/// Sets the current level, to be used until new flushing.
+	void SetCurrentLevel(eChLogLevel mlev) {current_level = mlev;};
+
+			/// Gets the current level
+	eChLogLevel GetCurrentLevel() {return current_level;};
+
+			/// Restore the default level.
+	void RestoreDefaultLevel() {current_level = default_level;};
+
+			/// Using the - operator is easy to set the status of the 
+			/// log, so in you code you can write, for example:
+			///   GetLog() - ChLog::CHERROR << "a big error in " << mynumber << " items \n" ;
+	ChLog& operator - (eChLogLevel mnewlev);
+
+			/// Prints current time to the log 
+	//void PrintCurTime();
+
+private:
+
+};
+
+
+
+////////////////////////////////////////////////////////
+//  LOG TO CONSOLE
+//
+/// Specialized class for logging errors in std::cout.
+/// Messages, warnings, etc. go always into the standard console.
+
+
+class ChApi ChLogConsole : public ChLog , public ChStreamOstreamWrapper  
+{
+public:
+			/// Create default logger: this will use the std::cout
+	ChLogConsole() : ChStreamOstreamWrapper(&std::cout)  {}
+
+	virtual ~ChLogConsole() {};
+
+			/// Redirect output stream to file wrapper.
+	virtual void	Output(const char* data, int n) 
+		{ 
+			if (current_level != CHQUIET)
+				ChStreamOstreamWrapper::Write(data, n); 
+		}
+
+
+private:
+
+};
+
+
+
+////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////
+ 
+
+/// Global function to get the current ChLog object
+ChApi
+ChLog& GetLog();
+
+/// Global function to set another ChLog object as current 'global' logging system.
+/// For example, a plugin developer may like to see logs on a GUI dialog: if so, he
+/// can inherit a specialized ChLog class (overriding the Output() function) and 
+/// use the SetLog() function to have it available all times.
+/// Doing so, in your code you can write, for example:
+///
+///   chrono::GetLog() << "message";
+///
+
+ChApi
+void   SetLog(ChLog& new_logobject);
+
+/// Global function to set the default ChLogConsole output to std::output.
+ChApi
+void   SetLogDefault();
+
+
+
+
+
+
+ 
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of header
+
diff --git a/SRC/ChronoEngine/core/ChMath.h b/SRC/ChronoEngine/core/ChMath.h
new file mode 100644
index 0000000..5fbfceb
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMath.h
@@ -0,0 +1,45 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHMATH_H
+#define CHMATH_H
+
+//////////////////////////////////////////////////
+//  
+//   ChMath.h
+//
+//   Math functions 
+//
+//   This header includes headers for vectors, matrices, 
+//   coordsys etc., all at once.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+// This header is just a trick to include quickly the 
+// following headers, all at once with a single #include "core/ChMath.h" statement
+
+
+#include "core/ChMathematics.h"
+#include "core/ChVector.h"
+#include "core/ChQuaternion.h"
+#include "core/ChMatrix.h"
+#include "core/ChCoordsys.h"
+
+
+
+#endif  // END of ChMath.h 
diff --git a/SRC/ChronoEngine/core/ChMathematics.cpp b/SRC/ChronoEngine/core/ChMathematics.cpp
new file mode 100644
index 0000000..c4fef51
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMathematics.cpp
@@ -0,0 +1,132 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+// 
+//   ChMathematics.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChMathematics.h"
+
+
+namespace chrono 
+{
+
+
+
+// ANGLE UNITS CONVERSIONS
+
+
+double ChAtan2(double mcos, double msin)
+{
+	double ret;
+	if (fabs(mcos) < 0.707)
+	{
+		ret = acos(mcos);
+		if (msin < 0.0)
+			ret = -ret;
+	}
+	else
+	{
+		ret = asin(msin);
+		if (mcos < 0.0)
+			ret = CH_C_PI - ret;
+	}
+	return ret;
+}
+
+
+
+// OTHER
+
+// Park-Miller hi-quality random generator 
+
+#define IA 16807
+#define IM 2147483647
+#define AM (1.0/IM)
+#define IQ 127773
+#define IR 2836
+#define MASK 123459876
+
+static long CH_PAseed = 123;
+
+void ChSetRandomSeed (long newseed)
+{
+	if (CH_PAseed) CH_PAseed = newseed;
+}
+
+double ChRandom()
+{
+	long k;
+	double ans;
+	CH_PAseed ^= MASK;
+	k=(CH_PAseed)/IQ;
+	CH_PAseed = IA*(CH_PAseed-k*IQ)-IR*k;
+	if (CH_PAseed <0) CH_PAseed += IM;
+	ans=AM*(CH_PAseed);
+	CH_PAseed ^= MASK;
+	return ans;
+}
+
+
+void ChPeriodicPar(double& u, int closed)
+{
+	if (u < 0) { if (closed) u=u+1; else u=0;}
+	if (u > 1) { if (closed) u=u-1; else u=1;}
+}
+
+
+double ChNoise(double x, double amp, double freq, int octaves, double amp_ratio)
+{
+	double ret = 0;
+	long oldseed = CH_PAseed;
+	double o_freq, o_amp, xA, xB, yA, yB, period;
+	int iA, iB;
+
+	o_freq = freq;
+	o_amp = amp;
+
+	for (int i=1; i<= octaves; i++)
+	{
+		
+		period = 1.0/o_freq;
+		xA = period * floor(x/period);
+		xB = xA + period;
+		iA = int (floor(x/period));
+		iB = iA+1;
+		ChSetRandomSeed((long)(iA+12345));
+		ChRandom();ChRandom();ChRandom();  // just to puzzle the seed..
+		yA = (ChRandom()-0.5) * o_amp;
+		ChSetRandomSeed((long)(iB+12345));
+		ChRandom();ChRandom();ChRandom();  // just to puzzle the seed..
+		yB = (ChRandom()-0.5) * o_amp;
+		// cubic noise interpolation from (xA,yA) to (xB,yB), with flat extremal derivatives
+		ret += yA + (yB-yA)*( (3*(pow(((x-xA)/(xB-xA)),2))) - 2*(pow(((x-xA)/(xB-xA)),3)) );
+		// for following octave, reduce amplitude...
+		o_amp *= amp_ratio;
+		o_freq *= 2.0;
+	}
+	// restore previous seed
+	CH_PAseed = oldseed;
+	return ret;
+}
+
+
+} // END_OF_NAMESPACE____
+
+
+//////// 
+
diff --git a/SRC/ChronoEngine/core/ChMathematics.h b/SRC/ChronoEngine/core/ChMathematics.h
new file mode 100644
index 0000000..3b322dc
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMathematics.h
@@ -0,0 +1,131 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHMATHEMATICS_H
+#define CHMATHEMATICS_H
+
+//////////////////////////////////////////////////
+//  
+//   ChMathematics.h
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+#include <float.h>
+#include <assert.h>
+#include "ChApiCE.h"
+
+
+//
+// CONSTANTS	
+//
+
+#ifndef TRUE
+ #define TRUE 1
+#endif
+#ifndef FALSE
+ #define FALSE 0
+#endif
+
+
+namespace chrono
+{
+
+
+					 
+static const double CH_C_PI			 = 3.141592653589793238462643383279;
+static const double CH_C_PI_2		 = 1.570796326794896619231321691639;
+static const double CH_C_PI_4		 = 0.785398163397448309615660845819;
+static const double CH_C_1_PI		 = 0.318309886183790671537767526745;
+static const double CH_C_2PI		 = 6.283185307179586476925286766559;
+static const double CH_C_RAD_TO_DEG  = 180.0 / 3.1415926535897932384626433832795;
+static const double CH_C_DEG_TO_RAD  = 3.1415926535897932384626433832795 / 180.0;
+
+static const double CH_C_SQRT_2	     = 1.41421356237309504880;
+static const double CH_C_SQRT_1_2    = 0.70710678118654752440;
+
+static const double CH_C_E           = 2.71828182845904523536;
+static const double CH_C_LOG2E       = 1.44269504088896340736;
+static const double CH_C_LOG10E      = 0.43429448190325182765;
+static const double CH_C_LN2         = 0.69314718055994530941;
+static const double CH_C_LN10        = 2.30258509299404568402;
+
+
+
+static const double CH_HITOL     = 0.001;
+static const double CH_LOWTOL    = 0.0001;
+static const double CH_LOWLOWTOL = 0.00001;
+
+static const double CH_MICROTOL  = 1.e-10;
+static const double CH_NANOTOL   = 1.e-20;
+
+static const double BDF_STEP_HIGH	 = 0.0001;
+static const double BDF_STEP_LOW	 = 0.0000001;
+static const double BDF_STEP_VERYLOW = 1.e-10;
+static const double BDF_STEP_TOOLOW  = 1.e-20;
+
+
+//
+// ANGLE CONVERSIONS
+//
+
+
+			/// Computes the atan2, returning angle given cosine and sine.
+ChApi
+double ChAtan2(double mcos, double msin);
+
+
+
+
+//
+// OTHER
+//
+
+
+	/// Returns random value in (0..1) interval with Park-Miller method
+ChApi
+double ChRandom();
+
+	/// Sets the seed of the ChRandom function 	(Park-Miller method)
+ChApi
+void ChSetRandomSeed (long newseed);
+	
+
+	/// Computes a 1D harmonic multi-octave noise 
+ChApi
+double ChNoise(double x, double amp, double freq, int octaves, double amp_ratio); 
+
+
+	/// Maximum between two values
+inline int ChMax( int a , int b ){   if( a > b ) return a;   return b;}
+	/// Maximum between two values
+inline double ChMax( double a , double b ){   if( a > b ) return a;   return b;}
+	/// Minimum between two values
+inline int ChMin( int a , int b ){   if( a < b ) return a;   return b;}
+	/// Minimum between two values
+inline double ChMin( double a , double b ){   if( a < b ) return a;   return b;}
+
+	/// Parameter make periodic in 0..1 
+	/// (using 0..1 modulus if closed, otherwise clamping in 0..1 range)
+ChApi
+void ChPeriodicPar(double& u, int closed); 
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of ChMathematics.h 
diff --git a/SRC/ChronoEngine/core/ChMatrix.cpp b/SRC/ChronoEngine/core/ChMatrix.cpp
new file mode 100644
index 0000000..851ec90
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMatrix.cpp
@@ -0,0 +1,69 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2005, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+// 
+//   ChMath.cpp
+//
+//	 CHRONO  
+//   ------
+//   Multibody dinamics engine
+//
+//   Math functions for:
+// 
+//   - MATRIXES,
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+
+#include "core/ChMatrix.h"
+
+
+
+namespace chrono
+{
+
+
+
+
+
+// alternate 3x3 matrix representation
+
+void Chrono_to_Marray (ChMatrix33<>& mma, double marr[3][3])
+{
+	marr[0][0] = mma(0,0);	marr[0][1] = mma(0,1);	marr[0][2] = mma(0,2);
+	marr[1][0] = mma(1,0);	marr[1][1] = mma(1,1);	marr[1][2] = mma(1,2);
+	marr[2][0] = mma(2,0);	marr[2][1] = mma(2,1);	marr[2][2] = mma(2,2);
+}
+void Chrono_from_Marray (ChMatrix33<>& mma, double marr[3][3])
+{
+	mma(0,0) = marr[0][0];	mma(0,1) = marr[0][1];	mma(0,2) = marr[0][2];
+	mma(1,0) = marr[1][0];	mma(1,1) = marr[1][1];	mma(1,2) = marr[1][2];
+	mma(2,0) = marr[2][0];	mma(2,1) = marr[2][1];	mma(2,2) = marr[2][2];
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+//////// 
+
diff --git a/SRC/ChronoEngine/core/ChMatrix.h b/SRC/ChronoEngine/core/ChMatrix.h
new file mode 100644
index 0000000..0a9a2b8
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMatrix.h
@@ -0,0 +1,2125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2005, 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHMATRIX_H
+#define CHMATRIX_H
+
+//////////////////////////////////////////////////
+//  
+//   ChMatrix.h
+//
+//   Math functions for :
+//      - MATRICES
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "core/ChCoordsys.h"
+#include "core/ChStream.h"
+#include "core/ChException.h"
+
+namespace chrono
+{
+
+
+
+//
+// FAST MACROS TO SPEEDUP CODE
+//
+
+
+#define SetZero(els) {for (int i=0; i<els; ++i) this->address[i]=0; }
+#define ElementsCopy(to,from,els) {for (int i=0; i<els; ++i) to[i]=(Real)from[i]; }
+
+#define Set33Element(a,b,val)  SetElementN(((a*3)+(b)),val) 
+#define Get33Element(a,b)      GetElementN((a*3)+(b)) 
+
+#define Set34Element(a,b,val)  SetElementN(((a*4)+(b)),val) 
+#define Get34Element(a,b)      GetElementN((a*4)+(b)) 
+#define Set34Row(ma,a,val0,val1,val2,val3)  ma.SetElementN((a*4),val0);ma.SetElementN((a*4)+1,val1);ma.SetElementN((a*4)+2,val2);ma.SetElementN((a*4)+3,val3);
+
+#define Set44Element(a,b,val)  SetElementN(((a*4)+(b)),val) 
+#define Get44Element(a,b)      GetElementN((a*4)+(b)) 
+
+//forward declaration
+template <class Real = double> class ChMatrixDynamic ;
+
+
+///
+/// ChMatrix:		
+/// 
+///  A base class for matrix objects (tables of NxM numbers).
+/// To access elements, the indexes start from zero, and
+/// you must indicate first row, then column, that is: m(2,4)
+/// means the element at 3rd row, 5th column.
+///  This is an abstract class, so you cannot instantiate 
+/// objects from it: you must rather create matrices using the
+/// specialized child classes like ChMatrixDynamic, ChMatrixNM
+/// ChMatrix33 and so on; all of them have this same base class.
+///  Warning: for optimization reasons, not all functions will
+/// check about boundaries of element indexes and matrix sizes (in
+/// some cases, if sizes are wrong, debug asserts are used).
+
+
+
+template <class Real = double>
+class ChMatrix 
+{
+protected:
+
+			//
+			// DATA
+			//
+
+	int rows;
+	int	columns;
+	Real* address;
+
+public:
+
+			//
+			// CONSTRUCTORS (none - abstract class that must be implemented with child classes)
+			//
+
+
+	virtual ~ChMatrix () {};
+
+
+			//
+			// OPERATORS OVERLOADING
+			//
+
+					/// Parenthesis () operator, to access a single element of the matrix, by
+					/// supplying the row and the column (indexes start from 0).
+					/// For example: m(3,5) gets the element at the 4th row, 6th column.
+					/// Value is returned by reference, so it can be modified, like in m(1,2)=10.
+	inline Real& operator()(const int row, const int col) 
+						{	
+							assert (row >= 0 && col >= 0 && row < rows && col < columns);	 
+							return (*(address + col +(row*columns)));
+						};
+	inline const Real& operator()(const int row,  const int col) const
+						{	
+							assert (row >= 0 && col >= 0 && row < rows && col < columns);	 
+							return (*(address + col +(row*columns)));
+						};
+
+					/// Parenthesis () operator, to access a single element of the matrix, by
+					/// supplying the ordinal of the element (indexes start from 0).
+					/// For example: m(3) gets the 4th element, counting row by row. 
+					/// Mostly useful if the matrix is Nx1 sized (i.e. a N-element vector).
+					/// Value is returned by reference, so it can be modified, like in m(1,2)=10.
+	inline Real& operator()(const int el) 
+						{	
+							assert (el >= 0 && el < rows*columns);	 
+							return (*(address + el));
+						};
+	inline const Real& operator()(const int el) const
+						{	
+							assert (el >= 0 && el < rows*columns);	 
+							return (*(address + el));
+						};
+
+					/// The [] operator returns the address of the n-th row. This is mostly
+					/// for compatibility with old matrix programming styles (2d array-like) 
+					/// where to access an element at row i, column j, one can write mymatrix[i][j]. 
+	inline Real* operator[](const int row) 
+						{	
+							assert (row >= 0 && row < rows);	 
+							return ((address +(row*columns)));
+						};
+	inline const Real* operator[](const int row) const 
+						{	
+							assert (row >= 0 && row < rows);	 
+							return ((address +(row*columns)));
+						};
+
+
+					///	Multiplies this matrix by a factor, in place
+	ChMatrix<Real>& operator*=(const Real factor) 
+						{ MatrScale (factor); return *this;};
+	
+					///	Increments this matrix by another matrix, in place
+	template <class RealB>
+	ChMatrix<Real>& operator+=(const ChMatrix<RealB>& matbis) 
+						{ MatrInc (matbis); return *this;}
+	
+					///	Decrements this matrix by another matrix, in place
+	template <class RealB>
+	ChMatrix<Real>& operator-=(const ChMatrix<RealB>& matbis) 
+						{ MatrDec (matbis); return *this;}
+
+					/// Matrices are equal?
+	bool operator==(const ChMatrix<Real>& other)  { return Equals(other);}
+					/// Matrices are not equal?
+	bool operator!=(const ChMatrix<Real>& other)  { return !Equals(other);}
+
+					/// Assignment operator
+	inline	ChMatrix<Real>&	operator =(const ChMatrix<Real>& matbis)
+						{
+							if (&matbis != this) 
+								CopyFromMatrix(matbis);
+							return *this;
+						}
+	template <class RealB>
+	inline	ChMatrix<Real>&	operator =(const ChMatrix<RealB>& matbis)
+						{ 
+							CopyFromMatrix(matbis);
+							return *this;
+						}
+
+			//
+			// FUNCTIONS
+			//
+
+
+					/// Sets the element at row,col position. Indexes start with zero.
+	inline void   SetElement ( int row, int col, Real elem)
+						{ 
+							assert (row >= 0 && col >= 0 && row < rows && col < columns);	 // boundary checks
+							*(address + col +(row*columns)) = elem; 
+						};
+					/// Gets the element at row,col position. Indexes start with zero.
+					/// The return value is a copy of original value. Use Element() instead if you
+					/// want to access directly by reference the original element.
+	inline Real  GetElement ( int row, int col)
+						{
+							assert (row >= 0 && col >= 0 && row < rows && col < columns);	 // boundary checks
+							return(*(address + col +(row*columns))); 
+						};
+	inline Real  GetElement ( int row, int col) const
+						{
+							assert (row >= 0 && col >= 0 && row < rows && col < columns);	 // boundary checks
+							return(*(address + col +(row*columns))); 
+						};
+					/// Sets the Nth element, counting row after row.
+	inline void   SetElementN (int index, Real elem)
+						{
+							assert (index >=0 && index < (rows*columns));	// boundary checks
+							*(address+index) = elem;
+						}
+					/// Gets the Nth element, counting row after row. 
+	inline Real   GetElementN (int index)
+						{
+							assert (index >=0 && index < (rows*columns));
+							return(*(address+index));
+						}
+	inline const Real GetElementN (int index) const
+						{
+							assert (index >=0 && index < (rows*columns));
+							return(*(address+index));
+						}
+
+					/// Access a single element of the matrix, by
+					/// supplying the row and the column (indexes start from 0).
+					/// Value is returned by reference, so it can be modified, like in m.Element(1,2)=10.
+ 	inline Real& Element (int row, int col)
+						{
+							assert (row >= 0 && col >= 0 && row < rows && col < columns);
+							return(*(address + col +(row*columns)));
+						}
+ 	inline const Real& Element (int row, int col) const
+						{
+							assert (row >= 0 && col >= 0 && row < rows && col < columns);
+							return(*(address + col +(row*columns)));
+						}
+					/// Access a single element of the matrix, the Nth element, counting row after row.
+					/// Value is returned by reference, so it can be modified, like in m.Element(5)=10.
+ 	inline Real& ElementN (int index)
+						{
+							assert (index >=0 && index < (rows*columns));
+							return(*(address+index));
+						}
+ 	inline const Real& ElementN (int index) const
+						{
+							assert (index >=0 && index < (rows*columns));
+							return(*(address+index));
+						}
+
+					/// Access directly the "Real* address" buffer. Warning! this is a low level
+					/// function, it should be used in rare cases, if really needed!
+	inline Real* GetAddress ()  { return address; };
+	inline const Real* GetAddress () const { return address; };
+
+					/// Gets the number of rows
+	inline int GetRows ()	const	{ return rows; }
+				
+					/// Gets the number of columns
+	inline int GetColumns () const	{ return columns; }
+
+					/// Reallocate memory for a new size. VIRTUAL! Must be implemented by child classes!
+	virtual inline void Resize(int, int){};
+
+					/// Swaps the columns a and b
+	void SwapColumns (int a, int b)
+						{
+							Real temp;
+							for (int i=0; i < rows; i++)
+							{
+								temp = GetElement (i,a);
+								SetElement (i,a, GetElement (i,b));
+								SetElement (i,b, temp);
+							}
+						}
+
+					/// Swap the rows a and b
+	void SwapRows    (int a, int b)
+						{
+							Real temp; 
+							for (int i=0; i < columns; i++)
+							{
+								temp = GetElement (a,i);
+								SetElement (a,i, GetElement (b,i));
+								SetElement (b,i, temp);
+							}
+						}
+
+					/// Fill the diagonal elements, given a sample.
+					/// Note that the matrix must already be square (no check for 
+					/// rectangular matrices!), and the extradiagonal elements are
+					/// not modified -this function does not set them to 0-
+	void FillDiag	(Real sample)
+						{
+							for (int i=0;i < rows; ++i)
+								SetElement (i,i,sample);
+						}
+
+					/// Fill the matrix with the same value in all elements
+	void FillElem	(Real sample)
+						{
+							for (int i=0;i < rows*columns; ++i)
+								SetElementN (i,sample);
+						}
+
+					/// Fill the matrix with random float numbers, falling within the
+					/// "max"/"min" range.
+	void FillRandom	(Real max, Real min)
+						{
+							for (int i=0;i < rows*columns; ++i)
+								SetElementN (i, min+ ChRandom()*(max-min));
+						}
+
+					/// Resets the matrix to zero  (warning: simply sets memory to 0 bytes!)
+	void Reset()		{   
+							SetZero(rows*columns); //memset(address, 0, sizeof(Real) * rows * columns); 
+						}	
+					
+					/// Reset to zeroes and (if needed) changes the size to have row and col
+	void Reset(int nrows, int ncols)
+						{
+							Resize(nrows, ncols);
+							SetZero(rows*columns); //memset(address, 0, sizeof(Real) * rows * columns);
+						}
+					
+					/// Reset to identity matrix (ones on diagonal, zero elsewhere)
+	void SetIdentity()  {   Reset(); FillDiag(1.0); }
+
+	
+					/// Copy a matrix "matra" into this matrix. Note that 
+					/// the destination matrix will be resized if necessary.
+	template <class RealB>
+	void CopyFromMatrix (ChMatrix<RealB>& matra)
+						{
+							Resize(matra.GetRows(), matra.GetColumns());
+							ElementsCopy(address, matra.GetAddress(), rows*columns); //memcpy (address, matra.address, (sizeof(Real) * rows * columns));
+						}
+	template <class RealB>
+	void CopyFromMatrix (const ChMatrix<RealB>& matra)
+						{
+							Resize(matra.GetRows(), matra.GetColumns());
+							ElementsCopy(address, matra.GetAddress(), rows*columns); //memcpy (address, matra.address, (sizeof(Real) * rows * columns));
+						}
+
+					/// Copy the transpose of matrix "matra" into this matrix. Note that 
+					/// the destination matrix will be resized if necessary.
+	template <class RealB>
+	void CopyFromMatrixT (ChMatrix<RealB>& matra)
+						{
+							Resize(matra.GetColumns(), matra.GetRows());
+							for (int i=0;i < matra.GetRows(); ++i)
+								for (int j=0;j < matra.GetColumns(); ++j)
+									SetElement (j,i,(matra.Element(i,j)));
+						}
+	
+					/// Copy the transposed upper triangular part of "matra" in the lower triangular 
+					/// part of this matrix. (matra must be square)
+					/// Note that the destination matrix will be resized if necessary.
+	template <class RealB>																			//		_______								//
+	void CopyTUpMatrix (ChMatrix<RealB>& matra)														//		\      |			|\				//
+						{																			//		  \  A'|	--->	|  \			//
+							Resize(matra.GetRows(), matra.GetColumns());							//		    \  |			|this\			//
+							for(int i=0; i<matra.GetRows(); i++){									//			  \|			|______\		//
+								for(int j=0; j<matra.GetRows(); j++)
+									SetElement(j,i,matra.GetElement(i,j));
+							}
+						}
+
+					/// Copy the transposed lower triangulat part of "matra" in the upper triangular 
+					/// part of this matrix. (matra must be square)
+					/// Note that the destination matrix will be resized if necessary.
+	template <class RealB>																			//							_______			//
+	void CopyTLwMatrix (ChMatrix<RealB>& matra)														//		|\					\      |		//
+						{																			//		|  \		--->	  \this|		//
+							Resize(matra.GetRows(), matra.GetColumns());							//		|A'  \					\  |		//
+							for(int i=0; i<matra.GetRows(); i++){									//		|______\				  \|		//
+								for(int j=0; j<matra.GetRows(); j++)
+									SetElement(i,j,matra.GetElement(j,i));
+							}
+						}
+
+
+			//
+			// STREAMING
+			//
+					/// Method to allow serializing transient data into in ascii
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream)
+						{
+							mstream << "\n" << "Matrix " << GetRows() << " rows, " << GetColumns() << " columns." << "\n";
+							for (int i=0;i < ChMin(GetRows(),8); i++)
+							{
+									for (int j=0;j < ChMin(GetColumns(),8); j++)
+										mstream << GetElement (i,j) <<"  ";
+									if (GetColumns()>8) mstream << "...";
+									mstream << "\n";
+							}
+							if (GetRows()>8) mstream << "... \n\n";
+						}
+
+					/// Method to allow serializing transient data into an ascii stream (ex. a file)
+					/// as a Matlab .dat file (all numbers in a row, separated by space, then CR)
+	void StreamOUTdenseMatlabFormat(ChStreamOutAscii& mstream)
+						{
+							for(int ii=0; ii<this->GetRows(); ii++)
+							{
+								for(int jj=0; jj<this->GetColumns(); jj++)
+								{
+									mstream << this->GetElement(ii,jj);
+									if (jj<(this->GetColumns()-1))
+										mstream << " ";
+								}
+								mstream << "\n";
+							}
+						}
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream)
+						{
+							mstream << GetRows();
+							mstream << GetColumns();
+							int tot_elements = GetRows() * GetColumns();
+							for (int i=0; i< tot_elements; i++)
+							{
+								mstream << GetElementN(i);
+							}
+						}
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream)
+						{
+							int m_row, m_col;
+							mstream >> m_row;
+							mstream >> m_col;
+							if ((m_row ==0)||(m_col==0))
+								throw (ChException("Cannot load zero-sized matrix: wrong stream format?"));
+							Reset(m_row, m_col);
+							for (int i=0; i< (m_row*m_col); i++)
+							{
+								mstream >> ElementN(i);
+							}
+						}
+
+
+
+
+				//
+				// Math member functions. For speed reasons, sometimes 
+				// size checking of operands is left to the user!
+				//
+
+					/// Changes the sign of all the elements of this matrix, in place.
+	void MatrNeg()	{  for (int nel=0; nel<rows*columns; ++nel)	ElementN(nel)= -ElementN(nel);	}
+
+	
+					/// Sum two matrices, and stores the result in "this" matrix
+					/// [this]=[A]+[B]. 
+	template <class RealB,class RealC>
+	void MatrAdd	( const ChMatrix<RealB>& matra, const ChMatrix<RealC>& matrb)
+						{
+							assert (matra.GetColumns()==matrb.GetColumns() && matra.rows==matrb.GetRows());
+							assert (this->columns==matrb.GetColumns() && this->rows==matrb.GetRows());
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)= matra.ElementN(nel)+matrb.ElementN(nel);
+						}
+
+					/// Subtract two matrices, and stores the result in "this" matrix
+					/// [this]=[A]-[B]. 
+	template <class RealB,class RealC>
+	void MatrSub	( const ChMatrix<RealB>& matra, const ChMatrix<RealC>& matrb)
+						{
+							assert (matra.GetColumns()==matrb.GetColumns() && matra.rows==matrb.GetRows());
+							assert (this->columns==matrb.GetColumns() && this->rows==matrb.GetRows());
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)= matra.ElementN(nel)-matrb.ElementN(nel);
+						}
+
+					/// Increments this matrix with another matrix A, as: [this]+=[A]
+	template <class RealB>
+	void MatrInc	( const ChMatrix<RealB>& matra)
+						{
+							assert (matra.GetColumns()==columns && matra.GetRows()==rows);
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)+= (Real)matra.ElementN(nel);
+						}
+
+					/// Decrements this matrix with another matrix A, as: [this]-=[A]
+	template <class RealB>
+	void MatrDec	( const ChMatrix<RealB>& matra)
+						{
+							assert (matra.GetColumns()==columns && matra.GetRows()==rows);
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)-= (Real)matra.ElementN(nel);
+						}
+
+					/// Scales a matrix, multiplying all elements by a constant value: [this]*=f
+	void MatrScale	(Real factor)
+						{
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)*= factor;
+						}
+					/// Scales a matrix, multiplying all element by all oter elements of 
+					/// matra (it is not the classical matrix multiplication!)
+	template <class RealB>
+	void MatrScale	( const ChMatrix<RealB>& matra)
+						{
+							assert (matra.GetColumns()==columns && matra.GetRows()==rows);
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)*= (Real)matra.ElementN(nel);
+						}
+					/// Scales a matrix, dividing all elements by a constant value: [this]/=f
+	void MatrDivScale	(Real factor)
+						{
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)/= factor;
+						}
+					/// Scales a matrix, dividing all element by all oter elements of 
+					/// matra (it is not the classical matrix multiplication!)
+	template <class RealB>
+	void MatrDivScale	( const ChMatrix<RealB>& matra)
+						{
+							assert (matra.GetColumns()==columns && matra.GetRows()==rows);
+							for (int nel=0; nel<rows*columns; ++nel)
+								ElementN(nel)/= (Real)matra.ElementN(nel);
+						}
+
+					/// Multiplies two matrices, and stores the result in "this" matrix
+					/// [this]=[A]*[B].  
+	template <class RealB,class RealC>
+	void MatrMultiply  ( const ChMatrix<RealB>& matra, const ChMatrix<RealC>& matrb)
+						{
+							assert (matra.GetColumns()==matrb.GetRows());	
+							assert (this->rows==matra.GetRows());
+							assert (this->columns==matrb.GetColumns());
+							register int col, row, colres; 	
+							Real sum;
+							for (colres=0; colres < matrb.GetColumns(); ++colres)
+								for (row=0; row < matra.GetRows(); ++row)
+								{
+									sum = 0;
+									for (col=0; col < matra.GetColumns(); ++col)
+										sum+= (matra.Element(row,col))*(matrb.Element(col,colres));
+									SetElement (row, colres, sum);
+								}
+						}
+
+					/// Multiplies two matrices (the second is considered transposed): 
+					/// [this]=[A]*[B]'
+					/// Faster than doing B.MatrTranspose(); result.MatrMultiply(A,B); 
+					/// Note: no check on mistaken size of this! 
+	template <class RealB,class RealC>
+	void MatrMultiplyT ( const ChMatrix<RealB>& matra, const ChMatrix<RealC>& matrb)
+						{
+							assert (matra.GetColumns()==matrb.GetColumns());
+							assert (this->rows==matra.GetRows());
+							assert (this->columns==matrb.GetRows());
+							register int col, row, colres; 	
+							Real sum;
+							for (colres=0; colres < matrb.GetRows(); ++colres)
+								for (row=0; row < matra.GetRows(); ++row)
+								{
+									sum = 0;
+									for (col=0; col < matra.GetColumns(); ++col)
+										sum+= (matra.Element (row,col))*(matrb.Element(colres,col));
+									SetElement (row, colres, sum);
+								}
+						}
+
+					/// Multiplies two matrices (the first is considered transposed): 
+					/// [this]=[A]'*[B]
+					/// Faster than doing A.MatrTranspose(); result.MatrMultiply(A,B); 
+	template <class RealB,class RealC>
+	void MatrTMultiply ( const ChMatrix<RealB>& matra, const ChMatrix<RealC>& matrb)
+						{
+							assert (matra.GetRows()==matrb.GetRows());
+							assert (this->rows==matra.GetColumns());
+							assert (this->columns==matrb.GetColumns());
+							register int col, row, colres; 	
+							Real sum;
+							for (colres=0; colres < matrb.GetColumns(); ++colres)
+								for (row=0; row < matra.GetColumns(); ++row)
+								{
+									sum = 0;
+									for (col=0; col < (matra.GetRows()); ++col)
+										sum+= (matra.Element(col,row))*(matrb.Element(col,colres));
+									SetElement (row, colres, sum);
+								}
+						}
+
+					/// Computes dot product between two column-matrices (vectors) with 
+					/// same size. Returns a scalar value.
+	template <class RealB,class RealC>
+	static Real MatrDot(const ChMatrix<RealB>* ma, const ChMatrix<RealC>* mb)
+						{
+							assert (ma->GetColumns()==mb->GetColumns() && ma->GetRows()==mb->GetRows());
+							Real tot = 0;
+							for (int i=0; i<ma->GetRows(); ++i)
+								tot += ma->ElementN(i) * mb->ElementN(i);
+							return tot;
+						}
+
+					/// Transpose this matrix in place
+	void MatrTranspose	()
+						{
+							if (columns==rows)	// Square transp.is optimized
+							{
+								for (int row=0; row < rows; ++row)
+									for (int col=row; col < columns; ++col)
+										if (row!=col)
+										{
+											Real temp = Element (row,col);
+											Element (row,col)= Element (col,row);
+											Element (col,row)= temp;
+										}
+								int tmpr = rows; rows = columns; columns = tmpr;
+							}
+							else	// Naive implementation for rectangular case. Not in-place. Slower.
+							{
+								ChMatrixDynamic<Real> matrcopy(*this);
+								int tmpr = rows; rows = columns; columns = tmpr;	// dont' realloc buffer, anyway
+								for (int row=0; row < rows; ++row)
+									for (int col=0; col < columns; ++col)
+										Element(row,col)=matrcopy.Element(col,row);
+							}
+						}
+		
+					/// Returns the determinant of the matrix. 
+					/// Note! This method must be used only with max 4x4 matrices, 
+					/// otherwise it throws an exception.
+	double Det()
+		{
+			assert (this->GetRows()==this->GetColumns());
+			assert (this->GetRows() <= 4);
+
+			if (this->GetRows() != this->GetColumns()) 
+				throw("Cannot compute matrix determinant because rectangular matrix");
+			if (this->GetRows() > 4)
+				throw("Cannot compute matrix determinant because matr. larger than 3x3");
+			double det = 0;
+			switch (this->GetRows()) 
+			{
+				case 1:
+					det = (*this)(0,0);
+					break;
+				case 2:
+					det = (*this)(0,0)*(*this)(1,1)-
+						  (*this)(0,1)*(*this)(1,0);
+					break;
+				case 3:
+					det = (*this)(0,0)*(*this)(1,1)*(*this)(2,2)+
+						  (*this)(0,1)*(*this)(1,2)*(*this)(2,0)+
+						  (*this)(0,2)*(*this)(1,0)*(*this)(2,1)-
+						  (*this)(2,0)*(*this)(1,1)*(*this)(0,2)-
+						  (*this)(2,1)*(*this)(1,2)*(*this)(0,0)-
+						  (*this)(2,2)*(*this)(1,0)*(*this)(0,1);
+					break;
+				case 4:
+					det = (*this)(0,0)*(*this)(1,1)*(*this)(2,2)*(*this)(3,3)+(*this)(0,0)*(*this)(1,2)*(*this)(2,3)*(*this)(3,1)+(*this)(0,0)*(*this)(1,3)*(*this)(2,1)*(*this)(3,2)+
+						  (*this)(0,1)*(*this)(1,0)*(*this)(2,3)*(*this)(3,2)+(*this)(0,1)*(*this)(1,2)*(*this)(2,0)*(*this)(3,3)+(*this)(0,1)*(*this)(1,3)*(*this)(2,2)*(*this)(3,0)+
+						  (*this)(0,2)*(*this)(1,0)*(*this)(2,1)*(*this)(3,3)+(*this)(0,2)*(*this)(1,1)*(*this)(2,3)*(*this)(3,0)+(*this)(0,2)*(*this)(1,3)*(*this)(2,0)*(*this)(3,1)+
+						  (*this)(0,3)*(*this)(1,0)*(*this)(2,2)*(*this)(3,1)+(*this)(0,3)*(*this)(1,1)*(*this)(2,0)*(*this)(3,2)+(*this)(0,3)*(*this)(1,2)*(*this)(2,1)*(*this)(3,0)-
+						  (*this)(0,0)*(*this)(1,1)*(*this)(2,3)*(*this)(3,2)-(*this)(0,0)*(*this)(1,2)*(*this)(2,1)*(*this)(3,3)-(*this)(0,0)*(*this)(1,3)*(*this)(2,2)*(*this)(3,1)-
+						  (*this)(0,1)*(*this)(1,0)*(*this)(2,2)*(*this)(3,3)-(*this)(0,1)*(*this)(1,2)*(*this)(2,3)*(*this)(3,0)-(*this)(0,1)*(*this)(1,3)*(*this)(2,0)*(*this)(3,2)-
+						  (*this)(0,2)*(*this)(1,0)*(*this)(2,3)*(*this)(3,1)-(*this)(0,2)*(*this)(1,1)*(*this)(2,0)*(*this)(3,3)-(*this)(0,2)*(*this)(1,3)*(*this)(2,1)*(*this)(3,0)-
+						  (*this)(0,3)*(*this)(1,0)*(*this)(2,1)*(*this)(3,2)-(*this)(0,3)*(*this)(1,1)*(*this)(2,2)*(*this)(3,0)-(*this)(0,3)*(*this)(1,2)*(*this)(2,0)*(*this)(3,1);
+
+			}
+			return det;
+	}
+
+					/// Returns the inverse of the matrix. 
+					/// Note! This method must be used only with max 4x4 matrices, 
+					/// otherwise it throws an exception.
+	void MatrInverse()
+		{
+			assert (this->GetRows()==this->GetColumns());
+			assert (this->GetRows() <= 4);
+			assert (this->Det() !=0);
+
+			if (this->GetRows() != this->GetColumns()) 
+				throw("Cannot compute matrix inverse because rectangular matrix");
+			if (this->GetRows() > 4)
+				throw("Cannot compute matrix inverse because matr. larger than 4x4");
+			if (this->Det() == 0)
+				throw("Cannot compute matrix inverse because singular matrix");
+
+			switch (this->GetRows()) 
+			{
+				case 1:
+					(*this)(0,0) = (1/(*this)(0,0));
+					break;
+				case 2:
+					{
+					ChMatrixDynamic<Real> inv(2,2);
+					inv(0,0) = (*this)(1,1);
+					inv(0,1) = -(*this)(0,1);
+					inv(1,1) = (*this)(0,0);
+					inv(1,0) = -(*this)(1,0);
+					inv.MatrDivScale((*this).Det());
+					this->CopyFromMatrix(inv);
+					break;
+					}
+				case 3:
+					{
+					ChMatrixDynamic<Real> inv(3,3);
+					inv(0,0)=(*this)(1,1)*(*this)(2,2)-(*this)(1,2)*(*this)(2,1);	inv(0,1)=(*this)(2,1)*(*this)(0,2)-(*this)(0,1)*(*this)(2,2);	inv(0,2)=(*this)(0,1)*(*this)(1,2)-(*this)(0,2)*(*this)(1,1);
+					inv(1,0)=(*this)(1,2)*(*this)(2,0)-(*this)(1,0)*(*this)(2,2);	inv(1,1)=(*this)(2,2)*(*this)(0,0)-(*this)(2,0)*(*this)(0,2);	inv(1,2)=(*this)(0,2)*(*this)(1,0)-(*this)(1,2)*(*this)(0,0);
+					inv(2,0)=(*this)(1,0)*(*this)(2,1)-(*this)(1,1)*(*this)(2,0);	inv(2,1)=(*this)(0,1)*(*this)(2,0)-(*this)(0,0)*(*this)(2,1);	inv(2,2)=(*this)(0,0)*(*this)(1,1)-(*this)(0,1)*(*this)(1,0);
+					inv.MatrDivScale((*this).Det());
+					this->CopyFromMatrix(inv);
+					break;
+					}
+				case 4:
+					{
+					ChMatrixDynamic<Real> inv(4,4);
+					inv.SetElement(0,0, (*this)(1,2)*(*this)(2,3)*(*this)(3,1) - (*this)(1,3)*(*this)(2,2)*(*this)(3,1) + (*this)(1,3)*(*this)(2,1)*(*this)(3,2) - (*this)(1,1)*(*this)(2,3)*(*this)(3,2) - (*this)(1,2)*(*this)(2,1)*(*this)(3,3) + (*this)(1,1)*(*this)(2,2)*(*this)(3,3));
+					inv.SetElement(0,1, (*this)(0,3)*(*this)(2,2)*(*this)(3,1) - (*this)(0,2)*(*this)(2,3)*(*this)(3,1) - (*this)(0,3)*(*this)(2,1)*(*this)(3,2) + (*this)(0,1)*(*this)(2,3)*(*this)(3,2) + (*this)(0,2)*(*this)(2,1)*(*this)(3,3) - (*this)(0,1)*(*this)(2,2)*(*this)(3,3));
+					inv.SetElement(0,2, (*this)(0,2)*(*this)(1,3)*(*this)(3,1) - (*this)(0,3)*(*this)(1,2)*(*this)(3,1) + (*this)(0,3)*(*this)(1,1)*(*this)(3,2) - (*this)(0,1)*(*this)(1,3)*(*this)(3,2) - (*this)(0,2)*(*this)(1,1)*(*this)(3,3) + (*this)(0,1)*(*this)(1,2)*(*this)(3,3));
+					inv.SetElement(0,3, (*this)(0,3)*(*this)(1,2)*(*this)(2,1) - (*this)(0,2)*(*this)(1,3)*(*this)(2,1) - (*this)(0,3)*(*this)(1,1)*(*this)(2,2) + (*this)(0,1)*(*this)(1,3)*(*this)(2,2) + (*this)(0,2)*(*this)(1,1)*(*this)(2,3) - (*this)(0,1)*(*this)(1,2)*(*this)(2,3));
+					inv.SetElement(1,0, (*this)(1,3)*(*this)(2,2)*(*this)(3,0) - (*this)(1,2)*(*this)(2,3)*(*this)(3,0) - (*this)(1,3)*(*this)(2,0)*(*this)(3,2) + (*this)(1,0)*(*this)(2,3)*(*this)(3,2) + (*this)(1,2)*(*this)(2,0)*(*this)(3,3) - (*this)(1,0)*(*this)(2,2)*(*this)(3,3));
+					inv.SetElement(1,1, (*this)(0,2)*(*this)(2,3)*(*this)(3,0) - (*this)(0,3)*(*this)(2,2)*(*this)(3,0) + (*this)(0,3)*(*this)(2,0)*(*this)(3,2) - (*this)(0,0)*(*this)(2,3)*(*this)(3,2) - (*this)(0,2)*(*this)(2,0)*(*this)(3,3) + (*this)(0,0)*(*this)(2,2)*(*this)(3,3));
+					inv.SetElement(1,2, (*this)(0,3)*(*this)(1,2)*(*this)(3,0) - (*this)(0,2)*(*this)(1,3)*(*this)(3,0) - (*this)(0,3)*(*this)(1,0)*(*this)(3,2) + (*this)(0,0)*(*this)(1,3)*(*this)(3,2) + (*this)(0,2)*(*this)(1,0)*(*this)(3,3) - (*this)(0,0)*(*this)(1,2)*(*this)(3,3));
+					inv.SetElement(1,3, (*this)(0,2)*(*this)(1,3)*(*this)(2,0) - (*this)(0,3)*(*this)(1,2)*(*this)(2,0) + (*this)(0,3)*(*this)(1,0)*(*this)(2,2) - (*this)(0,0)*(*this)(1,3)*(*this)(2,2) - (*this)(0,2)*(*this)(1,0)*(*this)(2,3) + (*this)(0,0)*(*this)(1,2)*(*this)(2,3));
+					inv.SetElement(2,0, (*this)(1,1)*(*this)(2,3)*(*this)(3,0) - (*this)(1,3)*(*this)(2,1)*(*this)(3,0) + (*this)(1,3)*(*this)(2,0)*(*this)(3,1) - (*this)(1,0)*(*this)(2,3)*(*this)(3,1) - (*this)(1,1)*(*this)(2,0)*(*this)(3,3) + (*this)(1,0)*(*this)(2,1)*(*this)(3,3));
+					inv.SetElement(2,1, (*this)(0,3)*(*this)(2,1)*(*this)(3,0) - (*this)(0,1)*(*this)(2,3)*(*this)(3,0) - (*this)(0,3)*(*this)(2,0)*(*this)(3,1) + (*this)(0,0)*(*this)(2,3)*(*this)(3,1) + (*this)(0,1)*(*this)(2,0)*(*this)(3,3) - (*this)(0,0)*(*this)(2,1)*(*this)(3,3));
+					inv.SetElement(2,2, (*this)(0,1)*(*this)(1,3)*(*this)(3,0) - (*this)(0,3)*(*this)(1,1)*(*this)(3,0) + (*this)(0,3)*(*this)(1,0)*(*this)(3,1) - (*this)(0,0)*(*this)(1,3)*(*this)(3,1) - (*this)(0,1)*(*this)(1,0)*(*this)(3,3) + (*this)(0,0)*(*this)(1,1)*(*this)(3,3));
+					inv.SetElement(2,3, (*this)(0,3)*(*this)(1,1)*(*this)(2,0) - (*this)(0,1)*(*this)(1,3)*(*this)(2,0) - (*this)(0,3)*(*this)(1,0)*(*this)(2,1) + (*this)(0,0)*(*this)(1,3)*(*this)(2,1) + (*this)(0,1)*(*this)(1,0)*(*this)(2,3) - (*this)(0,0)*(*this)(1,1)*(*this)(2,3));
+					inv.SetElement(3,0, (*this)(1,2)*(*this)(2,1)*(*this)(3,0) - (*this)(1,1)*(*this)(2,2)*(*this)(3,0) - (*this)(1,2)*(*this)(2,0)*(*this)(3,1) + (*this)(1,0)*(*this)(2,2)*(*this)(3,1) + (*this)(1,1)*(*this)(2,0)*(*this)(3,2) - (*this)(1,0)*(*this)(2,1)*(*this)(3,2));
+					inv.SetElement(3,1, (*this)(0,1)*(*this)(2,2)*(*this)(3,0) - (*this)(0,2)*(*this)(2,1)*(*this)(3,0) + (*this)(0,2)*(*this)(2,0)*(*this)(3,1) - (*this)(0,0)*(*this)(2,2)*(*this)(3,1) - (*this)(0,1)*(*this)(2,0)*(*this)(3,2) + (*this)(0,0)*(*this)(2,1)*(*this)(3,2));
+					inv.SetElement(3,2, (*this)(0,2)*(*this)(1,1)*(*this)(3,0) - (*this)(0,1)*(*this)(1,2)*(*this)(3,0) - (*this)(0,2)*(*this)(1,0)*(*this)(3,1) + (*this)(0,0)*(*this)(1,2)*(*this)(3,1) + (*this)(0,1)*(*this)(1,0)*(*this)(3,2) - (*this)(0,0)*(*this)(1,1)*(*this)(3,2));
+					inv.SetElement(3,3, (*this)(0,1)*(*this)(1,2)*(*this)(2,0) - (*this)(0,2)*(*this)(1,1)*(*this)(2,0) + (*this)(0,2)*(*this)(1,0)*(*this)(2,1) - (*this)(0,0)*(*this)(1,2)*(*this)(2,1) - (*this)(0,1)*(*this)(1,0)*(*this)(2,2) + (*this)(0,0)*(*this)(1,1)*(*this)(2,2));
+					inv.MatrDivScale((*this).Det());
+					this->CopyFromMatrix(inv);
+					break;
+					}
+			}
+	}
+
+
+					/// Returns true if vector is identical to other vector
+	bool	Equals ( const ChMatrix<Real>& other) { return Equals(other,0.0); }
+
+					/// Returns true if vector equals another vector, within a tolerance 'tol'
+	bool	Equals ( const ChMatrix<Real>& other, Real tol) 
+						{
+							if ((other.GetColumns() != this->columns)||(other.GetRows() != this->rows)) return false;
+							for (int nel=0; nel<rows*columns; ++nel)
+								if (fabs(ElementN(nel)-other.ElementN(nel)) > tol) return false;
+							return true;
+						}
+
+
+
+					/// Multiplies this 3x4 matrix by a quaternion, as v=[G]*q
+					/// The matrix must be 3x4.
+					///  \return The result of the multiplication, i.e. a vector.
+	template <class RealB>
+	ChVector<Real> Matr34_x_Quat (ChQuaternion<RealB> qua)
+						{
+							assert ((rows ==3) && (columns ==4));
+							return ChVector<Real> (
+										((Get34Element(0,0))*qua.e0)+
+									    ((Get34Element(0,1))*qua.e1)+
+									    ((Get34Element(0,2))*qua.e2)+
+									    ((Get34Element(0,3))*qua.e3)  ,
+										((Get34Element(1,0))*qua.e0)+
+									    ((Get34Element(1,1))*qua.e1)+
+									    ((Get34Element(1,2))*qua.e2)+
+									    ((Get34Element(1,3))*qua.e3)  ,
+										((Get34Element(2,0))*qua.e0)+
+									    ((Get34Element(2,1))*qua.e1)+
+									    ((Get34Element(2,2))*qua.e2)+
+									    ((Get34Element(2,3))*qua.e3)  );
+						}
+
+					/// Multiplies this 3x4 matrix (transposed) by a vector, as q=[G]'*v
+					/// The matrix must be 3x4.
+					///  \return The result of the multiplication, i.e. a quaternion.
+	template <class RealB>
+	ChQuaternion<Real> Matr34T_x_Vect (ChVector<RealB> va)
+						{
+							assert ((rows ==3) && (columns ==4));
+							return ChQuaternion<Real>  (
+										((Get34Element(0,0))*va.x)+
+										((Get34Element(1,0))*va.y)+
+										((Get34Element(2,0))*va.z)  ,
+										((Get34Element(0,1))*va.x)+
+									    ((Get34Element(1,1))*va.y)+
+									    ((Get34Element(2,1))*va.z)  ,
+										((Get34Element(0,2))*va.x)+
+										((Get34Element(1,2))*va.y)+
+										((Get34Element(2,2))*va.z)  ,
+										((Get34Element(0,3))*va.x)+
+										((Get34Element(1,3))*va.y)+
+										((Get34Element(2,3))*va.z)  );
+						}
+
+					/// Multiplies this 4x4 matrix (transposed) by a quaternion, 
+					/// The matrix must be  4x4.
+					///  \return The result of the multiplication, i.e. a quaternion.
+	template <class RealB>
+	ChQuaternion<Real> Matr44_x_Quat (ChQuaternion<RealB> qua)
+						{
+							assert ((rows ==4) && (columns ==4));
+							return ChQuaternion<Real> (
+										((Get44Element(0,0))*qua.e0)+
+										((Get44Element(0,1))*qua.e1)+
+										((Get44Element(0,2))*qua.e2)+
+										((Get44Element(0,3))*qua.e3)  ,
+										((Get44Element(1,0))*qua.e0)+
+										((Get44Element(1,1))*qua.e1)+
+										((Get44Element(1,2))*qua.e2)+
+										((Get44Element(1,3))*qua.e3)  ,
+										((Get44Element(2,0))*qua.e0)+
+										((Get44Element(2,1))*qua.e1)+
+										((Get44Element(2,2))*qua.e2)+
+										((Get44Element(2,3))*qua.e3)  ,
+										((Get44Element(3,0))*qua.e0)+
+										((Get44Element(3,1))*qua.e1)+
+										((Get44Element(3,2))*qua.e2)+
+										((Get44Element(3,3))*qua.e3)  );
+						}
+
+					/// Transposes only the lower-right 3x3 submatrix of a hemisimetric 4x4 matrix,
+					/// used when the 4x4 matrix is a "star" matrix [q] coming from a quaternion q:
+					/// the non commutative quat. product is: 
+					///     q1 x q2  =  [q1]*q2  =  [q2st]*q1 
+					/// where [q2st] is the "semitranspose of [q2].
+	void MatrXq_SemiTranspose()
+						{
+							SetElement (1,2, -GetElement (1,2));
+							SetElement (1,3, -GetElement (1,3));
+							SetElement (2,1, -GetElement (2,1));
+							SetElement (2,3, -GetElement (2,3));
+							SetElement (3,1, -GetElement (3,1));
+							SetElement (3,2, -GetElement (3,2));
+						}
+
+					/// Change the sign of the 2nd, 3rd and 4th columns of a 4x4 matrix,
+					/// The product between a quaternion q1 and the coniugate of q2 (q2'), is:
+					///    q1 x q2'  = [q1]*q2'   = [q1sn]*q2
+					/// where [q1sn] is the seminegation of the 4x4 matrix [q1]. 
+	void MatrXq_SemiNeg()
+						{
+							for (int i=0;i < rows;++i)
+								for (int j=1;j < columns;++j)
+									SetElement (i,j,-GetElement(i,j));
+						}
+
+
+					/// Gets the norm infinite of the matrix, i.e. the max.
+					/// of its elements in absolute value.
+	Real NormInf ()
+						{
+							Real norm = 0;
+							for (int nel=0; nel<rows*columns; ++nel)
+								if ( (fabs (ElementN(nel))) > norm)
+									norm= fabs (ElementN(nel));
+							return norm;
+						}
+
+					/// Gets the norm two of the matrix, i.e. the square root
+					/// of the sum of the elements squared.
+	Real NormTwo ()
+						{
+							Real norm = 0;
+								for (int nel=0; nel<rows*columns; ++nel)	
+									norm += ElementN(nel)*ElementN(nel);
+							return (sqrt(norm));
+						}
+
+
+					/// Finds max value among the values of the matrix
+	Real Max()			{
+							Real mmax = GetElement(0,0);
+							for (int nel=0; nel<rows*columns; ++nel)
+								if (ElementN(nel)>mmax) mmax = ElementN(nel);
+							return mmax;
+						}
+					/// Finds min value among the values of the matrix
+	Real Min()			{
+							Real mmin = GetElement(0,0);
+							for (int nel=0; nel<rows*columns; ++nel)
+								if (ElementN(nel)<mmin) mmin = ElementN(nel);
+							return mmin;
+						}
+
+					/// Linear interpolation of two matrices. Parameter mx must be 0...1.
+					/// [this] =(1-x)[A]+ (x)[B]    Matrices must have the same size!!
+	void LinInterpolate(const ChMatrix<Real>& matra, const ChMatrix<Real>& matrb, double mx)
+						{
+							assert (matra.columns==matrb.columns && matra.rows==matrb.rows);
+							for (int nel=0; nel<rows*columns; nel++)
+								ElementN(nel)= matra.ElementN(nel)*(1.0-mx) + matrb.ElementN(nel)*(mx);
+						}
+
+					/// Fills a matrix or a vector with a bilinear interpolation, 
+					/// from corner values (as a u-v patch).
+	void RowColInterp(double vmin, double vmax, double umin, double umax)
+						{
+							for (int iu = 0; iu <GetColumns(); iu++)
+								for (int iv = 0; iv <GetRows(); iv++)
+								{
+									if (GetRows()>1)    Element(iv,iu) =  vmin+(vmax-vmin)*((double)iv/((double)(GetRows()-1)));
+									if (GetColumns()>1)	Element(iv,iu) += umin+(umax-umin)*((double)iu/((double)(GetColumns()-1)));
+								}
+						}
+
+
+
+
+
+
+			//
+			// BOOKKEEPING
+			//
+
+
+					/// Paste a matrix "matra" into "this", inserting at location insrow-inscol.
+					/// Normal copy for insrow=inscol=0 
+	template <class RealB>
+	void PasteMatrix (ChMatrix<RealB>* matra, int insrow, int inscol)
+						{
+							for (int i=0;i < matra->GetRows();++i)
+								for (int j=0;j < matra->GetColumns();++j)
+									Element(i+insrow, j+inscol) = matra->Element (i,j);
+						}
+
+					/// Paste a matrix "matra" into "this", inserting at location insrow-inscol
+					/// and performing a sum with the preexisting values.
+	template <class RealB>
+	void PasteSumMatrix (ChMatrix<RealB>* matra, int insrow, int inscol)
+						{
+							for (int i=0;i < matra->GetRows();++i)
+								for (int j=0;j < matra->GetColumns();++j)
+									Element(i+insrow, j+inscol) += matra->Element (i,j);
+						}
+
+					/// Paste a matrix "matra", transposed, into "this", inserting at location insrow-inscol.
+					/// Normal copy for insrow=inscol=0 
+	template <class RealB>
+	void PasteTranspMatrix (ChMatrix<RealB>* matra, int insrow, int inscol)
+						{
+							for (int i=0;i <  matra->GetRows(); ++i)
+								for (int j=0;j < matra->GetColumns(); ++j)
+									Element(j+insrow, i+inscol) = matra->Element (i,j);
+						}
+
+					/// Paste a matrix "matra", transposed, into "this", inserting at location insrow-inscol
+					/// and performing a sum with the preexisting values.
+	template <class RealB>
+	void PasteSumTranspMatrix (ChMatrix<RealB>* matra, int insrow, int inscol)
+						{
+							for (int i=0;i <  matra->GetRows(); ++i)
+								for (int j=0;j < matra->GetColumns(); ++j)
+									Element(j+insrow, i+inscol) += matra->Element (i,j);
+						}
+
+					/// Paste a clipped portion of the matrix "matra" into "this",
+					/// inserting the clip (of size nrows, ncolumns) at the location insrow-inscol.
+	template <class RealB>
+	void PasteClippedMatrix (ChMatrix<RealB>* matra, int cliprow, int clipcol, int nrows, int ncolumns, int insrow, int inscol)
+						{
+							for (int i=0;i < nrows;++i)
+								for (int j=0;j < ncolumns;++j)
+									Element (i+insrow, j+inscol) = (Real)matra->Element (i+cliprow,j+clipcol);
+						}
+
+					/// Paste a clipped portion of the matrix "matra" into "this", performing a sum with preexisting values,
+					/// inserting the clip (of size nrows, ncolumns) at the location insrow-inscol.
+	template <class RealB>
+	void PasteSumClippedMatrix (ChMatrix<RealB>* matra, int cliprow, int clipcol, int nrows, int ncolumns, int insrow, int inscol)
+						{
+							for (int i=0;i < nrows;++i)
+								for (int j=0;j < ncolumns;++j)
+									Element (i+insrow, j+inscol) += (Real)matra->Element (i+cliprow,j+clipcol);
+						}
+
+					/// Paste a vector "va" into the matrix.
+	template <class RealB>
+	void PasteVector (ChVector<RealB> va, int insrow, int inscol)
+						{
+							SetElement (insrow,   inscol, (Real)va.x);
+							SetElement (insrow+1, inscol, (Real)va.y);
+							SetElement (insrow+2, inscol, (Real)va.z);
+						}
+
+
+					/// Paste a vector "va" into the matrix, summing it with preexisting values..
+	template <class RealB>
+	void PasteSumVector (ChVector<RealB> va, int insrow, int inscol)
+						{
+							Element (insrow,   inscol) += va.x;
+							Element (insrow+1, inscol) += va.y;
+							Element (insrow+2, inscol) += va.z;
+						}
+
+					/// Paste a vector "va" into the matrix, subtracting it with preexisting values..
+	template <class RealB>
+	void PasteSubVector (ChVector<RealB> va, int insrow, int inscol)
+						{
+							Element (insrow,   inscol) -= va.x;
+							Element (insrow+1, inscol) -= va.y;
+							Element (insrow+2, inscol) -= va.z;
+						}
+
+					/// Paste a quaternion into the matrix.
+	template <class RealB>
+	void PasteQuaternion (ChQuaternion<RealB> qa, int insrow, int inscol)
+						{
+							SetElement (insrow,   inscol, qa.e0);
+							SetElement (insrow+1, inscol, qa.e1);
+							SetElement (insrow+2, inscol, qa.e2);
+							SetElement (insrow+3, inscol, qa.e3);
+						}
+
+					/// Paste a quaternion into the matrix, summing it with preexisting values..
+	template <class RealB>
+	void PasteSumQuaternion (ChQuaternion<RealB> qa, int insrow, int inscol)
+						{
+							Element (insrow,   inscol) += qa.e0;
+							Element (insrow+1, inscol) += qa.e1;
+							Element (insrow+2, inscol) += qa.e2;
+							Element (insrow+3, inscol) += qa.e3;
+						}
+
+					/// Paste a coordsys into the matrix.
+	template <class RealB>
+	void PasteCoordsys (ChCoordsys<RealB> cs, int insrow, int inscol)
+						{
+							PasteVector		(cs.pos, insrow, inscol);
+							PasteQuaternion	(cs.rot, insrow+3 ,inscol);
+						}
+
+					/// Returns the vector clipped from insrow, inscol.
+	ChVector<Real> ClipVector ( int insrow, int inscol)
+						{	return ChVector<Real>(Element (insrow,inscol), Element (insrow+1,inscol), Element (insrow+2,inscol)); }
+
+					/// Returns the quaternion clipped from insrow, inscol.
+	ChQuaternion<Real> ClipQuaternion ( int insrow, int inscol)
+						{	return ChQuaternion<Real>(Element (insrow,inscol), Element (insrow+1,inscol), Element (insrow+2,inscol), Element (insrow+3,inscol)); }
+
+					/// Returns the coordsys clipped from insrow, inscol.
+	ChCoordsys<Real> ClipCoordsys ( int insrow, int inscol)
+						{	return ChCoordsys<Real>(ClipVector (insrow, inscol), ClipQuaternion (insrow+3, inscol)) ; }
+
+
+
+
+			//
+			// MULTIBODY SPECIFIC MATH FUCTION
+			//
+
+					/// Fills a 4x4 matrix as the "star" matrix, representing quaternion cross product.
+					/// That is, given two quaternions a and b, aXb= [Astar]*b
+	template <class RealB>
+	void Set_Xq_matrix	( ChQuaternion<RealB> q )
+	{
+		Set44Element (0,0, q.e0 );
+		Set44Element (0,1,-q.e1 );
+		Set44Element (0,2,-q.e2 );
+		Set44Element (0,3,-q.e3 );
+		Set44Element (1,0, q.e1 );
+		Set44Element (1,1, q.e0 );
+		Set44Element (1,2,-q.e3 );
+		Set44Element (1,3, q.e2 );
+		Set44Element (2,0, q.e2 );
+		Set44Element (2,1, q.e3 );
+		Set44Element (2,2, q.e0 );
+		Set44Element (2,3,-q.e1 );
+		Set44Element (3,0, q.e3 );
+		Set44Element (3,1,-q.e2 );
+		Set44Element (3,2, q.e1 );
+		Set44Element (3,3, q.e0 );
+	}
+
+
+
+};
+
+
+
+
+
+
+
+///
+/// ChMatrixDynamic
+///
+///  Specialized 'resizeable' matrix class where the elements are allocated on heap.
+/// The size of the matrix can be known even at compile-time, and the matrix can 
+/// be freely resized also after creation. The size is unlimited (until you have memory). 
+///  Although this is the most generic type of matrix, please do not use it 
+/// where you know in advance its size because there are more efficient
+/// types for those matrices with 'static' size (for example, 3x3 rotation
+/// matrices are faster if created as ChMatrix33).
+
+
+
+template <class Real>
+class ChMatrixDynamic : public ChMatrix<Real>
+{
+private:
+			//
+			// DATA
+			//
+
+			/// [simply use the  "Real* address" pointer of the base class
+
+public:			
+			//
+			// CONSTRUCTORS
+			//
+
+									/// The default constructor builds a 3x3 matrix, 
+	inline ChMatrixDynamic () 
+						{ 
+							this->rows= 3;
+							this->columns = 3;
+							this->address = new Real[9];
+							SetZero(9);
+						}	
+									/// Copy constructor 
+	inline ChMatrixDynamic (const ChMatrixDynamic<Real>& msource)
+						{
+							this->rows= msource.GetRows();
+							this->columns= msource.GetColumns();
+							this->address= new Real[this->rows*this->columns];
+							ElementsCopy(this->address, msource.GetAddress(), this->rows*this->columns); //memcpy (address, msource.GetAddress(), (sizeof(Real) * rows * columns));
+						}
+									/// Copy constructor from all types of base matrices
+	template <class RealB>
+	inline ChMatrixDynamic (const ChMatrix<RealB>& msource)
+						{
+							this->rows= msource.GetRows();
+							this->columns= msource.GetColumns();
+							this->address= new Real[this->rows*this->columns];
+							ElementsCopy(this->address, msource.GetAddress(), this->rows*this->columns); //memcpy (address, msource.GetAddress(), (sizeof(Real) * rows * columns));
+						}
+									/// The constructor for a generic nxm matrix. 
+									/// Rows and columns cannot be zero or negative.
+	inline ChMatrixDynamic (const int row, const int col )
+						{
+							assert (row >=0 && col >=0);
+							this->rows= row;
+							this->columns = col;
+							this->address = new Real[row*col]; 
+							SetZero(row*col);
+						};
+
+
+									/// Destructor
+									/// Delete allocated heap mem. 
+	virtual inline ~ChMatrixDynamic () 
+						{ 
+							delete[]this->address; 
+						};
+
+			//
+			// OPERATORS
+			//
+					/// Assignment operator (from generic other matrix, it always work)
+	inline	ChMatrixDynamic<Real>&	operator =(const ChMatrix<Real>& matbis)
+						{
+							ChMatrix<Real>::operator=(matbis);
+							return *this;
+						}
+
+					///	Negates sign of the matrix. 
+					/// Performance warning: a new object is created.
+	ChMatrixDynamic<Real> operator-() 
+						{ ChMatrixDynamic<Real> result (*this); result.MatrNeg(); return result;};
+
+					///	Sums this matrix and another matrix. 
+					/// Performance warning: a new object is created.
+	template <class RealB>
+	ChMatrixDynamic<Real> operator+(const ChMatrix<RealB>& matbis) 
+						{ ChMatrixDynamic<Real> result (this->rows, this->columns); result.MatrAdd (*this, matbis); return result;}
+
+					///	Subtracts this matrix and another matrix. 
+					/// Performance warning: a new object is created.
+	template <class RealB>
+    ChMatrixDynamic<Real> operator-(const ChMatrix<RealB>& matbis) 
+						{ ChMatrixDynamic<Real> result (this->rows, this->columns); result.MatrSub (*this, matbis); return result;}
+
+					///	Multiplies this matrix and another matrix. 
+					/// Performance warning: a new object is created.
+	template <class RealB>
+	ChMatrixDynamic<Real> operator*(const ChMatrix<RealB>& matbis)	
+						{ ChMatrixDynamic<Real> result (this->rows, matbis.GetColumns()); result.MatrMultiply (*this, matbis); return result;}
+
+					///	Multiplies this matrix by a scalar value.
+					/// Performance warning: a new object is created.
+	ChMatrixDynamic<Real> operator*(const Real factor) 
+						{ ChMatrixDynamic<Real> result (*this); result.MatrScale (factor); return result;};
+
+
+			//
+			// FUNCTIONS
+			//
+									/// Reallocate memory for a new size.
+	virtual inline void Resize(int nrows, int ncols)
+						{
+							assert (nrows >= 0 && ncols >= 0);
+							if ((nrows != this->rows) || (ncols != this->columns))
+							{
+								this->rows= nrows;
+								this->columns= ncols;
+								delete[]this->address;		
+								this->address= new Real[this->rows*this->columns]; 
+								SetZero(this->rows*this->columns);
+							}
+						}
+};
+
+
+
+
+///
+/// ChMatrixNM
+///
+/// Specialized matrix class having a pre-allocated NxM buffer of elements on stack.
+///  This means that elements are put the stack when the matrix is created, and this
+/// can be more efficient than heap allocation (but, please, do not use too large N or M 
+/// sizes, this is meant to work up to 10x10, for example; prefer ChMatrixDyamic for larger).
+///  The NxM size must be known 'statically', at compile-time; however later at run-time
+/// this matrix can be resized anyway (but for larger size than NxM, it falls back to 
+/// heap allocation). Note that if resizing is often required, it may be better
+/// to create a ChMatrixDyamic instead, from the beginning.
+
+
+
+template <class Real = double, int preall_rows=3, int preall_columns=3>
+class ChMatrixNM : public ChMatrix<Real>
+{
+protected:
+	Real  buffer[preall_rows*preall_columns];
+
+public:			
+			//
+			// CONSTRUCTORS
+			//
+
+									/// The default constructor builds a NxN matrix, 
+	inline ChMatrixNM () 
+						{ 
+							this->rows= preall_rows;
+							this->columns = preall_columns;
+							this->address = buffer;
+							SetZero(preall_rows*preall_columns);
+						}	
+									/// Copy constructor
+	inline ChMatrixNM (const ChMatrixNM<Real,preall_rows,preall_columns>& msource) 
+						{
+							this->rows= preall_rows;
+							this->columns = preall_columns;
+							this->address = buffer;
+							ElementsCopy(this->address, msource.address, preall_rows*preall_columns); 
+						}
+									/// Copy constructor from all types of base matrices (only with same size)
+	template <class RealB>
+	inline ChMatrixNM (const ChMatrix<RealB>& msource) 
+						{
+							assert(msource.GetColumns()==preall_columns && msource.GetRows()==preall_rows);
+							this->rows= preall_rows;
+							this->columns = preall_columns;
+							this->address = buffer;
+							ElementsCopy(this->address, msource.GetAddress(), preall_rows*preall_columns);
+						}
+									/// Destructor
+	virtual inline ~ChMatrixNM () { 
+						};
+
+			//
+			// OPERATORS
+			//
+
+					/// Assignment operator (from generic other matrix, acceptable only if other matrix has same size)
+	ChMatrixNM<Real,preall_rows,preall_columns>& operator =(const ChMatrix<Real>& matbis)
+						{
+							assert(matbis.GetColumns()==preall_columns && matbis.GetRows()==preall_rows);
+							ChMatrix<Real>::operator=(matbis);
+							return *this;
+						}
+
+					///	Negates sign of the matrix. 
+					/// Performance warning: a new object is created.
+	ChMatrixNM<Real,preall_rows,preall_columns> operator-() 
+						{ 
+							ChMatrixNM<Real,preall_rows,preall_columns> result (*this); 
+							result.MatrNeg(); 
+							return result;
+						};
+
+					///	Sums this matrix and another matrix (of same size) 
+					/// Performance warning: a new object is created.
+	template <class RealB>
+	ChMatrixNM<Real,preall_rows,preall_columns> operator+(const ChMatrix<RealB>& matbis) 
+						{ 
+							ChMatrixNM<Real,preall_rows,preall_columns> result; 
+							result.MatrAdd (*this, matbis); 
+							return result;
+						}
+
+					///	Subtracts this matrix and another matrix (of same size). 
+					/// Performance warning: a new object is created.
+	template <class RealB>
+    ChMatrixNM<Real,preall_rows,preall_columns> operator-(const ChMatrix<RealB>& matbis) 
+						{ 
+							ChMatrixNM<Real,preall_rows,preall_columns> result; 
+							result.MatrSub (*this, matbis); 
+							return result;
+						}
+
+					///	Multiplies this matrix and another ChMatrixNM matrix.
+					/// This is optimized: it returns another ChMatrixMN because size of matbis is known statically.
+					/// Performance warning: a new object is created.
+	template <class RealB, int B_rows, int B_columns>
+	ChMatrixNM<Real,preall_rows,B_columns> operator*(const ChMatrixNM<RealB,preall_columns,B_columns>& matbis)	
+						{ 
+							ChMatrixNM<Real, preall_rows,B_columns> result;
+							result.MatrMultiply (*this, matbis); 
+							return result;
+						}
+
+					///	Multiplies this matrix and another generic matrix.
+					/// Returns a ChMatrixDynamic matrix, because size of matbis is not known at compile time.
+					/// Performance warning: a new object is created.
+	template <class RealB>
+	ChMatrixDynamic<Real> operator*(const ChMatrix<RealB>& matbis)	
+						{ 
+							ChMatrixDynamic<Real> result (this->rows, matbis.GetColumns());
+							result.MatrMultiply (*this, matbis); 
+							return result;
+						}
+
+					///	Multiplies this matrix by a scalar value
+					/// Performance warning: a new object is created.
+	ChMatrixNM<Real,preall_rows,preall_columns> operator*(const Real factor) 
+						{ ChMatrixNM<Real,preall_rows,preall_columns> result (*this); result.MatrScale (factor); return result;};
+
+
+
+			//
+			// FUNCTIONS
+			//
+									/// Resize for this matrix is NOT SUPPORTED ! DO NOTHING!
+	virtual inline void Resize(int nrows, int ncols)
+						{
+							assert ((nrows == this->rows) && (ncols == this->columns));
+						}
+
+};
+
+
+
+
+
+
+///
+/// ChMatrix33
+///
+/// A special type of NxM matrix: the 3x3 matrix that is commonly used 
+/// to represent coordinate transformations in 3D space.
+/// This matrix cannot be resized.
+/// The 3x3 matrix can be multiplied/added with other matrix types.
+///
+
+
+template <class Real = double>
+class ChMatrix33 : public ChMatrixNM<Real,3,3>
+{
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+					/// Default constructor builds a 3x3 matrix with zeroes.
+	inline ChMatrix33() : ChMatrixNM<Real,3,3>() {};
+
+					/// Copy constructor 
+	inline ChMatrix33 (const ChMatrix33<Real>& msource) : ChMatrixNM<Real,3,3>(msource) {};
+
+					/// Copy constructor from all types of base matrices (only with same size)
+	template <class RealB>
+	inline ChMatrix33 (const ChMatrix<RealB>& msource) 
+						{
+							assert(msource.GetColumns()==3 && msource.GetRows()==3);
+							this->rows= 3;
+							this->columns = 3;
+							this->address = this->buffer;
+							ElementsCopy(this->address, msource.GetAddress(), 9); 
+						}
+
+					/// The constructor which builds a 3x3 matrix given a 
+					/// quaternion representing rotation
+	template <class RealB>
+	inline ChMatrix33 (const ChQuaternion<RealB>& mq)   
+						{ 
+							this->rows= 3;
+							this->columns = 3;
+							this->address = this->buffer;
+							Set_A_quaternion(mq);
+						}
+
+
+			//
+			// OPERATORS
+			//
+						/// Assignment operator (from generic other matrix, acceptable only if other matrix has 3x3 size)
+	inline ChMatrix33<Real>&  operator =(const ChMatrix<Real>& matbis)
+						{
+							assert(matbis.GetColumns()==3 && matbis.GetRows()==3);
+							ChMatrix<Real>::operator=(matbis);
+							return *this;
+						}
+
+					///	Negates sign of the matrix. 
+					/// Performance warning: a new object is created.
+	ChMatrix33<Real> operator-() 
+						{ 
+							ChMatrix33<Real> result (*this); 
+							result.MatrNeg(); 
+							return result;
+						};
+
+					///	Sums this matrix and another matrix (of same size)
+					/// Performance warning: a new object is created.
+	template <class RealB>
+	ChMatrix33<Real> operator+(const ChMatrix<RealB>& matbis) 
+						{ 
+							ChMatrix33<Real> result; 
+							result.MatrAdd (*this, matbis); 
+							return result;
+						}
+
+					///	Subtracts this matrix and another matrix (of same size). 
+					/// Performance warning: a new object is created.
+	template <class RealB>
+    ChMatrix33<Real> operator-(const ChMatrix<RealB>& matbis) 
+						{ 
+							ChMatrix33<Real> result; 
+							result.MatrSub (*this, matbis); 
+							return result;
+						}
+
+					///	Multiplies this ChMatrix33 matrix and another ChMatrix33 matrix. 
+					/// Performance warning: a new object is created.
+	template <class RealB>
+	ChMatrix33<Real> operator*(const ChMatrix33<RealB>& matbis)	
+						{ 
+							ChMatrix33<Real> result; 
+							result.MatrMultiply (*this, matbis); 
+							return result;
+						}
+
+					///	Multiplies this matrix and another ChMatrixNM matrix (3xN). 
+					/// Performance warning: a new object is created (of ChMatrixNM type).
+	template <class RealB, int B_rows, int B_columns>
+	ChMatrixNM<Real,3, B_columns> operator*(const ChMatrixNM<RealB,3, B_columns>& matbis)	
+						{ 
+							ChMatrixNM<Real, 3, B_columns> result; // try statical sizing
+							result.MatrMultiply (*this, matbis); 
+							return result;
+						}
+
+					///	Multiplies this matrix and another generic matrix. 
+					/// Performance warning: a new object is created (of ChMatrixDynamic type).
+	template <class RealB>
+	ChMatrixDynamic<Real> operator*(const ChMatrix<RealB>& matbis)	
+						{ 
+							ChMatrixDynamic<Real> result (this->rows, matbis.GetColumns()); 
+							result.MatrMultiply (*this, matbis); 
+							return result;
+						}
+
+					///	Multiplies this matrix by a scalar value
+					/// Performance warning: a new object is created.
+	ChMatrix33<Real> operator*(const Real factor) 
+						{ ChMatrix33<Real> result (*this); result.MatrScale (factor); return result;};
+
+					///	Multiplies this matrix by a vector.
+	ChVector<Real> operator*(const ChVector<Real>& myvect) 
+						{ return (this->Matr_x_Vect (myvect)); };
+
+			//
+			// FUNCTIONS
+			//
+
+					/// Reset to identity a 3x3 matrix (ones on diagonal, zero elsewhere)
+					/// Note: optimized, for 3x3 matrices ONLY!
+	void Set33Identity()
+						{
+							this->Reset();
+							this->Set33Element(0,0, 1.0); this->Set33Element(1,1, 1.0); this->Set33Element(2,2, 1.0);
+						}	
+
+					/// Multiplies this matrix by a vector, like in coordinate rotation [M]*v. 
+					///  \return The result of the multiplication, i.e. a vector.
+	template <class RealB>
+	inline ChVector<Real> Matr_x_Vect	(ChVector<RealB> va) const
+						{
+							return ChVector<Real> (
+										(( this->Get33Element(0,0))*va.x)+
+										(( this->Get33Element(0,1))*va.y)+
+										(( this->Get33Element(0,2))*va.z),
+										(( this->Get33Element(1,0))*va.x)+
+										(( this->Get33Element(1,1))*va.y)+
+										(( this->Get33Element(1,2))*va.z),
+										(( this->Get33Element(2,0))*va.x)+
+										(( this->Get33Element(2,1))*va.y)+
+										(( this->Get33Element(2,2))*va.z) );
+						}
+
+					/// Multiplies this matrix (transposed) by a vector, as [M]'*v
+					///  \return The result of the multiplication, i.e. a vector.
+	template <class RealB>
+	inline ChVector<Real> MatrT_x_Vect	(ChVector<RealB> va) const
+						{
+							return ChVector<Real> (
+										((this->Get33Element(0,0))*va.x)+
+										((this->Get33Element(1,0))*va.y)+
+										((this->Get33Element(2,0))*va.z)  ,
+										((this->Get33Element(0,1))*va.x)+
+										((this->Get33Element(1,1))*va.y)+
+										((this->Get33Element(2,1))*va.z)  ,
+										((this->Get33Element(0,2))*va.x)+
+										((this->Get33Element(1,2))*va.y)+
+										((this->Get33Element(2,2))*va.z)  );
+						}
+
+					/// Fast inversion of small matrices. Result will be in 'matra'.
+					/// \return Returns the determinant.
+	template <class RealB>
+	double FastInvert (ChMatrix33<RealB>* matra)
+					{
+						double det;
+						double sdet0, sdet1, sdet2;
+
+						sdet0 =+(this->Get33Element(1,1) * this->Get33Element(2,2))
+							   -(this->Get33Element(2,1) * this->Get33Element(1,2));
+						sdet1 =-(this->Get33Element(1,0) * this->Get33Element(2,2))
+							   +(this->Get33Element(2,0) * this->Get33Element(1,2));
+						sdet2 =+(this->Get33Element(1,0) * this->Get33Element(2,1))
+							   -(this->Get33Element(2,0) * this->Get33Element(1,1));
+
+						det = sdet0 * this->Get33Element(0,0) +
+							  sdet1 * this->Get33Element(0,1) +
+							  sdet2 * this->Get33Element(0,2);
+
+						matra->Set33Element (0,0, sdet0/det);
+						matra->Set33Element (1,0, sdet1/det);
+						matra->Set33Element (2,0, sdet2/det);
+						matra->Set33Element (0,1,(-(this->Get33Element(0,1) * this->Get33Element(2,2))
+												  +(this->Get33Element(2,1) * this->Get33Element(0,2)))/det);
+						matra->Set33Element (1,1,(+(this->Get33Element(0,0) * this->Get33Element(2,2))
+												  -(this->Get33Element(2,0) * this->Get33Element(0,2)))/det);
+						matra->Set33Element (2,1,(-(this->Get33Element(0,0) * this->Get33Element(2,1))
+												  +(this->Get33Element(2,0) * this->Get33Element(0,1)))/det);
+						matra->Set33Element (0,2,(+(this->Get33Element(0,1) * this->Get33Element(1,2))
+												  -(this->Get33Element(1,1) * this->Get33Element(0,2)))/det);
+						matra->Set33Element (1,2,(-(this->Get33Element(0,0) * this->Get33Element(1,2))
+												  +(this->Get33Element(1,0) * this->Get33Element(0,2)))/det);
+						matra->Set33Element (2,2,(+(this->Get33Element(0,0) * this->Get33Element(1,1))
+												  -(this->Get33Element(1,0) * this->Get33Element(0,1)))/det);
+
+						return (det);
+					}
+
+
+	#define EIG_ROTATE(a,i,j,k,l) g=a->Get33Element(i,j); h=a->Get33Element(k,l); a->Set33Element(i,j,g-s*(h+g*tau)); a->Set33Element(k,l,h+s*(g-h*tau));
+
+					/// Returns 3 eigenvalues and 3 eigenvectors in a 3x3 matrix, 
+					/// Notes:
+					///   - only for cases where eigenvalues are real!! 
+					///   - output eigenvectors as columns of matrix 'eigenvects'
+					///     (which will be resized to 3x3 if not yet so..)
+					///   - this original matrix is modified
+	void FastEigen(ChMatrix33<Real>& eigenvects, double eigenvals[])
+					{
+						  int n = 3;
+						  int j,iq,ip,i;
+						  double tresh,theta,tau,t,sm,s,h,g,c;
+						  int nrot;
+						  double b[3];
+						  double z[3];
+						  double d[3];
+						  ChMatrix33<double> v;
+						  //ChMatrix33<double> vout;
+
+						  v.Set33Identity();
+
+						  for(ip=0; ip<n; ip++) 
+							{
+							  b[ip] = this->Get33Element(ip,ip);
+							  d[ip] = this->Get33Element(ip,ip);
+							  z[ip] = 0.0;
+							}
+						  
+						  nrot = 0;
+						  
+						  for(i=0; i<50; i++)
+						  {
+
+							sm=0.0;
+							for(ip=0;ip<n;ip++)
+								for(iq=ip+1;iq<n;iq++) 
+									sm+=fabs(this->Get33Element(ip,iq));
+						    
+							if (sm == 0.0)
+							{
+							  //vout.CopyFromMatrix(v);
+							  //dout[0] = d[0];
+							  //dout[1] = d[1];
+							  //dout[2] = d[2];
+							  return;
+							}    
+						      
+							if (i < 3) tresh=(double)0.2*sm/(n*n);
+							  else tresh=0.0;
+						      
+							for(ip=0; ip<n; ip++) for(iq=ip+1; iq<n; iq++)
+							{
+							  g = (double)100.0*fabs(this->Get33Element(ip,iq));
+							  if (i>3 && 
+								  fabs(d[ip])+g==fabs(d[ip]) && 
+								  fabs(d[iq])+g==fabs(d[iq]))
+								this->Set33Element(ip,iq,0.0);
+							  else if (fabs(this->Get33Element(ip,iq))>tresh)
+								{
+								  h = d[iq]-d[ip];
+								  if (fabs(h)+g == fabs(h)) t=(this->Get33Element(ip,iq))/h;
+								  else
+								{
+								  theta=(double)0.5*h/(this->Get33Element(ip,iq));
+								  t=(double)(1.0/(fabs(theta)+sqrt(1.0+theta*theta)));
+								  if (theta < 0.0) t = -t;
+								}
+								  c=(double)1.0/sqrt(1+t*t);
+								  s=t*c;
+								  tau=s/((double)1.0+c);
+								  h=t*this->Get33Element(ip,iq);
+								  z[ip] -= h;
+								  z[iq] += h;
+								  d[ip] -= h;
+								  d[iq] += h;
+								  this->Set33Element(ip,iq,0.0);
+								  for(j=0;j<ip;j++) { EIG_ROTATE(this,j,ip,j,iq); } 
+								  for(j=ip+1;j<iq;j++) { EIG_ROTATE(this,ip,j,j,iq); } 
+								  for(j=iq+1;j<n;j++) { EIG_ROTATE(this,ip,j,iq,j); } 
+								  for(j=0;j<n;j++) { EIG_ROTATE((&v),j,ip,j,iq); } 
+								  nrot++;
+								}
+							}
+
+							for(ip=0;ip<n;ip++)
+							{
+							  b[ip] += z[ip];
+							  d[ip] = b[ip];
+							  z[ip] = 0.0;
+							}
+						  }
+
+						  return;
+					}
+
+					/// Fills a 3x3 matrix as a rotation matrix corresponding
+					/// to the rotation expressed by the quaternion 'quat'.
+	template <class RealB>
+	void Set_A_quaternion( ChQuaternion<RealB> quat )
+					{
+						double e0e0;
+						double e1e1;
+						double e2e2;
+						double e3e3;
+						double e0e1;
+						double e0e2;
+						double e0e3;
+						double e1e2;
+						double e1e3;
+						double e2e3;
+
+						e0e0 = quat.e0 * quat.e0;
+						e1e1 = quat.e1 * quat.e1;
+						e2e2 = quat.e2 * quat.e2;
+						e3e3 = quat.e3 * quat.e3;
+						e0e1 = quat.e0 * quat.e1;
+						e0e2 = quat.e0 * quat.e2;
+						e0e3 = quat.e0 * quat.e3;
+						e1e2 = quat.e1 * quat.e2; 
+						e1e3 = quat.e1 * quat.e3; 
+						e2e3 = quat.e2 * quat.e3; 
+					 
+						this->Set33Element (0,0, (e0e0 + e1e1) * 2 - 1);
+						this->Set33Element (0,1, (e1e2 - e0e3) * 2 );
+						this->Set33Element (0,2, (e1e3 + e0e2) * 2 );
+						this->Set33Element (1,0, (e1e2 + e0e3) * 2 );
+						this->Set33Element (1,1, (e0e0 + e2e2) * 2 - 1);
+						this->Set33Element (1,2, (e2e3 - e0e1) * 2 );
+						this->Set33Element (2,0, (e1e3 - e0e2) * 2 );
+						this->Set33Element (2,1, (e2e3 + e0e1) * 2 );
+						this->Set33Element (2,2, (e0e0 + e3e3) * 2 - 1);
+					}
+					
+					/// Fills a 3x3 matrix as the "star" matrix, representing vector cross product.
+					/// That is, given two 3d vectors a and b, aXb= [Astar]*b
+	template <class RealB>
+	void Set_X_matrix	( ChVector<RealB> vect )
+					{
+						this->Set33Element (0,0,0);
+						this->Set33Element (0,1,(- vect.z));
+						this->Set33Element (0,2,(  vect.y));
+						this->Set33Element (1,0,(  vect.z));
+						this->Set33Element (1,1,0);
+						this->Set33Element (1,2,(- vect.x));
+						this->Set33Element (2,0,(- vect.y));
+						this->Set33Element (2,1,(  vect.x));
+						this->Set33Element (2,2,0);
+					}
+
+						/// Fills a 3x3 matrix as a rotation matrix, given the three 
+					/// versors X,Y,Z of the basis.
+	template <class RealB>
+	void Set_A_axis		 ( ChVector<RealB> X, ChVector<RealB> Y, ChVector<RealB> Z)
+					{
+						this->Set33Element (0,0,X.x);
+						this->Set33Element (0,1,Y.x);
+						this->Set33Element (0,2,Z.x);
+						this->Set33Element (1,0,X.y);
+						this->Set33Element (1,1,Y.y);
+						this->Set33Element (1,2,Z.y);
+						this->Set33Element (2,0,X.z);
+						this->Set33Element (2,1,Y.z);
+						this->Set33Element (2,2,Z.z);
+					}
+
+					/// Fills a 3x3 matrix as a rotation matrix, given the three
+					/// Eulero angles (not to be confused with 'Eulero parameters', aka quaternions) 
+	template <class RealB>
+	void Set_A_Eulero	 ( ChVector<RealB> eul )
+					{
+						double cx, cy, cz, sx, sy, sz;
+						cx= cos(eul.x);
+						cy= cos(eul.y);
+						cz= cos(eul.z);
+						sx= sin(eul.x);
+						sy= sin(eul.y);
+						sz= sin(eul.z);
+
+						this->Set33Element (0,0,((cz*cx)-(cy*sx*sz)));
+						this->Set33Element (0,1,(-(sz*cx)-(cy*sx*cz)));
+						this->Set33Element (0,2,(sy*sx));
+						this->Set33Element (1,0,((cz*sx)+(cy*cx*sz)));
+						this->Set33Element (1,1,(-(sz*sx)+(cy*cx*cz)));
+						this->Set33Element (1,2,(-sy*cx));
+						this->Set33Element (2,0,(sy*sz));
+						this->Set33Element (2,1,(sy*cz));
+						this->Set33Element (2,2,(cy));
+					}
+
+					/// Fills a 3x3 matrix as a rotation matrix, given the three
+					/// Cardano angles.
+	template <class RealB>
+	void Set_A_Cardano	 ( ChVector<RealB> car )
+					{
+						double cx, cy, cz, sx, sy, sz;
+						cx= cos(car.x);
+						cy= cos(car.y);
+						cz= cos(car.z);
+						sx= sin(car.x);
+						sy= sin(car.y);
+						sz= sin(car.z);
+
+						this->Set33Element (0,0,((cx*cz)-(sz*sx*sy)));
+						this->Set33Element (0,1,(-sx*cy));
+						this->Set33Element (0,2,((cx*sz)+(sx*sy*cz)));
+						this->Set33Element (1,0,((sx*cz)+(cx*sy*sz)));
+						this->Set33Element (1,1,(cy*cx));
+						this->Set33Element (1,2,((sx*sz)-(cx*sy*cz)));
+						this->Set33Element (2,0,(-sz*cy));
+						this->Set33Element (2,1,(sy));
+						this->Set33Element (2,2,(cy*cz));
+					}
+
+					/// Fills a 3x3 matrix as a rotation matrix, given the three
+					/// head, pitch, banking  angles.
+	template <class RealB>
+	void Set_A_Hpb		 ( ChVector<RealB> hpb )
+					{
+						double cx, cy, cz, sx, sy, sz;
+						cx= cos(hpb.y);
+						cy= cos(hpb.x);
+						cz= cos(hpb.z);
+						sx= sin(hpb.y);
+						sy= sin(hpb.x);
+						sz= sin(hpb.z);
+
+						this->Set33Element (0,0,((cz*cy)-(sz*sx*sy)));
+						this->Set33Element (0,1,(-(sz*cy)-(cz*sx*sy)));
+						this->Set33Element (0,2,(-cx*sy));
+						this->Set33Element (1,0,(sz*cx));
+						this->Set33Element (1,1,(cz*cx));
+						this->Set33Element (1,2,(-sx));
+						this->Set33Element (2,0,((cz*sy)+(sz*sx*cy)));
+						this->Set33Element (2,1,(-(sz*sy)+(cz*sx*cy)));
+						this->Set33Element (2,2,(cx*cy));
+					}
+
+					/// Fills a 3x3 matrix as a rotation matrix, given the three
+					/// angles of consecutive rotations about x,y,z axis.
+	template <class RealB>
+	void Set_A_Rxyz		 ( ChVector<RealB> xyz )
+					{
+						double cx, cy, cz, sx, sy, sz;
+						cx= cos(xyz.x);
+						cy= cos(xyz.y);
+						cz= cos(xyz.z);
+						sx= sin(xyz.x);
+						sy= sin(xyz.y);
+						sz= sin(xyz.z);
+
+						this->Set33Element (0,0,(cy*cz));
+						this->Set33Element (0,1,(cy*sz));
+						this->Set33Element (0,2,(-sy));
+						this->Set33Element (1,0,((sx*sy*cz)-(cx*sz)));
+						this->Set33Element (1,1,((sx*sy*sz)+(cx*cz)));
+						this->Set33Element (1,2,(sx*cy));
+						this->Set33Element (2,0,((cx*sy*cz)+(sx*sz)));
+						this->Set33Element (2,1,((cx*sy*sz)-(sx*cz)));
+						this->Set33Element (2,2,(cx*cy));
+					}
+
+
+					/// Fills a 3x3 matrix as a rotation matrix, given the three
+					/// Rodriguez' parameters.
+	template <class RealB>
+	void Set_A_Rodriguez ( ChVector<RealB> rod )
+					{
+						double gam= pow(rod.x,2)+pow(rod.y,2)+pow(rod.z,2);
+
+						this->Set33Element (0,0,(1+pow(rod.x,2)-pow(rod.y,2)-pow(rod.z,2)));
+						this->Set33Element (0,1,(2*(rod.x*rod.y - rod.z)));
+						this->Set33Element (0,2,(2*(rod.x*rod.z + rod.y)));
+						this->Set33Element (1,0,(2*(rod.x*rod.y + rod.z)));
+						this->Set33Element (1,1,(1-pow(rod.x,2)+pow(rod.y,2)-pow(rod.z,2)));
+						this->Set33Element (1,2,(2*(rod.y*rod.z - rod.x)));
+						this->Set33Element (2,0,(2*(rod.x*rod.z - rod.y)));
+						this->Set33Element (2,1,(2*(rod.y*rod.z + rod.x)));
+						this->Set33Element (2,2,(1-pow(rod.x,2)-pow(rod.y,2)+pow(rod.z,2)));
+
+						this->MatrScale((1/(1+gam)));
+					}
+
+					/// Use the Gram-Schmidt orthonormalization to find the three
+					/// orthogonal vectors of a coordinate system whose X axis is this vector.
+					/// mVsingular (optional) suggests the XY plane, possibly it is not too parallel to X.
+	void	Set_A_Xdir( ChVector<Real> Xdir,			///< X axis 
+						ChVector<Real>* mVsingular =0	///< a direction on XY plane (optional suggestion for Y axis) 
+					   ) 
+					{
+						ChVector<Real> mX;
+						ChVector<Real> mY;
+						ChVector<Real> mZ;
+						Xdir.DirToDxDyDz(&mX,&mY,&mZ, mVsingular);
+						this->Set_A_axis(mX,mY,mZ);
+					}
+
+					/// Given a 3x3 rotation matrix, computes the corresponding 
+					/// quaternion.
+	ChQuaternion<Real> Get_A_quaternion ()
+					{
+						ChQuaternion<Real> q;
+						double s, tr;
+													// for speed reasons: ..
+						double m00 = this->Get33Element(0,0);
+						double m01 = this->Get33Element(0,1);
+						double m02 = this->Get33Element(0,2);
+						double m10 = this->Get33Element(1,0);
+						double m11 = this->Get33Element(1,1);
+						double m12 = this->Get33Element(1,2);
+						double m20 = this->Get33Element(2,0);
+						double m21 = this->Get33Element(2,1);
+						double m22 = this->Get33Element(2,2);
+
+						tr=m00 + m11 + m22;		// diag sum
+
+						if (tr >= 0)
+						{
+							s = sqrt(tr + 1);
+							q.e0 = 0.5 * s;
+							s = 0.5 / s;
+							q.e1 = (m21 - m12) * s;
+							q.e2 = (m02 - m20) * s;
+							q.e3 = (m10 - m01) * s;
+						}
+						else
+						{
+							int i = 0;
+
+							if (m11 > m00)
+							{	
+								i = 1;
+								if (m22 > m11)	i = 2;
+							}
+							else
+							{
+								if (m22 > m00)  i = 2;
+							}
+
+							switch (i)
+							{
+							case 0:
+								s = sqrt (m00 - m11 - m22 + 1);
+								q.e1 = 0.5 * s;
+								s = 0.5 / s;
+								q.e2 = (m01 + m10) * s;
+								q.e3 = (m20 + m02) * s;
+								q.e0 = (m21 - m12) * s;
+								break;
+							case 1:
+								s = sqrt (m11 - m22 - m00 + 1);
+								q.e2 = 0.5 * s;
+								s = 0.5 / s;
+								q.e3 = (m12 + m21) * s;
+								q.e1 = (m01 + m10) * s;
+								q.e0 = (m02 - m20) * s;
+								break;
+							case 2:
+								s = sqrt (m22 - m00 - m11 + 1);
+								q.e3 = 0.5 * s;
+								s = 0.5 / s;
+								q.e1 = (m20 + m02) * s;
+								q.e2 = (m12 + m21) * s;
+								q.e0 = (m10 - m01) * s;
+								break;
+							}
+						}
+						return q;
+					}
+
+					/// Given a 3x3 rotation matrix, returns the versor of X axis.
+	ChVector<Real> Get_A_Xaxis ()
+					{
+						ChVector<Real> X;
+						X.x= this->Get33Element (0,0);
+						X.y= this->Get33Element (1,0);
+						X.z= this->Get33Element (2,0);
+						return X;
+					}
+
+					/// Given a 3x3 rotation matrix, returns the versor of Y axis.
+	ChVector<Real> Get_A_Yaxis ()
+					{
+						ChVector<Real> Y;
+						Y.x= this->Get33Element (0,1);
+						Y.y= this->Get33Element (1,1);
+						Y.z= this->Get33Element (2,1);
+						return Y;
+					}
+
+					/// Given a 3x3 rotation matrix, returns the versor of Z axis.
+	ChVector<Real> Get_A_Zaxis ()
+					{
+						ChVector<Real> Z;
+						Z.x= this->Get33Element (0,2);
+						Z.y= this->Get33Element (1,2);
+						Z.z= this->Get33Element (2,2);
+						return Z;
+					}
+
+					/// Given a 3x3 rotation matrix, returns the Eulero angles.
+	ChVector<Real> Get_A_Eulero ()
+					{
+						ChVector<Real> eul;
+
+						eul.y= acos(this->GetElement(2,2));	// rho, nutation
+
+						eul.z= acos((this->GetElement(2,1))/sin(eul.y));	// csi, spin
+
+						eul.x= acos(-(this->GetElement(1,2))/sin(eul.y));	// rho, nutation
+
+						if (eul.y == 0)
+						{		// handle undefined initial position set
+							eul.x = 0;
+							eul.z = 0;
+						}
+
+						return (eul);
+					}
+
+					/// Given a 3x3 rotation matrix, returns the Cardano angles.
+	ChVector<Real> Get_A_Cardano ()
+					{
+						ChVector<Real> car;
+
+						double mel21 = this->GetElement(2,1);
+						if (mel21 >1)  mel21 =  1;
+						if (mel21 <-1) mel21 = -1;
+
+						car.y= asin(mel21);
+
+						double arg2 = (this->GetElement(2,2))/cos(car.y);
+						if (arg2 >1)  arg2 =  1;
+						if (arg2 <-1) arg2 = -1;
+						double arg3 = (this->GetElement(1,1))/cos(car.y);
+						if (arg3 >1)  arg3 =  1;
+						if (arg3 <-1) arg3 = -1;
+
+						car.z= acos(arg2);
+						car.x= acos(arg3);
+
+						return (car);
+					}
+
+					/// Given a 3x3 rotation matrix, returns the head-pitch-banking angles.
+	ChVector<Real> Get_A_Hpb ()
+					{
+						ChVector<Real> Hpb;
+
+						double arg1 = -(this->GetElement(1,2));
+						if (arg1 >1)  arg1 =  1;
+						if (arg1 <-1) arg1 = -1;
+
+						Hpb.y= asin(arg1);	// P
+
+						double arg2 = (this->GetElement(2,2))/cos(Hpb.y);
+						if (arg2 >1)  arg2 =  1;
+						if (arg2 <-1) arg2 = -1;
+						double arg3 = (this->GetElement(1,1))/cos(Hpb.y);
+						if (arg3 >1)  arg3 =  1;
+						if (arg3 <-1) arg3 = -1;
+
+						Hpb.x= acos(arg2); // H
+						Hpb.z= acos(arg3); // B
+
+						return (Hpb);
+					}
+
+					/// Given a 3x3 rotation matrix, returns the angles for
+					/// consecutive rotations on x,y,z axes..
+	ChVector<Real> Get_A_Rxyz ()
+					{
+						ChVector<Real> Rxyz;
+
+						double arg1 = -(this->GetElement(0,2));
+						if (arg1 >1)  arg1 =  1;
+						if (arg1 <-1) arg1 = -1;
+						Rxyz.y= asin(arg1);
+
+						double arg2 = (this->GetElement(0,1))/cos(Rxyz.y);
+						if (arg2 >1)  arg2 =  1;
+						if (arg2 <-1) arg2 = -1;
+						double arg3 = (this->GetElement(1,2))/cos(Rxyz.y);
+						if (arg3 >1)  arg3 =  1;
+						if (arg3 <-1) arg3 = -1;
+
+						Rxyz.z= asin(arg2);
+						Rxyz.x= asin(arg3);
+
+						return (Rxyz);
+					}
+
+					/// Given a 3x3 rotation matrix, returns the Rodriguez parameters.
+	ChVector<Real> Get_A_Rodriguez ()
+					{
+						ChVector<Real> rod;
+						ChQuaternion<Real> qtemp;
+						qtemp = Get_A_quaternion();
+						// warning: infinite results may happen..
+						rod.x = qtemp.e1 / qtemp.e0;
+						rod.y = qtemp.e2 / qtemp.e0;
+						rod.z = qtemp.e3 / qtemp.e0;
+
+						return (rod);
+					}
+					/// Returns the absolute value of each element in the matrix
+	ChMatrix33<Real> Get_Abs_Matrix()
+				{
+		ChMatrix33<Real> temp;
+
+		temp.SetElement(0,0,fabs(this->GetElement(0,0)));
+		temp.SetElement(0,1,fabs(this->GetElement(0,1)));
+		temp.SetElement(0,2,fabs(this->GetElement(0,2)));
+
+		temp.SetElement(1,0,fabs(this->GetElement(1,0)));
+		temp.SetElement(1,1,fabs(this->GetElement(1,1)));
+		temp.SetElement(1,2,fabs(this->GetElement(1,2)));
+
+		temp.SetElement(2,0,fabs(this->GetElement(2,0)));
+		temp.SetElement(2,1,fabs(this->GetElement(2,1)));
+		temp.SetElement(2,2,fabs(this->GetElement(2,2)));
+
+		return temp;
+
+				}
+
+};
+
+
+
+
+
+//
+// Conversion from/to matrix declarated as double[3][3]  \todo implement as class members
+//
+ChApi
+void Chrono_to_Marray   (ChMatrix33<>& ma, double marr[3][3]);
+
+ChApi
+void Chrono_from_Marray (ChMatrix33<>& ma, double marr[3][3]);
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#endif  // END of ChMatrix.h 
diff --git a/SRC/ChronoEngine/core/ChMemory.cpp b/SRC/ChronoEngine/core/ChMemory.cpp
new file mode 100644
index 0000000..81b4ee6
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMemory.cpp
@@ -0,0 +1,1757 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2005, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChMemory.cpp
+//
+//   Math functions for :
+//      - MEMORY DEBUGING
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+//  
+// BASED ON:  mmgr.h  by Paul Nettle
+//
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Originally created on 12/22/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+// NOTES:
+//
+// 1. If you get compiler errors having to do with set_new_handler, then go through this source and search/replace
+//    "std::set_new_handler" with "set_new_handler".
+//
+// 2. This code purposely uses no external routines that allocate RAM (other than the raw allocation routines, such as malloc). We
+//    do this because we want this to be as self-contained as possible. As an example, we don't use assert, because when running
+//    under WIN32, the assert brings up a dialog box, which allocates RAM. Doing this in the middle of an allocation would be bad.
+//
+// 3. When trying to override new/delete under MFC (which has its own version of global new/delete) the linker will complain. In
+//    order to fix this error, use the compiler option: /FORCE, which will force it to build an executable even with linker errors.
+//    Be sure to check those errors each time you compile, otherwise, you may miss a valid linker error.
+//
+// 4. If you see something that looks odd to you or seems like a strange way of going about doing something, then consider that this
+//    code was carefully thought out. If something looks odd, then just assume I've got a good reason for doing it that way (an
+//    example is the use of the class MemStaticTimeTracker.)
+//
+// 5. With MFC applications, you will need to comment out any occurance of "#define new DEBUG_NEW" from all source files.
+//
+// 6. Include file dependencies are _very_important_ for getting the MMGR to integrate nicely into your application. Be careful if
+//    you're including standard includes from within your own project inclues; that will break this very specific dependency order. 
+//    It should look like this:
+//
+//		#include <stdio.h>   // Standard includes MUST come first
+//		#include <stdlib.h>  //
+//		#include <streamio>  //
+//
+//		#include "ChMemory.h"    // ChMemory.h MUST come next
+//
+//		#include "myfile1.h" // Project includes MUST come last
+//		#include "myfile2.h" //
+//		#include "myfile3.h" //
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#ifdef	CH_MEMORY_DEBUG
+
+
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h> 
+#include <tchar.h>
+
+#include <iostream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h> 
+#include <string.h>
+#include <time.h>
+#include <stdarg.h>
+#include <new>
+
+#ifndef	WIN32
+#include <unistd.h>
+#endif
+
+#include "core/ChMemory.h"
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- If you're like me, it's hard to gain trust in foreign code. This memory manager will try to INDUCE your code to crash (for
+// very good reasons... like making bugs obvious as early as possible.) Some people may be inclined to remove this memory tracking
+// software if it causes crashes that didn't exist previously. In reality, these new crashes are the BEST reason for using this
+// software!
+//
+// Whether this software causes your application to crash, or if it reports errors, you need to be able to TRUST this software. To
+// this end, you are given some very simple debugging tools.
+// 
+// The quickest way to locate problems is to enable the STRESS_TEST macro (below.) This should catch 95% of the crashes before they
+// occur by validating every allocation each time this memory manager performs an allocation function. If that doesn't work, keep
+// reading...
+//
+// If you enable the TEST_MEMORY_MANAGER #define (below), this memory manager will log an entry in the memory.log file each time it
+// enters and exits one of its primary allocation handling routines. Each call that succeeds should place an "ENTER" and an "EXIT"
+// into the log. If the program crashes within the memory manager, it will log an "ENTER", but not an "EXIT". The log will also
+// report the name of the routine.
+//
+// Just because this memory manager crashes does not mean that there is a bug here! First, an application could inadvertantly damage
+// the heap, causing malloc(), realloc() or free() to crash. Also, an application could inadvertantly damage some of the memory used
+// by this memory tracking software, causing it to crash in much the same way that a damaged heap would affect the standard
+// allocation routines.
+//
+// In the event of a crash within this code, the first thing you'll want to do is to locate the actual line of code that is
+// crashing. You can do this by adding log() entries throughout the routine that crashes, repeating this process until you narrow
+// in on the offending line of code. If the crash happens in a standard C allocation routine (i.e. malloc, realloc or free) don't
+// bother contacting me, your application has damaged the heap. You can help find the culprit in your code by enabling the
+// STRESS_TEST macro (below.)
+//
+// If you truely suspect a bug in this memory manager (and you had better be sure about it! :) you can contact me at
+// midnight at FluidStudios.com. Before you do, however, check for a newer version at:
+//
+//	http://www.FluidStudios.com/publications.html
+//
+// When using this debugging aid, make sure that you are NOT setting the alwaysLogAll variable on, otherwise the log could be
+// cluttered and hard to read.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#define	TEST_MEMORY_MANAGER
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Enable this sucker if you really want to stress-test your app's memory usage, or to help find hard-to-find bugs
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#define	STRESS_TEST
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Enable this sucker if you want to stress-test your app's error-handling. Set RANDOM_FAIL to the percentage of failures you
+//       want to test with (0 = none, >100 = all failures).
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+//#define	RANDOM_FAILURE 10.0
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Locals -- modify these flags to suit your needs
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#ifdef	STRESS_TEST
+static	const	unsigned int	hashBits               = 12;
+static		bool		randomWipe             = true;
+static		bool		alwaysValidateAll      = true;
+static		bool		alwaysLogAll           = true;
+static		bool		alwaysWipeAll          = true;
+static		bool		cleanupLogOnFirstRun   = true;
+static	const	unsigned int	paddingSize            = 1024; // An extra 8K per allocation!
+#else
+static	const	unsigned int	hashBits               = 12;
+static		bool		randomWipe             = false;
+static		bool		alwaysValidateAll      = false;
+static		bool		alwaysLogAll           = false;
+static		bool		alwaysWipeAll          = true;
+static		bool		cleanupLogOnFirstRun   = true;
+static	const	unsigned int	paddingSize            = 4;
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// We define our own assert, because we don't want to bring up an assertion dialog, since that allocates RAM. Our new assert
+// simply declares a forced breakpoint.
+//
+// The BEOS assert added by Arvid Norberg <arvid at iname.com>.
+// ---------------------------------------------------------------------------------------------------------------------------------
+ 
+#ifdef	WIN32
+	#ifdef	_DEBUG
+	#define	m_assert(x) if ((x) == false) __asm { int 3 }
+	#else
+	#define	m_assert(x) {}
+	#endif
+#elif defined(__BEOS__)
+	#ifdef DEBUG
+		extern void debugger(const char *message);
+		#define	m_assert(x) if ((x) == false) debugger("mmgr: assert failed")
+	#else
+		#define m_assert(x) {}
+	#endif
+#else	// Linux uses assert, which we can use safely, since it doesn't bring up a dialog within the program.
+	#define	m_assert(cond) assert(cond)
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Here, we turn off our macros because any place in this source file where the word 'new' or the word 'delete' (etc.)
+// appear will be expanded by the macro. So to avoid problems using them within this source file, we'll just #undef them.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#undef	new
+#undef	delete
+#undef	malloc
+#undef	calloc
+#undef	realloc
+#undef	free
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Defaults for the constants & statics in the MemoryManager class
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+const		unsigned int	m_alloc_unknown        = 0;
+const		unsigned int	m_alloc_new            = 1;
+const		unsigned int	m_alloc_new_array      = 2;
+const		unsigned int	m_alloc_malloc         = 3;
+const		unsigned int	m_alloc_calloc         = 4;
+const		unsigned int	m_alloc_realloc        = 5;
+const		unsigned int	m_alloc_delete         = 6;
+const		unsigned int	m_alloc_delete_array   = 7;
+const		unsigned int	m_alloc_free           = 8;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Get to know these values. They represent the values that will be used to fill unused and deallocated RAM.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static		unsigned int	prefixPattern          = 0xbaadf00d; // Fill pattern for bytes preceeding allocated blocks
+static		unsigned int	postfixPattern         = 0xdeadc0de; // Fill pattern for bytes following allocated blocks
+static		unsigned int	unusedPattern          = 0xfeedface; // Fill pattern for freshly allocated blocks
+static		unsigned int	releasedPattern        = 0xdeadbeef; // Fill pattern for deallocated blocks
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Other locals
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	const	unsigned int	hashSize               = 1 << hashBits;
+static	const	char		*allocationTypes[]     = {"Unknown",
+							  "new",     "new[]",  "malloc",   "calloc",
+							  "realloc", "delete", "delete[]", "free"};
+static		sAllocUnit	*hashTable[hashSize];
+static		sAllocUnit	*reservoir;
+static		unsigned int	currentAllocationCount = 0;
+static		unsigned int	breakOnAllocationCount = 0;
+static		sMStats		stats;
+static	const	char		*sourceFile            = "??";
+static	const	char		*sourceFunc            = "??";
+static		unsigned int	sourceLine             = 0;
+static		bool		staticDeinitTime       = false;
+static		sAllocUnit	**reservoirBuffer      = NULL;
+static		unsigned int	reservoirBufferSize    = 0;
+static const	char		*memoryLogFile         = "CH_memory.log";
+static const	char		*memoryLeakLogFile     = "CH_memleaks.log";
+static		void		doCleanupLogOnFirstRun();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Local functions only
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	void	log(const char *format, ...)
+{
+	// Cleanup the log?
+
+	if (cleanupLogOnFirstRun) doCleanupLogOnFirstRun();
+
+	// Build the buffer
+
+	static char buffer[2048];
+	va_list	ap;
+	va_start(ap, format);
+	vsprintf(buffer, format, ap);
+	va_end(ap);
+
+	// Open the log file
+
+	FILE	*fp = fopen(memoryLogFile, "ab");
+
+	// If you hit this assert, then the memory logger is unable to log information to a file (can't open the file for some
+	// reason.) You can interrogate the variable 'buffer' to see what was supposed to be logged (but won't be.)
+	m_assert(fp);
+
+	if (!fp) return;
+
+	// Spit out the data to the log
+
+	fprintf(fp, "%s\r\n", buffer);
+	fclose(fp);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	void	doCleanupLogOnFirstRun()
+{
+	if (cleanupLogOnFirstRun)
+	{
+		//unlink(memoryLogFile);
+		cleanupLogOnFirstRun = false;
+
+		// Print a header for the log
+
+		time_t	t = time(NULL);
+		log("--------------------------------------------------------------------------------");
+		log("");
+		log("      %s - Chrono memory logging file created on %s", memoryLogFile, asctime(localtime(&t)));
+		log("--------------------------------------------------------------------------------");
+		log("");
+		log("This file contains a log of all memory operations performed during the last run.");
+		log("");
+		log("Interrogate this file to track errors or to help track down memory-related");
+		log("issues. You can do this by tracing the allocations performed by a specific owner");
+		log("or by tracking a specific address through a series of allocations and");
+		log("reallocations.");
+		log("");
+		log("There is a lot of useful information here which, when used creatively, can be");
+		log("extremely helpful.");
+		log("");
+		log("Note that the following guides are used throughout this file:");
+		log("");
+		log("   [!] - Error");
+		log("   [+] - Allocation");
+		log("   [~] - Reallocation");
+		log("   [-] - Deallocation");
+		log("   [I] - Generic information");
+		log("   [F] - Failure induced for the purpose of stress-testing your application");
+		log("   [D] - Information used for debugging this memory manager");
+		log("");
+		log("...so, to find all errors in the file, search for \"[!]\"");
+		log("");
+		log("--------------------------------------------------------------------------------");
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	const char	*sourceFileStripper(const char *sourceFile)
+{
+	char	*ptr = strrchr(sourceFile, '\\');
+	if (ptr) return ptr + 1;
+	ptr = strrchr(sourceFile, '/');
+	if (ptr) return ptr + 1;
+	return sourceFile;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	const char	*ownerString(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc)
+{
+	static	char	str[90];
+	memset(str, 0, sizeof(str));
+	sprintf(str, "%s(%05d)::%s", sourceFileStripper(sourceFile), sourceLine, sourceFunc);
+	return str;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	const char	*insertCommas(unsigned int value)
+{
+	static	char	str[30];
+	memset(str, 0, sizeof(str));
+
+	sprintf(str, "%u", value);
+	if (strlen(str) > 3)
+	{
+		memmove(&str[strlen(str)-3], &str[strlen(str)-4], 4);
+		str[strlen(str) - 4] = ',';
+	}
+	if (strlen(str) > 7)
+	{
+		memmove(&str[strlen(str)-7], &str[strlen(str)-8], 8);
+		str[strlen(str) - 8] = ',';
+	}
+	if (strlen(str) > 11)
+	{
+		memmove(&str[strlen(str)-11], &str[strlen(str)-12], 12);
+		str[strlen(str) - 12] = ',';
+	}
+
+	return str;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	const char	*memorySizeString(unsigned long size)
+{
+	static	char	str[90];
+	     if (size > (1024*1024))	sprintf(str, "%10s (%7.2fM)", insertCommas(size), static_cast<float>(size) / (1024.0f * 1024.0f));
+	else if (size > 1024)		sprintf(str, "%10s (%7.2fK)", insertCommas(size), static_cast<float>(size) / 1024.0f);
+	else				sprintf(str, "%10s bytes     ", insertCommas(size));
+	return str;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	sAllocUnit	*findAllocUnit(const void *reportedAddress)
+{
+	// Just in case...
+	m_assert(reportedAddress != NULL);
+
+	// Use the address to locate the hash index. Note that we shift off the lower four bits. This is because most allocated
+	// addresses will be on four-, eight- or even sixteen-byte boundaries. If we didn't do this, the hash index would not have
+	// very good coverage.
+
+	unsigned int	hashIndex = (reinterpret_cast<unsigned int>(const_cast<void *>(reportedAddress)) >> 4) & (hashSize - 1);
+	sAllocUnit	*ptr = hashTable[hashIndex];
+	while(ptr)
+	{
+		if (ptr->reportedAddress == reportedAddress) return ptr;
+		ptr = ptr->next;
+	}
+
+	return NULL;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	size_t	calculateActualSize(const size_t reportedSize)
+{
+	// We use DWORDS as our padding, and a long is guaranteed to be 4 bytes, but an int is not (ANSI defines an int as
+	// being the standard word size for a processor; on a 32-bit machine, that's 4 bytes, but on a 64-bit machine, it's
+	// 8 bytes, which means an int can actually be larger than a long.)
+
+	return reportedSize + paddingSize * sizeof(long) * 2;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	size_t	calculateReportedSize(const size_t actualSize)
+{
+	// We use DWORDS as our padding, and a long is guaranteed to be 4 bytes, but an int is not (ANSI defines an int as
+	// being the standard word size for a processor; on a 32-bit machine, that's 4 bytes, but on a 64-bit machine, it's
+	// 8 bytes, which means an int can actually be larger than a long.)
+
+	return actualSize - paddingSize * sizeof(long) * 2;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	void	*calculateReportedAddress(const void *actualAddress)
+{
+	// We allow this...
+
+	if (!actualAddress) return NULL;
+
+	// JUst account for the padding
+
+	return reinterpret_cast<void *>(const_cast<char *>(reinterpret_cast<const char *>(actualAddress) + sizeof(long) * paddingSize));
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	void	wipeWithPattern(sAllocUnit *allocUnit, unsigned long pattern, const unsigned int originalReportedSize = 0)
+{
+	// For a serious test run, we use wipes of random a random value. However, if this causes a crash, we don't want it to
+	// crash in a differnt place each time, so we specifically DO NOT call srand. If, by chance your program calls srand(),
+	// you may wish to disable that when running with a random wipe test. This will make any crashes more consistent so they
+	// can be tracked down easier.
+
+	if (randomWipe)
+	{
+		pattern = ((rand() & 0xff) << 24) | ((rand() & 0xff) << 16) | ((rand() & 0xff) << 8) | (rand() & 0xff);
+	}
+
+	// -DOC- We should wipe with 0's if we're not in debug mode, so we can help hide bugs if possible when we release the
+	// product. So uncomment the following line for releases.
+	//
+	// Note that the "alwaysWipeAll" should be turned on for this to have effect, otherwise it won't do much good. But we'll
+	// leave it this way (as an option) because this does slow things down.
+//	pattern = 0;
+
+	// This part of the operation is optional
+
+	if (alwaysWipeAll && allocUnit->reportedSize > originalReportedSize)
+	{
+		// Fill the bulk
+
+		long	*lptr = reinterpret_cast<long *>(reinterpret_cast<char *>(allocUnit->reportedAddress) + originalReportedSize);
+		int	length = static_cast<int>(allocUnit->reportedSize - originalReportedSize);
+		int	i;
+		for (i = 0; i < (length >> 2); i++, lptr++)
+		{
+			*lptr = pattern;
+		}
+
+		// Fill the remainder
+
+		unsigned int	shiftCount = 0;
+		char		*cptr = reinterpret_cast<char *>(lptr);
+		for (i = 0; i < (length & 0x3); i++, cptr++, shiftCount += 8)
+		{
+			*cptr = static_cast<char>((pattern & (0xff << shiftCount)) >> shiftCount);
+		}
+	}
+
+	// Write in the prefix/postfix bytes
+
+	long		*pre = reinterpret_cast<long *>(allocUnit->actualAddress);
+	long		*post = reinterpret_cast<long *>(reinterpret_cast<char *>(allocUnit->actualAddress) + allocUnit->actualSize - paddingSize * sizeof(long));
+	for (unsigned int i = 0; i < paddingSize; i++, pre++, post++)
+	{
+		*pre = prefixPattern;
+		*post = postfixPattern;
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	void	dumpAllocations(FILE *fp)
+{
+	fprintf(fp, "Alloc.   Addr       Size       Addr       Size                        BreakOn BreakOn              \r\n");
+	fprintf(fp, "Number Reported   Reported    Actual     Actual     Unused    Method  Dealloc Realloc Allocated by \r\n");
+	fprintf(fp, "------ ---------- ---------- ---------- ---------- ---------- -------- ------- ------- --------------------------------------------------- \r\n");
+
+
+	for (unsigned int i = 0; i < hashSize; i++)
+	{
+		sAllocUnit *ptr = hashTable[i];
+		while(ptr)
+		{
+			fprintf(fp, "%06d 0x%08X 0x%08X 0x%08X 0x%08X 0x%08X %-8s    %c       %c    %s\r\n",
+				ptr->allocationNumber,
+				reinterpret_cast<unsigned int>(ptr->reportedAddress), ptr->reportedSize,
+				reinterpret_cast<unsigned int>(ptr->actualAddress), ptr->actualSize,
+				m_calcUnused(ptr),
+				allocationTypes[ptr->allocationType],
+				ptr->breakOnDealloc ? 'Y':'N',
+				ptr->breakOnRealloc ? 'Y':'N',
+				ownerString(ptr->sourceFile, ptr->sourceLine, ptr->sourceFunc));
+			ptr = ptr->next;
+		}
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	void	dumpLeakReport()
+{
+	// Open the report file
+
+	FILE	*fp = fopen(memoryLeakLogFile, "w+b");
+
+	// If you hit this assert, then the memory report generator is unable to log information to a file (can't open the file for
+	// some reason.)
+	m_assert(fp);
+	if (!fp) return;
+
+	// Any leaks?
+
+	// Header
+
+	static  char    timeString[25];
+	memset(timeString, 0, sizeof(timeString));
+	time_t  t = time(NULL);
+	struct  tm *tme = localtime(&t);
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "|                                          Memory leak report for:  %02d/%02d/%04d %02d:%02d:%02d                                            |\r\n", tme->tm_mon + 1, tme->tm_mday, tme->tm_year + 1900, tme->tm_hour, tme->tm_min, tme->tm_sec);
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "\r\n");
+	fprintf(fp, "\r\n");
+	if (stats.totalAllocUnitCount)
+	{
+		fprintf(fp, "%d memory leak%s found:\r\n", stats.totalAllocUnitCount, stats.totalAllocUnitCount == 1 ? "":"s");
+	}
+	else
+	{
+		fprintf(fp, "Congratulations! No memory leaks found!\r\n");
+
+		// We can finally free up our own memory allocations
+
+		if (reservoirBuffer)
+		{
+			for (unsigned int i = 0; i < reservoirBufferSize; i++)
+			{
+				free(reservoirBuffer[i]);
+			}
+			free(reservoirBuffer);
+			reservoirBuffer = 0;
+			reservoirBufferSize = 0;
+			reservoir = NULL;
+		}
+	}
+	fprintf(fp, "\r\n");
+
+	if (stats.totalAllocUnitCount)
+	{
+		dumpAllocations(fp);
+	}
+
+	fclose(fp);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// We use a static class to let us know when we're in the midst of static deinitialization
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+class	MemStaticTimeTracker
+{
+public:
+	MemStaticTimeTracker() {doCleanupLogOnFirstRun();}
+	~MemStaticTimeTracker() {staticDeinitTime = true; dumpLeakReport();}
+};
+static	MemStaticTimeTracker	mstt;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Flags & options -- Call these routines to enable/disable the following options
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	&m_alwaysValidateAll()
+{
+	// Force a validation of all allocation units each time we enter this software
+	return alwaysValidateAll;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	&m_alwaysLogAll()
+{
+	// Force a log of every allocation & deallocation into CH_memory.log
+	return alwaysLogAll;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	&m_alwaysWipeAll()
+{
+	// Force this software to always wipe memory with a pattern when it is being allocated/dallocated
+	return alwaysWipeAll;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	&m_randomeWipe()
+{
+	// Force this software to use a random pattern when wiping memory -- good for stress testing
+	return randomWipe;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Simply call this routine with the address of an allocated block of RAM, to cause it to force a breakpoint when it is
+// reallocated.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	&m_breakOnRealloc(void *reportedAddress)
+{
+	// Locate the existing allocation unit
+
+	sAllocUnit	*au = findAllocUnit(reportedAddress);
+
+	// If you hit this assert, you tried to set a breakpoint on reallocation for an address that doesn't exist. Interrogate the
+	// stack frame or the variable 'au' to see which allocation this is.
+	m_assert(au != NULL);
+
+	// If you hit this assert, you tried to set a breakpoint on reallocation for an address that wasn't allocated in a way that
+	// is compatible with reallocation.
+	m_assert(au->allocationType == m_alloc_malloc ||
+		 au->allocationType == m_alloc_calloc ||
+		 au->allocationType == m_alloc_realloc);
+
+	return au->breakOnRealloc;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Simply call this routine with the address of an allocated block of RAM, to cause it to force a breakpoint when it is
+// deallocated.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	&m_breakOnDealloc(void *reportedAddress)
+{
+	// Locate the existing allocation unit
+
+	sAllocUnit	*au = findAllocUnit(reportedAddress);
+
+	// If you hit this assert, you tried to set a breakpoint on deallocation for an address that doesn't exist. Interrogate the
+	// stack frame or the variable 'au' to see which allocation this is.
+	m_assert(au != NULL);
+
+	return au->breakOnDealloc;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- When tracking down a difficult bug, use this routine to force a breakpoint on a specific allocation count
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	m_breakOnAllocation(unsigned int count)
+{
+	breakOnAllocationCount = count;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Used by the macros
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	m_setOwner(const char *file, const unsigned int line, const char *func)
+{
+	// You're probably wondering about this...
+	//
+	// It's important for this memory manager to primarily work with global new/delete in their original forms (i.e. with
+	// no extra parameters.) In order to do this, we use macros that call this function prior to operators new & delete. This
+	// is fine... usually. Here's what actually happens when you use this macro to delete an object:
+	//
+	// m_setOwner(__FILE__, __LINE__, __FUNCTION__) --> object::~object() --> delete
+	//
+	// Note that the compiler inserts a call to the object's destructor just prior to calling our overridden operator delete.
+	// But what happens when we delete an object whose destructor deletes another object, whose desctuctor deletes another
+	// object? Here's a diagram (indentation follows stack depth):
+	//
+	// m_setOwner(...) -> ~obj1()                          // original call to delete obj1
+	//     m_setOwner(...) -> ~obj2()                      // obj1's destructor deletes obj2
+	//         m_setOwner(...) -> ~obj3()                  // obj2's destructor deletes obj3
+	//             ...                                     // obj3's destructor just does some stuff
+	//         delete                                      // back in obj2's destructor, we call delete
+	//     delete                                          // back in obj1's destructor, we call delete
+	// delete                                              // back to our original call, we call delete
+	//
+	// Because m_setOwner() just sets up some static variables (below) it's important that each call to m_setOwner() and
+	// successive calls to new/delete alternate. However, in this case, three calls to m_setOwner() happen in succession
+	// followed by three calls to delete in succession (with a few calls to destructors mixed in for fun.) This means that
+	// only the final call to delete (in this chain of events) will have the proper reporting, and the first two in the chain
+	// will not have ANY owner-reporting information. The deletes will still work fine, we just won't know who called us.
+	//
+	// "Then build a stack, my friend!" you might think... but it's a very common thing that people will be working with third-
+	// party libraries (including MFC under Windows) which is not compiled with this memory manager's macros. In those cases,
+	// m_setOwner() is never called, and rightfully should not have the proper trace-back information. So if one of the
+	// destructors in the chain ends up being a call to a delete from a non-mmgr-compiled library, the stack will get confused.
+	//
+	// I've been unable to find a solution to this problem, but at least we can detect it and report the data before we
+	// lose it. That's what this is all about. It makes it somewhat confusing to read in the logs, but at least ALL the
+	// information is present...
+	//
+	// There's a caveat here... The compiler is not required to call operator delete if the value being deleted is NULL.
+	// In this case, any call to delete with a NULL will sill call m_setOwner(), which will make m_setOwner() think that
+	// there is a destructor chain becuase we setup the variables, but nothing gets called to clear them. Because of this
+	// we report a "Possible destructor chain".
+	//
+	// Thanks to J. Woznack (from Kodiak Interactive Software Studios -- www.kodiakgames.com) for pointing this out.
+
+	if (sourceLine && alwaysLogAll)
+	{
+		log("[I] NOTE! Possible destructor chain: previous owner is %s", ownerString(sourceFile, sourceLine, sourceFunc));
+	}
+
+	// Okay... save this stuff off so we can keep track of the caller
+
+	sourceFile = file;
+	sourceLine = line;
+	sourceFunc = func;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+static	void	resetGlobals()
+{
+	sourceFile = "??";
+	sourceLine = 0;
+	sourceFunc = "??";
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Global new/new[]
+//
+// These are the standard new/new[] operators. They are merely interface functions that operate like normal new/new[], but use our
+// memory tracking routines.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	*operator new(size_t reportedSize)
+{
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] ENTER: new");
+	#endif
+
+	// Save these off...
+
+	const	char		*file = sourceFile;
+	const	unsigned int	line = sourceLine;
+	const	char		*func = sourceFunc;
+
+	// ANSI says: allocation requests of 0 bytes will still return a valid value
+
+	if (reportedSize == 0) reportedSize = 1;
+
+	// ANSI says: loop continuously because the error handler could possibly free up some memory
+
+	for(;;)
+	{
+		// Try the allocation
+
+		void	*ptr = m_allocator(file, line, func, m_alloc_new, reportedSize);
+		if (ptr)
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new");
+			#endif
+			return ptr;
+		}
+
+		// There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+		// set it back again.
+
+		new_handler	nh = set_new_handler(0);
+		set_new_handler(nh);
+
+		// If there is an error handler, call it
+
+		if (nh)
+		{
+			(*nh)();
+		}
+
+		// Otherwise, throw the exception
+
+		else
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new");
+			#endif
+			throw;// std::bad_alloc();
+		}
+	}
+} 
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	*operator new[](size_t reportedSize)
+{
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] ENTER: new[]");
+	#endif
+
+	// Save these off...
+
+	const	char		*file = sourceFile;
+	const	unsigned int	line = sourceLine;
+	const	char		*func = sourceFunc;
+
+	// The ANSI standard says that allocation requests of 0 bytes will still return a valid value
+
+	if (reportedSize == 0) reportedSize = 1;
+
+	// ANSI says: loop continuously because the error handler could possibly free up some memory
+
+	for(;;)
+	{
+		// Try the allocation
+
+		void	*ptr = m_allocator(file, line, func, m_alloc_new_array, reportedSize);
+		if (ptr)
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new[]");
+			#endif
+			return ptr;
+		}
+
+		// There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+		// set it back again.
+
+		new_handler	nh = set_new_handler(0);
+		set_new_handler(nh);
+
+		// If there is an error handler, call it
+
+		if (nh)
+		{
+			(*nh)();
+		}
+
+		// Otherwise, throw the exception
+
+		else
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new[]");
+			#endif
+			throw ; //std::bad_alloc();
+		}
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Other global new/new[]
+//
+// These are the standard new/new[] operators as used by Microsoft's memory tracker. We don't want them interfering with our memory
+// tracking efforts. Like the previous versions, these are merely interface functions that operate like normal new/new[], but use
+// our memory tracking routines.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	*operator new(size_t reportedSize, const char *sourceFile, int sourceLine)
+{
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] ENTER: new");
+	#endif
+
+	// The ANSI standard says that allocation requests of 0 bytes will still return a valid value
+
+	if (reportedSize == 0) reportedSize = 1;
+
+	// ANSI says: loop continuously because the error handler could possibly free up some memory
+
+	for(;;)
+	{
+		// Try the allocation
+
+		void	*ptr = m_allocator(sourceFile, sourceLine, "??", m_alloc_new, reportedSize);
+		if (ptr)
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new");
+			#endif
+			return ptr;
+		}
+
+		// There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+		// set it back again.
+
+		new_handler	nh = set_new_handler(0);
+		set_new_handler(nh);
+
+		// If there is an error handler, call it
+
+		if (nh)
+		{
+			(*nh)();
+		}
+
+		// Otherwise, throw the exception
+
+		else
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new");
+			#endif
+			throw ; //std::bad_alloc();
+		}
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	*operator new[](size_t reportedSize, const char *sourceFile, int sourceLine)
+{
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] ENTER: new[]");
+	#endif
+
+	// The ANSI standard says that allocation requests of 0 bytes will still return a valid value
+
+	if (reportedSize == 0) reportedSize = 1;
+
+	// ANSI says: loop continuously because the error handler could possibly free up some memory
+
+	for(;;)
+	{
+		// Try the allocation
+
+		void	*ptr = m_allocator(sourceFile, sourceLine, "??", m_alloc_new_array, reportedSize);
+		if (ptr)
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new[]");
+			#endif
+			return ptr;
+		}
+
+		// There isn't a way to determine the new handler, except through setting it. So we'll just set it to NULL, then
+		// set it back again.
+
+		new_handler	nh = set_new_handler(0);
+		set_new_handler(nh);
+
+		// If there is an error handler, call it
+
+		if (nh)
+		{
+			(*nh)();
+		}
+
+		// Otherwise, throw the exception
+
+		else
+		{
+			#ifdef TEST_MEMORY_MANAGER
+			log("[D] EXIT : new[]");
+			#endif
+			throw ;// std::bad_alloc();
+		}
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Global delete/delete[]
+//
+// These are the standard delete/delete[] operators. They are merely interface functions that operate like normal delete/delete[],
+// but use our memory tracking routines.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	operator delete(void *reportedAddress)
+{
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] ENTER: delete");
+	#endif
+
+	// ANSI says: delete & delete[] allow NULL pointers (they do nothing)
+
+	if (reportedAddress) m_deallocator(sourceFile, sourceLine, sourceFunc, m_alloc_delete, reportedAddress);
+	else if (alwaysLogAll) log("[-] ----- %8s of NULL                      by %s", allocationTypes[m_alloc_delete], ownerString(sourceFile, sourceLine, sourceFunc));
+
+	// Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+	// source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+	resetGlobals();
+
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] EXIT : delete");
+	#endif
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	operator delete[](void *reportedAddress)
+{
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] ENTER: delete[]");
+	#endif
+
+	// ANSI says: delete & delete[] allow NULL pointers (they do nothing)
+
+	if (reportedAddress) m_deallocator(sourceFile, sourceLine, sourceFunc, m_alloc_delete_array, reportedAddress);
+	else if (alwaysLogAll)
+		log("[-] ----- %8s of NULL                      by %s", allocationTypes[m_alloc_delete_array], ownerString(sourceFile, sourceLine, sourceFunc));
+
+	// Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+	// source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+	resetGlobals();
+
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] EXIT : delete[]");
+	#endif
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Allocate memory and track it
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	*m_allocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int allocationType, const size_t reportedSize)
+{
+	try
+	{
+		#ifdef TEST_MEMORY_MANAGER
+		log("[D] ENTER: m_allocator()");
+		#endif
+
+		// Increase our allocation count
+
+		currentAllocationCount++;
+
+		// Log the request
+
+		if (alwaysLogAll) log("[+] %05d %8s of size 0x%08X(%08d) by %s", currentAllocationCount, allocationTypes[allocationType], reportedSize, reportedSize, ownerString(sourceFile, sourceLine, sourceFunc));
+
+		// If you hit this assert, you requested a breakpoint on a specific allocation count
+		m_assert(currentAllocationCount != breakOnAllocationCount);
+
+		// If necessary, grow the reservoir of unused allocation units
+
+		if (!reservoir)
+		{
+			// Allocate 256 reservoir elements
+
+			reservoir = (sAllocUnit *) malloc(sizeof(sAllocUnit) * 256);
+
+			// If you hit this assert, then the memory manager failed to allocate internal memory for tracking the
+			// allocations
+			m_assert(reservoir != NULL);
+
+			// Danger Will Robinson!
+
+			if (reservoir == NULL) throw "Unable to allocate RAM for internal memory tracking data";
+
+			// Build a linked-list of the elements in our reservoir
+
+			memset(reservoir, 0, sizeof(sAllocUnit) * 256);
+			for (unsigned int i = 0; i < 256 - 1; i++)
+			{
+				reservoir[i].next = &reservoir[i+1];
+			}
+
+			// Add this address to our reservoirBuffer so we can free it later
+
+			sAllocUnit	**temp = (sAllocUnit **) realloc(reservoirBuffer, (reservoirBufferSize + 1) * sizeof(sAllocUnit *));
+			m_assert(temp);
+			if (temp)
+			{
+				reservoirBuffer = temp;
+				reservoirBuffer[reservoirBufferSize++] = reservoir;
+			}
+		}
+
+		// Logical flow says this should never happen...
+		m_assert(reservoir != NULL);
+
+		// Grab a new allocaton unit from the front of the reservoir
+
+		sAllocUnit	*au = reservoir;
+		reservoir = au->next;
+
+		// Populate it with some real data
+
+		memset(au, 0, sizeof(sAllocUnit));
+		au->actualSize        = calculateActualSize(reportedSize);
+		#ifdef RANDOM_FAILURE
+		double	a = rand();
+		double	b = RAND_MAX / 100.0 * RANDOM_FAILURE;
+		if (a > b)
+		{
+			au->actualAddress = malloc(au->actualSize);
+		}
+		else
+		{
+			log("[F] Random faiure");
+			au->actualAddress = NULL;
+		}
+		#else
+		au->actualAddress     = malloc(au->actualSize);
+		#endif
+		au->reportedSize      = reportedSize;
+		au->reportedAddress   = calculateReportedAddress(au->actualAddress);
+		au->allocationType    = allocationType;
+		au->sourceLine        = sourceLine;
+		au->allocationNumber  = currentAllocationCount;
+		if (sourceFile) strncpy(au->sourceFile, sourceFileStripper(sourceFile), sizeof(au->sourceFile) - 1);
+		else		strcpy (au->sourceFile, "??");
+		if (sourceFunc) strncpy(au->sourceFunc, sourceFunc, sizeof(au->sourceFunc) - 1);
+		else		strcpy (au->sourceFunc, "??");
+
+		// We don't want to assert with random failures, because we want the application to deal with them.
+
+		#ifndef RANDOM_FAILURE
+		// If you hit this assert, then the requested allocation simply failed (you're out of memory.) Interrogate the
+		// variable 'au' or the stack frame to see what you were trying to do.
+		m_assert(au->actualAddress != NULL);
+		#endif
+
+		if (au->actualAddress == NULL)
+		{
+			throw "Request for allocation failed. Out of memory.";
+		}
+
+		// If you hit this assert, then this allocation was made from a source that isn't setup to use this memory tracking
+		// software, use the stack frame to locate the source and include our H file.
+		m_assert(allocationType != m_alloc_unknown);
+
+		// Insert the new allocation into the hash table
+
+		unsigned int	hashIndex = (reinterpret_cast<unsigned int>(au->reportedAddress) >> 4) & (hashSize - 1);
+		if (hashTable[hashIndex]) hashTable[hashIndex]->prev = au;
+		au->next = hashTable[hashIndex];
+		au->prev = NULL;
+		hashTable[hashIndex] = au;
+
+		// Account for the new allocatin unit in our stats
+
+		stats.totalReportedMemory += static_cast<unsigned int>(au->reportedSize);
+		stats.totalActualMemory   += static_cast<unsigned int>(au->actualSize);
+		stats.totalAllocUnitCount++;
+		if (stats.totalReportedMemory > stats.peakReportedMemory) stats.peakReportedMemory = stats.totalReportedMemory;
+		if (stats.totalActualMemory   > stats.peakActualMemory)   stats.peakActualMemory   = stats.totalActualMemory;
+		if (stats.totalAllocUnitCount > stats.peakAllocUnitCount) stats.peakAllocUnitCount = stats.totalAllocUnitCount;
+		stats.accumulatedReportedMemory += static_cast<unsigned int>(au->reportedSize);
+		stats.accumulatedActualMemory += static_cast<unsigned int>(au->actualSize);
+		stats.accumulatedAllocUnitCount++;
+
+		// Prepare the allocation unit for use (wipe it with recognizable garbage)
+
+		wipeWithPattern(au, unusedPattern);
+
+		// calloc() expects the reported memory address range to be filled with 0's
+
+		if (allocationType == m_alloc_calloc)
+		{
+			memset(au->reportedAddress, 0, au->reportedSize);
+		}
+
+		// Validate every single allocated unit in memory
+
+		if (alwaysValidateAll) m_validateAllAllocUnits();
+
+		// Log the result
+
+		if (alwaysLogAll) log("[+] ---->             addr 0x%08X", reinterpret_cast<unsigned int>(au->reportedAddress));
+
+		// Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+		// source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+		resetGlobals();
+
+		// Return the (reported) address of the new allocation unit
+
+		#ifdef TEST_MEMORY_MANAGER
+		log("[D] EXIT : m_allocator()");
+		#endif
+
+		return au->reportedAddress;
+	}
+	catch(const char *err)
+	{
+		// Deal with the errors
+
+		log("[!] %s", err);
+		resetGlobals();
+
+		#ifdef TEST_MEMORY_MANAGER
+		log("[D] EXIT : m_allocator()");
+		#endif
+
+		return NULL;
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Reallocate memory and track it
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	*m_reallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int reallocationType, const size_t reportedSize, void *reportedAddress)
+{
+	try
+	{
+		#ifdef TEST_MEMORY_MANAGER
+		log("[D] ENTER: m_reallocator()");
+		#endif
+
+		// Calling realloc with a NULL should force same operations as a malloc
+
+		if (!reportedAddress)
+		{
+			return m_allocator(sourceFile, sourceLine, sourceFunc, reallocationType, reportedSize);
+		}
+
+		// Increase our allocation count
+
+		currentAllocationCount++;
+
+		// If you hit this assert, you requested a breakpoint on a specific allocation count
+		m_assert(currentAllocationCount != breakOnAllocationCount);
+
+		// Log the request
+
+		if (alwaysLogAll) log("[~] %05d %8s of size 0x%08X(%08d) by %s", currentAllocationCount, allocationTypes[reallocationType], reportedSize, reportedSize, ownerString(sourceFile, sourceLine, sourceFunc));
+
+		// Locate the existing allocation unit
+
+		sAllocUnit	*au = findAllocUnit(reportedAddress);
+
+		// If you hit this assert, you tried to reallocate RAM that wasn't allocated by this memory manager.
+		m_assert(au != NULL);
+		if (au == NULL) throw "Request to reallocate RAM that was never allocated";
+
+		// If you hit this assert, then the allocation unit that is about to be reallocated is damaged. But you probably
+		// already know that from a previous assert you should have seen in validateAllocUnit() :)
+		m_assert(m_validateAllocUnit(au));
+
+		// If you hit this assert, then this reallocation was made from a source that isn't setup to use this memory
+		// tracking software, use the stack frame to locate the source and include our H file.
+		m_assert(reallocationType != m_alloc_unknown);
+
+		// If you hit this assert, you were trying to reallocate RAM that was not allocated in a way that is compatible with
+		// realloc. In other words, you have a allocation/reallocation mismatch.
+		m_assert(au->allocationType == m_alloc_malloc ||
+			 au->allocationType == m_alloc_calloc ||
+			 au->allocationType == m_alloc_realloc);
+
+		// If you hit this assert, then the "break on realloc" flag for this allocation unit is set (and will continue to be
+		// set until you specifically shut it off. Interrogate the 'au' variable to determine information about this
+		// allocation unit.
+		m_assert(au->breakOnRealloc == false);
+
+		// Keep track of the original size
+
+		unsigned int	originalReportedSize = static_cast<unsigned int>(au->reportedSize);
+
+		if (alwaysLogAll) log("[~] ---->             from 0x%08X(%08d)", originalReportedSize, originalReportedSize);
+
+		// Do the reallocation
+
+		void	*oldReportedAddress = reportedAddress;
+		size_t	newActualSize = calculateActualSize(reportedSize);
+		void	*newActualAddress = NULL;
+		#ifdef RANDOM_FAILURE
+		double	a = rand();
+		double	b = RAND_MAX / 100.0 * RANDOM_FAILURE;
+		if (a > b)
+		{
+			newActualAddress = realloc(au->actualAddress, newActualSize);
+		}
+		else
+		{
+			log("[F] Random faiure");
+		}
+		#else
+		newActualAddress = realloc(au->actualAddress, newActualSize);
+		#endif
+
+		// We don't want to assert with random failures, because we want the application to deal with them.
+
+		#ifndef RANDOM_FAILURE
+		// If you hit this assert, then the requested allocation simply failed (you're out of memory) Interrogate the
+		// variable 'au' to see the original allocation. You can also query 'newActualSize' to see the amount of memory
+		// trying to be allocated. Finally, you can query 'reportedSize' to see how much memory was requested by the caller.
+		m_assert(newActualAddress);
+		#endif
+
+		if (!newActualAddress) throw "Request for reallocation failed. Out of memory.";
+
+		// Remove this allocation from our stats (we'll add the new reallocation again later)
+
+		stats.totalReportedMemory -= static_cast<unsigned int>(au->reportedSize);
+		stats.totalActualMemory   -= static_cast<unsigned int>(au->actualSize);
+
+		// Update the allocation with the new information
+
+		au->actualSize        = newActualSize;
+		au->actualAddress     = newActualAddress;
+		au->reportedSize      = calculateReportedSize(newActualSize);
+		au->reportedAddress   = calculateReportedAddress(newActualAddress);
+		au->allocationType    = reallocationType;
+		au->sourceLine        = sourceLine;
+		au->allocationNumber  = currentAllocationCount;
+		if (sourceFile) strncpy(au->sourceFile, sourceFileStripper(sourceFile), sizeof(au->sourceFile) - 1);
+		else		strcpy (au->sourceFile, "??");
+		if (sourceFunc) strncpy(au->sourceFunc, sourceFunc, sizeof(au->sourceFunc) - 1);
+		else		strcpy (au->sourceFunc, "??");
+
+		// The reallocation may cause the address to change, so we should relocate our allocation unit within the hash table
+
+		unsigned int	hashIndex = static_cast<unsigned int>(-1);
+		if (oldReportedAddress != au->reportedAddress)
+		{
+			// Remove this allocation unit from the hash table
+
+			{
+				unsigned int	hashIndex = (reinterpret_cast<unsigned int>(oldReportedAddress) >> 4) & (hashSize - 1);
+				if (hashTable[hashIndex] == au)
+				{
+					hashTable[hashIndex] = hashTable[hashIndex]->next;
+				}
+				else
+				{
+					if (au->prev)	au->prev->next = au->next;
+					if (au->next)	au->next->prev = au->prev;
+				}
+			}
+
+			// Re-insert it back into the hash table
+
+			hashIndex = (reinterpret_cast<unsigned int>(au->reportedAddress) >> 4) & (hashSize - 1);
+			if (hashTable[hashIndex]) hashTable[hashIndex]->prev = au;
+			au->next = hashTable[hashIndex];
+			au->prev = NULL;
+			hashTable[hashIndex] = au;
+		}
+
+		// Account for the new allocatin unit in our stats
+
+		stats.totalReportedMemory += static_cast<unsigned int>(au->reportedSize);
+		stats.totalActualMemory   += static_cast<unsigned int>(au->actualSize);
+		if (stats.totalReportedMemory > stats.peakReportedMemory) stats.peakReportedMemory = stats.totalReportedMemory;
+		if (stats.totalActualMemory   > stats.peakActualMemory)   stats.peakActualMemory   = stats.totalActualMemory;
+		int	deltaReportedSize = static_cast<int>(reportedSize - originalReportedSize);
+		if (deltaReportedSize > 0)
+		{
+			stats.accumulatedReportedMemory += deltaReportedSize;
+			stats.accumulatedActualMemory += deltaReportedSize;
+		}
+
+		// Prepare the allocation unit for use (wipe it with recognizable garbage)
+
+		wipeWithPattern(au, unusedPattern, originalReportedSize);
+
+		// If you hit this assert, then something went wrong, because the allocation unit was properly validated PRIOR to
+		// the reallocation. This should not happen.
+		m_assert(m_validateAllocUnit(au));
+
+		// Validate every single allocated unit in memory
+
+		if (alwaysValidateAll) m_validateAllAllocUnits();
+
+		// Log the result
+
+		if (alwaysLogAll) log("[~] ---->             addr 0x%08X", reinterpret_cast<unsigned int>(au->reportedAddress));
+
+		// Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+		// source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+		resetGlobals(); 
+
+		// Return the (reported) address of the new allocation unit
+
+		#ifdef TEST_MEMORY_MANAGER
+		log("[D] EXIT : m_reallocator()");
+		#endif
+
+		return au->reportedAddress;
+	}
+	catch(const char *err)
+	{
+		// Deal with the errors
+
+		log("[!] %s", err);
+		resetGlobals();
+
+		#ifdef TEST_MEMORY_MANAGER
+		log("[D] EXIT : m_reallocator()");
+		#endif
+
+		return NULL;
+	}
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Deallocate memory and track it
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	m_deallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc, const unsigned int deallocationType, const void *reportedAddress)
+{
+	try
+	{
+		#ifdef TEST_MEMORY_MANAGER
+		log("[D] ENTER: m_deallocator()");
+		#endif
+
+		// Log the request
+
+		if (alwaysLogAll) log("[-] ----- %8s of addr 0x%08X           by %s", allocationTypes[deallocationType], reinterpret_cast<unsigned int>(const_cast<void *>(reportedAddress)), ownerString(sourceFile, sourceLine, sourceFunc));
+
+		// We should only ever get here with a null pointer if they try to do so with a call to free() (delete[] and delete will
+		// both bail before they get here.) So, since ANSI allows free(NULL), we'll not bother trying to actually free the allocated
+		// memory or track it any further.
+
+		if (reportedAddress)
+		{
+			// Go get the allocation unit
+
+			sAllocUnit	*au = findAllocUnit(reportedAddress);
+
+			// If you hit this assert, you tried to deallocate RAM that wasn't allocated by this memory manager.
+			m_assert(au != NULL);
+			if (au == NULL) throw "Request to deallocate RAM that was never allocated";
+
+			// If you hit this assert, then the allocation unit that is about to be deallocated is damaged. But you probably
+			// already know that from a previous assert you should have seen in validateAllocUnit() :)
+			m_assert(m_validateAllocUnit(au));
+
+			// If you hit this assert, then this deallocation was made from a source that isn't setup to use this memory
+			// tracking software, use the stack frame to locate the source and include our H file.
+			m_assert(deallocationType != m_alloc_unknown);
+
+			// If you hit this assert, you were trying to deallocate RAM that was not allocated in a way that is compatible with
+			// the deallocation method requested. In other words, you have a allocation/deallocation mismatch.
+			m_assert((deallocationType == m_alloc_delete       && au->allocationType == m_alloc_new      ) ||
+				(deallocationType == m_alloc_delete_array && au->allocationType == m_alloc_new_array) ||
+				(deallocationType == m_alloc_free         && au->allocationType == m_alloc_malloc   ) ||
+				(deallocationType == m_alloc_free         && au->allocationType == m_alloc_calloc   ) ||
+				(deallocationType == m_alloc_free         && au->allocationType == m_alloc_realloc  ) ||
+				(deallocationType == m_alloc_unknown                                                ) );
+
+			// If you hit this assert, then the "break on dealloc" flag for this allocation unit is set. Interrogate the 'au'
+			// variable to determine information about this allocation unit.
+			m_assert(au->breakOnDealloc == false);
+
+			// Wipe the deallocated RAM with a new pattern. This doen't actually do us much good in debug mode under WIN32,
+			// because Microsoft's memory debugging & tracking utilities will wipe it right after we do. Oh well.
+
+			wipeWithPattern(au, releasedPattern);
+
+			// Do the deallocation
+
+			free(au->actualAddress);
+
+			// Remove this allocation unit from the hash table
+
+			unsigned int	hashIndex = (reinterpret_cast<unsigned int>(au->reportedAddress) >> 4) & (hashSize - 1);
+			if (hashTable[hashIndex] == au)
+			{
+				hashTable[hashIndex] = au->next;
+			}
+			else
+			{
+				if (au->prev)	au->prev->next = au->next;
+				if (au->next)	au->next->prev = au->prev;
+			}
+
+			// Remove this allocation from our stats
+
+			stats.totalReportedMemory -= static_cast<unsigned int>(au->reportedSize);
+			stats.totalActualMemory   -= static_cast<unsigned int>(au->actualSize);
+			stats.totalAllocUnitCount--;
+
+			// Add this allocation unit to the front of our reservoir of unused allocation units
+
+			memset(au, 0, sizeof(sAllocUnit));
+			au->next = reservoir;
+			reservoir = au;
+		}
+
+		// Resetting the globals insures that if at some later time, somebody calls our memory manager from an unknown
+		// source (i.e. they didn't include our H file) then we won't think it was the last allocation.
+
+		resetGlobals();
+
+		// Validate every single allocated unit in memory
+
+		if (alwaysValidateAll) m_validateAllAllocUnits();
+
+		// If we're in the midst of static deinitialization time, track any pending memory leaks
+
+		if (staticDeinitTime) dumpLeakReport();
+	}
+	catch(const char *err)
+	{
+		// Deal with errors
+
+		log("[!] %s", err);
+		resetGlobals();
+	}
+
+	#ifdef TEST_MEMORY_MANAGER
+	log("[D] EXIT : m_deallocator()");
+	#endif
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- The following utilitarian allow you to become proactive in tracking your own memory, or help you narrow in on those tough
+// bugs.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	m_validateAddress(const void *reportedAddress)
+{
+	// Just see if the address exists in our allocation routines
+
+	return findAllocUnit(reportedAddress) != NULL;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	m_validateAllocUnit(const sAllocUnit *allocUnit)
+{
+	// Make sure the padding is untouched
+
+	long	*pre = reinterpret_cast<long *>(allocUnit->actualAddress);
+	long	*post = reinterpret_cast<long *>((char *)allocUnit->actualAddress + allocUnit->actualSize - paddingSize * sizeof(long));
+	bool	errorFlag = false;
+	for (unsigned int i = 0; i < paddingSize; i++, pre++, post++)
+	{
+		if (*pre != (long) prefixPattern)
+		{
+			log("[!] A memory allocation unit was corrupt because of an underrun:");
+			m_dumpAllocUnit(allocUnit, "  ");
+			errorFlag = true;
+		}
+
+		// If you hit this assert, then you should know that this allocation unit has been damaged. Something (possibly the
+		// owner?) has underrun the allocation unit (modified a few bytes prior to the start). You can interrogate the
+		// variable 'allocUnit' to see statistics and information about this damaged allocation unit.
+		m_assert(*pre == static_cast<long>(prefixPattern));
+
+		if (*post != static_cast<long>(postfixPattern))
+		{
+			log("[!] A memory allocation unit was corrupt because of an overrun:");
+			m_dumpAllocUnit(allocUnit, "  ");
+			errorFlag = true;
+		}
+
+		// If you hit this assert, then you should know that this allocation unit has been damaged. Something (possibly the
+		// owner?) has overrun the allocation unit (modified a few bytes after the end). You can interrogate the variable
+		// 'allocUnit' to see statistics and information about this damaged allocation unit.
+		m_assert(*post == static_cast<long>(postfixPattern));
+	}
+
+	// Return the error status (we invert it, because a return of 'false' means error)
+
+	return !errorFlag;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool	m_validateAllAllocUnits()
+{
+	// Just go through each allocation unit in the hash table and count the ones that have errors
+
+	unsigned int	errors = 0;
+	unsigned int	allocCount = 0;
+	for (unsigned int i = 0; i < hashSize; i++)
+	{
+		sAllocUnit	*ptr = hashTable[i];
+		while(ptr)
+		{
+			allocCount++;
+			if (!m_validateAllocUnit(ptr)) errors++;
+			ptr = ptr->next;
+		}
+	}
+
+	// Test for hash-table correctness
+
+	if (allocCount != stats.totalAllocUnitCount)
+	{
+		log("[!] Memory tracking hash table corrupt!");
+		errors++;
+	}
+
+	// If you hit this assert, then the internal memory (hash table) used by this memory tracking software is damaged! The
+	// best way to track this down is to use the alwaysLogAll flag in conjunction with STRESS_TEST macro to narrow in on the
+	// offending code. After running the application with these settings (and hitting this assert again), interrogate the
+	// memory.log file to find the previous successful operation. The corruption will have occurred between that point and this
+	// assertion.
+	m_assert(allocCount == stats.totalAllocUnitCount);
+
+	// If you hit this assert, then you've probably already been notified that there was a problem with a allocation unit in a
+	// prior call to validateAllocUnit(), but this assert is here just to make sure you know about it. :)
+	m_assert(errors == 0);
+
+	// Log any errors
+
+	if (errors) log("[!] While validting all allocation units, %d allocation unit(s) were found to have problems", errors);
+
+	// Return the error status
+
+	return errors != 0;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- Unused RAM calculation routines. Use these to determine how much of your RAM is unused (in bytes)
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+unsigned int	m_calcUnused(const sAllocUnit *allocUnit)
+{
+	const unsigned long	*ptr = reinterpret_cast<const unsigned long *>(allocUnit->reportedAddress);
+	unsigned int		count = 0;
+
+	for (unsigned int i = 0; i < allocUnit->reportedSize; i += sizeof(long), ptr++)
+	{
+		if (*ptr == unusedPattern) count += sizeof(long);
+	}
+
+	return count;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+unsigned int	m_calcAllUnused()
+{
+	// Just go through each allocation unit in the hash table and count the unused RAM
+
+	unsigned int	total = 0;
+	for (unsigned int i = 0; i < hashSize; i++)
+	{
+		sAllocUnit	*ptr = hashTable[i];
+		while(ptr)
+		{
+			total += m_calcUnused(ptr);
+			ptr = ptr->next;
+		}
+	}
+
+	return total;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// -DOC- The following functions are for logging and statistics reporting.
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	m_dumpAllocUnit(const sAllocUnit *allocUnit, const char *prefix)
+{
+	log("[I] %sAddress (reported): %010p",       prefix, allocUnit->reportedAddress);
+	log("[I] %sAddress (actual)  : %010p",       prefix, allocUnit->actualAddress);
+	log("[I] %sSize (reported)   : 0x%08X (%s)", prefix, static_cast<unsigned int>(allocUnit->reportedSize), memorySizeString(static_cast<unsigned int>(allocUnit->reportedSize)));
+	log("[I] %sSize (actual)     : 0x%08X (%s)", prefix, static_cast<unsigned int>(allocUnit->actualSize), memorySizeString(static_cast<unsigned int>(allocUnit->actualSize)));
+	log("[I] %sOwner             : %s(%d)::%s",  prefix, allocUnit->sourceFile, allocUnit->sourceLine, allocUnit->sourceFunc);
+	log("[I] %sAllocation type   : %s",          prefix, allocationTypes[allocUnit->allocationType]);
+	log("[I] %sAllocation number : %d",          prefix, allocUnit->allocationNumber);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	m_dumpMemoryReport(const char *filename, const bool overwrite)
+{
+	// Open the report file
+
+	FILE	*fp = NULL;
+	
+	if (overwrite)	fp = fopen(filename, "w+b");
+	else		fp = fopen(filename, "ab");
+
+	// If you hit this assert, then the memory report generator is unable to log information to a file (can't open the file for
+	// some reason.)
+	m_assert(fp);
+	if (!fp) return;
+
+        // Header
+
+        static  char    timeString[25];
+        memset(timeString, 0, sizeof(timeString));
+        time_t  t = time(NULL);
+        struct  tm *tme = localtime(&t);
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+        fprintf(fp, "|                                             Memory report for: %02d/%02d/%04d %02d:%02d:%02d                                               |\r\n", tme->tm_mon + 1, tme->tm_mday, tme->tm_year + 1900, tme->tm_hour, tme->tm_min, tme->tm_sec);
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "\r\n");
+	fprintf(fp, "\r\n");
+
+	// Report summary
+
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "|                                                           T O T A L S                                                            |\r\n");
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "              Allocation unit count: %10s\r\n", insertCommas(stats.totalAllocUnitCount));
+	fprintf(fp, "            Reported to application: %s\r\n", memorySizeString(stats.totalReportedMemory));
+	fprintf(fp, "         Actual total memory in use: %s\r\n", memorySizeString(stats.totalActualMemory));
+	fprintf(fp, "           Memory tracking overhead: %s\r\n", memorySizeString(stats.totalActualMemory - stats.totalReportedMemory));
+	fprintf(fp, "\r\n");
+
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "|                                                            P E A K S                                                             |\r\n");
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "              Allocation unit count: %10s\r\n", insertCommas(stats.peakAllocUnitCount));
+	fprintf(fp, "            Reported to application: %s\r\n", memorySizeString(stats.peakReportedMemory));
+	fprintf(fp, "                             Actual: %s\r\n", memorySizeString(stats.peakActualMemory));
+	fprintf(fp, "           Memory tracking overhead: %s\r\n", memorySizeString(stats.peakActualMemory - stats.peakReportedMemory));
+	fprintf(fp, "\r\n");
+
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "|                                                      A C C U M U L A T E D                                                       |\r\n");
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "              Allocation unit count: %s\r\n", memorySizeString(stats.accumulatedAllocUnitCount));
+	fprintf(fp, "            Reported to application: %s\r\n", memorySizeString(stats.accumulatedReportedMemory));
+	fprintf(fp, "                             Actual: %s\r\n", memorySizeString(stats.accumulatedActualMemory));
+	fprintf(fp, "\r\n");
+
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "|                                                           U N U S E D                                                            |\r\n");
+	fprintf(fp, " ---------------------------------------------------------------------------------------------------------------------------------- \r\n");
+	fprintf(fp, "    Memory allocated but not in use: %s\r\n", memorySizeString(m_calcAllUnused()));
+	fprintf(fp, "\r\n");
+
+	dumpAllocations(fp);
+
+	fclose(fp);
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+sMStats	m_getMemoryStatistics()
+{
+	return stats;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// ChMemory.cpp - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#endif // CH_MEMORY_DEBUG
diff --git a/SRC/ChronoEngine/core/ChMemory.h b/SRC/ChronoEngine/core/ChMemory.h
new file mode 100644
index 0000000..7838e4c
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMemory.h
@@ -0,0 +1,207 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifdef	CH_MEMORY_DEBUG
+
+#ifndef	CH_MEMORY_H
+#define	CH_MEMORY_H
+
+//////////////////////////////////////////////////
+//  
+//   ChMemory.h
+//
+//   Math functions for :
+//      - MEMORY DEBUGING
+//
+//   This class is a memory leakage detector, based on
+//   the original code of
+//
+//       mmgr.h  by Paul Nettle
+//
+//   ---------------------------------------------------------
+//   Originally created on 12/22/2000 by Paul Nettle
+//
+//   Copyright 2000, Fluid Studios, Inc., all rights reserved.
+//   ---------------------------------------------------------
+//
+//    To use this memory leakage detector, include this
+//   header in your .cpp code (best if after the inclusion of
+//   system headers, and before inclusion of your headers).
+//
+//    When the program exits, you'll find .log files in 
+//   the program current directory, showing a list of memory
+//   leakages, if you forgot to deallocate memory.
+//
+//    Remember to set the CH_MEMORY_DEBUG flag in 
+//   compiler flags!  Also, you should use it only in 
+//   debugging, not for release configuration (it slows
+//   down program execution!)
+// 
+//     Note: you may use the memory debugger in your header
+//   files as well (say you have a .h file with some 'new'
+//   and 'delete' statements inside..) BUT!!! Remember that 
+//   this may cause MAJOR troubles because of conflicts with
+//   other headers, for example STL libraries and such (in fact,
+//   lot of other .h and .cpp files in your project may load 
+//   the memory-debugged header, as a cascade, then the result 
+//   can be inpredictable!) 
+//   Anyway, there is a quick solution: use 
+//            #include"ChMemory.h" 
+//   in your header file, _after_ you included other .h files,
+//   then use
+//            #include"ChMemorynomgr.h" 
+//   at the _end_ of your .h file. Doing so, the default 'new' and
+//   'delete' behaviour is restored after parsing your header,
+//   and no conflicts will happen.
+//
+//
+//   HEADER file for CHRONO,
+//
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+// For systems that don't have the __FUNCTION__ variable, we can just define it here
+
+
+#define	__FUNCTION__ "??"
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Types
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+typedef	struct tag_au
+{
+	size_t		actualSize;
+	size_t		reportedSize;
+	void		*actualAddress;
+	void		*reportedAddress;
+	char		sourceFile[40];
+	char		sourceFunc[40];
+	unsigned int	sourceLine;
+	unsigned int	allocationType;
+	bool		breakOnDealloc;
+	bool		breakOnRealloc;
+	unsigned int	allocationNumber;
+	struct tag_au	*next;
+	struct tag_au	*prev;
+} sAllocUnit;
+
+typedef	struct
+{
+	unsigned int	totalReportedMemory;
+	unsigned int	totalActualMemory;
+	unsigned int	peakReportedMemory;
+	unsigned int	peakActualMemory;
+	unsigned int	accumulatedReportedMemory;
+	unsigned int	accumulatedActualMemory;
+	unsigned int	accumulatedAllocUnitCount;
+	unsigned int	totalAllocUnitCount;
+	unsigned int	peakAllocUnitCount;
+} sMStats;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// External constants
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+extern	const	unsigned int	m_alloc_unknown;
+extern	const	unsigned int	m_alloc_new;
+extern	const	unsigned int	m_alloc_new_array;
+extern	const	unsigned int	m_alloc_malloc;
+extern	const	unsigned int	m_alloc_calloc;
+extern	const	unsigned int	m_alloc_realloc;
+extern	const	unsigned int	m_alloc_delete;
+extern	const	unsigned int	m_alloc_delete_array;
+extern	const	unsigned int	m_alloc_free;
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Used by the macros
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void		m_setOwner(const char *file, const unsigned int line, const char *func);
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Allocation breakpoints
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool		&m_breakOnRealloc(void *reportedAddress);
+bool		&m_breakOnDealloc(void *reportedAddress);
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// The meat of the memory tracking software
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void		*m_allocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc,
+			     const unsigned int allocationType, const size_t reportedSize);
+void		*m_reallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc,
+			       const unsigned int reallocationType, const size_t reportedSize, void *reportedAddress);
+void		m_deallocator(const char *sourceFile, const unsigned int sourceLine, const char *sourceFunc,
+			      const unsigned int deallocationType, const void *reportedAddress);
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Utilitarian functions
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+bool		m_validateAddress(const void *reportedAddress);
+bool		m_validateAllocUnit(const sAllocUnit *allocUnit);
+bool		m_validateAllAllocUnits();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Unused RAM calculations
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+unsigned int	m_calcUnused(const sAllocUnit *allocUnit);
+unsigned int	m_calcAllUnused();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Logging and reporting
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void		m_dumpAllocUnit(const sAllocUnit *allocUnit, const char *prefix = "");
+void		m_dumpMemoryReport(const char *filename = "memreport.log", const bool overwrite = true);
+sMStats		m_getMemoryStatistics();
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Variations of global operators new & delete
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+void	*operator new(size_t reportedSize);
+void	*operator new[](size_t reportedSize);
+void	*operator new(size_t reportedSize, const char *sourceFile, int sourceLine);
+void	*operator new[](size_t reportedSize, const char *sourceFile, int sourceLine);
+void	operator delete(void *reportedAddress);
+void	operator delete[](void *reportedAddress);
+
+#endif // CHMEMORY_H
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// Macros -- "Kids, please don't try this at home. We're trained professionals here." :)
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#include "core/ChMemorynomgr.h"
+#define	new		(m_setOwner  (__FILE__,__LINE__,__FUNCTION__),false) ? NULL : new
+#define	delete		(m_setOwner  (__FILE__,__LINE__,__FUNCTION__),false) ? m_setOwner("",0,"") : delete
+#define	malloc(sz)	m_allocator  (__FILE__,__LINE__,__FUNCTION__,m_alloc_malloc,sz)
+#define	calloc(sz)	m_allocator  (__FILE__,__LINE__,__FUNCTION__,m_alloc_calloc,sz)
+#define	realloc(ptr,sz)	m_reallocator(__FILE__,__LINE__,__FUNCTION__,m_alloc_realloc,sz,ptr)
+#define	free(ptr)	m_deallocator(__FILE__,__LINE__,__FUNCTION__,m_alloc_free,ptr)
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// ChMemory.h - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
+
+#endif // CH_MEMORY_DEBUG
+
diff --git a/SRC/ChronoEngine/core/ChMemorynomgr.h b/SRC/ChronoEngine/core/ChMemorynomgr.h
new file mode 100644
index 0000000..dc04661
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChMemorynomgr.h
@@ -0,0 +1,65 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2005, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChMemory.h
+//
+//   Math functions for :
+//      - MEMORY DEBUGING
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+// 
+// BASED ON:  mmgr.h  by Paul Nettle
+//
+// ------------------------------------------------
+// Originally created on 12/22/2000 by Paul Nettle
+//
+// Copyright 2000, Fluid Studios, Inc., all rights reserved.
+// ------------------------------------------------
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#ifdef	new
+#undef	new
+#endif
+
+#ifdef	delete
+#undef	delete
+#endif
+
+#ifdef	malloc
+#undef	malloc
+#endif
+
+#ifdef	calloc
+#undef	calloc
+#endif
+
+#ifdef	realloc
+#undef	realloc
+#endif
+
+#ifdef	free
+#undef	free
+#endif
+
+// ---------------------------------------------------------------------------------------------------------------------------------
+// nommgr.h - End of file
+// ---------------------------------------------------------------------------------------------------------------------------------
diff --git a/SRC/ChronoEngine/core/ChPlatform.h b/SRC/ChronoEngine/core/ChPlatform.h
new file mode 100644
index 0000000..3a69448
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChPlatform.h
@@ -0,0 +1,54 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHPLATFORM_H
+#define CHPLATFORM_H
+
+//////////////////////////////////////////////////
+//
+//   ChPlatform.h
+//
+//   platform-specific stuff
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+// Functionality for API import/export symbols,
+// in a platform independent way.
+//
+// When building the DLL, the CH_EXPORTS symbol must be defined.
+//
+// Each exported function / class in Chrono::Engine
+// will use the 'ChApi' macro in headers (for non-MS compilers,
+// this has no effect because all symbols will be exported).
+
+#if ((defined _WIN32) || (defined(__MINGW32__) || defined(__CYGWIN__))) && defined(_DLL)
+#if !defined(CH_DLL) && !defined(CH_STATIC)
+#define CH_DLL
+#endif
+#endif
+
+#if ((defined _WIN32) || (defined(__MINGW32__) || defined(__CYGWIN__))) && defined(CH_DLL)
+#define ChApiEXPORT 
+#define ChApiINPORT 
+#else
+#define ChApiEXPORT
+#define ChApiINPORT
+#endif
+
+
+
+#endif  // END of header
diff --git a/SRC/ChronoEngine/core/ChQuaternion.cpp b/SRC/ChronoEngine/core/ChQuaternion.cpp
new file mode 100644
index 0000000..6cdce28
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChQuaternion.cpp
@@ -0,0 +1,478 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChQuaternion.cpp
+//
+//   Math functions for:
+//	 - QUATERNIONS
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+
+#include "core/ChQuaternion.h"
+#include "core/ChMatrix.h"
+
+
+
+namespace chrono
+{
+
+
+
+///////////////////////////////////////////////////
+// QUATERNION OPERATIONS
+
+
+
+
+double Qlenght (Quaternion q)
+{
+	return (sqrt (pow(q.e0, 2) + pow(q.e1, 2) + pow(q.e2, 2) + pow(q.e3, 2)));
+}
+
+Quaternion Qscale (Quaternion q, double fact)
+{
+	Quaternion result;
+	result.e0= q.e0 * fact;
+	result.e1= q.e1 * fact;
+	result.e2= q.e2 * fact;
+	result.e3= q.e3 * fact;
+	return result;
+}
+
+Quaternion Qadd (Quaternion qa, Quaternion qb)
+{
+	Quaternion result;
+	result.e0= qa.e0 + qb.e0;
+	result.e1= qa.e1 + qb.e1;
+	result.e2= qa.e2 + qb.e2;
+	result.e3= qa.e3 + qb.e3;
+	return result;
+}
+
+Quaternion Qsub (Quaternion qa, Quaternion qb)
+{
+	Quaternion result;
+	result.e0= qa.e0 - qb.e0;
+	result.e1= qa.e1 - qb.e1;
+	result.e2= qa.e2 - qb.e2;
+	result.e3= qa.e3 - qb.e3;
+	return result;
+}
+// returns the norm two of the quaternion. Eulero's parameters have norm = 1
+
+Quaternion Qnorm (Quaternion q)
+{
+	double invlenght;
+	invlenght = 1/(Qlenght(q));
+	return Qscale (q, invlenght);
+}
+
+// The conjugate of the quaternion [s,v1,v2,v3] is [s,-v1,-v2,-v3]
+
+Quaternion Qconjugate (Quaternion q)
+{
+	Quaternion res;
+	res.e0= q.e0;
+	res.e1= -q.e1;
+	res.e2= -q.e2;
+	res.e3= -q.e3;
+	return (res);
+}
+
+
+// Returns the product of two quaternions. It is NONcommutative! (like cross
+// product in vectors.
+
+Quaternion Qcross (Quaternion qa, Quaternion qb)
+{
+	Quaternion res;
+	res.e0= qa.e0 * qb.e0 - qa.e1 * qb.e1 - qa.e2 * qb.e2 - qa.e3 * qb.e3;
+	res.e1= qa.e0 * qb.e1 + qa.e1 * qb.e0 - qa.e3 * qb.e2 + qa.e2 * qb.e3;
+	res.e2= qa.e0 * qb.e2 + qa.e2 * qb.e0 + qa.e3 * qb.e1 - qa.e1 * qb.e3;
+	res.e3= qa.e0 * qb.e3 + qa.e3 * qb.e0 - qa.e2 * qb.e1 + qa.e1 * qb.e2;
+	return (res);
+}
+
+
+// Gets the quaternion from an agle of rotation and an axis,
+// defined in _abs_ coords. The axis is supposed to be fixed, i.e.
+// it is constant during rotation! And must be normalized!
+
+Quaternion Q_from_AngAxis (double angle, Vector axis)
+{
+	Quaternion quat;
+	double halfang;
+	double sinhalf;
+
+	halfang= (angle * 0.5);
+	sinhalf= sin (halfang);
+
+	quat.e0 = cos (halfang);
+	quat.e1 = axis.x * sinhalf;
+	quat.e2 = axis.y * sinhalf;
+	quat.e3 = axis.z * sinhalf;
+	return (quat);
+}
+
+
+Quaternion  Q_from_AngZ (double angleZ) { return Q_from_AngAxis (angleZ, VECT_Z);}
+Quaternion  Q_from_AngX (double angleX) { return Q_from_AngAxis (angleX, VECT_X);}
+Quaternion  Q_from_AngY (double angleY) { return Q_from_AngAxis (angleY, VECT_Y);}
+
+Quaternion  Q_from_NasaAngles(Vector mang)
+{
+	Quaternion mq;
+	double c1 = cos(mang.z/2);
+	double s1 = sin(mang.z/2);
+	double c2 = cos(mang.x/2);
+	double s2 = sin(mang.x/2);
+	double c3 = cos(mang.y/2);
+	double s3 = sin(mang.y/2);
+    double c1c2 = c1*c2;
+	double s1s2 = s1*s2;
+	mq.e0 =c1c2*c3 + s1s2*s3;
+  	mq.e1 =c1c2*s3 - s1s2*c3;
+	mq.e2 =c1*s2*c3 + s1*c2*s3;
+	mq.e3 =s1*c2*c3 - c1*s2*s3;
+	return mq;
+}
+Vector      Q_to_NasaAngles(Quaternion q1)
+{
+	Vector mnasa;
+	double sqw = q1.e0*q1.e0;
+	double sqx = q1.e1*q1.e1;
+	double sqy = q1.e2*q1.e2;
+	double sqz = q1.e3*q1.e3;
+	// heading
+	mnasa.z = atan2(2.0 * (q1.e1*q1.e2 + q1.e3*q1.e0),(sqx - sqy - sqz + sqw));
+	// bank
+	mnasa.y = atan2(2.0 * (q1.e2*q1.e3 + q1.e1*q1.e0),(-sqx - sqy + sqz + sqw));
+	// attitude
+	mnasa.x = asin(-2.0 * (q1.e1*q1.e3 - q1.e2*q1.e0));
+	return mnasa;
+}
+
+void Q_to_AngAxis (Quaternion* quat, double* a_angle, Vector* a_axis)
+{
+	double arg, invsine;
+	Vector vtemp;
+
+	if (quat->e0 < 0.99999999)
+	{
+		arg = acos (quat->e0);
+		*a_angle = 2*arg;
+		invsine = 1 / (sin(arg));
+		vtemp.x = invsine * quat->e1;
+		vtemp.y = invsine * quat->e2;
+		vtemp.z = invsine * quat->e3;
+		*a_axis = Vnorm (vtemp);
+	}
+	else
+	{
+		a_axis->x = 1;
+		a_axis->y = 0;
+		a_axis->z = 0;
+		*a_angle  = 0;
+	}
+}
+
+
+//	Gets the four quaternion dq/dt from the vector of angular speed,
+// with w specified in _absolute_ coords.
+
+Quaternion Qdt_from_Wabs (Vector w, Quaternion q)
+{
+	static Quaternion qw;
+	double half = 0.5;
+
+	qw.e0=0; qw.e1=w.x; qw.e2=w.y; qw.e3=w.z;
+
+	return Qscale(Qcross(qw, q), half);  // {q_dt} = 1/2 {0,w}*{q}
+}
+
+//	Gets the four quaternion dq/dt from the vector of angular speed,
+// with w specified in _local_ coords.
+
+Quaternion Qdt_from_Wrel (Vector w, Quaternion q)
+{
+	static Quaternion qw;
+	double half = 0.5;
+
+	qw.e0=0; qw.e1=w.x; qw.e2=w.y; qw.e3=w.z;
+
+	return Qscale(Qcross(q, qw), half);  // {q_dt} = 1/2 {q}*{0,w_rel}
+}
+
+//	Gets the quaternion ddq/dtdt from the vector of angular acceleration
+//  with a specified in _absolute_ coords.
+
+Quaternion Qdtdt_from_Aabs (Vector a, Quaternion q, Quaternion q_dt)
+{
+	Quaternion ret;
+	ret.Qdtdt_from_Aabs(a,q,q_dt);
+	return ret;
+
+}
+
+//	Gets the quaternion ddq/dtdt from the vector of angular acceleration
+//  with a specified in _relative_ coords.
+
+Quaternion Qdtdt_from_Arel (Vector a, Quaternion q, Quaternion q_dt)
+{
+	Quaternion ret;
+	ret.Qdtdt_from_Arel(a,q,q_dt);
+	return ret;
+}
+
+// Gets the dquaternion/dt from a quaternion, a speed of
+// rotation and an axis, defined in _abs_ coords.
+
+Quaternion Qdt_from_AngAxis (Quaternion quat, double angle_dt, Vector axis)
+{
+	Vector W;
+
+	W = Vmul (axis, angle_dt);
+
+	return (chrono::Qdt_from_Wabs (W, quat));
+}
+
+// Gets the ddquaternion/dtdt from a quaternion, an angular
+// acceleration and an axis, defined in _abs_ coords.
+
+Quaternion Qdtdt_from_AngAxis (double angle_dtdt, Vector axis, Quaternion q, Quaternion q_dt)
+{
+	Vector Acc;
+
+	Acc = Vmul (axis, angle_dtdt);
+
+	return (chrono::Qdtdt_from_Aabs (Acc, q, q_dt));
+}
+
+
+// Returns TRUE if two quaternions are equal
+
+int  Qequal  (Quaternion* qa, Quaternion* qb)
+{
+	if ((qa->e0 == qb->e0) &&
+		(qa->e1 == qb->e1) &&
+		(qa->e2 == qb->e2) &&
+		(qa->e3 == qb->e3)) return 1;
+	else return 0;
+}
+
+// Returns TRUE if quaternion is not null;
+
+int  Qnotnull  (Quaternion* qa)
+{
+	if (qa->e0) return 1;
+	if (qa->e1) return 1;
+	if (qa->e2) return 1;
+	if (qa->e3) return 1;
+	return 0;
+}
+
+// Given the immaginary (vectorial) {e1 e2 e3} part of a quaternion, tries to find the
+// entire quaternion q = {e0, e1, e2, e3}. Also for q_dt and q_dtdt
+// Note: singularities may happen!
+
+Quaternion  ImmQ_complete (Vector* qimm)
+{
+	Quaternion mq;
+	mq.e1 = qimm->x;  mq.e2 = qimm->y;  mq.e3 = qimm->z;
+	mq.e0 = sqrt(1- mq.e1*mq.e1 - mq.e2*mq.e2 - mq.e3*mq.e3);
+	return (mq);
+}
+
+Quaternion  ImmQ_dt_complete (Quaternion* mq, Vector* qimm_dt)
+{
+	Quaternion mqdt;
+	mqdt.e1 = qimm_dt->x;  mqdt.e2 = qimm_dt->y;  mqdt.e3 = qimm_dt->z;
+	mqdt.e0 = (- mq->e1*mqdt.e1 - mq->e2*mqdt.e2 - mq->e3*mqdt.e3) / mq->e0;
+	return (mqdt);
+}
+
+Quaternion  ImmQ_dtdt_complete (Quaternion* mq, Quaternion* mqdt, Vector* qimm_dtdt)
+{
+	Quaternion mqdtdt;
+	mqdtdt.e1 = qimm_dtdt->x;  mqdtdt.e2 = qimm_dtdt->y;  mqdtdt.e3 = qimm_dtdt->z;
+	mqdtdt.e0 = (- mq->e1*mqdtdt.e1 - mq->e2*mqdtdt.e2 - mq->e3*mqdtdt.e3
+				 - mqdt->e0*mqdt->e0 - mqdt->e1*mqdt->e1 - mqdt->e2*mqdt->e2 - mqdt->e3*mqdt->e3) / mq->e0;
+	return (mqdtdt);
+}
+
+
+
+////////////////////////////////////////////////////////////
+//  ANGLE CONVERSION UTILITIES
+
+
+Quaternion Angle_to_Quat (int angset, Vector* mangles)
+{
+	Quaternion res;
+	ChMatrix33<> Acoord;
+
+	switch (angset)
+	{
+	case ANGLESET_EULERO:
+		Acoord.Set_A_Eulero(*mangles);
+		break;
+	case ANGLESET_CARDANO:
+		Acoord.Set_A_Cardano(*mangles);
+		break;
+	case ANGLESET_HPB:
+		Acoord.Set_A_Hpb(*mangles);
+		break;
+	case ANGLESET_RXYZ:
+		Acoord.Set_A_Rxyz(*mangles);
+		break;
+	case ANGLESET_RODRIGUEZ:
+		Acoord.Set_A_Rodriguez(*mangles);
+		break;
+	}
+	res = Acoord.Get_A_quaternion();
+	return res;
+}
+
+Vector Quat_to_Angle (int angset, Quaternion* mquat)
+{
+	Vector res;
+	ChMatrix33<> Acoord;
+
+	Acoord.Set_A_quaternion(*mquat);
+
+	switch (angset)
+	{
+	case ANGLESET_EULERO:
+		res = Acoord.Get_A_Eulero();
+		break;
+	case ANGLESET_CARDANO:
+		res = Acoord.Get_A_Cardano();
+		break;
+	case ANGLESET_HPB:
+		res = Acoord.Get_A_Hpb();
+		break;
+	case ANGLESET_RXYZ:
+		res = Acoord.Get_A_Rxyz();
+		break;
+	case ANGLESET_RODRIGUEZ:
+		res = Acoord.Get_A_Rodriguez();
+		break;
+	}
+	return res;
+}
+
+Quaternion AngleDT_to_QuatDT (int angset, Vector* mangles, Quaternion* q)
+{
+	Quaternion res;
+	Quaternion q2;
+	Vector ang1, ang2;
+
+	ang1 = Quat_to_Angle (angset, q);
+	ang2 = Vadd(ang1, Vmul(*mangles,CH_LOWTOL));
+	q2 = Angle_to_Quat(angset, &ang2);
+	res = Qscale (Qsub(q2, *q), (1/CH_LOWTOL));
+
+	return res;
+}
+
+Quaternion AngleDTDT_to_QuatDTDT (int angset, Vector* mangles, Quaternion* q)
+{
+	Quaternion res;
+	Quaternion qa, qb;
+	Vector ang0, angA, angB;
+	double hsquared = CH_LOWTOL;
+
+	ang0 = Quat_to_Angle (angset, q);
+	angA = Vsub(ang0, Vmul(*mangles, hsquared));
+	angB = Vadd(ang0, Vmul(*mangles, hsquared));
+	qa = Angle_to_Quat(angset, &angA);
+	qb = Angle_to_Quat(angset, &angB);
+	res = Qscale (Qadd(Qadd(qa,qb),Qscale(*q,-2)), 1/hsquared);
+
+	return res;
+}
+
+Vector	Angle_to_Angle(int setfrom, int setto, Vector* mangles)
+{
+	Vector res;
+	ChMatrix33<> Acoord;
+
+	switch (setfrom)
+	{
+	case ANGLESET_EULERO:
+		Acoord.Set_A_Eulero(*mangles);
+		break;
+	case ANGLESET_CARDANO:
+		Acoord.Set_A_Cardano(*mangles);
+		break;
+	case ANGLESET_HPB:
+		Acoord.Set_A_Hpb(*mangles);
+		break;
+	case ANGLESET_RXYZ:
+		Acoord.Set_A_Rxyz(*mangles);
+		break;
+	case ANGLESET_RODRIGUEZ:
+		Acoord.Set_A_Rodriguez(*mangles);
+		break;
+	}
+
+	switch (setto)
+	{
+	case ANGLESET_EULERO:
+		res = Acoord.Get_A_Eulero();
+		break;
+	case ANGLESET_CARDANO:
+		res = Acoord.Get_A_Cardano();
+		break;
+	case ANGLESET_HPB:
+		res = Acoord.Get_A_Hpb();
+		break;
+	case ANGLESET_RXYZ:
+		res = Acoord.Get_A_Rxyz();
+		break;
+	case ANGLESET_RODRIGUEZ:
+		res = Acoord.Get_A_Rodriguez();
+		break;
+	}
+	return res;
+}
+
+
+
+// Get the X axis of a coordsystem, given the quaternion which
+// represents the alignment of the coordsystem.
+Vector VaxisXfromQuat (Quaternion quat)
+{
+	Vector res;
+	res.x = (pow(quat.e0,2) + pow(quat.e1,2))*2 - 1;
+	res.y = ((quat.e1*quat.e2) + (quat.e0*quat.e3))*2;
+	res.z = ((quat.e1*quat.e3) - (quat.e0*quat.e2))*2;
+	return res;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+////////
+
diff --git a/SRC/ChronoEngine/core/ChQuaternion.h b/SRC/ChronoEngine/core/ChQuaternion.h
new file mode 100644
index 0000000..b65adcf
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChQuaternion.h
@@ -0,0 +1,677 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHQUATERNION_H
+#define CHQUATERNION_H
+
+//////////////////////////////////////////////////
+//  
+//   ChQuaternion.h
+//
+//   Math functions for :
+//      - QUATERNIONS
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChVector.h"
+#include "ChApiCE.h"
+
+
+namespace chrono
+{
+
+
+
+///
+/// QUATERNION:	
+///
+/// Class defining quaternion objects, that is four-dimensional
+/// numbers, also known as Eulero's parameters.
+/// Quaternions are very handy when used to represent rotations in 3d.	
+///
+///  The quaternion object comes either with the template "ChQuaternion<type>" mode,
+/// either in the 'shortcut' flavour, that is "Quaternion", which assumes
+/// the type of the four scalars is double precision, so it is faster to type.
+///  For example, for a declaration, you can write "ChQuaternion<double> foo;", 
+/// as well as "Quaternion foo;" (less typing effort for the second..)
+///
+
+template <class Real = double>
+class ChQuaternion 
+{
+public:
+			//
+			// DATA
+			//
+	Real e0;
+	Real e1;
+	Real e2;
+	Real e3;
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChQuaternion(): e0(0), e1(0), e2(0), e3(0) {};
+	ChQuaternion(const Real ne0, const Real ne1, const Real ne2,const Real ne3) : e0(ne0), e1(ne1), e2(ne2), e3(ne3) {};
+	ChQuaternion(const Real ns, const ChVector<Real> nv) : e0(ns), e1(nv.x), e2(nv.y), e3(nv.z) {} 
+
+			/// Copy constructor 
+	ChQuaternion(const ChQuaternion<Real>& other) : e0(other.e0),e1(other.e1),e2(other.e2),e3(other.e3)  {};
+
+			/// Copy constructor between vectors float<->double etc
+	template <class RealB>
+	ChQuaternion(const ChQuaternion<RealB>& other)	: e0(other.e0),e1(other.e1),e2(other.e2),e3(other.e3)  {}
+						
+			//
+			// OPERATORS OVERLOADING
+			//
+			// Note: c++ automatically creates temporary objects to store intermediate
+			// results in long formulas, such as a= b*c*d, so the usage of operators
+			// may give slower results than a wise (less readable however) usage of
+			// Dot(), Cross() etc.. Also pay attention to C++ operator precedence rules!
+
+					/// Assignment operator: copy from another quaternion
+	ChQuaternion<Real>& operator=(const ChQuaternion<Real>& other)	
+							{ if (&other == this) return *this; e0 = other.e0;  e1 = other.e1; e2 = other.e2; e3 = other.e3; return *this; }
+				
+					/// Operator for sign change 
+	ChQuaternion<Real>  operator-() const { return ChQuaternion<Real>(-e0, -e1, -e2, -e3);   }
+
+					/// Operator for making a conjugate quaternion (the original is not changed)
+					/// A conjugate quaternion has the vectorial part with changed sign
+	ChQuaternion<Real>  operator!() const { return ChQuaternion<Real>(e0, -e1, -e2, -e3);};
+
+					/// Operator for quaternion sum
+	ChQuaternion<Real>  operator+(const ChQuaternion<Real>& other) const { return ChQuaternion<Real>(e0+other.e0, e1+other.e1, e2+other.e2, e3+other.e3);	}
+	ChQuaternion<Real>& operator+=(const ChQuaternion<Real>& other)	{ e0+=other.e0;  e1+=other.e1; e2+=other.e2;  e3+=other.e3; return *this; }
+
+					/// Operator for quaternion difference
+	ChQuaternion<Real>  operator-(const ChQuaternion<Real>& other) const { return ChQuaternion<Real>(e0-other.e0, e1-other.e1, e2-other.e2, e3-other.e3);	}
+	ChQuaternion<Real>& operator-=(const ChQuaternion<Real>& other)	{ e0-=other.e0;  e1-=other.e1; e2-=other.e2;  e3-=other.e3; return *this; }
+
+					/// Operator for element-wise multiplication (note that
+					/// this is neither dot product nor quaternion product! Quaternion product  is % operator!)
+	ChQuaternion<Real>  operator*(const ChQuaternion<Real>& other) const { return ChQuaternion<Real>(e0*other.e0, e1*other.e1, e2*other.e2, e3*other.e3);	}
+	ChQuaternion<Real>& operator*=(const ChQuaternion<Real>& other)	{ e0*=other.e0; e1*=other.e1; e2*=other.e2; e3*=other.e3; return *this; }
+
+					// Operator for scaling the quaternion by a scalar value, as q*s
+	ChQuaternion<Real>  operator*(const Real v) const { return ChQuaternion<Real>(e0 * v, e1 * v, e2 * v, e3 * v);	}
+	ChQuaternion<Real>& operator*=(const Real v) { e0*=v; e1*=v; e2*=v; e3*=v; return *this; }
+
+					/// Operator for element-wise division (note that
+					/// this is NOT the quaternion division operation!)
+	ChQuaternion<Real>  operator/(const ChQuaternion<Real>& other) const { return ChQuaternion<Real>(e0/other.e0, e1/other.e1, e2/other.e2, e3/other.e3);	}
+	ChQuaternion<Real>& operator/=(const ChQuaternion<Real>& other)	{ e0/=other.e0; e1/=other.e1; e2/=other.e2; e3/=other.e3; return *this; }
+
+					/// Operator for scaling the quaternion by inverse of a scalar value, as q/s
+	ChQuaternion<Real>  operator/(const Real v) const { Real i=(Real)1.0/v; return ChQuaternion<Real>(e0 * i, e1 * i, e2 * i, e3 * i);	}
+	ChQuaternion<Real>& operator/=(const Real v) { Real i=(Real)1.0/v; e0*=i; e1*=i; e2*=i; e3*=i; return *this; }
+
+					/// Operator for quaternion product: A%B means the typical quaternion product AxB
+					/// Note: pay attention to operator low precedence (see C++ precedence rules!)
+	ChQuaternion<Real> operator%(const ChQuaternion<Real>& other) const { ChQuaternion<Real> mr; mr.Cross(*this, other); return mr;}
+	ChQuaternion<Real>& operator%=(const ChQuaternion<Real>& other) { this->Cross(*this, other); return *this;}
+
+					/// Operator for dot product: A^B means the scalar dot-product A*B
+					/// Note: pay attention to operator low precedence (see C++ precedence rules!)
+	double operator^(const ChQuaternion<Real>& other) const { return Dot(*this, other);}
+
+
+
+	bool operator<=(const ChQuaternion<Real>&other) const { return e0<=other.e0 && e1<=other.e1 && e2<=other.e2 && e3<=other.e3;};
+	bool operator>=(const ChQuaternion<Real>&other) const { return e0>=other.e0 && e1>=other.e1 && e2>=other.e2 && e3>=other.e3;};
+
+	bool operator==(const ChQuaternion<Real>& other) const { return other.e0==e0 && other.e1==e1 && other.e2==e2 && other.e3==e3; }
+	bool operator!=(const ChQuaternion<Real>& other) const { return other.e0!=e0 || other.e1!=e1 || other.e2!=e2 || other.e3!=e3; }
+
+
+
+
+				//
+				// FUNCTIONS
+				//
+
+
+					/// Sets the four values of the quaternion at once
+	void Set(const Real ne0, const Real ne1, const Real ne2, const Real ne3) 
+						{ e0=ne0; e1=ne1; e2=ne2; e3=ne3;}
+
+					/// Sets the quaternion as a copy of another quaternion
+	void Set(const ChQuaternion<Real>& n) {  e0=n.e0; e1=n.e1; e2=n.e2; e3=n.e3;}
+
+					/// Sets the quaternion with four components as a sample scalar
+	void Set(const Real p) { e0=p; e1=p; e2=p; e3=p;}
+
+					/// Sets the quaternion as a null quaternion
+	void SetNull() { e0=e1=e2=e3=0;};
+					/// Sets the quaternion as a unit quaternion
+	void SetUnit() { e0=1.; e1=e2=e3=0;};
+					/// Sets the scalar part only
+	void SetScalar(const Real s) { e0=s;};
+					/// Sets the vectorial part only
+	void SetVector(const ChVector<Real>& mv) { e1=mv.x; e2=mv.y; e3=mv.z;};
+					/// Gets the vectorial part only
+	ChVector<Real> GetVector() { return ChVector<Real>(e1,e2,e3);};
+
+					/// Returns true if quaternion is identical to other quaternion
+	bool	Equals ( const ChQuaternion<Real>& other) const { return (other.e0==e0) && (other.e1==e1) && (other.e2==e2) && (other.e3==e3);}
+
+					/// Returns true if quaternion equals another quaternion, within a tolerance 'tol'
+	bool	Equals ( const ChQuaternion<Real>& other, Real tol) const
+						{
+							return  (fabs(other.e0-e0)<tol) &&
+									(fabs(other.e1-e1)<tol) &&
+									(fabs(other.e2-e2)<tol) &&
+									(fabs(other.e3-e3)<tol); 
+						}
+		
+					/// The quaternion becomes the sum of the two quaternions A and B: 
+					/// this=A+B
+	void 	Add    ( const ChQuaternion<Real> A, const ChQuaternion<Real> B) 
+						{
+							e0=A.e0+B.e0; e1=A.e1+B.e1; e2=A.e2+B.e2; e3=A.e3+B.e3; 
+						}
+
+					/// The quaternion becomes the difference of the two quaternions A and B: 
+					/// this=A-B
+	void 	Sub	   ( const ChQuaternion<Real> A, const ChQuaternion<Real> B) 
+						{ 
+							e0=A.e0-B.e0; e1=A.e1-B.e1; e2=A.e2-B.e2; e3=A.e3-B.e3;
+						}
+
+					/// The quaternion becomes the quaternion product of the two quaternions A and B: 
+					/// following the classic Hamilton rule:  this=AxB
+					/// This is the true, typical quaternion product. It is NOT commutative.
+	void	Cross  ( const ChQuaternion<Real> qa, const ChQuaternion<Real> qb) 
+						{
+							this->e0= qa.e0 * qb.e0 - qa.e1 * qb.e1 - qa.e2 * qb.e2 - qa.e3 * qb.e3;
+							this->e1= qa.e0 * qb.e1 + qa.e1 * qb.e0 - qa.e3 * qb.e2 + qa.e2 * qb.e3;
+							this->e2= qa.e0 * qb.e2 + qa.e2 * qb.e0 + qa.e3 * qb.e1 - qa.e1 * qb.e3;
+							this->e3= qa.e0 * qb.e3 + qa.e3 * qb.e0 - qa.e2 * qb.e1 + qa.e1 * qb.e2;
+						}
+
+					/// The result is dot product of the two quaternion A and B: 
+					/// result=A*B. This kind of product is not used a lot, anyway...
+	double  Dot   ( const ChQuaternion<Real> A, const ChQuaternion<Real> B) const
+						{  
+							return (A.e0 * B.e0)+(A.e1 * B.e1)+(A.e2 * B.e2)+(A.e3 * B.e3);
+						};
+
+					/// The quaternion becomes the product of a quaternion A and a scalar v: 
+					/// this=A*v
+	void 	Mul	   ( const ChQuaternion<Real> A, const Real v) 
+						{ 
+							e0=A.e0*v; e1=A.e1*v; e2=A.e2*v; e3=A.e3*v; 
+						}
+
+					/// The quaternion is multiplied by a scalar factor 's' 
+					/// this*=v
+	void    Scale  ( const Real v) { e0*=v; e1*=v; e2*=v; e3*=v;}
+
+					/// Computes the euclidean norm of the quaternion,
+					/// that is its length or magnitude
+	double	Length	 () { return sqrt(e0*e0 + e1*e1 + e2*e2 + e3*e3); }
+
+					/// Computes the euclidean norm of the quaternion, squared 
+					/// (i.e. as Length(), but skipping the square root)
+	double	Length2	 () { return (e0*e0 + e1*e1 + e2*e2 + e3*e3); }
+
+					/// Computes the infinite norm of the quaternion, that
+					/// is the maximum absolute value of one of its elements
+	double	LengthInf () { return ChMax(ChMax(ChMax(fabs(e0),fabs(e1)), fabs(e2)), fabs(e3)); }
+
+					/// Normalize this quaternion, so that its euclidean length is 1. 
+					/// Returns false if original quaternion had zero length (in such a case 
+					/// it will be defaulted as 1,0,0,0) otherwise returns true for success.  
+	bool    Normalize () 
+						{
+							double mlenght = this->Length();
+							if (mlenght<CH_NANOTOL)
+							{
+								e0=1.; e1=e2=e3=0.; 
+								return false;
+							}else
+							{	
+								this->Scale(1.0/mlenght); 
+							}
+							return true;
+						}
+					/// Return a normalized copy of this quaternion, with euclidean length =1.
+					/// Not to be confused with Normalize(), that normalizes in place.
+	ChQuaternion<Real> GetNormalized() const
+						{
+							ChQuaternion<Real> mret(*this);
+							mret.Normalize();
+							return mret;
+						}
+
+					/// The quaternion is set as the conjugate of A quaternion
+	void	Conjugate (const ChQuaternion<Real>& A) 
+						{
+							e0 = A.e0;  e1 = -A.e1; e2 = -A.e2; e3 = -A.e3;
+						}
+
+					/// The quaternion itself is conjugated (its vectorial part changes sign)
+	void	Conjugate () { Conjugate(*this);}
+
+					/// Returns a conjugated version of this quaternion.
+	ChQuaternion<Real> 	GetConjugate () const { return ChQuaternion<Real>(e0, -e1, -e2, -e3);}
+	
+
+				//
+				// TRANSFORMATIONS
+				//
+
+					/// Rotates the vector A on the basis of this quaternion: res=p*[0,A]*p'
+					/// (speed-optimized version). Endomorphism assumes p is already normalized.
+	ChVector<Real> Rotate(const ChVector<Real> A) const
+						{
+							double e0e0 = e0 * e0;
+							double e1e1 = e1 * e1;
+							double e2e2 = e2 * e2;
+							double e3e3 = e3 * e3;
+							double e0e1 = e0 * e1;
+							double e0e2 = e0 * e2;
+							double e0e3 = e0 * e3;
+							double e1e2 = e1 * e2; 
+							double e1e3 = e1 * e3; 
+							double e2e3 = e2 * e3; 
+							return ChVector<Real> (
+							 ((e0e0 + e1e1)*2. - 1.)*A.x + ((e1e2 - e0e3)*2. )*A.y + ((e1e3 + e0e2)*2. )*A.z ,
+							 ((e1e2 + e0e3)*2. )*A.x + ((e0e0 + e2e2)*2. - 1.)*A.y + ((e2e3 - e0e1)*2. )*A.z ,
+							 ((e1e3 - e0e2)*2. )*A.x + ((e2e3 + e0e1)*2. )*A.y + ((e0e0 + e3e3)*2. - 1.)*A.z  );
+						}
+
+					/// Rotates the vector A on the basis of conjugate of this quaternion: res=p'*[0,A]*p
+					/// (speed-optimized version).  Endomorphism assumes p is already normalized.
+	ChVector<Real> RotateBack(const ChVector<Real> A) const
+						{
+							double e0e0 = e0 * e0;
+							double e1e1 = e1 * e1;
+							double e2e2 = e2 * e2;
+							double e3e3 = e3 * e3;
+							double e0e1 = -e0 * e1;
+							double e0e2 = -e0 * e2;
+							double e0e3 = -e0 * e3;
+							double e1e2 = e1 * e2; 
+							double e1e3 = e1 * e3; 
+							double e2e3 = e2 * e3; 
+							return ChVector<Real> (
+							 ((e0e0 + e1e1)*2. - 1.)*A.x + ((e1e2 - e0e3)*2. )*A.y + ((e1e3 + e0e2)*2. )*A.z ,
+							 ((e1e2 + e0e3)*2. )*A.x + ((e0e0 + e2e2)*2. - 1.)*A.y + ((e2e3 - e0e1)*2. )*A.z ,
+							 ((e1e3 - e0e2)*2. )*A.x + ((e2e3 + e0e1)*2. )*A.y + ((e0e0 + e3e3)*2. - 1.)*A.z  );
+						}
+	
+
+				//
+				// CONVERSIONS
+				//
+
+					/// Sets the quaternion from an agle of rotation and an axis, 
+					/// defined in _absolute_ coords. The axis is supposed to be fixed, i.e.
+					/// it is constant during rotation! NOTE, axismust be normalized!
+	void  Q_from_AngAxis(const double angle, const ChVector<Real> axis)
+						{
+							double halfang= (angle * 0.5);
+							double sinhalf= sin (halfang);
+							this->e0 = cos (halfang);
+							this->e1 = axis.x * sinhalf;
+							this->e2 = axis.y * sinhalf;
+							this->e3 = axis.z * sinhalf;
+						}
+
+					/// Sets the quaternion from an agle of rotation about X axis
+	void  Q_from_AngX (const double angleX) { Q_from_AngAxis(angleX, VECT_X);}
+
+					/// Sets the quaternion from an agle of rotation about Y axis
+	void  Q_from_AngY (const double angleY) { Q_from_AngAxis(angleY, VECT_Y);}
+
+					/// Sets the quaternion from an agle of rotation about Z axis
+	void  Q_from_AngZ (const double angleZ) { Q_from_AngAxis(angleZ, VECT_Z);}
+
+					/// Converts the quaternion to an agle of rotation and an axis, 
+					/// defined in _absolute_ coords. Resulting angle and axis must be passed as parameters
+	void  Q_to_AngAxis (double& a_angle, ChVector<Real>& a_axis)
+						{
+							double arg, invsine;
+							if (e0 < 0.99999999)
+							{
+								arg = acos (e0);
+								a_angle = 2.0 *arg;
+								invsine = 1.0 / (sin(arg));
+								a_axis.x = invsine * e1;
+								a_axis.y = invsine * e2;
+								a_axis.z = invsine * e3;
+								a_axis.Normalize();
+							}
+							else
+							{
+								a_axis.x = 1;
+								a_axis.y = 0;
+								a_axis.z = 0;
+								a_angle  = 0;
+							}
+						}
+
+
+					/// Sets the quaternion from three angles (NASA angle set) heading,
+					/// bank and attitude
+	void  Q_from_NasaAngles(const ChVector<Real> mang)
+						{
+							double c1 = cos(mang.z/2);
+							double s1 = sin(mang.z/2);
+							double c2 = cos(mang.x/2);
+							double s2 = sin(mang.x/2);
+							double c3 = cos(mang.y/2);
+							double s3 = sin(mang.y/2);
+							double c1c2 = c1*c2;
+							double s1s2 = s1*s2;
+							e0 =c1c2*c3 + s1s2*s3;
+  							e1 =c1c2*s3 - s1s2*c3;
+							e2 =c1*s2*c3 + s1*c2*s3;	
+							e3 =s1*c2*c3 - c1*s2*s3;
+						}
+
+					/// Converts the quaternion to three angles (NASA angle set)  heading,
+					/// bank and attitude
+	ChVector<Real>  Q_to_NasaAngles()
+						{
+							ChVector<Real> mnasa;
+							double sqw = e0*e0;    
+							double sqx = e1*e1;    
+							double sqy = e2*e2;    
+							double sqz = e3*e3;
+							// heading
+							mnasa.z = atan2(2.0 * (e1*e2 + e3*e0),(sqx - sqy - sqz + sqw));    
+							// bank
+							mnasa.y = atan2(2.0 * (e2*e3 + e1*e0),(-sqx - sqy + sqz + sqw));    
+							// attitude
+							mnasa.x = asin(-2.0 * (e1*e3 - e2*e0));
+							return mnasa;
+						}
+
+
+
+					///	Sets the quaternion dq/dt. Inputs:  the vector of angular speed
+					/// w specified in _absolute_ coords, and the rotation expressed 
+					/// as a quaternion q.
+	void Qdt_from_Wabs (const ChVector<Real> w, 
+						const ChQuaternion<Real> q)
+						{
+							ChQuaternion<Real> qwo(0,w);
+							this->Cross(qwo, q);
+							this->Scale(0.5);		// {q_dt} = 1/2 {0,w}*{q} 
+						}
+
+					///	Sets the quaternion dq/dt. Inputs:  the vector of angular speed
+					/// w specified in _relative coords, and the rotation expressed 
+					/// as a quaternion q.
+	void Qdt_from_Wrel (const ChVector<Real> w, 
+						const ChQuaternion<Real> q)
+						{
+							ChQuaternion<Real> qwl(0,w);
+							this->Cross(q, qwl);
+							this->Scale(0.5);  // {q_dt} = 1/2 {q}*{0,w_rel}
+						}
+
+					///	Computes the vector of angular speed 'w' specified in _absolute_ coords,
+					/// from the quaternion dq/dt and the rotation expressed as a quaternion q.
+	void Qdt_to_Wabs (  ChVector<Real> w, 
+						const ChQuaternion<Real> q)
+						{
+							ChQuaternion<Real> qwo;
+							qwo.Cross(*this, q.GetConjugate());
+							w = qwo.GetVector();
+							w.Scale(2.0);
+						}
+
+					///	Computes the vector of angular speed 'w' specified in _relative_ coords,
+					/// from the quaternion dq/dt and the rotation expressed as a quaternion q.
+	void Qdt_to_Wrel (  ChVector<Real> w, 
+						const ChQuaternion<Real> q)
+						{
+							ChQuaternion<Real> qwl;
+							qwl.Cross(q.GetConjugate(), *this);
+							w = qwl.GetVector();
+							w.Scale(2.0);
+						}
+
+
+					///	Sets the quaternion ddq/dtdt. Inputs: the vector of angular acceleration
+					/// 'a' specified in _absolute_ coords, the rotation expressed 
+					/// as a quaternion q, the rotation speed as a quaternion 'q_dt'.
+	void Qdtdt_from_Aabs (	const ChVector<Real>     a, 
+							const ChQuaternion<Real> q, 
+							const ChQuaternion<Real> q_dt)
+						{
+							ChQuaternion<Real> qao(0,a);
+							ChQuaternion<Real> qwo;
+							ChQuaternion<Real> qtmpa;
+							ChQuaternion<Real> qtmpb;
+							qwo.Cross(q_dt, q.GetConjugate());
+							qtmpb.Cross(qwo,q_dt);
+							qtmpa.Cross(qao, q);
+							qtmpa.Scale(0.5);
+							this->Add(qtmpa, qtmpb);
+						}
+
+					///	Sets the quaternion ddq/dtdt. Inputs: the vector of angular acceleration
+					/// 'a' specified in _relative_ coords, the rotation expressed 
+					/// as a quaternion q, the rotation speed as a quaternion 'q_dt'.
+	void Qdtdt_from_Arel      ( const ChVector<Real>	 a, 
+								const ChQuaternion<Real> q, 
+								const ChQuaternion<Real> q_dt)
+						{
+							ChQuaternion<Real> qal(0,a);
+							ChQuaternion<Real> qwl;
+							ChQuaternion<Real> qtmpa;
+							ChQuaternion<Real> qtmpb;
+							qwl.Cross(q.GetConjugate(), q_dt);
+							qtmpb.Cross(q_dt, qwl);
+							qtmpa.Cross(q, qal);
+							qtmpa.Scale(0.5);
+							this->Add(qtmpa, qtmpb);
+						}
+
+					///	Sets the quaternion dq/dt. Inputs:  the axis of rotation 'axis' 
+					/// (assuming it is already normalized and in _absolute_ coords), 
+					/// the angular speed 'angle_dt' (scalar value), and the 
+					/// rotation expressed as a quaternion 'q'.
+	void Qdt_from_AngAxis (		const ChQuaternion<Real>  q, 
+								const double              angle_dt, 
+								const ChVector<Real>      axis)
+						{
+							this->Qdt_from_Wabs ( Vmul (axis, angle_dt) , q);
+						}
+
+					///	Sets the quaternion ddq/dtdt. Inputs: the axis of ang.acceleration 'axis' 
+					/// (assuming it is already normalized and in _absolute_ coords), 
+					/// the angular acceleration 'angle_dtdt' (scalar value), the 
+					/// rotation expressed as a quaternion 'quat' and th rotation speed 'q_dt'.
+	void Qdtdt_from_AngAxis (	const ChQuaternion<Real>  q, 
+								const ChQuaternion<Real>  q_dt,
+								const double              angle_dtdt, 
+								const ChVector<Real>      axis)
+						{
+							this->Qdtdt_from_Aabs ( Vmul (axis, angle_dtdt), q, q_dt);
+						}
+
+
+					/// Given the immaginary (vectorial) {e1 e2 e3} part of a quaternion, 
+					/// tries to set the entire quaternion q = {e0, e1, e2, e3}. 
+					/// Also for q_dt and q_dtdt
+					/// Note: singularities may happen!
+	void ImmQ_complete (const ChVector<Real>& qimm)
+						{
+							SetVector(qimm);
+							e0 = sqrt(1- e1*e1 - e2*e2 - e3*e3);
+						}
+	void ImmQ_dt_complete (const ChQuaternion<Real>& mq, const ChVector<Real>& qimm_dt)
+						{
+							SetVector(qimm_dt);
+							e0 = (- mq.e1*e1 - mq.e2*e2 - mq.e3*e3) / mq.e0;
+						}
+	void ImmQ_dtdt_complete (const ChQuaternion<Real>& mq, const ChQuaternion<Real>& mqdt, const ChVector<Real>& qimm_dtdt)
+						{
+							SetVector(qimm_dtdt);
+							e0 = (- mq.e1*e1 - mq.e2*e2 - mq.e3*e3 
+										 - mqdt.e0*mqdt.e0 - mqdt.e1*mqdt.e1 - mqdt.e2*mqdt.e2 - mqdt.e3*mqdt.e3) / mq.e0;
+						}
+
+	
+					/// Gets the X axis of a coordsystem, given the quaternion which
+					/// represents the alignment of the coordsystem. Assuming that quaternion is already normalized!
+	ChVector<Real> GetXaxis()
+						{
+							return ChVector<Real> ( (e0*e0 + e1*e1)*2.0 - 1.0 , 
+													((e1*e2) + (e0*e3))*2.0 ,
+													((e1*e3) - (e0*e2))*2.0  );
+						}
+
+
+			//
+			// STREAMING
+			//
+					/// Method to allow serializing transient data into ascii
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream)
+						{
+							mstream << "\n" << e0 << "\n" << e1 << "\n" << e2 << "\n" << e3 << "\n"; 
+						}
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream)
+						{
+							mstream << e0;
+							mstream << e1;
+							mstream << e2;
+							mstream << e3;
+						}
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream)
+						{
+							mstream >> e0;
+							mstream >> e1;
+							mstream >> e2;
+							mstream >> e3;
+						}
+
+
+};
+
+
+
+/// Shortcut for faster use of typical double-precision quaternion.
+///  Instead of writing    "ChQuaternion<double> foo;"   you can write 
+///  the shorter version   "Quaternion foo;"
+///
+typedef ChQuaternion<double> Quaternion;
+
+/// Shortcut for faster use of typical single-precision quaternion.
+///
+typedef ChQuaternion<float>  QuaternionF;
+
+
+
+
+//
+// STATIC QUATERNION MATH OPERATIONS
+//
+//  These functions are here for people which prefer to use static 
+// functions instead of ChQuaternion class' member functions.
+// NOTE: sometimes a wise adoption of the following functions may
+// give faster results than using overloaded operators +/-/* in 
+// the quaternion class.
+//  Also, these functions are here for backward compatibility with
+// old parts of chrono code.
+//  For best readability of our code, it is suggested not to use 
+// these functions - use the member functions or operators of 
+// the ChQuaternion class instead!
+
+ChApi double		Qlenght (Quaternion q);
+ChApi Quaternion	Qadd (Quaternion qa, Quaternion qb);
+ChApi Quaternion	Qsub (Quaternion qa, Quaternion qb);
+ChApi Quaternion	Qscale (Quaternion q, double fact);
+ChApi Quaternion	Qnorm (Quaternion q);
+ChApi Quaternion	Q_from_AngAxis (double angle, Vector axis);
+ChApi Quaternion	Q_from_NasaAngles(Vector RxRyRz);
+ChApi Vector		Q_to_NasaAngles(Quaternion mq);
+ChApi Quaternion	Q_from_AngZ (double angleZ);
+ChApi Quaternion	Q_from_AngX (double angleX);
+ChApi Quaternion	Q_from_AngY (double angleY);
+ChApi void			Q_to_AngAxis (Quaternion* quat, double* a_angle, Vector* a_axis);
+ChApi Quaternion	Qdt_from_Wrel (Vector w, Quaternion q);
+ChApi Quaternion	Qdt_from_Wabs (Vector w, Quaternion q);
+ChApi Quaternion	Qdt_from_AngAxis (Quaternion quat, double angle_dt, Vector axis);
+ChApi Quaternion	Qdtdt_from_Aabs (Vector a, Quaternion q, Quaternion q_dt);
+ChApi Quaternion	Qdtdt_from_Arel (Vector a, Quaternion q, Quaternion q_dt);
+ChApi Quaternion	Qdtdt_from_AngAxis (double angle_dtdt, Vector axis, Quaternion q, Quaternion q_dt);
+ChApi Quaternion	Qconjugate (Quaternion q);
+ChApi Quaternion	Qcross (Quaternion qa, Quaternion qb);
+ChApi int			Qequal (Quaternion* qa, Quaternion* qb);
+ChApi int			Qnotnull (Quaternion* qa);
+ChApi Quaternion	ImmQ_complete (Vector* qimm);
+ChApi Quaternion	ImmQ_dt_complete (Quaternion* mq, Vector* qimm_dt);
+ChApi Quaternion	ImmQ_dtdt_complete (Quaternion* mq, Quaternion* mqdt, Vector* qimm_dtdt);
+
+ChApi Vector	    VaxisXfromQuat (Quaternion quat);
+
+
+//
+// ANGLE SET CONVERSION
+//
+
+#define ANGLESET_ANGLE_AXIS		0
+#define ANGLESET_EULERO			1
+#define ANGLESET_CARDANO		2
+#define ANGLESET_HPB			3
+#define ANGLESET_RXYZ			4
+#define ANGLESET_RODRIGUEZ		5
+#define ANGLESET_QUATERNION		6
+
+
+
+	// Angle conversion utilities
+
+ChApi Vector     Quat_to_Angle (int angset, Quaternion* mquat);
+ChApi Vector	 Angle_to_Angle(int setfrom, int setto, Vector* mangles);
+ChApi Quaternion Angle_to_Quat (int angset, Vector* mangles);
+ChApi Quaternion AngleDT_to_QuatDT (int angset, Vector* mangles, Quaternion* q);
+ChApi Quaternion AngleDTDT_to_QuatDTDT (int angset, Vector* mangles, Quaternion* q);
+
+
+
+//
+// CONSTANTS
+//
+
+
+static const ChQuaternion<double> QNULL (0.,0.,0.,0.);
+static const ChQuaternion<double> QUNIT (1.,0.,0.,0.);
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of ChQuaternion.h 
diff --git a/SRC/ChronoEngine/core/ChRealtimeStep.h b/SRC/ChronoEngine/core/ChRealtimeStep.h
new file mode 100644
index 0000000..1f6c7e1
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChRealtimeStep.h
@@ -0,0 +1,96 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHREALTIMESTEP_H
+#define CHREALTIMESTEP_H
+
+//////////////////////////////////////////////////
+//
+//   ChRealtimeStep.h
+//
+//   Class for a timer which measure the time spent
+//   in VR or game-like simulation loops, and suggests
+//   a dt integration step for the physical simulation
+//   for the next step.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "ChTimer.h"
+#include "ChMath.h"
+
+namespace chrono
+{
+
+
+/// Class for a timer which measure the time spent
+/// in VR or game-like simulation loops, and suggests
+/// a dt integration step for the physical simulation
+/// for the next step. Uses high-resolution timer.
+/// Note that the suggested integrations step tries
+/// to keep a true real-time pace in advancing the 
+/// simulation, that is the simulated time should 
+/// match the real time. The suggested step may 
+/// be non-constant because the overhead of the
+/// simulaiton loop may vary because of varying 
+/// overhead in visualization, collision or simulation.
+
+class ChRealtimeStepTimer : public ChTimer<double>
+{
+public:
+		/// Create the timer (outside the simulation loop, preferably
+		/// just before beginning the while{} loop)
+	ChRealtimeStepTimer() 
+			{
+				this->start();
+			}
+
+		/// Call this function INSIDE the simulation loop, just ONCE
+		/// per loop, to get the suggested time for the next integration
+		/// time step. If the the ChRealtimeStepTimer measured that
+	    /// previous simulation step required few real-time, it will 
+		/// suggest a corresponding small value for advancing the simulated 
+		/// time, and viceversa will give higher values (up to a maximum 
+		/// 'max_step' limit, however) if the simulation goes slow because
+		/// of high CPU overhead. If the clamping value of 'max_step' is
+		/// not reached, the real-time and simulated time should always match.
+		/// There is also an optional 'min_step' value, which avoids too small
+		/// integration steps.
+		
+	double SuggestSimulationStep(double max_step =0.02,		///< upper limit for step 
+								 double min_step =CH_NANOTOL) ///< lower limit for step
+			{
+				this->stop();
+				double mstep = (*this)();
+				this->start();
+
+				if (mstep<min_step) 
+					return min_step;
+				if (mstep>max_step) 
+					return max_step;
+				return mstep;
+			}
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChTimer.h
diff --git a/SRC/ChronoEngine/core/ChRunTimeType.h b/SRC/ChronoEngine/core/ChRunTimeType.h
new file mode 100644
index 0000000..0bcb9b6
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChRunTimeType.h
@@ -0,0 +1,178 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHRUNTIMETYPE_H
+#define CHRUNTIMETYPE_H
+
+
+//////////////////////////////////////////////////
+//  
+//   ChRunTimeType.h
+//
+//   A toolkit to simulate the C++ RTTI (run time type 
+//   information) features, without having to enable 
+//   RTTI in compilation - for faster performance.
+//   Each class can use these RTTI features, by inserting
+//   just a simple macro into its header.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+#include <string>
+#include "core/ChLog.h"
+
+namespace chrono
+{
+
+
+
+/// ChRunTimeType is a base class containing information
+/// about type of a generic C++ class.
+
+class ChRunTimeType
+{
+private:
+		//
+		// DATA
+		//
+	
+				/// The base class RTTI object
+    const ChRunTimeType* m_pkBaseRTTI;
+
+				/// The class name ID.
+    std::string m_kName;
+
+public:
+
+		// 
+		// CONSTRUCTORS
+		//
+			
+				/// Build the RTTI infos given the name ID of this class
+				/// and the base class, if any.
+    ChRunTimeType (const char* acName, const ChRunTimeType* pkBaseRTTI)
+    {
+        m_kName = /*"chrono::"+ */ std::string(acName);
+        m_pkBaseRTTI = pkBaseRTTI;
+    }
+
+		// 
+		// METHODS
+		//
+			
+	bool operator==(const ChRunTimeType& other) const 
+					{ 
+						return other.m_kName == m_kName; 
+					}
+
+				/// Gets the run-time type information of the parent class.
+    const ChRunTimeType* GetBaseRTTI () const
+					{
+						return m_pkBaseRTTI;
+					}
+
+
+				/// Get the name ID of the class, at run-time.
+    const char* GetName () const
+					{
+						return m_kName.c_str();
+					}
+
+				/// Tells if this type is exactly the same of another
+	bool IsExactlyClass (const ChRunTimeType* pkQueryRTTI) const 
+					{ 
+						return (pkQueryRTTI->m_kName == m_kName);
+						//return ( this == pkQueryRTTI );
+					} 
+		
+				/// Tells if this type is derived from some other type
+				/// Note: for the double inheritance, only the 1st parent tree is scanned.
+	bool IsDerivedFromClass (const ChRunTimeType* pkQueryRTTI)  const\
+					{  
+						const ChRunTimeType* pkRTTI = this; 
+						while ( pkRTTI ) 
+						{ 
+							if (pkRTTI->m_kName == pkQueryRTTI->m_kName)//if ( pkRTTI == pkQueryRTTI ) 
+								return true; 
+							pkRTTI = (ChRunTimeType*)pkRTTI->GetBaseRTTI(); 
+						} 
+						return false; 
+					} 
+
+};
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
+
+//
+//  MACROS
+//
+//  These macros can be inserted into the class definition of
+//  whatever C++ code, in order to enable the 'simulated RTTI'
+//  features of the ChRunTimeType() class.
+//
+
+
+#define CH_RTTI_ROOT(classname) \
+	\
+	public: \
+		virtual const chrono::ChRunTimeType* GetRTTI () const { static ChRunTimeType m_RTTI(#classname,NULL); return &m_RTTI; } \
+		static  const chrono::ChRunTimeType* GetClassRTTI()   { static ChRunTimeType m_RTTI(#classname,NULL); return &m_RTTI; }; 
+
+#define CH_RTTI(classname, parentclassname) \
+	\
+	public: \
+		virtual const chrono::ChRunTimeType* GetRTTI () const { static ChRunTimeType m_RTTI(#classname, parentclassname::GetClassRTTI()); return &m_RTTI; } \
+		static  const chrono::ChRunTimeType* GetClassRTTI()   { static ChRunTimeType m_RTTI(#classname, parentclassname::GetClassRTTI()); return &m_RTTI; }; 
+
+
+
+//////////////////////////////////////////////////////////////
+//
+// MISC FUNCTIONS for runtime type testing and casting
+//
+
+		/// Check if an object has some class type of another.
+#define ChIsExactlyClass(classname,pObj) \
+	( (pObj) ? (pObj)->GetRTTI()->IsExactlyClass(classname::GetClassRTTI()) : false )
+
+		/// Check if some object is derived from some class
+#define ChIsDerivedFromClass(classname,pObj) \
+	( (pObj) ? (pObj)->GetRTTI()->IsDerivedFromClass(classname::GetClassRTTI()) : false )
+
+		/// Perform a static cast from a type to another.
+#define ChStaticCast(classname,pObj) \
+	((classname*)(void*)(pObj))
+
+		/// Performs a dynamic cast.
+#define ChDynamicCast(classname,pObj) \
+	( (pObj) ? ( (pObj)->GetRTTI()->IsDerivedFromClass(classname::GetClassRTTI()) ? (classname*)pObj : NULL ) : NULL )
+
+
+
+
+
+
+};  // END_OF_NAMESPACE____
+
+#endif 
+
+
diff --git a/SRC/ChronoEngine/core/ChShared.h b/SRC/ChronoEngine/core/ChShared.h
new file mode 100644
index 0000000..93351ca
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChShared.h
@@ -0,0 +1,136 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHARED_H
+#define CHSHARED_H
+
+//////////////////////////////////////////////////
+//  
+//   ChShared.h
+//
+// Base class for shared objects, i.e. objects
+// which must be managed with smart pointers of
+// intrusive type (where the reference counting 
+// method is used to understand when to delete 
+// the object)
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+#include "ChRunTimeType.h"
+#include "ChSmartpointers.h"
+
+
+
+namespace chrono 
+{
+
+
+
+
+/// Base class for shared objects, i.e. objects
+/// which must be managed with smart pointers of
+/// intrusive type (where the reference counting 
+/// method is used to understand when to delete 
+/// the object).
+///
+/// Intrusive smart pointers must call AddRef()
+/// each time they reference such kind of object,
+/// and call RemoveRef() each time that they do
+/// not reference it anymore. When the reference
+/// count falls to 0, the object is automatically
+/// deleted. 
+
+
+
+class ChApi ChShared {
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI_ROOT(ChShared);
+
+private:
+			// 
+			// DATA
+			//
+
+	mutable unsigned int m_ref_counter;
+
+
+public:
+			//
+			//	CONSTRUCTORS
+			// 
+
+	ChShared()	
+			: m_ref_counter(1) 
+			{
+			}
+
+
+	virtual ~ChShared() 
+			{	
+			}
+
+			//
+			//	FUNCTIONS
+			// 
+
+				/// Add a reference to this object (tell that someone, in addition to
+				/// the creator, is using it. For example some pointer is pointing to
+				/// it... 
+				/// In fact intrusive smart pointers automatically call this when copied.
+	void AddRef() 
+			{
+				m_ref_counter++;
+			}
+	
+				/// Remove a reference to this object (tell that someone
+				/// who was using it, now is not interested in it anymore).
+				/// If the reference count drops to zero, the last time
+				/// RemoveRef() is called, the object is automatically
+				/// deleted. Also the creator must call this, instead of delete().
+				/// In fact intrusive smart pointers automatically call this.
+	void RemoveRef()
+			{
+				m_ref_counter--; 
+				
+				if (m_ref_counter==0)
+					delete this;
+			}
+
+				/// Tells how many items are sharing this object, i.e. the
+				/// reference count.
+	int ReferenceCount() {return m_ref_counter;}
+
+};
+
+ 
+
+
+
+// The following functions are needed as interfaces to the smart_ptr 
+// implementation when using the intrusive policy.
+
+//inline void intrusive_ptr_add_ref(ChShared * p){p->AddRef();}
+//inline void intrusive_ptr_release(ChShared * p){p->RemoveRef();}
+//inline bool intrusive_ptr_is_ref (ChShared * p){return (p->ReferenceCount() >= 1);}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/core/ChSmartpointers.h b/SRC/ChronoEngine/core/ChSmartpointers.h
new file mode 100644
index 0000000..4155a9b
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChSmartpointers.h
@@ -0,0 +1,368 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSMARTPOINTERS_H
+#define CHSMARTPOINTERS_H
+
+//////////////////////////////////////////////////
+//  
+//   ChSmartpointers.h
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdexcept>
+
+
+namespace chrono 
+{
+
+
+///  Smart pointer to be used with generic objects to be shared
+/// among multiple pointers, without the risk of deleting the 
+/// pointed instance too early, hence avoids dangling pointers.
+///  It does not need that instances are inherited from ChShared 
+/// because it uses an auxiliary 
+/// reference counter which is allocated on heap).
+///  It should be initialized in the following two main ways:
+///    ChSmartPtr<MyClass> foo_pointer(new MyClass);
+///       or
+///    ChSmartPtr<MyClass> foo_pointer(another_smart_pointer);
+///  Doing so, you will _never_ need to call 'delete', because the reference
+/// count mechanism will automatically delete the instance when no smart pointers 
+/// reference it.
+///  This kind of pointer does not perform copy of pointed data when copied.
+
+
+
+template <class T> 
+class ChSmartPtr
+{
+public:
+    typedef T element_type;
+
+			/// Constructor for initializing with dynamically allocated data, with new()
+			/// Mandatory way of using it:
+			///  ChSmartPtr<MyClass> pointerA(new MyClass);
+			/// Thank to automatic reference counting, you never have to call delete()!
+    explicit ChSmartPtr(T* p = 0) 
+        : itsCounter(0) 
+			{
+				if (p) itsCounter = new ChCounter (p);
+			}
+
+			/// Copy constructor for the case 
+			///  ChSmartPtr<MyClassA> pointerA(pointerB);
+    ChSmartPtr(const ChSmartPtr& r) throw()
+			{
+				acquire(r);
+			}
+
+			/// Copy constructor and converter for the case 
+			///  ChSmartPtr<MyClassA> pointerA(pointerB);
+			/// when pointerB comes from a class MyClassB which is inherited from MyClassA. 
+			/// If casting is not possible, the created shared pointer is invalidated (IsNull() = true).
+			/// Warnings! - upcast (MyClassA is parent of MyClassB) exactness and..
+			///			  - downcast (MyClassA is child of MyClassB) exactness  
+			///				is done in runtime with dynamic_cast; MyClassA & MyClassB must be polimorphic.
+			///           - MyClassA & MyClassB MUST have virtual destructors, if you want to use casting!
+	template <class T_other>
+	ChSmartPtr(const ChSmartPtr<T_other>& r) throw()
+			{
+				if (dynamic_cast<T*>(r.get_ptr()))
+					acquire (r);
+				else
+					itsCounter = 0;
+			}
+
+			/// Destructor decrements the reference count and automatically delete only 
+			/// when the last reference is destroyed
+	~ChSmartPtr()
+			{
+				release();
+			}
+
+			/// Bool type casting, true if the pointer is still bound to an object, or
+			/// false if unbound and invalidated (ex. after unsuccesfull casting). Example:
+			///    if(mysharedptr) {...}
+	operator bool() const { return itsCounter ? itsCounter->ptr!=0 : 0; }
+
+			/// Assignment form for an already-constructed smart-pointer.
+    ChSmartPtr& operator=(const ChSmartPtr& r)
+			{
+				if (this != &r) {
+					release();
+					acquire(r);
+				}
+				return *this;
+			}
+
+			/// Dereference the smart pointer to get the object, as in the form *p1
+    T& operator*()   throw()   {return *itsCounter->ptr;}
+	const T& operator*()  const throw()   {return *itsCounter->ptr;}
+
+			/// Used for member access to the contained object,
+			/// e.g. pointer->Print() calls T::Print()
+    T* operator->()  throw()   {return itsCounter->ptr;}
+	const T* operator->(void) const throw() {return itsCounter->ptr;}
+
+			/// Tells if this is shared by no one else.
+    bool IsUnique()   const throw()
+        {return (itsCounter ? itsCounter->count == 1 : true);}
+
+			/// Returns the raw pointer to pointed instance.
+			/// Note: If a correct programming style is used, you should 
+			/// never need to use this.
+	T* get_ptr() const throw() {return itsCounter ? itsCounter->ptr : 0;} 
+	T* get()	 const throw() {return itsCounter ? itsCounter->ptr : 0;}
+
+			/// Occasionally, the shared pointer can be invalidated (unbound from
+			/// object), for instance if you create it with null default
+			/// ChSharedPtr<MyClass> pointerA;   instead of typical   
+			/// ChSharedPtr<MyClass> pointerA(new MyClass);
+	bool IsNull() const throw() {return itsCounter ? itsCounter->ptr==0 : true;};
+
+			/// Unbind the shared pointer from referenced shared object,
+			/// and automatically delete in case of last reference. It should
+			/// be used sparingly, because this unbinding already happens automatically
+			/// when the shared pointer dies. Use this only to 'force' premature unbinding.
+    void SetNull() { this->release(); }
+
+			/// Tells if the referenced object is inherited from a specific class
+			/// and can be cast with copy constructor, for example 
+			///   if (ptrA.IsType<classB>() ) { ChSharedPtr<classB> ptrB (ptrA); }
+	template <class T_other>
+	bool IsType() { return itsCounter ? dynamic_cast<T_other*>(this->get_ptr()) : false ;}
+
+private:
+
+	class ChCounter 
+	{
+	public:
+        ChCounter(T* p = 0, unsigned int c = 1) : ptr(p), count(c) {}
+        T*           ptr;
+        unsigned int count;
+	}* itsCounter;
+
+			// increment the count
+	template <class T_other>
+    void acquire(const ChSmartPtr<T_other> &r) throw()
+			{ 
+				itsCounter = r.itsCounter;
+				if (itsCounter) ++itsCounter->count;
+			}
+
+			// decrement the count, delete if it is 0
+    void release()
+			{ 
+				if (itsCounter) {
+					if (--itsCounter->count == 0) 
+					{
+						delete (T*)(itsCounter->ptr);
+						delete itsCounter;
+					}
+					itsCounter = 0;
+				}
+			}
+};
+
+// Comparisons operators are required for using the shared pointer
+// class in an STL container
+
+template<typename T>
+bool operator==(const ChSmartPtr<T>& left, const ChSmartPtr<T>& right)
+{
+	if (left.get_ptr() == right.get_ptr()) return true;
+	return *left == *right;
+}
+template<typename T>
+bool operator<(const ChSmartPtr<T>& left, const ChSmartPtr<T>& right)
+{
+	if (left.get_ptr() == right.get_ptr()) return false;
+	return *left < *right;
+}
+
+
+
+
+/////////////////////////////////////////////////////////////////////
+
+
+
+///  Smart pointer to be used with generic objects to be shared
+/// among multiple pointers, without the risk of deleting the 
+/// pointed instance too early, hence avoids dangling pointers.
+///  When compared to the ChSharedPtr, this is a faster version
+/// but requires that you use it only for data which is instanced
+/// from the ChShared class.
+///  It should be initialized in the following two main ways:
+///    ChSmartPtr<MyClass> foo_pointer(new MyClass);
+///       or
+///    ChSmartPtr<MyClass> foo_pointer(another_smart_pointer);
+///  Doing so, you will _never_ need to call 'delete', because the reference
+/// count mechanism will automatically delete the instance when no smart pointers 
+/// reference it.
+///  This kind of pointer does not perform copy of pointed data when copied.
+
+template <class T> 
+class ChSharedPtr
+{
+
+public:
+    typedef T element_type;
+
+			/// Constructor for initializing with dynamically allocated data, with new()
+			/// Mandatory way of using it:
+			///   ChSharedPtr<MyClass> pointerA(new MyClass);
+			/// Thank to automatic reference counting, you never have to call delete()!
+    explicit ChSharedPtr(T* p = 0) 
+			{
+				ptr = p;
+			}
+
+			/// Copy constructor for the case 
+			///   ChSharedPtr<MyClassA> pointerA(pointerB);
+	ChSharedPtr(const ChSharedPtr& r) throw()
+			{
+				acquire(r);
+			}
+
+			/// Copy constructor and converter for the case 
+			///  ChSharedPtr<MyClassA> pointerA(pointerB);
+			/// when pointerB comes from a class MyClassB which is inherited from MyClassA or viceversa.
+			/// If casting is not possible, the created shared pointer is invalidated (IsNull() = true). 
+			/// Warnings! - upcast (MyClassA is parent of MyClassB) exactness and..
+			///			  - downcast (MyClassA is child of MyClassB) exactness  
+			///				is done in runtime with dynamic_cast; MyClassA & MyClassB must be polimorphic.
+			///           - MyClassA & MyClassB MUST have virtual destructors, if you want to use casting!
+	template <class T_other>
+	ChSharedPtr(const ChSharedPtr<T_other>& r) throw()
+			{
+				if (dynamic_cast<T*>(r.get_ptr()))
+					acquire (r);
+				else
+					ptr = 0;
+			}
+
+			/// Destructor decrements the reference count and automatically delete only 
+			/// when the last reference is destroyed
+	~ChSharedPtr()
+			{
+				release();
+			}
+
+
+			/// Bool type casting, true if the pointer is still bound to an object, or
+			/// false if unbound and invalidated (ex. after unsuccesfull casting). Example:
+			///    if(mysharedptr) {...}
+	operator bool() const { return ptr!=0; }
+
+			/// Assignment form for an already-constructed smart-pointer.
+    ChSharedPtr& operator=(const ChSharedPtr& r)
+			{
+				if (this != &r) 
+				{
+					release();
+					acquire(r);
+				}
+				return *this;
+			}
+
+			/// Dereference the smart pointer to get the object, as in the form *p1
+    T& operator*()  throw()   {return *ptr;}
+	const T& operator*()  const throw()   {return *ptr;}
+
+			/// Used for member access to the contained object,
+			/// e.g. pointer->Print() calls T::Print()
+    T* operator->() throw()   {return ptr;}
+	const T* operator->(void) const throw() {return ptr;}
+
+
+			/// Tells if this is shared by no one else.
+    bool IsUnique()   const throw()
+        {return (ptr ? ptr->ReferenceCount() == 1 : true);}
+
+			/// Returns the raw pointer to pointed instance.
+			/// Note: If a correct programming style is used, you should 
+			/// never need to use this.
+	T* get_ptr() const throw()  {return ptr;} 
+    T* get()     const throw()  {return ptr;}
+
+			/// Occasionally, the shared pointer can be invalidated (unbound from
+			/// object), for instance if you create it with null default
+			/// ChSharedPtr<MyClass> pointerA;   instead of typical   
+			/// ChSharedPtr<MyClass> pointerA(new MyClass);
+	bool IsNull() const throw() {return ptr == 0;};
+
+			/// Unbind the shared pointer from referenced shared object,
+			/// and automatically delete in case of last reference. It should
+			/// be used sparingly, because this unbinding already happens automatically
+			/// when the shared pointer dies. Use this only to 'force' premature unbinding.
+    void SetNull() { this->release(); ptr =0;}
+
+			/// Tells if the referenced object is inherited from a specific class
+			/// and can be cast with copy constructor, for example 
+			///   if (ptrA.IsType<classB>() ) { ChSharedPtr<classB> ptrB (ptrA); }
+	template <class T_other>
+	bool IsType() { if (dynamic_cast<T_other*>(ptr)) return true; else return false; }
+		//return (bool)dynamic_cast<T_other*>(ptr); }
+
+private:
+
+	T*          ptr;
+
+			// increment the count
+	template <class T_other>
+    void acquire(const ChSharedPtr<T_other>& r) throw()
+			{ 
+				ptr = (T*)(r.get_ptr());
+				if (ptr)
+				{
+					ptr->AddRef();
+				}
+			}
+
+			// decrement the count, delete if it is 0
+    void release()
+			{ 
+				// this should automatically delete the object when its ref.counter goes to 0.
+				if (ptr)
+				{
+					ptr->RemoveRef(); 
+				}
+			}
+};
+
+// Comparisons operators are required for using the shared pointer
+// class in an STL container
+
+template<typename T>
+bool operator==(const ChSharedPtr<T>& left, const ChSharedPtr<T>& right)
+{
+	if (left.get_ptr() == right.get_ptr()) return true;
+	return *left == *right;
+}
+template<typename T>
+bool operator<(const ChSharedPtr<T>& left, const ChSharedPtr<T>& right)
+{
+	if (left.get_ptr() == right.get_ptr()) return false;
+	return *left < *right;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/core/ChSpmatrix.cpp b/SRC/ChronoEngine/core/ChSpmatrix.cpp
new file mode 100644
index 0000000..09cf4e3
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChSpmatrix.cpp
@@ -0,0 +1,1819 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChSpmatrix.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChMath.h"
+#include "core/ChSpmatrix.h"
+
+#define PIVOT_ACCEPT_TRESHOLD 0.8
+#define ACCEPT_PIVOT	0.001
+#define MIN_PIVOT  0.00000001
+#define INFINITE_PIVOT  1.e+34
+
+namespace chrono
+{
+
+
+void ChSparseMatrix::Build(int row, int col, double fullness)
+{
+	rows = row;
+	columns = col;
+	address = NULL; // for we don't need this base-class data
+
+	mtot_size = 0;
+	mbuffer_added = 0;
+	mnextel = NULL;
+
+	// alloc buffer of elements
+	mbuffer_size = (int)(row*col*fullness);
+	if(row>5000) mbuffer_size=SPM_DEF_MAXELEMENTS;
+	if(col>5000) mbuffer_size=SPM_DEF_MAXELEMENTS;
+	if (mbuffer_size > SPM_DEF_MAXELEMENTS) mbuffer_size=SPM_DEF_MAXELEMENTS;
+	if (mbuffer_size < row*2) mbuffer_size = row*2;
+
+	ChMelement* mbuffer = (ChMelement*) calloc (mbuffer_size, sizeof(ChMelement));
+
+	mtot_size += mbuffer_size;
+	mnextel = mbuffer;
+	mbufferlist.AddHead(mbuffer);
+
+	// alloc pointers to first column
+	elarray = (ChMelement**) calloc (row, sizeof(ChMelement*));
+
+
+	for (int i=0; i<row; i++)
+	{
+		*(elarray+i) = mnextel;	// initialize vector of 1st col pointr pointers
+		(mnextel)->Initialize(0, NULL, NULL, i, 0);	// initialize 1st col.elements
+		mbuffer_added++;	// increment the counter of "used" elements.
+		mnextel++;
+	}
+}
+
+
+ChSparseMatrix::ChSparseMatrix (int row, int col, double fullness)
+{
+	ChSparseMatrix::Build(row, col, fullness);
+}
+
+ChSparseMatrix::ChSparseMatrix (int row, int col)
+{
+	ChSparseMatrix::Build(row, col, SPM_DEF_FULLNESS);
+}
+
+ChSparseMatrix::ChSparseMatrix ()
+{
+	ChSparseMatrix::Build(3, 3, 1);
+}
+
+ChSparseMatrix::~ChSparseMatrix ()
+{
+	mbuffer_size = 0;
+	mbuffer_added = 0;
+
+	free (elarray);		elarray = NULL;
+
+	for (ChNode<ChMelement>* mnode = mbufferlist.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		free(mnode->data);	// deallocate memory buffers
+	}
+
+	mbufferlist.RemoveAll(); //  may be avoided, since it will automatically remove at list deletion
+	mtot_size = 0;
+}
+
+// copy optimized also for source sparse matrix
+// (copy from matrices with structural zeros does not waste space)
+
+void ChSparseMatrix::CopyFromMatrix (ChMatrix<>* matra)
+{
+	double el;
+	ChMelement* mguess;
+
+	Reset(matra->GetRows(), matra->GetColumns());
+
+		// fill matrix
+	for (int r = 0; r< rows; r++)
+	{
+		mguess = *(elarray+r);
+		for (int c = 0; c< columns; c++)
+		{
+			el = matra->GetElement(r,c);
+			if (el != 0)
+				mguess = SetElement(r,c,el,mguess);
+		}
+	}
+}
+
+void ChSparseMatrix::CopyToMatrix	(ChMatrix<>* matra)
+{
+	matra->Reset(rows,columns);	// first, set all zeros in full matrix...
+
+	ChMelement* currel;
+	for (int i=0; i<rows; i++)
+	{
+		for(currel= *(elarray+i); currel!=NULL; currel=currel->next)
+		{
+			matra->SetElement(currel->row, currel->col, currel->val);
+		}
+	}
+}
+
+void ChSparseMatrix::CopyFromMatrix (ChSparseMatrix* matra)
+{
+	static ChMelement* eguess;
+	static ChMelement* srowel;
+	double val;
+
+	Reset(matra->rows, matra->columns);
+
+	for (int r = 0; r< rows; r++)
+	{
+		eguess = *(elarray+r);
+
+		for (srowel= *(matra->elarray +r); srowel != NULL; srowel=srowel->next)
+		{
+			val = srowel->val;
+			if (val) eguess= SetElement
+						   (r,
+							srowel->col,
+							val,
+							eguess);
+		}
+	}
+}
+
+void ChSparseMatrix::MoreBuffer(double inflate)
+{
+	mbuffer_size = (int)(inflate * (double)mbuffer_size);	// inflate buffer size
+
+	if(this->rows < 5000)
+		if ((mtot_size+mbuffer_size) > rows*columns)
+			mbuffer_size = rows*columns - mtot_size;
+
+	ChMelement* mbuffer;
+	mbuffer = (ChMelement*) calloc (mbuffer_size, sizeof(ChMelement));
+
+	mtot_size += mbuffer_size;
+	mnextel = mbuffer;
+	mbufferlist.AddTail(mbuffer);	// add another buffer!
+
+	mbuffer_added = 0;
+}
+
+
+void ChSparseMatrix::Reset()
+{
+	Reset(rows, columns);
+}
+
+void ChSparseMatrix::Reset(int row, int col)
+{
+	// realloc 1st column array, only if needed
+	if (row !=rows)
+	{
+		if (elarray) free (elarray);
+		elarray = (ChMelement**) calloc (row, sizeof(ChMelement*));
+	}
+
+	// realloc buffer (but only if needed!!! -see the if() conditions below.. - ) ,
+	// eventually compacting list into a _new_ single buffer
+
+	int mneed_buffer_size = 0;
+
+	if (mbufferlist.Count()>1)
+		mneed_buffer_size = mtot_size;	//   sum of all list of buffers, if multiple
+
+	if (mtot_size < row*2)
+		mneed_buffer_size = row*2;		// ..at least two columns
+
+	if(row < 5000)
+		if (mtot_size > (int)(row*col*1.2))
+			mneed_buffer_size = row*col;	// ..at maximum row*col
+
+	if (mneed_buffer_size)   // ok, a new allocation must be done...
+	{
+		// manage reallocation of buffer...
+		for (ChNode<ChMelement>* mnode = mbufferlist.GetHead(); mnode != NULL; mnode= mnode->next)
+		{
+			free(mnode->data);	// deallocate old memory buffers
+		}
+
+		mbufferlist.RemoveAll();
+		mtot_size = 0;
+
+		mbuffer_size = mneed_buffer_size;
+		ChMelement* mbuffer = (ChMelement*) calloc (mbuffer_size, sizeof(ChMelement));
+		mtot_size += mbuffer_size;
+		mnextel = mbuffer;
+		mbufferlist.AddHead(mbuffer);	// add buffer to empty list
+
+		mbuffer_added = 0;
+	}
+
+	rows = row;
+	columns = col;
+
+ 	mbuffer_added = 0;
+	mnextel = (mbufferlist.GetHead())->data;	// rewind the elem. pointer
+
+	// Just reinitialize 1st row elements
+	for (int i=0; i<rows; i++)
+	{
+		*(elarray+i) = mnextel;	// initialize vector of 1st col pointr pointers
+		(mnextel)->Initialize(0, NULL, NULL, i, 0);	// initialize 1st col.elements
+		mbuffer_added++;	// increment the counter of "used" elements.
+		mnextel++;
+	}
+}
+
+void ChSparseMatrix::ResetBlocks(int row, int col)
+{
+	if ((row == rows)&&(col == columns))	// size doesn't change
+	{
+		static ChMelement* currel;
+		for (int i=0; i<rows; i++)
+		{
+			for(currel= *(elarray+i); currel!=NULL; currel=currel->next)
+			{
+				currel->val= 0.0;
+			}
+		}
+	}
+	else	// size changes
+	{
+		Reset(row, col);
+	}
+}
+
+
+
+	// optimized SetElement,  returning the fetched Melement*
+ChMelement* ChSparseMatrix::SetElement (int row, int col, double val, register ChMelement* guess)
+{
+	#ifdef CH_DEBUG
+		assert (row >= 0);		// boundary checks
+		assert (col >= 0);
+		assert (row < rows );
+		assert (col < columns);
+		assert (guess->row == row)
+	#endif
+
+	ChMelement* enext;
+	ChMelement* eprev;
+	ChMelement* newguess;
+
+	while (guess->col != col)
+	{
+		// forward search
+		if (guess->col < col)
+		{
+			enext=guess->next;
+			if (enext)
+			{
+				if (enext->col <= col)
+					guess = enext;	// .. and repeat
+				else // if (enext->col >  col)
+				{
+					newguess = NewElement (val, enext, guess, row, col);
+					guess->next=newguess;
+					enext->prev=newguess;
+					return (newguess);
+				}
+			}
+			else
+			{
+				newguess = NewElement(val, NULL, guess, row, col);
+				guess->next = newguess;
+				return (newguess);
+			}
+		}
+
+		// backward search
+		if (guess->col > col)
+		{
+			eprev=guess->prev;
+			if (eprev)
+			{
+				if (eprev->col >= col)
+					guess = eprev;	// .. and repeat
+				else // if (eprev->col <  col)
+				{
+					newguess = NewElement (val, guess, eprev, row, col);
+					eprev->next=newguess;
+					guess->prev=newguess;
+					return (newguess);
+				}
+			}
+			else
+			{
+				newguess = NewElement(val, guess, NULL, row, col);
+				guess->prev = newguess;
+				return (newguess);
+			}
+		}
+
+	}	// end while loop
+
+	guess->val = val;
+	return (guess);
+}
+
+	// optimized GetElement,  returning the fetched Melement*
+ChMelement* ChSparseMatrix::GetElement (int row, int col, double* val, register ChMelement* guess)
+{
+	#ifdef CH_DEBUG
+		assert (row >= 0);		// boundary checks
+		assert (col >= 0);
+		assert (row < rows );
+		assert (col < columns);
+		assert (guess->row == row)
+	#endif
+
+	register ChMelement* enext;
+	ChMelement* eprev;
+
+	while (guess->col != col)
+	{
+		// forward search
+		if (guess->col < col)
+		{
+			enext=guess->next;
+			if (enext)
+			{
+				if (enext->col <= col)
+					guess = enext;	// .. and repeat
+				else //if (enext->col >  col)
+				{
+					*val = 0;
+					return (guess);
+				}
+			}
+			else
+			{
+				*val = 0;
+				return (guess);
+			}
+		}
+
+		// backward search
+		if (guess->col > col)
+		{
+			eprev=guess->prev;
+			if (eprev)
+			{
+				if (eprev->col >= col)
+					guess = eprev;	// .. and repeat
+				else // if (eprev->col <  col)
+				{
+					*val = 0;
+					return (guess);
+				}
+			}
+			else
+			{
+				*val = 0;
+				return (guess);
+			}
+		}
+
+	}	// end while loop
+
+	*val = guess->val;
+	return (guess);
+}
+
+void ChSparseMatrix::SetElement ( int row, int col, double elem)
+{
+	ChMelement* guess;
+	guess= *(elarray+row);
+	SetElement (row, col, elem, guess);
+}
+
+double ChSparseMatrix::GetElement ( int row, int col)
+{
+	double retv;
+	ChMelement* guess;
+	guess= *(elarray+row);
+	GetElement (row, col, &retv, guess);
+	return retv;
+}
+
+void ChSparseMatrix::SwapRows    (int a, int b)
+{
+	ChMelement* mtemp;
+	mtemp = *(elarray+a);
+	*(elarray+a) = *(elarray+b);	// rows lists easy switched
+	*(elarray+b) = mtemp;			// here...
+
+	for(mtemp= *(elarray+a); mtemp!=NULL; mtemp=mtemp->next)
+	{
+		mtemp->row = a;
+	}
+	for(mtemp= *(elarray+b); mtemp!=NULL; mtemp=mtemp->next)
+	{
+		mtemp->row = b;
+	}
+}
+
+void ChSparseMatrix::SwapColumns (int a, int b)
+{
+	ChMelement* guessA;
+	ChMelement* guessB;
+	double valA, valB;
+
+	for (int i=0; i<rows; i++)
+	{
+		guessA =GetElement (i, a, &valA, *(elarray+i));
+		guessB =GetElement (i, b, &valB, *(elarray+i));
+
+		SetElement (i,a, valB, guessA);
+		SetElement (i,b, valA, guessB);
+	}
+}
+
+void ChSparseMatrix::PasteMatrix (ChMatrix<>* matra, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	double val;
+
+	for (i=0;i < maxrows;i++)
+	{
+		eguess= *(elarray+i+insrow);
+
+		for (j=0;j < maxcol;j++)
+		{
+			val = (matra->GetElement (i,j));
+			if (val) eguess= SetElement (i+insrow,
+							j+inscol,
+							val,
+							eguess);
+		}
+	}
+}
+
+void ChSparseMatrix::PasteTranspMatrix (ChMatrix<>* matra, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	double val;
+
+	for (j=0;j < maxcol; j++)
+	{
+		eguess= *(elarray+j+insrow);
+
+		for (i=0;i < maxrows; i++)
+		{
+			val = (matra->GetElement (i,j));
+			if (val) eguess= SetElement (j+insrow,
+							i+inscol,
+							val,
+							eguess);
+		}
+	}
+}
+
+void ChSparseMatrix::PasteMatrixFloat (ChMatrix<float>* matra, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	double val;
+
+	for (i=0;i < maxrows;i++)
+	{
+		eguess= *(elarray+i+insrow);
+
+		for (j=0;j < maxcol;j++)
+		{
+			val = (matra->GetElement (i,j));
+			if (val) eguess= SetElement (i+insrow,
+							j+inscol,
+							val,
+							eguess);
+		}
+	}
+}
+
+void ChSparseMatrix::PasteTranspMatrixFloat (ChMatrix<float>* matra, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	double val;
+
+	for (j=0;j < maxcol; j++)
+	{
+		eguess= *(elarray+j+insrow);
+
+		for (i=0;i < maxrows; i++)
+		{
+			val = (matra->GetElement (i,j));
+			if (val) eguess= SetElement (j+insrow,
+							i+inscol,
+							val,
+							eguess);
+		}
+	}
+}
+
+
+void ChSparseMatrix::PasteSumMatrix (ChMatrix<>* matra, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	ChMelement* eguessread;
+	double val, aval, sum;
+
+	for (i=0;i < maxrows;i++)
+	{
+		eguess= *(elarray+i+insrow);
+		eguessread= eguess;
+
+		for (j=0;j < maxcol;j++)
+		{
+			val = (matra->GetElement (i,j));
+			if (val)
+			{
+				eguessread= GetElement (i+insrow, j+inscol, &aval, eguessread);
+				sum = val+aval;
+				eguess= SetElement (i+insrow,
+						j+inscol,
+						sum,
+						eguess);
+			}
+		}
+	}
+}
+
+void ChSparseMatrix::PasteSumTranspMatrix (ChMatrix<>* matra, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	ChMelement* eguessread;
+	double val, aval, sum;
+
+	for (j=0;j < maxcol; j++)
+	{
+		eguess= *(elarray+j+insrow);
+		eguessread = eguess;
+
+		for (i=0;i < maxrows; i++)
+		{
+			val = (matra->GetElement (i,j));
+			if (val)
+			{
+				eguessread= GetElement (j+insrow, i+inscol, &aval, eguessread);
+				sum = val + aval;
+				eguess= SetElement (j+insrow,
+						i+inscol,
+						sum,
+						eguess);
+			}
+		}
+	}
+}
+
+void ChSparseMatrix::PasteMatrix (ChSparseMatrix* matra, int insrow, int inscol)
+{
+	int i;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	ChMelement* srowel;
+	double val;
+
+	for (i=0;i < maxrows;i++)
+	{
+		eguess= *(elarray+i+insrow);
+
+		for (srowel= *(matra->elarray +i); srowel != NULL; srowel=srowel->next)
+		{
+			val = srowel->val;
+			if (val) eguess= SetElement
+						   (i+insrow,
+							srowel->col + inscol,
+							val,
+							eguess);
+		}
+	}
+}
+
+
+void ChSparseMatrix::PasteTranspMatrix (ChSparseMatrix* matra, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	double val;
+					// note: could be optimized for wide matra matrices..
+	for (j=0;j < maxcol; j++)
+	{
+		eguess= *(elarray+j+insrow);
+
+		for (i=0;i < maxrows; i++)
+		{
+			val = (matra->GetElement (i,j));
+			if (val) eguess= SetElement (j+insrow,
+							i+inscol,
+							val,
+							eguess);
+		}
+	}
+}
+
+void ChSparseMatrix::PasteClippedMatrix (ChMatrix<>* matra, int cliprow, int clipcol, int nrows, int ncolumns, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	double val;
+
+	for (i=0;i < nrows;i++)
+	{
+		eguess = *(elarray+i+insrow);
+
+		for (j=0;j < ncolumns;j++)
+		{
+			val = (matra->GetElement (i+cliprow,j+clipcol));
+			if (val) eguess = SetElement (i+insrow,
+						j+inscol,
+						val,
+						eguess);
+		}
+	}
+}
+
+void ChSparseMatrix::PasteSumClippedMatrix (ChMatrix<>* matra, int cliprow, int clipcol, int nrows, int ncolumns, int insrow, int inscol)
+{
+	int i, j;
+	int maxrows = matra->GetRows();
+	int maxcol = matra->GetColumns();
+	ChMelement* eguess;
+	ChMelement* eguessread;
+	double val, aval, sum;
+
+	for (i=0;i < nrows;i++)
+	{
+		eguess = *(elarray+i+insrow);
+		eguessread= eguess;
+
+		for (j=0;j < ncolumns;j++)
+		{
+			val = (matra->GetElement (i+cliprow,j+clipcol));
+			if (val)
+			{
+				eguessread= GetElement (i+insrow, j+inscol, &aval, eguessread);
+				sum = val+aval;
+				eguess = SetElement (i+insrow,
+						j+inscol,
+						sum,
+						eguess);
+			}
+		}
+	}
+}
+
+
+void ChSparseMatrix::MatrMultiply ( ChSparseMatrix* matra, ChSparseMatrix* matrb)
+{
+	//**** TO DO ****
+}
+
+void ChSparseMatrix::MatrMultiplyT ( ChSparseMatrix* matra, ChSparseMatrix* matrb)
+{
+	//**** TO DO ****
+}
+
+void ChSparseMatrix::MatrTMultiply ( ChSparseMatrix* matra, ChSparseMatrix* matrb)
+{
+	//**** TO DO ****
+}
+
+void ChSparseMatrix::MatrAdd	( ChSparseMatrix* matra, ChSparseMatrix* matrb)
+{
+	//**** TO DO ****
+}
+
+void ChSparseMatrix::MatrSub	( ChSparseMatrix* matra, ChSparseMatrix* matrb)
+{
+	//**** TO DO ****
+}
+
+void ChSparseMatrix::MatrInc	( ChSparseMatrix* matra)
+{
+	//**** TO DO ****
+}
+
+void ChSparseMatrix::MatrScale	( double factor)
+{
+	ChMelement* currel;
+
+	for (int i=0; i<rows; i++)
+	{
+		for(currel= *(elarray+i); currel!=NULL; currel=currel->next)
+		{
+			currel->val= currel->val*factor;
+		}
+	}
+}
+
+void ChSparseMatrix::MatrTranspose()
+{
+	//**** TO DO ****
+}
+
+void ChSparseMatrix::Neg()
+{
+	ChMelement* currel;
+
+	for (int i=0; i<rows; i++)
+	{
+		for(currel= *(elarray+i); currel!=NULL; currel=currel->next)
+		{
+			currel->val= -(currel->val);
+		}
+	}
+}
+
+
+// Linear algebra function
+
+int ChSparseMatrix::BestPivotRow (int current)
+{
+	double temp = 0;
+	int i;
+	int pivotrow = current;
+
+	for (i = current; i < rows; i++)
+	{
+		if (fabs(GetElement (i,current)) > temp)
+		{
+			temp = fabs(GetElement (i,current));
+			pivotrow = i;
+		}
+		if (temp >= PIVOT_ACCEPT_TRESHOLD) break;
+	}
+	return pivotrow;
+}
+
+int ChSparseMatrix::BestPivotDiag (int current)
+{
+	double temp = 0;
+	int i;
+	int pivotrow = current;
+
+	for (i = current; i < rows; i++)
+	{
+		if (fabs(GetElement (i,i)) > temp)
+		{
+			temp = fabs(GetElement (i,i));
+			pivotrow = i;
+		}
+		if (temp >= PIVOT_ACCEPT_TRESHOLD) break;
+	}
+	return pivotrow;
+}
+
+// Effect only on upper-left triangle!!!
+
+void ChSparseMatrix::DiagPivotSymmetric(int rowA, int rowB)
+{
+	int elcol, elrow;
+	double temp;
+	for (elrow=0; elrow<rowA; elrow++)
+	{
+		temp = GetElement(elrow, rowA);
+		SetElement(elrow,rowA, GetElement(elrow, rowB));
+		SetElement(elrow,rowB, temp);
+	}
+	for (elcol=rowB+1; elcol<columns; elcol++)
+	{
+		temp = GetElement(rowA, elcol);
+		SetElement(rowA, elcol, GetElement(rowB, elcol));
+		SetElement(rowB, elcol, temp);
+	}
+	for (elcol=rowA+1; elcol<rowB; elcol++)
+	{
+		temp = GetElement(rowA, elcol);
+		SetElement(rowA, elcol, GetElement(elcol,rowB));
+		SetElement(elcol, rowB, temp);
+	}
+	temp = GetElement(rowA, rowA);
+	SetElement (rowA,rowA, GetElement(rowB,rowB));
+	SetElement (rowB,rowB, temp);
+}
+
+// Solution of linear systems, optimized for sparse matrix.
+// The array of pivot indexes (pivarray) is optional
+
+int ChSparseMatrix::Solve_LinSys	(ChMatrix<>* B, ChMatrix<>* X, int* pivarray, double* det) // the object is the [A] matrix.
+{
+	ChMelement* rowel;
+	ChMelement* subrowel;
+	int i,k, pivrow, eqpivoted;
+	double r, bi, x, sum, pivot, pivlast, mval, subval, newval, leader;
+	int err = 0;
+
+	if (pivarray)	// initialize pivot index array
+	{
+		for (int ind = 0; ind < rows; ind++)
+		{ pivarray[ind] = ind;}
+	}
+
+	*det = 1;
+
+			// FORWARD reduction
+	for (k=1; k < rows; k++)
+	{
+		pivot = GetElement((k-1),(k-1));
+		if (fabs(pivot) < ACCEPT_PIVOT)
+		{
+			pivrow = BestPivotRow(k-1);
+			SwapRows ((k-1), pivrow );
+			B->SwapRows ((k-1), pivrow );
+			*det = - *det;
+			if (pivarray)
+			{
+				eqpivoted = pivarray[pivrow]; // swap eq.ids in pivot array
+				pivarray[pivrow] =pivarray[k-1];
+				pivarray[k-1] = eqpivoted;
+			}
+			pivot = GetElement((k-1),(k-1));
+		}
+		if (fabs(pivot) <= MIN_PIVOT)	// was unable to find better pivot: force solution to zero.and go ahead
+		{
+			//*det = *det;
+			pivot = INFINITE_PIVOT;
+			SetElement(k-1, k-1 , pivot);
+			if (!err)
+				err = (1+rows-k);	// report deficiency
+		}
+		else
+			*det = *det * pivot;
+
+		for (i=k; i < rows; i++)
+		{
+			leader = GetElement(i, (k-1));
+
+			if (leader)
+			{
+		  	 r = leader / pivot;
+
+			 bi= B->GetElement(i,0) - r * B->GetElement((k-1),0);
+			 B->SetElement(i,0, bi);
+
+			 subrowel = GetElarrayMel(i);
+			 rowel=GetElarrayMel(k-1);
+
+			 //while ((rowel->col<k) && (rowel->next))
+			//	 rowel = rowel->next;		// advance top row element till it has (col >= k)
+
+			 for (NULL; rowel!=NULL ; rowel=rowel->next)
+			 {
+				if (rowel->col >= k)		// skip
+				{
+					mval = rowel->val;
+					subrowel= GetElement(i, rowel->col, &subval, subrowel);
+					newval = subval - r * mval;
+					subrowel= SetElement(i, rowel->col, newval, subrowel);
+				}
+			 }
+			}
+		}
+	}
+
+	pivlast = GetElement((rows-1),(rows-1));
+	if (fabs(pivlast) <= MIN_PIVOT)
+	{
+		//*det = *det;
+		pivlast = INFINITE_PIVOT;
+		SetElement(rows-1, rows-1 , pivlast);
+		if (!err)
+			err = (1);	// report deficiency
+	}
+	else
+		*det = *det * pivlast;
+
+			// BACKWARD substitution
+	double xlast = B->GetElement(rows-1,0) / pivlast;
+	X->SetElement((rows-1),0,xlast);
+
+	for (k=(rows-2); k>= 0; k--)
+	{
+		sum = 0;
+
+		rowel=GetElarrayMel(k);
+
+		for (NULL; rowel!=NULL ; rowel=rowel->next) //for (j=(k+1); j< rows; j++)
+		{
+			if (rowel->col >= k+1)		// skip L part,
+			{
+				sum += rowel->val * (X->GetElement(rowel->col,0)); //sum += (GetElement(k,j))*(X->GetElement(j,0));
+			}
+		}
+
+		x = (B->GetElement(k,0) - sum) / GetElement(k,k);
+		X->SetElement(k,0, x);
+	}
+
+	return err;
+}
+
+void ChSparseMatrix::Solve_LinSys ( ChMatrix<>* B, ChMatrix<>* X)
+{
+	double det;
+	Solve_LinSys ( B, X, (int*)NULL, &det);
+}
+
+
+// LU decomposition and solution
+
+int	ChSparseMatrix::Decompose_LU(int* pivarray, double* det)
+{
+	ChMelement* rowel;
+	ChMelement* subrowel;
+	int i,k, pivrow, eqpivoted;
+	double r, pivot, mval, subval, newval, leader;
+	int err = 0;
+
+	if (pivarray)	// initialize pivot index array
+	{
+		for (int ind = 0; ind < rows; ind++)
+		{ pivarray[ind] = ind;}
+	}
+	else return TRUE; // error: no pivot array.
+
+	*det = 1;
+
+	for (k=1; k < rows; k++)
+	{
+		pivot = GetElement((k-1),(k-1));
+
+		if (fabs(pivot) < ACCEPT_PIVOT)
+		{
+			// pivoting is needed, so swap equations
+			pivrow = BestPivotRow(k-1);
+			SwapRows ((k-1), pivrow );
+			*det = - *det;
+
+			eqpivoted = pivarray[pivrow]; // swap eq.ids in pivot array
+			pivarray[pivrow] =pivarray[k-1];
+			pivarray[k-1] = eqpivoted;
+
+			pivot = GetElement((k-1),(k-1)); // fetch new pivot
+		}
+
+		if (fabs(pivot) <= MIN_PIVOT)	// was unable to find better pivot: force solution to zero.and go ahead
+		{
+			//*det = *det;
+			pivot = INFINITE_PIVOT;
+			SetElement(k-1, k-1 , pivot);
+			if (!err)
+				err = (1+rows-k);	// report deficiency
+		}
+		else
+			*det = *det * pivot;
+
+		for (i=k; i < rows; i++)
+		{
+			leader = GetElement(i, (k-1));
+
+			if (leader)
+			{
+			 r= leader / pivot;	// compute multiplier
+			 SetElement(i,(k-1),r);				// store the multiplier in L part!!!
+
+			 subrowel = GetElarrayMel(i); // initialize guessed sparse elements
+			 rowel=GetElarrayMel(k-1);	  // for speed optimization. They are in two rows.
+
+			 //while ((rowel->col<k) && (rowel->next))
+			 //	 rowel = rowel->next;		// advance top row element till it has (col >= k)
+
+			 for (NULL; rowel!= NULL; rowel=rowel->next)	//for (j=k; j < columns; j++)  where j = rowel->col
+			 {
+				 if (rowel->col >= k)	// skip
+				 {
+					mval = rowel->val;
+					subrowel= GetElement(i, rowel->col, &subval, subrowel);
+					newval = subval - r * mval;
+					subrowel= SetElement(i, rowel->col, newval, subrowel);	// set the U part
+				 }
+			 }
+			}
+		}
+	}
+
+	pivot = GetElement((rows-1),(rows-1));
+	if (fabs(pivot) <= MIN_PIVOT)
+	{
+		//*det = *det;
+		pivot = INFINITE_PIVOT;
+		SetElement(rows-1, rows-1 , pivot);
+		if (!err)
+			err = (1);	// report deficiency
+	}
+	else
+		*det = *det * pivot;
+
+	return err;
+}
+
+int	ChSparseMatrix::Solve_LU(ChMatrix<>* B, ChMatrix<>* X, int* pivarray)
+{
+	ChMelement* rowel;
+	int  k;
+	double sum, x;
+
+
+	// BACKWARD substitution - L
+	double xlast = B->GetElement(pivarray[0],0); //  ../ GetElement(0,0) => ../1;
+	X->SetElement(0,0,xlast);
+
+	for (k=1; k<rows; k++)
+	{
+		sum = 0;
+
+		rowel=GetElarrayMel(k);			// L(k,0)
+
+		for (NULL; (rowel!=NULL && rowel->col<k); rowel=rowel->next) // (j=0; j<k; j++)
+		{
+			sum += rowel->val * (X->GetElement(rowel->col,0)); //sum += (GetElement(k,j))*(X->GetElement(j,0));
+		}
+
+		x = (B->GetElement(pivarray[k],0) - sum); //  ../ GetElement(k,k) => ../1;
+		X->SetElement(k,0, x);
+	}
+
+	// BACKWARD substitution - U
+	xlast = X->GetElement((rows-1),0) / GetElement(rows-1, rows-1);
+	X->SetElement((rows-1),0,xlast);
+
+	for (k=(rows-2); k>= 0; k--)
+	{
+		sum = 0;
+
+		rowel=GetElarrayMel(k);
+
+		for (NULL; rowel!=NULL ; rowel=rowel->next) //for (j=(k+1); j< rows; j++)
+		{
+			if (rowel->col >= k+1)		// skip L part,   U row starts from (k,k+1) or further
+			{
+				sum += rowel->val * (X->GetElement(rowel->col,0)); //sum += (GetElement(k,j))*(X->GetElement(j,0));
+			}
+		}
+
+		x = (X->GetElement(k,0) - sum) / GetElement(k,k);
+		X->SetElement(k,0, x);
+	}
+
+	return TRUE;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////
+
+//
+// LDL decomposition (only upper right part of [A] is used!)
+//
+
+int	ChSparseMatrix::Decompose_LDL(int* pivarray, double* det, int from_eq)
+{
+	ChMelement* rowel;
+	ChMelement* subrowel;
+	int i,k, pivrow, eqpivoted;
+	double r, leader, pivot, mval, subval, newval;
+	int err = 0;
+
+	if (pivarray)	// initialize pivot index array
+	{
+		for (int ind = 0; ind < rows; ind++)
+		{ pivarray[ind] = ind;}
+	}
+	else return TRUE; // error: no pivot array.
+
+	*det = 1;
+
+	for (k=1; k < rows; k++)
+	{
+		pivot = GetElement((k-1),(k-1));
+
+		if (fabs(pivot) < ACCEPT_PIVOT)
+		{
+			//static cntpiv=0;
+			//R3Error("pivot %d   %g", cntpiv, fabs(pivot));
+
+			// pivoting is needed, so ...
+			pivrow = BestPivotDiag(k-1);
+			DiagPivotSymmetric(k-1,pivrow);	// swap both column and row (only upper right!)
+			*det = - *det;					// invert determ.sign
+
+			eqpivoted = pivarray[pivrow];	// swap diagonal pivot indexes
+			pivarray[pivrow] =pivarray[k-1];
+			pivarray[k-1] = eqpivoted;
+
+			pivot = GetElement((k-1),(k-1));
+		}
+
+		if (fabs(pivot) <= MIN_PIVOT)	// was unable to find better pivot: force solution to zero.and go ahead
+		{
+			pivot = INFINITE_PIVOT;
+			SetElement(k-1, k-1 , pivot);
+			if (!err)
+				err = (1+rows-k);	// report deficiency
+		}
+		else
+			*det = *det * pivot;
+
+		for (i=k; i < rows; i++)
+		{
+			leader = GetElement((k-1), i);
+
+			if (leader)
+			{
+			  r= (leader / pivot);	// compute multiplier (mirror look A)
+
+			  subrowel = GetElarrayMel(i); // initialize guessed sparse elements
+			  rowel=GetElarrayMel(k-1);	   // for speed optimization. They are in two rows.
+
+			  // advance top row element till it has (col >= k)
+
+			  for (NULL; rowel!= NULL; rowel=rowel->next)	// for (j=i; j < columns; j++)	// only upper right part
+			  {
+				if (rowel->col >= i)	// only upper right part is filled!
+				{
+					mval = rowel->val;
+					subrowel= GetElement(i, rowel->col, &subval, subrowel);
+					newval = subval - r * mval;
+					subrowel= SetElement(i, rowel->col, newval, subrowel);
+				}
+			  }
+
+			  SetElement((k-1),i, r); // now can store the multiplier in L part (mirror look! is up)
+			}
+
+		}
+	}
+
+	pivot = GetElement((rows-1),(rows-1));
+	if (fabs(pivot) <= MIN_PIVOT)
+	{
+		pivot = INFINITE_PIVOT;
+		SetElement(rows-1, rows-1 , pivot);
+		if (!err)
+			err = (1);	// report deficiency
+	}
+	else
+		*det = *det * pivot;
+
+	return err;
+}
+
+//
+// Back substitution after LDL decomposition, to solve for X
+//
+
+int	ChSparseMatrix::Solve_LDL(ChMatrix<>* B, ChMatrix<>* X, int* pivarray)
+{
+	ChMelement* rowel;
+	int j,k;
+	double sum, x;
+
+		// BACKWARD substitution - L
+	double xlast = B->GetElement(pivarray[0],0); //  ../ GetElement(0,0) => ../1;
+	X->SetElement(pivarray[0],0,xlast);
+
+	for (k=1; k<rows; k++)
+	{
+		sum = 0;
+		for (j=0; j<k; j++)
+		{
+			sum += (GetElement(j,k))*(X->GetElement(pivarray[j],0));
+		}
+		x = (B->GetElement(pivarray[k],0) - sum); //  ../ GetElement(k,k) => ../1;
+		X->SetElement(pivarray[k],0, x);
+	}
+		// BACKWARD substitution - D
+	for (k=0; k<rows; k++)
+	{
+		x = X->GetElement(pivarray[k],0) / GetElement(k,k);
+		X->SetElement(pivarray[k],0,x);
+	}
+		// BACKWARD substitution - L'
+	for (k=(rows-2); k>= 0; k--)
+	{
+		sum = 0;
+
+		rowel=GetElarrayMel(k);
+
+		for (NULL; rowel!=NULL ; rowel=rowel->next) //for (j=(k+1); j< rows; j++)
+		{
+			if (rowel->col >= k+1)		// skip L part,
+			{
+				sum += rowel->val * (X->GetElement(pivarray[rowel->col],0)); //sum += (GetElement(k,j))*(X->GetElement(j,0));
+			}
+		}
+
+		x = (X->GetElement(pivarray[k],0) - sum);  // .../ GetElement(k,k); -> ../1 ;
+		X->SetElement(pivarray[k],0, x);
+	}
+
+	return TRUE;
+}
+
+
+//
+// Decompose and solve at once
+//
+
+int	ChSparseMatrix::DecomposeAndSolve_LDL(ChMatrix<>* B, ChMatrix<>* X, double& mdet, int from_eq)
+{
+	// decompose and solve at once
+
+	assert(B->GetRows() == this->rows);
+	assert(X->GetRows() == this->rows);
+	assert(this->rows == this->columns);
+
+	int* pivarray = (int*) calloc ((this->rows), sizeof(int));
+
+	int nredundancy = this->Decompose_LDL(pivarray, &mdet);
+	this->Solve_LDL(B, X, pivarray);
+
+	free (pivarray);
+
+	return nredundancy;
+}
+
+
+
+
+//
+// LCP solver
+//
+
+
+#define LCP_EPS 10e-6
+
+//
+// Decompose and solve at once (optimized for LCP iteration)
+//
+
+int	ChSparseMatrix::DecomposeAndSolve_LDL_forLCP(ChMatrix<>* B, ChMatrix<>* X, double& mdet,
+											   int i_D, int i_C, int n_unilaterals,
+											   ChUnilateralData constr_data[], int from_eq)
+{
+	ChSparseMatrix tempM;
+	tempM.CopyFromMatrix(this);
+
+	// deactivate the non-clamped or not yet considered unilateral constraints
+	for (int  nd = 0; nd < n_unilaterals; nd++)
+	{
+		if (constr_data[nd].status != CONSTR_UNILATERAL_ON)
+			tempM.SetElement(i_D+nd, i_D+nd, INFINITE_PIVOT);
+	}
+
+	tempM.DecomposeAndSolve_LDL(B,X,mdet, from_eq);
+
+	return TRUE;
+}
+
+int	ChSparseMatrix::DecomposeAndSolve_LDL_forLCP
+											  (ChSparseMatrix* Aorig,
+											   ChSparseMatrix* Afact,
+												ChMatrix<>* B, ChMatrix<>* X, double& mdet,
+											   int i_D, int i_C, int n_unilaterals,
+											   ChUnilateralData constr_data[],
+											   int from_eq,
+											   int backup_from)
+{
+	assert(B->GetRows() == Afact->rows);
+	assert(X->GetRows() == Afact->rows);
+	assert(Afact->rows == Afact->columns);
+	assert(Aorig->GetRows() == Afact->rows);
+	assert(Aorig->GetColumns() == Afact->columns);
+	assert((from_eq==0) ||(from_eq >= backup_from));
+	assert(from_eq < Afact->rows);
+	assert(backup_from < Afact->rows);
+
+	// The factorization:
+
+	double adet; double* det = &adet;
+	ChMelement* rowel;
+	ChMelement* subrowel;
+	int i,k;
+	//int pivrow, eqpivoted;
+	double r, leader, pivot, mval, subval, newval;
+	int err = 0;
+
+	int* pivarray = (int*) calloc ((Afact->rows), sizeof(int));
+
+	for (int indp = 0; indp < Afact->rows; indp++)
+		{ pivarray[indp] = indp;}
+
+	int* modarray = (int*) calloc ((Afact->rows), sizeof(int));
+
+	for (int indm = 0; indm < Afact->rows; indm++)
+		{ modarray[indm] = false;}
+
+
+	*det = 1;
+
+	if (from_eq==0)
+	{
+		Afact->CopyFromMatrix(Aorig);
+	}
+	else
+	{
+		// should be optimized?
+		Afact->CopyFromMatrix(Aorig);
+	}
+
+
+	int begin_row = 0;
+
+	if (from_eq > 0)
+		begin_row = backup_from;
+
+	for (k=begin_row+1; k < Afact->rows; k++)
+	{
+		// Perform optimized backup of partially factored matrix into another sparse matrix
+		if (from_eq == 0)
+		if ((k-1) == backup_from)
+		{
+			Aorig->CopyFromMatrix(Afact);
+		}
+
+		pivot = Afact->GetElement((k-1),(k-1));
+/*
+		if (fabs(pivot) < ACCEPT_PIVOT)
+		{
+			//static cntpiv=0;
+			//R3Error("pivot %d   %g", cntpiv, fabs(pivot));
+
+			// pivoting is needed, so ...
+			pivrow = Afact->BestPivotDiag(k-1);
+			Afact->DiagPivotSymmetric(k-1,pivrow);	// swap both column and row (only upper right!)
+			*det = - *det;					// invert determ.sign
+
+			eqpivoted = pivarray[pivrow];	// swap diagonal pivot indexes
+			pivarray[pivrow] =pivarray[k-1];
+			pivarray[k-1] = eqpivoted;
+
+			pivot = Afact->GetElement((k-1),(k-1));
+		}
+*/
+		int row_num_D = (k-1) - i_D;
+
+		bool infinite_pivot = false;
+										// force unactive bases to no effect, with infinite pivot
+		if (row_num_D >= 0)
+		if (constr_data[row_num_D].status != CONSTR_UNILATERAL_ON)
+		{
+			infinite_pivot = true;
+			pivot = INFINITE_PIVOT;
+			Afact->SetElement(k-1, k-1 , pivot);
+		}
+
+		if (fabs(pivot) <= MIN_PIVOT)	// was unable to find better pivot: force solution to zero.and go ahead
+		{
+			infinite_pivot = true;
+			pivot = INFINITE_PIVOT;
+			Afact->SetElement(k-1, k-1 , pivot);
+			if (!err)
+				err = (1+ Afact->rows - k);	// report deficiency
+		}
+		else
+			*det = *det * pivot;
+
+		for (i=k; i < Afact->rows; i++)
+		{
+			leader = Afact->GetElement((k-1), i);
+
+			if (leader!=0)
+			{
+			  r= (leader / pivot);	// compute multiplier (mirror look A)
+
+			  if (!infinite_pivot)
+			  {
+				  subrowel = Afact->GetElarrayMel(i); // initialize guessed sparse elements
+				  rowel= Afact->GetElarrayMel(k-1);	   // for speed optimization. They are in two rows.
+
+				  // advance top row element till it has (col >= k)
+
+				  for (NULL; rowel!= NULL; rowel=rowel->next)	// for (j=i; j < columns; j++)	// only upper right part
+				  {
+					if (rowel->col >= i)	// only upper right part is filled!
+					{
+						mval = rowel->val;
+						subrowel= Afact->GetElement(i, rowel->col, &subval, subrowel);
+						newval = subval - r * mval;
+						subrowel= Afact->SetElement(i, rowel->col, newval, subrowel);
+					}
+				  }
+			  }
+
+			  Afact->SetElement((k-1),i, r); // now can store the multiplier in L part (mirror look! is up)
+			}
+
+		}
+	}
+
+	pivot = Afact->GetElement((Afact->rows-1),(Afact->rows-1));
+	if (fabs(pivot) <= MIN_PIVOT)
+	{
+		pivot = INFINITE_PIVOT;
+		Afact->SetElement(Afact->rows-1, Afact->rows-1 , pivot);
+		if (!err)
+			err = (1);	// report deficiency
+	}
+	else
+		*det = *det * pivot;
+
+	//
+	// Back-Solve using the factored matrix
+
+	Afact->Solve_LDL(B, X, pivarray);
+
+
+	free (pivarray);
+	free (modarray);
+
+	return TRUE;
+}
+
+
+
+
+static void LCP_compute_DL_residuals(ChSparseMatrix* M, ChMatrix<>* B, ChMatrix<>* X, ChMatrix<>* D, ChMatrix<>* L,
+								   int i_D, int i_C, int n_unilaterals,
+								   ChUnilateralData constr_data[])
+{
+	// Recover the residuals of unilateral constraints, given body accelerations and jacobians
+	// (for example, contact normal accelerations)
+
+	D->FillElem(0);
+	for (int res =0 ; res < n_unilaterals; res++)
+	{
+		// the n-th D residual can be computed from jacobian [Dx] and B vector: Dn=[Dx]*x-Bn
+		double sum = - B->GetElement(i_D+res,0);
+		for (int mcol = 0; mcol<i_C; mcol++)
+				sum += X->GetElement(mcol,0)*M->GetElement(i_D+res,mcol);
+
+		// force to precise zero if constraint is clamped enough
+		// (to avoid cycling because of numerical errors)
+		//if (constr_data[res].status==CONSTR_UNILATERAL_ON)
+		//	if (fabs(sum)<10e-6)
+		//		sum = 0;
+
+		D->SetElement(res,0, sum );
+	}
+
+	// Recover the multipliers (ex. the reactions of constraints in acceleration problem)
+	// for later easier reference.
+
+	L->PasteClippedMatrix(X, i_D,0,  n_unilaterals,1,  0,0);
+}
+
+static bool LCP_compute_maxstep(ChMatrix<>* D,      ChMatrix<>* L,
+								ChMatrix<>* Dguess, ChMatrix<>* Lguess,
+								const int idirection,
+								ChUnilateralData constr_data[],
+								int n_unilaterals,
+								int& ichanged, double& step)
+{
+	step	 = 1.0;
+	ichanged = -1;
+
+	double try_step;
+
+
+	// Check limit caused by some constraint which must be turned OFF
+	// because clamped constraints must always keep multiplier L<0
+
+    int id;
+
+	for (id = 0; id < n_unilaterals; id++)
+	{
+		if (constr_data[id].status==CONSTR_UNILATERAL_ON)
+		{
+			if (Lguess->GetElement(id,0) > +LCP_EPS)
+			{
+				try_step = - L->GetElement(id,0)/
+							   (Lguess->GetElement(id,0) - L->GetElement(id,0));
+				if (try_step < step)
+				{
+					step = try_step;
+					ichanged = id;
+				}
+			}
+		}
+	}
+
+	// Check limit caused by some constraint which must be turned ON
+	// because not-clamped constraints must always keep D>0
+
+	for (id = 0; id < n_unilaterals; id++)
+	{
+		if (constr_data[id].status==CONSTR_UNILATERAL_OFF)
+		{
+			if (Dguess->GetElement(id,0) < -LCP_EPS)
+			{
+				try_step = - D->GetElement(id,0)/
+							   (Dguess->GetElement(id,0) - D->GetElement(id,0));
+				if (try_step < step)
+				{
+					step = try_step;
+					ichanged = id;
+				}
+			}
+		}
+	}
+
+	if ((step <= 0) || (step>1.0000001))
+	{
+		//R3Error("  Warning, overconstrained LCP,  Step %g is not in 0..1. Changed constr.%d on %d",
+		//							step, ichanged, n_unilaterals);	//***DEBUG***
+		step = 0;
+		ichanged = idirection;
+		constr_data[ichanged].status = CONSTR_UNILATERAL_REDUNDANT;
+	}
+
+	if (ichanged == -1)
+		return false;		// no limiting is required in this direction, keep step = 1;
+
+	return true;
+}
+
+#define UNOPTIMIZED_LCP 1
+
+int ChSparseMatrix::SolveLCP(ChMatrix<>* B, ChMatrix<>* X,
+						   int n_bilaterals, int n_unilaterals,
+						   int maxiters,
+						   bool keep_unilateral_status,
+						   ChUnilateralData constr_data[])
+{
+	// Check some low-level error in passing function parameters
+
+	assert (B->GetRows() == this->rows);
+	assert (X->GetRows() == this->rows);
+	assert (this->rows == this->columns);
+
+	int i_C = rows-n_unilaterals-n_bilaterals;
+	int i_D = rows-n_unilaterals;
+
+	// In case no unilateral constraints are provided, this can be readily solved as
+	// a simple linear problem:
+
+	if (n_unilaterals==0)
+	{
+		double mdet;
+
+		DecomposeAndSolve_LDL(B, X, mdet);
+
+		return TRUE;
+	}
+
+	//-------------------------------------------------------------
+	// Dantzig revisited algorithm
+	//
+
+
+	// Initialize temporary structures
+
+	int own_constr_data = FALSE;
+	int success = FALSE;
+
+
+
+	int* pivarray = (int*) calloc ((this->rows), sizeof(int));
+
+	if (constr_data == NULL)
+	{
+		constr_data= (ChUnilateralData*) calloc ((n_unilaterals), sizeof(ChUnilateralData));
+		own_constr_data = TRUE;
+		for (int ind = 0; ind < n_unilaterals; ind++)
+		{
+			constr_data[ind].Reset();
+		}
+	}
+
+	ChMatrixDynamic<> D(n_unilaterals,1); // for storing residuals
+	ChMatrixDynamic<> L(n_unilaterals,1); // for storing multipliers
+	ChMatrixDynamic<> Dguess(n_unilaterals,1); // for storing guess residuals
+	ChMatrixDynamic<> Lguess(n_unilaterals,1); // for storing guess multipliers
+	ChMatrixDynamic<> Xguess(X->GetRows(),1); // for storing guess solution
+
+	ChSparseMatrix Mbackup(this->rows, this->columns);	// for storing partial decomposition
+
+
+	// initialize status of unilateral constraints (all constraints are unclamped).
+	if (!keep_unilateral_status)
+		for (int ind = 0; ind < n_unilaterals; ind++)
+		{
+			constr_data[ind].status = CONSTR_UNILATERAL_OFF;//CONSTR_UNILATERAL_NONE;
+		}
+
+	// - compute unknowns (q, fd, etc.) using the LDL sparse solver ++++++
+	//   for no unilateral constraint clamped...
+	double mdet;
+
+#ifdef UNOPTIMIZED_LCP
+	DecomposeAndSolve_LDL_forLCP( B, X,  mdet, i_D, i_C,
+									n_unilaterals, constr_data);
+#else
+	ChSparseMatrix::DecomposeAndSolve_LDL_forLCP(this, &Mbackup, B, X,  mdet, i_D, i_C,
+										n_unilaterals, constr_data, 0, i_D) ;
+#endif
+
+	//
+	// The outer main loop
+	//
+
+	int tot_iters  = 0;
+
+
+	if (!keep_unilateral_status)
+	while (true)
+	{
+		// - compute D and L residuals
+
+		LCP_compute_DL_residuals(this, B, X, &D,&L, i_D, i_C,
+											n_unilaterals, constr_data);
+
+
+		// - find a residual to drive-to-zero in the main outer loop, if any
+
+		int id;
+		bool must_drive  = false;
+
+		for (id = 0; id < n_unilaterals; id++)
+		{
+			if (   (constr_data[id].status != CONSTR_UNILATERAL_ON)
+				 &&(constr_data[id].status != CONSTR_UNILATERAL_REDUNDANT))
+			if (D.GetElement(id,0) < -LCP_EPS)
+			{
+				must_drive = true;
+				break; // will drive the residual n. 'id'.
+			}
+		}
+
+		if (must_drive == false)
+		{
+			success = TRUE;
+			break;			// -> exit: all D residuals are at least >=0;
+		}
+
+		// - Now perform the inner loop, to drive-to-zero the 'id' residual:
+
+		constr_data[id].status = CONSTR_UNILATERAL_ON;
+
+		while (true)
+		{
+			// Guess a destination, hoping that solution is reached without
+			// clamping or unclamping any constraint (if not, will repeat from rewound position..)
+#ifdef UNOPTIMIZED_LCP
+			DecomposeAndSolve_LDL_forLCP( B, &Xguess,  mdet, i_D, i_C,
+													n_unilaterals, constr_data);
+#else
+			ChSparseMatrix::DecomposeAndSolve_LDL_forLCP(this, &Mbackup,
+															B, &Xguess,
+															mdet, i_D, i_C,
+															n_unilaterals, constr_data,
+															i_D, i_D) ;
+#endif
+
+			// D and L variables for the guess..
+
+			LCP_compute_DL_residuals(this, B, &Xguess, &Dguess, &Lguess, i_D, i_C,
+												n_unilaterals, constr_data);
+
+			// Find the 'most limiting' inequality from path to guessed solution:
+
+			double step;
+			int ichanged;
+			if (!LCP_compute_maxstep( &D,  &L, &Dguess,  &Lguess,
+								id, constr_data, n_unilaterals,
+								ichanged, step))
+			{
+				// move the D and L and X values to end of step (for lucky step=1)
+				X->CopyFromMatrix(Xguess);
+				D.CopyFromMatrix(Dguess);
+				L.CopyFromMatrix(Lguess);
+				break;
+			}
+
+			// move the D and L and X values to inbetween point of step (for step 0..1)
+			X->LinInterpolate(*X, Xguess,step);
+			D.LinInterpolate( D,  Dguess,step);
+			L.LinInterpolate( L,  Lguess,step);
+
+			if (constr_data[ichanged].status==CONSTR_UNILATERAL_ON)
+			{
+				constr_data[ichanged].status=CONSTR_UNILATERAL_OFF;
+			}
+			else if(constr_data[ichanged].status==CONSTR_UNILATERAL_OFF)
+			{
+				constr_data[ichanged].status=CONSTR_UNILATERAL_ON;
+			}
+
+			tot_iters++;
+			if (maxiters)
+			 if (tot_iters > maxiters)
+				break;			// -> exit without success, too many iterations;
+
+		}
+
+
+		tot_iters++;
+		if (maxiters)
+		 if (tot_iters > maxiters)
+			break;			// -> exit without success, too many iterations;
+	}
+
+
+	// compute final feasability
+
+	LCP_compute_DL_residuals(this, B, X, &Dguess, &Lguess, i_D, i_C,
+											n_unilaterals, constr_data);
+	double minD = Dguess.Min(); // test
+	double maxD = Dguess.Max(); // test
+	double minL = Lguess.Min(); // test
+	double maxL = Lguess.Max(); // test
+	double feas_error = 0.;
+	for (int mc = 0; mc <Dguess.GetRows(); mc++)
+	{
+		if (fabs(Dguess.GetElement(mc,0)*Lguess.GetElement(mc,0)) > feas_error)
+			feas_error = fabs(Dguess.GetElement(mc,0)*Lguess.GetElement(mc,0));
+	}
+
+	/*
+	if (!success)
+		R3Error("Too many iters, feas_error %g, Dn=%d, iter=%d, Dmin=%g, Dmax=%g, Lmin=%g, Lmax=%g",
+						feas_error, n_unilaterals, tot_iters, minD, maxD, minL, maxL);
+	*/
+
+	free (pivarray);
+
+	if (own_constr_data)
+		free (constr_data);
+
+	return success;
+}
+
+
+
+void ChSparseMatrix::StreamOUTsparseMatlabFormat(ChStreamOutAscii& mstream)
+{
+	for(int ii=0; ii<this->GetRows(); ii++)
+	{
+		for(int jj=0; jj<this->GetColumns(); jj++)
+		{
+			double elVal = this->GetElement(ii,jj);
+			if (elVal || (ii+1==this->GetRows() && jj+1==this->GetColumns()))
+			{
+				mstream << ii+1 << " " << jj+1 << " " << elVal << "\n";
+			}
+		}
+	}
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+// END
diff --git a/SRC/ChronoEngine/core/ChSpmatrix.h b/SRC/ChronoEngine/core/ChSpmatrix.h
new file mode 100644
index 0000000..aa946b0
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChSpmatrix.h
@@ -0,0 +1,300 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSPMATRIX_H
+#define CHSPMATRIX_H
+
+//////////////////////////////////////////////////
+//  
+//   ChSpmatrix.h
+//
+//   Math functions for :
+//      - SPARSE MATRICES
+//      - SPARSE DIAGONAL MATRICES
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChMatrix.h"
+#include "core/ChLists.h"
+#include "core/ChApiCE.h"
+
+namespace chrono
+{
+
+ // default predicted density, for allocation, 0<..<1 , default 1/10 th
+#define SPM_DEF_FULLNESS 0.1
+ // default limit on initial number of extradiagonal elements, for allocation, default 10000
+#define SPM_DEF_MAXELEMENTS 10000
+
+///////////////////////////////////////////
+// 
+/// Generic element of a sparse matrix ChSparseMatrix
+///
+
+class ChApi ChMelement 
+{
+public:
+	double val;
+	ChMelement* next;
+	ChMelement* prev;
+	int row;
+	int col;
+
+	ChMelement(double val, ChMelement* mnext, ChMelement* mprev, int row, int col);
+	void Initialize(double val, ChMelement* mnext, ChMelement* mprev, int row, int col);
+};
+
+inline ChMelement::ChMelement (double mval, ChMelement* mnext, ChMelement* mprev, int mrow, int mcol)
+{
+	val = mval;
+	next = mnext;
+	prev = mprev;
+	col = mcol;
+	row = mrow;
+}
+
+inline void ChMelement::Initialize (double mval, ChMelement* mnext, ChMelement* mprev, int mrow, int mcol)
+{
+	val = mval;
+	next = mnext;
+	prev = mprev;
+	col = mcol;
+	row = mrow;
+}
+
+//***TO DO*** move into ChLcpSimplexSolver
+
+#define LCP_MAX_ITERS             200
+#define CONSTR_UNILATERAL_NONE		0
+#define CONSTR_UNILATERAL_REDUNDANT 1
+#define CONSTR_UNILATERAL_OFF		2
+#define CONSTR_UNILATERAL_ON	  102
+
+
+class ChUnilateralData {
+public:
+	void Reset()	{
+			//status= CONSTR_UNILATERAL_NONE;
+			status= CONSTR_UNILATERAL_OFF;
+			//friction = 0.;
+	}
+
+	char	status;
+	//double	friction;
+};
+
+
+//////////////////////////////////////////////////
+// SPARSE MATRIX CLASS
+//
+/// This class defines a sparse matrix, using the method of 
+/// linked lists of non-structural-zeros per each row.
+///
+/// Note that this class is inherited from the ChMatrix class, 
+/// however, since ChMatrix has no 'virtual' members for speed
+/// reasons (especially, the Set/GetElement fundamental methods
+/// are not virtual!) this means that MOST ChMatrix methods
+/// must be overridden and re-implemented, even if you 
+/// would stick with the implementation in the base class!
+/// (here, only few of them are reimplemented, more will
+/// come later in futire releases.).
+/// 
+
+
+class ChApi ChSparseMatrix : public ChMatrix<double> {
+ private:
+	ChMelement** elarray;	// array of 1st column elements 
+
+	ChList<ChMelement> mbufferlist;		// list of pointers to Melement* buffers
+	ChMelement* mnextel;				// address of next writable element in mbufferlist 
+
+	int mtot_size;		// total allocated space for elements (maybe in noncontiguous buffers list) 
+	int mbuffer_size;	// size of currently used buffer
+	int mbuffer_added;	// mbuffer_added grows all time a new element is set non-zero,
+						// until it reaches mbuffer_size (if so, allocation of another buffer is needed). Handled internally.
+
+	ChMelement* NewElement (double mval, ChMelement* mnext, ChMelement* mprev, int mrow, int mcol); // used internally
+	ChMelement** GetElarray () { return elarray; };
+	ChMelement* GetElarrayMel(int num) {return (*(elarray+num));}
+	double GetElarrayN (int num) { return (*(elarray+num))->val; };
+	void SetElarrayN (double val, int num) { (*(elarray+num))->val = val;};
+ public:
+
+		// 
+		// CONSTRUCTORS
+		//
+
+					/// Creates a sparse matrix with given size.
+					/// fullness = predicted initial "density" of matrix,
+					/// between 0..1, to have best buffer handling and
+					/// memory allocations.
+	ChSparseMatrix (int row, int col, double fullness);	 
+
+					/// Creates a sparse matrix with given size.
+					/// and default 'predicted' fullness as SPM_DEF_FULLNESS
+	ChSparseMatrix (int row, int col);
+
+					/// Creates a default 3x3 (a bit unuseful, use 
+					/// ChSparseMatrix for _large_ matrices! :)
+	ChSparseMatrix ();	
+	~ChSparseMatrix ();
+
+	void Build(int row, int col, double fullness);		///< [mostly used internally]
+
+
+
+	void CopyFromMatrix (ChMatrix<>* matra);
+	void CopyFromMatrix (ChSparseMatrix* matra);
+	void CopyToMatrix	(ChMatrix<>* matra);
+
+					// optimized SetElement,  returning the fetched Melement*
+	ChMelement* SetElement (int row, int col, double val, ChMelement* guess);
+					// optimized GetElement,  returning the fetched Melement*
+	ChMelement* GetElement (int row, int col, double* val, ChMelement* guess);
+
+					// Add another buffer in buffer list, bigger of last 
+					// (max total buffer size = col x rows) as in newbuffer = lastbuffer * inflate  
+					// (use inflate >1, suggested 2)     [mostly used internally]
+	void MoreBuffer(double inflate);			
+
+
+		// Overloadings of standard matrix functions:
+	void Resize(int, int) {assert (false);}; // not implemented
+
+	void Reset();						// reset to null matrix 
+	void Reset(int row, int col);		// reset to null matrix and (if needed) changes the size.
+	void ResetBlocks(int row, int col);	// if size changes, is like the above, otherwise just sets to zero the elements .
+	
+	void   SetElement ( int row, int col, double elem);
+	double GetElement ( int row, int col);
+
+	void SwapColumns (int a, int b);
+	void SwapRows    (int a, int b);
+
+
+		// Customized functions, speed-optimized for sparse matrices:
+
+	void PasteMatrix (ChMatrix<>* matra, int insrow, int inscol);
+	void PasteTranspMatrix (ChMatrix<>* matra, int insrow, int inscol);
+	void PasteMatrixFloat (ChMatrix<float>* matra, int insrow, int inscol);
+	void PasteTranspMatrixFloat (ChMatrix<float>* matra, int insrow, int inscol);
+	void PasteMatrix (ChSparseMatrix* matra, int insrow, int inscol);
+	void PasteTranspMatrix (ChSparseMatrix* matra, int insrow, int inscol);
+	void PasteClippedMatrix (ChMatrix<>* matra, int cliprow, int clipcol, int nrows, int ncolumns, int insrow, int inscol);
+	void PasteSumClippedMatrix (ChMatrix<>* matra, int cliprow, int clipcol, int nrows, int ncolumns, int insrow, int inscol);
+	void PasteSumMatrix (ChMatrix<>* matra, int insrow, int inscol);
+	void PasteSumTranspMatrix (ChMatrix<>* matra, int insrow, int inscol);
+
+	void MatrMultiply ( ChSparseMatrix* matra, ChSparseMatrix* matrb);
+	void MatrMultiplyT ( ChSparseMatrix* matra, ChSparseMatrix* matrb);
+	void MatrTMultiply ( ChSparseMatrix* matra, ChSparseMatrix* matrb);
+	void MatrAdd	( ChSparseMatrix* matra, ChSparseMatrix* matrb);
+	void MatrSub	( ChSparseMatrix* matra, ChSparseMatrix* matrb);
+	void MatrInc	( ChSparseMatrix* matra);
+	void MatrScale	( double factor);
+	void MatrTranspose();
+	void Neg();
+
+	// Linear algebra functions
+
+					// Basic Gauss solver 
+	int  BestPivotRow (int current);
+	int  BestPivotDiag (int current);
+	void DiagPivotSymmetric(int rowA, int rowB);
+	int  Solve_LinSys ( ChMatrix<>* B, ChMatrix<>* X, int* pivarray, double* det);
+	void Solve_LinSys ( ChMatrix<>* B, ChMatrix<>* X); // the object is the [A] matrix.
+
+					// LU decomposition, in place. (matrix [A] is overwritten) 
+					// Pivot array must exist! (it will be filled with the _row_ pivots, if any)
+	int	 Decompose_LU(int* pivarray, double* det);
+	int	 Solve_LU(ChMatrix<>* B, ChMatrix<>* X, int* pivarray);	
+	int  Extract_LU(ChMatrix<>* L, ChMatrix<>* U);	// From this matrix, computed 'in place' with Decompose_LU(), fills the separate L and U 
+							
+					/// LDL decomposition, only for symmetric matrices [A]!! Note: pivarray is for 
+					/// both row and col swap (full diagonal pivot)! Note: only upper part of [A] is used.
+					/// The decomposition can be made to start from the 'from_eq' equation, if matrix was already decomposed and only 
+					/// a basis has been modified under the right-lower part at 'from_eq, from_eq' cell (ex: in LCP solver)
+	int	 Decompose_LDL(int* pivarray, double* det, int from_eq = 0);	
+	int	 Solve_LDL(ChMatrix<>* B, ChMatrix<>* X, int* pivarray);
+	int  Extract_LDL(ChMatrix<>* L, ChMatrix<>* D, ChMatrix<>* Lu);
+	int	 DecomposeAndSolve_LDL(ChMatrix<>* B, ChMatrix<>* X, double& mdet, int from_eq = 0);
+				
+	int	 DecomposeAndSolve_LDL_forLCP (ChMatrix<>* B, ChMatrix<>* X, double& mdet, 
+											   int i_D, int i_C, int n_unilaterals,
+											   ChUnilateralData constr_data[], int from_eq = 0);
+	static int DecomposeAndSolve_LDL_forLCP
+											  (ChSparseMatrix* Afact,
+											   ChSparseMatrix* Aorig,
+												ChMatrix<>* B, ChMatrix<>* X, double& mdet, 
+											   int i_D, int i_C, int n_unilaterals, 
+											   ChUnilateralData constr_data[], int from_eq,
+											   int backup_from);
+
+					// LCP solver for dynamic problems: the matrix must contain the mass matrix
+					// on the upper left part, bordered with the jacobians of bilateral constraints C,
+					// then bordered with 'n_unilaterals' unilateral constraints D: 
+					//       this      *  X   =   B 
+					//
+					//   | M  C'  D' |   |q	|	|Qf |
+					//   | C  0   0  | * |fc| = |Qc |
+					//   | D  0   0  |   |fd|   |Qd |
+					//
+					// Only the upper part of the matrix is modified (the one with transpose jacobians C' and D'),
+					// the lower is used to store the original jacobians.
+	int  SolveLCP(ChMatrix<>* B, ChMatrix<>* X, 
+						   int n_bilaterals, int n_unilaterals, 
+						   int maxiters = 200,
+						   bool keep_unilateral_status = false,
+						   ChUnilateralData constr_data[] = NULL);
+
+
+
+					/// Method to allow serializing transient data into in ascii stream (es a file)
+					/// as a Matlab sparse matrix format ( each row in file has three elements: 
+					///     row,    column,    value 
+					/// Note: the row and column indexes start from 1, not 0 as in C language.
+	void StreamOUTsparseMatlabFormat(ChStreamOutAscii& mstream);
+
+};
+
+
+// used internally:
+inline ChMelement* ChSparseMatrix::NewElement (double mval, ChMelement* mnext, ChMelement* mprev, int mrow, int mcol)
+{
+	if (mbuffer_added >= mbuffer_size)
+	{
+		MoreBuffer(2.0);
+	}
+
+	ChMelement* newel = mnextel;
+	mnextel->Initialize(mval,mnext,mprev,mrow,mcol);
+	
+	mbuffer_added++;
+	mnextel++;
+
+	return (newel);
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/core/ChStream.cpp b/SRC/ChronoEngine/core/ChStream.cpp
new file mode 100644
index 0000000..b81286e
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChStream.cpp
@@ -0,0 +1,869 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChStream.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include <math.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <iterator>
+
+#include "core/ChStream.h"
+#include "core/ChException.h"
+#include "core/ChLog.h"
+
+
+namespace chrono
+{
+
+
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// ChStreamOutAscii
+
+
+ChStreamOutAscii& ChStreamOutAscii::operator <<(bool bVal)
+{
+    if (bVal) Output("1", 1);
+	else      Output("0", 1);
+	return *this;
+}
+
+ChStreamOutAscii& ChStreamOutAscii::operator <<(char* str)
+{
+    Output(str,  strlen(str));
+	return *this;
+}
+ChStreamOutAscii& ChStreamOutAscii::operator <<(std::string &str)
+{
+    Output(str.c_str(),  strlen(str.c_str()));
+	return *this;
+}
+ChStreamOutAscii& ChStreamOutAscii::operator <<(const char* str)
+{
+    Output(str,  strlen(str));
+	return *this;
+}
+
+ChStreamOutAscii& ChStreamOutAscii::operator <<(int unVal)
+{
+	char buffer[100];
+
+	sprintf(buffer, "%d", unVal);
+
+    Output(buffer, strlen(buffer));
+
+	return *this;
+}
+
+ChStreamOutAscii& ChStreamOutAscii::operator <<(unsigned int unVal)
+{
+	char buffer[100];
+
+	sprintf(buffer, "%u", unVal);
+
+    Output(buffer, strlen(buffer));
+
+	return *this;
+}
+ChStreamOutAscii& ChStreamOutAscii::operator <<(unsigned long unVal)
+{
+	char buffer[100];
+
+	sprintf(buffer, "%lu", unVal);
+
+    Output(buffer, strlen(buffer));
+
+	return *this;
+}
+ChStreamOutAscii& ChStreamOutAscii::operator <<(unsigned long long unVal)
+{
+    char buffer[100];
+        
+    sprintf(buffer, "%ll", unVal);
+        
+    Output(buffer, strlen(buffer));
+        
+    return *this;
+}
+/*
+ChStreamOutAscii& ChStreamOutAscii::operator <<(long lVal)
+{
+	char buffer[100];
+
+	sprintf(buffer, "%ld", lVal);
+
+    Output(buffer, strlen(buffer));
+
+	return *this;
+}
+*/
+ChStreamOutAscii& ChStreamOutAscii::operator <<(char	tch)
+{
+    char szCh[2];
+    szCh[0] = tch;
+    szCh[1] = '\0';
+    Output(szCh,  1);
+    return *this;
+}
+/*
+ChStreamOutAscii& ChStreamOutAscii::operator <<(unsigned long ulVal)
+{
+    char buffer[100];
+
+	sprintf(buffer, "%lu", ulVal);
+
+    Output(buffer, strlen(buffer));
+
+	return *this;
+}
+*/
+ChStreamOutAscii& ChStreamOutAscii::operator <<(double dVal)
+{
+    char buffer[100];
+
+	sprintf(buffer, number_format, dVal);
+
+    Output(buffer,  strlen(buffer));
+
+	return *this;
+}
+
+ChStreamOutAscii& ChStreamOutAscii::operator <<(float dVal)
+{
+    char buffer[100];
+
+	sprintf(buffer, number_format, ((double)dVal));
+
+    Output(buffer,  strlen(buffer));
+
+	return *this;
+}
+
+
+void ChStreamOutAscii::Format(char* formatString, ...)
+{
+	if ( formatString == NULL)
+	{
+		throw (ChException("Bad format string"));
+	}
+
+	va_list argList;
+
+	// Set va_list to the beginning of optional arguments
+
+	va_start(argList, formatString);
+	char* ptr = formatString;
+
+	while(*ptr != '\0')
+	{
+		char* str			= NULL;
+		int nInteger		= 0;
+		unsigned int unInt	= 0;
+		double	dDoub		= 0;
+
+		if(*ptr == '%')
+		{
+			switch(*(ptr+1))
+			{
+			case 's':
+				str = va_arg(argList, char*);
+
+				if( NULL == str)
+					break;
+				*this << str;
+				ptr++;
+				break;
+
+			case 'd':
+				nInteger = va_arg(argList, int);
+				*this << nInteger;
+				ptr++;
+				break;
+
+			case 'u':
+				unInt = va_arg(argList, unsigned int);
+				*this << unInt;
+				ptr++;
+				break;
+
+			case 'f':
+				dDoub = va_arg(argList, double);
+				*this << dDoub;
+				ptr++;
+				break;
+			default:
+				*this << *ptr;
+			}
+		}
+		else
+		{
+			*this << *ptr;
+		}
+
+
+		ptr++;
+	}
+
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// ChStreamInAscii
+
+static void RemoveTrailingCommas(std::string mstring)
+{
+	/*
+	while(mstring.length() > 0)
+	{
+		if ((mstring.substr(mstring.length()-1,1) == ",") || 
+			(mstring.substr(mstring.length()-1,1) == ";") ) 
+				mstring.resize(mstring.length()-1);
+	}
+	*/
+}
+
+ChStreamInAscii& ChStreamInAscii::operator >> (bool	&bVal)
+{
+	std::string textboolean;
+	bool parsed = false;
+	*this >> textboolean;
+	RemoveTrailingCommas(textboolean);
+	if (textboolean=="true") {
+		bVal = true;
+		parsed = true;
+	}
+	if (textboolean=="false") {
+		bVal = false;
+		parsed = true;
+	}
+	if (textboolean=="1") {
+		bVal = true;
+		parsed = true;
+	}
+	if (textboolean=="0") {
+		bVal = false;
+		parsed = true;
+	}
+	if (!parsed)
+		throw (ChException( "String " +textboolean+ " is not a valid 'true'/'false' value"));
+	return *this;
+}
+/*
+ChStreamInAscii& ChStreamInAscii::operator >> (long	&lVal)
+{
+	std::string buffer;
+	*this >> buffer;
+	RemoveTrailingCommas(buffer);
+	lVal = atoi(buffer.c_str());
+	return *this;
+}
+*/
+ChStreamInAscii& ChStreamInAscii::operator >>(char	&tch)
+{
+	char loa[1];
+	Input(loa, 1);
+	tch=loa[0];
+	return *this;
+}
+
+ChStreamInAscii& ChStreamInAscii::operator >>(int	&nVal)
+{
+	std::string buffer;
+	*this >> buffer;
+	RemoveTrailingCommas(buffer);
+	nVal = atoi(buffer.c_str());
+	return *this;
+}
+/*
+ChStreamInAscii& ChStreamInAscii::operator >>(unsigned	long	&ulVal)
+{
+	std::string buffer;
+	*this >> buffer;
+	RemoveTrailingCommas(buffer);
+	ulVal = atoi(buffer.c_str());
+	return *this;
+}
+*/
+
+
+ChStreamInAscii& ChStreamInAscii::operator >>(double	&dVal)
+{
+	std::string buffer;
+	*this >> buffer;
+	RemoveTrailingCommas(buffer);
+	dVal = atof(buffer.c_str());
+	//if (errno)
+		//throw (ChException( "String " +buffer+ " is not a valid number format"));
+	return *this;
+}
+
+ChStreamInAscii& ChStreamInAscii::operator >>(float	&dVal)
+{
+	std::string buffer;
+	*this >> buffer;
+	RemoveTrailingCommas(buffer);
+	dVal = (float)(atof(buffer.c_str()));
+	//if (errno)
+		//throw (ChException( "String " +buffer+ " is not a valid number format"));
+	return *this;
+}
+
+ChStreamInAscii& ChStreamInAscii::operator >>(unsigned	int	&unVal)
+{
+	std::string buffer;
+	*this >> buffer;
+	RemoveTrailingCommas(buffer);
+	unVal = atoi(buffer.c_str());
+	return *this;
+}
+
+
+ChStreamInAscii& ChStreamInAscii::operator >>( char* str)
+{
+	/*
+	bool stop = 0;
+	int cnt = 0;
+	char loa[2];
+	loa[1]=0;
+
+	while(true)
+	{
+
+		try {Input(loa, 1);}
+		catch (std::exception mfoo)
+		{
+			if (!(this->End_of_stream() && cnt>0))
+				throw (ChException("Cannot read from stream"));
+		}
+
+		if (this->End_of_stream() || loa[0]==*"\n" || loa[0]==*" " || loa[0]==*"\t" || loa[0]==0)
+			break;
+
+		str[cnt]=loa[0];
+		cnt++;
+	}
+	str[cnt]=NULL;
+	*/
+
+	std::string buffer;
+	*this >> buffer;
+	strcpy(str, buffer.c_str());
+
+	return *this;
+}
+
+
+
+ChStreamInAscii& ChStreamInAscii::operator >>(std::string &str)
+{
+	//bool stop = 0; //unused
+	int cnt = 0;
+	char loa[2];
+	loa[1]=0;
+	str="";
+	bool started = false;
+
+	while(true)
+	{
+
+		try {Input(loa, 1);}
+		catch (std::exception mfoo)
+		{
+			if (!(this->End_of_stream() && cnt>0))
+				throw (ChException("Cannot read from stream"));
+		}
+
+		if (this->End_of_stream())
+			break;
+		
+		if (loa[0]!=*"\n" && loa[0]!=*" " && loa[0]!=*"\t")
+			started = true;
+
+		if (started)
+		{
+			if (loa[0]==*"\n" || loa[0]==*" " || loa[0]==*"\t" || loa[0]==0)
+				break;
+			str.append(loa);
+		}
+
+		cnt++;
+	}
+
+	return *this;
+}
+
+
+
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// ChBinaryArchive
+
+
+// Endian test
+bool ChBinaryArchive::IsBigEndianMachine()
+{
+  union {
+    int word;
+    unsigned char byte;
+  } endian_test;
+
+  endian_test.word = 1;
+  if(endian_test.byte != 1)
+	  return true;
+  else
+	  return false;
+
+  return false;
+}
+
+
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// ChStreamOutBinary
+
+
+
+
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(char	Val)
+{
+	this->Output((char*)&Val, sizeof(char));
+	return (*this);
+}
+ChStreamOutBinary& ChStreamOutBinary::operator <<(bool	Val)
+{
+	// convert booleans to char, for cross-platform compatibility.
+	char tmp;
+	tmp = (char)Val;
+	this->Output((char*)&tmp, sizeof(char));
+	return (*this);
+}
+/*
+ChStreamOutBinary& ChStreamOutBinary::operator <<(long	Val)
+{
+	if (big_endian_machine)
+	{
+		long tmp = Val;
+		StreamSwapBytes<long>(&tmp);
+		this->Output((char*)&tmp, sizeof(long));
+	}
+	this->Output((char*)&Val, sizeof(long));
+	return (*this);
+}
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(unsigned long Val)
+{
+	if (big_endian_machine)
+	{
+		unsigned long tmp = Val;
+		StreamSwapBytes<unsigned long>(&tmp);
+		this->Output((char*)&tmp, sizeof(unsigned long));
+	}
+	this->Output((char*)&Val, sizeof(unsigned long));
+	return (*this);
+}
+*/
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(const int		Val)
+{
+	if (big_endian_machine)
+	{
+		int tmp = Val;
+		StreamSwapBytes<int>(&tmp);
+		this->Output((char*)&tmp, sizeof(int));
+	} else  {
+	  this->Output((char*)&Val, sizeof(int));
+	}
+	return (*this);
+}
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(unsigned int Val)
+{
+	if (big_endian_machine)
+	{
+		unsigned int tmp = Val;
+		StreamSwapBytes<unsigned int>(&tmp);
+		this->Output((char*)&tmp, sizeof(unsigned int));
+	} else {
+	  this->Output((char*)&Val, sizeof(unsigned int));
+	}
+	return (*this);
+}
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(const double	Val)
+{
+	if (big_endian_machine)
+	{
+		double tmp = Val;
+		StreamSwapBytes<double>(&tmp);
+		this->Output((char*)&tmp, sizeof(double));
+	} else {
+	  this->Output((char*)&Val, sizeof(double));
+	}
+	return (*this);
+}
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(const float	Val)
+{
+	if (big_endian_machine)
+	{
+		float tmp = Val;
+		StreamSwapBytes<float>(&tmp);
+		this->Output((char*)&tmp, sizeof(float));
+	} else {
+	  this->Output((char*)&Val, sizeof(float));
+	}
+	return (*this);
+}
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(char*		str)
+{
+	// save string length, including null termination
+	int mlength = strlen(str)+1;
+	*this << mlength;
+	// save all bytes including null termination
+	this->Output(str, mlength);
+	return *this;
+}
+
+ChStreamOutBinary& ChStreamOutBinary::operator <<(std::string	&str)
+{
+	// save string length, including null termination
+        int mlength = strlen(str.c_str());
+	*this << mlength;
+	// save all bytes including null termination
+	this->Output(str.c_str(), strlen(str.c_str()));
+	return *this;
+}
+
+void ChStreamOutBinary::VersionWrite(int mver)
+{
+	*this << mver;
+}
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// ChStreamInBinary
+
+
+
+
+ChStreamInBinary& ChStreamInBinary::operator >>(char		&Val)
+{
+	this->Input((char*)&Val, sizeof(char));
+	return (*this);
+}
+
+ChStreamInBinary& ChStreamInBinary::operator >>(bool		&Val)
+{
+	// booleans as chars, for cross platform portability
+	char tmp;
+	this->Input((char*)&tmp, sizeof(char));
+	if (tmp) Val= true; else Val = false;
+	//Val = (bool)tmp;
+	return (*this);
+}
+/*
+ChStreamInBinary& ChStreamInBinary::operator >>(long		&Val)
+{
+	if (big_endian_machine) {
+		long tmp;
+		this->Input((char*)&tmp, sizeof(long));
+		StreamSwapBytes<long>(&tmp);
+		Val = tmp;
+	} else {
+		this->Input((char*)&Val, sizeof(long));
+	}
+	return (*this);
+}
+
+ChStreamInBinary& ChStreamInBinary::operator >>(unsigned long &Val)
+{
+	if (big_endian_machine) {
+		unsigned long tmp;
+		this->Input((char*)&tmp, sizeof(unsigned long));
+		StreamSwapBytes<unsigned long>(&tmp);
+		Val = tmp;
+	} else {
+		this->Input((char*)&Val, sizeof(unsigned long));
+	}
+	return (*this);
+}
+*/
+ChStreamInBinary& ChStreamInBinary::operator >>(int		&Val)
+{
+	if (big_endian_machine) {
+		int  tmp;
+		this->Input((char*)&tmp, sizeof(int));
+		StreamSwapBytes<int>(&tmp);
+		Val = tmp;
+	} else {
+		this->Input((char*)&Val, sizeof(int));
+	}
+	return (*this);
+}
+
+ChStreamInBinary& ChStreamInBinary::operator >>(unsigned int &Val)
+{
+	if (big_endian_machine) {
+		unsigned int  tmp;
+		this->Input((char*)&tmp, sizeof(unsigned int));
+		StreamSwapBytes<unsigned int>(&tmp);
+		Val = tmp;
+	} else {
+		this->Input((char*)&Val, sizeof(unsigned int));
+	}
+	return (*this);
+}
+
+ChStreamInBinary& ChStreamInBinary::operator >>(double		&Val)
+{
+	if (big_endian_machine) {
+		double tmp;
+		this->Input((char*)&tmp, sizeof(double));
+		StreamSwapBytes<double>(&tmp);
+		Val = tmp;
+	} else {
+		this->Input((char*)&Val, sizeof(double));
+	}
+	return (*this);
+}
+
+
+ChStreamInBinary& ChStreamInBinary::operator >>(float		&Val)
+{
+	if (big_endian_machine) {
+		float  tmp;
+		this->Input((char*)&tmp, sizeof(float));
+		StreamSwapBytes<float>(&tmp);
+		Val = tmp;
+	} else {
+		this->Input((char*)&Val, sizeof(float));
+	}
+	return (*this);
+}
+
+ChStreamInBinary& ChStreamInBinary::operator >>(char*		str)
+{
+	// Read string length , plus null-termination char
+	int mlength;
+	*this >> mlength;
+	// Read all bytes of string.
+	this->Input(str, mlength);
+	return *this;
+}
+
+ChStreamInBinary& ChStreamInBinary::operator >>(std::string		&str)
+{
+	// Read string length , plus null-termination char
+	str = "";
+	char buf[2];
+	buf[1]='\0';
+	int mlength;
+	*this >> mlength ;
+	str.reserve(mlength);
+	for (int i = 0; i<mlength; i++)
+	{
+		this->Input(buf, 1);
+		str.append(buf);
+	}
+	// Read all bytes of string.
+
+	return *this;
+}
+
+int ChStreamInBinary::VersionRead()
+{
+	int mres;
+	*this >> mres;
+	return mres;
+}
+
+////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////
+//
+// ChStreamFile
+
+
+ChStreamFile::ChStreamFile(const char* filename, std::ios::openmode mmode)
+{
+	try
+	{
+		//file.exceptions(std::ios::failbit | std::ios::badbit);
+		file.exceptions(std::ios::failbit | std::ios::badbit | std::ios::eofbit);
+		file.open(filename, mmode);
+	}
+	catch (std::exception)
+	{
+		std::cout << "CANNOT OPEN";
+		throw ChException("Cannot open stream");
+	};
+	strcpy (name, filename);
+};
+
+			/// Destruction means that the file stream is also closed.
+ChStreamFile::~ChStreamFile()
+{
+	file.flush();
+	file.close();
+};
+
+void ChStreamFile::Write(const char* data, int n)
+{
+	try{ file.write(data, n); }
+	catch (std::exception){throw ChException("Cannot write to stream");};
+}
+
+void ChStreamFile::Read(char* data, int n)
+{
+	try{ file.read(data, n); }
+	catch (std::exception){throw ChException("Cannot read from stream");};
+}
+
+//////////////////////////////////
+
+ChStreamOstreamWrapper::ChStreamOstreamWrapper(std::ostream* mfile)
+{
+	assert(mfile);
+	afile = mfile;
+};
+ChStreamOstreamWrapper::~ChStreamOstreamWrapper() {};
+
+
+void ChStreamOstreamWrapper::Write(const char* data, int n)
+{
+	try{ afile->write(data, n); }
+	catch (std::exception){throw ChException("Cannot write to wrapped stream");};
+}
+
+//////////////////////////////////
+
+ChStreamIstreamWrapper::ChStreamIstreamWrapper(std::istream* mfile)
+{
+	assert(mfile);
+	afile = mfile;
+};
+ChStreamIstreamWrapper::~ChStreamIstreamWrapper() {};
+
+
+void ChStreamIstreamWrapper::Read(char* data, int n)
+{
+	try{ afile->read(data, n); }
+	catch (std::exception){throw ChException("Cannot read from wrapped stream");};
+}
+
+
+//////////////////////////////////
+
+ChStreamVectorWrapper::ChStreamVectorWrapper(std::vector<char>* mchars)
+{
+	assert(mchars);
+	vbuffer = mchars;
+	pos = 0;
+};
+ChStreamVectorWrapper::~ChStreamVectorWrapper() {};
+
+
+void ChStreamVectorWrapper::Write(const char* data, int n)
+{
+	std::copy(data, data+n, std::back_inserter(*vbuffer));
+}
+void ChStreamVectorWrapper::Read(char* data, int n)
+{
+	if (pos+n > vbuffer->size())
+		n = vbuffer->size()-pos;
+
+	for (int i=0; i<n; i++)
+	{
+		data[i] = (*vbuffer)[pos];
+		pos++;
+	}
+}
+bool ChStreamVectorWrapper::End_of_stream()
+{
+	if (pos >= vbuffer->size()) 
+		return true;
+	return false;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// These constructors / destructors, though concise, cannost stay in .h because
+// the GNU GCC linker gives strange problems...
+
+ChStreamOut::ChStreamOut() {};
+ChStreamOut::~ChStreamOut() {};
+
+ChStreamIn::ChStreamIn() {};
+ChStreamIn::~ChStreamIn() {};
+
+ChStreamOutAscii::ChStreamOutAscii()
+{
+	strcpy(number_format, "%g");
+	strcpy(comment_trailer, "#");
+};
+ChStreamOutAscii::~ChStreamOutAscii() {};
+
+ChStreamInAscii::ChStreamInAscii()
+{
+	strcpy(number_format, "%g");
+};
+ChStreamInAscii::~ChStreamInAscii() {};
+
+ChStreamOutBinary::ChStreamOutBinary() {};
+ChStreamOutBinary::~ChStreamOutBinary() {};
+
+ChBinaryArchive::ChBinaryArchive() {Init();};
+ChBinaryArchive::~ChBinaryArchive() {};
+
+ChStreamInBinary::ChStreamInBinary() {};
+ChStreamInBinary::~ChStreamInBinary() {};
+
+
+ChStreamOutBinaryFile::ChStreamOutBinaryFile(const char* filename, std::ios::openmode mmode) : ChStreamFile(filename,  mmode | std::ios::out| std::ios::binary) {};
+ChStreamOutBinaryFile::~ChStreamOutBinaryFile() {};
+
+ChStreamOutAsciiFile::ChStreamOutAsciiFile(const char* filename, std::ios::openmode mmode) : ChStreamFile(filename,  mmode | std::ios::out ) {};
+ChStreamOutAsciiFile::~ChStreamOutAsciiFile() {};
+
+ChStreamInBinaryFile::ChStreamInBinaryFile(const char* filename) : ChStreamFile(filename, std::ios::in | std::ios::binary) {};
+ChStreamInBinaryFile::~ChStreamInBinaryFile() {};
+
+ChStreamInAsciiFile::ChStreamInAsciiFile(const char* filename) : ChStreamFile(filename,  std::ios::in) {};
+ChStreamInAsciiFile::~ChStreamInAsciiFile() {};
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/core/ChStream.h b/SRC/ChronoEngine/core/ChStream.h
new file mode 100644
index 0000000..ba04bea
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChStream.h
@@ -0,0 +1,909 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSTREAM_H
+#define CHSTREAM_H
+
+//////////////////////////////////////////////////
+//
+//   ChStream.h
+//
+//   Class for stream input-output of Chrono objects.
+//   Defines some functions for ASCII parsing of the
+//   textual file format of Chrono.
+//   Defines binary in/out
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <ios>
+#include "ChException.h"
+#include "core/ChApiCE.h"
+//#include "core/ChClassRegister.h"	///this didn't help the "create not found problem..."
+namespace chrono
+{
+///Ugly hack added by hammad to get code to compile on osx.
+///Compiler had trouble finding the create function,
+///adding #incldue to ChClassRegister made other things break in ChLog so I couldn't do that....
+template<class T>
+void create( std::string cls_name, T** ppObj);
+
+///
+/// This is a base class for input/output (streaming)
+///
+
+class ChApi ChStream {
+
+public:
+				/// Modes for chrono files (the ch-modes) - obsolete -
+	enum eChMode {
+		CHFILE_NORMAL = 0,	///< writes/reads as a normal file
+		CHFILE_NOWRITE,		///< force do not write even if in w or wb (write mode)
+		CHFILE_SAFEWRITE,	///< safe writing (obsolete)
+		CHFILE_OPENLATER,	///< creates the file only as soon as first writing is attempted
+	};
+
+				/// Errors for chrono files (the ch-modes)
+	enum eChStreamError {
+		CHSTREAM_OK = 0,	///< write/read operation successfull
+		CHSTREAM_EOF,		///< end of file
+		CHSTREAM_FAIL,		///< operation failed
+	};
+
+protected:
+				//
+	  			// DATA
+				//
+};
+
+
+///
+/// This is a base class for all OUTPUT streams.
+/// Does nothing special - it must be implemented by child classes
+///
+
+class ChApi ChStreamOut : public ChStream
+{
+public:
+
+	ChStreamOut();
+
+	virtual ~ChStreamOut();
+
+protected:
+
+			/// Outputs a raw chunk of data, from pointer 'data' up to 'n'
+			/// chars (bytes).
+			/// NOTE! Inherited class could override only this function to have
+			/// everything working, for example to output into a message box,
+			/// or to sockets, etc..
+	virtual void	Output(const char* data, int n) =0;
+
+
+};
+
+
+///
+/// This is a base class for all INPUT streams.
+/// Does nothing special - it must be implemented by child classes
+///
+
+class ChApi ChStreamIn : public ChStream
+{
+public:
+
+	ChStreamIn();
+
+	virtual ~ChStreamIn();
+
+			/// Returns true if end of stream reached.
+			/// Child classes should implement it.
+	virtual bool End_of_stream() {return true;};
+
+protected:
+
+			/// Inputs a raw chunk of data, from pointer 'data' up to 'n'
+			/// chars (bytes).
+			/// NOTE! Inherited class could override only this function to have
+			/// everything working, for example to output into a message box,
+			/// or to sockets, etc..
+	virtual void	Input(char* data, int n) =0;
+
+
+
+};
+
+
+///
+/// This is a base class for all ASCII OUTPUT streams, in the
+/// sense that number are formatted into readable strings, etc.
+/// Defines some << operators from basic
+/// types, converting all them into calls to the Output() function.
+/// Also, defines the Format() function, which can be used a bit
+/// like the printf formatting.
+/// At least some inherited class should be used by the user in
+/// order to get some practical effect (file saving, etc.)
+///
+
+class ChApi ChStreamOutAscii : public ChStreamOut
+{
+protected:
+	char number_format[10];
+	char comment_trailer[10];
+
+public:
+
+	ChStreamOutAscii();
+
+	virtual ~ChStreamOutAscii();
+
+			//  Operators
+
+				/// Generic << operator for all classes which implement serialization
+				/// by means of a method named  'void StreamOUT(ChStreamOutAscii&)'
+
+	ChStreamOutAscii& operator <<(bool		bVal);
+	ChStreamOutAscii& operator <<(char		tch);
+	ChStreamOutAscii& operator <<(const int	nVal);
+	ChStreamOutAscii& operator <<(const double	dVal);
+	ChStreamOutAscii& operator <<(const float	dVal);
+	ChStreamOutAscii& operator <<(unsigned int unVal);
+	ChStreamOutAscii& operator <<(char*	 str);
+	ChStreamOutAscii& operator <<(const char*	str);
+	ChStreamOutAscii& operator <<(std::string&	str);
+	ChStreamOutAscii& operator <<(unsigned long unVal);
+    ChStreamOutAscii& operator <<(unsigned long long unVal);
+
+	template<class T>
+	ChStreamOutAscii& operator <<(T obj)
+				{
+					obj.StreamOUT(*this);
+					return *this;
+				}
+
+			/// Output the log message in form of a formatted string, like in printf()
+	virtual void Format(char* formatString, ...);
+
+			/// Set the formatting string (ex "%f" or "%g" etc.) for float->text conversion
+	void SetNumFormat (char* mf)
+				{
+					if (strlen(mf) < 10)
+						strcpy(number_format, mf);
+				}
+			/// Set the trailer symbol before each comment (example: "#" , or "//" etc.)
+	void SetCommentTrailer (char* mt)
+				{
+					if (strlen(mt) < 10)
+						strcpy(comment_trailer, mt);
+				}
+
+			/// Outputs carriage return
+	void CR()	{ *this << "\n";};
+
+			/// Output tab
+	void TAB()	{ *this << "\t";};
+
+			/// Output comment with preceding trailer (ex #)
+	void Comment (char m_string[])
+				{
+					//if (CHGLOBALS().WriteComments)
+					//{
+						TAB(); TAB(); TAB();
+						*this << comment_trailer << m_string;
+					//}
+					CR();
+				}
+					/// Output a separation bar in Ascii file
+	void Bar() { *this << comment_trailer << "#------------------------------------------------------------ \n";};
+
+};
+
+///
+/// This is a base class for all ASCII INPUT streams, in the
+/// sense that number are formatted into readable strings, etc.
+/// Defines some << operators from basic
+/// types, converting all them into calls to the Input() function.
+/// At least some inherited class should be used by the user in
+/// order to get some practical effect (file loading, etc.)
+///
+
+class ChApi ChStreamInAscii : public ChStreamIn
+{
+protected:
+	char number_format[10];
+
+public:
+
+	ChStreamInAscii();
+
+	virtual ~ChStreamInAscii();
+
+			//  Operators
+
+	virtual ChStreamInAscii& operator >>(bool				&bVal);
+	virtual ChStreamInAscii& operator >>(char				&tch);
+	virtual ChStreamInAscii& operator >>(int				&nVal);
+	virtual ChStreamInAscii& operator >>(double				&dVal);
+	virtual ChStreamInAscii& operator >>(float				&dVal);
+	virtual ChStreamInAscii& operator >>(unsigned	int		&unVal);
+	virtual ChStreamInAscii& operator >>(char*				str);
+	virtual ChStreamInAscii& operator >>(std::string		&str);
+
+
+			/// Set the formatting string (ex "%f" or "%g" etc.) for text->float conversion
+	void SetNumFormat (char* mf)
+				{
+					if (strlen(mf) < 10)
+						strcpy(number_format, mf);
+				}
+
+};
+
+
+/// Templated function for swapping bytes of objects of type 'T',
+/// in general fo rwhatever T type. This is used for cross-platform
+/// compatibility when sharing objects between big-endian and little-endian
+/// memory models, depending on the microprocessor type.
+
+template <class T>
+inline void StreamSwapBytes (T* ptData)
+{
+    char* acBytes = (char*) ptData;
+    int iSize = (int)(sizeof(T));
+    int iSizeM1 = iSize - 1;
+    int iHSize = iSize/2;
+    for (int i0 = 0, i1 = iSizeM1; i0 < iHSize; i0++, i1--)
+    {
+        char cSave = acBytes[i0];
+        acBytes[i0] = acBytes[i1];
+        acBytes[i1] = cSave;
+    }
+}
+
+
+///
+/// Base class for streams (either in or out) based on
+/// binary formats.
+///   This class implements a basic functionality
+/// about platform-independent treatment of data (the
+/// big-endian/little-endian issue).
+///   Also this class implements functionality to avoid
+/// storing multiple times the same object (persistent
+/// data archive).
+///
+
+class ChApi ChBinaryArchive
+{
+protected:
+	bool big_endian_machine;
+
+				/// vector of pointers to stored/retrieved objects,
+				/// to avoid saving duplicates or deadlocks
+	std::vector<void*>  objects_pointers;
+
+public:
+	ChBinaryArchive();
+
+	virtual ~ChBinaryArchive();
+
+				/// Returns TRUE if the machine where the code runs
+				/// has big endian byte ordering, returns FALSE otherwise.
+	bool IsBigEndianMachine();
+
+				/// Reinitialize the vector of pointers to loaded/saved objects
+	void Init()
+				{
+					big_endian_machine = IsBigEndianMachine();
+					objects_pointers.clear();
+					objects_pointers.push_back(NULL);
+				}
+				/// Put a pointer in pointer vector, but only if it
+				/// was not previously interted. Returns position of pointer
+				/// if already existing, otherwise -1.
+	int PutPointer(void* object)
+				{
+					for (size_t i=0; i<objects_pointers.size(); ++i)
+					{
+						if (objects_pointers[i]==object) return (int) i;
+					}
+					//wasn't in list.. add to it
+					objects_pointers.push_back(object);
+
+					return -1;
+				}
+};
+
+
+///
+/// This is a base class for all BINARY OUTPUT streams, in a way such
+/// that the stream is platform indepent (see the 'little endian' stuff
+/// in 'floating point to persistent data' topics..)
+/// Defines some << operators from basic
+/// types, converting all them into calls to the Output() function.
+/// At least some inherited class should be used by the user in
+/// order to get some practical effect (file saving, etc.)
+///
+
+class ChApi ChStreamOutBinary : public ChStreamOut , public ChBinaryArchive
+{
+private:
+
+
+public:
+
+	ChStreamOutBinary();
+
+	virtual ~ChStreamOutBinary();
+
+			//  Operators
+
+				/// Generic << operator for all classes which implement serialization
+				/// by means of a method named  'void StreamOUT(ChStreamOutBinary&)'
+	template<class T>
+	ChStreamOutBinary& operator <<(T& obj)
+				{
+					obj.StreamOUT(*this);
+					return *this;
+				}
+
+				/// Specialized operators for basic primitives (numbers like long,
+				/// double, int. etc., and booleans)
+				/// Handle byte ordering issues in little.endian/big.endian representations,
+				/// for cross platform portability.
+	ChStreamOutBinary& operator <<(char		Val);
+	ChStreamOutBinary& operator <<(bool		Val);
+	ChStreamOutBinary& operator <<(int		Val);
+	ChStreamOutBinary& operator <<(unsigned int Val);
+	ChStreamOutBinary& operator <<(double		Val);
+	ChStreamOutBinary& operator <<(float		Val);
+	ChStreamOutBinary& operator <<(std::string	&str);
+
+				/// Specialized operator for C strings.
+	ChStreamOutBinary& operator <<(char*	str);
+
+
+
+				/// Generic operator for binary streaming of generic objects.
+				/// WARNING!!! raw byte streaming! If class 'T' contains double,
+				/// int, long, etc, these may give problems when loading on another
+				/// platform which has big-endian ordering, if generated on a little-edian platform...
+	template <class T>
+	void GenericBinaryOutput(T& ogg)
+				{
+					// from object to stream, all bytes of objects of 'T' type
+					this->Output((char*)&ogg, sizeof(T));
+				}
+
+				/// Stores an object, given the pointer, into the archive.
+				/// This function can be used to serialize objects from
+				/// nontrivial class trees, where at load time one may wonder
+				/// which was the class type of the saved object.
+				/// Note: the object must be load with ChStreamInBinary::AbstractReadCreate()
+				/// Also, the AbstractWrite()-AbstractReadCreate() mechanism avoids
+				/// storing/creating multiple times the shared objects.
+				/// Supports only objects with Chrono RTTI and serializer member StreamOUT().
+	template <class t>
+	t* AbstractWrite(t* pObj)
+				{
+					int pos=PutPointer(pObj);
+
+					if (pos==-1)
+					{
+						pObj->GetRTTI()->GetName();
+						//New Object, we have to full serialize it
+						std::string str = pObj->GetRTTI()->GetName();
+						*this << str;		// serialize class type
+						*this << *pObj;	// serialize data
+					}
+					else
+					{
+						//Object already in list. Only store position
+						std::string str="NULL";
+						*this << str;	// serialize 'this was already saved' info
+						*this << pos;	// serialize position in pointers vector
+					}
+
+					return pObj;
+				}
+
+					/// Stores an object, given the pointer, into the archive.
+					/// This function can be used to serialize objects from
+					/// nontrivial class trees, where at load time one may wonder
+					/// which was the class type of the saved object.
+					/// Note: the object must be load with ChStreamInBinary::AbstractReadCreate()
+					/// Also, the AbstractWrite()-AbstractReadCreate() mechanism avoids
+					/// storing/creating multiple times the shared objects.
+					/// Supports only objects with Chrono RTTI and serializer member StreamOUT().
+		template <class t>
+		t* AbstractWriteAll(t* pObj)
+					{
+						int pos=PutPointer(pObj);
+
+						if (pos==-1)
+						{
+							pObj->GetRTTI()->GetName();
+							//New Object, we have to full serialize it
+							std::string str = pObj->GetRTTI()->GetName();
+							*this << str;		// serialize class type
+							pObj->StreamOUTall(*this); // serialize data
+						}
+						else
+						{
+							//Object already in list. Only store position
+							std::string str="NULL";
+							*this << str;	// serialize 'this was already saved' info
+							*this << pos;	// serialize position in pointers vector
+						}
+
+						return pObj;
+					}
+
+				/// Some objects may write class version at the beginning
+				/// of the streamed data, using this function.
+	void VersionWrite(int mver);
+};
+
+
+///
+/// This is a base class for all BINARY INPUT streams, in a way such
+/// that the stream is platform indepent (see the 'little endian' stuff
+/// in 'floating point to persistent data' topics..)
+/// Defines some << operators from basic
+/// types, converting all them into calls to the Output() function.
+/// At least some inherited class should be used by the user in
+/// order to get some practical effect (file saving, etc.)
+///
+
+class ChApi ChStreamInBinary : public ChStreamIn , public ChBinaryArchive
+{
+private:
+
+public:
+
+	ChStreamInBinary();
+
+	virtual ~ChStreamInBinary();
+
+			//  Operators
+
+				/// Generic >> operator for all classes which implement serialization
+				/// by means of a method named  'void StreamIN(ChStreamInBinary&)'
+	template<class T>
+	ChStreamInBinary& operator >>(T& obj)
+				{
+					obj.StreamIN(*this);
+					return *this;
+				}
+
+				/// Specialized operators for basic primitives (numbers like long,
+				/// double, int. etc., and booleans)
+				/// Handle byte ordering issues in little.endian/big.endian representations,
+				/// for cross platform portability.
+	ChStreamInBinary& operator >>(char		&Val);
+	ChStreamInBinary& operator >>(bool		&Val);
+	ChStreamInBinary& operator >>(int		&Val);
+	ChStreamInBinary& operator >>(unsigned int &Val);
+	ChStreamInBinary& operator >>(double	&Val);
+	ChStreamInBinary& operator >>(float		&Val);
+	ChStreamInBinary& operator >>(std::string	&str);
+
+				/// Specialized operator for C strings
+	ChStreamInBinary& operator >>(char*	str);
+
+
+				/// Generic operator for raw binary streaming of generic objects
+				/// WARNING!!! raw byte streaming! If class 'T' contains double,
+				/// int, long, etc, these may give problems when loading on another
+				/// platform which has big-endian ordering, if generated on a little-edian platform...
+	template <class T>
+	void GenericBinaryInput(T& ogg)
+				{
+					// from stream to object, all bytes of objects of 'T' type
+					this->Input((char*)&ogg, sizeof(T));
+				}
+
+				/// Extract an object from the archive, and assignes the pointer to it.
+				/// This function can be used to load objects whose class is not
+				/// known in advance (anyway, assuming the class had been registered
+				/// with Chrono class factory registration). It _creates_ the object
+				/// of the proper downcasted class, and deserializes it.
+				/// Note: the object must be saved with ChStreamOutBinary::AbstractWrite()
+				/// Also, the AbstractWrite()-AbstractReadCreate() mechanism avoids
+				/// storing/creating multiple times the shared objects.
+				/// Supports only objects with Chrono RTTI and serializer member StreamIN().
+	template<class t>
+	t*   AbstractReadCreate(t** mObj)
+				{
+					std::string cls_name;
+					*mObj = NULL;
+
+					// 1) Read name of class (chrono RTTI type id)
+					*this >> cls_name;
+
+					if (cls_name!="NULL")
+					{
+						// 2) Dynamically create using class factory
+						chrono::create( cls_name, mObj );
+
+						if ( (*mObj)!=NULL)
+						{
+							objects_pointers.push_back(*mObj);
+							// 3) Deserialize
+							*this >> **mObj;
+						}
+						else
+						{
+							throw (ChException("Stream cannot create object"));
+						}
+					}
+					else
+					{
+						int pos=0;
+						// 2b) Was a shared object: just get the pointer to already-retrieved
+						*this >> pos;
+
+						*mObj=static_cast<t*>(objects_pointers[pos]);
+					}
+
+					return *mObj;
+				}
+
+					/// Extract an object from the archive, and assignes the pointer to it.
+					/// This function can be used to load objects whose class is not
+					/// known in advance (anyway, assuming the class had been registered
+					/// with Chrono class factory registration). It _creates_ the object
+					/// of the proper downcasted class, and deserializes it.
+					/// Note: the object must be saved with ChStreamOutBinary::AbstractWrite()
+					/// Also, the AbstractWrite()-AbstractReadCreate() mechanism avoids
+					/// storing/creating multiple times the shared objects.
+					/// Supports only objects with Chrono RTTI and serializer member StreamIN().
+		template<class t>
+		t*   AbstractReadAllCreate(t** mObj)
+					{
+						std::string cls_name;
+						*mObj = NULL;
+
+						// 1) Read name of class (chrono RTTI type id)
+						*this >> cls_name;
+
+						if (cls_name!="NULL")
+						{
+							// 2) Dynamically create using class factory
+							create( cls_name, mObj );
+
+							if ( (*mObj)!=NULL)
+							{
+								objects_pointers.push_back(*mObj);
+								// 3) Deserialize
+								(*mObj)->StreamINall(*this);
+								//*this >> **mObj;
+							}
+							else
+							{
+								throw (ChException("Stream cannot create object"));
+							}
+						}
+						else
+						{
+							int pos=0;
+							// 2b) Was a shared object: just get the pointer to already-retrieved
+							*this >> pos;
+
+							*mObj=static_cast<t*>(objects_pointers[pos]);
+						}
+
+						return *mObj;
+					}
+
+
+				/// Some objects may write class version at the beginning
+				/// of the streamed data, they can use this function to read class from stream.
+	int VersionRead();
+
+};
+
+
+
+///
+/// This is a base class for typical output on system's file,
+/// on a disk, using the typical C++ 'fstream' handler.
+///
+
+class ChApi ChStreamFile
+{
+private:
+				/// Handler to a C++ file
+	std::fstream file;
+				/// The file name
+	char name[180];
+
+public:
+
+				/// Creates a system file, like the C++ fstream, and opens it,
+				/// given filename on disk, and the opening mode (ex: std::ios::out or
+				/// std::ios::in)
+	ChStreamFile(const char* filename, std::ios::openmode mmode);
+
+				/// Destruction means that the file stream is also closed.
+	virtual ~ChStreamFile();
+
+				/// Writes to file, up to n chars.
+				/// If does not succeed, throws exception.
+	virtual void	Write(const char* data, int n);
+
+				/// Reads from file, up to n chars.
+				/// If does not succeed, throws exception.
+	virtual void	Read(char* data, int n);
+
+				/// Returns true if end of stream reached.
+	virtual bool End_of_stream() { return file.eof();};
+
+				/// Reference to fstream encapsulated here.
+	std::fstream& GetFstream() { return file;}
+};
+
+
+
+///
+/// This is a wrapper for already-opened std::ostream 
+/// output streams (like std::cout or similar)
+///
+
+class ChApi ChStreamOstreamWrapper
+{
+private:
+				/// Handler to a C++ file
+	std::ostream* afile;
+
+public:
+				/// Creates a wrapper for an already existing, already opened,
+				/// ostream, given the pointer to that ostream.
+	ChStreamOstreamWrapper(std::ostream* mfile);
+
+				/// Deleting this stream wrapper does not delete nor closes
+				/// the wrapped ostream!
+	virtual ~ChStreamOstreamWrapper();
+
+				/// Writes raw data to file, up to n chars.
+				/// If does not succeed, throws exception.
+	virtual void	Write(const char* data, int n);
+
+				/// Returns true if end of stream reached.
+	virtual bool End_of_stream() { return afile->eof();};
+	
+				/// Reference to ostream encapsulated here.
+	std::ostream* GetOstream() { return afile;}
+};
+
+///
+/// This is a wrapper for already-opened std::istream 
+/// input streams 
+///
+
+class ChApi ChStreamIstreamWrapper
+{
+private:
+				/// Handler to a C++ stream
+	std::istream* afile;
+
+public:
+				/// Creates a wrapper for an already existing, already opened,
+				/// istream, given the pointer to that istream.
+	ChStreamIstreamWrapper(std::istream* mfile);
+
+				/// Deleting this stream wrapper does not delete nor closes
+				/// the wrapped istream!
+	virtual ~ChStreamIstreamWrapper();
+
+				/// Reads from stream, up to n chars.
+				/// If does not succeed, throws exception.
+	virtual void	Read(char* data, int n);
+
+				/// Returns true if end of stream reached.
+	virtual bool End_of_stream() { return afile->eof();};
+
+				/// Reference to istream encapsulated here.
+	std::istream* GetIstream() { return afile;}
+};
+
+
+
+///
+/// This is a wrapper for a std::vector<char> (buffer of chars)
+///
+
+class ChApi ChStreamVectorWrapper
+{
+private:
+				/// Handler to a C++ stream
+	std::vector<char>* vbuffer;
+	int pos;
+
+public:
+				/// Creates a wrapper for an already existing std::vector<char>,
+				/// given the pointer to that vector.
+	ChStreamVectorWrapper(std::vector<char>* mchars);
+
+				/// Deleting this wrapper does not delete nor closes
+				/// the wrapped buffer!
+	virtual ~ChStreamVectorWrapper();
+
+				/// Reads from vector, up to n chars.
+				/// If does not succeed, throws exception.
+	virtual void	Read(char* data, int n);
+
+				/// Writes raw data to vector, up to n chars.
+				/// If does not succeed, throws exception.
+	virtual void	Write(const char* data, int n);
+
+				/// Returns true if end of stream (end of vector) reached.
+	virtual bool End_of_stream();
+
+				/// Direct reference to std::vector<char> encapsulated here.
+	std::vector<char>* GetVector() { return vbuffer;}
+
+				/// Rewind read position to char number (0= beginning). 
+				/// Write position is always at the end (append).
+	void Seek(int position) { pos = position;}
+};
+
+
+
+
+
+///
+/// This is a specialized class for BINARY output to wrapped std::ostream,
+///
+
+class ChApi ChStreamOutBinaryStream : public ChStreamOstreamWrapper , public ChStreamOutBinary
+{
+public:
+	ChStreamOutBinaryStream(std::ostream* mfile)  : ChStreamOstreamWrapper(mfile), ChStreamOutBinary() {};
+	virtual ~ChStreamOutBinaryStream() {};
+
+	virtual bool End_of_stream() { return ChStreamOstreamWrapper::End_of_stream(); }
+private:
+	virtual void Output(const char* data, int n) { ChStreamOstreamWrapper::Write(data, n); }
+};
+
+///
+/// This is a specialized class for BINARY input from wrapped std::istream,
+///
+
+class ChApi ChStreamInBinaryStream : public ChStreamIstreamWrapper , public ChStreamInBinary
+{
+public:
+	ChStreamInBinaryStream(std::istream* mfile)  : ChStreamIstreamWrapper(mfile), ChStreamInBinary() {};
+	virtual ~ChStreamInBinaryStream() {};
+
+	virtual bool End_of_stream() { return ChStreamIstreamWrapper::End_of_stream(); }
+private:
+	virtual void Input(char* data, int n) { ChStreamIstreamWrapper::Read(data, n); }
+};
+
+
+///
+/// This is a specialized class for BINARY output to wrapped std::vector<char>,
+///
+
+class ChApi ChStreamOutBinaryVector : public ChStreamVectorWrapper , public ChStreamOutBinary
+{
+public:
+	ChStreamOutBinaryVector(std::vector<char>* mchars)  : ChStreamVectorWrapper(mchars), ChStreamOutBinary() {};
+	virtual ~ChStreamOutBinaryVector() {};
+
+	virtual bool End_of_stream() { return ChStreamVectorWrapper::End_of_stream(); }
+private:
+	virtual void Output(const char* data, int n) { ChStreamVectorWrapper::Write(data, n); }
+};
+
+///
+/// This is a specialized class for BINARY input from wrapped std::vector<char>,
+///
+
+class ChApi ChStreamInBinaryVector : public ChStreamVectorWrapper , public ChStreamInBinary
+{
+public:
+	ChStreamInBinaryVector(std::vector<char>* mchars)  : ChStreamVectorWrapper(mchars), ChStreamInBinary() {};
+	virtual ~ChStreamInBinaryVector() {};
+
+	virtual bool End_of_stream() { return ChStreamVectorWrapper::End_of_stream(); }
+private:
+	virtual void Input(char* data, int n) { ChStreamVectorWrapper::Read(data, n); }
+};
+
+
+
+
+///
+/// This is a specialized class for BINARY output on system's file,
+///
+
+class ChApi ChStreamOutBinaryFile : public ChStreamFile , public ChStreamOutBinary
+{
+public:
+	ChStreamOutBinaryFile(const char* filename, std::ios::openmode mmode = std::ios::trunc); // trunc or app
+	virtual ~ChStreamOutBinaryFile();
+
+private:
+	virtual void Output(const char* data, int n) { ChStreamFile::Write(data, n); }
+};
+
+///
+/// This is a specialized class for ASCII output on system's file,
+///
+
+class ChApi ChStreamOutAsciiFile : public ChStreamFile , public ChStreamOutAscii
+{
+public:
+	ChStreamOutAsciiFile(const char* filename, std::ios::openmode mmode = std::ios::trunc); // trunc or app);
+	virtual ~ChStreamOutAsciiFile();
+
+private:
+	virtual void Output(const char* data, int n) { ChStreamFile::Write(data, n); }
+};
+
+
+///
+/// This is a specialized class for BINARY input on system's file,
+///
+
+class ChApi ChStreamInBinaryFile : public ChStreamFile , public ChStreamInBinary
+{
+public:
+	ChStreamInBinaryFile(const char* filename);
+	virtual ~ChStreamInBinaryFile();
+
+	virtual bool End_of_stream() { return ChStreamFile::End_of_stream(); }
+private:
+	virtual void Input(char* data, int n) { ChStreamFile::Read(data, n); }
+};
+
+///
+/// This is a specialized class for ASCII input on system's file,
+///
+
+class ChApi ChStreamInAsciiFile : public ChStreamFile , public ChStreamInAscii
+{
+public:
+	ChStreamInAsciiFile(const char* filename);
+	virtual ~ChStreamInAsciiFile();
+
+	virtual bool End_of_stream() { return ChStreamFile::End_of_stream(); }
+private:
+	virtual void Input(char* data, int n) { ChStreamFile::Read(data, n); }
+};
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/core/ChTimer.h b/SRC/ChronoEngine/core/ChTimer.h
new file mode 100644
index 0000000..94afd5d
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChTimer.h
@@ -0,0 +1,168 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTIMER_H
+#define CHTIMER_H
+
+//////////////////////////////////////////////////
+//
+//   ChTimer.h
+//
+//   Class for high-resolution timer.
+//   This class can be used to get the execution time of
+//   fast algorithms, for example for profiling.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#if (((defined WIN32)|| (defined WIN64)) && !(defined(__MINGW32__) || defined(__CYGWIN__)))
+#include <time.h>
+# ifndef NOMINMAX
+#  define NOMINMAX
+# endif
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# include <time.h>
+# undef WIN32_LEAN_AND_MEAN
+# undef NOMINMAX
+#else
+# include<sys/time.h>
+#endif
+
+
+
+
+namespace chrono
+{
+
+
+/// Class for high-resolution timer.
+/// This class can be used to get the execution time of
+/// fast algorithms, for example for profiling.
+///
+/// Based on http://www-106.ibm.com/developerworks/library/l-rt1/
+/// and on the timer of the OpenTissue project ( (C) J.Sporring, K.Erleben)
+///
+/// How to use it:
+///
+///  ChTimer<double> timer;
+///
+///  timer.start();
+///  ...
+///  timer.stop();
+///  GetLog() << "It took " << timer() << " seconds to perform" << std::endl;
+///
+
+template<typename real_type>
+class ChTimer
+{
+
+#if (((defined WIN32)|| (defined WIN64))  && !(defined(__MINGW32__) || defined(__CYGWIN__)))
+
+  private:
+    LARGE_INTEGER m_start;
+    LARGE_INTEGER m_end;
+    LARGE_INTEGER m_freq;
+    bool m_first;
+  public:
+
+    ChTimer():m_first(true){}
+  public:
+
+				/// Start the timer
+    void start()
+    {
+      if(m_first)
+      {
+        QueryPerformanceFrequency(&m_freq);
+        m_first = false;
+      }
+      QueryPerformanceCounter(&m_start);
+    }
+
+				/// Stops the timer
+    void stop()
+    {
+      QueryPerformanceCounter(&m_end);
+    }
+				/// Get the timer value, with the () operator.
+    real_type operator()()const
+    {
+      real_type end = static_cast<real_type>(m_end.QuadPart);
+      real_type start = static_cast<real_type>(m_start.QuadPart);
+      real_type freq = static_cast<real_type>(m_freq.QuadPart);
+      return (end - start)/ freq;
+    }
+/*
+  // Simple version with 10ms precision max
+  private:
+    clock_t m_start;
+    clock_t m_end;
+  public:
+				/// Start the timer
+    void start() { m_start = clock();}
+
+				/// Stops the timer
+    void stop()  { m_end = clock(); }
+
+				/// Get the timer value, with the () operator. Wind-up after 72 min.
+    real_type operator()()const
+    {
+      real_type t1 =  static_cast<real_type>(m_start)/(static_cast<real_type>(CLOCKS_PER_SEC));
+      real_type t2 =  static_cast<real_type>(m_end)/(static_cast<real_type>(CLOCKS_PER_SEC));
+      return t2-t1;
+    }
+*/
+#else
+
+  private:
+    struct timeval m_start;
+    struct timeval m_end;
+    #ifdef SGI
+     time_t			 m_tz;
+	#else
+     struct	timezone m_tz;
+	#endif
+  public:
+				/// Start the timer
+    void start() { gettimeofday(&m_start, &m_tz); }
+
+				/// Stops the timer
+    void stop()  { gettimeofday(&m_end,   &m_tz); }
+
+				/// Get the timer value, with the () operator.
+    real_type operator()()const
+    {
+      real_type t1 =  static_cast<real_type>(m_start.tv_sec) + static_cast<real_type>(m_start.tv_usec)/(1000*1000);
+      real_type t2 =  static_cast<real_type>(m_end.tv_sec) + static_cast<real_type>(m_end.tv_usec)/(1000*1000);
+      return t2-t1;
+    }
+
+#endif
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChTimer.h
diff --git a/SRC/ChronoEngine/core/ChTransform.h b/SRC/ChronoEngine/core/ChTransform.h
new file mode 100644
index 0000000..8e69f8d
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChTransform.h
@@ -0,0 +1,175 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2005, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTRANSFORM_H
+#define CHTRANSFORM_H
+
+//////////////////////////////////////////////////
+//
+//   ChTransform.h
+//
+//   Math functions for coordinate transformations
+//   (translation and rotation).
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "core/ChVector.h"
+#include "core/ChQuaternion.h"
+#include "core/ChMatrix.h"
+
+namespace chrono {
+
+/// ChTransform: a class for fast coordinate transformations
+/// in 3D space.
+///
+///  A coordinate system (a 'frame') has a translation and
+/// a rotation respect to a 'parent' coordinate system,
+/// usually the absolute (world) coordinates.
+///  This class implements useful static functions
+/// to perform the typical local->parent or parent->local
+/// transformations of points. Such functions are static,
+/// so you don't even need to instantiate a ChTransform object,
+/// you can just call functions in this way:
+///   ChTransform<>::SomeFunction(..)
+///
+
+template <class Real = double>
+class ChTransform {
+  public:
+    //
+    // STATIC FUNCTIONS
+    //
+
+    // TRANSFORMATIONS, USING POSITION AND ROTATION MATRIX [A]
+
+    /// This function transforms a point from the parent coordinate
+    /// system to a local coordinate system, whose relative position
+    /// is given by the 'origin' translation and 'alignment' rotation matrix.
+    ///  Since the function is static, you do not need a ChTransform object, for example
+    /// use it as: mresult=ChTransform<>::TransformParentToLocal(mpar, morig, malign)
+    ///  This function is optimised for fast execution.
+    /// \return The point in local coordinate, as local=[A]'*(parent-origin)
+
+    static ChVector<Real> TransformParentToLocal(
+        const ChVector<Real>& parent,  ///< point to transform, given in parent coordinates;
+        const ChVector<Real>&
+            origin,  ///< location of local frame with respect to parent, expressed in parent ref frame;
+        const ChMatrix33<Real>&
+            alignment  ///< rotation of local frame with respect to parent, expressed in parent coords.
+        ) {
+        Real mx = parent.x - origin.x;
+        Real my = parent.y - origin.y;
+        Real mz = parent.z - origin.z;
+        return ChVector<Real>(((alignment.Get33Element(0, 0)) * mx) + ((alignment.Get33Element(1, 0)) * my) +
+                                  ((alignment.Get33Element(2, 0)) * mz),
+                              ((alignment.Get33Element(0, 1)) * mx) + ((alignment.Get33Element(1, 1)) * my) +
+                                  ((alignment.Get33Element(2, 1)) * mz),
+                              ((alignment.Get33Element(0, 2)) * mx) + ((alignment.Get33Element(1, 2)) * my) +
+                                  ((alignment.Get33Element(2, 2)) * mz));
+    }
+
+    /// This function transforms a point from the local reference
+    /// frame to the parent reference frame. The relative attitude of
+    /// the local reference frame with respect to the parent reference frame
+    /// is given by the 'origin' translation and the 'alignment' rotation matrix.
+    /// Since the function is static, you do not need a ChTransform object. For example,
+    /// use it as: mresult=ChTransform<>::TransformLocalToParent(mloc, morig, malign).
+    /// This function is optimized for fast execution.
+    /// \return The point in the parent reference frame, as parent=origin +[A]*(local)
+
+    static ChVector<Real> TransformLocalToParent(
+        const ChVector<Real>& local,       ///< point to transform, given in local coordinates
+        const ChVector<Real>& origin,      ///< origin of frame respect to parent, in parent coords,
+        const ChMatrix33<Real>& alignment  ///< rotation of frame respect to parent, in parent coords.
+        ) {
+        return ChVector<Real>(((alignment.Get33Element(0, 0)) * local.x) + ((alignment.Get33Element(0, 1)) * local.y) +
+                                  ((alignment.Get33Element(0, 2)) * local.z) + origin.x,
+                              ((alignment.Get33Element(1, 0)) * local.x) + ((alignment.Get33Element(1, 1)) * local.y) +
+                                  ((alignment.Get33Element(1, 2)) * local.z) + origin.y,
+                              ((alignment.Get33Element(2, 0)) * local.x) + ((alignment.Get33Element(2, 1)) * local.y) +
+                                  ((alignment.Get33Element(2, 2)) * local.z) + origin.z);
+    }
+
+    // TRANSFORMATIONS, USING POSITION AND ROTATION QUATERNION
+
+    /// This function transforms a point from the parent coordinate
+    /// system to a local coordinate system, whose relative position
+    /// is given by the 'origin' translation and 'alignment' quaternion q.
+    ///  Since the function is static, you do not need a ChTransform object, for example
+    /// use it as: mresult=ChTransform<>::TransformParentToLocal(mpar, morig, malign)
+    /// \return The point in local coordinate, as local=q*[(parent-origin)]*q
+
+    static ChVector<Real> TransformParentToLocal(
+        const ChVector<Real>& parent,        ///< point to transform, given in parent coordinates
+        const ChVector<Real>& origin,        ///< origin of frame respect to parent, in parent coords,
+        const ChQuaternion<Real>& alignment  ///< rotation of frame respect to parent, in parent coords.
+        ) {
+        // It could be simply "return alignment.RotateBack(parent-origin);"
+        // but for faster execution do this:
+        Real e0e0 = alignment.e0 * alignment.e0;
+        Real e1e1 = alignment.e1 * alignment.e1;
+        Real e2e2 = alignment.e2 * alignment.e2;
+        Real e3e3 = alignment.e3 * alignment.e3;
+        Real e0e1 = -alignment.e0 * alignment.e1;
+        Real e0e2 = -alignment.e0 * alignment.e2;
+        Real e0e3 = -alignment.e0 * alignment.e3;
+        Real e1e2 = alignment.e1 * alignment.e2;
+        Real e1e3 = alignment.e1 * alignment.e3;
+        Real e2e3 = alignment.e2 * alignment.e3;
+        Real dx = parent.x - origin.x;
+        Real dy = parent.y - origin.y;
+        Real dz = parent.z - origin.z;
+        return ChVector<Real>(((e0e0 + e1e1) * 2. - 1.) * dx + ((e1e2 - e0e3) * 2.) * dy + ((e1e3 + e0e2) * 2.) * dz,
+                              ((e1e2 + e0e3) * 2.) * dx + ((e0e0 + e2e2) * 2. - 1.) * dy + ((e2e3 - e0e1) * 2.) * dz,
+                              ((e1e3 - e0e2) * 2.) * dx + ((e2e3 + e0e1) * 2.) * dy + ((e0e0 + e3e3) * 2. - 1.) * dz);
+    }
+
+    /// This function transforms a point from the local coordinate
+    /// system to the parent coordinate system. Relative position of local respect
+    /// to parent is given by the 'origin' translation and 'alignment' quaternion rotation.
+    ///  Since the function is static, you do not need a ChTransform object, for example
+    /// use it as: mresult=ChTransform<>::TransformLocalToParent(mloc, morig, malign)
+    /// \return The point in parent coordinate, as parent=origin +q'*(local)*q
+
+    static ChVector<Real> TransformLocalToParent(
+        const ChVector<Real>& local,         ///< point to transform, given in local coordinates
+        const ChVector<Real>& origin,        ///< origin of frame respect to parent, in parent coords,
+        const ChQuaternion<Real>& alignment  ///< rotation of frame respect to parent, in parent coords.
+        ) {
+        // It could be simply: "return origin+alignment.Rotate(local);"
+        // but for faster execution, do this:
+        Real e0e0 = alignment.e0 * alignment.e0;
+        Real e1e1 = alignment.e1 * alignment.e1;
+        Real e2e2 = alignment.e2 * alignment.e2;
+        Real e3e3 = alignment.e3 * alignment.e3;
+        Real e0e1 = alignment.e0 * alignment.e1;
+        Real e0e2 = alignment.e0 * alignment.e2;
+        Real e0e3 = alignment.e0 * alignment.e3;
+        Real e1e2 = alignment.e1 * alignment.e2;
+        Real e1e3 = alignment.e1 * alignment.e3;
+        Real e2e3 = alignment.e2 * alignment.e3;
+        return ChVector<Real>(origin.x + ((e0e0 + e1e1) * 2. - 1.) * local.x + ((e1e2 - e0e3) * 2.) * local.y +
+                                  ((e1e3 + e0e2) * 2.) * local.z,
+                              origin.y + ((e1e2 + e0e3) * 2.) * local.x + ((e0e0 + e2e2) * 2. - 1.) * local.y +
+                                  ((e2e3 - e0e1) * 2.) * local.z,
+                              origin.z + ((e1e3 - e0e2) * 2.) * local.x + ((e2e3 + e0e1) * 2.) * local.y +
+                                  ((e0e0 + e3e3) * 2. - 1.) * local.z);
+    }
+};
+
+}  // END_OF_NAMESPACE____
+
+#endif  // END of ChTransform.h
diff --git a/SRC/ChronoEngine/core/ChTrasform.h b/SRC/ChronoEngine/core/ChTrasform.h
new file mode 100644
index 0000000..1f0fe6e
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChTrasform.h
@@ -0,0 +1,206 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 1996, 2005, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTRASFORM_H
+#define CHTRASFORM_H
+
+//////////////////////////////////////////////////
+//
+//   ChTrasform.h
+//
+//   Math functions for coordinate transformations
+//   (translation and rotation).
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChVector.h"
+#include "core/ChQuaternion.h"
+#include "core/ChMatrix.h"
+
+
+namespace chrono
+{
+
+
+
+
+/// ChTrasform: a class for fast coordinate trasformations
+/// in 3D space.
+///
+///  A coordinate system (a 'frame') has a translation and
+/// a rotation respect to a 'parent' coordinate system,
+/// usually the absolute (world) coordinates.
+///  This class implements useful static functions
+/// to perform the typical local->parent or parent->local
+/// transformations of points. Such functions are static,
+/// so you don't even need to instantiate a ChTrasform object,
+/// you can just call functions in this way:
+///   ChTrasform<>::SomeFunction(..)
+///
+
+template <class Real = double>
+class ChTrasform
+{
+public:
+
+			//
+			// STATIC FUNCTIONS
+			//
+
+				// TRANSFORMATIONS, USING POSITION AND ROTATION MATRIX [A]
+
+					/// This function transforms a point from the parent coordinate
+					/// system to a local coordinate system, whose relative position
+					/// is given by the 'origin' translation and 'alignment' rotation matrix.
+					///  Since the function is static, you do not need a ChTrasform object, for example
+					/// use it as: mresult=ChTrasform<>::TrasformParentToLocal(mpar, morig, malign)
+					///  This function is optimised for fast execution.
+					/// \return The point in local coordinate, as local=[A]'*(parent-origin)
+
+	static ChVector<Real> TrasformParentToLocal (
+								const ChVector<Real>& parent,	///< point to transform, given in parent coordinates
+								const ChVector<Real>& origin,	///< origin of frame respect to parent, in parent coords,
+								const ChMatrix33<Real>& alignment	///< rotation of frame respect to parent, in parent coords.
+								)
+						{
+							Real mx = parent.x-origin.x;
+							Real my = parent.y-origin.y;
+							Real mz = parent.z-origin.z;
+							return ChVector<Real> (
+										(( alignment.Get33Element(0,0))*mx)+
+										(( alignment.Get33Element(1,0))*my)+
+										(( alignment.Get33Element(2,0))*mz),
+										(( alignment.Get33Element(0,1))*mx)+
+										(( alignment.Get33Element(1,1))*my)+
+										(( alignment.Get33Element(2,1))*mz),
+										(( alignment.Get33Element(0,2))*mx)+
+										(( alignment.Get33Element(1,2))*my)+
+										(( alignment.Get33Element(2,2))*mz) );
+						}
+
+					/// This function transforms a point from the local coordinate
+					/// system to the parent coordinate system. Relative position of local respect
+					/// to parent is given by the 'origin' translation and 'alignment' rotation matrix.
+					///  Since the function is static, you do not need a ChTrasform object, for example
+					/// use it as: mresult=ChTrasform<>::TrasformLocalToParent(mloc, morig, malign)
+					///  This function is optimised for fast execution.
+					/// \return The point in parent coordinate, as parent=origin +[A]*(local)
+
+	static ChVector<Real> TrasformLocalToParent (
+								const ChVector<Real>& local,	///< point to transform, given in local coordinates
+								const ChVector<Real>& origin,	///< origin of frame respect to parent, in parent coords,
+								const ChMatrix33<Real>& alignment	///< rotation of frame respect to parent, in parent coords.
+								)
+						{
+							return ChVector<Real> (
+										(( alignment.Get33Element(0,0))*local.x)+
+										(( alignment.Get33Element(0,1))*local.y)+
+										(( alignment.Get33Element(0,2))*local.z) + origin.x,
+										(( alignment.Get33Element(1,0))*local.x)+
+										(( alignment.Get33Element(1,1))*local.y)+
+										(( alignment.Get33Element(1,2))*local.z) + origin.y,
+										(( alignment.Get33Element(2,0))*local.x)+
+										(( alignment.Get33Element(2,1))*local.y)+
+										(( alignment.Get33Element(2,2))*local.z) + origin.z);
+						}
+
+
+
+				// TRANSFORMATIONS, USING POSITION AND ROTATION QUATERNION
+
+					/// This function transforms a point from the parent coordinate
+					/// system to a local coordinate system, whose relative position
+					/// is given by the 'origin' translation and 'alignment' quaternion q.
+					///  Since the function is static, you do not need a ChTrasform object, for example
+					/// use it as: mresult=ChTrasform<>::TrasformParentToLocal(mpar, morig, malign)
+					/// \return The point in local coordinate, as local=q*[(parent-origin)]*q
+
+	static ChVector<Real> TrasformParentToLocal (
+								const ChVector<Real>& parent,		///< point to transform, given in parent coordinates
+								const ChVector<Real>& origin,		///< origin of frame respect to parent, in parent coords,
+								const ChQuaternion<Real>& alignment	///< rotation of frame respect to parent, in parent coords.
+								)
+						{
+
+							// It could be simply "return alignment.RotateBack(parent-origin);"
+							// but for faster execution do this:
+							Real e0e0 = alignment.e0 * alignment.e0;
+							Real e1e1 = alignment.e1 * alignment.e1;
+							Real e2e2 = alignment.e2 * alignment.e2;
+							Real e3e3 = alignment.e3 * alignment.e3;
+							Real e0e1 = - alignment.e0 * alignment.e1;
+							Real e0e2 = - alignment.e0 * alignment.e2;
+							Real e0e3 = - alignment.e0 * alignment.e3;
+							Real e1e2 = alignment.e1 * alignment.e2;
+							Real e1e3 = alignment.e1 * alignment.e3;
+							Real e2e3 = alignment.e2 * alignment.e3;
+							Real dx = parent.x - origin.x;
+							Real dy = parent.y - origin.y;
+							Real dz = parent.z - origin.z;
+							return ChVector<Real> (
+							 ((e0e0 + e1e1)*2. - 1.)*dx + ((e1e2 - e0e3)*2. )*dy + ((e1e3 + e0e2)*2. )*dz ,
+							 ((e1e2 + e0e3)*2. )*dx + ((e0e0 + e2e2)*2. - 1.)*dy + ((e2e3 - e0e1)*2. )*dz ,
+							 ((e1e3 - e0e2)*2. )*dx + ((e2e3 + e0e1)*2. )*dy + ((e0e0 + e3e3)*2. - 1.)*dz  );
+						}
+
+
+					/// This function transforms a point from the local coordinate
+					/// system to the parent coordinate system. Relative position of local respect
+					/// to parent is given by the 'origin' translation and 'alignment' quaternion rotation.
+					///  Since the function is static, you do not need a ChTrasform object, for example
+					/// use it as: mresult=ChTrasform<>::TrasformLocalToParent(mloc, morig, malign)
+					/// \return The point in parent coordinate, as parent=origin +q'*(local)*q
+
+	static ChVector<Real> TrasformLocalToParent (
+								const ChVector<Real>& local,		///< point to transform, given in local coordinates
+								const ChVector<Real>& origin,		///< origin of frame respect to parent, in parent coords,
+								const ChQuaternion<Real>& alignment	///< rotation of frame respect to parent, in parent coords.
+								)
+						{
+							// It could be simply: "return origin+alignment.Rotate(local);"
+							// but for faster execution, do this:
+							Real e0e0 = alignment.e0 * alignment.e0;
+							Real e1e1 = alignment.e1 * alignment.e1;
+							Real e2e2 = alignment.e2 * alignment.e2;
+							Real e3e3 = alignment.e3 * alignment.e3;
+							Real e0e1 = alignment.e0 * alignment.e1;
+							Real e0e2 = alignment.e0 * alignment.e2;
+							Real e0e3 = alignment.e0 * alignment.e3;
+							Real e1e2 = alignment.e1 * alignment.e2;
+							Real e1e3 = alignment.e1 * alignment.e3;
+							Real e2e3 = alignment.e2 * alignment.e3;
+							return ChVector<Real> (
+							 origin.x + ((e0e0 + e1e1)*2. - 1.)*local.x + ((e1e2 - e0e3)*2. )*local.y + ((e1e3 + e0e2)*2. )*local.z ,
+							 origin.y + ((e1e2 + e0e3)*2. )*local.x + ((e0e0 + e2e2)*2. - 1.)*local.y + ((e2e3 - e0e1)*2. )*local.z ,
+							 origin.z + ((e1e3 - e0e2)*2. )*local.x + ((e2e3 + e0e1)*2. )*local.y + ((e0e0 + e3e3)*2. - 1.)*local.z  );
+						}
+
+
+};
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChTrasform.h
diff --git a/SRC/ChronoEngine/core/ChVector.cpp b/SRC/ChronoEngine/core/ChVector.cpp
new file mode 100644
index 0000000..e070dde
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChVector.cpp
@@ -0,0 +1,56 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+// 
+//   ChVector.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+   
+
+#include <math.h>
+ 
+    
+#include "core/ChVector.h"
+ 
+      
+namespace chrono 
+{ 
+      
+    
+   
+
+////////////////////////////////////////////////////////////
+//  VECTOR OPERATIONS
+
+ 
+
+
+
+ 
+
+
+ 
+
+ 
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+//////// 
+
diff --git a/SRC/ChronoEngine/core/ChVector.h b/SRC/ChronoEngine/core/ChVector.h
new file mode 100644
index 0000000..13cc240
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChVector.h
@@ -0,0 +1,607 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHVECTOR_H
+#define CHVECTOR_H
+
+//////////////////////////////////////////////////
+//
+//   ChVector.h
+//
+//   Math functions for :
+//      - VECTORS
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include <iostream>
+#include <iomanip>
+
+#include "core/ChMathematics.h"
+#include "core/ChClassRegister.h"
+#include "core/ChStream.h"
+
+
+/// This is the namespace for most functions of the Chrono library
+namespace chrono
+{
+
+
+
+///
+/// VECTOR:	a class for general purpose 3d vectorial variables, such as
+/// points in 3D. It implements the vectorisl algebra in 3D (Gibbs products).
+///
+///  The vector object comes either with the template "ChVector<type>" mode,
+/// either in the 'shortcut' flavour, that is "Vector", which assumes
+/// the type of x,y,z is double precision, so it is faster to type.
+///  For example, for a declaration, you can write "ChVector<double> foo;",
+/// as well as "Vector foo;" (less typing effort for the second..)
+///
+
+//
+// CONSTANTS
+//
+// Added this here as code was not compiling (under linux at least)- Hammad
+#define VNULL  ChVector<double> (0.,0.,0.)
+#define VECT_X ChVector<double> (1.,0.,0.)
+#define VECT_Y ChVector<double> (0.,1.,0.)
+#define VECT_Z ChVector<double> (0.,0.,1.)
+
+template <class Real = double>
+class ChVector
+{
+
+public:
+			//
+			// DATA
+			//
+	Real x;
+	Real y;
+	Real z;
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChVector(): x(0), y(0), z(0) {};
+	ChVector(const Real nx, const Real ny, const Real nz) : x(nx), y(ny), z(nz) {};
+	ChVector(const Real n) : x(n), y(n), z(n) {}; //initialize to a constant
+
+					/// Copy constructor
+	ChVector(const ChVector<Real>& other)	:x(other.x), y(other.y), z(other.z) {};
+
+					/// Copy constructor between vectors float<->double etc
+	template <class RealB>
+	ChVector(const ChVector<RealB>& other)	:x((Real)other.x), y((Real)other.y), z((Real)other.z) {}
+
+			//
+			// OPERATORS OVERLOADING
+			//
+			// Note: c++ automatically creates temporary objects to store intermediate
+			// results in long formulas, such as a= b*c*d, so the usage of operators
+			// may give slower results than a wise (less readable however) usage of
+			// Dot(), Cross() etc.. Also pay attention to C++ operator precedence rules!
+
+					/// Assignment operator: copy from another vector
+	ChVector<Real>& operator=(const ChVector<Real>& other)	{if (&other == this) return *this;  x = other.x; y = other.y; z = other.z; return *this; }
+
+	template <class RealB>
+	ChVector<Real>& operator=(const ChVector<RealB>& other)	{ x = (Real)other.x; y = (Real)other.y; z = (Real)other.z; return *this; }
+
+					/// Operator for sign change
+	ChVector<Real> operator-() const { return ChVector<Real>(-x, -y, -z);   }
+
+					/// Operator for indexed access (0=x, 1=y, 2=z). Not so much performance..may be useful sometimes..
+	inline Real& operator()(const int el)
+						{	assert (el<3 && el>=0);
+							if(el==0) return x; else if(el==1) return y; return z;
+						};
+	inline const Real& operator()(const int el) const
+						{	assert (el<3 && el>=0);
+							if(el==0) return x; else if(el==1) return y; return z;
+						};
+
+					/// Operator for vector sum
+	ChVector<Real> operator+(const ChVector<Real>& other) const { return ChVector<Real>(x + other.x, y + other.y, z + other.z);	}
+	ChVector<Real>& operator+=(const ChVector<Real>& other)	{ x+=other.x; y+=other.y; z+=other.z; return *this; }
+
+					/// Operator for vector difference
+	ChVector<Real> operator-(const ChVector<Real>& other) const { return ChVector<Real>(x - other.x, y - other.y, z - other.z);	}
+	ChVector<Real>& operator-=(const ChVector<Real>& other)	{ x-=other.x; y-=other.y; z-=other.z; return *this; }
+
+					/// Operator for element-wise multiplication (note that
+					/// this is neither dot product nor cross product!)
+	ChVector<Real> operator*(const ChVector<Real>& other) const { return ChVector<Real>(x * other.x, y * other.y, z * other.z);	}
+	ChVector<Real>& operator*=(const ChVector<Real>& other)	{ x*=other.x; y*=other.y; z*=other.z; return *this; }
+
+					/// Operator for scaling the vector by a scalar value, as v*s
+	ChVector<Real> operator*(const Real v) const { return ChVector<Real>(x * v, y * v, z * v);	}
+	ChVector<Real>& operator*=(const Real v) { x*=v; y*=v; z*=v; return *this; }
+
+					/// Operator for element-wise division (note that
+					/// 3D vector algebra is a skew field, non-divisional algebra, so this
+					/// division operation is just an element-by element division)
+	ChVector<Real> operator/(const ChVector<Real>& other) const { return ChVector<Real>(x / other.x, y / other.y, z / other.z);	}
+	ChVector<Real>& operator/=(const ChVector<Real>& other)	{ x/=other.x; y/=other.y; z/=other.z; return *this; }
+
+					/// Operator for scaling the vector by inverse of a scalar value, as v/s
+	ChVector<Real> operator/(const Real v) const { Real i=(Real)1.0/v; return ChVector<Real>(x * i, y * i, z * i);	}
+	ChVector<Real>& operator/=(const Real v) { Real i=(Real)1.0/v; x*=i; y*=i; z*=i; return *this; }
+
+					/// Operator for cross product: A%B means the vector cross-product AxB
+					/// Note: pay attention to operator low precedence (see C++ precedence rules!)
+	ChVector<Real> operator%(const ChVector<Real>& other) const { ChVector<Real> mr; mr.Cross(*this, other); return mr;}
+	ChVector<Real>& operator%=(const ChVector<Real>& other) { this->Cross(*this, other); return *this;}
+
+					/// Operator for dot product: A^B means the scalar dot-product A*B
+					/// Note: pay attention to operator low precedence (see C++ precedence rules!)
+	double operator^(const ChVector<Real>& other) const { return Dot(*this, other);}
+
+	bool operator<=(const ChVector<Real>&other) const { return x<=other.x && y<=other.y && z<=other.z;};
+	bool operator>=(const ChVector<Real>&other) const { return x>=other.x && y>=other.y && z>=other.z;};
+	bool operator<(const ChVector<Real>&other) const { return x<other.x && y<other.y && z<other.z;};
+	bool operator>(const ChVector<Real>&other) const { return x>other.x && y>other.y && z>other.z;};
+
+	bool operator==(const ChVector<Real>& other) const { return other.x==x && other.y==y && other.z==z; }
+	bool operator!=(const ChVector<Real>& other) const { return other.x!=x || other.y!=y || other.z!=z; }
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+					/// Sets the three values of the vector at once
+	void Set(const Real nx, const Real ny, const Real nz) {x=nx; y=ny; z=nz; }
+
+					/// Sets the vector as a copy of another vector
+	void Set(const ChVector<Real>& p) { x=p.x; y=p.y; z=p.z;}
+
+					/// Sets the vector with three components as a sample scalar
+	void Set(const Real p) { x=p; y=p; z=p;}
+
+					/// Sets the vector as a null vector
+	void SetNull() { x=y=z=0;};
+
+					/// Returns true if vector is identical to other vector
+	bool	Equals ( const ChVector<Real>& other) const { return (other.x==x) && (other.y==y) && (other.z==z);}
+
+					/// Returns true if vector equals another vector, within a tolerance 'tol'
+	bool	Equals ( const ChVector<Real>& other, Real tol) const
+						{
+							return  (fabs(other.x-x)<tol) &&
+								    (fabs(other.y-y)<tol) &&
+									(fabs(other.z-z)<tol);
+						}
+
+					/// The vector becomes the sum of the two vectors A and B:
+					/// this=A+B
+	void 	Add    ( const ChVector<Real> A, const ChVector<Real> B)
+						{
+							x=A.x+B.x; y=A.y+B.y; z=A.z+B.z;
+						}
+
+					/// The vector becomes the difference of the two vectors A and B:
+					/// this=A-B
+	void 	Sub	   ( const ChVector<Real> A, const ChVector<Real> B)
+						{
+							x=A.x-B.x; y=A.y-B.y; z=A.z-B.z;
+						}
+
+					/// The vector becomes the cross product of the two vectors A and B:
+					/// this=AxB
+	void	Cross  ( const ChVector<Real> A, const ChVector<Real> B)
+						{
+							this->x= (A.y * B.z)-(A.z * B.y);
+							this->y= (A.z * B.x)-(A.x * B.z);
+							this->z= (A.x * B.y)-(A.y * B.x);
+						}
+
+					/// Gives the dot product of the two vectors A and B:
+	double  Dot   ( const ChVector<Real> A, const ChVector<Real> B) const
+						{
+							return (A.x * B.x)+(A.y * B.y)+(A.z * B.z);
+						};
+
+					/// Gives the dot product with another vector:
+					/// result=this*B
+	double  Dot   ( const ChVector<Real> B) const
+						{
+							return (x * B.x)+(y * B.y)+(z * B.z);
+						};
+
+
+					/// The vector becomes the product of a vectors A and a scalar v:
+					/// this=A*v
+	void 	Mul	   ( const ChVector<Real> A, const Real v)
+						{
+							x=A.x*v; y=A.y*v; z=A.z*v;
+						}
+
+					/// The vector is multiplied by a scalar factor 's'
+					/// this*=v
+	void    Scale (const Real v) { x*=v; y*=v; z*=v;}
+
+					/// Computes the euclidean norm of the vector,
+					/// that is its length or magnitude
+	double	Length	 () { return sqrt(x*x + y*y + z*z); }
+
+					/// Computes the euclidean norm of the vector, squared 
+					/// (i.e. as Length(), but skipping the square root)
+	double	Length2	 () { return (x*x + y*y + z*z); }
+
+					/// Computes the infinite norm of the vector, that
+					/// is the maximum absolute value of one of its elements
+	double	LengthInf () { return ChMax(ChMax(fabs(x),fabs(y)), fabs(z)); }
+
+					/// Normalize this vector, so that its euclidean length is 1.
+					/// Returns false if original vector had zero length (in such a case
+					/// it will be defaulted as VECT_X) otherwise returns true for success.
+	bool    Normalize ()
+						{
+							double mlenght = this->Length();
+							if (mlenght<CH_NANOTOL)
+							{
+								x=1; y=0; z=0;
+								return false;
+							}else
+							{
+								this->Scale(1.0/mlenght);
+							}
+							return true;
+						}
+					/// Return a normalized copy of this vector, with euclidean length =1.
+					/// Not to be confused with Normalize(), that normalizes in place.
+	ChVector<Real> GetNormalized() const
+						{
+							ChVector<Real> mret(*this);
+							mret.Normalize();
+							return mret;
+						}
+
+
+					/// Impose a new length to the vector, keeping the direction
+					/// unchanged.
+	void    SetLength (Real v)
+						{
+							Normalize();
+							Scale(v);
+						}
+
+
+					/// Use the Gram-Schmidt orthonormalization to find the three
+					/// orthogonal vectors of a coordinate system whose X axis is this vector.
+					/// mVsingular (optional) suggests the XY plane, possibly it is not too parallel to X.
+	void	DirToDxDyDz( ChVector<Real>* Vx,  
+						 ChVector<Real>* Vy, 
+						 ChVector<Real>* Vz,
+						 ChVector<Real>* mVsingular =0) const
+						{
+							ChVector<Real> mdefVsingular = VECT_Y;
+							ChVector<Real> mVnull = VNULL;
+							double mzlen;
+
+							if (this->Equals(mVnull))
+								*Vx = VECT_X;
+							else
+								*Vx = this->GetNormalized();
+							
+							if (!mVsingular)
+								mVsingular = &mdefVsingular;
+
+							*Vz = Vcross(*Vx, *mVsingular);
+							mzlen = Vlenght(*Vz);
+
+							if (mzlen < 0.0001) // was near singularity? change singularity reference vector!
+							{
+								if (fabs(mVsingular->z) < 0.9)	
+									*mVsingular = VECT_Z;
+								if (fabs(mVsingular->y) < 0.9)
+									*mVsingular = VECT_Y;
+								if (fabs(mVsingular->x) < 0.9)
+									*mVsingular = VECT_X;
+								*Vz = Vcross(*Vx, *mVsingular);
+								mzlen = Vlenght(*Vz);		// now should be nonzero length..
+							}
+							// normalize Vz
+							*Vz = Vmul(*Vz, 1.0/mzlen);
+							// compute Vy
+							*Vy = Vcross(*Vz,*Vx);
+						}
+
+
+			//
+			// STREAMING
+			//
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream)
+						{
+							mstream << "\n" << x << "\n" << y << "\n" << z << "\n";
+						}
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream)
+						{
+							mstream << x;
+							mstream << y;
+							mstream << z;
+						}
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream)
+						{
+							mstream >> x;
+							mstream >> y;
+							mstream >> z;
+						}
+};
+
+
+
+
+/// Shortcut for faster use of typical double-precision vectors.
+///  Instead of writing    ChVector<double> foo;   you can write
+///  the shorter version   Vector foo;
+///
+typedef ChVector<double> Vector;
+
+/// Shortcut for faster use of typical single-precision vectors.
+///
+typedef ChVector<float>  VectorF;
+
+
+
+
+// Reversed operators
+
+					/// Operator for scaling the vector by a scalar value, as v*s
+template <class Real>
+ChVector<Real> operator*(const double v, const ChVector<Real> V)
+		{ return ChVector<Real>(V.x * v, V.y * v, V.z * v);	}
+
+
+
+//
+// CONSTANTS
+//
+// Commented this and added #defines above as code was not compiling (under linux at least)- Hammad
+//static const ChVector<double> VNULL(0.,0.,0.);
+//static const ChVector<double> VECT_X(1.,0.,0.);
+//static const ChVector<double> VECT_Y(0.,1.,0.);
+//static const ChVector<double> VECT_Z(0.,0.,1.);
+
+
+//
+// STATIC VECTOR MATH OPERATIONS
+//
+//  These functions are here for people which prefer to use static
+// functions instead of ChVector class' member functions.
+// NOTE: sometimes a wise adoption of the following functions may
+// give faster results rather than using overloaded operators +/-/* in
+// the vector class.
+//  Also, these functions are here for backward compatibility with
+// old parts of Chrono code.
+//  For best readability of our code, it is suggested not to use
+// these functions - use the member functions or operators of
+// the ChVector class instead-.
+
+template <class RealA, class RealB>
+RealA	Vdot ( const ChVector<RealA> va, const ChVector<RealB> vb)
+{
+	return (RealA) ((va.x * vb.x)+(va.y * vb.y)+(va.z * vb.z));
+}
+
+template <class RealA>
+void Vset ( ChVector<RealA>* v, RealA mx, RealA my, RealA mz)
+{
+	v->x= mx;
+	v->y= my;
+	v->z= mz;
+}
+
+template <class RealA, class RealB>
+ChVector<RealA>	Vadd ( ChVector<RealA> va, ChVector<RealB> vb)
+{
+	ChVector<RealA> result;
+	result.x= va.x + vb.x;
+	result.y= va.y + vb.y;
+	result.z= va.z + vb.z;
+	return result;
+}
+
+template <class RealA, class RealB>
+ChVector<RealA>	Vsub ( ChVector<RealA> va, ChVector<RealB> vb)
+{
+	ChVector<RealA> result;
+	result.x= va.x - vb.x;
+	result.y= va.y - vb.y;
+	result.z= va.z - vb.z;
+	return result;
+}
+
+template <class RealA, class RealB>
+ChVector<RealA>	Vcross (ChVector<RealA> va, ChVector<RealB> vb)
+{
+	ChVector<RealA> result;
+	result.x= (va.y * vb.z)-(va.z * vb.y);
+	result.y= (va.z * vb.x)-(va.x * vb.z);
+	result.z= (va.x * vb.y)-(va.y * vb.x);
+	return result;
+}
+
+template <class RealA, class RealB>
+ChVector<RealA>	Vmul (ChVector<RealA> va, RealB fact)
+{
+	ChVector<RealA> result;
+	result.x= va.x * (RealA)fact;
+	result.y= va.y * (RealA)fact;
+	result.z= va.z * (RealA)fact;
+	return result;
+}
+
+template <class RealA>
+RealA	Vlenght	(ChVector<RealA> va)
+{
+	return (RealA)va.Length(); //(sqrt(pow(va.x, 2) + pow(va.y, 2) + pow(va.z, 2)));
+}
+
+template <class RealA>
+ChVector<RealA>	Vnorm	(ChVector<RealA> va)
+{
+	ChVector<RealA> result(va);
+	result.Normalize();
+	/*
+	double lenght_va;
+	double invlenght;
+
+	lenght_va= Vlenght(va);
+	if (lenght_va==0)
+	{
+		result.x=1;
+		result.y=0;
+		result.z=0;
+	} else
+	{	
+		invlenght = (1/lenght_va);
+		result= Vmul (va, invlenght);
+	}
+	*/
+	return result; 
+}
+
+template <class RealA, class RealB>
+bool  Vequal  (ChVector<RealA>* va, ChVector<RealB>* vb)
+{
+	return (va==vb);
+}
+
+template <class RealA>
+bool	Vnotnull  (ChVector<RealA>* va)
+{
+	if (va->x) return true;
+	if (va->y) return true;
+	if (va->z) return true;
+	return false;
+}
+
+// Gets the zenith angle of a unit vector respect to YZ plane  ***OBSOLETE
+template <class RealA>
+double	VangleYZplane (ChVector<RealA>* va)
+{
+	return asin (Vdot(*va, VECT_X));
+}
+
+// Gets the zenith angle of a unit vector respect to YZ plane  ***OBSOLETE
+template <class RealA>
+double	VangleYZplaneNorm (ChVector<RealA>* va)
+{
+	return acos (Vdot(*va, VECT_X));
+}
+
+// Gets the angle of the projection on the YZ plane respect to
+// the Y vector, as spinning about X.
+template <class RealA>
+double VangleRX (ChVector<RealA>* va)
+{
+	Vector vproj; 
+	vproj.x = 0;
+	vproj.y = va->y;
+	vproj.z = va->z;
+	vproj = Vnorm(vproj);
+	if (vproj.x == 1) return 0;
+	return acos (vproj.y);
+}
+
+// The reverse of the two previous functions, gets the vector
+// given the angle above the normal to YZ plane and the angle
+// of rotation on X
+template <class RealA>
+ChVector<RealA> VfromPolar (double norm_angle, double pol_angle)
+{
+	ChVector<> res;
+	double projlen;
+	res.x= cos (norm_angle);	// 1) rot 'norm.angle'about z
+	res.y= sin (norm_angle);
+	res.z= 0;
+	projlen = res.y;
+	res.y = projlen * cos(pol_angle);
+	res.z = projlen * sin(pol_angle);
+	return res;
+}
+
+			// From non normalized x direction, to versors DxDyDz.
+			// mVsingular (optional) sets normal to plane on which Dz must lie.
+template <class RealA>
+void	XdirToDxDyDz(ChVector<RealA>* mVxdir, 
+					 ChVector<RealA>* mVsingular, 
+					 ChVector<RealA>* Vx,  
+					 ChVector<RealA>* Vy, 
+					 ChVector<RealA>* Vz)
+{
+	ChVector<RealA> mdefVsingular;
+	ChVector<RealA> mVnull = VNULL;
+	double mzlen;
+
+	mdefVsingular = VECT_Y;
+
+	if (Vequal(mVxdir, &mVnull))
+		*Vx = VECT_X;
+	else
+		*Vx = Vnorm(*mVxdir);
+	
+	if (!mVsingular)
+		mVsingular = &mdefVsingular;
+
+	*Vz = Vcross(*Vx, *mVsingular);
+	mzlen = Vlenght(*Vz);
+
+	if (mzlen < 0.0001) // was near singularity? change singularity reference vector!
+	{
+		if (fabs(mVsingular->z) < 0.9)	
+			*mVsingular = VECT_Z;
+		if (fabs(mVsingular->y) < 0.9)
+			*mVsingular = VECT_Y;
+		if (fabs(mVsingular->x) < 0.9)
+			*mVsingular = VECT_X;
+		*Vz = Vcross(*Vx, *mVsingular);
+		mzlen = Vlenght(*Vz);		// now should be nonzero length..
+	}
+	// normalize Vz
+	*Vz = Vmul(*Vz, 1.0/mzlen);
+	// compute Vy
+	*Vy = Vcross(*Vz,*Vx);
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChVector.h
+
diff --git a/SRC/ChronoEngine/core/ChWrapHashmap.h b/SRC/ChronoEngine/core/ChWrapHashmap.h
new file mode 100644
index 0000000..ad2773b
--- /dev/null
+++ b/SRC/ChronoEngine/core/ChWrapHashmap.h
@@ -0,0 +1,49 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHWRAPHASHMAP_H
+#define CHWRAPHASHMAP_H
+
+//////////////////////////////////////////////////
+// 
+//   ChWrapHashmap.h
+//
+//   This header can be used to include the STL 
+//   hash_map implementation, in a compiler-independent
+//   way.
+//   In fact, an annoying thing is that some STL 
+//   distributions (ex. in GNU C++) must include
+//   the #include<ext/hash_map>, other must do
+//   #include<hash_map>, maybe with different namespaces.
+//   To avoid this problem you can just use
+//   #include<ChWrapHashmap.h>.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#ifdef COMPILER_GCC
+ #include <ext/hash_map>
+ namespace chronohash = ::__gnu_cxx;
+#else
+ #include <hash_map>
+ namespace chronohash = ::stdext; // NOTE: in Visual C++ Toolkit 2003 is ::std;
+#endif
+
+
+
+#endif
+
diff --git a/SRC/ChronoEngine/geometry/ChCBox.cpp b/SRC/ChronoEngine/geometry/ChCBox.cpp
new file mode 100644
index 0000000..c6710d7
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCBox.cpp
@@ -0,0 +1,352 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2003, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCBox.cpp
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include <stdio.h>
+
+
+#include "ChCBox.h"
+#include "core/ChTrasform.h"
+
+ 
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChBox> a_registration_ChBox;
+
+
+
+
+ChBox::ChBox(Vector& mC0, Vector& mC1,Vector& mC2,Vector& mC3) 
+{
+	Vector D1 = Vsub(mC1, mC0);
+	Vector D2 = Vsub(mC2, mC0);
+	Vector D3 = Vsub(mC3, mC0);
+	Vector C0 = mC0;
+
+	Vector zax;
+	zax.Cross(D1, D2);
+	if (Vdot(D3, zax) < 0 ) 
+	{	
+		C0 += D3;
+		D3 = -D3;
+	}
+
+	this->Size.x = 0.5*Vlenght(D1);
+	this->Size.y = 0.5*Vlenght(D2);
+	this->Size.z = 0.5*Vlenght(D3);
+	this->Pos = Vadd( Vadd( Vadd(C0, 
+		 Vmul(D1,0.5) ) ,  
+		 Vmul(D2,0.5) ) ,  
+		 Vmul(D3,0.5) ); 
+	this->Rot.Set_A_axis(Vnorm(D1), Vnorm(D2), Vnorm(D3));
+}
+
+
+
+void ChBox::Evaluate(Vector& pos, 
+						const double parU, 
+						const double parV, 
+						const double parW)
+{
+	Vector Pr;
+	Pr.x= Size.x * (parU-0.5);
+	Pr.y= Size.y * (parV-0.5);
+	Pr.z= Size.z * (parW-0.5);
+	pos = ChTrasform<>::TrasformLocalToParent(Pr, Pos, Rot);
+}
+
+
+
+Vector ChBox::GetP1()
+{
+	Vector P1r;
+	P1r.x= +Size.x;
+	P1r.y= +Size.y;
+	P1r.z= +Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P1r, Pos, Rot);
+}
+Vector ChBox::GetP2()
+{
+	Vector P2r;
+	P2r.x= -Size.x;
+	P2r.y= +Size.y;
+	P2r.z= +Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P2r, Pos, Rot);
+}
+Vector ChBox::GetP3()
+{
+	Vector P3r;
+	P3r.x= -Size.x;
+	P3r.y= -Size.y;
+	P3r.z= +Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P3r, Pos, Rot);
+}
+Vector ChBox::GetP4()
+{
+	Vector P4r;
+	P4r.x= +Size.x;
+	P4r.y= -Size.y;
+	P4r.z= +Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P4r, Pos, Rot);
+}
+Vector ChBox::GetP5()
+{
+	Vector P5r;
+	P5r.x= +Size.x;
+	P5r.y= +Size.y;
+	P5r.z= -Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P5r, Pos, Rot);
+}
+Vector ChBox::GetP6()
+{ 
+	Vector P6r;
+	P6r.x= -Size.x;
+	P6r.y= +Size.y;
+	P6r.z= -Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P6r, Pos, Rot);
+}
+Vector ChBox::GetP7()
+{
+	Vector P7r;
+	P7r.x= -Size.x;
+	P7r.y= -Size.y;
+	P7r.z= -Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P7r, Pos, Rot);
+}
+Vector ChBox::GetP8()
+{
+	Vector P8r;
+	P8r.x= +Size.x;
+	P8r.y= -Size.y;
+	P8r.z= -Size.z;
+	return ChTrasform<>::TrasformLocalToParent(P8r, Pos, Rot);
+}
+
+Vector ChBox::GetPn(int ipoint)
+{
+	switch (ipoint)
+	{
+	case 1: return GetP1();
+	case 2: return GetP2();
+	case 3: return GetP3();
+	case 4: return GetP4();
+	case 5: return GetP5();
+	case 6: return GetP6();
+	case 7: return GetP7();
+	case 8: return GetP8();
+	default: return GetP1();
+	}
+}
+
+
+
+
+void ChBox::GetBoundingBox(double& xmin, double& xmax, 
+					    double& ymin, double& ymax, 
+						double& zmin, double& zmax, 
+						ChMatrix33<>* bbRot)
+{	
+	// TO OPTIMIZE for speed
+
+	Vector p1,p2,p3,p4,p5,p6,p7,p8;
+	
+	xmax = ymax = zmax = -10e20;
+	xmin = ymin = zmin = +10e20;
+
+	if (bbRot==NULL)
+	{
+		p1 = GetP1();
+		p2 = GetP2();
+		p3 = GetP3();
+		p4 = GetP4();
+		p5 = GetP5();
+		p6 = GetP6();
+		p7 = GetP7();
+		p8 = GetP8();
+	}
+	else
+	{
+		p1 = bbRot->MatrT_x_Vect(GetP1());
+		p2 = bbRot->MatrT_x_Vect(GetP2());
+		p3 = bbRot->MatrT_x_Vect(GetP3());
+		p4 = bbRot->MatrT_x_Vect(GetP4());
+		p5 = bbRot->MatrT_x_Vect(GetP5());
+		p6 = bbRot->MatrT_x_Vect(GetP6());
+		p7 = bbRot->MatrT_x_Vect(GetP7());
+		p8 = bbRot->MatrT_x_Vect(GetP8());
+	}
+
+	if (p1.x > xmax) xmax = p1.x;
+	if (p1.y > ymax) ymax = p1.y;
+	if (p1.z > zmax) zmax = p1.z;
+	if (p2.x > xmax) xmax = p2.x;
+	if (p2.y > ymax) ymax = p2.y;
+	if (p2.z > zmax) zmax = p2.z;
+	if (p3.x > xmax) xmax = p3.x;
+	if (p3.y > ymax) ymax = p3.y;
+	if (p3.z > zmax) zmax = p3.z;
+	if (p4.x > xmax) xmax = p4.x;
+	if (p4.y > ymax) ymax = p4.y;
+	if (p4.z > zmax) zmax = p4.z;
+    if (p5.x > xmax) xmax = p5.x;
+	if (p5.y > ymax) ymax = p5.y;
+	if (p5.z > zmax) zmax = p5.z;
+	if (p6.x > xmax) xmax = p6.x;
+	if (p6.y > ymax) ymax = p6.y;
+	if (p6.z > zmax) zmax = p6.z;
+	if (p7.x > xmax) xmax = p7.x;
+	if (p7.y > ymax) ymax = p7.y;
+	if (p7.z > zmax) zmax = p7.z;
+	if (p8.x > xmax) xmax = p8.x;
+	if (p8.y > ymax) ymax = p8.y;
+	if (p8.z > zmax) zmax = p8.z;
+
+	if (p1.x < xmin) xmin = p1.x;
+	if (p1.y < ymin) ymin = p1.y;
+	if (p1.z < zmin) zmin = p1.z;
+	if (p2.x < xmin) xmin = p2.x;
+	if (p2.y < ymin) ymin = p2.y;
+	if (p2.z < zmin) zmin = p2.z;
+	if (p3.x < xmin) xmin = p3.x;
+	if (p3.y < ymin) ymin = p3.y;
+	if (p3.z < zmin) zmin = p3.z;
+	if (p4.x < xmin) xmin = p4.x;
+	if (p4.y < ymin) ymin = p4.y;
+	if (p4.z < zmin) zmin = p4.z;
+    if (p5.x < xmin) xmin = p5.x;
+	if (p5.y < ymin) ymin = p5.y;
+	if (p5.z < zmin) zmin = p5.z;
+	if (p6.x < xmin) xmin = p6.x;
+	if (p6.y < ymin) ymin = p6.y;
+	if (p6.z < zmin) zmin = p6.z;
+	if (p7.x < xmin) xmin = p7.x;
+	if (p7.y < ymin) ymin = p7.y;
+	if (p7.z < zmin) zmin = p7.z;
+	if (p8.x < xmin) xmin = p8.x;
+	if (p8.y < ymin) ymin = p8.y;
+	if (p8.z < zmin) zmin = p8.z;
+}
+
+
+void ChBox::CovarianceMatrix(ChMatrix33<>& C) 
+{
+	Vector p1,p2,p3,p4,p5,p6,p7,p8;
+
+	p1 = GetP1();
+	p2 = GetP2();
+	p3 = GetP3();
+	p4 = GetP4();
+	p5 = GetP5();
+	p6 = GetP6();
+	p7 = GetP7();
+	p8 = GetP8();
+
+	C(0,0)= p1.x*p1.x + 
+		    p2.x*p2.x + 
+			p3.x*p3.x +
+			p4.x*p4.x +
+			p5.x*p5.x +
+			p6.x*p6.x +
+			p7.x*p7.x +
+			p8.x*p8.x;
+	C(1,1)= p1.y*p1.y + 
+		    p2.y*p2.y + 
+			p3.y*p3.y +
+			p4.y*p4.y +
+			p5.y*p5.y +
+			p6.y*p6.y +
+			p7.y*p7.y +
+			p8.y*p8.y;
+	C(2,2)= p1.z*p1.z + 
+		    p2.z*p2.z + 
+			p3.z*p3.z +
+			p4.z*p4.z +
+			p5.z*p5.z +
+			p6.z*p6.z +
+			p7.z*p7.z +
+			p8.z*p8.z;
+	C(0,1)= p1.x*p1.y + 
+		    p2.x*p2.y + 
+			p3.x*p3.y +
+			p4.x*p4.y +
+			p5.x*p5.y +
+			p6.x*p6.y +
+			p7.x*p7.y +
+			p8.x*p8.y;
+	C(0,2)= p1.x*p1.z + 
+		    p2.x*p2.z + 
+			p3.x*p3.z +
+			p4.x*p4.z +
+			p5.x*p5.z +
+			p6.x*p6.z +
+			p7.x*p7.z +
+			p8.x*p8.z;
+	C(1,2)= p1.y*p1.z + 
+		    p2.y*p2.z + 
+			p3.y*p3.z +
+			p4.y*p4.z +
+			p5.y*p5.z +
+			p6.y*p6.z +
+			p7.y*p7.z +
+			p8.y*p8.z;
+};
+
+ 
+
+
+void ChBox::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChGeometry::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << Pos;
+	mstream << Rot;
+	mstream << Size;
+}
+
+void ChBox::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChGeometry::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> Pos;
+	mstream >> Rot;
+	mstream >> Size;
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/geometry/ChCBox.h b/SRC/ChronoEngine/geometry/ChCBox.h
new file mode 100644
index 0000000..94ab63d
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCBox.h
@@ -0,0 +1,193 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_BOX_H
+#define CHC_BOX_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCBox.h
+// 
+//   Header for the box geometry, used for collision
+//   detection an other stuff.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+
+#include "geometry/ChCGeometry.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+#define CH_GEOCLASS_BOX   3
+
+///
+/// A box.
+/// Geometric object for collisions and such.
+///
+
+class ChApi ChBox : public ChGeometry{
+
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChBox,ChGeometry);
+
+public:
+
+		//
+		// CONSTRUCTORS
+		//
+
+	ChBox() 
+				{
+					Pos= VNULL;
+					Size = VNULL;
+					Rot.Set33Identity();
+				};
+					
+			/// Build from pos, rotation, xyzlengths 
+	ChBox(ChVector<>& mpos, ChMatrix33<>& mrot, ChVector<>& mlengths) 
+				{
+					Pos = mpos; Size = 0.5*mlengths;
+					Rot.CopyFromMatrix(mrot);
+				}
+
+			/// Build from first corner and three other neighbouring corners
+	ChBox(ChVector<>& mC0, ChVector<>& mC1, ChVector<>& mC2, ChVector<>& mC3);
+
+
+	ChBox(ChBox & source)
+				{
+					Copy(&source);
+				}
+
+	void Copy (ChBox* source) 
+				{
+					Pos = source->Pos;
+					Size = source->Size;
+					Rot.CopyFromMatrix(*source->GetRotm());
+				};
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChBox(); 
+					mgeo->Copy(this); return mgeo;
+				};
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_BOX;};
+
+	virtual void GetBoundingBox(double& xmin, double& xmax, 
+					    double& ymin, double& ymax, 
+						double& zmin, double& zmax, 
+						ChMatrix33<>* bbRot = NULL);
+	
+			/// Computes the baricenter of the box
+	virtual Vector Baricenter() {return Pos;};
+
+			/// Computes the covariance matrix for the box
+	virtual void CovarianceMatrix(ChMatrix33<>& C);
+
+			/// Evaluate position in cube volume
+	virtual void Evaluate(Vector& pos, 
+						const double parU, 
+						const double parV = 0., 
+						const double parW = 0.);
+
+			/// This is a solid
+	virtual int GetManifoldDimension() {return 3;}
+
+
+		//
+		// CUSTOM FUNCTIONS
+		//
+	
+		/// Access the rotation of the box
+	ChMatrix33<>* GetRotm() {return &Rot;};
+
+		/// Access the position of the barycenter of the box
+	ChVector<>& GetPos() {return Pos;};
+
+		/// Access the size of the box: a vector with the 
+		/// three hemi-lengths (lenghts divided by two!)
+	ChVector<>& GetSize(){return Size;};
+	
+		/// Get the x y z lenghts of this box (that is, double
+		/// the Size values)
+	ChVector<> GetLenghts(){return 2.0*Size;}
+
+		/// Set the x y z lenghts of this box (that is, double
+		/// the Size values)
+	void SetLenghts(ChVector<>& mlen){ Size = 0.5*mlen;}
+
+
+	
+					// Get the 8 corner points, translated and rotated
+	ChVector<> GetP1();
+	ChVector<> GetP2();
+	ChVector<> GetP3();
+	ChVector<> GetP4();
+	ChVector<> GetP5();
+	ChVector<> GetP6();
+	ChVector<> GetP7();
+	ChVector<> GetP8();
+					/// Get the n-th corner point, with ipoint = 1...8
+	ChVector<> GetPn(int ipoint);
+
+					/// Get the volume (assuming no scaling in Rot matrix)
+	double GetVolume() {return Size.x*Size.y*Size.z*8.0;};
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+
+
+		//
+		// DATA
+		//
+
+
+			/// Rotation of box
+	ChMatrix33<> Rot;
+			/// Position of center
+	ChVector<> Pos;
+			/// Hemi size (extension of box from center to corner)
+	ChVector<> Size;
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCCone.cpp b/SRC/ChronoEngine/geometry/ChCCone.cpp
new file mode 100644
index 0000000..173d940
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCCone.cpp
@@ -0,0 +1,68 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2006 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCCone.cpp
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+
+
+#include "ChCCone.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChCone> a_registration_ChCone;
+
+
+void ChCone::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChGeometry::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << center;
+	mstream << rad;
+}
+
+void ChCone::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChGeometry::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> center;
+	mstream >> rad;
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/geometry/ChCCone.h b/SRC/ChronoEngine/geometry/ChCCone.h
new file mode 100644
index 0000000..3e46b6c
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCCone.h
@@ -0,0 +1,125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_CONE_H
+#define CHC_CONE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCCone.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "ChCGeometry.h"
+
+namespace chrono {
+namespace geometry {
+
+#define EPS_SHPEREDEGENERATE 1e-20
+
+#define CH_GEOCLASS_CONE   4
+
+///
+/// A sphere.
+/// Geometric object for collisions and such.
+///
+
+class ChApi ChCone: public ChGeometry {
+		// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChCone,ChGeometry)
+		;
+
+	public:
+
+		//
+		// CONSTRUCTORS
+		//
+
+		ChCone() {
+			center = VNULL;
+			rad = 0;
+		};
+
+		ChCone(Vector& mc, Vector mrad)
+		{
+			center = mc;
+			rad = mrad;
+		}
+
+		ChCone(const ChCone & source)
+		{
+			Copy(&source);
+		}
+
+		void Copy (const ChCone* source)
+		{
+			center = source->center;
+			rad = source->rad;
+		};
+
+		ChGeometry* Duplicate ()
+		{
+			ChGeometry* mgeo = new ChCone();
+			mgeo->Copy(this); return mgeo;
+		};
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+					virtual int GetClassType () {return CH_GEOCLASS_CONE;};
+
+					virtual void GetBoundingBox(double& xmin, double& xmax,
+							double& ymin, double& ymax,
+							double& zmin, double& zmax,
+							ChMatrix33<>* Rot = NULL)
+					{
+
+					}
+
+					virtual Vector Baricenter() {return center;};
+
+					virtual void CovarianceMatrix(ChMatrix33<>& C)
+					{
+
+					};
+
+					/// This is a solid
+					virtual int GetManifoldDimension() {return 3;}
+
+					//
+					// DATA
+					//
+
+					Vector center;
+
+					Vector rad;
+
+					//
+					// STREAMING
+					//
+
+					void StreamOUT(ChStreamOutBinary& mstream);
+
+					void StreamIN(ChStreamInBinary& mstream);
+
+				};
+
+				}     // END_OF_NAMESPACE____
+				}     // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCCylinder.cpp b/SRC/ChronoEngine/geometry/ChCCylinder.cpp
new file mode 100644
index 0000000..170b6fb
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCCylinder.cpp
@@ -0,0 +1,69 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2006, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCCylinder.cpp
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+
+
+#include "ChCCylinder.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChCylinder> a_registration_ChCylinder;
+
+
+void ChCylinder::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChGeometry::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << p1;
+	mstream << p2;
+	mstream << rad;
+}
+
+void ChCylinder::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChGeometry::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> p1;
+	mstream >> p2;
+	mstream >> rad;
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/geometry/ChCCylinder.h b/SRC/ChronoEngine/geometry/ChCCylinder.h
new file mode 100644
index 0000000..a9b9ad6
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCCylinder.h
@@ -0,0 +1,164 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_CYLINDER_H
+#define CHC_CYLINDER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCCylinder.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChCGeometry.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+
+#define EPS_CYLINDERDEGENERATE 1e-20
+
+
+#define CH_GEOCLASS_CYLINDER   13
+
+
+///
+/// A cylinder.
+/// Geometric object for collisions and such.
+///
+
+class ChApi ChCylinder : public ChGeometry
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChCylinder,ChGeometry);
+
+public:
+
+		//
+		// CONSTRUCTORS
+		//
+
+	ChCylinder() 
+				{
+					p1= VNULL;
+					p2= ChVector<>(0,1,0);
+					rad = 0.1;
+				};
+	
+	ChCylinder(ChVector<>& mp1, ChVector<>& mp2, double mrad) 
+				{
+					p1 = mp1;
+					p2 = mp2;
+					rad = mrad;
+				}
+
+	ChCylinder(const ChCylinder & source)
+				{
+					Copy(&source);
+				}
+
+	void Copy (const ChCylinder* source) 
+				{
+					p1 = source->p1;
+					p2 = source->p2;
+					rad = source->rad;
+				};
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChCylinder(); 
+					mgeo->Copy(this); return mgeo;
+				};
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_CYLINDER;};
+
+	virtual void GetBoundingBox(double& xmin, double& xmax, 
+					    double& ymin, double& ymax, 
+						double& zmin, double& zmax,
+						ChMatrix33<>* Rot = NULL)
+				{
+		Vector dims = Vector(rad, p2.y - p1.y, rad);
+		Vector trsfCenter = Baricenter();
+							if (Rot)
+							{
+								trsfCenter = Rot->MatrT_x_Vect(Baricenter());
+							}
+							xmin=trsfCenter.x-dims.x;
+							xmax=trsfCenter.x+dims.x;
+							ymin=trsfCenter.y-dims.y;
+							ymax=trsfCenter.y+dims.y;
+							zmin=trsfCenter.z-dims.z;
+							zmax=trsfCenter.z+dims.z;
+
+
+				}
+	
+	virtual ChVector<> Baricenter() {return (p1+p2)*0.5;};
+
+			//***TO DO***  obsolete/unused
+	virtual void CovarianceMatrix(ChMatrix33<>& C) 
+				{
+					C.Reset();
+					C(0,0)= p1.x*p1.x;
+					C(1,1)= p1.y*p1.y;
+					C(2,2)= p1.z*p1.z;
+				};
+
+				/// This is a solid
+	virtual int GetManifoldDimension() {return 3;}
+
+
+			
+
+
+		//
+		// DATA
+		//
+
+	ChVector<> p1;
+	ChVector<> p2;
+
+	double rad;
+
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCEllipsoid.cpp b/SRC/ChronoEngine/geometry/ChCEllipsoid.cpp
new file mode 100644
index 0000000..07c8003
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCEllipsoid.cpp
@@ -0,0 +1,68 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2006 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCEllipsoid.cpp
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+
+
+#include "ChCEllipsoid.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChEllipsoid> a_registration_ChEllipsoid;
+
+
+void ChEllipsoid::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChGeometry::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << center;
+	mstream << rad;
+}
+
+void ChEllipsoid::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChGeometry::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> center;
+	mstream >> rad;
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/geometry/ChCEllipsoid.h b/SRC/ChronoEngine/geometry/ChCEllipsoid.h
new file mode 100644
index 0000000..97f65e5
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCEllipsoid.h
@@ -0,0 +1,156 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_ELLIPSOID_H
+#define CHC_ELLIPSOID_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCEllipsoid.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChCGeometry.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+
+#define EPS_SHPEREDEGENERATE 1e-20
+
+
+#define CH_GEOCLASS_SPHERE   2
+
+
+///
+/// A sphere.
+/// Geometric object for collisions and such.
+///
+
+class ChApi ChEllipsoid : public ChGeometry
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChEllipsoid,ChGeometry);
+
+public:
+
+		//
+		// CONSTRUCTORS
+		//
+
+	ChEllipsoid()
+				{
+					center= VNULL;
+					rad = 0;
+				};
+	
+	ChEllipsoid(Vector& mc, Vector mrad)
+				{
+					center = mc;
+					rad = mrad;
+				}
+
+	ChEllipsoid(const ChEllipsoid & source)
+				{
+					Copy(&source);
+				}
+
+	void Copy (const ChEllipsoid* source)
+				{
+					center = source->center;
+					rad = source->rad;
+				};
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChEllipsoid();
+					mgeo->Copy(this); return mgeo;
+				};
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_SPHERE;};
+
+	virtual void GetBoundingBox(double& xmin, double& xmax, 
+					    double& ymin, double& ymax, 
+						double& zmin, double& zmax,
+						ChMatrix33<>* Rot = NULL)
+				{
+					Vector trsfCenter = center;
+					if (Rot)
+					{
+						trsfCenter = Rot->MatrT_x_Vect(center);
+					}
+					xmin=trsfCenter.x-rad.x;
+					xmax=trsfCenter.x+rad.x;
+					ymin=trsfCenter.y-rad.y;
+					ymax=trsfCenter.y+rad.y;
+					zmin=trsfCenter.z-rad.z;
+					zmax=trsfCenter.z+rad.z;
+				}
+	
+	virtual Vector Baricenter() {return center;};
+
+	virtual void CovarianceMatrix(ChMatrix33<>& C) 
+				{
+					C.Reset();
+					C(0,0)= center.x*center.x;
+					C(1,1)= center.y*center.y;
+					C(2,2)= center.z*center.z;
+				};
+
+				/// This is a solid
+	virtual int GetManifoldDimension() {return 3;}
+
+
+			
+
+
+		//
+		// DATA
+		//
+
+	Vector center;
+
+	Vector rad;
+
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCGeometry.cpp b/SRC/ChronoEngine/geometry/ChCGeometry.cpp
new file mode 100644
index 0000000..3020a32
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCGeometry.cpp
@@ -0,0 +1,85 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2006, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCGeometry.cpp
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+
+
+#include "ChCGeometry.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChGeometry> a_registration_ChGeometry;
+
+
+
+ChGeometry::ChGeometry() {};
+
+ChGeometry::~ChGeometry() {};
+
+
+
+void ChGeometry::Derive(Vector& dir, 
+						const double parU, 
+						const double parV, 
+						const double parW)
+{
+	double bdf = 10e-9;
+	double uA=0,uB=0;
+
+	if (parU > 0.5)
+	{
+		double uB = parU;
+		double uA = parU-bdf;
+	}else
+	{
+		double uB = parU+bdf;
+		double uA = parU;
+	}
+	Vector vA, vB;
+	Evaluate(vA,uA);
+	Evaluate(vB,uB);
+	
+	dir = (vB-vA)*(1/bdf);
+}
+
+void ChGeometry::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+}
+
+void ChGeometry::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/geometry/ChCGeometry.h b/SRC/ChronoEngine/geometry/ChCGeometry.h
new file mode 100644
index 0000000..a62f960
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCGeometry.h
@@ -0,0 +1,185 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_GEOMETRY
+#define CHC_GEOMETRY
+
+//////////////////////////////////////////////////
+//   
+//   ChCGeometry.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "core/ChMath.h"
+#include "core/ChApiCE.h"
+
+
+namespace chrono 
+{
+
+/// Namespace for classes which represent basic geometric objects
+namespace geometry
+{
+
+
+#define CH_GEOCLASS_GEOMETRY	0
+
+
+
+///
+/// Base class for geometric objects.
+/// Geometric object are used for collisions and such.
+///
+
+class ChApi ChGeometry  {
+
+								// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI_ROOT(ChGeometry);
+
+public:
+		//
+		//CONSTRUCTORS
+		//
+
+	ChGeometry();
+
+	virtual ~ChGeometry();
+
+	virtual void Copy (ChGeometry*) {};
+
+	virtual ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChGeometry(); 
+					mgeo->Copy(this); return mgeo;
+				};
+
+				/// Get the class type as unique numerical ID (faster 
+				/// than using ChronoRTTI mechanism).
+				/// Each inherited class must return an unique ID.
+	virtual int GetClassType () {return CH_GEOCLASS_GEOMETRY;};
+
+
+		//
+		// GEOMETRIC FUNCTIONS
+		//
+
+				/// Compute bounding box.
+				/// If a matrix Rot is not null, it should compute bounding box along
+				/// the rotated directions represented by that transformation matrix Rot.
+				/// It must be overridden by inherited classes.
+	virtual void GetBoundingBox(double& xmin, double& xmax, 
+				    double& ymin, double& ymax, 
+				    double& zmin, double& zmax, 
+				    ChMatrix33<>* = NULL)
+				{
+					xmin=xmax=ymin=ymax=zmin=zmax =0.0 ;
+				}
+			
+				/// Enlarge a previous existing bounding box.
+				/// Usually it does not need to be overriden: base function uses GetBoundingBox()
+				/// If Rot is not null, the bounding box axes are considered rotated.
+	virtual void InflateBoundingBox(double& xmin, double& xmax, 
+									double& ymin, double& ymax, 
+									double& zmin, double& zmax, 
+									ChMatrix33<>* Rot = NULL)
+				{
+					double bxmin, bxmax, bymin, bymax, bzmin, bzmax;
+					this->GetBoundingBox(bxmin, bxmax, bymin, bymax, bzmin, bzmax, Rot);
+					if (xmin>bxmin) xmin = bxmin;
+					if (ymin>bymin) ymin = bymin;
+					if (zmin>bzmin) zmin = bzmin;
+					if (xmax<bxmax) xmax = bxmax;
+					if (ymax<bymax) ymax = bymax;
+					if (zmax<bzmax) zmax = bzmax;
+				};
+
+				/// Returns the radius of the sphere which can enclose the geometry
+	virtual double Size()
+				{
+					double bxmin, bxmax, bymin, bymax, bzmin, bzmax;
+					this->GetBoundingBox(bxmin, bxmax, bymin, bymax, bzmin, bzmax);
+					return sqrt(pow((0.5*(bxmax-bxmin)),2)+pow((0.5*(bymax-bymin)),2)+pow((0.5*(bzmax-bzmin)),2));
+				};
+
+				/// Evaluates a point on a geometry, given parametric coordinates, 
+				/// if possible. Parameters  U,V,W should be usually in 0..1 range.
+				/// For a line, only U parameter is needed, for a surface also V.
+				/// Computed value goes into the 'pos' reference.
+				/// It should be overriden by inherited classes.
+	virtual void Evaluate(Vector& pos, 
+			      const double, 
+			      const double = 0., 
+			      const double = 0.) 
+				{
+					pos = VNULL; 
+				};
+
+
+				/// Evaluates a tangent versor on a geometry, given parametric coordinates, 
+				/// if possible. Parameters  U,V,W should be usually in 0..1 range.
+				/// For a line, only U parameter is needed, for a surface also V.
+				/// Computed value goes into the 'pos' reference.
+				/// It could be overriden by inherited classes if a precise solution is
+				/// known (otherwise it defaults to numerical BDF using the Evaluate() 
+				/// function.
+	virtual void Derive(Vector& dir, 
+						const double parU, 
+						const double parV = 0., 
+						const double parW = 0.);
+
+
+				/// Compute center of mass
+				/// It should be overriden by inherited classes
+	virtual Vector Baricenter() {return VNULL;};
+
+				/// Compute the 3x3 covariance matrix (only the diagonal and upper part)
+				/// It should be overriden by inherited classes
+	virtual void CovarianceMatrix(ChMatrix33<>& C) { C.Reset();};
+
+				/// Tells the dimension of the geometry 
+				/// (0=point, 1=line, 2=surface, 3=solid)
+	virtual int GetManifoldDimension() {return 0;}
+
+				/// Generic update of internal data. Default, does nothing.
+				/// Most often it is not needed to implement this method, but 
+				/// some inherited classes may implement it (ex. to update references to 
+				/// external data. etc.).
+	virtual void Update() {};
+
+
+		//
+		// STREAMING
+		//
+
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+	virtual void StreamIN(ChStreamInBinary& mstream); 
+
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
+
diff --git a/SRC/ChronoEngine/geometry/ChCLine.cpp b/SRC/ChronoEngine/geometry/ChCLine.cpp
new file mode 100644
index 0000000..5e00338
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCLine.cpp
@@ -0,0 +1,295 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChCline.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+#include "ChCLine.h"
+
+namespace chrono
+{
+namespace geometry
+{
+
+/////////////////////////////////////////////////////////
+///
+///   GENERIC LINE CLASS
+///
+///
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLine> a_registration_ChLine;
+
+
+
+
+//
+// basic geometric  functions
+//
+
+int ChLine::FindNearestLinePoint (Vector& point, double& resU, double approxU, double tol)
+{
+	double mu;
+	int points = 20;
+	int closed = FALSE;
+	double bestU = 0;
+	double bestdist = 9999999;
+	double dist, d1, d2;
+	int iters = 0;
+	int maxiters = 11;
+
+	Vector vres, vp1, vp2;
+
+	points = this->Get_complexity();
+	closed = this->Get_closed();
+
+	points = points * 4; // double sampling along line.
+
+		// first approximation
+	for (int i = 0; i<=points; i++)
+	{
+		mu = (double)i/(double)points;
+		this->Evaluate(vres, mu);
+		dist = Vlenght(Vsub(vres,point));
+		if (dist < bestdist)
+		{
+			bestdist = dist;
+			bestU = mu;
+		}
+	}
+		// refine position with pseudo-NR
+	double step = 1/(double)points;
+	double nrU = bestU;
+	double u1, u2;
+
+	u1 = nrU - step;
+	if (u1 < 0)
+		{ if (!closed) u1 = 0;	else u1 = u1 + 1;}
+	this->Evaluate(vres, u1);
+	d1 = Vlenght(Vsub(vres,point));
+	vp1 = vres;
+
+	u2 = nrU + step;
+	if (u2 > 1)
+		{ if (!closed) u2 = 1;	else u2 = u2 - 1;}
+	this->Evaluate(vres, u2);
+	d2 = Vlenght(Vsub(vres,point));
+	vp2 = vres;
+
+	while (TRUE)
+	{
+		iters++;
+
+		if (nrU < 0)
+			{ if (!closed) nrU = 0;	else nrU = nrU + 1;}
+		if (nrU > 1)
+			{ if (!closed) nrU = 1;	else nrU = nrU - 1;}
+		this->Evaluate(vres, nrU);
+		dist = Vlenght(Vsub(vres,point));
+
+		bestU = nrU;
+
+		if (d1 < d2)
+		{
+			u2 = nrU; d2 = dist; vp2 = vres; // move point 2 to nrU
+			step = step / 2;
+			nrU = nrU - step;	 // move nrU in middle
+			if (d1 < dist) bestU = u1;
+		}
+		else
+		{
+			u1 = nrU; d1 = dist; vp1 = vres; // move point 1 to nrU
+			step = step / 2;
+			nrU = nrU + step;	 // move nrU in middle
+			if (d2 < dist) bestU = u2;
+		}
+
+		if ((Vlenght(Vsub(vp1, vp2)) <= tol)||(dist <= tol)) {
+			resU = bestU;
+			return TRUE; }
+		if (iters > maxiters)  {resU = bestU;
+			return FALSE;}
+	}
+
+	resU = bestU;
+	return TRUE;
+}
+
+
+double ChLine::CurveCurveDist (ChLine* compline, int samples)
+{
+	double mres = 0;
+	double par;
+	// distances this<->compare_line
+	for (par = 0; par < 1; par = par + 1/((double)samples))
+	{
+		double mpos;
+		Vector ptB; compline->Evaluate(ptB, par);
+		this->FindNearestLinePoint(ptB, mpos, 0, 0.00002);
+		Vector ptA; this->Evaluate(ptA, mpos);
+		mres += Vlenght(Vsub(ptA,ptB));
+	}
+	// ..and viceversa
+	for (par = 0; par < 1; par = par + 1/((double)samples))
+	{
+		double mpos;
+		Vector ptB; this->Evaluate(ptB, par);
+		compline->FindNearestLinePoint(ptB, mpos, 0, 0.00002);
+		Vector ptA; compline->Evaluate(ptA, mpos);
+		mres += Vlenght(Vsub(ptA,ptB));
+	}
+
+	return (mres/(samples*2));
+}
+
+double ChLine::CurveCurveDistMax (ChLine* compline, int samples)
+{
+	double mres = 0;
+	double par;
+	double mdis;
+	// distances this<->compare_line
+	for (par = 0; par < 1; par = par + 1/((double)samples))
+	{
+		double mpos;
+		Vector ptB; compline->Evaluate(ptB, par);
+		this->FindNearestLinePoint(ptB, mpos, 0, 0.00002);
+		Vector ptA; this->Evaluate(ptA, mpos);
+		mdis = Vlenght(Vsub(ptA,ptB));
+		if (mres < mdis) mres = mdis;
+	}
+	// ..and viceversa
+	for (par = 0; par < 1; par = par + 1/((double)samples))
+	{
+		double mpos;
+		Vector ptB;  this->Evaluate(ptB, par);
+		compline->FindNearestLinePoint(ptB, mpos, 0, 0.00002);
+		Vector ptA;  compline->Evaluate(ptA, mpos);
+		mdis = Vlenght(Vsub(ptA,ptB));
+		if (mres < mdis) mres = mdis;
+	}
+
+	return mres;
+}
+
+
+double ChLine::CurveSegmentDist (ChLine* complinesegm, int samples)
+{
+	double mres = 0;
+	double par;
+	// distances this<->compare_line
+	for (par = 0; par < 1; par = par + 1/((double)samples))
+	{
+		double mpos;
+		Vector ptB;  complinesegm->Evaluate(ptB, par);
+		this->FindNearestLinePoint(ptB, mpos, 0, 0.00002);
+		Vector ptA;  this->Evaluate(ptA, mpos);
+		mres += Vlenght(Vsub(ptA,ptB));
+	}
+	return (mres/samples);
+}
+
+double ChLine::CurveSegmentDistMax (ChLine* complinesegm, int samples)
+{
+	double mres = 0;
+	double par;
+	double mdis;
+	// distances this<->compare_line
+	for (par = 0; par < 1; par = par + 1/((double)samples))
+	{
+		double mpos;
+		Vector ptB;  complinesegm->Evaluate(ptB, par);
+		this->FindNearestLinePoint(ptB, mpos, 0, 0.00002);
+		Vector ptA;  this->Evaluate(ptA, mpos);
+		mdis = Vlenght(Vsub(ptA,ptB));
+		if (mres < mdis) mres = mdis;
+	}
+	return (mres);
+}
+
+double ChLine::Lenght (int sampling)
+{
+	double mres = 0;
+	double par, step;
+
+	if (!closed)
+		step = 1/((double)(Get_complexity()-1));
+	else
+		step = 1/((double)(Get_complexity()));
+
+	if (sampling >1)
+		step = step/(double)sampling;
+
+	Vector pA; this->Evaluate(pA, 0.);
+	Vector pB;
+	for (par = 0; par <= 1.000000001; par = par + step)
+	{
+		this->Evaluate(pB, par);
+		mres += Vlenght(Vsub(pA,pB));
+		pA = pB;
+	}
+	return mres;
+}
+
+
+
+
+
+
+void ChLine::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChGeometry::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << closed;
+	mstream << complexityU;
+}
+
+void ChLine::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChGeometry::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> closed;
+	mstream >> complexityU;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+////// end
diff --git a/SRC/ChronoEngine/geometry/ChCLine.h b/SRC/ChronoEngine/geometry/ChCLine.h
new file mode 100644
index 0000000..c2c6090
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCLine.h
@@ -0,0 +1,161 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_LINE_H
+#define CHC_LINE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCLine.h
+//
+//   Base class for lines
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "ChCGeometry.h"
+
+
+namespace chrono
+{
+namespace geometry 
+{
+
+
+
+
+
+#define CH_GEOCLASS_LINE   4	
+
+
+///
+/// LINE.
+///
+/// Base class for all geometric objects representing lines 
+/// in 3D space.
+///
+
+class ChApi ChLine : public ChGeometry 
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChLine,ChGeometry);
+
+protected:
+	int		closed;
+	int		complexityU;
+public:	
+
+		//
+		// CONSTRUCTORS
+		//
+
+	ChLine () { closed = FALSE; complexityU = 2;};
+
+	~ChLine () {};
+
+	ChLine(const ChLine & source)
+				{
+					Copy(&source);
+				}
+
+	void Copy (const ChLine* source) 
+				{
+					closed = source->closed;
+					complexityU = source->complexityU;
+				};
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChLine(); 
+					mgeo->Copy(this); return mgeo;
+				};
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+				/// Get the class type as unique numerical ID (faster 
+				/// than using ChronoRTTI mechanism).
+				/// Each inherited class must return an unique ID.
+	virtual int GetClassType () {return CH_GEOCLASS_LINE;};
+
+
+			/// Tell if the curve is closed
+	virtual int Get_closed() {return closed;};
+	virtual void Set_closed(int mc) {closed = mc;};
+
+			/// Tell the complexity
+	virtual int Get_complexity() {return complexityU;};
+	virtual void Set_complexity(int mc) {complexityU = mc;};
+
+			/// This is a line
+	virtual int GetManifoldDimension() {return 1;}
+
+
+
+		//
+		// CUSTOM FUNCTIONS
+		//
+
+			/// Find the parameter resU for the nearest point on curve to "point".
+	int FindNearestLinePoint (Vector& point, double& resU, double approxU, double tol);
+
+			/// Returns curve lenght. Typical sampling 1..5 (1 already gives correct result with degree1 curves)
+	virtual double Lenght (int sampling);
+
+			/// Returns an adimensional information on "how much" this curve is similar to another
+			/// in its overall shape (doesnot matter parametrization or start point). Try with 20 samples.
+			/// The return value is somewhat the "average distance between the two curves".
+			/// Note that the result is affected by "weight" of curves. If it chnges from default 1.0, the 
+			/// distance extimation is higher/lower (ex: if a curve defines low 'weight' in its central segment,
+			/// its CurveCurveDistance from another segment is not much affected by errors near the central segment).
+	double CurveCurveDist (ChLine* compline, int samples);
+
+			/// Same as before, but returns "how near" is complinesegm to 
+			/// whatever segment of this line (does not matter the percentual of line).
+	        /// Again, this is affected by "weight" of curves. If weight changes along curves ->'weighted' distance  
+	double CurveSegmentDist (ChLine* complinesegm, int samples);
+
+			/// Same as above, but instead of making average of the distances,
+			/// these functions return the maximum of the distances...
+	double CurveCurveDistMax (ChLine* compline, int samples);
+	double CurveSegmentDistMax (ChLine* complinesegm, int samples);
+
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif  // END of header
+
+ 
diff --git a/SRC/ChronoEngine/geometry/ChCLineCam.cpp b/SRC/ChronoEngine/geometry/ChCLineCam.cpp
new file mode 100644
index 0000000..64e945c
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCLineCam.cpp
@@ -0,0 +1,262 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChCLineCam.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+
+#include "ChCLineCam.h"
+
+
+namespace chrono
+{
+namespace geometry
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLineCam> a_registration_ChLineCam;
+
+
+
+
+ChLineCam::ChLineCam ()
+{
+	Set_complexity(10);
+	this->closed = TRUE;
+	type = CAM_TYPE_SLIDEFOLLOWER;
+	Rb = 1.0;
+	Rr = 0.0;
+	p = 1.8;
+	d = 2;
+	b0 = CH_C_PI / 6.0;
+	center = VNULL;
+	e = 0;
+	s = Rb;
+	law = new ChFunction_Const(0);
+	negative = FALSE;
+	internal = FALSE;
+}
+
+ChLineCam::~ChLineCam ()
+{
+	if (law) {delete law; law = 0;}
+};
+
+void ChLineCam::Copy (const ChLineCam* source) 
+{
+	// copy parent class data
+	ChLine::Copy(source);
+	// copy class data
+
+	type = source->type;
+
+	Rb = source->Rb;
+	Rr = source->Rr;
+	p = source->p;
+	d = source->d;
+	b0 = source->b0;
+	center = source->center;
+	e = source->e;
+	s = source->s;
+	if (law) 
+		delete law; 
+	law = source->law->new_Duplicate();
+	negative = source->negative;
+	internal = source->internal;
+};
+
+void ChLineCam::EvaluateCamPoint(double par, Vector& res, double& g, double& q)
+{
+	double a = par * 2 * CH_C_PI;  // range : par 0..1 -> angle 0...2PI
+	double r, f, b, B, fshift,y,ydx, ydxdx, sa, fxalpha, u, uh = 0;
+	double sign, signdx, signdxdx;
+
+	// defaults
+	g = 0;
+	q = 0;
+	res = VNULL;
+
+	if (internal) Rr = -Rr;
+	if (negative) e = -e;
+
+	fxalpha = a;
+	sign = signdx = signdxdx = +1;
+
+	if (negative)
+	{
+		sign = signdx = signdxdx = -1;	// reverse sign
+
+		if ((type == CAM_TYPE_ROTATEFOLLOWER) ||
+			(type == CAM_TYPE_FLATOSCILLATE) )
+		{
+				fxalpha = 2*CH_C_PI - a;			// also reverse direction
+				signdx = signdxdx = +1;
+		}
+	}
+
+	y = sign * law->Get_y(fxalpha);
+	ydx = signdx * law->Get_y_dx(fxalpha);
+	ydxdx = signdxdx * law->Get_y_dxdx(fxalpha);
+
+
+	switch (this->type)
+	{
+	case CAM_TYPE_SLIDEFOLLOWER:
+		g = atan(ydx /(Rb+y));
+		r = sqrt(Rr*Rr + pow(Rb+y,2) -2*Rr*(Rb+y)*cos(g));
+		fshift = asin(Rr*sin(g)/r);
+		if (Rr > Rb) fshift = CH_C_PI - fshift;
+		f = a + fshift;
+		q = pow(ydx*ydx + pow(Rb+y,2) , 1.5) / (pow(Rb+y,2)-ydxdx*(Rb+y)+2*(ydx*ydx)) - Rr;
+		break;
+	case CAM_TYPE_ROTATEFOLLOWER:
+		b = b0 + y;
+		u = atan2 ( (p*sin(b)*(1-ydx)) , (d - p*cos(b)*(1-ydx)) );
+		g = CH_C_PI/2.0 - b - u;
+		r = sqrt( pow( p*sin(b)-Rr*sin(u), 2) + pow ( d-p*cos(b)-Rr*cos(u) ,2) );
+		fshift = atan2( (p*sin(b)-Rr*sin(u)) , (d-p*cos(b)-Rr*cos(u)) );
+		f = (a + fshift);
+		uh = (p*(1-ydx)*ydx*cos(b+u) - p*ydxdx*sin(b+u)) / (d*cos(u)-p*(1-ydx)*cos(b+u));
+		q = ((p*cos(b0+y)*(1-ydx))+d) / ((1+uh)*cos(u)) - Rr;
+		break;
+	case CAM_TYPE_ECCENTRICFOLLOWER:
+		s = Get_s();
+		sa = s+y;
+		g = atan ( (ydx - e) / (s+y) );
+		r = sqrt ( pow(( sa -Rr*cos(g)),2) + pow((e+Rr*sin(g)),2) );
+		fshift = atan( (e+Rr*sin(g))/( sa -Rr*cos(g)) );
+		if (Rr > Rb) fshift = CH_C_PI + fshift;
+		f = a + fshift;
+		q = pow((pow(s+y,2)+pow(e-ydx,2) ),1.5) / (pow(s+y,2)+(e-ydx)*(e-2*ydx)-(s+y)*ydxdx) - Rr;
+		break;
+	case CAM_TYPE_FLAT:
+		g = 0;
+		B = ydx;
+		r = sqrt (pow(Rb+y,2) + ydx*ydx );
+		f = a + atan2( ydx , (Rb+y));
+		q = Rb+y+ydxdx;
+		break;
+	case CAM_TYPE_FLATOSCILLATE:
+		b = b0 + y;
+		B = (d*cos(b)) / (1 - ydx);
+		g = atan2 (e,B);
+		r = sqrt ( pow(d - e *sin(b) - B*cos(b), 2) + pow (B*sin(b)-e*cos(b), 2) );
+		f = a + atan2( (B*sin(b)-e*cos(b)) , (d - e *sin(b) - B*cos(b)) );
+		q = (d*sin(b)*(1-2*ydx)+B*ydxdx ) / (pow(1-ydx,2)) - e;
+		break;
+	default:
+		g = r = f = 0;
+		break;
+	}
+
+	if (negative)
+	{
+		if ((type == CAM_TYPE_FLAT) ||
+			(type == CAM_TYPE_SLIDEFOLLOWER) ||
+			(type == CAM_TYPE_ECCENTRICFOLLOWER) )
+				f += CH_C_PI;		// polar 180
+
+		if ((type == CAM_TYPE_ROTATEFOLLOWER) ||
+			(type == CAM_TYPE_FLATOSCILLATE) )
+		{
+				f = -f;			// y mirror
+		}
+	}
+
+	res.z= 0;
+	res.x = this->center.x + r*cos(f+phase);
+	res.y = this->center.y + r*sin(f+phase);
+
+
+	if (internal) Rr = -Rr; // restore Rr if sign inverted.
+	if (negative) e = -e;	// restore e
+}
+
+
+void ChLineCam::Evaluate(Vector& pos, 
+						const double parU, 
+						const double parV, 
+						const double parW) 
+{
+	double qtmp, gtmp;
+	EvaluateCamPoint(parU, pos , gtmp, qtmp);
+}
+
+
+
+
+void ChLineCam::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLine::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << (int) type;
+	mstream.AbstractWrite(law);
+	mstream << phase;
+	mstream << Rb;
+	mstream << Rr;
+	mstream << p;
+	mstream << d;
+	mstream << b0;
+	mstream << e;
+	mstream << s;
+	mstream << negative;
+	mstream << internal;		
+	mstream << center;	
+}
+
+void ChLineCam::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLine::StreamIN(mstream);
+
+		// stream in all member data
+	int mint;
+	mstream >> mint; type = (eChCamType)mint;
+	if (law) delete law;
+	mstream.AbstractReadCreate(&law);
+	mstream >> phase;
+	mstream >> Rb;
+	mstream >> Rr;
+	mstream >> p;
+	mstream >> d;
+	mstream >> b0;
+	mstream >> e;
+	mstream >> s;
+	mstream >> negative;
+	mstream >> internal;		
+	mstream >> center;	
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+////// end
diff --git a/SRC/ChronoEngine/geometry/ChCLineCam.h b/SRC/ChronoEngine/geometry/ChCLineCam.h
new file mode 100644
index 0000000..0232027
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCLineCam.h
@@ -0,0 +1,217 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_LINECAM_H
+#define CHC_LINECAM_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCLineCam.h
+//
+//   2D profile of cam, depending on a motion law.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "ChCLine.h"
+#include "physics/ChFunction.h"
+
+
+namespace chrono
+{
+namespace geometry 
+{
+
+	
+/// For ChLineCam: types of cams
+enum eChCamType{		
+	CAM_TYPE_SLIDEFOLLOWER = 0,
+	CAM_TYPE_ROTATEFOLLOWER,
+	CAM_TYPE_ECCENTRICFOLLOWER,
+	CAM_TYPE_FLAT,
+	CAM_TYPE_FLATOSCILLATE,
+};
+
+
+
+#define CH_GEOCLASS_LINECAM 6		
+
+///
+/// CAM-PROFILE LINE
+///
+/// The object which describes analitycally the shape of a cam,
+/// given the ChFunction which defines the motion law of the follower.
+
+
+class ChApi ChLineCam : public ChLine 
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChLineCam,ChLine);
+
+private:
+		//
+		// DATA
+		//
+
+	eChCamType type;	// see codes
+	ChFunction* law;	// motion law
+	double phase;		// 0..2PI  phase (rotation). Def=0, neutral position
+
+	double Rb;			// base radius
+	double Rr;			// radius of contact wheel
+
+	double p;			// lenght of rotating mover
+	double d;			// distance center of cam - center of rotation of mover
+	double b0;			// initial rotation for mover
+
+	double e;			// eccentricity of sliding follower 
+	double s;			// distance of sliding follower
+
+	int negative;		// negative cam: for desmodromic stuff, (cam is also Y or X mirrored, depend.on type ) 
+	int internal;		// follower roller is inside the cam
+
+	Vector center;		// center of cam in space (def.alignment on xy plane)
+
+public:	
+
+		//
+		// CONSTRUCTORS
+		//
+
+	ChLineCam ();
+
+	virtual ~ChLineCam ();
+
+	ChLineCam(const ChLineCam & source)
+				{
+					law=0;
+					Copy(&source);
+				}
+
+	void Copy (const ChLineCam* source);
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChLineCam(); 
+					mgeo->Copy(this); return mgeo;
+				};
+
+				/// Get the class type as unique numerical ID (faster 
+				/// than using ChronoRTTI mechanism).
+				/// Each inherited class must return an unique ID.	
+	virtual int GetClassType () {return CH_GEOCLASS_LINECAM;};
+
+
+	int Get_closed() {return TRUE;};
+	void Set_closed(int mc) {};
+
+	void Set_Phase(double mf) {phase = mf;};
+	double Get_Phase() {return phase;}
+
+				/// Base radius of cam
+	void Set_Rb(double mrb) {Rb = mrb; if (e>0.9*Rb) e=0.9*Rb; if (e<-0.9*Rb) e=-0.9*Rb; };
+	double Get_Rb() {return Rb;}
+
+				/// Radius of contact wheel
+	void Set_Rr(double mrr) {Rr = mrr;};
+	double Get_Rr() {return Rr;}
+
+				/// The motion law, as a ChFunction.
+	void Set_motion_law(ChFunction* mlaw) {if (law) delete law; law = mlaw;};
+	ChFunction* Get_motion_law() {return law;};
+
+				/// Type of cam (see the eChCamType enum values below).
+	void Set_type(eChCamType mt) {type = mt;};
+	eChCamType Get_type() {return type;}
+
+				/// position of center of cam in 3d space.
+	void Set_center(Vector mc) {center = mc;};
+	Vector Get_center() {return center;}
+
+				/// If true, creates a negative cam.
+	void Set_Negative(int mne) {negative = mne;};
+	int Get_Negative() {return negative;}
+			
+				/// If true, creates an internal cam.
+	void Set_Internal(int min) {internal = min;};
+	int Get_Internal() {return internal;}
+
+				/// Sets the data for the rotating follower (length, distance from cam center, initial phase mb0)
+	void Set_rotating_follower(double mp, double md, double mb0) {p = mp; d = md; b0 = mb0; Rb=sqrt(p*p+d*d-2*p*d*cos(b0));};
+	double Get_p() {return p;};
+	double Get_d() {return d;};
+	double Get_b0() {return b0;};
+
+				/// Sets the data for the sliding follower (if eccentrical, with me eccentricity)
+	void Set_sliding_eccentrical(double me) {e = me; };
+	double Get_e() {return e;};
+	double Get_s() { s = sqrt(Rb*Rb - e*e); return s;};
+
+				/// Sets the data for the flat rotating follower (length, distance from cam center, initial phase mb0) 
+	void Set_flat_oscillate(double me, double md, double mb0) {e = me; d = md; b0 = mb0; Rb = e+d*sin(b0);};
+
+				/// Evaluate at once all important properties of cam, 
+				/// function of rotation 'par'
+				/// (par in range 0..1, since 1 means 360�!):
+				/// Gets point res, pressure angle g, curvature radius q.
+	virtual void EvaluateCamPoint(double par, Vector& res, double& g, double& q);
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+				/// Curve evaluation.
+				/// Given a parameter "u", finds position on line of the
+				/// kind p=p(u); note that u is in the range 0...1, to make a complete cycle along the cam
+	virtual void Evaluate(Vector& pos, 
+						const double parU, 
+						const double parV = 0., 
+						const double parW = 0.); 
+
+
+				/// Weight evaluation. 
+				/// Given that the shape is defined by a Ch_function, the 
+				/// returned weight is the weight of the function (Ch_function_sequence can
+				/// have different 'weight' values depending on the function segment)
+	virtual double Get_weight(double par) {return law->Get_weight(par * 2 * CH_C_PI);};
+
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif  // END of header
+
+ 
diff --git a/SRC/ChronoEngine/geometry/ChCLinePoly.cpp b/SRC/ChronoEngine/geometry/ChCLinePoly.cpp
new file mode 100644
index 0000000..5847050
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCLinePoly.cpp
@@ -0,0 +1,204 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChCLinePoly.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+ 
+#include "ChCLinePoly.h"
+
+
+namespace chrono
+{
+namespace geometry
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinePoly> a_registration_ChLinePoly;
+
+
+
+//
+// CLASS FOR POLY LINE
+//
+// The object which represent 3d lines/splines  
+//
+
+
+
+ChLinePoly::ChLinePoly (int mnumpoints)
+{
+	closed= 0;
+	numpoints = mnumpoints;
+	points = new Vector [mnumpoints];
+	int degree = 1;
+}
+
+ChLinePoly::~ChLinePoly ()
+{
+	if (points)
+		delete[] points;
+}
+
+void ChLinePoly::Copy (const ChLinePoly* source) 
+{
+	// Copy parent data;
+	ChLine::Copy(source);
+
+	// Copy custom data;
+	numpoints = source->numpoints;
+	degree = source->degree;
+	if (points) 
+		delete[] points;
+	points = new Vector[numpoints];
+	memcpy (points, source->points, (sizeof(Vector) * numpoints));
+};
+
+int ChLinePoly::Get_closed()
+{
+	return closed;
+}
+
+void ChLinePoly::Set_closed(int mc)
+{
+	closed = mc;
+}
+
+int ChLinePoly::Get_numpoints()
+{
+	return numpoints;
+}
+
+int	ChLinePoly::Get_degree()
+{
+	return degree;
+}
+
+Vector ChLinePoly::Get_point(int mnum)
+{
+	if (mnum>=Get_numpoints()) return VNULL;
+
+	return this->points[mnum];
+}
+
+int ChLinePoly::Set_point (int mnum, Vector mpoint)
+{
+	if (mnum>=Get_numpoints()) return FALSE;
+
+	this->points[mnum] = mpoint;
+
+	return TRUE;
+}
+
+
+
+//
+// Curve evaluation.
+//
+
+
+void ChLinePoly::Evaluate(Vector& pos, 
+						const double parU, 
+						const double parV, 
+						const double parW) 
+{
+	double par = parU;
+	pos = VNULL;
+
+	if (par<0) par=0;
+	if (par>1) par=1;
+	int pA= 0;
+	int pB= 0;
+	double epar;
+	if (!closed)
+		epar = par*(Get_numpoints()-1);
+	else
+		epar = par*Get_numpoints();
+	pA = (int)floor(epar);
+	pB = (int)ceil(epar);
+	if (pA<0)
+		pA=0;
+	if (pA>=(Get_numpoints()-1))
+		pA=(Get_numpoints()-1);
+	if (pB>=Get_numpoints())
+	{
+		if (!closed)
+			pB=(Get_numpoints()-1);
+		else
+			pB=0;
+	}
+		// linear interpolation
+	pos = Vadd (Vmul (Get_point(pA), 1-(epar-(double)pA)),
+		  Vmul (Get_point(pB),    epar-(double)pA));
+}
+
+
+double ChLinePoly::Lenght (int sampling)
+{
+	return ChLine::Lenght(1);
+}
+
+
+
+
+
+
+void ChLinePoly::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLine::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << numpoints;
+	mstream << degree;
+
+	for (int i=0; i<numpoints; i++)
+		mstream << points[i];
+}
+
+void ChLinePoly::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLine::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> numpoints;
+	mstream >> degree;
+	
+	if (points) delete[] points;
+	points = new Vector[numpoints];
+	for (int i=0; i<numpoints; i++)
+		mstream >> points[i];
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+////// end
+
diff --git a/SRC/ChronoEngine/geometry/ChCLinePoly.h b/SRC/ChronoEngine/geometry/ChCLinePoly.h
new file mode 100644
index 0000000..4286fa3
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCLinePoly.h
@@ -0,0 +1,155 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_LINEPOLY_H
+#define CHC_LINEPOLY_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCLinePoly.h
+//
+//   Base class for lines with control points
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "ChCLine.h"
+
+
+namespace chrono
+{
+namespace geometry 
+{
+
+
+
+#define CH_GEOCLASS_LINEPOLY   5
+
+///
+/// POLY LINE
+///
+/// Geometric object representing a line in 3D space, which
+/// is controlled by control points.
+///
+	
+class ChApi ChLinePoly : public ChLine 
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChLinePoly,ChLine);
+
+private:
+
+		//
+		// DATA
+		//
+
+	Vector* points; // control points
+	int		numpoints;
+	int		degree;
+
+public:	
+
+		//
+		// CONSTRUCTORS
+		//
+
+	ChLinePoly (int mnumpoints=1);
+
+	~ChLinePoly ();
+
+	ChLinePoly(const ChLinePoly & source)
+				{
+					points = 0;
+					Copy(&source);
+				}
+
+	void Copy (const ChLinePoly* source);
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChLinePoly(*this); 
+					return mgeo;
+				};
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_LINEPOLY;};
+
+
+	virtual int Get_closed();
+	virtual void Set_closed(int mc);
+
+	virtual int Get_complexity() {return numpoints;};
+	virtual void Set_complexity(int mc) {};
+
+			/// Curve evaluation (only parU is used, in 0..1 range)
+	virtual void Evaluate(Vector& pos, 
+						const double parU, 
+						const double parV = 0., 
+						const double parW = 0.);
+
+			/// Returns curve lenght. sampling does not matter
+	double Lenght (int sampling);
+
+
+		//
+		// CUSTOM FUNCTIONS
+		//
+
+			/// Gets the number of control points 
+	virtual int Get_numpoints();
+
+			/// Get the degree of the curve (1= linear,
+			/// 2= quadric, 3= cubic, etc.)
+	virtual int	Get_degree();
+
+			/// Get the n-th control point
+	virtual Vector Get_point(int mnum);
+
+			/// Set the n-th control point
+	virtual int Set_point (int mnum, Vector mpoint);
+
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+#endif  // END of header
+
+
+ 
+	
diff --git a/SRC/ChronoEngine/geometry/ChCSphere.cpp b/SRC/ChronoEngine/geometry/ChCSphere.cpp
new file mode 100644
index 0000000..2fadd77
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCSphere.cpp
@@ -0,0 +1,67 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2006, 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChCSphere.cpp
+//
+// ------------------------------------------------
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+
+
+#include "ChCSphere.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChSphere> a_registration_ChSphere;
+
+
+void ChSphere::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChGeometry::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << center;
+	mstream << rad;
+}
+
+void ChSphere::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChGeometry::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> center;
+	mstream >> rad;
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/geometry/ChCSphere.h b/SRC/ChronoEngine/geometry/ChCSphere.h
new file mode 100644
index 0000000..b61fe46
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCSphere.h
@@ -0,0 +1,156 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_SPHERE_H
+#define CHC_SPHERE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCSphere.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChCGeometry.h"
+
+
+namespace chrono 
+{
+namespace geometry 
+{
+
+
+
+#define EPS_SHPEREDEGENERATE 1e-20
+
+
+#define CH_GEOCLASS_SPHERE   2
+
+
+///
+/// A sphere.
+/// Geometric object for collisions and such.
+///
+
+class ChApi ChSphere : public ChGeometry
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChSphere,ChGeometry);
+
+public:
+
+		//
+		// CONSTRUCTORS
+		//
+
+	ChSphere() 
+				{
+					center= VNULL;
+					rad = 0;
+				};
+	
+	ChSphere(Vector& mc, double mrad) 
+				{
+					center = mc;
+					rad = mrad;
+				}
+
+	ChSphere(const ChSphere & source)
+				{
+					Copy(&source);
+				}
+
+	void Copy (const ChSphere* source) 
+				{
+					center = source->center;
+					rad = source->rad;
+				};
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChSphere(); 
+					mgeo->Copy(this); return mgeo;
+				};
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_SPHERE;};
+
+	virtual void GetBoundingBox(double& xmin, double& xmax, 
+					    double& ymin, double& ymax, 
+						double& zmin, double& zmax,
+						ChMatrix33<>* Rot = NULL)
+				{
+					Vector trsfCenter = center;
+					if (Rot)
+					{
+						trsfCenter = Rot->MatrT_x_Vect(center);
+					}
+					xmin=trsfCenter.x-rad;
+					xmax=trsfCenter.x+rad;
+					ymin=trsfCenter.y-rad;
+					ymax=trsfCenter.y+rad;
+					zmin=trsfCenter.z-rad;
+					zmax=trsfCenter.z+rad;
+				}
+	
+	virtual Vector Baricenter() {return center;};
+
+	virtual void CovarianceMatrix(ChMatrix33<>& C) 
+				{
+					C.Reset();
+					C(0,0)= center.x*center.x;
+					C(1,1)= center.y*center.y;
+					C(2,2)= center.z*center.z;
+				};
+
+				/// This is a solid
+	virtual int GetManifoldDimension() {return 3;}
+
+
+			
+
+
+		//
+		// DATA
+		//
+
+	Vector center;
+
+	double rad;
+
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCTriangle.cpp b/SRC/ChronoEngine/geometry/ChCTriangle.cpp
new file mode 100644
index 0000000..b13384b
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCTriangle.cpp
@@ -0,0 +1,261 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChCTriangle.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+
+
+#include "ChCTriangle.h"
+
+ 
+
+namespace chrono
+{
+namespace geometry
+{
+	
+ChTriangle::ChTriangle() 
+{
+	p1=p2=p3= VNULL;
+};
+	
+ChTriangle::ChTriangle(const ChVector<>& mp1, const ChVector<>& mp2, const ChVector<>& mp3) 
+{
+	p1= mp1; p2= mp2; p3= mp3;
+}
+	
+ChTriangle::ChTriangle(const ChTriangle& source)
+{
+	Copy(&source);
+}
+
+ChTriangle::~ChTriangle() {};
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChTriangle> a_registration_ChTriangle;
+
+
+
+
+void ChTriangle::GetBoundingBox(double& xmin, double& xmax,
+					    double& ymin, double& ymax,
+						double& zmin, double& zmax,
+						ChMatrix33<>* Rot)
+{
+	if (Rot==NULL)
+	{
+		xmin=ChMin(ChMin(p1.x, p2.x),p3.x);
+		ymin=ChMin(ChMin(p1.y, p2.y),p3.y);
+		zmin=ChMin(ChMin(p1.z, p2.z),p3.z);
+		xmax=ChMax(ChMax(p1.x, p2.x),p3.x);
+		ymax=ChMax(ChMax(p1.y, p2.y),p3.y);
+		zmax=ChMax(ChMax(p1.z, p2.z),p3.z);
+	}
+	else
+	{
+		Vector trp1 = Rot->MatrT_x_Vect(p1);
+		Vector trp2 = Rot->MatrT_x_Vect(p2);
+		Vector trp3 = Rot->MatrT_x_Vect(p3);
+		xmin=ChMin(ChMin(trp1.x, trp2.x),trp3.x);
+		ymin=ChMin(ChMin(trp1.y, trp2.y),trp3.y);
+		zmin=ChMin(ChMin(trp1.z, trp2.z),trp3.z);
+		xmax=ChMax(ChMax(trp1.x, trp2.x),trp3.x);
+		ymax=ChMax(ChMax(trp1.y, trp2.y),trp3.y);
+		zmax=ChMax(ChMax(trp1.z, trp2.z),trp3.z);
+	}
+}
+
+Vector ChTriangle::Baricenter()
+{
+	Vector mb;
+	mb.x = (p1.x + p2.x + p3.x)/3.;
+	mb.y = (p1.y + p2.y + p3.y)/3.;
+	mb.z = (p1.z + p2.z + p3.z)/3.;
+	return mb;
+}
+
+void ChTriangle::CovarianceMatrix(ChMatrix33<>& C)
+{
+	C(0,0)= p1.x*p1.x +
+		    p2.x*p2.x +
+			p3.x*p3.x;
+	C(1,1)= p1.y*p1.y +
+		    p2.y*p2.y +
+			p3.y*p3.y;
+	C(2,2)= p1.z*p1.z +
+		    p2.z*p2.z +
+			p3.z*p3.z;
+	C(0,1)= p1.x*p1.y +
+		    p2.x*p2.y +
+			p3.x*p3.y;
+	C(0,2)= p1.x*p1.z +
+		    p2.x*p2.z +
+			p3.x*p3.z;
+	C(1,2)= p1.y*p1.z +
+		    p2.y*p2.z +
+			p3.y*p3.z;
+};
+
+
+bool ChTriangle::Normal(Vector& N)
+{
+    Vector u;
+	u = Vsub(p2,p1);
+    Vector v;
+	v = Vsub(p3,p1);
+
+	Vector n;
+	n = Vcross(u,v);
+
+	double len = Vlenght(n);
+
+	if (fabs (len) > EPS_TRIDEGENERATE)
+		N = Vmul(n, (1.0/len));
+	else
+		return false;
+
+	return true;
+};
+
+
+bool ChTriangle::IsDegenerated()
+{
+	Vector u = Vsub(p2,p1);
+    Vector v = Vsub(p3,p1);
+
+	Vector vcr;
+	vcr = Vcross(u,v);
+	if (fabs(vcr.x) < EPS_TRIDEGENERATE && fabs(vcr.y) < EPS_TRIDEGENERATE && fabs(vcr.z) < EPS_TRIDEGENERATE )
+		return true;
+	return false;
+}
+
+
+
+
+double ChTriangle::PointTriangleDistance(Vector B,
+							   Vector& A1,			///< point of triangle
+							   Vector& A2,			///< point of triangle
+							   Vector& A3,			///< point of triangle
+							   double& mu,
+							   double& mv,
+							   bool& is_into,
+							   Vector& Bprojected)
+{
+	// defaults
+	is_into = false;
+	mu=mv=-1;
+	double mdistance = 10e22;
+
+	Vector Dx, Dy, Dz, T1, T1p;
+
+	Dx= Vsub (A2, A1);
+	Dz= Vsub (A3, A1);
+	Dy= Vcross(Dz,Dx);
+
+	double dylen = Vlenght(Dy);
+
+	if(fabs(dylen)<EPS_TRIDEGENERATE)	// degenere triangle
+		return mdistance;
+
+	Dy= Vmul(Dy,1.0/dylen);
+
+	ChMatrix33<> mA;
+	ChMatrix33<> mAi;
+	mA.Set_A_axis(Dx,Dy,Dz);
+
+	// invert triangle coordinate matrix -if singular matrix, was degenerate triangle-.
+	if (fabs(mA.FastInvert(&mAi)) <0.000001)
+		return mdistance;
+
+	T1 = mAi.Matr_x_Vect( Vsub (B, A1) );
+	T1p = T1;
+	T1p.y=0;
+	mu = T1.x;
+	mv = T1.z;
+	if (mu >=0  &&  mv >=0  &&  mv<=1.0-mu)
+	{
+		is_into = true;
+		mdistance = fabs(T1.y);
+		Bprojected = Vadd(A1, mA.Matr_x_Vect(T1p));
+	}
+
+	return mdistance;
+}
+
+
+
+
+
+double ChTriangle::PointLineDistance(Vector& p, Vector& dA, Vector& dB, double& mu, bool& is_insegment)
+{
+	mu=-1.0;
+	is_insegment = 0;
+	double mdist=10e34;
+
+	Vector vseg = Vsub(dB,dA);
+	Vector vdir = Vnorm(vseg);
+	Vector vray = Vsub(p,dA);
+
+	mdist = Vlenght(Vcross(vray,vdir));
+	mu = Vdot(vray,vdir)/Vlenght(vseg);
+
+	if ((mu>=0) && (mu<=1.0))
+		is_insegment = 1;
+
+	return mdist;
+}
+
+
+
+void ChTriangle::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChGeometry::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << p1;
+	mstream << p2;
+	mstream << p3;
+}
+
+void ChTriangle::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChGeometry::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> p1;
+	mstream >> p2;
+	mstream >> p3;
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/geometry/ChCTriangle.h b/SRC/ChronoEngine/geometry/ChCTriangle.h
new file mode 100644
index 0000000..a7443f0
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCTriangle.h
@@ -0,0 +1,190 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_TRI_H
+#define CHC_TRI_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCTriangle.h
+//
+//   Basic triangle geometry in 3d.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "ChCGeometry.h"
+
+
+
+namespace chrono
+{
+namespace geometry 
+{
+
+
+
+
+#define EPS_TRIDEGENERATE 1e-20
+
+
+#define CH_GEOCLASS_TRIANGLE   1
+
+///
+/// A triangle.
+/// Geometric object for collisions and such.
+///
+
+class ChApi ChTriangle : public ChGeometry
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChTriangle,ChGeometry);
+
+public:
+	ChTriangle();
+	
+	ChTriangle(const ChVector<>& mp1, const ChVector<>& mp2, const ChVector<>& mp3); 
+	
+	ChTriangle(const ChTriangle& source);
+
+	virtual ~ChTriangle();
+
+					/// Assignment operator: copy from another triangle
+	ChTriangle& operator=(const ChTriangle& source)	
+				{
+					if (&source == this) return *this;  
+					this->Copy(&source);
+					return *this; 
+				}
+
+	
+
+	void Copy (const ChTriangle* source) 
+				{
+					p1= source->p1;
+					p2= source->p2;
+					p3= source->p3;
+				};
+
+	ChGeometry* Duplicate () 
+				{
+					ChGeometry* mgeo = new ChTriangle(); 
+					mgeo->Copy(this); return mgeo;
+				};
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_TRIANGLE;};
+
+	virtual void GetBoundingBox(double& xmin, double& xmax, 
+					    double& ymin, double& ymax, 
+						double& zmin, double& zmax, 
+						ChMatrix33<>* Rot = NULL);
+	
+	virtual ChVector<> Baricenter();
+	virtual void CovarianceMatrix(ChMatrix33<>& C);
+
+				/// This is a surface
+	virtual int GetManifoldDimension() {return 2;}
+
+
+		//
+		// CUSTOM FUNCTIONS
+		//
+			
+			// return false if triangle has almost zero area
+	bool IsDegenerated();
+
+			// compute triangle normal
+	bool   Normal(Vector& N);
+
+	ChVector<> GetNormal() 
+				{
+					ChVector<> mn; this->Normal(mn); return mn;
+				};
+
+
+
+			/// Given point B and a generic triangle, computes the distance from the triangle plane,
+			/// returning also the projection of point on the plane and other infos
+			///			\return the signed distance
+	static double PointTriangleDistance(ChVector<> B,	///< point to be measured
+							   ChVector<>& A1,			///< point of triangle 
+							   ChVector<>& A2,			///< point of triangle
+							   ChVector<>& A3,			///< point of triangle
+							   double& mu,				///< returns U parametric coord of projection
+							   double& mv,				///< returns V parametric coord of projection
+							   bool& is_into,			///< returns true if projection falls on the triangle
+							   ChVector<>& Bprojected	///< returns the position of the projected point
+							   );
+
+			/// Given point B, computes the distance from this triangle plane,
+			/// returning also the projection of point on the plane and other infos
+			///			\return the signed distance
+	double PointTriangleDistance(ChVector<> B,			///< point to be measured
+							   double& mu,				///< returns U parametric coord of projection
+							   double& mv,				///< returns V parametric coord of projection
+							   bool& is_into,			///< returns true if projection falls on the triangle
+							   ChVector<>& Bprojected	///< returns the position of the projected point
+							   )
+				{ 
+					return PointTriangleDistance(B, this->p1, this->p2, this->p3, mu, mv, is_into, Bprojected); 
+				}
+
+			/// Calculate distance between a point p and a line identified
+			/// with segment dA,dB. Returns distance. Also, the mu value reference
+			/// tells if the nearest projection of point on line falls into segment (for mu 0...1)
+			///			\return the distance
+	static double PointLineDistance(ChVector<>& p,	///< point to be measured 
+								ChVector<>& dA,		///< a point on the line 
+								ChVector<>& dB,		///< another point on the line
+								double& mu,			///< parametric coord: if in 0..1 interval, projection is between dA and dB 
+								bool& is_insegment	///< returns true if projected point is between dA and dB
+								);
+
+		//
+		// DATA
+		//
+
+	ChVector<> p1;
+	ChVector<> p2;
+	ChVector<> p3;
+
+
+		//
+		// STREAMING
+		//
+
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	void StreamIN(ChStreamInBinary& mstream); 
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCTriangleMesh.h b/SRC/ChronoEngine/geometry/ChCTriangleMesh.h
new file mode 100644
index 0000000..f87f13f
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCTriangleMesh.h
@@ -0,0 +1,123 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_TRIANGLEMESH_H
+#define CHC_TRIANGLEMESH_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCTriangleMesh.h
+//
+//   Basic interface for triangle meshes in 3d.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "ChCTriangle.h"
+
+
+
+namespace chrono
+{
+namespace geometry 
+{
+
+
+
+#define CH_GEOCLASS_TRIANGLEMESH   9
+
+
+///
+/// A basic triangle mesh: just a list of triangles (no edge connectivity info).
+///
+
+class ChApi ChTriangleMesh : public ChGeometry
+{
+					// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChTriangleMesh,ChGeometry);
+
+		// 
+		// DATA
+		// 
+
+	//std::vector<ChTriangle>	m_triangles;
+	
+
+public:
+	ChTriangleMesh () {};
+
+
+		//
+		// MESH INTERFACE FUNCTIONS
+		//
+
+			/// Add a triangle to this triangle mesh, by specifying the three coordinates
+	virtual void addTriangle(const ChVector<>& vertex0, const ChVector<>& vertex1, const ChVector<>& vertex2) = 0;
+	
+			/// Add a triangle to this triangle mesh, by specifying a ChTriangle 
+	virtual void addTriangle(const ChTriangle& atriangle) = 0;
+
+			/// Get the number of triangles already added to this mesh
+	virtual int getNumTriangles() const = 0;
+
+			/// Get the n-th triangle in mesh
+	virtual ChTriangle getTriangle(int index) const = 0;
+
+			/// Clear all data
+	virtual void Clear() = 0;
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_TRIANGLEMESH;};
+
+	/*
+	virtual void GetBoundingBox(double& xmin, double& xmax, 
+					    double& ymin, double& ymax, 
+						double& zmin, double& zmax, 
+						ChMatrix33<>* Rot = NULL) { }; //TODO
+	
+	virtual Vector Baricenter();//TODO
+	virtual void CovarianceMatrix(ChMatrix33<>& C);//TODO
+    */
+				/// This is a surface
+	virtual int GetManifoldDimension() {return 2;}
+
+
+
+		//
+		// STREAMING
+		//
+
+	//void StreamOUT(ChStreamOutBinary& mstream);//TODO
+
+	//void StreamIN(ChStreamInBinary& mstream); //TODO
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCTriangleMeshConnected.cpp b/SRC/ChronoEngine/geometry/ChCTriangleMeshConnected.cpp
new file mode 100644
index 0000000..316ee70
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCTriangleMeshConnected.cpp
@@ -0,0 +1,980 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChCTriangleMeshConnected.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdio.h>
+
+
+#include "ChCTriangleMeshConnected.h"
+
+ 
+
+namespace chrono
+{
+namespace geometry
+{
+	
+
+
+// NOTE!!!
+// THE FOLLOWING CODE IS MODIFIED BY A.TASORA TO MATCH SOME
+// FEATURES OF THE C::E CLASS
+
+/*!
+**
+** Copyright (c) 20011 by John W. Ratcliff mailto:jratcliffscarab at gmail.com
+**
+**
+** The MIT license:
+**
+** Permission is hereby granted, free of charge, to any person obtaining a copy
+** of this software and associated documentation files (the "Software"), to deal
+** in the Software without restriction, including without limitation the rights
+** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+** copies of the Software, and to permit persons to whom the Software is furnished
+** to do so, subject to the following conditions:
+**
+** The above copyright notice and this permission notice shall be included in all
+** copies or substantial portions of the Software.
+
+** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifdef _WIN32
+#	define strcasecmp _stricmp 
+#endif
+
+#pragma warning(disable:4996)
+
+typedef std::vector< int > IntVector;
+typedef std::vector< float > FloatVector;
+
+namespace WAVEFRONT
+{
+
+/*******************************************************************/
+/******************** InParser.h  ********************************/
+/*******************************************************************/
+class InPlaceParserInterface
+{
+public:
+	virtual int ParseLine(int lineno,int argc,const char **argv) =0;  // return TRUE to continue parsing, return FALSE to abort parsing process
+};
+
+enum SeparatorType
+{
+	ST_DATA,        // is data
+	ST_HARD,        // is a hard separator
+	ST_SOFT,        // is a soft separator
+	ST_EOS          // is a comment symbol, and everything past this character should be ignored
+};
+
+class InPlaceParser
+{
+public:
+	InPlaceParser(void)
+	{
+		Init();
+	}
+
+	InPlaceParser(char *data,int len)
+	{
+		Init();
+		SetSourceData(data,len);
+	}
+
+	InPlaceParser(const char *fname)
+	{
+		Init();
+		SetFile(fname);
+	}
+
+	~InPlaceParser(void);
+
+	void Init(void)
+	{
+		mQuoteChar = 34;
+		mData = 0;
+		mLen  = 0;
+		mMyAlloc = false;
+		for (int i=0; i<256; i++)
+		{
+			mHard[i] = ST_DATA;
+			mHardString[i*2] = (char)i;
+			mHardString[i*2+1] = 0;
+		}
+		mHard[0]  = ST_EOS;
+		mHard[32] = ST_SOFT;
+		mHard[9]  = ST_SOFT;
+		mHard[13] = ST_SOFT;
+		mHard[10] = ST_SOFT;
+	}
+
+	void SetFile(const char *fname); // use this file as source data to parse.
+
+	void SetSourceData(char *data,int len)
+	{
+		mData = data;
+		mLen  = len;
+		mMyAlloc = false;
+	};
+
+	int  Parse(InPlaceParserInterface *callback); // returns true if entire file was parsed, false if it aborted for some reason
+
+	int ProcessLine(int lineno,char *line,InPlaceParserInterface *callback);
+
+	const char ** GetArglist(char *source,int &count); // convert source string into an arg list, this is a destructive parse.
+
+	void SetHardSeparator(char c) // add a hard separator
+	{
+		mHard[c] = ST_HARD;
+	}
+
+	void SetHard(char c) // add a hard separator
+	{
+		mHard[c] = ST_HARD;
+	}
+
+
+	void SetCommentSymbol(char c) // comment character, treated as 'end of string'
+	{
+		mHard[c] = ST_EOS;
+	}
+
+	void ClearHardSeparator(char c)
+	{
+		mHard[c] = ST_DATA;
+	}
+
+
+	void DefaultSymbols(void); // set up default symbols for hard seperator and comment symbol of the '#' character.
+
+	bool EOS(char c)
+	{
+		if ( mHard[c] == ST_EOS )
+		{
+			return true;
+		}
+		return false;
+	}
+
+	void SetQuoteChar(char c)
+	{
+		mQuoteChar = c;
+	}
+
+private:
+
+
+	inline char * AddHard(int &argc,const char **argv,char *foo);
+	inline bool   IsHard(char c);
+	inline char * SkipSpaces(char *foo);
+	inline bool   IsWhiteSpace(char c);
+	inline bool   IsNonSeparator(char c); // non seperator,neither hard nor soft
+
+	bool   mMyAlloc; // whether or not *I* allocated the buffer and am responsible for deleting it.
+	char  *mData;  // ascii data to parse.
+	int    mLen;   // length of data
+	SeparatorType  mHard[256];
+	char   mHardString[256*2];
+	char           mQuoteChar;
+};
+
+/*******************************************************************/
+/******************** InParser.cpp  ********************************/
+/*******************************************************************/
+void InPlaceParser::SetFile(const char *fname)
+{
+	if ( mMyAlloc )
+	{
+		free(mData);
+	}
+	mData = 0;
+	mLen  = 0;
+	mMyAlloc = false;
+
+	FILE *fph = fopen(fname,"rb");
+	if ( fph )
+	{
+		fseek(fph,0L,SEEK_END);
+		mLen = ftell(fph);
+		fseek(fph,0L,SEEK_SET);
+		if ( mLen )
+		{
+			mData = (char *) malloc(sizeof(char)*(mLen+1));
+			size_t ok = fread(mData, mLen, 1, fph);
+			if ( !ok )
+			{
+				free(mData);
+				mData = 0;
+			}
+			else
+			{
+				mData[mLen] = 0; // zero byte terminate end of file marker.
+				mMyAlloc = true;
+			}
+		}
+		fclose(fph);
+	}
+
+}
+
+InPlaceParser::~InPlaceParser(void)
+{
+	if ( mMyAlloc )
+	{
+		free(mData);
+	}
+}
+
+#define MAXARGS 512
+
+bool InPlaceParser::IsHard(char c)
+{
+	return mHard[c] == ST_HARD;
+}
+
+char * InPlaceParser::AddHard(int &argc,const char **argv,char *foo)
+{
+	while ( IsHard(*foo) )
+	{
+		const char *hard = &mHardString[*foo*2];
+		if ( argc < MAXARGS )
+		{
+			argv[argc++] = hard;
+		}
+		foo++;
+	}
+	return foo;
+}
+
+bool   InPlaceParser::IsWhiteSpace(char c)
+{
+	return mHard[c] == ST_SOFT;
+}
+
+char * InPlaceParser::SkipSpaces(char *foo)
+{
+	while ( !EOS(*foo) && IsWhiteSpace(*foo) ) foo++;
+	return foo;
+}
+
+bool InPlaceParser::IsNonSeparator(char c)
+{
+	if ( !IsHard(c) && !IsWhiteSpace(c) && c != 0 ) return true;
+	return false;
+}
+
+
+int InPlaceParser::ProcessLine(int lineno,char *line,InPlaceParserInterface *callback)
+{
+	int ret = 0;
+
+	const char *argv[MAXARGS];
+	int argc = 0;
+
+	char *foo = line;
+
+	while ( !EOS(*foo) && argc < MAXARGS )
+	{
+
+		foo = SkipSpaces(foo); // skip any leading spaces
+
+		if ( EOS(*foo) ) break;
+
+		if ( *foo == mQuoteChar ) // if it is an open quote
+		{
+			foo++;
+			if ( argc < MAXARGS )
+			{
+				argv[argc++] = foo;
+			}
+			while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
+			if ( !EOS(*foo) )
+			{
+				*foo = 0; // replace close quote with zero byte EOS
+				foo++;
+			}
+		}
+		else
+		{
+
+			foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
+
+			if ( IsNonSeparator(*foo) )  // add non-hard argument.
+			{
+				bool quote  = false;
+				if ( *foo == mQuoteChar )
+				{
+					foo++;
+					quote = true;
+				}
+
+				if ( argc < MAXARGS )
+				{
+					argv[argc++] = foo;
+				}
+
+				if ( quote )
+				{
+					while (*foo && *foo != mQuoteChar ) foo++;
+					if ( *foo ) *foo = 32;
+				}
+
+				// continue..until we hit an eos ..
+				while ( !EOS(*foo) ) // until we hit EOS
+				{
+					if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
+					{
+						*foo = 0;
+						foo++;
+						break;
+					}
+					else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
+					{
+						const char *hard = &mHardString[*foo*2];
+						*foo = 0;
+						if ( argc < MAXARGS )
+						{
+							argv[argc++] = hard;
+						}
+						foo++;
+						break;
+					}
+					foo++;
+				} // end of while loop...
+			}
+		}
+	}
+
+	if ( argc )
+	{
+		ret = callback->ParseLine(lineno, argc, argv );
+	}
+
+	return ret;
+}
+
+int  InPlaceParser::Parse(InPlaceParserInterface *callback) // returns true if entire file was parsed, false if it aborted for some reason
+{
+	assert( callback );
+	if ( !mData ) return 0;
+
+	int ret = 0;
+
+	int lineno = 0;
+
+	char *foo   = mData;
+	char *begin = foo;
+
+
+	while ( *foo )
+	{
+		if ( *foo == 10 || *foo == 13 )
+		{
+			lineno++;
+			*foo = 0;
+
+			if ( *begin ) // if there is any data to parse at all...
+			{
+				int v = ProcessLine(lineno,begin,callback);
+				if ( v ) ret = v;
+			}
+
+			foo++;
+			if ( *foo == 10 ) foo++; // skip line feed, if it is in the carraige-return line-feed format...
+			begin = foo;
+		}
+		else
+		{
+			foo++;
+		}
+	}
+
+	lineno++; // lasst line.
+
+	int v = ProcessLine(lineno,begin,callback);
+	if ( v ) ret = v;
+	return ret;
+}
+
+
+void InPlaceParser::DefaultSymbols(void)
+{
+	SetHardSeparator(',');
+	SetHardSeparator('(');
+	SetHardSeparator(')');
+	SetHardSeparator('=');
+	SetHardSeparator('[');
+	SetHardSeparator(']');
+	SetHardSeparator('{');
+	SetHardSeparator('}');
+	SetCommentSymbol('#');
+}
+
+
+const char ** InPlaceParser::GetArglist(char *line,int &count) // convert source string into an arg list, this is a destructive parse.
+{
+	const char **ret = 0;
+
+	static const char *argv[MAXARGS];
+	int argc = 0;
+
+	char *foo = line;
+
+	while ( !EOS(*foo) && argc < MAXARGS )
+	{
+
+		foo = SkipSpaces(foo); // skip any leading spaces
+
+		if ( EOS(*foo) ) break;
+
+		if ( *foo == mQuoteChar ) // if it is an open quote
+		{
+			foo++;
+			if ( argc < MAXARGS )
+			{
+				argv[argc++] = foo;
+			}
+			while ( !EOS(*foo) && *foo != mQuoteChar ) foo++;
+			if ( !EOS(*foo) )
+			{
+				*foo = 0; // replace close quote with zero byte EOS
+				foo++;
+			}
+		}
+		else
+		{
+
+			foo = AddHard(argc,argv,foo); // add any hard separators, skip any spaces
+
+			if ( IsNonSeparator(*foo) )  // add non-hard argument.
+			{
+				bool quote  = false;
+				if ( *foo == mQuoteChar )
+				{
+					foo++;
+					quote = true;
+				}
+
+				if ( argc < MAXARGS )
+				{
+					argv[argc++] = foo;
+				}
+
+				if ( quote )
+				{
+					while (*foo && *foo != mQuoteChar ) foo++;
+					if ( *foo ) *foo = 32;
+				}
+
+				// continue..until we hit an eos ..
+				while ( !EOS(*foo) ) // until we hit EOS
+				{
+					if ( IsWhiteSpace(*foo) ) // if we hit a space, stomp a zero byte, and exit
+					{
+						*foo = 0;
+						foo++;
+						break;
+					}
+					else if ( IsHard(*foo) ) // if we hit a hard separator, stomp a zero byte and store the hard separator argument
+					{
+						const char *hard = &mHardString[*foo*2];
+						*foo = 0;
+						if ( argc < MAXARGS )
+						{
+							argv[argc++] = hard;
+						}
+						foo++;
+						break;
+					}
+					foo++;
+				} // end of while loop...
+			}
+		}
+	}
+
+	count = argc;
+	if ( argc )
+	{
+		ret = argv;
+	}
+
+	return ret;
+}
+
+/*******************************************************************/
+/******************** Geometry.h  ********************************/
+/*******************************************************************/
+
+class GeometryVertex
+{
+public:
+	float        mPos[3];
+	float        mNormal[3];
+	float        mTexel[2];
+};
+
+
+class GeometryInterface
+{
+public:
+
+	virtual void NodeTriangle(const GeometryVertex * /*v1*/,const GeometryVertex * /*v2*/,const GeometryVertex * /*v3*/, bool /*textured*/)
+	{
+	}
+
+};
+
+
+/*******************************************************************/
+/******************** Obj.h  ********************************/
+/*******************************************************************/
+
+
+class OBJ : public InPlaceParserInterface
+{
+public:
+  int LoadMesh(const char *fname,GeometryInterface *callback, bool textured);
+  int ParseLine(int lineno,int argc,const char **argv);  // return TRUE to continue parsing, return FALSE to abort parsing process
+private:
+
+  void GetVertex(GeometryVertex &v,const char *face) const;
+
+public: //***ALEX***
+  FloatVector     mVerts;
+  FloatVector     mTexels;
+  FloatVector     mNormals;
+
+  //***ALEX***
+  IntVector mIndexesVerts;
+  IntVector mIndexesNormals;
+  IntVector mIndexesTexels;
+
+
+  bool            mTextured;
+
+  GeometryInterface *mCallback;
+};
+
+
+/*******************************************************************/
+/******************** Obj.cpp  ********************************/
+/*******************************************************************/
+
+int OBJ::LoadMesh(const char *fname,GeometryInterface *iface, bool textured)
+{
+  mTextured = textured;
+  int ret = 0;
+
+  mVerts.clear();
+  mTexels.clear();
+  mNormals.clear();
+
+    //***ALEX***
+  mIndexesVerts.clear();
+  mIndexesNormals.clear();
+  mIndexesTexels.clear();
+
+  mCallback = iface;
+
+  InPlaceParser ipp(fname);
+
+  ipp.Parse(this);
+
+return ret;
+}
+
+/***
+static const char * GetArg(const char **argv,int i,int argc)
+{
+  const char * ret = 0;
+  if ( i < argc ) ret = argv[i];
+  return ret;
+}
+****/
+
+void OBJ::GetVertex(GeometryVertex &v,const char *face) const
+{
+  v.mPos[0] = 0;
+  v.mPos[1] = 0;
+  v.mPos[2] = 0;
+
+  v.mTexel[0] = 0;
+  v.mTexel[1] = 0;
+
+  v.mNormal[0] = 0;
+  v.mNormal[1] = 1;
+  v.mNormal[2] = 0;
+
+  int index = atoi( face )-1;
+
+  const char *texel = strstr(face,"/");
+
+  if ( texel )
+  {
+    int tindex = atoi( texel+1) - 1;
+
+    if ( tindex >=0 && tindex < (int)(mTexels.size()/2) )
+    {
+    	const float *t = &mTexels[tindex*2];
+
+      v.mTexel[0] = t[0];
+      v.mTexel[1] = t[1];
+
+    }
+
+    const char *normal = strstr(texel+1,"/");
+    if ( normal )
+    {
+      int nindex = atoi( normal+1 ) - 1;
+
+      if (nindex >= 0 && nindex < (int)(mNormals.size()/3) )
+      {
+      	const float *n = &mNormals[nindex*3];
+
+        v.mNormal[0] = n[0];
+        v.mNormal[1] = n[1];
+        v.mNormal[2] = n[2];
+      }
+    }
+  }
+
+  if ( index >= 0 && index < (int)(mVerts.size()/3) )
+  {
+
+    const float *p = &mVerts[index*3];
+
+    v.mPos[0] = p[0];
+    v.mPos[1] = p[1];
+    v.mPos[2] = p[2];
+  }
+
+}
+
+int OBJ::ParseLine(int /*lineno*/,int argc,const char **argv)  // return TRUE to continue parsing, return FALSE to abort parsing process
+{
+  int ret = 0;
+
+  if ( argc >= 1 )
+  {
+    const char *foo = argv[0];
+    if ( *foo != '#' )
+    {
+      if ( strcasecmp(argv[0],"v") == 0 && argc == 4 )
+      {
+        float vx = (float) atof( argv[1] );
+        float vy = (float) atof( argv[2] );
+        float vz = (float) atof( argv[3] );
+        mVerts.push_back(vx);
+        mVerts.push_back(vy);
+        mVerts.push_back(vz);
+      }
+      else if ( strcasecmp(argv[0],"vt") == 0 && (argc == 3 || argc == 4))
+      {
+        // ignore 3rd component if present
+        float tx = (float) atof( argv[1] );
+        float ty = (float) atof( argv[2] );
+        mTexels.push_back(tx);
+        mTexels.push_back(ty);
+      }
+      else if ( strcasecmp(argv[0],"vn") == 0 && argc == 4 )
+      {
+        float normalx = (float) atof(argv[1]);
+        float normaly = (float) atof(argv[2]);
+        float normalz = (float) atof(argv[3]);
+        mNormals.push_back(normalx);	
+        mNormals.push_back(normaly);
+        mNormals.push_back(normalz);
+      }
+      else if ( strcasecmp(argv[0],"f") == 0 && argc >= 4 )
+      {
+		  // ***ALEX*** do not use the BuildMesh stuff
+		int vcount = argc-1;
+		for (int i=1; i<argc; i++)
+		{
+			if (i>3) 
+				break; // should do a fan here..
+
+			// the index of i-th vertex
+			int index = atoi( argv[i] )-1;
+			this->mIndexesVerts.push_back(index);
+
+			const char *texel = strstr( argv[i],"/");
+			if ( texel )
+			{
+				// the index of i-th texel
+				int tindex = atoi( texel+1) - 1;
+				this->mIndexesTexels.push_back(tindex);
+
+				const char *normal = strstr(texel+1,"/");
+				if ( normal )
+				{
+				  // the index of i-th normal
+				  int nindex = atoi( normal+1 ) - 1;
+				  this->mIndexesNormals.push_back(nindex);
+				}
+			}
+
+
+        }
+
+		 /* ***ALEX***
+        GeometryVertex v[32];
+
+        int vcount = argc-1;
+
+        for (int i=1; i<argc; i++)
+        {
+          GetVertex(v[i-1],argv[i] );
+        }
+
+
+		mCallback->NodeTriangle(&v[0],&v[1],&v[2], mTextured);
+
+        if ( vcount >=3 ) // do the fan
+        {
+          for (int i=2; i<(vcount-1); i++)
+          {
+            mCallback->NodeTriangle(&v[0],&v[i],&v[i+1], mTextured);
+          }
+        }
+		*/
+
+      }
+    }
+  }
+
+  return ret;
+}
+
+
+
+
+class BuildMesh : public GeometryInterface
+{
+public:
+
+	int GetIndex(const float *p, const float *texCoord)
+	{
+
+		int vcount = (int)mVertices.size()/3;
+
+		if(vcount>0)
+		{
+			//New MS STL library checks indices in debug build, so zero causes an assert if it is empty.
+			const float *v = &mVertices[0];
+			const float *t = texCoord != NULL ? &mTexCoords[0] : NULL;
+
+			for (int i=0; i<vcount; i++)
+			{
+				if ( v[0] == p[0] && v[1] == p[1] && v[2] == p[2] )
+				{
+					if (texCoord == NULL || (t[0] == texCoord[0] && t[1] == texCoord[1]))
+					{
+						return i;
+					}
+				}
+				v+=3;
+				if (t != NULL)
+					t += 2;
+			}
+		}
+
+		mVertices.push_back( p[0] );
+		mVertices.push_back( p[1] );
+		mVertices.push_back( p[2] );
+
+		if (texCoord != NULL)
+		{
+			mTexCoords.push_back( texCoord[0] );
+			mTexCoords.push_back( texCoord[1] );
+		}
+
+		return vcount;
+	}
+
+	virtual void NodeTriangle(const GeometryVertex *v1,const GeometryVertex *v2,const GeometryVertex *v3, bool textured)
+	{
+		mIndices.push_back( GetIndex(v1->mPos, textured ? v1->mTexel : NULL) );
+		mIndices.push_back( GetIndex(v2->mPos, textured ? v2->mTexel : NULL) );
+		mIndices.push_back( GetIndex(v3->mPos, textured ? v3->mTexel : NULL) );
+	}
+
+  const FloatVector& GetVertices(void) const { return mVertices; };
+  const FloatVector& GetTexCoords(void) const { return mTexCoords; };
+  const IntVector& GetIndices(void) const { return mIndices; };
+
+private:
+  FloatVector     mVertices;
+  FloatVector     mTexCoords;
+  IntVector       mIndices;
+};
+
+};
+
+
+using namespace WAVEFRONT;
+
+
+void ChTriangleMeshConnected::LoadWavefrontMesh(std::string filename, bool load_normals, bool load_uv)
+{
+	this->m_vertices.clear();
+	this->m_normals.clear();
+	this->m_UV.clear();
+	this->m_face_v_indices.clear();
+	this->m_face_n_indices.clear();
+	this->m_face_u_indices.clear();
+	
+	GeometryInterface emptybm; // BuildMesh bm;
+
+	OBJ obj;
+
+	obj.LoadMesh(filename.c_str(), &emptybm, true);
+
+	for (unsigned int iv= 0; iv< obj.mVerts.size(); iv += 3)
+	{
+		this->m_vertices.push_back(ChVector<double> (obj.mVerts[iv], obj.mVerts[iv+1], obj.mVerts[iv+2]));
+	}
+	for (unsigned int in= 0; in< obj.mNormals.size(); in += 3)
+	{
+		this->m_normals.push_back(ChVector<double> (obj.mNormals[in], obj.mNormals[in+1], obj.mNormals[in+2]));
+	}
+	for (unsigned int it= 0; it< obj.mTexels.size(); it += 2) // +2 because only u,v each texel
+	{
+		this->m_UV.push_back(ChVector<double> (obj.mTexels[it], obj.mTexels[it+1], 0));
+	}
+	for (unsigned int iiv= 0; iiv< obj.mIndexesVerts.size(); iiv += 3)
+	{
+		this->m_face_v_indices.push_back(ChVector<int> (obj.mIndexesVerts[iiv], obj.mIndexesVerts[iiv+1], obj.mIndexesVerts[iiv+2]));
+	}
+	for (unsigned int iin= 0; iin< obj.mIndexesNormals.size(); iin += 3)
+	{
+		this->m_face_n_indices.push_back(ChVector<int> (obj.mIndexesNormals[iin], obj.mIndexesNormals[iin+1], obj.mIndexesNormals[iin+2]));
+	}
+	for (unsigned int iit= 0; iit< obj.mIndexesTexels.size(); iit += 3)
+	{
+		this->m_face_u_indices.push_back(ChVector<int> (obj.mIndexesTexels[iit], obj.mIndexesTexels[iit+1], obj.mIndexesTexels[iit+2]));
+	}
+}
+
+
+/*
+using namespace WAVEFRONT;
+
+
+WavefrontObj::WavefrontObj(void)
+{
+	mVertexCount = 0;
+	mTriCount    = 0;
+	mIndices     = 0;
+	mVertices    = NULL;
+	mTexCoords   = NULL;
+}
+
+WavefrontObj::~WavefrontObj(void)
+{
+	delete mIndices;
+	delete mVertices;
+}
+
+unsigned int WavefrontObj::loadObj(const char *fname, bool textured) // load a wavefront obj returns number of triangles that were loaded.  Data is persists until the class is destructed.
+{
+
+	unsigned int ret = 0;
+
+	delete mVertices;
+	mVertices = 0;
+	delete mIndices;
+	mIndices = 0;
+	mVertexCount = 0;
+	mTriCount = 0;
+
+
+  BuildMesh bm;
+
+  OBJ obj;
+
+  obj.LoadMesh(fname,&bm, textured);
+
+
+	const FloatVector &vlist = bm.GetVertices();
+	const IntVector &indices = bm.GetIndices();
+	if ( vlist.size() )
+	{
+		mVertexCount = (int)vlist.size()/3;
+		mVertices = new float[mVertexCount*3];
+		memcpy( mVertices, &vlist[0], sizeof(float)*mVertexCount*3 );
+
+		if (textured)
+		{
+			mTexCoords = new float[mVertexCount * 2];
+			const FloatVector& tList = bm.GetTexCoords();
+			memcpy( mTexCoords, &tList[0], sizeof(float) * mVertexCount * 2);
+		}
+
+		mTriCount = (int)indices.size()/3;
+		mIndices = new int[mTriCount*3*sizeof(int)];
+		memcpy(mIndices, &indices[0], sizeof(int)*mTriCount*3);
+		ret = mTriCount;
+	}
+
+
+	return ret;
+}
+
+
+bool WavefrontObj::saveObj(const char *fname,int vcount,const float *vertices,int tcount,const int *indices)
+{
+  bool ret = false;
+
+  FILE *fph = fopen(fname,"wb");
+  if ( fph )
+  {
+    for (int i=0; i<vcount; i++)
+    {
+      fprintf(fph,"v %0.9f %0.9f %0.9f\r\n", vertices[0], vertices[1], vertices[2] );
+      vertices+=3;
+    }
+    for (int i=0; i<tcount; i++)
+    {
+      fprintf(fph,"f %d %d %d\r\n", indices[0]+1, indices[1]+1, indices[2]+1 );
+      indices+=3;
+    }
+    fclose(fph);
+    ret = true;
+  }
+  return ret;
+}
+
+*/
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/geometry/ChCTriangleMeshConnected.h b/SRC/ChronoEngine/geometry/ChCTriangleMeshConnected.h
new file mode 100644
index 0000000..74ed303
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCTriangleMeshConnected.h
@@ -0,0 +1,163 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_TRIANGLEMESHCONNECTED_H
+#define CHC_TRIANGLEMESHCONNECTED_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCTriangleMeshConnected.h
+//
+//   Triangle mesh in 3d, with shared vertices
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "ChCTriangleMesh.h"
+
+
+
+namespace chrono
+{
+namespace geometry 
+{
+
+
+
+#define CH_GEOCLASS_TRIANGLEMESHCONNECTED   11
+
+
+
+/// A triangle mesh with connectivity info: vertices can be 
+/// shared between faces.
+
+class ChApi ChTriangleMeshConnected : public ChTriangleMesh
+{
+					// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChTriangleMeshConnected,ChTriangleMesh);
+
+		// 
+		// DATA
+		// 
+
+	std::vector< ChVector<double> >	m_vertices;
+	std::vector< ChVector<double> >	m_normals;
+	std::vector< ChVector<double> >	m_UV;
+	std::vector< ChVector<float> >	m_colors;
+
+	std::vector< ChVector<int> >	m_face_v_indices;
+	std::vector< ChVector<int> >	m_face_n_indices;
+	std::vector< ChVector<int> >	m_face_u_indices;
+	std::vector< ChVector<int> >	m_face_col_indices;
+	
+public:
+	ChTriangleMeshConnected () {};
+
+
+		//
+		// CUSTOM FUNCTIONS
+		//
+
+	std::vector< ChVector<double> >& getCoordsVertices() {return m_vertices;}
+	std::vector< ChVector<double> >& getCoordsNormals()  {return m_normals;}
+	std::vector< ChVector<double> >& getCoordsUV()	     {return m_UV;}
+	std::vector< ChVector<float > >& getCoordsColors()	 {return m_colors;}
+
+	std::vector< ChVector<int> >&	getIndicesVertexes() {return m_face_v_indices;}
+	std::vector< ChVector<int> >&	getIndicesNormals() {return m_face_n_indices;}
+	std::vector< ChVector<int> >&	getIndicesUV() {return m_face_u_indices;}
+	std::vector< ChVector<int> >&	getIndicesColors() {return m_face_col_indices;}
+
+		// Load a triangle mesh saved as a Wavefront .obj file
+	void LoadWavefrontMesh(std::string filename, bool load_normals = true, bool load_uv = false);
+
+
+		//
+		// MESH INTERFACE FUNCTIONS
+		//
+
+			/// Add a triangle to this triangle mesh, by specifying the three coordinates.
+			/// This is disconnected - no vertex sharing is used even if it could be..
+	virtual void addTriangle(const ChVector<>& vertex0, const ChVector<>& vertex1, const ChVector<>& vertex2)
+	{
+		int base_v = m_vertices.size();
+		m_vertices.push_back(vertex0);
+		m_vertices.push_back(vertex1);
+		m_vertices.push_back(vertex2);
+		m_face_v_indices.push_back(ChVector<int>(base_v, base_v+1, base_v+2));
+	}
+			/// Add a triangle to this triangle mesh, by specifying a ChTriangle 
+	virtual void addTriangle(const ChTriangle& atriangle)
+	{
+		int base_v = m_vertices.size();
+		m_vertices.push_back(atriangle.p1);
+		m_vertices.push_back(atriangle.p2);
+		m_vertices.push_back(atriangle.p3);
+		m_face_v_indices.push_back(ChVector<int>(base_v, base_v+1, base_v+2));
+	}
+
+			/// Get the number of triangles already added to this mesh
+	virtual int getNumTriangles() const
+	{
+		return m_face_v_indices.size();
+	}
+
+			/// Access the n-th triangle in mesh
+	virtual ChTriangle getTriangle(int index) const
+	{
+		return ChTriangle( m_vertices[m_face_v_indices[index].x],  m_vertices[m_face_v_indices[index].y],  m_vertices[m_face_v_indices[index].z] );
+	}
+
+			/// Clear all data
+	virtual void Clear()
+	{
+		this->getCoordsVertices().clear();
+		this->getCoordsNormals().clear();
+		this->getCoordsUV().clear();
+		this->getCoordsColors().clear();
+		this->getIndicesVertexes().clear();
+		this->getIndicesNormals().clear();
+		this->getIndicesNormals().clear();
+		this->getIndicesColors().clear();
+	}
+
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_TRIANGLEMESHCONNECTED;};
+
+		//
+		// STREAMING
+		//
+
+	//void StreamOUT(ChStreamOutBinary& mstream);//***TO DO***
+
+	//void StreamIN(ChStreamInBinary& mstream); //***TO DO***
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/geometry/ChCTriangleMeshSoup.h b/SRC/ChronoEngine/geometry/ChCTriangleMeshSoup.h
new file mode 100644
index 0000000..44b8187
--- /dev/null
+++ b/SRC/ChronoEngine/geometry/ChCTriangleMeshSoup.h
@@ -0,0 +1,129 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHC_TRIANGLEMESHSOUP_H
+#define CHC_TRIANGLEMESHSOUP_H
+
+//////////////////////////////////////////////////
+//  
+//   ChCTriangleMeshSoup.h
+//
+//   Basic triangle mesh with disconnected triangles
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "ChCTriangleMesh.h"
+
+
+
+namespace chrono
+{
+namespace geometry 
+{
+
+
+
+#define CH_GEOCLASS_TRIANGLEMESHSOUP   12
+
+
+///
+/// A basic triangle mesh: just a list of triangles (no edge connectivity info).
+///
+
+class ChApi ChTriangleMeshSoup : public ChTriangleMesh
+{
+					// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChTriangleMeshSoup,ChTriangleMesh);
+
+		// 
+		// DATA
+		// 
+
+	std::vector<ChTriangle>	m_triangles;
+	
+
+public:
+	ChTriangleMeshSoup () {};
+
+
+				/// Access the n-th triangle in mesh
+	virtual ChTriangle& Triangle(int index)
+	{
+		return m_triangles[index];
+	}
+
+
+		//
+		// MESH INTERFACE FUNCTIONS
+		//
+
+			/// Add a triangle to this triangle mesh, by specifying the three coordinates
+	virtual void  addTriangle(const ChVector<>& vertex0, const ChVector<>& vertex1, const ChVector<>& vertex2)
+	{
+		ChTriangle tri(vertex0,vertex1,vertex2);
+		m_triangles.push_back(tri);
+	}
+			/// Add a triangle to this triangle mesh, by specifying a ChTriangle 
+	virtual void addTriangle(const ChTriangle& atriangle)
+	{
+		m_triangles.push_back(atriangle);
+	}
+
+			/// Get the number of triangles already added to this mesh
+	virtual int getNumTriangles() const
+	{
+		return m_triangles.size();
+	}
+
+			/// Access the n-th triangle in mesh
+	virtual ChTriangle getTriangle(int index) const
+	{
+		return m_triangles[index];
+	}
+
+			/// Clear all data
+	virtual void Clear()
+	{
+		this->m_triangles.clear();
+	}
+
+		//
+		// OVERRIDE BASE CLASS FUNCTIONS
+		//
+
+	virtual int GetClassType () {return CH_GEOCLASS_TRIANGLEMESHSOUP;};
+
+		//
+		// STREAMING
+		//
+
+	//void StreamOUT(ChStreamOutBinary& mstream);//***TO DO***
+
+	//void StreamIN(ChStreamInBinary& mstream); //***TO DO***
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraint.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraint.cpp
new file mode 100644
index 0000000..02b1901
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraint.cpp
@@ -0,0 +1,125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraint.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+ 
+#include "ChLcpConstraint.h"
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+//ChClassRegister<ChLcpConstraint> a_registration_ChLcpConstraint;
+
+
+
+ChLcpConstraint& ChLcpConstraint::operator=(const ChLcpConstraint& other)
+{
+	if (&other == this) return *this;
+
+	c_i=other.c_i;
+	g_i=other.g_i;
+	b_i=other.b_i;
+	l_i=other.l_i;
+	cfm_i= other.cfm_i;
+	valid = other.valid;
+	_active = other._active;
+	disabled = other.disabled;
+	redundant = other.redundant;
+	broken = other.broken;
+	mode = other.mode;
+
+	return *this;
+}
+
+ 
+bool ChLcpConstraint::operator==(const ChLcpConstraint& other) const
+{
+	return	other.cfm_i==cfm_i &&
+			other.valid==valid &&
+			other._active==_active &&
+			other.disabled==disabled &&
+			other.redundant==redundant &&
+			other.broken==broken &&
+			other.mode==mode;
+}
+
+
+void ChLcpConstraint::Project()
+{
+	if (mode==CONSTRAINT_UNILATERAL)
+	{
+		if (l_i < 0.)
+			l_i=0.;
+	}
+};
+
+double ChLcpConstraint::Violation(double mc_i)
+{
+	if (mode==CONSTRAINT_UNILATERAL)
+	{
+		if (mc_i > 0.)
+			return 0.;
+	}
+
+	return mc_i;
+}
+
+
+void ChLcpConstraint::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// stream useful member data
+	mstream << cfm_i;
+	mstream << valid;
+	mstream << disabled;
+	mstream << redundant;
+	mstream << broken;
+	mstream << (int)mode;
+}
+
+void ChLcpConstraint::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in member data
+	 int mint;
+	mstream >> cfm_i;
+	mstream >> valid;
+	mstream >> disabled;
+	mstream >> redundant;
+	mstream >> broken;
+	mstream >> mint;	mode = (eChConstraintMode)mint;
+	this->UpdateActiveFlag();
+}
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraint.h b/SRC/ChronoEngine/lcp/ChLcpConstraint.h
new file mode 100644
index 0000000..5ac552b
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraint.h
@@ -0,0 +1,410 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINT_H
+#define CHLCPCONSTRAINT_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraint.h
+//
+//    Base class for representing a constraint for
+//   sparse variational problems (VI/CCP/LCP/linear problems)
+//   including inequalities, equalities, nonlinearities,
+//   etc.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+#include "core/ChMatrix.h"
+#include "core/ChSpmatrix.h"
+#include "core/ChClassRegister.h"
+
+
+namespace chrono
+{
+
+// forward reference
+class ChSparseMatrix;
+
+/// Modes for constraint
+enum eChConstraintMode {
+		CONSTRAINT_FREE			= 0, ///< the constraint does not enforce anything
+		CONSTRAINT_LOCK		    = 1, ///< the constraint enforces c_i=0;
+		CONSTRAINT_UNILATERAL	= 2, ///< the constraint enforces linear complementarity c_i>0, l_i>0, l_1*c_i=0;
+		CONSTRAINT_FRIC			= 3, ///< the constraint is one of three reactions in friction (cone complementarity problem)
+};
+
+
+///  Base class for representing constraints to be used
+/// with variational inequality solvers, used with Linear/CCP/LCP
+/// problems including inequalities, equalities, nonlinearities, etc.
+/// The matrices define the variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals)
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0)
+/// * case CCP: Y_i are friction cones)
+///  The jacobian matrix [Cq] is built row by row by jacobians
+/// [Cq_i] of the constraints. [E] optionally includes 'cfm_i' terms 
+/// on the diagonal.
+///  In general, typical bilateral constraints must be solved
+/// to have residual the residual c_i = 0 (unilaterals: c_i>0)
+/// where the following linearization is introduced:
+///      c_i= [Cq_i]*q + b_i
+///
+///  The base class introduce just the minimum requirements
+/// for the solver, that is the basic methods which will be
+/// called by the solver. It is up to the inherited classes
+/// to implement these methods, and to add further features..
+
+class ChApi ChLcpConstraint
+{
+	CH_RTTI_ROOT(ChLcpConstraint)
+
+protected:
+			//
+			// DATA
+			//
+
+				/// The 'c_i' residual of the constraint (if satisfied, c must be =0)
+	double c_i;
+				/// The 'l_i' lagrangian multiplier (reaction)
+	double l_i;
+				/// The 'b_i' right term in [Cq_i]*q+b_i=0 , note: c_i= [Cq_i]*q + b_i 
+	double b_i;
+				/// The constraint force mixing, if needed (usually is zero) to add some
+				/// numerical 'compliance' in the constraint, that is the equation becomes:
+				/// c_i= [Cq_i]*q + b_i + cfm*l_i =0;   
+				/// Example, it could be   cfm = [k * h^2](^-1)   where k is stiffness
+	double cfm_i;
+
+
+			// FLAGS
+private:
+				/// Flag: the link has no formal problems (references restored correctly, etc)
+	bool valid;
+				/// Flag: the user can turn on/off the link easily
+	bool disabled;
+				/// Flag: the constraint is redundant or singular
+	bool redundant;
+				/// Flag: the constraint is broken (someone pulled too much..)
+	bool broken;
+				/// Cached active state depending on previous flags. Internal update.
+	bool _active; 
+
+
+protected:
+				/// The mode of the constraint: free / lock / complementar
+	eChConstraintMode mode;
+
+			// Auxiliary data, (ex. for iterative solvers):
+
+				/// The 'g_i' product [Cq_i]*[invM_i]*[Cq_i]' (+cfm)
+	double g_i;
+
+				/// offset in global "l" state vector (needed by some solvers)
+	int offset;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+	ChLcpConstraint()
+					{
+						c_i=0; g_i=0; b_i=0; l_i = 0; cfm_i=0;
+						valid = false;
+						disabled = false;
+						redundant = false;
+						broken = false;
+						_active = true;
+						mode = CONSTRAINT_LOCK;
+					};
+
+						/// Copy constructor
+	ChLcpConstraint(const ChLcpConstraint& other)
+					{
+						c_i=other.c_i;
+						g_i=other.g_i;
+						b_i=other.b_i;
+						l_i=other.l_i;
+						cfm_i= other.cfm_i;
+						valid = other.valid;
+						disabled = other.disabled;
+						redundant = other.redundant;
+						broken = other.broken;
+						mode = other.mode;
+					}
+
+	virtual ~ChLcpConstraint()
+					{
+					};
+
+	virtual ChLcpConstraint* new_Duplicate () =0;
+
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraint& operator=(const ChLcpConstraint& other);
+
+					/// Comparison (compares anly flags, not the jacobians etc.)
+	bool operator==(const ChLcpConstraint& other) const;
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Tells if the constraint data is currently valid.
+	virtual bool IsValid() {return valid;}
+				/// Use this function to set the valid state (child class 
+				/// Children classes must use this function depending on 
+				/// the result of their implementations of RestoreReference();
+	virtual void SetValid(bool mon) {valid = mon; UpdateActiveFlag();}
+
+				/// Tells if the constraint is currently turned on or off by the user.
+	virtual bool IsDisabled() {return disabled;}
+				/// User can use this to enable/disable the constraint as desired
+	virtual void SetDisabled(bool mon) {disabled = mon; UpdateActiveFlag();}
+
+				/// Tells if the constraint is redundant or singular.
+	virtual bool IsRedundant() {return redundant;}
+				/// Solvers may use the following to mark a constraint as redundant
+	virtual void SetRedundant(bool mon) {redundant = mon; UpdateActiveFlag();}
+
+				/// Tells if the constraint is broken, for eccess of pulling/pushing.
+	virtual bool IsBroken() {return broken;}
+				/// 3rd party software can set the 'broken' status via this method
+				/// (by default, constraints never break);
+	virtual void SetBroken(bool mon) {broken = mon; UpdateActiveFlag();}
+
+				/// Tells if the constraint is unilateral (typical complementarity constraint).
+	virtual bool IsUnilateral() {return mode==CONSTRAINT_UNILATERAL;}
+
+				/// Tells if the constraint is linear (if non linear, returns false).
+	virtual bool IsLinear() {return true;}
+
+				/// Gets the mode of the constraint: free / lock / complementary
+				/// A typical constraint has 'lock = true' by default.
+	eChConstraintMode GetMode() {return mode;}
+
+				/// Sets the mode of the constraint: free / lock / complementary
+	void SetMode(eChConstraintMode mmode) {mode = mmode; UpdateActiveFlag();}
+
+
+				/// A VERY IMPORTANT function!
+				/// Tells if the constraint is currently active, in general,
+				/// that is tells if it must be included into the system solver or not.
+				/// This method cumulates the effect of all flags (so a constraint may
+				/// be not active either because 'disabled', or 'broken', o 'redundant', or not 'valid'.)
+	virtual bool IsActive()
+					{
+						/*
+						return ( valid &&
+								!disabled &&
+								!redundant &&
+								!broken &&
+								mode!=(CONSTRAINT_FREE));
+								*/ // Optimized: booleans precomputed and cached in _active.
+						return _active;
+					}
+
+
+				/// Compute the residual of the constraint using the LINEAR 
+				/// expression   c_i= [Cq_i]*q + cfm_i*l_i + b_i . For a satisfied bilateral
+				/// constraint, this residual must be near zero.
+	virtual double Compute_c_i() { c_i = Compute_Cq_q() + cfm_i*l_i + b_i; return c_i;};
+
+				///  This function must update the 'c_i' residual of
+				/// the constraint.								  // CURRENTLY NOT USED
+				/// *** This function MAY BE OVERRIDDEN by specialized
+				/// inherited classes! (a possible alternative is not
+				/// overriding this, and using the Set_c_i() function
+				/// an all the constraints, from an external procedure,
+				/// just before calling the solver - if the solver does not
+				/// need successive evaluations of residuals during the process.)
+	//virtual void Update_c_i() { /* do nothing */ };
+
+				/// Sets the residual 'c_i' of this constraint.   // CURRENTLY NOT USED
+	//void   Set_c_i(const double mc) {c_i = mc;}
+
+				/// Return the residual 'c_i' of this constraint. // CURRENTLY NOT USED
+	double Get_c_i() {return c_i;}
+
+
+				/// Sets the known term b_i in [Cq_i]*q + b_i =0,
+				/// where: c_i= [Cq_i]*q + b_i = 0
+	void   Set_b_i(const double mb) {b_i = mb;}
+
+				/// Return the known term b_i in [Cq_i]*q + b_i =0,
+				/// where: c_i= [Cq_i]*q + b_i = 0
+	double Get_b_i() {return b_i;}
+
+
+				/// Sets the constraint force mixing term (default=0).
+				/// Adds artificial 'elasticity' to the constraint,
+				/// as:   c_i= [Cq_i]*q + b_i + cfm*l_i =0;
+	void   Set_cfm_i(const double mcfm) {cfm_i = mcfm;}
+
+				/// Returns the constraint force mixing term.
+	double Get_cfm_i() {return cfm_i;}
+
+
+				/// Sets the 'l_i' value (constraint reaction, see 'l' vector)
+	virtual void   Set_l_i(double ml_i) { l_i = ml_i ;}
+
+				/// Return the 'l_i' value (constraint reaction, see 'l' vector)
+	virtual double Get_l_i() { return l_i;}
+
+
+
+				// -----  Functions often used by iterative solvers:
+
+				///  This function must update jacobians and auxiliary
+				/// data such as the 'g_i' product. This function is
+				/// often called by LCP solvers at the beginning of the
+				/// solution process.
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes, which have some jacobians!
+	virtual void Update_auxiliary() { /* do nothing */ };
+
+
+				/// Return the 'g_i' product , that is [Cq_i]*[invM_i]*[Cq_i]' (+cfm)
+	double Get_g_i() {return g_i;}
+
+				/// Usually you should not use the Set_g_i function, because g_i
+				/// should be automatically computed during the Update_auxiliary() .
+	void Set_g_i(double m_g_i) {g_i = m_g_i;}
+
+
+				///  This function must computes the product between
+				/// the row-jacobian of this constraint '[Cq_i]' and the
+				/// vector of variables, 'q'. that is    Cq_q=[Cq_i]*q
+				///  This is used for some iterative LCP solvers.
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes! (since it will be called frequently,
+				/// when iterative solvers are used, the implementation of 
+				/// the [Cq_i]*q product must be AS FAST AS POSSIBLE!).
+				///  It returns the result of the computation.
+	virtual double Compute_Cq_q() = 0;  
+
+
+				///  This function must increment the vector of variables
+				/// 'q' with the quantity [invM]*[Cq_i]'*deltal,that is
+				///   q+=[invM]*[Cq_i]'*deltal
+				///  This is used for some iterative LCP solvers.
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes!
+	virtual void Increment_q(const double deltal) = 0;
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyAndAdd(double& result, ChMatrix<double>& vect) = 0;
+
+				/// Computes the product of the corresponding transposed block in the 
+				/// system matrix (ie. the TRANSPOSED jacobian matrix C_q') by 'l', and add to 'result'. 
+				/// NOTE: the 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyTandAdd(ChMatrix<double>& result, double l) = 0;
+
+				/// For iterative solvers: project the value of a possible
+				/// 'l_i' value of constraint reaction onto admissible orthant/set.
+				/// Default behavior: if constraint is unilateral and l_i<0, reset l_i=0
+				/// *** This function MAY BE OVERRIDDEN by specialized
+				/// inherited classes! For example, a bilateral constraint
+				/// can do nothing, a monolateral: l_i= ChMax(0., l_i);
+				/// a 'boxed constraint': l_i= ChMin(ChMax(min., l_i), max); etc. etc.
+	virtual void Project();
+
+				/// Given the residual of the constraint computed as the
+				/// linear map  mc_i =  [Cq]*q + b_i + cfm*l_i , returns the
+				/// violation of the constraint, considering inequalities, etc.
+				///   For bilateral constraint,  violation = mc_i.
+				///   For unilateral constraint, violation = min(mc_i, 0),
+				///   For boxed constraints or such, inherited class MAY OVERRIDE THIS!
+	virtual double Violation(double mc_i);
+
+				/// Puts the jacobian portions into the 'insrow' row of a sparse matrix,
+				/// where each portion of jacobian is shifted in order to match the 
+				/// offset of the corresponding ChLcpVariable. 
+				/// This is used only by the ChLcpSimplex solver (iterative solvers 
+				/// don't need to know jacobians explicitly)
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes!
+	virtual void Build_Cq(ChSparseMatrix& storage, int insrow) =0;
+				/// Same as Build_Cq, but puts the _transposed_ jacobian row as a column.
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes!
+	virtual void Build_CqT(ChSparseMatrix& storage, int inscol) =0;
+
+				/// Return true only if this constraint can be used by the special GPU 
+				/// solver (for example, constraint with two jacobians of 6 elements each). 
+	virtual bool IsGPUcompatible() {return false;}
+
+				/// Set offset in global q vector (set automatically by ChLcpSystemDescriptor)
+	void SetOffset(int moff) {offset = moff;}
+				/// Get offset in global q vector 
+	int GetOffset() {return offset;}
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+
+private: 
+	void UpdateActiveFlag()
+				{
+					this->_active = ( valid &&
+								!disabled &&
+								!redundant &&
+								!broken &&
+								mode!=(CONSTRAINT_FREE));
+				}
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+
+
+#endif  // END of ChLcpConstraint.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintNodeContactN.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeContactN.cpp
new file mode 100644
index 0000000..8225ea0
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeContactN.cpp
@@ -0,0 +1,125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintNodeContactN.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintNodeContactN.h" 
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintNodeContactN> a_registration_ChLcpConstraintNodeContactN;
+
+  
+
+void ChLcpConstraintNodeContactN::Project()
+{
+	if (!constraint_U)
+		return;
+
+	if (!constraint_V)
+		return;
+
+	// METHOD 
+	// Anitescu-Tasora projection on cone generator and polar cone 
+	// (contractive, but performs correction on three components: normal,u,v)
+
+	double f_n = this->l_i;
+	double f_u = constraint_U->Get_l_i();
+	double f_v = constraint_V->Get_l_i();;
+	double f_tang = sqrt (f_v*f_v + f_u*f_u );
+
+		// shortcut
+	if (!friction)
+	{
+		constraint_U->Set_l_i(0);
+		constraint_V->Set_l_i(0);
+		if (f_n < 0)
+			this->Set_l_i( 0 );
+		return;
+	}
+
+		// inside upper cone? keep untouched!
+	if (f_tang < friction * f_n)
+		return;
+
+		// inside lower cone? reset  normal,u,v to zero!
+	if ((f_tang < -(1.0/friction) * f_n)||(fabs(f_n)<10e-15))
+	{
+		double f_n_proj = 0;
+		double f_u_proj = 0;
+		double f_v_proj = 0;
+
+		this->Set_l_i( f_n_proj );
+		constraint_U->Set_l_i(f_u_proj);
+		constraint_V->Set_l_i(f_v_proj);
+
+		return;
+	} 
+ 
+		// remaining case: project orthogonally to generator segment of upper cone
+	double f_n_proj =  ( f_tang * friction + f_n ) / (friction*friction + 1) ;
+	double f_tang_proj = f_n_proj * friction;
+	double tproj_div_t = f_tang_proj / f_tang;
+	double f_u_proj = tproj_div_t * f_u;
+	double f_v_proj = tproj_div_t * f_v; 
+
+	this->Set_l_i( f_n_proj );
+	constraint_U->Set_l_i(f_u_proj);
+	constraint_V->Set_l_i(f_v_proj);					  
+}
+
+
+void ChLcpConstraintNodeContactN::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoGeneric::StreamOUT(mstream);
+
+		// stream out all member data..
+	mstream << friction;
+
+}
+
+void ChLcpConstraintNodeContactN::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoGeneric::StreamIN(mstream);
+
+		// stream in all member data..
+	mstream >> friction;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintNodeContactN.h b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeContactN.h
new file mode 100644
index 0000000..24f20d2
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeContactN.h
@@ -0,0 +1,178 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTNODECONTACTN_H
+#define CHLCPCONSTRAINTNODECONTACTN_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintNodeContactN.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between two ChLcpVariable items.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintNodeFrictionT.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+/// It is used to represent the normal reaction between a 3DOF node
+/// and a 6 DOF body, only when also two ChLcpConstraintNodeFrictionT 
+/// objects are used to represent friction. 
+
+class ChApi ChLcpConstraintNodeContactN : public ChLcpConstraintTwoGeneric
+{
+	CH_RTTI(ChLcpConstraintNodeContactN, ChLcpConstraintTwoGeneric)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// the friction coefficient 'f', for  sqrt(Tx^2+Ty^2)<f*Nz
+	float friction;
+
+					/// the pointer to U tangential component
+	ChLcpConstraintNodeFrictionT* constraint_U;
+					/// the pointer to V tangential component
+	ChLcpConstraintNodeFrictionT* constraint_V;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintNodeContactN() 
+					{
+						mode = CONSTRAINT_FRIC;
+						friction = 0.0;
+						constraint_U = constraint_V = 0;
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the U and V tangential friction constraints
+	ChLcpConstraintNodeContactN(ChLcpVariablesBody* mvariables_a, 
+							    ChLcpVariablesNode* mvariables_b,
+							   ChLcpConstraintNodeFrictionT* aU = 0,
+							   ChLcpConstraintNodeFrictionT* aV = 0
+								)
+			: ChLcpConstraintTwoGeneric(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_FRIC;
+						friction=0.0;
+						constraint_U = aU;
+						constraint_V = aV;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintNodeContactN(const ChLcpConstraintNodeContactN& other) 
+			: ChLcpConstraintTwoGeneric(other)
+					{
+						friction=other.friction;
+						constraint_U = other.constraint_U;
+						constraint_V = other.constraint_V;
+					}
+
+	virtual ~ChLcpConstraintNodeContactN()
+					{
+					};
+
+	virtual ChLcpConstraintNodeContactN* new_Duplicate () {return new ChLcpConstraintNodeContactN(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintNodeContactN& operator=(const ChLcpConstraintNodeContactN& other)
+					{
+						if (&other == this)
+							return *this;
+						// copy parent class data
+						ChLcpConstraintTwoGeneric::operator=(other);
+						
+						friction = other.friction;
+						constraint_U = other.constraint_U;
+						constraint_V = other.constraint_V;
+						return *this;
+					}
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+
+				/// Get the friction coefficient
+	float GetFrictionCoefficient() {return friction; }
+				/// Set the friction coefficient
+	void SetFrictionCoefficient(float mcoeff) {friction = mcoeff;}
+
+
+				/// Get pointer to U tangential component
+	ChLcpConstraintNodeFrictionT* GetTangentialConstraintU() {return constraint_U;}			
+				/// Get pointer to V tangential component
+	ChLcpConstraintNodeFrictionT* GetTangentialConstraintV() {return constraint_V;}
+
+				/// Set pointer to U tangential component
+	void SetTangentialConstraintU(ChLcpConstraintNodeFrictionT* mconstr) {constraint_U = mconstr;}
+				/// Set pointer to V tangential component
+	void SetTangentialConstraintV(ChLcpConstraintNodeFrictionT* mconstr) {constraint_V = mconstr;}
+
+
+				/// For iterative solvers: project the value of a possible
+				/// 'l_i' value of constraint reaction onto admissible set.
+				/// This projection will also modify the l_i values of the two
+				/// tangential friction constraints (projection onto the friction cone,
+				/// as by Anitescu-Tasora theory).
+	virtual void Project();
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintNodeFrictionT.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeFrictionT.cpp
new file mode 100644
index 0000000..b04d40f
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeFrictionT.cpp
@@ -0,0 +1,68 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintNodeFrictionT.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintNodeFrictionT.h"
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time 
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintNodeFrictionT> a_registration_ChLcpConstraintNodeFrictionT;
+
+
+double ChLcpConstraintNodeFrictionT::Violation(double mc_i)
+{
+	return 0.0; //***TO DO*** compute true violation when in sticking?
+}
+
+
+
+void ChLcpConstraintNodeFrictionT::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoGeneric::StreamOUT(mstream);
+
+}
+ 
+void ChLcpConstraintNodeFrictionT::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoGeneric::StreamIN(mstream);
+
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintNodeFrictionT.h b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeFrictionT.h
new file mode 100644
index 0000000..fa4cfe4
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintNodeFrictionT.h
@@ -0,0 +1,132 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTNODEFRICTIONT_H
+#define CHLCPCONSTRAINTNODEFRICTIONT_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintNodeFrictionT.h
+//
+//  Class used to represent friction constraint
+// between a 3DOF node and a 6DOF body.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoGeneric.h"
+#include "ChLcpVariablesBody.h"
+#include "ChLcpVariablesNode.h"
+
+namespace chrono
+{
+
+
+/// Class used to represent friction constraint
+/// between a 3DOF node and a 6DOF body.
+
+class ChApi ChLcpConstraintNodeFrictionT : public ChLcpConstraintTwoGeneric
+{
+	CH_RTTI(ChLcpConstraintNodeFrictionT, ChLcpConstraintTwoGeneric)
+
+			//
+			// DATA
+			//
+
+protected:
+
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintNodeFrictionT()
+					{
+						mode = CONSTRAINT_FRIC; 
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the  and the normal constraint
+						/// other tangential constraint (the latter is mandatory only
+						/// for the second of the two tangential constraints)
+	ChLcpConstraintNodeFrictionT( ChLcpVariablesBody* mvariables_a,
+								ChLcpVariablesNode* mvariables_b)
+				: ChLcpConstraintTwoGeneric(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_FRIC; 
+					};
+
+						/// Copy constructor
+	ChLcpConstraintNodeFrictionT(const ChLcpConstraintNodeFrictionT& other) 
+				: ChLcpConstraintTwoGeneric(other)
+					{
+					}
+
+	virtual ~ChLcpConstraintNodeFrictionT() {};
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintNodeFrictionT(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintNodeFrictionT& operator=(const ChLcpConstraintNodeFrictionT& other)
+					{
+						if (&other == this)
+							return *this;
+
+						// copy parent class data
+						ChLcpConstraintTwoGeneric::operator=(other);
+
+						return *this;
+					}
+
+
+			//
+			// FUNCTIONS
+			//
+
+					/// Tells that this constraint is not linear, that is: it cannot
+					/// be solved with a plain simplex solver.
+	virtual bool IsLinear() {return false;}
+
+					/// The constraint is satisfied?
+	virtual double Violation(double mc_i);
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintThree.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintThree.cpp
new file mode 100644
index 0000000..a029a3a
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintThree.cpp
@@ -0,0 +1,85 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintThree.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include "ChLcpConstraintThree.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChLcpConstraintThree> a_registration_ChLcpConstraintThree;
+
+
+
+ChLcpConstraintThree& ChLcpConstraintThree::operator=(const ChLcpConstraintThree& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpConstraint::operator=(other);
+
+	this->variables_a = other.variables_a;
+	this->variables_b = other.variables_b;
+	this->variables_c = other.variables_c;
+
+	return *this;
+}
+
+
+void ChLcpConstraintThree::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraint::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (pointers to variables must be rebound in run-time.)
+
+}
+
+void ChLcpConstraintThree::StreamIN(ChStreamInBinary& mstream) 
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraint::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (pointers to variables must be rebound in run-time.)
+
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintThree.h b/SRC/ChronoEngine/lcp/ChLcpConstraintThree.h
new file mode 100644
index 0000000..52b32cd
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintThree.h
@@ -0,0 +1,157 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTHREE_H
+#define CHLCPCONSTRAINTTHREE_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintThree.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between three ChLcpVariable items.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraint.h"
+#include "ChLcpVariables.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the base ChLcpConstraint(),
+/// which does almost nothing. So here this class implements
+/// the functionality for a constrint between a THREE
+/// objects of type ChLcpVariables(), and defines three constraint
+/// matrices, whose column number automatically matches the number
+/// of elements in variables vectors.
+///  Before starting the LCP solver one must provide the proper
+/// values in constraints (and update them if necessary), i.e.
+/// must set at least the c_i and b_i values, and jacobians.
+
+class ChApi ChLcpConstraintThree : public ChLcpConstraint
+{
+	CH_RTTI(ChLcpConstraintThree, ChLcpConstraint)
+
+			//
+			// DATA
+			//
+
+protected:
+
+				/// The first  constrained object
+	ChLcpVariables* variables_a;
+				/// The second constrained object
+	ChLcpVariables* variables_b;
+				/// The third constrained object
+	ChLcpVariables* variables_c;
+
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintThree()
+					{
+						variables_a = variables_b = variables_c = NULL;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintThree(const ChLcpConstraintThree& other) : ChLcpConstraint(other)
+					{
+						variables_a = other.variables_a;
+						variables_b = other.variables_b;
+						variables_c = other.variables_c;
+					}
+
+	virtual ~ChLcpConstraintThree()
+					{
+					};
+
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintThree& operator=(const ChLcpConstraintThree& other);
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_a() =0;
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_b() =0;
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_c() =0;
+
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_a() =0;
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_b() =0;
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_c() =0;
+
+				/// Access the first variable object
+	ChLcpVariables* GetVariables_a() {return variables_a;}
+				/// Access the second variable object
+	ChLcpVariables* GetVariables_b() {return variables_b;}
+				/// Access the second variable object
+	ChLcpVariables* GetVariables_c() {return variables_c;}
+
+				/// Set references to the constrained objects, each of ChLcpVariables type,
+				/// automatically creating/resizing jacobians if needed.
+	virtual void SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b, ChLcpVariables* mvariables_c) =0;
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  // END of ChLcpConstraintTwo.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintThreeBBShaft.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeBBShaft.cpp
new file mode 100644
index 0000000..b7b414e
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeBBShaft.cpp
@@ -0,0 +1,172 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintThreeBBShaft.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include "ChLcpConstraintThreeBBShaft.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintThreeBBShaft> a_registration_ChLcpConstraintThreeBBShaft;
+
+
+
+ChLcpConstraintThreeBBShaft& ChLcpConstraintThreeBBShaft::operator=(const ChLcpConstraintThreeBBShaft& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpConstraintThree::operator=(other);
+
+	Cq_a = other.Cq_a;
+	Cq_b = other.Cq_b;
+	Cq_c = other.Cq_c;
+	Eq_a = other.Eq_a;
+	Eq_b = other.Eq_b;
+	Eq_c = other.Eq_c;
+
+	this->variables_a = other.variables_a;
+	this->variables_b = other.variables_b;
+	this->variables_c = other.variables_c;
+
+	return *this;
+}
+
+ 
+
+void ChLcpConstraintThreeBBShaft::SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b, ChLcpVariables* mvariables_c)
+{
+	assert(dynamic_cast<ChLcpVariablesBody*>(mvariables_a));
+	assert(dynamic_cast<ChLcpVariablesBody*>(mvariables_b));
+	assert(dynamic_cast<ChLcpVariablesBody*>(mvariables_c));
+
+	if (!mvariables_a || !mvariables_b || !mvariables_c)
+	{
+		SetValid(false);
+		return ;
+	}
+
+	SetValid(true);
+	variables_a = mvariables_a;
+	variables_b = mvariables_b;
+	variables_c = mvariables_c;
+	
+}
+
+void ChLcpConstraintThreeBBShaft::Update_auxiliary()
+{
+	//1- Assuming jacobians are already computed, now compute
+	//   the matrices [Eq_a]=[invM_a]*[Cq_a]'  etc
+	if (variables_a->IsActive())
+	{
+		ChMatrixNM<float,6,1> mtemp1;
+		mtemp1.CopyFromMatrixT(Cq_a);
+		variables_a->Compute_invMb_v(Eq_a, mtemp1);
+	}
+	if (variables_b->IsActive())
+	{
+		ChMatrixNM<float,6,1> mtemp1;
+		mtemp1.CopyFromMatrixT(Cq_b);
+		variables_b->Compute_invMb_v(Eq_b, mtemp1);
+	}
+	if (variables_c->IsActive())
+	{
+		ChMatrixNM<float,1,1> mtemp1;
+		mtemp1.CopyFromMatrixT(Cq_c);
+		variables_c->Compute_invMb_v(Eq_c, mtemp1);
+	}
+
+	//2- Compute g_i = [Cq_i]*[invM_i]*[Cq_i]' + cfm_i 
+	ChMatrixNM<float,1,1> res;
+	g_i = 0;
+	if (variables_a->IsActive())
+	{
+		res.MatrMultiply(Cq_a, Eq_a);
+		g_i = res(0,0);
+	}
+	if (variables_b->IsActive())
+	{
+		res.MatrMultiply(Cq_b, Eq_b); 
+		g_i += res(0,0);
+	}
+	if (variables_c->IsActive())
+	{
+		res.MatrMultiply(Cq_c, Eq_c); 
+		g_i += res(0,0);
+	}
+
+	//3- adds the constraint force mixing term (usually zero):
+	if (cfm_i)
+		g_i += cfm_i;
+}; 
+ 
+
+
+
+
+
+
+void ChLcpConstraintThreeBBShaft::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintThree::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream << Cq_a;
+	// mstream << Cq_b;
+}
+
+void ChLcpConstraintThreeBBShaft::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintThree::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream >> Cq_a;
+	// mstream >> Cq_b;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintThreeBBShaft.h b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeBBShaft.h
new file mode 100644
index 0000000..ed97349
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeBBShaft.h
@@ -0,0 +1,280 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTHREEBBSHAFT_H
+#define CHLCPCONSTRAINTTHREEBBSHAFT_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintThreeBBShaft.h
+//
+//   A class for representing a constraint between 
+//   two bodies (2x6dof in space) and a 1D dof (a shaft)
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintThree.h"
+#include "ChLcpVariablesBody.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+/// A class for representing a constraint between 
+/// two bodies (2x6dof in space) and a 1D dof (a shaft)
+
+class ChApi ChLcpConstraintThreeBBShaft : public ChLcpConstraintThree
+{
+	CH_RTTI(ChLcpConstraintThreeBBShaft, ChLcpConstraintThree)
+
+			//
+			// DATA
+			//
+
+protected:
+
+
+				/// The [Cq_a] jacobian of the constraint
+	ChMatrixNM<float,1,6> Cq_a;
+				/// The [Cq_b] jacobian of the constraint
+	ChMatrixNM<float,1,6> Cq_b;
+				/// The [Cq_c] jacobian of the constraint
+	ChMatrixNM<float,1,1> Cq_c;
+
+
+				// Auxiliary data: will be used by iterative constraint solvers:
+
+				/// The [Eq_a] product [Eq_a]=[invM_a]*[Cq_a]'
+	ChMatrixNM<float,6,1> Eq_a;
+				/// The [Eq_b] product [Eq_b]=[invM_b]*[Cq_b]'
+	ChMatrixNM<float,6,1> Eq_b;
+				/// The [Eq_c] product [Eq_c]=[invM_c]*[Cq_c]'
+	ChMatrixNM<float,1,1> Eq_c;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintThreeBBShaft()
+					{
+					};
+
+						/// Construct and immediately set references to variables
+	ChLcpConstraintThreeBBShaft(ChLcpVariablesBody* mvariables_a, ChLcpVariablesBody* mvariables_b, ChLcpVariables* mvariables_c)
+					{
+						assert(mvariables_c->Get_ndof()==1);
+						SetVariables(mvariables_a, mvariables_b, mvariables_c);
+					};
+
+						/// Copy constructor
+	ChLcpConstraintThreeBBShaft(const ChLcpConstraintThreeBBShaft& other)  
+			: ChLcpConstraintThree(other)
+					{
+						Cq_a = other.Cq_a;
+						Cq_b = other.Cq_b;
+						Cq_c = other.Cq_c;
+						Eq_a = other.Eq_a;
+						Eq_b = other.Eq_b;
+						Eq_c = other.Eq_c;
+					}
+
+	virtual ~ChLcpConstraintThreeBBShaft()
+					{
+					};
+
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintThreeBBShaft(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintThreeBBShaft& operator=(const ChLcpConstraintThreeBBShaft& other);
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_a() {return &Cq_a;}
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_b() {return &Cq_b;}
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_c() {return &Cq_c;}
+
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_a() {return &Eq_a;}
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_b() {return &Eq_b;}
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_c() {return &Eq_c;}
+
+
+				/// Set references to the constrained objects,
+				/// If first two variables aren't from ChLcpVariablesBody class, an assert failure happens.
+	void SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b, ChLcpVariables* mvariables_c);
+
+
+				/// This function updates the following auxiliary data:
+				///  - the Eq_a and Eq_b and Eq_c matrices
+				///  - the g_i product
+				/// This is often called by LCP solvers at the beginning
+				/// of the solution process.
+				/// Most often, inherited classes won't need to override this.
+	virtual void Update_auxiliary();
+	
+
+				///  This function must computes the product between
+				/// the row-jacobian of this constraint '[Cq_i]' and the
+				/// vector of variables, 'v'. that is    CV=[Cq_i]*v
+				///  This is used for some iterative LCP solvers.
+	virtual double Compute_Cq_q() 
+					{
+						double ret = 0;
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < 6; i++)
+							ret += Cq_a.ElementN(i) * variables_a->Get_qb().ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < 6; i++)
+							ret += Cq_b.ElementN(i) * variables_b->Get_qb().ElementN(i);
+
+						if (variables_c->IsActive())
+							ret += Cq_c.ElementN(0) * variables_c->Get_qb().ElementN(0);
+
+						return ret;
+					}
+
+		
+
+				///  This function must increment the vector of variables
+				/// 'v' with the quantity [invM]*[Cq_i]'*deltal,that is
+				///   v+=[invM]*[Cq_i]'*deltal  or better: v+=[Eq_i]*deltal
+				///  This is used for some iterative LCP solvers.
+
+	virtual void Increment_q(const double deltal)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Eq_a.GetRows(); i++)
+							variables_a->Get_qb()(i) += Eq_a.ElementN(i) * deltal;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Eq_b.GetRows(); i++)
+							variables_b->Get_qb()(i) += Eq_b.ElementN(i) * deltal;
+
+						if (variables_c->IsActive())
+							variables_c->Get_qb()(0) += Eq_c.ElementN(0) * deltal;
+					};
+
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyAndAdd(double& result, ChMatrix<double>& vect)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a.GetRows(); i++)
+							result += vect(variables_a->GetOffset()+i) * Cq_a.ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b.GetRows(); i++)
+							result += vect(variables_b->GetOffset()+i) * Cq_b.ElementN(i);
+
+						if (variables_c->IsActive())
+							result += vect(variables_c->GetOffset()) * Cq_c.ElementN(0);  
+					};
+
+				/// Computes the product of the corresponding transposed blocks in the 
+				/// system matrix (ie. the TRANSPOSED jacobian matrix C_q') by 'l', and add to 'result'. 
+				/// NOTE: the 'result' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyTandAdd(ChMatrix<double>& result, double l)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a.GetRows(); i++)
+							result(variables_a->GetOffset()+i) += Cq_a.ElementN(i) * l;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b.GetRows(); i++)
+							result(variables_b->GetOffset()+i) += Cq_b.ElementN(i) * l;
+
+						if (variables_c->IsActive())
+							result(variables_c->GetOffset()) += Cq_c.ElementN(0) * l;  
+					};
+
+				/// Puts the jacobian parts into the 'insrow' row of a sparse matrix,
+				/// where both portions of the jacobian are shifted in order to match the 
+				/// offset of the corresponding ChLcpVariable.
+				/// This is used only by the ChLcpSimplex solver (iterative solvers 
+				/// don't need to know jacobians explicitly)
+	virtual void Build_Cq(ChSparseMatrix& storage, int insrow)
+					{
+						if (variables_a->IsActive())
+							storage.PasteMatrixFloat(&Cq_a, insrow, variables_a->GetOffset());
+						if (variables_b->IsActive())
+							storage.PasteMatrixFloat(&Cq_b, insrow, variables_b->GetOffset());
+						if (variables_c->IsActive())
+							storage.PasteMatrixFloat(&Cq_c, insrow, variables_c->GetOffset());
+					}
+	virtual void Build_CqT(ChSparseMatrix& storage, int inscol)
+					{
+						if (variables_a->IsActive())
+							storage.PasteTranspMatrixFloat(&Cq_a, variables_a->GetOffset(), inscol);
+						if (variables_b->IsActive())
+							storage.PasteTranspMatrixFloat(&Cq_b, variables_b->GetOffset(), inscol);
+						if (variables_c->IsActive())
+							storage.PasteTranspMatrixFloat(&Cq_c, variables_c->GetOffset(), inscol);
+					}
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintThreeGeneric.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeGeneric.cpp
new file mode 100644
index 0000000..4041f99
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeGeneric.cpp
@@ -0,0 +1,289 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintThreeGeneric.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include "ChLcpConstraintThreeGeneric.h" 
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintThreeGeneric> a_registration_ChLcpConstraintThreeGeneric;
+
+
+
+ChLcpConstraintThreeGeneric& ChLcpConstraintThreeGeneric::operator=(const ChLcpConstraintThreeGeneric& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpConstraintThree::operator=(other);
+
+	if (other.Cq_a)
+	{
+		if (Cq_a==NULL)
+			Cq_a = new ChMatrixDynamic<float>;
+		Cq_a->CopyFromMatrix(*other.Cq_a);
+	}
+	else
+	{
+		if (Cq_a) delete Cq_a; Cq_a=NULL;
+	}
+
+	if (other.Cq_b)
+	{
+		if (Cq_b==NULL)
+			Cq_b = new ChMatrixDynamic<float>;
+		Cq_b->CopyFromMatrix(*other.Cq_b);
+	}
+	else
+	{
+		if (Cq_b) delete Cq_b; Cq_b=NULL;
+	}
+
+	if (other.Cq_c)
+	{
+		if (Cq_c==NULL)
+			Cq_c = new ChMatrixDynamic<float>;
+		Cq_c->CopyFromMatrix(*other.Cq_c);
+	}
+	else
+	{
+		if (Cq_c) delete Cq_c; Cq_c=NULL;
+	}
+
+	if (other.Eq_a)
+	{
+		if (Eq_a==NULL)
+			Eq_a = new ChMatrixDynamic<float>;
+		Eq_a->CopyFromMatrix(*other.Eq_a);
+	}
+	else
+	{
+		if (Eq_a) delete Eq_a; Eq_a=NULL;
+	}
+
+	if (other.Eq_b)
+	{
+		if (Eq_b==NULL)
+			Eq_b = new ChMatrixDynamic<float>;
+		Eq_b->CopyFromMatrix(*other.Eq_b);
+	}
+	else
+	{
+		if (Eq_b) delete Eq_b; Eq_b=NULL;
+	}
+
+	if (other.Eq_c)
+	{
+		if (Eq_c==NULL)
+			Eq_c = new ChMatrixDynamic<float>;
+		Eq_c->CopyFromMatrix(*other.Eq_c);
+	}
+	else
+	{
+		if (Eq_c) delete Eq_c; Eq_c=NULL;
+	}
+
+	return *this;
+}
+
+
+
+
+void ChLcpConstraintThreeGeneric::SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b, ChLcpVariables* mvariables_c)
+{
+	if (!mvariables_a || !mvariables_b ||  !mvariables_c)
+	{
+		SetValid(false);
+		return ;
+	}
+
+	SetValid(true);
+	variables_a = mvariables_a;
+	variables_b = mvariables_b;
+	variables_c = mvariables_c;
+
+	if (variables_a->Get_ndof())
+	{
+		if (!Cq_a)
+			Cq_a = new ChMatrixDynamic<float>(1, variables_a->Get_ndof());
+		else
+			Cq_a->Resize(1, variables_a->Get_ndof());
+
+		if (!Eq_a)
+			Eq_a = new ChMatrixDynamic<float>(variables_a->Get_ndof(), 1);
+		else
+			Eq_a->Resize(variables_a->Get_ndof(), 1);
+	}
+	else
+	{
+		if (Cq_a) delete Cq_a; Cq_a = NULL;
+		if (Eq_a) delete Eq_a; Eq_a = NULL;
+	}
+
+	if (variables_b->Get_ndof())
+	{
+		if (!Cq_b)
+			Cq_b = new ChMatrixDynamic<float>(1, variables_b->Get_ndof());
+		else
+			Cq_b->Resize(1, variables_b->Get_ndof());
+
+		if (!Eq_b)
+			Eq_b = new ChMatrixDynamic<float>(variables_b->Get_ndof(), 1);
+		else
+			Eq_b->Resize(variables_b->Get_ndof(), 1);
+	}
+	else
+	{
+		if (Cq_b) delete Cq_b; Cq_b = NULL;
+		if (Eq_b) delete Eq_b; Eq_b = NULL;
+	}
+
+	if (variables_c->Get_ndof())
+	{
+		if (!Cq_c)
+			Cq_c = new ChMatrixDynamic<float>(1, variables_c->Get_ndof());
+		else
+			Cq_b->Resize(1, variables_c->Get_ndof());
+
+		if (!Eq_c)
+			Eq_c = new ChMatrixDynamic<float>(variables_c->Get_ndof(), 1);
+		else
+			Eq_c->Resize(variables_c->Get_ndof(), 1);
+	}
+	else
+	{
+		if (Cq_c) delete Cq_c; Cq_c = NULL;
+		if (Eq_c) delete Eq_c; Eq_c = NULL;
+	}
+}
+
+
+
+
+void ChLcpConstraintThreeGeneric::Update_auxiliary()
+{
+	//1- Assuming jacobians are already computed, now compute
+	//   the matrices [Eq_a]=[invM_a]*[Cq_a]' and [Eq_b]
+	if (variables_a->IsActive())
+	if (variables_a->Get_ndof())
+	{
+		ChMatrixDynamic<float> mtemp1(variables_a->Get_ndof(), 1);
+		mtemp1.CopyFromMatrixT(*Cq_a);
+		variables_a->Compute_invMb_v(*Eq_a, mtemp1);
+	}
+	if (variables_b->IsActive())
+	if (variables_b->Get_ndof())
+	{
+		ChMatrixDynamic<float> mtemp1(variables_b->Get_ndof(), 1);
+		mtemp1.CopyFromMatrixT(*Cq_b);
+		variables_b->Compute_invMb_v(*Eq_b, mtemp1);
+	}
+	if (variables_c->IsActive())
+	if (variables_c->Get_ndof())
+	{
+		ChMatrixDynamic<float> mtemp1(variables_c->Get_ndof(), 1);
+		mtemp1.CopyFromMatrixT(*Cq_c);
+		variables_c->Compute_invMb_v(*Eq_c, mtemp1);
+	}
+
+	//2- Compute g_i = [Cq_i]*[invM_i]*[Cq_i]' + cfm_i
+	ChMatrixDynamic<float> res(1,1);
+	g_i = 0;
+	if (variables_a->IsActive())
+	if (variables_a->Get_ndof())
+	{
+		res.MatrMultiply(*Cq_a, *Eq_a);
+		g_i = res(0,0);
+	}
+	if (variables_b->IsActive())
+	if (variables_b->Get_ndof())
+	{
+		res.MatrMultiply(*Cq_b, *Eq_b);
+		g_i += res(0,0);
+	}
+	if (variables_c->IsActive())
+	if (variables_c->Get_ndof())
+	{
+		res.MatrMultiply(*Cq_c, *Eq_c);
+		g_i += res(0,0);
+	}
+
+	//3- adds the constraint force mixing term (usually zero):
+	if (cfm_i)
+		g_i += cfm_i;
+};
+
+
+
+
+
+
+
+void ChLcpConstraintThreeGeneric::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintThree::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream << Cq_a;
+	// mstream << Cq_b;
+}
+ 
+
+
+
+void ChLcpConstraintThreeGeneric::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintThree::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream >> Cq_a;
+	// mstream >> Cq_b;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintThreeGeneric.h b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeGeneric.h
new file mode 100644
index 0000000..30a27c1
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintThreeGeneric.h
@@ -0,0 +1,301 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTHREEGENERIC_H
+#define CHLCPCONSTRAINTTHREEGENERIC_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintThreeGeneric.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between three ChLcpVariable items.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintThree.h"
+#include "ChLcpVariables.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the base ChLcpConstraintThree(),
+/// which is a base for triple constraints. So here this class implements
+/// the functionality for a constraint between a TRHEE
+/// objects of type ChLcpVariables(), with generic number of scalar
+/// variables each (ex.ChLcpVariablesGeneric() or ChLcpVariablesBody() )
+/// and defines three jacobian matrices, whose column number automatically
+/// matches the number of elements in variables vectors.
+///  Before starting the LCP solver one must provide the proper
+/// values in constraints (and update them if necessary), i.e.
+/// must set at least the c_i and b_i values, and jacobians.
+
+class ChApi ChLcpConstraintThreeGeneric : public ChLcpConstraintThree
+{
+	CH_RTTI(ChLcpConstraintThreeGeneric, ChLcpConstraintThree)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// The [Cq_a] jacobian of the constraint
+	ChMatrixDynamic<float>* Cq_a;
+				/// The [Cq_b] jacobian of the constraint
+	ChMatrixDynamic<float>* Cq_b;
+				/// The [Cq_c] jacobian of the constraint
+	ChMatrixDynamic<float>* Cq_c;
+
+
+				// Auxiliary data: will be used by iterative constraint solvers:
+
+				/// The [Eq_a] product [Eq_a]=[invM_a]*[Cq_a]'
+	ChMatrixDynamic<float>* Eq_a;
+				/// The [Eq_a] product [Eq_b]=[invM_b]*[Cq_b]'
+	ChMatrixDynamic<float>* Eq_b;
+				/// The [Eq_a] product [Eq_c]=[invM_b]*[Cq_c]'
+	ChMatrixDynamic<float>* Eq_c;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintThreeGeneric()
+					{
+						Cq_a = Cq_b = Cq_c = Eq_a = Eq_b = Eq_c = NULL;
+					};
+
+						/// Construct and immediately set references to variables
+	ChLcpConstraintThreeGeneric(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b, ChLcpVariables* mvariables_c)
+					{
+						Cq_a = Cq_b = Cq_c = Eq_a = Eq_b = Eq_c = NULL;
+						SetVariables(mvariables_a, mvariables_b, mvariables_c);
+					};
+
+						/// Copy constructor
+	ChLcpConstraintThreeGeneric(const ChLcpConstraintThreeGeneric& other) 
+			: ChLcpConstraintThree(other)
+					{
+						Cq_a = Cq_b = Cq_c = Eq_a = Eq_b = Eq_c = NULL;
+						if(other.Cq_a) Cq_a = new ChMatrixDynamic<float>(*other.Cq_a);
+						if(other.Cq_b) Cq_b = new ChMatrixDynamic<float>(*other.Cq_b);
+						if(other.Cq_c) Cq_c = new ChMatrixDynamic<float>(*other.Cq_c);
+						if(other.Eq_a) Eq_a = new ChMatrixDynamic<float>(*other.Eq_a);
+						if(other.Eq_b) Eq_b = new ChMatrixDynamic<float>(*other.Eq_b);
+						if(other.Eq_c) Eq_c = new ChMatrixDynamic<float>(*other.Eq_c);
+					}
+
+	virtual ~ChLcpConstraintThreeGeneric()
+					{
+						if (Cq_a) delete Cq_a;
+						if (Cq_b) delete Cq_b;
+						if (Cq_c) delete Cq_c;
+						if (Eq_a) delete Eq_a;
+						if (Eq_b) delete Eq_b;
+						if (Eq_c) delete Eq_c;
+					};
+
+
+	virtual ChLcpConstraintThreeGeneric* new_Duplicate () {return new ChLcpConstraintThreeGeneric(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintThreeGeneric& operator=(const ChLcpConstraintThreeGeneric& other);
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_a() {return Cq_a;}
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_b() {return Cq_b;}
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_c() {return Cq_c;}
+
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_a() {return Eq_a;}
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_b() {return Eq_b;}
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_c() {return Eq_c;}
+
+
+				/// Set references to the constrained objects, each of ChLcpVariables type,
+				/// automatically creating/resizing jacobians if needed.
+	virtual void SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b, ChLcpVariables* mvariables_c);
+
+
+				/// This function updates the following auxiliary data:
+				///  - the Eq_a and Eq_b and Eq_c  matrices
+				///  - the g_i product
+				/// This is often called by LCP solvers at the beginning
+				/// of the solution process.
+				/// Most often, inherited classes won't need to override this.
+	virtual void Update_auxiliary();
+					
+
+
+				///  This function must computes the product between
+				/// the row-jacobian of this constraint '[Cq_i]' and the
+				/// vector of variables, 'v'. that is    CV=[Cq_i]*v
+				///  This is used for some iterative LCP solvers.
+	virtual double Compute_Cq_q() 
+					{
+						double ret = 0;
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a->GetColumns(); i++)
+							ret += Cq_a->ElementN(i) * variables_a->Get_qb().ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b->GetColumns(); i++)
+							ret += Cq_b->ElementN(i) * variables_b->Get_qb().ElementN(i);
+
+						if (variables_c->IsActive())
+						 for (int i= 0; i < Cq_c->GetColumns(); i++)
+							ret += Cq_c->ElementN(i) * variables_c->Get_qb().ElementN(i);
+
+						return ret;
+					}
+
+
+
+				///  This function must increment the vector of variables
+				/// 'v' with the quantity [invM]*[Cq_i]'*deltal,that is
+				///   v+=[invM]*[Cq_i]'*deltal  or better: v+=[Eq_i]*deltal
+				///  This is used for some iterative LCP solvers.
+
+	virtual void Increment_q(const double deltal)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Eq_a->GetRows(); i++)
+							variables_a->Get_qb()(i) += Eq_a->ElementN(i) * deltal;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Eq_b->GetRows(); i++)
+							variables_b->Get_qb()(i) += Eq_b->ElementN(i) * deltal;
+
+						if (variables_c->IsActive())
+						 for (int i= 0; i < Eq_c->GetRows(); i++)
+							variables_c->Get_qb()(i) += Eq_c->ElementN(i) * deltal;
+					};
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyAndAdd(double& result, ChMatrix<double>& vect)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a->GetRows(); i++)
+							result += vect(variables_a->GetOffset()+i) * Cq_a->ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b->GetRows(); i++)
+							result += vect(variables_b->GetOffset()+i) * Cq_b->ElementN(i);
+
+						if (variables_c->IsActive())
+						 for (int i= 0; i < Cq_c->GetRows(); i++)
+							result += vect(variables_c->GetOffset()+i) * Cq_c->ElementN(i); 
+					};
+
+				/// Computes the product of the corresponding transposed blocks in the 
+				/// system matrix (ie. the TRANSPOSED jacobian matrix C_q') by 'l', and add to 'result'. 
+				/// NOTE: the 'result' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyTandAdd(ChMatrix<double>& result, double l)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a->GetRows(); i++)
+							result(variables_a->GetOffset()+i) += Cq_a->ElementN(i) * l;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b->GetRows(); i++)
+							result(variables_b->GetOffset()+i) += Cq_b->ElementN(i) * l;
+
+						if (variables_c->IsActive())
+						 for (int i= 0; i < Cq_c->GetRows(); i++)
+							result(variables_c->GetOffset()+i) += Cq_c->ElementN(i) * l; 
+					};
+
+				/// Puts the three jacobian parts into the 'insrow' row of a sparse matrix,
+				/// where both portions of the jacobian are shifted in order to match the 
+				/// offset of the corresponding ChLcpVariable.
+				/// This is used only by the ChLcpSimplex solver (iterative solvers 
+				/// don't need to know jacobians explicitly)
+	virtual void Build_Cq(ChSparseMatrix& storage, int insrow)
+					{
+						if (variables_a->IsActive())
+							storage.PasteMatrixFloat(Cq_a, insrow, variables_a->GetOffset());
+						if (variables_b->IsActive())
+							storage.PasteMatrixFloat(Cq_b, insrow, variables_b->GetOffset());
+						if (variables_b->IsActive())
+							storage.PasteMatrixFloat(Cq_c, insrow, variables_c->GetOffset());
+					}
+	virtual void Build_CqT(ChSparseMatrix& storage, int inscol)
+					{
+						if (variables_a->IsActive())
+							storage.PasteTranspMatrixFloat(Cq_a, variables_a->GetOffset(), inscol);
+						if (variables_b->IsActive())
+							storage.PasteTranspMatrixFloat(Cq_b, variables_b->GetOffset(), inscol);
+						if (variables_c->IsActive())
+							storage.PasteTranspMatrixFloat(Cq_c, variables_c->GetOffset(), inscol);
+					}
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwo.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwo.cpp
new file mode 100644
index 0000000..414503a
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwo.cpp
@@ -0,0 +1,84 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwo.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include "ChLcpConstraintTwo.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChLcpConstraintTwo> a_registration_ChLcpConstraintTwo;
+
+
+
+ChLcpConstraintTwo& ChLcpConstraintTwo::operator=(const ChLcpConstraintTwo& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpConstraint::operator=(other);
+
+	this->variables_a = other.variables_a;
+	this->variables_b = other.variables_b;
+
+	return *this;
+}
+
+
+void ChLcpConstraintTwo::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraint::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (pointers to variables must be rebound in run-time.)
+
+}
+
+void ChLcpConstraintTwo::StreamIN(ChStreamInBinary& mstream) 
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraint::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (pointers to variables must be rebound in run-time.)
+
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwo.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwo.h
new file mode 100644
index 0000000..801a279
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwo.h
@@ -0,0 +1,148 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWO_H
+#define CHLCPCONSTRAINTTWO_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwo.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between two ChLcpVariable items.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraint.h"
+#include "ChLcpVariables.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the base ChLcpConstraint(),
+/// which does almost nothing. So here this class implements
+/// the functionality for a constrint between a COUPLE of TWO
+/// objects of type ChLcpVariables(), and defines two constraint
+/// matrices, whose column number automatically matches the number
+/// of elements in variables vectors.
+///  Before starting the LCP solver one must provide the proper
+/// values in constraints (and update them if necessary), i.e.
+/// must set at least the c_i and b_i values, and jacobians.
+
+class ChApi ChLcpConstraintTwo : public ChLcpConstraint
+{
+	CH_RTTI(ChLcpConstraintTwo, ChLcpConstraint)
+
+			//
+			// DATA
+			//
+
+protected:
+
+				/// The first  constrained object
+	ChLcpVariables* variables_a;
+				/// The second constrained object
+	ChLcpVariables* variables_b;
+
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwo()
+					{
+						variables_a = variables_b = NULL;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwo(const ChLcpConstraintTwo& other) : ChLcpConstraint(other)
+					{
+						variables_a = other.variables_a;
+						variables_b = other.variables_b;
+					}
+
+	virtual ~ChLcpConstraintTwo()
+					{
+					};
+
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwo& operator=(const ChLcpConstraintTwo& other);
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_a() =0;
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_b() =0;
+
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_a() =0;
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_b() =0;
+
+				/// Access the first variable object
+	ChLcpVariables* GetVariables_a() {return variables_a;}
+				/// Access the second variable object
+	ChLcpVariables* GetVariables_b() {return variables_b;}
+
+				/// Set references to the constrained objects, each of ChLcpVariables type,
+				/// automatically creating/resizing jacobians if needed.
+	virtual void SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b) =0;
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  // END of ChLcpConstraintTwo.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.cpp
new file mode 100644
index 0000000..d534c42
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.cpp
@@ -0,0 +1,156 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoBodies.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include "ChLcpConstraintTwoBodies.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoBodies> a_registration_ChLcpConstraintTwoBodies;
+
+
+
+ChLcpConstraintTwoBodies& ChLcpConstraintTwoBodies::operator=(const ChLcpConstraintTwoBodies& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpConstraintTwo::operator=(other);
+
+	Cq_a = other.Cq_a;
+	Cq_b = other.Cq_b;
+	Eq_a = other.Eq_a;
+	Eq_b = other.Eq_b;
+
+	this->variables_a = other.variables_a;
+	this->variables_b = other.variables_b;
+
+	return *this;
+}
+
+ 
+
+void ChLcpConstraintTwoBodies::SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b)
+{
+	assert(dynamic_cast<ChLcpVariablesBody*>(mvariables_a));
+	assert(dynamic_cast<ChLcpVariablesBody*>(mvariables_b));
+
+	if (!mvariables_a || !mvariables_b)
+	{
+		SetValid(false);
+		return ;
+	}
+
+	SetValid(true);
+	variables_a = mvariables_a;
+	variables_b = mvariables_b;
+	
+}
+
+void ChLcpConstraintTwoBodies::Update_auxiliary()
+{
+	//1- Assuming jacobians are already computed, now compute
+	//   the matrices [Eq_a]=[invM_a]*[Cq_a]' and [Eq_b]
+	if (variables_a->IsActive())
+	{
+		ChMatrixNM<float,6,1> mtemp1;
+		mtemp1.CopyFromMatrixT(Cq_a);
+		variables_a->Compute_invMb_v(Eq_a, mtemp1);
+	}
+	if (variables_b->IsActive())
+	{
+		ChMatrixNM<float,6,1> mtemp1;
+		mtemp1.CopyFromMatrixT(Cq_b);
+		variables_b->Compute_invMb_v(Eq_b, mtemp1);
+	}
+
+	//2- Compute g_i = [Cq_i]*[invM_i]*[Cq_i]' + cfm_i 
+	ChMatrixNM<float,1,1> res;
+	g_i = 0;
+	if (variables_a->IsActive())
+	{
+		res.MatrMultiply(Cq_a, Eq_a);
+		g_i = res(0,0);
+	}
+	if (variables_b->IsActive())
+	{
+		res.MatrMultiply(Cq_b, Eq_b); 
+		g_i += res(0,0);
+	}
+
+	//3- adds the constraint force mixing term (usually zero):
+	if (cfm_i)
+		g_i += cfm_i;
+}; 
+ 
+
+
+
+
+
+
+void ChLcpConstraintTwoBodies::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwo::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream << Cq_a;
+	// mstream << Cq_b;
+}
+
+void ChLcpConstraintTwoBodies::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwo::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream >> Cq_a;
+	// mstream >> Cq_b;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.h
new file mode 100644
index 0000000..a2b3101
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoBodies.h
@@ -0,0 +1,270 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOBODIES_H
+#define CHLCPCONSTRAINTTWOBODIES_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoBodies.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between two ChLcpVariableBody items.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwo.h"
+#include "ChLcpVariablesBody.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the base ChLcpConstraintTwo(),
+/// that is implements the functionality for a constraint between 
+/// a couple of two objects of type ChLcpVariablesBody(). 
+/// Important note, it reports 
+/// IsGPUcompatible() as 'true' because here we're sure that 
+/// jacobians are 1x6 and 1x6, as required by the GPU solver.
+
+class ChApi ChLcpConstraintTwoBodies : public ChLcpConstraintTwo
+{
+	CH_RTTI(ChLcpConstraintTwoBodies, ChLcpConstraintTwo)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// The [Cq_a] jacobian of the constraint
+	ChMatrixNM<float,1,6> Cq_a;
+				/// The [Cq_b] jacobian of the constraint
+	ChMatrixNM<float,1,6> Cq_b;
+
+
+				// Auxiliary data: will be used by iterative constraint solvers:
+
+				/// The [Eq_a] product [Eq_a]=[invM_a]*[Cq_a]'
+	ChMatrixNM<float,6,1> Eq_a;
+				/// The [Eq_a] product [Eq_b]=[invM_b]*[Cq_b]'
+	ChMatrixNM<float,6,1> Eq_b;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoBodies()
+					{
+					};
+
+						/// Construct and immediately set references to variables
+	ChLcpConstraintTwoBodies(ChLcpVariablesBody* mvariables_a, ChLcpVariablesBody* mvariables_b)
+					{
+						SetVariables(mvariables_a, mvariables_b);
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoBodies(const ChLcpConstraintTwoBodies& other)  
+			: ChLcpConstraintTwo(other)
+					{
+						Cq_a = other.Cq_a;
+						Cq_b = other.Cq_b;
+						Eq_a = other.Eq_a;
+						Eq_b = other.Eq_b;
+					}
+
+	virtual ~ChLcpConstraintTwoBodies()
+					{
+					};
+
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintTwoBodies(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoBodies& operator=(const ChLcpConstraintTwoBodies& other);
+
+
+
+			//
+			// FUNCTIONS
+			//
+				
+				/// Return true because this is the constraint type supported by GPU solver
+	virtual bool IsGPUcompatible() {return true;}
+
+
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_a() {return &Cq_a;}
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_b() {return &Cq_b;}
+
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_a() {return &Eq_a;}
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_b() {return &Eq_b;}
+
+
+				/// Set references to the constrained objects, each of ChLcpVariablesBody type,
+				/// automatically creating/resizing jacobians if needed.
+				/// If variables aren't from ChLcpVariablesBody class, an assert failure happens.
+	void SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b);
+
+
+				/// This function updates the following auxiliary data:
+				///  - the Eq_a and Eq_b matrices
+				///  - the g_i product
+				/// This is often called by LCP solvers at the beginning
+				/// of the solution process.
+				/// Most often, inherited classes won't need to override this.
+	virtual void Update_auxiliary();
+	
+
+				///  This function must computes the product between
+				/// the row-jacobian of this constraint '[Cq_i]' and the
+				/// vector of variables, 'v'. that is    CV=[Cq_i]*v
+				///  This is used for some iterative LCP solvers.
+	virtual double Compute_Cq_q() 
+					{
+						double ret = 0;
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < 6; i++)
+							ret += Cq_a.ElementN(i) * variables_a->Get_qb().ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < 6; i++)
+							ret += Cq_b.ElementN(i) * variables_b->Get_qb().ElementN(i);
+
+						return ret;
+					}
+
+		
+
+				///  This function must increment the vector of variables
+				/// 'v' with the quantity [invM]*[Cq_i]'*deltal,that is
+				///   v+=[invM]*[Cq_i]'*deltal  or better: v+=[Eq_i]*deltal
+				///  This is used for some iterative LCP solvers.
+
+	virtual void Increment_q(const double deltal)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < 6; i++)
+							variables_a->Get_qb()(i) += Eq_a.ElementN(i) * deltal;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < 6; i++)
+							variables_b->Get_qb()(i) += Eq_b.ElementN(i) * deltal;
+					};
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyAndAdd(double& result, ChMatrix<double>& vect)
+					{
+						int off_a = variables_a->GetOffset();
+						int off_b = variables_b->GetOffset();
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < 6; i++)
+							result += vect(off_a+i) * Cq_a.ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < 6; i++)
+							result += vect(off_b+i) * Cq_b.ElementN(i);
+					};
+
+				/// Computes the product of the corresponding transposed blocks in the 
+				/// system matrix (ie. the TRANSPOSED jacobian matrix C_q') by 'l', and add to 'result'. 
+				/// NOTE: the 'result' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyTandAdd(ChMatrix<double>& result, double l)
+					{
+						int off_a = variables_a->GetOffset();
+						int off_b = variables_b->GetOffset();
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < 6; i++)
+							result(off_a+i) += Cq_a.ElementN(i) * l;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < 6; i++)
+							result(off_b+i) += Cq_b.ElementN(i) * l;
+					};
+
+
+				/// Puts the two jacobian parts into the 'insrow' row of a sparse matrix,
+				/// where both portions of the jacobian are shifted in order to match the 
+				/// offset of the corresponding ChLcpVariable.The same is done
+				/// on the 'insrow' column, so that the sparse matrix is kept symmetric.
+				/// This is used only by the ChLcpSimplex solver (iterative solvers 
+				/// don't need to know jacobians explicitly)
+	virtual void Build_Cq(ChSparseMatrix& storage, int insrow)
+					{
+						if (variables_a->IsActive())
+							storage.PasteMatrixFloat(&Cq_a, insrow, variables_a->GetOffset());
+						if (variables_b->IsActive())
+							storage.PasteMatrixFloat(&Cq_b, insrow, variables_b->GetOffset());
+					}
+	virtual void Build_CqT(ChSparseMatrix& storage, int inscol)
+					{
+						if (variables_a->IsActive())
+							storage.PasteTranspMatrixFloat(&Cq_a, variables_a->GetOffset(), inscol);
+						if (variables_b->IsActive())
+							storage.PasteTranspMatrixFloat(&Cq_b, variables_b->GetOffset(), inscol);
+					}
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.cpp
new file mode 100644
index 0000000..c16d680
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.cpp
@@ -0,0 +1,66 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoContact.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintTwoContact.h" 
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoContact> a_registration_ChLcpConstraintTwoContact;
+
+
+ 
+void ChLcpConstraintTwoContact::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoBodies::StreamOUT(mstream);
+
+		// stream out all member data..
+
+}
+
+void ChLcpConstraintTwoContact::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoBodies::StreamIN(mstream);
+
+		// stream in all member data..
+
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.h
new file mode 100644
index 0000000..aa4d3c6
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContact.h
@@ -0,0 +1,141 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOCONTACT_H
+#define CHLCPCONSTRAINTTWOCONTACT_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoContact.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between two ChLcpVariable items.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoBodies.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the ChLcpConstraintTwoBodies(),
+/// It is used to represent the normal reaction between two objects
+/// ONLY when also two ChLcpConstraintTwoFriction objects are
+/// used to represent friction. (If these two tangent constraint
+/// are not used, for frictionless case, please use a simple ChConstraintTwo
+/// with the CONSTRAINT_UNILATERAL mode.) 
+/// Differently from an unilateral constraint, this does not enforce
+/// projection on positive constraint, since it will be up to the 'companion'
+/// ChLcpConstraintTwoFriction objects to call a projection on the cone, by
+/// modifying all the three components (normal, u, v) at once.
+
+class ChLcpConstraintTwoContact : public ChLcpConstraintTwoBodies
+{
+	CH_RTTI(ChLcpConstraintTwoContact, ChLcpConstraintTwoBodies)
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoContact() 
+					{
+						mode = CONSTRAINT_FRIC;
+					};
+
+						/// Construct and immediately set references to variables
+	ChLcpConstraintTwoContact(ChLcpVariablesBody* mvariables_a, ChLcpVariablesBody* mvariables_b)
+			: ChLcpConstraintTwoBodies(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_FRIC;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoContact(const ChLcpConstraintTwoContact& other) 
+			: ChLcpConstraintTwoBodies(other)
+					{
+					}
+
+	virtual ~ChLcpConstraintTwoContact()
+					{
+					};
+
+	virtual ChLcpConstraintTwoContact* new_Duplicate () {return new ChLcpConstraintTwoContact(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoContact& operator=(const ChLcpConstraintTwoContact& other)
+					{
+						if (&other == this)
+							return *this;
+						// copy parent class data
+						ChLcpConstraintTwoBodies::operator=(other);
+						// no data to copy
+						return *this;
+					}
+
+
+			//
+			// FUNCTIONS
+			//
+
+
+
+	virtual void Project()
+					{
+						// This is here to prevent this constraint to do Project(), during
+						// the LCP iterative solver, since a special projection (involving three 
+						// components, i.e. this normal reaction and the two tangent u v friction
+						// reactions) will be made by one of the two companions ChLcpConstraintTwoFriction 
+						// objects - only when needed.
+					}
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContactN.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContactN.cpp
new file mode 100644
index 0000000..296a22e
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContactN.cpp
@@ -0,0 +1,125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoContactN.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintTwoContactN.h" 
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoContactN> a_registration_ChLcpConstraintTwoContactN;
+
+  
+
+void ChLcpConstraintTwoContactN::Project()
+{
+	if (!constraint_U)
+		return;
+
+	if (!constraint_V)
+		return;
+
+	// METHOD 
+	// Anitescu-Tasora projection on cone generator and polar cone 
+	// (contractive, but performs correction on three components: normal,u,v)
+
+	double f_n = this->l_i + this->cohesion;
+	double f_u = constraint_U->Get_l_i();
+	double f_v = constraint_V->Get_l_i();;
+	double f_tang = sqrt (f_v*f_v + f_u*f_u );
+
+		// shortcut
+	if (!friction)
+	{
+		constraint_U->Set_l_i(0);
+		constraint_V->Set_l_i(0);
+		if (f_n < 0)
+			this->Set_l_i( 0 );
+		return;
+	}
+
+		// inside upper cone? keep untouched!
+	if (f_tang < friction * f_n)
+		return;
+
+		// inside lower cone? reset  normal,u,v to zero!
+	if ((f_tang < -(1.0/friction) * f_n)||(fabs(f_n)<10e-15))
+	{
+		double f_n_proj = 0;
+		double f_u_proj = 0;
+		double f_v_proj = 0;
+
+		this->Set_l_i( f_n_proj );
+		constraint_U->Set_l_i(f_u_proj);
+		constraint_V->Set_l_i(f_v_proj);
+
+		return;
+	} 
+ 
+		// remaining case: project orthogonally to generator segment of upper cone
+	double f_n_proj =  ( f_tang * friction + f_n ) / (friction*friction + 1) ;
+	double f_tang_proj = f_n_proj * friction;
+	double tproj_div_t = f_tang_proj / f_tang;
+	double f_u_proj = tproj_div_t * f_u;
+	double f_v_proj = tproj_div_t * f_v; 
+
+	this->Set_l_i( f_n_proj -this->cohesion);
+	constraint_U->Set_l_i(f_u_proj);
+	constraint_V->Set_l_i(f_v_proj);					  
+}
+
+
+void ChLcpConstraintTwoContactN::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoBodies::StreamOUT(mstream);
+
+		// stream out all member data..
+	mstream << friction;
+
+}
+
+void ChLcpConstraintTwoContactN::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoBodies::StreamIN(mstream);
+
+		// stream in all member data..
+	mstream >> friction;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContactN.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContactN.h
new file mode 100644
index 0000000..cf29ed1
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoContactN.h
@@ -0,0 +1,194 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOCONTACTN_H
+#define CHLCPCONSTRAINTTWOCONTACTN_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoContactN.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between two ChLcpVariable items.
+//   Used with LCP systems including inequalities,
+//   equalities, nonlinearities, etc.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoFrictionT.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the ChLcpConstraintTwoBodies(),
+/// It is used to represent the normal reaction between two objects
+/// ONLY when also two ChLcpConstraintTwoFrictionT objects are
+/// used to represent friction. (If these two tangent constraint
+/// are not used, for frictionless case, please use a simple ChConstraintTwo
+/// with the CONSTRAINT_UNILATERAL mode.) 
+/// Differently from an unilateral constraint, this does not enforce
+/// projection on positive constraint, since it will be up to the 'companion'
+/// ChLcpConstraintTwoFriction objects to call a projection on the cone, by
+/// modifying all the three components (normal, u, v) at once.
+
+class ChApi ChLcpConstraintTwoContactN : public ChLcpConstraintTwoBodies
+{
+	CH_RTTI(ChLcpConstraintTwoContactN, ChLcpConstraintTwoBodies)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// the friction coefficient 'f', for  sqrt(Tx^2+Ty^2)<f*Nz
+	float friction;
+				/// the cohesion 'c', positive, if any, for  sqrt(Tx^2+Ty^2)<f*(Nz+c)
+	float cohesion;
+
+					/// the pointer to U tangential component
+	ChLcpConstraintTwoFrictionT* constraint_U;
+					/// the pointer to V tangential component
+	ChLcpConstraintTwoFrictionT* constraint_V;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoContactN() 
+					{
+						mode = CONSTRAINT_FRIC;
+						friction = 0.0;
+						cohesion = 0.0;
+						constraint_U = constraint_V = 0;
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the U and V tangential friction constraints
+	ChLcpConstraintTwoContactN(ChLcpVariablesBody* mvariables_a, 
+							   ChLcpVariablesBody* mvariables_b,
+							   ChLcpConstraintTwoFrictionT* aU = 0,
+							   ChLcpConstraintTwoFrictionT* aV = 0
+								)
+			: ChLcpConstraintTwoBodies(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_FRIC;
+						friction=0.0;
+						cohesion=0.0;
+						constraint_U = aU;
+						constraint_V = aV;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoContactN(const ChLcpConstraintTwoContactN& other) 
+			: ChLcpConstraintTwoBodies(other)
+					{
+						friction=other.friction;
+						cohesion=other.cohesion;
+						constraint_U = other.constraint_U;
+						constraint_V = other.constraint_V;
+					}
+
+	virtual ~ChLcpConstraintTwoContactN()
+					{
+					};
+
+	virtual ChLcpConstraintTwoContactN* new_Duplicate () {return new ChLcpConstraintTwoContactN(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoContactN& operator=(const ChLcpConstraintTwoContactN& other)
+					{
+						if (&other == this)
+							return *this;
+						// copy parent class data
+						ChLcpConstraintTwoBodies::operator=(other);
+						
+						friction = other.friction;
+						cohesion = other.cohesion;
+						constraint_U = other.constraint_U;
+						constraint_V = other.constraint_V;
+						return *this;
+					}
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+
+				/// Get the friction coefficient
+	float GetFrictionCoefficient() {return friction; }
+				/// Set the friction coefficient
+	void SetFrictionCoefficient(float mcoeff) {friction = mcoeff;}
+
+				/// Get the cohesion
+	float GetCohesion() {return cohesion; }
+				/// Set the cohesion
+	void SetCohesion(float mcoh) {cohesion = mcoh;}
+
+
+				/// Get pointer to U tangential component
+	ChLcpConstraintTwoFrictionT* GetTangentialConstraintU() {return constraint_U;}			
+				/// Get pointer to V tangential component
+	ChLcpConstraintTwoFrictionT* GetTangentialConstraintV() {return constraint_V;}
+
+				/// Set pointer to U tangential component
+	void SetTangentialConstraintU(ChLcpConstraintTwoFrictionT* mconstr) {constraint_U = mconstr;}
+				/// Set pointer to V tangential component
+	void SetTangentialConstraintV(ChLcpConstraintTwoFrictionT* mconstr) {constraint_V = mconstr;}
+
+
+				/// For iterative solvers: project the value of a possible
+				/// 'l_i' value of constraint reaction onto admissible set.
+				/// This projection will also modify the l_i values of the two
+				/// tangential friction constraints (projection onto the friction cone,
+				/// as by Anitescu-Tasora theory).
+	virtual void Project();
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFriction.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFriction.cpp
new file mode 100644
index 0000000..cb5f642
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFriction.cpp
@@ -0,0 +1,72 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoFriction.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintTwoFriction.h"
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time 
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoFriction> a_registration_ChLcpConstraintTwoFriction;
+
+
+double ChLcpConstraintTwoFriction::Violation(double mc_i)
+{
+	return 0.0; //***TO DO*** compute true violation when in sticking?
+}
+
+
+
+void ChLcpConstraintTwoFriction::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoBodies::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << friction;
+}
+ 
+void ChLcpConstraintTwoFriction::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoBodies::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> friction;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFriction.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFriction.h
new file mode 100644
index 0000000..bf341ef
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFriction.h
@@ -0,0 +1,140 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOFRICTION_H
+#define CHLCPCONSTRAINTTWOFRICTION_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoFriction.h
+//
+//  Class used to represent friction constraint
+// between two ChLcpVariable() items.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoBodies.h"
+#include "ChLcpVariables.h"
+
+namespace chrono
+{
+
+
+/// Base class for friction constraints (see specialized children classes
+/// for more details - this is mostly an interface)
+
+class ChLcpConstraintTwoFriction : public ChLcpConstraintTwoBodies
+{
+	CH_RTTI(ChLcpConstraintTwoFriction, ChLcpConstraintTwoBodies)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// the friction coefficient 'f', for  sqrt(Tx^2+Ty^2)<f*Nz
+	double friction;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoFriction()
+					{
+						friction=0.0;
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the  and the normal constraint
+						/// other tangential constraint (the latter is mandatory only
+						/// for the second of the two tangential constraints)
+	ChLcpConstraintTwoFriction( ChLcpVariablesBody* mvariables_a,
+								ChLcpVariablesBody* mvariables_b)
+				: ChLcpConstraintTwoBodies(mvariables_a, mvariables_b)
+					{
+						friction=0.0;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoFriction(const ChLcpConstraintTwoFriction& other) 
+				: ChLcpConstraintTwoBodies(other)
+					{
+						friction = other.friction;
+					}
+
+	virtual ~ChLcpConstraintTwoFriction() {};
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintTwoFriction(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoFriction& operator=(const ChLcpConstraintTwoFriction& other)
+					{
+						if (&other == this)
+							return *this;
+
+						// copy parent class data
+						ChLcpConstraintTwoBodies::operator=(other);
+
+						friction = other.friction;
+						return *this;
+					}
+
+
+			//
+			// FUNCTIONS
+			//
+
+					/// Tells that this constraint is not linear, that is: it cannot
+					/// be solved with a plain simplex solver.
+	virtual bool IsLinear() {return false;}
+
+				/// Get the friction coefficient
+	double GetFrictionCoefficient() {return friction; }
+				/// Set the friction coefficient
+	void SetFrictionCoefficient(double mcoeff) {friction = mcoeff;}
+
+
+				/// The constraint is satisfied?
+	virtual double Violation(double mc_i);
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpConstraintTwoFriction.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionApprox.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionApprox.cpp
new file mode 100644
index 0000000..5e8411b
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionApprox.cpp
@@ -0,0 +1,94 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoFrictionApprox.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintTwoFrictionApprox.h" 
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoFrictionApprox> a_registration_ChLcpConstraintTwoFrictionApprox;
+
+
+
+void ChLcpConstraintTwoFrictionApprox::Project()
+{
+	if (!constraint_Tother)
+		return;
+
+	if (!constraint_N)
+		return;
+
+	// METHOD
+	// Tasora horizontal projection on cone (not necessarily a contractive mapping)
+	double f_tang = sqrt (l_i*l_i + constraint_Tother->l_i * constraint_Tother->l_i );
+	double f_limit = friction * constraint_N->Get_l_i();
+	if (f_tang > f_limit)
+	{	
+		double shrink = f_limit / f_tang;
+		l_i *= shrink;
+		//constraint_Tother->l_i *= shrink;
+
+	}
+
+}
+
+
+
+void ChLcpConstraintTwoFrictionApprox::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoFriction::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+}
+ 
+void ChLcpConstraintTwoFrictionApprox::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoFriction::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionApprox.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionApprox.h
new file mode 100644
index 0000000..226d51c
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionApprox.h
@@ -0,0 +1,178 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOFRICTIONAPPROX_H
+#define CHLCPCONSTRAINTTWOFRICTIONAPPROX_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoFrictionApprox.h
+//
+//  Class used to represent friction constraint
+// between two ChLcpVariable() items.
+// Since
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoFriction.h"
+#include "ChLcpVariables.h"
+
+namespace chrono
+{
+
+
+///  This class is inherited by the base ChLcpConstraintTwoBodies(),
+/// which provides most functionalities.
+/// This class implements features to have the tangential constraint
+/// limits as functions of the normal contact force.
+///  Since in 3D you have two tangential scalar reactions for
+/// each single normal reaction, at each contact point you will
+/// use a single ChLcpConstraintTwoBodies and a couple of
+/// ChLcpConstraintTwoFrictionApprox. All three are 'linked' with
+/// pointers, so that the Project() operation on the two
+/// friction constraints will project the tangential force onto
+/// the admissible Coloumb friction cone, moving parallel to the
+/// contact plane (hence this method has NOT the non-extensibility
+/// property, and may not assure convergence). 
+///  Before starting the LCP solver one must provide the proper
+/// values in constraints (and update them if necessary), i.e.
+/// must set at least the c_i and b_i values, and jacobians.
+
+class ChLcpConstraintTwoFrictionApprox : public ChLcpConstraintTwoFriction
+{
+	CH_RTTI(ChLcpConstraintTwoFrictionApprox, ChLcpConstraintTwoFriction)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// the pointer to the normal contact constraint
+	ChLcpConstraintTwoBodies* constraint_N;
+
+				/// the pointer to the other tangential component
+	ChLcpConstraintTwoFrictionApprox* constraint_Tother;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoFrictionApprox()
+					{
+						mode = CONSTRAINT_LOCK;
+						constraint_N = constraint_Tother= NULL;
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the  and the normal constraint
+						/// other tangential constraint (the latter is mandatory only
+						/// for the second of the two tangential constraints)
+	ChLcpConstraintTwoFrictionApprox( ChLcpVariablesBody* mvariables_a,
+								ChLcpVariablesBody* mvariables_b,
+								ChLcpConstraintTwoBodies* aN,
+								ChLcpConstraintTwoFrictionApprox* aT = NULL)
+				: ChLcpConstraintTwoFriction(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_LOCK;
+						constraint_N = aN;
+						constraint_Tother= aT;
+					};
+
+
+						/// Copy constructor
+	ChLcpConstraintTwoFrictionApprox(const ChLcpConstraintTwoFrictionApprox& other) 
+				: ChLcpConstraintTwoFriction(other)
+					{
+						constraint_N = other.constraint_N;
+						constraint_Tother = other.constraint_Tother;
+					}
+
+	virtual ~ChLcpConstraintTwoFrictionApprox() {};
+
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintTwoFrictionApprox(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoFrictionApprox& operator=(const ChLcpConstraintTwoFrictionApprox& other)
+					{
+						if (&other == this)
+							return *this;
+
+						// copy parent class data
+						ChLcpConstraintTwoFriction::operator=(other);
+
+						constraint_N = other.constraint_N;
+						constraint_Tother = other.constraint_Tother;
+						return *this;
+					}
+
+
+			//
+			// FUNCTIONS
+			//
+
+
+				/// Get pointer to the normal contact constraint
+	ChLcpConstraintTwoBodies* GetNormalConstraint() {return constraint_N;}
+				/// Set pointer to the normal contact constraint
+	void SetNormalConstraint(ChLcpConstraintTwoBodies* mconstr) {constraint_N = mconstr;}
+
+				/// Get pointer to the other tangential component
+	ChLcpConstraintTwoFrictionApprox* GetOtherTangentialConstraint() {return constraint_Tother;}
+				/// Set pointer to the other tangential component
+	void SetOtherTangentialConstraint(ChLcpConstraintTwoFrictionApprox* mconstr) {constraint_Tother = mconstr;}
+
+
+
+				/// For iterative solvers: project the value of a possible
+				/// 'l_i' value of constraint reaction onto admissible set.
+				/// Default behavior: if constraint is unilateral and l_i<0, reset l_i=0
+				/// but this is not good for our 'friction' tangential constraint, so
+				/// we override the base behaviour by projecting in this way:
+				///    sqrt(l_ix^2+l_iy^2)< f*l_iz
+				/// where l_ix and l_iy are the reactions of the two tangential
+				/// constraints, and the l_iz is the reaction of the normal constraint.
+	virtual void Project();
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpConstraintTwoFrictionApprox.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionT.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionT.cpp
new file mode 100644
index 0000000..3e1d19f
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionT.cpp
@@ -0,0 +1,68 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoFrictionT.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintTwoFrictionT.h"
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time 
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoFrictionT> a_registration_ChLcpConstraintTwoFrictionT;
+
+
+double ChLcpConstraintTwoFrictionT::Violation(double mc_i)
+{
+	return 0.0; //***TO DO*** compute true violation when in sticking?
+}
+
+
+
+void ChLcpConstraintTwoFrictionT::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoBodies::StreamOUT(mstream);
+
+}
+ 
+void ChLcpConstraintTwoFrictionT::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoBodies::StreamIN(mstream);
+
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionT.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionT.h
new file mode 100644
index 0000000..870a8b4
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoFrictionT.h
@@ -0,0 +1,131 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOFRICTIONT_H
+#define CHLCPCONSTRAINTTWOFRICTIONT_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoFrictionT.h
+//
+//  Class used to represent friction constraint
+// between two ChLcpVariable() items.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoBodies.h"
+#include "ChLcpVariables.h"
+
+namespace chrono
+{
+
+
+/// Base class for friction constraints (see specialized children classes
+/// for more details - this is mostly an interface)
+
+class ChApi ChLcpConstraintTwoFrictionT : public ChLcpConstraintTwoBodies
+{
+	CH_RTTI(ChLcpConstraintTwoFrictionT, ChLcpConstraintTwoBodies)
+
+			//
+			// DATA
+			//
+
+protected:
+
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoFrictionT()
+					{
+						mode = CONSTRAINT_FRIC; 
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the  and the normal constraint
+						/// other tangential constraint (the latter is mandatory only
+						/// for the second of the two tangential constraints)
+	ChLcpConstraintTwoFrictionT( ChLcpVariablesBody* mvariables_a,
+								ChLcpVariablesBody* mvariables_b)
+				: ChLcpConstraintTwoBodies(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_FRIC; 
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoFrictionT(const ChLcpConstraintTwoFrictionT& other) 
+				: ChLcpConstraintTwoBodies(other)
+					{
+					}
+
+	virtual ~ChLcpConstraintTwoFrictionT() {};
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintTwoFrictionT(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoFrictionT& operator=(const ChLcpConstraintTwoFrictionT& other)
+					{
+						if (&other == this)
+							return *this;
+
+						// copy parent class data
+						ChLcpConstraintTwoBodies::operator=(other);
+
+						return *this;
+					}
+
+
+			//
+			// FUNCTIONS
+			//
+
+					/// Tells that this constraint is not linear, that is: it cannot
+					/// be solved with a plain simplex solver.
+	virtual bool IsLinear() {return false;}
+
+					/// The constraint is satisfied?
+	virtual double Violation(double mc_i);
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpConstraintTwoFrictionT.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.cpp
new file mode 100644
index 0000000..841bea6
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.cpp
@@ -0,0 +1,235 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoGeneric.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include "ChLcpConstraintTwoGeneric.h" 
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoGeneric> a_registration_ChLcpConstraintTwoGeneric;
+
+
+
+ChLcpConstraintTwoGeneric& ChLcpConstraintTwoGeneric::operator=(const ChLcpConstraintTwoGeneric& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpConstraintTwo::operator=(other);
+
+	if (other.Cq_a)
+	{
+		if (Cq_a==NULL)
+			Cq_a = new ChMatrixDynamic<float>;
+		Cq_a->CopyFromMatrix(*other.Cq_a);
+	}
+	else
+	{
+		if (Cq_a) delete Cq_a; Cq_a=NULL;
+	}
+
+	if (other.Cq_b)
+	{
+		if (Cq_b==NULL)
+			Cq_b = new ChMatrixDynamic<float>;
+		Cq_b->CopyFromMatrix(*other.Cq_b);
+	}
+	else
+	{
+		if (Cq_b) delete Cq_b; Cq_b=NULL;
+	}
+
+	if (other.Eq_a)
+	{
+		if (Eq_a==NULL)
+			Eq_a = new ChMatrixDynamic<float>;
+		Eq_a->CopyFromMatrix(*other.Eq_a);
+	}
+	else
+	{
+		if (Eq_a) delete Eq_a; Eq_a=NULL;
+	}
+
+	if (other.Eq_b)
+	{
+		if (Eq_b==NULL)
+			Eq_b = new ChMatrixDynamic<float>;
+		Eq_b->CopyFromMatrix(*other.Eq_b);
+	}
+	else
+	{
+		if (Eq_b) delete Eq_b; Eq_b=NULL;
+	}
+
+	return *this;
+}
+
+
+
+
+void ChLcpConstraintTwoGeneric::SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b)
+{
+	if (!mvariables_a || !mvariables_b)
+	{
+		SetValid(false);
+		return ;
+	}
+
+	SetValid(true);
+	variables_a = mvariables_a;
+	variables_b = mvariables_b;
+
+	if (variables_a->Get_ndof())
+	{
+		if (!Cq_a)
+			Cq_a = new ChMatrixDynamic<float>(1, variables_a->Get_ndof());
+		else
+			Cq_a->Resize(1, variables_a->Get_ndof());
+
+		if (!Eq_a)
+			Eq_a = new ChMatrixDynamic<float>(variables_a->Get_ndof(), 1);
+		else
+			Eq_a->Resize(variables_a->Get_ndof(), 1);
+	}
+	else
+	{
+		if (Cq_a) delete Cq_a; Cq_a = NULL;
+		if (Eq_a) delete Eq_a; Eq_a = NULL;
+	}
+
+	if (variables_b->Get_ndof())
+	{
+		if (!Cq_b)
+			Cq_b = new ChMatrixDynamic<float>(1, variables_b->Get_ndof());
+		else
+			Cq_b->Resize(1, variables_b->Get_ndof());
+
+		if (!Eq_b)
+			Eq_b = new ChMatrixDynamic<float>(variables_b->Get_ndof(), 1);
+		else
+			Eq_b->Resize(variables_b->Get_ndof(), 1);
+	}
+	else
+	{
+		if (Cq_b) delete Cq_b; Cq_b = NULL;
+		if (Eq_b) delete Eq_b; Eq_b = NULL;
+	}
+}
+
+
+
+
+void ChLcpConstraintTwoGeneric::Update_auxiliary()
+{
+	//1- Assuming jacobians are already computed, now compute
+	//   the matrices [Eq_a]=[invM_a]*[Cq_a]' and [Eq_b]
+	if (variables_a->IsActive())
+	if (variables_a->Get_ndof())
+	{
+		ChMatrixDynamic<float> mtemp1(variables_a->Get_ndof(), 1);
+		mtemp1.CopyFromMatrixT(*Cq_a);
+		variables_a->Compute_invMb_v(*Eq_a, mtemp1);
+	}
+	if (variables_b->IsActive())
+	if (variables_b->Get_ndof())
+	{
+		ChMatrixDynamic<float> mtemp1(variables_b->Get_ndof(), 1);
+		mtemp1.CopyFromMatrixT(*Cq_b);
+		variables_b->Compute_invMb_v(*Eq_b, mtemp1);
+	}
+
+	//2- Compute g_i = [Cq_i]*[invM_i]*[Cq_i]' + cfm_i
+	g_i = 0;
+	ChMatrixDynamic<float> res(1,1);
+	if (variables_a->IsActive())
+	if (variables_a->Get_ndof())
+	{
+		res.MatrMultiply(*Cq_a, *Eq_a);
+		g_i = res(0,0);
+	}
+	if (variables_b->IsActive())
+	if (variables_b->Get_ndof())
+	{
+		res.MatrMultiply(*Cq_b, *Eq_b);
+		g_i += res(0,0);
+	}
+
+	//3- adds the constraint force mixing term (usually zero):
+	if (cfm_i)
+		g_i += cfm_i;
+};
+
+
+
+
+
+
+
+void ChLcpConstraintTwoGeneric::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwo::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream << Cq_a;
+	// mstream << Cq_b;
+}
+ 
+
+
+
+void ChLcpConstraintTwoGeneric::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwo::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream >> Cq_a;
+	// mstream >> Cq_b;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.h
new file mode 100644
index 0000000..dac2c67
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGeneric.h
@@ -0,0 +1,278 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOGENERIC_H
+#define CHLCPCONSTRAINTTWOGENERIC_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoGeneric.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between two ChLcpVariable items.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwo.h"
+#include "ChLcpVariables.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the base ChLcpConstraintTwo(),
+/// which is a base for pairwise constraints. So here this class implements
+/// the functionality for a constraint between a COUPLE of TWO
+/// objects of type ChLcpVariables(), with generic number of scalar
+/// variables each (ex.ChLcpVariablesGeneric() or ChLcpVariablesBody() )
+/// and defines two constraint matrices, whose column number automatically
+/// matches the number of elements in variables vectors.
+///  Before starting the LCP solver one must provide the proper
+/// values in constraints (and update them if necessary), i.e.
+/// must set at least the c_i and b_i values, and jacobians.
+
+class ChApi ChLcpConstraintTwoGeneric : public ChLcpConstraintTwo
+{
+	CH_RTTI(ChLcpConstraintTwoGeneric, ChLcpConstraintTwo)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// The [Cq_a] jacobian of the constraint
+	ChMatrixDynamic<float>* Cq_a;
+				/// The [Cq_b] jacobian of the constraint
+	ChMatrixDynamic<float>* Cq_b;
+
+
+				// Auxiliary data: will be used by iterative constraint solvers:
+
+				/// The [Eq_a] product [Eq_a]=[invM_a]*[Cq_a]'
+	ChMatrixDynamic<float>* Eq_a;
+				/// The [Eq_a] product [Eq_b]=[invM_b]*[Cq_b]'
+	ChMatrixDynamic<float>* Eq_b;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoGeneric()
+					{
+						Cq_a = Cq_b = Eq_a = Eq_b = NULL;
+					};
+
+						/// Construct and immediately set references to variables
+	ChLcpConstraintTwoGeneric(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b)
+					{
+						Cq_a = Cq_b = Eq_a = Eq_b = NULL;
+						SetVariables(mvariables_a, mvariables_b);
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoGeneric(const ChLcpConstraintTwoGeneric& other) 
+			: ChLcpConstraintTwo(other)
+					{
+						Cq_a = Cq_b = Eq_a = Eq_b = NULL;
+						if(other.Cq_a) Cq_a = new ChMatrixDynamic<float>(*other.Cq_a);
+						if(other.Cq_b) Cq_b = new ChMatrixDynamic<float>(*other.Cq_b);
+						if(other.Eq_a) Eq_a = new ChMatrixDynamic<float>(*other.Eq_a);
+						if(other.Eq_b) Eq_b = new ChMatrixDynamic<float>(*other.Eq_b);
+					}
+
+	virtual ~ChLcpConstraintTwoGeneric()
+					{
+						if (Cq_a) delete Cq_a;
+						if (Cq_b) delete Cq_b;
+						if (Eq_a) delete Eq_a;
+						if (Eq_b) delete Eq_b;
+					};
+
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintTwoGeneric(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoGeneric& operator=(const ChLcpConstraintTwoGeneric& other);
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_a() {return Cq_a;}
+				/// Access jacobian matrix
+	virtual ChMatrix<float>* Get_Cq_b() {return Cq_b;}
+
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_a() {return Eq_a;}
+				/// Access auxiliary matrix (ex: used by iterative solvers)
+	virtual ChMatrix<float>* Get_Eq_b() {return Eq_b;}
+
+
+
+				/// Set references to the constrained objects, each of ChLcpVariables type,
+				/// automatically creating/resizing jacobians if needed.
+	virtual void SetVariables(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b);
+
+
+				/// This function updates the following auxiliary data:
+				///  - the Eq_a and Eq_b matrices
+				///  - the g_i product
+				/// This is often called by LCP solvers at the beginning
+				/// of the solution process.
+				/// Most often, inherited classes won't need to override this.
+	virtual void Update_auxiliary();
+					
+
+
+				///  This function must computes the product between
+				/// the row-jacobian of this constraint '[Cq_i]' and the
+				/// vector of variables, 'v'. that is    CV=[Cq_i]*v
+				///  This is used for some iterative LCP solvers.
+	virtual double Compute_Cq_q() 
+					{
+						double ret = 0;
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a->GetColumns(); i++)
+							ret += Cq_a->ElementN(i) * variables_a->Get_qb().ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b->GetColumns(); i++)
+							ret += Cq_b->ElementN(i) * variables_b->Get_qb().ElementN(i);
+
+						return ret;
+					}
+
+
+
+				///  This function must increment the vector of variables
+				/// 'v' with the quantity [invM]*[Cq_i]'*deltal,that is
+				///   v+=[invM]*[Cq_i]'*deltal  or better: v+=[Eq_i]*deltal
+				///  This is used for some iterative LCP solvers.
+
+	virtual void Increment_q(const double deltal)
+					{
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Eq_a->GetRows(); i++)
+							variables_a->Get_qb()(i) += Eq_a->ElementN(i) * deltal;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Eq_b->GetRows(); i++)
+							variables_b->Get_qb()(i) += Eq_b->ElementN(i) * deltal;
+					};
+
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyAndAdd(double& result, ChMatrix<double>& vect)
+					{
+						int off_a = variables_a->GetOffset();
+						int off_b = variables_b->GetOffset();
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a->GetColumns(); i++)
+							result += vect(off_a+i) * Cq_a->ElementN(i);
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b->GetColumns(); i++)
+							result += vect(off_b+i) * Cq_b->ElementN(i);
+					};
+
+				/// Computes the product of the corresponding transposed blocks in the 
+				/// system matrix (ie. the TRANSPOSED jacobian matrix C_q') by 'l', and add to 'result'. 
+				/// NOTE: the 'result' vector must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect; 
+	virtual void MultiplyTandAdd(ChMatrix<double>& result, double l)
+					{
+						int off_a = variables_a->GetOffset();
+						int off_b = variables_b->GetOffset();
+
+						if (variables_a->IsActive())
+						 for (int i= 0; i < Cq_a->GetColumns(); i++)
+							result(off_a+i) += Cq_a->ElementN(i) * l;
+
+						if (variables_b->IsActive())
+						 for (int i= 0; i < Cq_b->GetColumns(); i++)
+							result(off_b+i) += Cq_b->ElementN(i) * l;
+					};
+
+
+				/// Puts the two jacobian parts into the 'insrow' row of a sparse matrix,
+				/// where both portions of the jacobian are shifted in order to match the 
+				/// offset of the corresponding ChLcpVariable.
+				/// This is used only by the ChLcpSimplex solver (iterative solvers 
+				/// don't need to know jacobians explicitly)
+	virtual void Build_Cq(ChSparseMatrix& storage, int insrow)
+					{
+						if (variables_a->IsActive())
+							storage.PasteMatrixFloat(Cq_a, insrow, variables_a->GetOffset());
+						if (variables_b->IsActive())
+							storage.PasteMatrixFloat(Cq_b, insrow, variables_b->GetOffset());
+					}
+	virtual void Build_CqT(ChSparseMatrix& storage, int inscol)
+					{
+						if (variables_a->IsActive())
+							storage.PasteTranspMatrixFloat(Cq_a, variables_a->GetOffset(), inscol);
+						if (variables_b->IsActive())
+							storage.PasteTranspMatrixFloat(Cq_b, variables_b->GetOffset(), inscol);
+					}
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGenericBoxed.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGenericBoxed.cpp
new file mode 100644
index 0000000..26abc78
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGenericBoxed.cpp
@@ -0,0 +1,79 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoGenericBoxed.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include "ChLcpConstraintTwoGenericBoxed.h" 
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoGenericBoxed> a_registration_ChLcpConstraintTwoGenericBoxed;
+
+
+double ChLcpConstraintTwoGenericBoxed::Violation(double mc_i) 
+{
+	if ((l_i- 10e-5 < l_min)||(l_i +10e-5 > l_max))
+		return 0;
+	return mc_i;
+}
+
+
+void ChLcpConstraintTwoGenericBoxed::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoGeneric::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << l_min;
+	mstream << l_max;
+} 
+ 
+
+
+void ChLcpConstraintTwoGenericBoxed::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoGeneric::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> l_min;
+	mstream >> l_max;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGenericBoxed.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGenericBoxed.h
new file mode 100644
index 0000000..d4f60c0
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoGenericBoxed.h
@@ -0,0 +1,173 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOGENERICBOXED_H
+#define CHLCPCONSTRAINTTWOGENERICBOXED_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoGenericBoxed.h
+//
+//    An 'easy' derived class for representing a
+//   constraint between two ChLcpVariable items, where
+//   the multiplier must be   l_min < l < l_max
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoGeneric.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the base ChLcpConstraintTwoGeneric(),
+/// which can be used for most pairwise constraints, and adds the
+/// feature that the multiplier must be   
+///        l_min < l < l_max
+/// that is, the multiplier is 'boxed'. 
+/// Note that, if l_min = 0 and l_max = infinite, this can work
+/// also as an unilateral constraint..
+///  Before starting the LCP solver one must provide the proper
+/// values in constraints (and update them if necessary), i.e.
+/// must set at least the c_i and b_i values, and jacobians.
+
+class ChApi ChLcpConstraintTwoGenericBoxed : public ChLcpConstraintTwoGeneric
+{
+	CH_RTTI(ChLcpConstraintTwoGenericBoxed, ChLcpConstraintTwoGeneric)
+
+			//
+			// DATA
+			//
+
+protected:
+	double l_min;
+	double l_max;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoGenericBoxed()
+					{
+						l_min = -1.; 
+						l_max =  1.;
+					};
+
+						/// Construct and immediately set references to variables
+	ChLcpConstraintTwoGenericBoxed(ChLcpVariables* mvariables_a, ChLcpVariables* mvariables_b) 
+			: ChLcpConstraintTwoGeneric(mvariables_a, mvariables_b)
+					{
+						l_min = -1.; 
+						l_max =  1.;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoGenericBoxed(const ChLcpConstraintTwoGenericBoxed& other) 
+			: ChLcpConstraintTwoGeneric(other)
+					{
+						l_min = other.l_min; 
+						l_max = other.l_max;
+					}
+
+	virtual ~ChLcpConstraintTwoGenericBoxed()
+					{
+					};
+
+
+	virtual ChLcpConstraintTwoGenericBoxed* new_Duplicate () {return new ChLcpConstraintTwoGenericBoxed(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoGenericBoxed& operator=(const ChLcpConstraintTwoGenericBoxed& other)
+					{
+						if (&other == this) return *this;
+
+						// copy parent class data
+						ChLcpConstraintTwoGeneric::operator=(other);
+
+						l_min = other.l_min; 
+						l_max = other.l_max;
+
+						return *this;
+					}
+
+
+			//
+			// FUNCTIONS
+			//
+					 /// Set lower/upper limit for the multiplier.
+	void SetBoxedMinMax(double mmin, double mmax) 
+					{
+						assert (mmin <= mmax);
+						l_min = mmin;
+						l_max = mmax;
+					}
+
+					/// Get the lower limit for the multiplier
+	double GetBoxedMin() {return l_min;}
+					/// Get the upper limit for the multiplier
+	double GetBoxedMax() {return l_max;}
+
+				/// For iterative solvers: project the value of a possible
+				/// 'l_i' value of constraint reaction onto admissible orthant/set.
+				/// This 'boxed implementation overrides the default do-nothing case.
+	virtual void Project()
+					{
+						if (l_i < l_min)
+							l_i=l_min;
+						if (l_i > l_max)
+							l_i=l_max;
+					}
+
+				/// Given the residual of the constraint computed as the
+				/// linear map  mc_i =  [Cq]*q + b_i + cfm*l_i , returns the
+				/// violation of the constraint, considering inequalities, etc.
+	virtual double Violation(double mc_i);
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingN.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingN.cpp
new file mode 100644
index 0000000..24d9b0d
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingN.cpp
@@ -0,0 +1,166 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoRollingN.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintTwoRollingN.h" 
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoRollingN> a_registration_ChLcpConstraintTwoRollingN;
+
+  
+
+void ChLcpConstraintTwoRollingN::Project()
+{
+	if (!constraint_U)
+		return;
+
+	if (!constraint_V)
+		return;
+
+	if (!constraint_N)
+		return;
+
+	// METHOD 
+	// Anitescu-Tasora projection on rolling-friction cone generator and polar cone 
+	// (contractive, but performs correction on three components: normal,u,v)
+
+	double f_n = constraint_N->Get_l_i();
+	double t_n = this->Get_l_i();
+	double t_u = constraint_U->Get_l_i();
+	double t_v = constraint_V->Get_l_i();
+	double t_tang = sqrt (t_v*t_v + t_u*t_u );
+	double t_sptang = fabs(t_n);  // = sqrt(t_n*t_n);
+
+	// A Project the spinning friction (approximate - should do cone 
+	//   projection stuff as in B, but spinning friction is usually very low...)
+
+	if (spinningfriction)
+	{
+			// inside upper cone? keep untouched!
+		if (t_sptang < spinningfriction * f_n)
+		{
+		}
+		else
+		{
+				// inside lower cone? reset  normal,u,v to zero!
+			if ((t_sptang < -(1.0/spinningfriction) * f_n)||(fabs(f_n)<10e-15))
+			{
+				constraint_N->Set_l_i(0 );
+				this->Set_l_i        (0 );
+			}
+			else
+			{
+					// remaining case: project orthogonally to generator segment of upper cone (CAN BE simplified)
+				double f_n_proj =  ( t_sptang * spinningfriction + f_n ) / (spinningfriction*spinningfriction + 1) ;
+				double t_tang_proj = f_n_proj * spinningfriction;
+				double tproj_div_t = t_tang_proj / t_sptang;
+				double t_n_proj = tproj_div_t * t_n; 
+
+				constraint_N->Set_l_i(f_n_proj);
+				this->Set_l_i        (t_n_proj);
+			}
+		}
+	}
+
+	// B Project the rolling friction
+
+		// shortcut
+	if (!rollingfriction)
+	{
+		constraint_U->Set_l_i(0);
+		constraint_V->Set_l_i(0);
+		if (f_n < 0)
+			constraint_N->Set_l_i( 0 );
+		return;
+	}
+
+		// inside upper cone? keep untouched!
+	if (t_tang < rollingfriction * f_n)
+		return;
+
+		// inside lower cone? reset  normal,u,v to zero!
+	if ((t_tang < -(1.0/rollingfriction) * f_n)||(fabs(f_n)<10e-15))
+	{
+		double f_n_proj = 0;
+		double t_u_proj = 0;
+		double t_v_proj = 0;
+
+		constraint_N->Set_l_i(f_n_proj );
+		constraint_U->Set_l_i(t_u_proj);
+		constraint_V->Set_l_i(t_v_proj);
+
+		return;
+	} 
+ 
+		// remaining case: project orthogonally to generator segment of upper cone
+	double f_n_proj =  ( t_tang * rollingfriction + f_n ) / (rollingfriction*rollingfriction + 1) ;
+	double t_tang_proj = f_n_proj * rollingfriction;
+	double tproj_div_t = t_tang_proj / t_tang;
+	double t_u_proj = tproj_div_t * t_u;
+	double t_v_proj = tproj_div_t * t_v; 
+
+	constraint_N->Set_l_i(f_n_proj);
+	constraint_U->Set_l_i(t_u_proj);
+	constraint_V->Set_l_i(t_v_proj);	
+	
+}
+
+
+void ChLcpConstraintTwoRollingN::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoBodies::StreamOUT(mstream);
+
+		// stream out all member data..
+	mstream << rollingfriction;
+	mstream << spinningfriction;
+
+}
+
+void ChLcpConstraintTwoRollingN::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoBodies::StreamIN(mstream);
+
+		// stream in all member data..
+	mstream >> rollingfriction;
+	mstream >> spinningfriction;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingN.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingN.h
new file mode 100644
index 0000000..6173f63
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingN.h
@@ -0,0 +1,199 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOROLLINGN_H
+#define CHLCPCONSTRAINTTWOROLLINGN_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoRollingN.h
+//
+//    An 'easy' derived class for modeling rolling friction.
+//   Used with for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoRollingT.h"
+#include "ChLcpConstraintTwoContactN.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  This class is inherited by the ChLcpConstraintTwoBodies(),
+/// It is used to represent the rolling friction between two objects
+/// ONLY when also two ChLcpConstraintTwoRollingT objects and a 
+/// ChLcpConstraintTwoContactN are used to represent contact. 
+
+class ChApi ChLcpConstraintTwoRollingN : public ChLcpConstraintTwoBodies
+{
+	CH_RTTI(ChLcpConstraintTwoRollingN, ChLcpConstraintTwoBodies)
+
+			//
+			// DATA
+			//
+
+protected:
+				/// the rolling friction coefficient
+	float rollingfriction;
+	float spinningfriction;
+
+					/// the pointer to U tangential component
+	ChLcpConstraintTwoRollingT* constraint_U;
+					/// the pointer to V tangential component
+	ChLcpConstraintTwoRollingT* constraint_V;
+					/// the pointer to normal component
+	ChLcpConstraintTwoContactN* constraint_N;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoRollingN() 
+					{
+						mode = CONSTRAINT_FRIC;
+						rollingfriction = 0.0;
+						spinningfriction = 0.0;
+						constraint_U = constraint_V = 0;
+						constraint_N = 0;
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the U and V tangential friction constraints
+	ChLcpConstraintTwoRollingN(ChLcpVariablesBody* mvariables_a, 
+							   ChLcpVariablesBody* mvariables_b,
+							   ChLcpConstraintTwoRollingT* aU = 0,
+							   ChLcpConstraintTwoRollingT* aV = 0,
+							   ChLcpConstraintTwoContactN* aN = 0
+								)
+			: ChLcpConstraintTwoBodies(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_FRIC;
+						rollingfriction = 0.0;
+						spinningfriction = 0.0;
+						constraint_U = aU;
+						constraint_V = aV;
+						constraint_N = aN;
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoRollingN(const ChLcpConstraintTwoRollingN& other) 
+			: ChLcpConstraintTwoBodies(other)
+					{
+						rollingfriction=other.rollingfriction;
+						spinningfriction=other.spinningfriction;
+						constraint_U = other.constraint_U;
+						constraint_V = other.constraint_V;
+						constraint_N = other.constraint_N;
+					}
+
+	virtual ~ChLcpConstraintTwoRollingN()
+					{
+					};
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintTwoRollingN(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoRollingN& operator=(const ChLcpConstraintTwoRollingN& other)
+					{
+						if (&other == this)
+							return *this;
+						// copy parent class data
+						ChLcpConstraintTwoBodies::operator=(other);
+						
+						rollingfriction=other.rollingfriction;
+						spinningfriction=other.spinningfriction;
+						constraint_U = other.constraint_U;
+						constraint_V = other.constraint_V;
+						constraint_N = other.constraint_N;
+						return *this;
+					}
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+
+				/// Get the rolling friction coefficient
+	float GetRollingFrictionCoefficient() {return rollingfriction; }
+				/// Set the rolling friction coefficient
+	void SetRollingFrictionCoefficient(float mcoeff) {rollingfriction = mcoeff;}
+
+				/// Get the spinning friction coefficient
+	float GetSpinningFrictionCoefficient() {return spinningfriction; }
+				/// Set the spinning friction coefficient
+	void SetSpinningFrictionCoefficient(float mcoeff) {spinningfriction = mcoeff;}
+
+				/// Get pointer to U tangential component
+	ChLcpConstraintTwoRollingT* GetRollingConstraintU() {return constraint_U;}			
+				/// Get pointer to V tangential component
+	ChLcpConstraintTwoRollingT* GetRollingConstraintV() {return constraint_V;}
+				/// Get pointer to normal contact component
+	ChLcpConstraintTwoContactN* GetNormalConstraint() {return constraint_N;}
+
+				/// Set pointer to U tangential component
+	void SetRollingConstraintU(ChLcpConstraintTwoRollingT* mconstr) {constraint_U = mconstr;}
+				/// Set pointer to V tangential component
+	void SetRollingConstraintV(ChLcpConstraintTwoRollingT* mconstr) {constraint_V = mconstr;}
+				/// Set pointer to normal contact component
+	void SetNormalConstraint(ChLcpConstraintTwoContactN* mconstr) {constraint_N = mconstr;}
+
+
+				/// For iterative solvers: project the value of a possible
+				/// 'l_i' value of constraint reaction onto admissible set.
+				/// This projection will also modify the l_i values of the two
+				/// tangential friction constraints (projection onto the friction cone,
+				/// as by Anitescu-Tasora theory).
+	virtual void Project();
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingT.cpp b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingT.cpp
new file mode 100644
index 0000000..fd6a4e9
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingT.cpp
@@ -0,0 +1,68 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoRollingT.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpConstraintTwoRollingT.h"
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time 
+// dynamic creation and persistence
+ChClassRegister<ChLcpConstraintTwoRollingT> a_registration_ChLcpConstraintTwoRollingT;
+
+
+double ChLcpConstraintTwoRollingT::Violation(double mc_i)
+{
+	return 0.0; //***TO DO*** compute true violation when in sticking?
+}
+
+
+
+void ChLcpConstraintTwoRollingT::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpConstraintTwoBodies::StreamOUT(mstream);
+
+}
+ 
+void ChLcpConstraintTwoRollingT::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpConstraintTwoBodies::StreamIN(mstream);
+
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingT.h b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingT.h
new file mode 100644
index 0000000..59e981e
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpConstraintTwoRollingT.h
@@ -0,0 +1,130 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPCONSTRAINTTWOROLLINGT_H
+#define CHLCPCONSTRAINTTWOROLLINGT_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpConstraintTwoRollingT.h
+//
+//  Class used to represent rolling friction constraint
+// between two ChLcpVariable() items.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpConstraintTwoBodies.h"
+#include "ChLcpVariables.h"
+
+namespace chrono
+{
+
+
+/// This is used to make the rolling friction constraint. This 
+/// must be used in twice copy each ChLcpConstraintTwoRollingN
+
+class ChApi ChLcpConstraintTwoRollingT: public ChLcpConstraintTwoBodies
+{
+	CH_RTTI(ChLcpConstraintTwoRollingT, ChLcpConstraintTwoBodies)
+
+			//
+			// DATA
+			//
+
+protected:
+
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+						/// Default constructor
+	ChLcpConstraintTwoRollingT()
+					{
+						mode = CONSTRAINT_FRIC; 
+					};
+
+						/// Construct and immediately set references to variables,
+						/// also setting the  and the normal constraint
+						/// other tangential constraint (the latter is mandatory only
+						/// for the second of the two tangential constraints)
+	ChLcpConstraintTwoRollingT( ChLcpVariablesBody* mvariables_a,
+								ChLcpVariablesBody* mvariables_b)
+				: ChLcpConstraintTwoBodies(mvariables_a, mvariables_b)
+					{
+						mode = CONSTRAINT_FRIC; 
+					};
+
+						/// Copy constructor
+	ChLcpConstraintTwoRollingT(const ChLcpConstraintTwoRollingT& other) 
+				: ChLcpConstraintTwoBodies(other)
+					{
+					}
+
+	virtual ~ChLcpConstraintTwoRollingT() {};
+
+	virtual ChLcpConstraint* new_Duplicate () {return new ChLcpConstraintTwoRollingT(*this);};
+
+					/// Assignment operator: copy from other object
+	ChLcpConstraintTwoRollingT& operator=(const ChLcpConstraintTwoRollingT& other)
+					{
+						if (&other == this)
+							return *this;
+
+						// copy parent class data
+						ChLcpConstraintTwoBodies::operator=(other);
+
+						return *this;
+					}
+
+
+			//
+			// FUNCTIONS
+			//
+
+					/// Tells that this constraint is not linear, that is: it cannot
+					/// be solved with a plain simplex solver.
+	virtual bool IsLinear() {return false;}
+
+					/// The constraint is satisfied?
+	virtual double Violation(double mc_i);
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpConstraintTwoRollingT.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpDirectSolver.h b/SRC/ChronoEngine/lcp/ChLcpDirectSolver.h
new file mode 100644
index 0000000..51abbc5
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpDirectSolver.h
@@ -0,0 +1,82 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPDIRECTSOLVER_H
+#define CHLCPDIRECTSOLVER_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpDirectSolver.h
+//
+//    Base class for all LCP solution methods
+//   based on direct schemes, such as the
+//   simplex-based / pivoting methods.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpSolver.h"
+
+
+namespace chrono
+{
+
+///    Base class for DIRECT solvers aimed at solving
+///   LCP linear complementarity problems arising
+///   from QP optimization problems.
+///    This class does nothing: it is up to inherited
+///   classes to implement specific solution methods,
+///   such as simplex, iterative SOR, etc.
+///    The LCP problem must be in this (symmetric) 
+///   form:
+///
+///    | M -Cq'|*|q|- | f|= |0| ,   c>=0, l>=0, l*c=0;
+///    | Cq  0 | |l|  |-b|  |c|
+///
+///   as arising in the solution of QP with
+///   inequalities or in multibody problems.
+
+class ChApi ChLcpDirectSolver : public ChLcpSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpDirectSolver()	{};
+
+	virtual ~ChLcpDirectSolver() {};
+
+			//
+			// FUNCTIONS
+			//
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpDirectSolver.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.cpp
new file mode 100644
index 0000000..1a00428
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.cpp
@@ -0,0 +1,367 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativeAPGD.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpIterativeAPGD.h"
+#include "ChLcpConstraintTwoFrictionT.h"
+
+namespace chrono
+{
+
+double ChLcpIterativeAPGD::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+
+	
+
+	double gdiff= 0.000001;
+
+	double maxviolation = 0.;
+	int i_friction_comp = 0;
+
+	double theta_k=1.0;
+	double theta_k1=theta_k;
+	double beta_k1=0.0;
+
+	double L_k=0.0;
+	double t_k=0.0;
+
+	tot_iterations = 0;
+	// Allocate auxiliary vectors;
+	
+	int nc = sysd.CountActiveConstraints();
+	if (verbose) GetLog() <<"\n-----Accelerated Projected Gradient Descent, solving nc=" << nc << "unknowns \n";
+
+	//ChMatrixDynamic<> ml(nc,1);		//I made this into a class variable so I could print it easier -Hammad
+	ml.Resize(nc,1);
+	ChMatrixDynamic<> mx(nc,1);
+	ChMatrixDynamic<> ms(nc,1);
+	ChMatrixDynamic<> my(nc,1);
+	ChMatrixDynamic<> ml_candidate(nc,1);
+	ChMatrixDynamic<> mg(nc,1);
+	ChMatrixDynamic<> mg_tmp(nc,1);
+	ChMatrixDynamic<> mg_tmp1(nc,1);
+	ChMatrixDynamic<> mg_tmp2(nc,1);
+	//ChMatrixDynamic<> mb(nc,1);   //I made this into a class variable so I could print it easier -Hammad
+	mb.Resize(nc,1);
+	ChMatrixDynamic<> mb_tmp(nc,1);
+
+
+	// Update auxiliary data in all constraints before starting,
+	// that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//  Can be used for the fixed point phase and/or by preconditioner.
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}
+	}
+
+	// ***TO DO*** move the following thirty lines in a short function ChLcpSystemDescriptor::ShurBvectorCompute() ?
+
+	// Compute the b_shur vector in the Shur complement equation N*l = b_shur
+	// with 
+	//   N_shur  = D'* (M^-1) * D
+	//   b_shur  = - c + D'*(M^-1)*k = b_i + D'*(M^-1)*k
+	// but flipping the sign of lambdas,  b_shur = - b_i - D'*(M^-1)*k
+	// Do this in three steps:
+	
+	// Put (M^-1)*k    in  q  sparse vector of each variable..
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb 
+
+	// ...and now do  b_shur = - D'*q = - D'*(M^-1)*k ..
+	int s_i = 0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mb(s_i, 0) = - mconstraints[ic]->Compute_Cq_q();
+			++s_i;
+		}
+
+	// ..and finally do   b_shur = b_shur - c
+	sysd.BuildBiVector(mb_tmp);	// b_i   =   -c   = phi/h
+	mb.MatrDec(mb_tmp);
+
+		// Optimization: backup the  q  sparse data computed above, 
+		// because   (M^-1)*k   will be needed at the end when computing primals.
+	ChMatrixDynamic<> mq; 
+	sysd.FromVariablesToVector(mq, true);	
+
+
+	// Initialize lambdas
+	if (warm_start)
+		sysd.FromConstraintsToVector(ml);
+	else
+		ml.FillElem(0);
+
+
+	// Initial projection of ml   ***TO DO***?
+	sysd.ConstraintsProject(ml);
+
+
+	// Fallback solution
+	double lastgoodres  = 10e30;
+	double lastgoodfval = 10e30;
+	ml_candidate.CopyFromMatrix(ml);
+
+	// g = gradient of 0.5*l'*N*l-l'*b
+	// g = N*l-b
+	sysd.ShurComplementProduct(mg, &ml, 0);		// 1)  g = N*l ...        #### MATR.MULTIPLICATION!!!###
+	mg.MatrDec(mb);								// 2)  g = N*l - b_shur ...
+
+	//
+	// THE LOOP
+	//
+
+	double mf_p =0;
+
+	mb_tmp.FillElem(-1.0);
+	mb_tmp.MatrInc(ml);
+	sysd.ShurComplementProduct(mg_tmp,&mb_tmp,0); // 1)  g = N*l ...        #### MATR.MULTIPLICATION!!!###
+	if(mb_tmp.NormTwo()==0){
+		L_k=1;
+	}else{
+		L_k=mg_tmp.NormTwo()/mb_tmp.NormTwo();
+	}
+	t_k=1/L_k;
+
+	double obj1=0;
+	double obj2=0;
+
+	my.CopyFromMatrix(ml);
+	mx.CopyFromMatrix(ml);
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		sysd.ShurComplementProduct(mg_tmp1, &my, 0);	// 1)  g_tmp1 = N*yk ...        #### MATR.MULTIPLICATION!!!###
+		mg.MatrSub(mg_tmp1,mb);							// 2)  g = N*yk - b_shur ...
+
+		mx.CopyFromMatrix(mg);						// 1) xk1=g
+		mx.MatrScale(-t_k); 						// 2) xk1=-tk*g
+		mx.MatrInc(my);								// 3) xk1=y-tk*g
+		sysd.ConstraintsProject(mx);				// 4) xk1=P(y-tk*g)
+
+		//Now do backtracking for the steplength
+		sysd.ShurComplementProduct(mg_tmp, &mx, 0);		// 1)  g_tmp = N*xk1 ...        #### MATR.MULTIPLICATION!!!###
+		mg_tmp2.MatrSub(mg_tmp,mb);						// 2)  g_tmp2 = N*xk1 - b_shur ...
+		mg_tmp.MatrScale(0.5);							// 3)  g_tmp=0.5*N*xk1
+		mg_tmp.MatrDec(mb);								// 4)  g_tmp=0.5*N*xk1-b_shur
+		obj1 = mx.MatrDot(&mx,&mg_tmp);					// 5)  obj1=xk1'*(0.5*N*x_k1-b_shur)
+
+		mg_tmp1.MatrScale(0.5);							// 1)  g_tmp1 = 0.5*N*yk
+		mg_tmp1.MatrDec(mb);							// 2)  g_tmp1 = 0.5*N*yk-b_shur
+		obj2 = my.MatrDot(&my,&mg_tmp1);				// 3)  obj2 = yk'*(0.5*N*yk-b_shur)
+
+		ms.MatrSub(mx,my);								// 1)  s=xk1-yk
+		while(obj1>obj2+mg.MatrDot(&mg,&ms)+0.5*L_k*pow(ms.NormTwo(),2.0))
+		{
+			L_k=2*L_k;
+			t_k=1/L_k;
+
+			mx.CopyFromMatrix(mg);						// 1) xk1=g
+			mx.MatrScale(-t_k);							// 2) xk1=-tk*g
+			mx.MatrInc(my);								// 3) xk1=yk-tk*g
+			sysd.ConstraintsProject(mx);				// 4) xk1=P(yk-tk*g)
+
+			sysd.ShurComplementProduct(mg_tmp, &mx, 0);		// 1)  g_tmp = N*xk1 ...        #### MATR.MULTIPLICATION!!!###
+			mg_tmp2.MatrSub(mg_tmp,mb);						// 2)  g_tmp2 = N*xk1 - b_shur ...
+			mg_tmp.MatrScale(0.5);							// 3)  g_tmp=0.5*N*xk1
+			mg_tmp.MatrDec(mb);								// 4)  g_tmp=0.5*N*xk1-b_shur
+			obj1 = mx.MatrDot(&mx,&mg_tmp);					// 5)  obj1=xk1'*(0.5*N*x_k1-b_shur)
+
+			ms.MatrSub(mx,my);								// 1)  s=xk1-yk
+			if (verbose) GetLog() << "APGD halving stepsize at it " << iter  << "\n";
+		}
+
+		theta_k1=(-pow(theta_k,2)+theta_k*sqrt(pow(theta_k,2)+4))/2.0;
+		beta_k1=theta_k*(1.0-theta_k)/(pow(theta_k,2)+theta_k1);
+
+		my.CopyFromMatrix(mx);						// 1) y=xk1;
+		my.MatrDec(ml);								// 2) y=xk1-xk;
+		my.MatrScale(beta_k1);						// 3) y=beta_k1*(xk1-xk);
+		my.MatrInc(mx);								// 4) y=xk1+beta_k1*(xk1-xk);
+		ms.MatrSub(mx,ml);						    // 0) s = xk1 - xk;
+
+		// Restarting logic if momentum is not appropriate
+		if (mg.MatrDot(&mg,&ms)>0)
+		{
+			my.CopyFromMatrix(mx);					// 1) y=xk1
+			theta_k1=1.0;							// 2) theta_k=1
+			if (verbose) GetLog() << "Restarting APGD at it " << iter  << "\n";
+		}
+
+		//Allow the step to grow...
+		L_k=0.9*L_k;
+		t_k=1/L_k;
+
+		ml.CopyFromMatrix(mx);						// 1) xk=xk1;
+		theta_k=theta_k1;							// 2) theta_k=theta_k1;
+
+		//****METHOD 1 for residual, same as ChLcpIterativeBB
+		// Project the gradient (for rollback strategy)
+		// g_proj = (l-project_orthogonal(l - gdiff*g, fric))/gdiff;
+		mb_tmp.CopyFromMatrix(mg_tmp2);
+		mb_tmp.MatrScale(-gdiff);
+		mb_tmp.MatrInc(ml);
+		sysd.ConstraintsProject(mb_tmp);
+		mb_tmp.MatrDec(ml);
+		mb_tmp.MatrDivScale(-gdiff);
+		double g_proj_norm = mb_tmp.NormTwo(); // NormInf() is faster..
+		//****End of METHOD 1 for residual, same as ChLcpIterativeBB
+
+		//****METHOD 2 for residual, same as ChLcpIterativeSOR
+		maxviolation = 0;
+		i_friction_comp = 0;
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		{
+			if (mconstraints[ic]->IsActive())
+			{
+				// true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
+				double candidate_violation = fabs(mconstraints[ic]->Violation(mg_tmp2.ElementN(ic)));
+
+				if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+				{
+					candidate_violation = 0;
+					i_friction_comp++;
+
+					if (i_friction_comp==1)
+						candidate_violation = fabs(ChMin(0.0,mg_tmp2.ElementN(ic)));
+
+					if (i_friction_comp==3)
+						i_friction_comp =0;
+				}
+				else
+				{
+
+				}
+				maxviolation = ChMax(maxviolation, fabs(candidate_violation));
+			}
+		}
+		g_proj_norm=maxviolation;
+		//****End of METHOD 2 for residual, same as ChLcpIterativeSOR
+
+		// Rollback solution: the last best candidate ('l' with lowest projected gradient)
+		// in fact the method is not monotone and it is quite 'noisy', if we do not
+		// do this, a prematurely truncated iteration might give a crazy result.
+		if(g_proj_norm < lastgoodres)
+		{
+			lastgoodres  = g_proj_norm;
+			ml_candidate = ml;
+		}
+
+		// METRICS - convergence, plots, etc
+
+		if (verbose)
+		{
+			// f_p = 0.5*l_candidate'*N*l_candidate - l_candidate'*b  = l_candidate'*(0.5*Nl_candidate - b);
+			sysd.ShurComplementProduct(mg_tmp, &ml_candidate, 0);		// 1)  g_tmp = N*l_candidate ...        #### MATR.MULTIPLICATION!!!###
+			mg_tmp.MatrScale(0.5);										// 2)  g_tmp = 0.5*N*l_candidate
+			mg_tmp.MatrDec(mb);											// 3)  g_tmp = 0.5*N*l_candidate-b_shur
+			mf_p = ml_candidate.MatrDot(&ml_candidate,&mg_tmp);			// 4)  mf_p  = l_candidate'*(0.5*N*l_candidate-b_shur)
+		}
+
+		double maxdeltalambda = ms.NormInf();
+		double maxd			  = lastgoodres;
+			
+		// For recording into correction/residuals/violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxd, maxdeltalambda, iter);
+
+		if (verbose) GetLog() << "  iter=" << iter << "   f=" << mf_p << "  |d|=" << maxd << "  |s|=" << maxdeltalambda  << "\n";
+
+		tot_iterations++;
+
+		// Terminate the loop if violation in constraints has been succesfully limited.
+		// ***TO DO*** a reliable termination creterion..
+		///*
+		if (maxd < this->tolerance)
+		{
+			if (verbose) GetLog() <<"APGD premature converged at i=" << iter << "\n";
+			break;
+		}
+		//*/
+
+	}
+
+	// Fallback to best found solution (might be useful because of nonmonotonicity)
+	ml.CopyFromMatrix(ml_candidate);
+
+
+	// Resulting DUAL variables:
+	// store ml temporary vector into ChLcpConstraint 'l_i' multipliers
+	sysd.FromVectorToConstraints(ml); 
+
+
+	// Resulting PRIMAL variables:
+	// compute the primal variables as   v = (M^-1)(k + D*l) 
+
+		// v = (M^-1)*k  ...    (by rewinding to the backup vector computed ad the beginning)
+	sysd.FromVectorToVariables(mq);
+
+
+		// ... + (M^-1)*D*l     (this increment and also stores 'qb' in the ChLcpVariable items)
+	for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+	{	
+		if (mconstraints[ic]->IsActive())
+			mconstraints[ic]->Increment_q( mconstraints[ic]->Get_l_i() );
+	}
+	
+
+	if (verbose) GetLog() <<"-----\n";
+	current_residual = lastgoodres;
+	return lastgoodres;
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.h b/SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.h
new file mode 100644
index 0000000..b921930
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeAPGD.h
@@ -0,0 +1,108 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVEAPGD_H
+#define CHLCPITERATIVEAPGD_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeAPGD.h
+//
+//  An iterative solver based on Nesterov's
+//  Projected Gradient Descent
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+/// An iterative solver based on Nesterov's
+/// Projected Gradient Descent.
+/// The problem is described by an LCP of type
+///
+///    | M -Cq'|*|q|- | f|= |0| ,   c>=0, l>=0, l*c=0;
+///    | Cq  0 | |l|  |-b|  |c|
+///
+/// or similar CCP problem.
+
+class ChApi ChLcpIterativeAPGD : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeAPGD(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0   ///< tolerance for termination criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,0.2)
+			{
+				
+			};
+				
+	virtual ~ChLcpIterativeAPGD() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	  
+				);
+//The extra stuff below is for debugging
+
+	ChMatrixDynamic<> mb;
+	ChMatrixDynamic<> ml;
+	double current_residual;
+
+	double GetResidual(){
+		return current_residual;
+	}
+	void Dump_Rhs(std::vector<double> &temp){
+		for (int i=0; i<mb.GetRows(); i++){
+			temp.push_back(mb(i,0));
+		}
+	}
+	void Dump_Lambda(std::vector<double> &temp){
+			for (int i=0; i<ml.GetRows(); i++){
+				temp.push_back(ml(i,0));
+			}
+		}
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeAPGD.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeBB.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativeBB.cpp
new file mode 100644
index 0000000..28aeb21
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeBB.cpp
@@ -0,0 +1,767 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativeBB.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpIterativeBB.h"
+#include "ChLcpConstraintTwoFrictionT.h"
+
+namespace chrono
+{
+
+double ChLcpIterativeBB::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+		// If stiffness blocks are used, the Schur complement cannot be esily
+		// used, so fall back to the Solve_SupportingStiffness method, that operates on KKT.
+	if (sysd.GetKstiffnessList().size() > 0)
+		return this->Solve_SupportingStiffness(sysd);
+
+
+	// Tuning of the spectral gradient search
+	double a_min = 1e-13;
+	double a_max = 1e13;
+	double sigma_min = 0.1;
+	double sigma_max = 0.9;
+	double alpha = 0.0001;
+	double gamma = 1e-4;
+	double gdiff= 0.000001;
+	bool do_preconditioning = this->diag_preconditioning;
+
+	bool do_BB1e2= true;
+	bool do_BB1	 = false;
+	bool do_BB2	 = false;
+	double neg_BB1_fallback = 0.11;
+	double neg_BB2_fallback = 0.12;
+
+	bool verbose = false;
+
+
+	int i_friction_comp = 0;
+	tot_iterations = 0;
+	// Allocate auxiliary vectors;
+	
+	int nc = sysd.CountActiveConstraints();
+	if (verbose) GetLog() <<"\n-----Barzilai-Borwein, solving nc=" << nc << "unknowns \n";
+
+	ChMatrixDynamic<> ml(nc,1);
+	ChMatrixDynamic<> ml_candidate(nc,1);
+	ChMatrixDynamic<> mg(nc,1);
+	ChMatrixDynamic<> mg_p(nc,1);
+	ChMatrixDynamic<> ml_p(nc,1);
+	ChMatrixDynamic<> mdir(nc,1);
+	ChMatrixDynamic<> mb(nc,1);
+	ChMatrixDynamic<> mb_tmp(nc,1);
+	ChMatrixDynamic<> ms(nc,1);
+	ChMatrixDynamic<> my(nc,1);
+	ChMatrixDynamic<> mD (nc,1);
+	ChMatrixDynamic<> mDg (nc,1);
+
+
+	
+	// Update auxiliary data in all constraints before starting,
+	// that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//  Can be used for the fixed point phase and/or by preconditioner.
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) 
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}	
+	}
+	// The vector with the diagonal of the N matrix
+	int d_i = 0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mD(d_i, 0) = mconstraints[ic]->Get_g_i();
+			++d_i;
+		}
+
+
+	// ***TO DO*** move the following thirty lines in a short function ChLcpSystemDescriptor::ShurBvectorCompute() ?
+
+	// Compute the b_shur vector in the Shur complement equation N*l = b_shur
+	// with 
+	//   N_shur  = D'* (M^-1) * D
+	//   b_shur  = - c + D'*(M^-1)*k = b_i + D'*(M^-1)*k
+	// but flipping the sign of lambdas,  b_shur = - b_i - D'*(M^-1)*k
+	// Do this in three steps:
+	
+	// Put (M^-1)*k    in  q  sparse vector of each variable..
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb 
+
+	// ...and now do  b_shur = - D'*q = - D'*(M^-1)*k ..
+	int s_i = 0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mb(s_i, 0) = - mconstraints[ic]->Compute_Cq_q();
+			++s_i;
+		}
+
+	// ..and finally do   b_shur = b_shur - c
+	sysd.BuildBiVector(mb_tmp);	// b_i   =   -c   = phi/h 
+	mb.MatrDec(mb_tmp);
+
+		// Optimization: backup the  q  sparse data computed above, 
+		// because   (M^-1)*k   will be needed at the end when computing primals.
+	ChMatrixDynamic<> mq; 
+	sysd.FromVariablesToVector(mq, true);	
+
+
+	// Initialize lambdas
+	if (warm_start)
+		sysd.FromConstraintsToVector(ml);
+	else
+		ml.FillElem(0);
+
+
+	// Initial projection of ml   ***TO DO***?
+	sysd.ConstraintsProject(ml);
+
+
+	// Fallback solution
+	double lastgoodres  = 10e30;
+	double lastgoodfval = 10e30;
+	ml_candidate = ml;
+
+	// g = gradient of 0.5*l'*N*l-l'*b 
+	// g = N*l-b 
+	sysd.ShurComplementProduct(mg, &ml, 0);		// 1)  g = N*l ...        #### MATR.MULTIPLICATION!!!###
+	mg.MatrDec(mb);								// 2)  g = N*l - b_shur ...
+
+	mg_p = mg;
+
+
+	//
+	// THE LOOP
+	//
+
+	double mf_p =0;
+	double mf =1e29;
+	std::vector<double> f_hist;
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// Dg = Di*g;
+		mDg = mg;
+		if (do_preconditioning)
+			mDg.MatrDivScale(mD);
+		
+		// dir  = [P(l - alpha*Dg) - l]
+		mdir.CopyFromMatrix(mDg);					// 1) dir = Dg  ...
+		mdir.MatrScale(-alpha);						// 2) dir = - alpha*Dg  ...
+		mdir.MatrInc(ml);							// 3) dir = l - alpha*Dg  ...
+		sysd.ConstraintsProject(mdir);				// 4) dir = P(l - alpha*Dg) ...
+		mdir.MatrDec(ml);							// 5) dir = P(l - alpha*Dg) - l
+
+		// dTg = dir'*g;
+		double dTg = mdir.MatrDot(&mdir,&mg);
+
+		// BB dir backward!? fallback to nonpreconditioned dir
+		if (dTg > 1e-8)
+		{	
+			// dir  = [P(l - alpha*g) - l]
+			mdir.CopyFromMatrix(mg);					// 1) dir = g  ...
+			mdir.MatrScale(-alpha);						// 2) dir = - alpha*g  ...
+			mdir.MatrInc(ml);							// 3) dir = l - alpha*g  ...
+			sysd.ConstraintsProject(mdir);				// 4) dir = P(l - alpha*g) ...
+			mdir.MatrDec(ml);							// 5) dir = P(l - alpha*g) - l
+			// dTg = d'*g;
+			dTg = mdir.MatrDot(&mdir,&mg);
+		}
+
+		double lambda = 1;
+
+		
+		
+		int  n_backtracks = 0;
+		bool armijo_repeat = true;
+
+		while (armijo_repeat)
+		{
+			// l_p = l + lambda*dir;
+			ml_p.CopyFromMatrix(mdir);
+			ml_p.MatrScale(lambda);
+			ml_p.MatrInc(ml);
+
+			// Nl_p = N*l_p;                        #### MATR.MULTIPLICATION!!!###
+			sysd.ShurComplementProduct(mb_tmp, &ml_p, 0);// 1)  mb_tmp = N*l_p  = Nl_p 
+
+			// g_p = N*l_p - b  = Nl_p - b		
+			mg_p.MatrSub(mb_tmp, mb);					 // 2)  g_p = N*l_p - b
+
+			// f_p = 0.5*l_p'*N*l_p - l_p'*b  = l_p'*(0.5*Nl_p - b);
+			mb_tmp.MatrScale(0.5);
+			mb_tmp.MatrDec(mb);
+			mf_p = ml_p.MatrDot(&ml_p,&mb_tmp);
+			
+			f_hist.push_back(mf_p);
+
+
+			double max_compare = 10e29;
+			for (int h = 1; h <= ChMin(iter,this->n_armijo); h++)
+			{
+				double compare = f_hist[iter-h] + gamma*lambda*dTg;
+				if (compare > max_compare)
+					max_compare = compare;
+			}
+
+			if (mf_p > max_compare)
+			{
+				armijo_repeat = true;
+				if (iter>0)
+					mf = f_hist[iter-1];
+				double lambdanew = - lambda * lambda * dTg / (2*(mf_p - mf -lambda*dTg));
+				lambda = ChMax(sigma_min*lambda, ChMin(sigma_max*lambda,lambdanew));
+				if (verbose)  GetLog() << " Repeat Armijo, new lambda=" << lambda << "\n";
+			}
+			else
+			{
+				armijo_repeat = false;
+			}
+        
+			n_backtracks = n_backtracks +1;
+			if (n_backtracks > this->max_armijo_backtrace)
+				armijo_repeat = false;
+		}
+
+		// s = l_p - l;
+		ms.MatrSub(ml_p, ml);
+		
+		// y = g_p - g;
+		my.MatrSub(mg_p, mg);
+
+		// l = l_p;
+		ml.CopyFromMatrix(ml_p);
+
+		// g = g_p;
+		mg.CopyFromMatrix(mg_p);
+
+		if (((do_BB1e2) && (iter%2 ==0)) || do_BB1)
+		{
+			mb_tmp = ms;
+			if (do_preconditioning)
+				mb_tmp.MatrScale(mD);
+			double sDs = ms.MatrDot(&ms,&mb_tmp);
+			double sy  = ms.MatrDot(&ms, &my);
+			if (sy <= 0)
+			{
+				alpha = neg_BB1_fallback;
+			}
+			else
+			{
+				double alph = sDs / sy;  // (s,Ds)/(s,y)   BB1
+				alpha = ChMin (a_max, ChMax(a_min, alph));
+			}
+		}
+
+		/*
+		// this is a modified rayleight quotient - looks like it works anyway...
+		if (((do_BB1e2) && (iter%2 ==0)) || do_BB1)
+		{
+			double ss = ms.MatrDot(&ms,&ms);
+			mb_tmp = my;
+			if (do_preconditioning)
+				mb_tmp.MatrDivScale(mD);
+			double sDy = ms.MatrDot(&ms, &mb_tmp);
+			if (sDy <= 0)
+			{
+				alpha = neg_BB1_fallback;
+			}
+			else
+			{
+				double alph = ss / sDy;  // (s,s)/(s,Di*y)   BB1 (modified version)
+				alpha = ChMin (a_max, ChMax(a_min, alph));
+			}
+		}
+		*/
+
+		if (((do_BB1e2) && (iter%2 !=0)) || do_BB2)
+		{
+			double sy = ms.MatrDot(&ms,&my);
+			mb_tmp = my;
+			if (do_preconditioning)
+				mb_tmp.MatrDivScale(mD);
+			double yDy = my.MatrDot(&my, &mb_tmp);
+			if (sy <= 0)
+			{
+				alpha = neg_BB2_fallback;
+			}
+			else
+			{
+				double alph = sy / yDy;  // (s,y)/(y,Di*y)   BB2
+				alpha = ChMin (a_max, ChMax(a_min, alph));
+			}
+		}
+
+        // Project the gradient (for rollback strategy)
+		// g_proj = (l-project_orthogonal(l - gdiff*g, fric))/gdiff;
+		mb_tmp = mg;
+		mb_tmp.MatrScale(-gdiff);
+		mb_tmp.MatrInc(ml);
+		sysd.ConstraintsProject(mb_tmp);
+		mb_tmp.MatrDec(ml);
+		mb_tmp.MatrDivScale(-gdiff);
+
+		double g_proj_norm = mb_tmp.NormTwo(); // NormInf() is faster..
+
+		// Rollback solution: the last best candidate ('l' with lowest projected gradient)
+		// in fact the method is not monotone and it is quite 'noisy', if we do not
+		// do this, a prematurely truncated iteration might give a crazy result.
+        if(g_proj_norm < lastgoodres)
+		{
+            lastgoodres  = g_proj_norm;
+            ml_candidate = ml;
+		}  
+
+
+		// METRICS - convergence, plots, etc
+
+		double maxdeltalambda = ms.NormInf();
+		double maxd			  = lastgoodres;  
+			
+		// For recording into correction/residuals/violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxd, maxdeltalambda, iter);
+
+		if (verbose) GetLog() << "  iter=" << iter << "   f=" << mf_p << "  |d|=" << maxd << "  |s|=" << maxdeltalambda  << "\n";
+
+		tot_iterations++;
+
+		// Terminate the loop if violation in constraints has been succesfully limited.
+		// ***TO DO*** a reliable termination creterion.. 
+		/*
+		if (maxd < this->tolerance)  
+		{
+			GetLog() <<"BB premature proj.gradient break at i=" << iter << "\n";
+			break;
+		}
+		*/
+		
+	}
+
+	// Fallback to best found solution (might be useful because of nonmonotonicity)
+	ml.CopyFromMatrix(ml_candidate);  
+
+
+	// Resulting DUAL variables:
+	// store ml temporary vector into ChLcpConstraint 'l_i' multipliers
+	sysd.FromVectorToConstraints(ml); 
+
+
+	// Resulting PRIMAL variables:
+	// compute the primal variables as   v = (M^-1)(k + D*l) 
+
+		// v = (M^-1)*k  ...    (by rewinding to the backup vector computed ad the beginning)
+	sysd.FromVectorToVariables(mq);
+
+
+		// ... + (M^-1)*D*l     (this increment and also stores 'qb' in the ChLcpVariable items)
+	for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+	{	
+		if (mconstraints[ic]->IsActive())
+			mconstraints[ic]->Increment_q( mconstraints[ic]->Get_l_i() );
+	}
+	
+
+	if (verbose) GetLog() <<"-----\n";
+
+	return lastgoodres;
+
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+double ChLcpIterativeBB::Solve_SupportingStiffness(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	 
+				)
+{
+
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+	std::vector<ChLcpKstiffness*>& mstiffness	= sysd.GetKstiffnessList();
+
+
+	// Tuning of the spectral gradient search
+	double a_min = 1e-13;
+	double a_max = 1e13;
+	double sigma_min = 0.1;
+	double sigma_max = 0.9;
+	double alpha = 0.0001;
+	double gamma = 1e-4;
+	double gdiff= 0.000001;
+	bool do_preconditioning = this->diag_preconditioning;
+
+	bool do_BB1e2= true;
+	bool do_BB1	 = false;
+	bool do_BB2	 = false;
+	double neg_BB1_fallback = 0.11;
+	double neg_BB2_fallback = 0.12;
+
+
+	int i_friction_comp = 0;
+	tot_iterations = 0;
+
+	// Allocate auxiliary vectors;
+	
+	int nv = sysd.CountActiveVariables();
+	int nc = sysd.CountActiveConstraints();
+	int nx = nv+nc;  // total scalar unknowns, in x vector for full KKT system Z*x-d=0
+
+	if (verbose) GetLog() <<"\n-----Barzilai-Borwein -supporting stiffness-, n.unknowns nx=" << nx << " \n";
+
+	ChMatrixDynamic<> mx(nx,1);
+	ChMatrixDynamic<> mx_candidate(nx,1);
+	ChMatrixDynamic<> mg(nx,1);
+	ChMatrixDynamic<> mg_p(nx,1);
+	ChMatrixDynamic<> mx_p(nx,1);
+	ChMatrixDynamic<> mdir(nx,1);
+	ChMatrixDynamic<> md(nx,1);
+	ChMatrixDynamic<> md_tmp(nx,1);
+	ChMatrixDynamic<> ms(nx,1);
+	ChMatrixDynamic<> my(nx,1);
+	ChMatrixDynamic<> mD (nx,1);
+	ChMatrixDynamic<> mDg (nx,1);
+
+	//
+	// --- Compute a diagonal (scaling) preconditioner for the KKT system:
+    //
+
+	// Initialize the mD vector with the diagonal of the Z matrix
+	sysd.BuildDiagonalVector(mD);
+
+	// Its inverse can be used as a scaling for the q unknowns, but not 
+	// for the l unknowns, since their diagonal is most often 0. So
+	// we will use the g_i=[Cq_i]*[invM_i]*[Cq_i]' terms (note, K stiffness
+	// if any, takes no effect).
+	// Firs, update auxiliary data in all constraints before starting,
+	// that will compute g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//  This is necessary because we want the scaling to be isotropic for each friction cone
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) 
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}	
+	}
+	// Store the g_i terms in the mD vector, whose inverse will be used for scaling.
+	int s_u = nv;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mD(s_u) = mconstraints[ic]->Get_g_i();
+			++s_u;
+		}
+
+
+	//
+	// --- Vector initialization and book-keeping 
+    //
+
+	// Initialize the x vector of unknowns x ={q; -l} (if warm starting needed, initialize 
+	// x with current values of q and l in variables and constraints)
+	if (warm_start)
+		sysd.FromUnknownsToVector(mx);
+	else
+		mx.FillElem(0);
+
+	// Initialize the d vector filling it with {f, -b}
+	sysd.BuildDiVector(md);
+
+
+
+	//
+	// --- THE SPG ALGORITHM
+	//
+
+	// Initial projection of mx   
+	sysd.UnknownsProject(mx);
+
+
+	// Fallback solution
+	double lastgoodres  = 10e30;
+	double lastgoodfval = 10e30;
+	mx_candidate = mx;
+
+	// g = Z*x-d 
+	sysd.SystemProduct(mg, &mx);				// 1)  g = Z*x ...        #### MATR.MULTIPLICATION!!!###
+	mg.MatrDec(md);								// 2)  g = Z*x - d ...
+
+	mg_p = mg;
+
+
+	//
+	// THE LOOP
+	//
+
+	double mf_p =0;
+	double mf =1e29;
+	std::vector<double> f_hist;
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// Dg = Di*g;
+		mDg = mg;
+		if (do_preconditioning)
+			mDg.MatrDivScale(mD);
+		
+		// dir  = [P(l - alpha*Dg) - l]
+		mdir.CopyFromMatrix(mDg);					// 1) dir = Dg  ...
+		mdir.MatrScale(-alpha);						// 2) dir = - alpha*Dg  ...
+		mdir.MatrInc(mx);							// 3) dir = x - alpha*Dg  ...
+		sysd.UnknownsProject(mdir);					// 4) dir = P(x - alpha*Dg) ...
+		mdir.MatrDec(mx);							// 5) dir = P(x - alpha*Dg) - x
+
+		// dTg = dir'*g;
+		double dTg = mdir.MatrDot(&mdir,&mg);
+
+		// BB dir backward!? fallback to nonpreconditioned dir
+		if (dTg > 1e-8)
+		{	
+			// dir  = [P(l - alpha*g) - l]
+			mdir.CopyFromMatrix(mg);					// 1) dir = g  ...
+			mdir.MatrScale(-alpha);						// 2) dir = - alpha*g  ...
+			mdir.MatrInc(mx);							// 3) dir = x - alpha*g  ...
+			sysd.UnknownsProject(mdir);					// 4) dir = P(x - alpha*g) ...
+			mdir.MatrDec(mx);							// 5) dir = P(x - alpha*g) - x
+			// dTg = d'*g;
+			dTg = mdir.MatrDot(&mdir,&mg);
+		}
+
+		double lambda = 1;
+
+		
+		
+		int  n_backtracks = 0;
+		bool armijo_repeat = true;
+
+		while (armijo_repeat)
+		{
+			// x_p = x + lambda*dir;
+			mx_p.CopyFromMatrix(mdir);
+			mx_p.MatrScale(lambda);
+			mx_p.MatrInc(mx);
+
+			// Zx_p = Z*x_p;                        #### MATR.MULTIPLICATION!!!###
+			sysd.SystemProduct(md_tmp, &mx_p );			 // 1)  md_tmp = Z*x_p  = Zx_p 
+
+			// g_p = Z*x_p - d  = Zx_p - d		
+			mg_p.MatrSub(md_tmp, md);					 // 2)  g_p = Z*x_p - d
+
+			// f_p = 0.5*x_p'*Z*x_p - x_p'*d  = x_p'*(0.5*Zx_p - d);
+			md_tmp.MatrScale(0.5);
+			md_tmp.MatrDec(md);
+			mf_p = mx_p.MatrDot(&mx_p,&md_tmp);
+			
+			f_hist.push_back(mf_p);
+
+
+			double max_compare = 10e29;
+			for (int h = 1; h <= ChMin(iter,this->n_armijo); h++)
+			{
+				double compare = f_hist[iter-h] + gamma*lambda*dTg;
+				if (compare > max_compare)
+					max_compare = compare;
+			}
+
+			if (mf_p > max_compare)
+			{
+				armijo_repeat = true;
+				if (iter>0)
+					mf = f_hist[iter-1];
+				double lambdanew = - lambda * lambda * dTg / (2*(mf_p - mf -lambda*dTg));
+				lambda = ChMax(sigma_min*lambda, ChMin(sigma_max*lambda,lambdanew));
+				if (verbose)  GetLog() << " Repeat Armijo, new lambda=" << lambda << "\n";
+			}
+			else
+			{
+				armijo_repeat = false;
+			}
+        
+			n_backtracks = n_backtracks +1;
+			if (n_backtracks > this->max_armijo_backtrace)
+				armijo_repeat = false;
+		}
+
+		// s = x_p - x;
+		ms.MatrSub(mx_p, mx);
+		
+		// y = g_p - g;
+		my.MatrSub(mg_p, mg);
+
+		// x = x_p;
+		mx.CopyFromMatrix(mx_p);
+
+		// g = g_p;
+		mg.CopyFromMatrix(mg_p);
+
+		if (((do_BB1e2) && (iter%2 ==0)) || do_BB1)
+		{
+			md_tmp = ms;
+			if (do_preconditioning)
+				md_tmp.MatrScale(mD);
+			double sDs = ms.MatrDot(&ms,&md_tmp);
+			double sy  = ms.MatrDot(&ms, &my);
+			if (sy <= 0)
+			{
+				alpha = neg_BB1_fallback;
+			}
+			else
+			{
+				double alph = sDs / sy;  // (s,Ds)/(s,y)   BB1
+				alpha = ChMin (a_max, ChMax(a_min, alph));
+			}
+		}
+
+	
+		if (((do_BB1e2) && (iter%2 !=0)) || do_BB2)
+		{
+			double sy = ms.MatrDot(&ms,&my);
+			md_tmp = my;
+			if (do_preconditioning)
+				md_tmp.MatrDivScale(mD);
+			double yDy = my.MatrDot(&my, &md_tmp);
+			if (sy <= 0)
+			{
+				alpha = neg_BB2_fallback;
+			}
+			else
+			{
+				double alph = sy / yDy;  // (s,y)/(y,Di*y)   BB2
+				alpha = ChMin (a_max, ChMax(a_min, alph));
+			}
+		}
+
+        // Project the gradient (for rollback strategy)
+		// g_proj = (x-project_orthogonal(x - gdiff*g, fric))/gdiff;
+		md_tmp = mg;
+		md_tmp.MatrScale(-gdiff);
+		md_tmp.MatrInc(mx);
+		sysd.UnknownsProject(md_tmp);
+		md_tmp.MatrDec(mx);
+		md_tmp.MatrDivScale(-gdiff);
+
+		double g_proj_norm = md_tmp.NormTwo(); // NormInf() is faster..
+
+		// Rollback solution: the last best candidate ('x' with lowest projected gradient)
+		// in fact the method is not monotone and it is quite 'noisy', if we do not
+		// do this, a prematurely truncated iteration might give a crazy result.
+        if(g_proj_norm < lastgoodres)
+		{
+            lastgoodres  = g_proj_norm;
+            mx_candidate = mx;
+		}  
+
+
+		// METRICS - convergence, plots, etc
+
+		double maxdeltalambda = ms.NormInf();
+		double maxd			  = lastgoodres;  
+			
+		// For recording into correction/residuals/violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxd, maxdeltalambda, iter);
+
+		if (verbose) GetLog() << "  iter=" << iter << "   f=" << mf_p << "  |d|=" << maxd << "  |s|=" << maxdeltalambda  << "\n";
+
+		tot_iterations++;
+
+		// Terminate the loop if tolerance reached
+		// ***TO DO*** a reliable termination creterion.. 
+		/*
+		if (maxd < this->tolerance)  
+		{
+			GetLog() <<"BB premature proj.gradient break at i=" << iter << "\n";
+			break;
+		}
+		*/
+		
+	}
+
+
+	// After having solved for unknowns x={q;-l}, now copy those values from x vector to
+	// the q values in ChLcpVariable items and to l values in ChLcpConstraint items
+	sysd.FromVectorToUnknowns(mx_candidate); // was FromVectorToUnknowns(mx), but mx is not monotone, mx_candidate is. 
+
+	
+	if (verbose) GetLog() <<"-----\n";
+
+	return lastgoodres;
+
+}
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeBB.h b/SRC/ChronoEngine/lcp/ChLcpIterativeBB.h
new file mode 100644
index 0000000..d527bbc
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeBB.h
@@ -0,0 +1,128 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVEBB_H
+#define CHLCPITERATIVEBB_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeBB.h
+//
+//  An iterative solver based on modified 
+//  Krylov iteration of spectral projected gradients
+//  with Borzilai-Borwein 
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+/// An iterative solver based on modified 
+/// Krylov iteration of spectral projected gradients
+/// with Borzilai-Borwein.
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals)
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0)
+/// * case CCP: Y_i are friction cones)
+
+class ChApi ChLcpIterativeBB : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+	int		n_armijo;
+	int		max_armijo_backtrace;
+	bool	diag_preconditioning;
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeBB(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0   ///< tolerance for termination criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,0.2)
+			{
+				n_armijo = 10;
+				max_armijo_backtrace = 3;
+				diag_preconditioning = true;
+			};
+				
+	virtual ~ChLcpIterativeBB() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	 
+				);
+
+
+				/// Same as Solve(), but this also supports the presence of
+				/// ChLcpKstiffness blocks. If Solve() is called and stiffness is present,
+				/// Solve() automatically falls back to this function.
+				/// It does not solve the Schur complement N*l-r=0 as Solve does, here the 
+				/// entire system KKT matrix with duals l and primals q is used.
+				/// ***NOT WORKING***
+	virtual double Solve_SupportingStiffness(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				);
+
+
+				/// Number of max tolerated steps in non-monotone Armijo
+				/// line search; usually good values are in 1..10 range.
+	void   SetNarmijo (int mf) {this->n_armijo = mf;}
+	double GetNarmijo () {return this->n_armijo;}
+				
+	void SetMaxArmijoBacktrace (int mm) {this->max_armijo_backtrace = mm;}
+	int  GetMaxArmijoBacktrace () {return this->max_armijo_backtrace;}
+
+				/// Enable diagonal preconditioning. It a simple but fast
+				/// preconditioning technique that is expecially useful to 
+				/// fix slow convergence in case variables have very different orders
+				/// of magnitude.
+	void SetDiagonalPreconditioning(bool mp) {this->diag_preconditioning = mp;}
+	bool GetDiagonalPreconditioning() {return this->diag_preconditioning;}
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeBB.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.cpp
new file mode 100644
index 0000000..c4f8c7a
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.cpp
@@ -0,0 +1,227 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativeJacobi.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+   
+#include "ChLcpIterativeJacobi.h" 
+
+
+namespace chrono
+{
+
+double ChLcpIterativeJacobi::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables						
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	tot_iterations = 0;
+	double maxviolation = 0.;
+	double maxdeltalambda = 0;
+	int i_friction_comp = 0;
+	double old_lambda_friction[3];
+
+	// 1)  Update auxiliary data in all constraints before starting,
+	//     that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) 
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}	
+	}
+
+	// 2)  Compute, for all items with variables, the initial guess for
+	//     still unconstrained system:
+
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb 
+
+
+	// 3)  For all items with variables, add the effect of initial (guessed)
+	//     lagrangian reactions of contraints, if a warm start is desired.
+	//     Otherwise, if no warm start, simply resets initial lagrangians to zero.
+	if (warm_start)
+	{
+	}
+	else
+	{
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+			mconstraints[ic]->Set_l_i(0.);
+	}
+
+	// 4)  Perform the iteration loops
+	//
+
+	std::vector<double> delta_gammas;
+	delta_gammas.resize(mconstraints.size());
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// The iteration on all constraints
+		//
+
+		maxviolation = 0;
+		maxdeltalambda =0;
+
+		for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+		{
+			// skip computations if constraint not active.
+			if (mconstraints[ic]->IsActive())
+			{
+				// compute residual  c_i = [Cq_i]*q + b_i + cfm_i*l_i
+				double mresidual = mconstraints[ic]->Compute_Cq_q() + mconstraints[ic]->Get_b_i()
+								 + mconstraints[ic]->Get_cfm_i() * mconstraints[ic]->Get_l_i();
+
+				// true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
+				double candidate_violation = fabs(mconstraints[ic]->Violation(mresidual));
+
+				// compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i + cfm_i*l_i )
+				double deltal = ( omega / mconstraints[ic]->Get_g_i() ) *
+								( -mresidual );
+
+				if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+				{
+					candidate_violation = 0;
+
+					// update:   lambda += delta_lambda;
+					old_lambda_friction[i_friction_comp] = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda_friction[i_friction_comp]  + deltal);
+					i_friction_comp++;
+					
+					if (i_friction_comp==1)
+						candidate_violation = fabs(ChMin(0.0,mresidual));
+
+					if (i_friction_comp==3)
+					{ 
+						mconstraints[ic-2]->Project(); // the N normal component will take care of N,U,V
+						double new_lambda_0 = mconstraints[ic-2]->Get_l_i() ;
+						double new_lambda_1 = mconstraints[ic-1]->Get_l_i() ;
+						double new_lambda_2 = mconstraints[ic-0]->Get_l_i() ;
+						// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+						if (this->shlambda!=1.0)
+						{
+							new_lambda_0 = shlambda*new_lambda_0 + (1.0-shlambda)*old_lambda_friction[0];
+							new_lambda_1 = shlambda*new_lambda_1 + (1.0-shlambda)*old_lambda_friction[1];
+							new_lambda_2 = shlambda*new_lambda_2 + (1.0-shlambda)*old_lambda_friction[2];
+							mconstraints[ic-2]->Set_l_i(new_lambda_0);
+							mconstraints[ic-1]->Set_l_i(new_lambda_1);
+							mconstraints[ic-0]->Set_l_i(new_lambda_2);
+						}
+						delta_gammas[ic-2] = new_lambda_0 - old_lambda_friction[0];
+						delta_gammas[ic-1] = new_lambda_1 - old_lambda_friction[1];
+						delta_gammas[ic-0] = new_lambda_2 - old_lambda_friction[2];
+						// Now do NOT update the primal variables , posticipate mconstraints[xx]->Increment_q(true_delta_xx);
+						
+						if (this->record_violation_history)
+						{
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(delta_gammas[ic-2]));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(delta_gammas[ic-1]));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(delta_gammas[ic-0]));
+						}
+						i_friction_comp =0;
+					}
+				} 
+				else
+				{
+					// update:   lambda += delta_lambda;
+					double old_lambda = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda + deltal);
+
+					// If new lagrangian multiplier does not satisfy inequalities, project
+					// it into an admissible orthant (or, in general, onto an admissible set)
+					mconstraints[ic]->Project();
+
+					// After projection, the lambda may have changed a bit..
+					double new_lambda = mconstraints[ic]->Get_l_i() ;
+
+					// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+					if (this->shlambda!=1.0)
+					{
+						new_lambda = shlambda*new_lambda + (1.0-shlambda)*old_lambda;
+						mconstraints[ic]->Set_l_i(new_lambda);
+					}
+
+					// Now do NOT update the primal variables , posticipate mconstraints[ic]->Increment_q(true_delta_xx);
+					delta_gammas[ic] = new_lambda - old_lambda;
+
+					if (this->record_violation_history)
+						maxdeltalambda = ChMax(maxdeltalambda, fabs(delta_gammas[ic])); 
+				}
+
+				maxviolation = ChMax(maxviolation, fabs(candidate_violation));
+
+			}
+		}
+
+		// Now, after all deltas are updated, sweep through all constraints and increment  q += [invM][Cq]'* delta_l 
+		for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+		{	
+			if (mconstraints[ic]->IsActive())
+				mconstraints[ic]->Increment_q(delta_gammas[ic]);
+		}
+ 
+
+		// For recording into violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxviolation, maxdeltalambda, iter);
+
+		tot_iterations++;
+		// Terminate the loop if violation in constraints has been succesfully limited.
+		if (maxviolation < tolerance)
+			break;
+
+	}
+
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.h b/SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.h
new file mode 100644
index 0000000..8e72de7
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeJacobi.h
@@ -0,0 +1,101 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVEJACOBI_H
+#define CHLCPITERATIVEJACOBI_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeJacobi.h
+//
+//  An iterative LCP solver based on projective
+//  fixed point method, similar to projected Jacobi.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+
+/// An iterative solver for VI (VI/CCP/LCP/linear problems,..) based 
+/// on projective fixed point method, similar to a projected 
+/// Jacobi method.
+/// Note: this method is here mostly for comparison
+/// and tests: we suggest you to use the more efficient
+/// ChLcpIterativeSOR - similar, but faster & converges better.
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, c \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpIterativeJacobi : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeJacobi(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0,  ///< tolerance for termination criterion
+				double momega=0.2       ///< overrelaxation criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance, momega)
+			{};
+				
+	virtual ~ChLcpIterativeJacobi() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// You must provide a ChLcpSystemDescriptor.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables		 
+				);
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeJacobi.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.cpp
new file mode 100644
index 0000000..c8777d0
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.cpp
@@ -0,0 +1,382 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativeMINRES.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpIterativeMINRES.h"
+#include "ChLcpConstraintTwoFrictionT.h"
+
+namespace chrono
+{
+
+double ChLcpIterativeMINRES::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	tot_iterations=0;
+	double maxviolation = 0.;
+	int i_friction_comp = 0;
+	//int iter_tot = 0;	// replaced with tot_iterations - Hammad
+
+
+	// Update auxiliary data in all constraints before starting,
+	// that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//  Can be used for the fixed point phase and/or by preconditioner.
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) 
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}	
+	}
+
+
+	// Allocate auxiliary vectors;
+	
+	int nc = sysd.CountActiveConstraints();
+
+	if (verbose) GetLog() <<"nc = " << nc << "\n";
+	ChMatrixDynamic<> ml(nc,1);
+	ChMatrixDynamic<> mb(nc,1);
+	ChMatrixDynamic<> mr(nc,1);
+	ChMatrixDynamic<> mp(nc,1);
+	ChMatrixDynamic<> mb_i(nc,1);
+	ChMatrixDynamic<> Nr(nc,1);
+	ChMatrixDynamic<> Np(nc,1);
+	std::vector<bool> en_l(nc);
+
+	// Compute the b_shur vector in the Shur complement equation N*l = b_shur
+	// with 
+	//   N_shur  = D'* (M^-1) * D
+	//   b_shur  = - c + D'*(M^-1)*k = b_i + D'*(M^-1)*k
+	// but flipping the sign of lambdas,  b_shur = - b_i - D'*(M^-1)*k
+	// Do this in three steps:
+	
+	// Put (M^-1)*k    in  q  sparse vector of each variable..
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb 
+
+	// ...and now do  b_shur = - D' * q  ..
+	int s_i = 0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mb(s_i, 0) = - mconstraints[ic]->Compute_Cq_q();
+			++s_i;
+		}
+
+	// ..and finally do   b_shur = b_shur - c
+	sysd.BuildBiVector(mb_i);	// b_i   =   -c   = phi/h 
+	mb.MatrDec(mb_i);
+
+
+
+	// Optimization: backup the  q  sparse data computed above, 
+	// because   (M^-1)*k   will be needed at the end when computing primals.
+	ChMatrixDynamic<> mq; 
+	sysd.FromVariablesToVector(mq, true);	
+
+
+
+	// Initialize lambdas
+	if (warm_start)
+		sysd.FromConstraintsToVector(ml);
+	else
+		ml.FillElem(0);
+
+	// Initially all constraints are enabled
+	for (int ie= 0; ie < nc; ie++)
+		en_l[ie] = true;
+
+	//
+	// THE LOOP
+	//
+
+	while (true)
+	{
+		if (verbose) GetLog() <<"\n";	
+
+		//
+		// A)  The MINRES loop. Operates only on set defined by en_l
+		//
+		
+		// Compute initial residual, with minus sign
+		sysd.ShurComplementProduct(mr, &ml, &en_l);	// 1)  r = N*l ...
+		mr.MatrDec(mb);								// 2)  r = N*l - b_shur ...
+		mr.MatrNeg();								// 3)  r = - N*l + b_shur
+
+		for (int row = 0; row < nc; row++)
+			if (en_l[row] == false)
+				mr(row) = 0;
+
+		mp = mr;
+
+		sysd.ShurComplementProduct(Nr, &mr,& en_l); // Nr  =  N * r
+		Np=Nr;									    // Np  =  N * p 
+
+		while (true)
+		{
+			if (verbose) GetLog() << "K";
+			//sysd.ShurComplementProduct(Nr, &mr,&en_l); // Nr  =  N * r  (no, recompute only when mr changes, see later)
+			double rNr = mr.MatrDot(&mr,&Nr);		// rNr = r' * N * r
+
+			//sysd.ShurComplementProduct(Np, &mp,&en_l); // Np  =  N * p  (no, see optimization at the end)
+			double den = pow(Np.NormTwo(),2);		// den =  ((N*p)'(N*p))
+
+	 		if (den==0) break; 
+
+			double alpha = rNr / den;				// alpha = r'*N*r / ((N*p)'(N*p))
+
+			//ml.MatrInc((mp*alpha));				// l = l + alpha * p;  done below, with projection too
+			
+			 // btw. must split projection in two loops to avoid troubles with frictional contacts (three updates, but project only at the end)
+			double norm_corr = 0;
+			double norm_jump = 0;
+			double norm_viol = 0;
+			double norm_dlam = 0;
+			int s_cc= 0;
+			for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+				if (mconstraints[ic]->IsActive())
+				{
+					if (en_l[s_cc] == true)
+					{
+						double old_l = ml(s_cc);
+						double new_l = old_l + alpha * mp(s_cc);
+						
+						mconstraints[ic]->Set_l_i(new_l); 
+					}
+					++s_cc;
+				}
+			s_cc= 0;
+			for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+				if (mconstraints[ic]->IsActive())
+				{
+					if (en_l[s_cc] == true)
+					{
+						double old_l = ml(s_cc);
+						double new_l = old_l + alpha * mp(s_cc);
+						
+						mconstraints[ic]->Project();
+						double new_lp = mconstraints[ic]->Get_l_i();
+					
+						double violation = mconstraints[ic]->Violation(mr(s_cc)); //?
+						if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+							violation = fabs(ChMin(0.0,violation));
+
+						// ??? trouble with Tang. constraints, for the moment just disable norms 
+						if (!dynamic_cast<ChLcpConstraintTwoFrictionT*>(mconstraints[ic]))
+						{
+							norm_corr += pow (new_lp - new_l, 2);
+							norm_jump += pow (new_l  - old_l, 2);
+							norm_dlam += pow (new_lp - old_l, 2);
+							norm_viol += pow (violation, 2);
+						}
+					}
+					++s_cc;
+				}
+			norm_corr = sqrt(norm_corr);
+			norm_jump = sqrt(norm_jump);
+			norm_dlam = sqrt(norm_dlam);
+			norm_viol = sqrt(norm_viol);
+			
+			if (norm_corr > this->feas_tolerance * norm_jump)
+			{
+				if (verbose) GetLog() << " " << (norm_corr/norm_jump);
+				break;
+			}
+
+			s_cc = 0;
+			for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+				if (mconstraints[ic]->IsActive())
+				{
+					if (en_l[s_cc] == true)
+					{
+						ml(s_cc) = mconstraints[ic]->Get_l_i();
+						
+					}
+					++s_cc;
+				}
+
+
+			
+			mr.MatrDec((Np*alpha));					// r = r - alpha * N*p;
+
+			sysd.ShurComplementProduct(Nr, &mr,&en_l); // Nr  =  N * r
+			double rNr_ = mr.MatrDot(&mr,&Nr);		// rNr = r' * N * r
+
+			double beta = rNr_ / rNr;				// beta = r'*(N*r)/ rjNrj;
+			
+			mp.MatrScale(beta);
+			mp.MatrInc(mr);							// p = r + beta*p;
+
+			Np.MatrScale(beta);						// Avoid matr x vector operation by doing:
+			Np.MatrInc(Nr);							// N*p' = Nr + beta * N*p
+
+			// For recording into violation history 
+			if (this->record_violation_history)
+				AtIterationEnd(0.0, norm_dlam, tot_iterations); //(norm_viol, norm_dlam, tot_iterations); ***DEBUG*** use 0.0 to show phase
+
+			++tot_iterations;
+			if (tot_iterations > this->max_iterations)
+				break;
+		}
+
+		if (tot_iterations > this->max_iterations)
+			break;
+
+		if (verbose)  GetLog() <<"\n";
+
+
+		//
+		// B)  The FIXED POINT, it also will find active sets. Operates on entire set
+		//
+
+		for (int iter_fixedp = 0; iter_fixedp < this->max_fixedpoint_steps; iter_fixedp++)
+		{
+			if (verbose) GetLog() << "p";
+
+			// Compute residual  as  r = N*l - b_shur
+			sysd.ShurComplementProduct(mr, &ml, 0);		// 1)  r = N*l ...
+			mr.MatrDec(mb);								// 2)  r = N*l - b_shur
+
+														//	l = l - omega * (diag(N)^-1)* (res);
+			double norm_dlam=0;
+			double norm_viol=0;
+			// must split projection in two loops to avoid troubles with frictional contacts (three updates, but project only at the end)
+			int s_cc= 0;
+			for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+				if (mconstraints[ic]->IsActive())
+				{
+					double dlam = -mr(s_cc) * (this->omega/mconstraints[ic]->Get_g_i());
+					ml(s_cc) +=  dlam;
+					mconstraints[ic]->Set_l_i(ml(s_cc));
+					norm_dlam += pow(dlam,2);
+					++s_cc;
+				}	
+			s_cc= 0;
+			for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+				if (mconstraints[ic]->IsActive())
+				{			
+					mconstraints[ic]->Project();
+					ml(s_cc) = mconstraints[ic]->Get_l_i(); 
+
+					double violation = mconstraints[ic]->Violation(mr(s_cc));
+					if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+							violation = fabs(ChMin(0.0,violation));
+
+					norm_viol += pow (violation, 2);
+
+					++s_cc;
+				}
+			norm_dlam= sqrt(norm_dlam);
+			norm_viol= sqrt(norm_viol);
+
+			// For recording into violation history 
+			if (this->record_violation_history)
+				AtIterationEnd(1.0, norm_dlam, tot_iterations); //(norm_viol, norm_dlam, tot_iterations); ***DEBUG*** use 1.0 to show phase
+
+			++tot_iterations;
+			if (tot_iterations > this->max_iterations)
+				break;
+		}
+
+		if (tot_iterations > this->max_iterations)
+			break;
+
+		if (verbose) GetLog() <<"\n";
+		//
+		// C)  The ACTIVE SET detection
+		//
+
+		for (int row = 0; row < nc; row++)
+		{
+			if (ml(row) == 0)
+			{
+				if (verbose) GetLog() <<"0";
+				en_l[row] = false;
+			}
+			else
+			{
+				if (verbose) GetLog() <<"1";
+				en_l[row] = true;
+			}
+		}
+
+	}
+
+
+	if (verbose) GetLog() <<"-----\n";
+
+	// Resulting DUAL variables:
+	// store ml temporary vector into ChLcpConstraint 'l_i' multipliers
+	sysd.FromVectorToConstraints(ml); 
+
+
+	// Resulting PRIMAL variables:
+	// compute the primal variables as   v = (M^-1)(k + D*l) 
+
+		// v = (M^-1)*k  ...    (by rewinding to the backup vector computed ad the beginning)
+	sysd.FromVectorToVariables(mq);
+
+
+		// ... + (M^-1)*D*l     (this increment and also stores 'qb' in the ChLcpVariable items)
+	for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+	{	
+		if (mconstraints[ic]->IsActive())
+			mconstraints[ic]->Increment_q( mconstraints[ic]->Get_l_i() );
+	}
+	
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.h b/SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.h
new file mode 100644
index 0000000..1540d2c
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeMINRES.h
@@ -0,0 +1,108 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVEMINRES_H
+#define CHLCPITERATIVEMINRES_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeMINRES.h
+//
+//  An iterative LCP solver based on modified 
+//  Krylov iteration of MINRES type alternated with
+//  gradeint projection.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+/// An iterative LCP solver based on modified 
+/// Krylov iteration of MINRES type alternated with
+/// gradient projection (active set)
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, c \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpIterativeMINRES : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+	double	feas_tolerance;
+	int		max_fixedpoint_steps;
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeMINRES(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0   ///< tolerance for termination criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,0.2)
+			{
+				feas_tolerance = 0.2;
+				max_fixedpoint_steps = 6;
+			};
+				
+	virtual ~ChLcpIterativeMINRES() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	 
+				);
+
+
+	void   SetFeasTolerance (double mf) {this->feas_tolerance = mf;}
+	double GetFeasTolerance () {return this->feas_tolerance;}
+
+	void SetMaxFixedpointSteps (int mm) {this->max_fixedpoint_steps = mm;}
+	int  GetMaxFixedpointSteps () {return this->max_fixedpoint_steps;}
+
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeMINRES.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativePCG.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativePCG.cpp
new file mode 100644
index 0000000..25cc236
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativePCG.cpp
@@ -0,0 +1,226 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativePCG.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpIterativePCG.h"
+#include "ChLcpConstraintTwoFrictionT.h"
+
+namespace chrono
+{
+
+double ChLcpIterativePCG::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	tot_iterations = 0;
+	double maxviolation = 0.;
+
+
+	// Update auxiliary data in all constraints before starting,
+	// that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+
+	// Allocate auxiliary vectors;
+	
+	int nc = sysd.CountActiveConstraints();
+	if (verbose) GetLog() <<"\n-----Projected CG, solving nc=" << nc << "unknowns \n";
+
+	ChMatrixDynamic<> ml(nc,1);
+	ChMatrixDynamic<> mb(nc,1);
+	ChMatrixDynamic<> mu(nc,1);
+	ChMatrixDynamic<> mp(nc,1);
+	ChMatrixDynamic<> mw(nc,1);
+	ChMatrixDynamic<> mz(nc,1);
+	ChMatrixDynamic<> mNp(nc,1);
+	ChMatrixDynamic<> mtmp(nc,1);
+
+	double graddiff= 0.00001; // explorative search step for gradient
+
+
+	// ***TO DO*** move the following thirty lines in a short function ChLcpSystemDescriptor::ShurBvectorCompute() ?
+
+	// Compute the b_shur vector in the Shur complement equation N*l = b_shur
+	// with 
+	//   N_shur  = D'* (M^-1) * D
+	//   b_shur  = - c + D'*(M^-1)*k = b_i + D'*(M^-1)*k
+	// but flipping the sign of lambdas,  b_shur = - b_i - D'*(M^-1)*k
+	// Do this in three steps:
+	
+	// Put (M^-1)*k    in  q  sparse vector of each variable..
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb 
+
+	// ...and now do  b_shur = - D' * q  ..
+	int s_i = 0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mb(s_i, 0) = - mconstraints[ic]->Compute_Cq_q();
+			++s_i;
+		}
+
+	// ..and finally do   b_shur = b_shur - c
+	sysd.BuildBiVector(mtmp);	// b_i   =   -c   = phi/h 
+	mb.MatrDec(mtmp);  
+
+
+		// Optimization: backup the  q  sparse data computed above, 
+		// because   (M^-1)*k   will be needed at the end when computing primals.
+	ChMatrixDynamic<> mq; 
+	sysd.FromVariablesToVector(mq, true);	
+
+
+
+	// Initialize lambdas
+	if (warm_start)
+		sysd.FromConstraintsToVector(ml);
+	else
+		ml.FillElem(0);
+
+	// Initial projection of ml   ***TO DO***?
+	// ...
+
+
+	std::vector<bool> en_l(nc);
+	// Initially all constraints are enabled
+	for (int ie= 0; ie < nc; ie++)
+		en_l[ie] = true;
+
+
+	// u = -N*l+b 
+	sysd.ShurComplementProduct(mu, &ml, &en_l);		// 1)  u = N*l ...        #### MATR.MULTIPLICATION!!!###
+	mu.MatrNeg();								// 2)  u =-N*l
+	mu.MatrInc(mb);								// 3)  u =-N*l+b
+	mp = mu;
+	
+
+	//
+	// THE LOOP
+	//
+
+	std::vector<double> f_hist;
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// alpha =  u'*p / p'*N*p 
+		sysd.ShurComplementProduct(mNp, &mp, &en_l);// 1)  Np = N*p ...    #### MATR.MULTIPLICATION!!!###
+		double pNp = mp.MatrDot(&mp,&mNp);			// 2)  pNp = p'*N*p
+		double up =  mu.MatrDot(&mu,&mp);			// 3)  up = u'*p
+		double alpha = up/pNp;						// 4)  alpha =  u'*p / p'*N*p 
+
+		if (fabs(pNp)<10e-10) GetLog() << "Rayleygh quotient pNp breakdown \n";
+
+		// l = l + alpha * p;
+		mtmp.CopyFromMatrix(mp);
+		mtmp.MatrScale(alpha);
+		ml.MatrInc(mtmp);
+
+		double maxdeltalambda = mtmp.NormInf();
+
+		// l = Proj(l)
+		sysd.ConstraintsProject(ml);				// 5) l = P(l) 
+
+		// u = -N*l+b 
+		sysd.ShurComplementProduct(mu, &ml, 0);		// 6)  u = N*l ...        #### MATR.MULTIPLICATION!!!###
+		mu.MatrNeg();								// 7)  u =-N*l
+		mu.MatrInc(mb);								// 8)  u =-N*l+b
+
+		// w = (Proj(l+lambda*u) -l) /lambda;
+		mw.CopyFromMatrix(mu);
+		mw.MatrScale(graddiff);
+		mw.MatrInc(ml);
+		sysd.ConstraintsProject(mw);				// 9) w = P(l+lambda*u) ...
+		mw.MatrDec(ml);
+		mw.MatrScale(1.0/graddiff);					//10) w = (P(l+lambda*u)-l)/lambda ...
+
+		// z = (Proj(l+lambda*p) -l) /lambda;
+		mz.CopyFromMatrix(mp);
+		mz.MatrScale(graddiff);
+		mz.MatrInc(ml);
+		sysd.ConstraintsProject(mz);				//11) z = P(l+lambda*u) ...
+		mz.MatrDec(ml);
+		mz.MatrScale(1.0/graddiff);					//12) z = (P(l+lambda*u)-l)/lambda ...
+
+		// beta = w'*Np / pNp;
+		double wNp = mw.MatrDot(&mw, &mNp);
+		double beta = wNp / pNp;
+
+		// p = w + beta * z;
+		mp.CopyFromMatrix(mz);
+		mp.MatrScale(beta);
+		mp.MatrInc(mw);
+
+		// METRICS - convergence, plots, etc
+		double maxd			  = mu.NormInf();  // ***TO DO***  should be max violation, but just for test...
+			
+		// For recording into correction/residuals/violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxd, maxdeltalambda, iter);
+
+		tot_iterations++;
+	}
+	
+
+	// Resulting DUAL variables:
+	// store ml temporary vector into ChLcpConstraint 'l_i' multipliers
+	sysd.FromVectorToConstraints(ml); 
+
+
+	// Resulting PRIMAL variables:
+	// compute the primal variables as   v = (M^-1)(k + D*l) 
+
+		// v = (M^-1)*k  ...    (by rewinding to the backup vector computed ad the beginning)
+	sysd.FromVectorToVariables(mq);
+
+
+		// ... + (M^-1)*D*l     (this increment and also stores 'qb' in the ChLcpVariable items)
+	for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+	{	
+		if (mconstraints[ic]->IsActive())
+			mconstraints[ic]->Increment_q( mconstraints[ic]->Get_l_i() );
+	}
+	
+
+	if (verbose) GetLog() <<"-----\n";
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativePCG.h b/SRC/ChronoEngine/lcp/ChLcpIterativePCG.h
new file mode 100644
index 0000000..6ca52c3
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativePCG.h
@@ -0,0 +1,96 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVEPCG_H
+#define CHLCPITERATIVEPCG_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativePCG.h
+//
+//  An iterative solver based on modified 
+//  Krylov iteration of projected conjugate gradient
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+/// An iterative solver based on modified 
+/// Krylov iteration of projected conjugate gradient.
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, c \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpIterativePCG : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativePCG(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0   ///< tolerance for termination criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,0.2)
+			{
+				
+			};
+				
+	virtual ~ChLcpIterativePCG() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				);
+
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeBB.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.cpp
new file mode 100644
index 0000000..2727bf7
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.cpp
@@ -0,0 +1,576 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativePMINRES.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpIterativePMINRES.h"
+#include "ChLcpConstraintTwoFrictionT.h"
+
+namespace chrono
+{
+
+double ChLcpIterativePMINRES::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	 
+					)
+{
+	bool do_preconditioning = this->diag_preconditioning;
+
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+		// If stiffness blocks are used, the Schur complement cannot be esily
+		// used, so fall back to the Solve_SupportingStiffness method, that operates on KKT.
+	if (sysd.GetKstiffnessList().size() > 0)
+		return this->Solve_SupportingStiffness(sysd);
+
+
+		// Allocate auxiliary vectors;
+	
+	int nc = sysd.CountActiveConstraints();
+	if (verbose) 
+		GetLog() <<"\n-----Projected MINRES, solving nc=" << nc << "unknowns \n";
+
+	ChMatrixDynamic<> ml(nc,1);
+	ChMatrixDynamic<> mb(nc,1);
+	ChMatrixDynamic<> mp(nc,1);
+	ChMatrixDynamic<> mr(nc,1);
+	ChMatrixDynamic<> mz(nc,1);
+	ChMatrixDynamic<> mz_old(nc,1);
+	ChMatrixDynamic<> mNp(nc,1);
+	ChMatrixDynamic<> mMNp(nc,1);
+	ChMatrixDynamic<> mNMr(nc,1);
+	ChMatrixDynamic<> mNMr_old(nc,1);
+	ChMatrixDynamic<> mtmp(nc,1);
+	ChMatrixDynamic<> mDi (nc,1);
+
+	this->tot_iterations = 0;
+	double maxviolation = 0.;
+
+
+	// Update auxiliary data in all constraints before starting,
+	// that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//  Can be used as diagonal preconditioner.
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) 
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}	
+	}
+			
+	// The vector with the inverse of diagonal of the N matrix
+	int d_i = 0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mDi(d_i, 0) = 1.0 / mconstraints[ic]->Get_g_i();
+			++d_i;
+		}
+
+
+	// ***TO DO*** move the following thirty lines in a short function ChLcpSystemDescriptor::ShurBvectorCompute() ?
+
+	// Compute the b_shur vector in the Shur complement equation N*l = b_shur
+	// with 
+	//   N_shur  = D'* (M^-1) * D
+	//   b_shur  = - c + D'*(M^-1)*k = b_i + D'*(M^-1)*k
+	// but flipping the sign of lambdas,  b_shur = - b_i - D'*(M^-1)*k
+	// Do this in three steps:
+	
+	// Put (M^-1)*k    in  q  sparse vector of each variable..
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb 
+
+	// ...and now do  b_shur = - D' * q  ..
+	int s_i = 0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		if (mconstraints[ic]->IsActive())
+		{
+			mb(s_i, 0) = - mconstraints[ic]->Compute_Cq_q();
+			++s_i;
+		}
+
+	// ..and finally do   b_shur = b_shur - c
+	sysd.BuildBiVector(mtmp);	// b_i   =   -c   = phi/h 
+	mb.MatrDec(mtmp);  
+
+
+		// Optimization: backup the  q  sparse data computed above, 
+		// because   (M^-1)*k   will be needed at the end when computing primals.
+	ChMatrixDynamic<> mq; 
+	sysd.FromVariablesToVector(mq, true);	
+
+
+	double rel_tol = this->rel_tolerance;
+	double abs_tol = this->tolerance;
+	double rel_tol_b = mb.NormInf() * rel_tol;
+
+
+	// Initialize lambdas
+	if (warm_start)
+		sysd.FromConstraintsToVector(ml);
+	else
+		ml.FillElem(0);
+
+	// Initial projection of ml   ***TO DO***?
+	// ...
+
+	// r = b - N*l;
+	sysd.ShurComplementProduct(mr, &ml);		// 1)  r = N*l ...        #### MATR.MULTIPLICATION!!!### can be avoided if no warm starting!
+	mr.MatrNeg();								// 2)  r =-N*l
+	mr.MatrInc(mb);								// 3)  r =-N*l+b
+
+	// r = (project_orthogonal(l+diff*r, fric) - l)/diff;
+	mr.MatrScale(this->grad_diffstep);
+	mr.MatrInc(ml);
+	sysd.ConstraintsProject(mr);				// p = P(l+diff*p) ...
+	mr.MatrDec(ml);
+	mr.MatrScale(1.0/this->grad_diffstep);		// p = (P(l+diff*p)-l)/diff
+
+	// p = Mi * r;
+	mp = mr;  
+	if (do_preconditioning)
+		mp.MatrScale(mDi);
+	
+	// z = Mi * r;
+	mz = mp;
+
+	// NMr = N*M*r = N*z
+	sysd.ShurComplementProduct(mNMr, &mz);		// NMr = N*z    #### MATR.MULTIPLICATION!!!###
+
+	// Np = N*p  
+	sysd.ShurComplementProduct(mNp, &mp);		// Np = N*p    #### MATR.MULTIPLICATION!!!###
+
+
+	//
+	// THE LOOP
+	//
+
+	std::vector<double> f_hist;
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// MNp = Mi*Np; % = Mi*N*p                  %% -- Precond
+		mMNp = mNp;
+		if (do_preconditioning)
+			mMNp.MatrScale(mDi);
+
+		// alpha = (z'*(NMr))/((MNp)'*(Np));
+		double zNMr =  mz.MatrDot(&mz,&mNMr);		// 1)  zMNr = z'* NMr
+		double MNpNp = mMNp.MatrDot(&mMNp,&mNp);	// 2)  MNpNp = ((MNp)'*(Np))
+		
+		 if (fabs(MNpNp)<10e-30) 
+		 {
+			if (verbose) 
+				GetLog() << "Iter=" << iter << " Rayleygh quotient alpha breakdown: " << zNMr << " / " << MNpNp << "\n";
+			MNpNp=10e-12;
+		 }
+		 
+		double alpha = zNMr/MNpNp;					// 3)  alpha = (z'*(NMr))/((MNp)'*(Np));
+
+		// l = l + alpha * p;
+		mtmp = mp;
+		mtmp.MatrScale(alpha);
+		ml.MatrInc(mtmp);
+
+		double maxdeltalambda = mtmp.NormTwo(); //***better NormInf() for speed reasons?
+
+
+		// l = Proj(l)
+		sysd.ConstraintsProject(ml);				// l = P(l) 
+
+
+		// r = b - N*l;
+		sysd.ShurComplementProduct(mr, &ml);		// 1)  r = N*l ...        #### MATR.MULTIPLICATION!!!###
+		mr.MatrNeg();								// 2)  r =-N*l
+		mr.MatrInc(mb);								// 3)  r =-N*l+b
+		
+		// r = (project_orthogonal(l+diff*r, fric) - l)/diff; 
+		mr.MatrScale(this->grad_diffstep);
+		mr.MatrInc(ml);
+		sysd.ConstraintsProject(mr);				// r = P(l+diff*r) ...
+		mr.MatrDec(ml);
+		mr.MatrScale(1.0/this->grad_diffstep);		// r = (P(l+diff*r)-l)/diff 
+		
+
+		this->tot_iterations++;
+
+		// Terminate iteration when the projected r is small, if (norm(r,2) <= max(rel_tol_b,abs_tol))
+		double r_proj_resid = mr.NormTwo();
+		if (r_proj_resid < ChMax(rel_tol_b, abs_tol) )
+		{
+			if (verbose) 
+				GetLog() << "Iter=" << iter <<  " P(r)-converged!  |P(r)|=" << r_proj_resid << "\n";
+			break;
+		}
+
+		// z_old = z;
+		mz_old = mz;
+    
+		// z = Mi*r;                                 %% -- Precond
+		mz = mr;
+		if (do_preconditioning)
+			mz.MatrScale(mDi);
+
+		// NMr_old = NMr;
+		mNMr_old = mNMr;
+   
+		// NMr = N*z;                             
+		sysd.ShurComplementProduct(mNMr, &mz);		// NMr = N*z;    #### MATR.MULTIPLICATION!!!###
+
+		// beta = z'*(NMr-NMr_old)/(z_old'*(NMr_old));
+		mtmp.MatrSub(mNMr,mNMr_old);
+		double numerator = mz.MatrDot(&mz,&mtmp);
+		double denominator = mz_old.MatrDot(&mz_old, &mNMr_old);
+		
+		double beta = numerator / denominator;
+		
+		// Robustness improver: restart if beta=0 or too large 
+		if (fabs(denominator)<10e-30 || fabs(numerator)<10e-30)
+		{
+			if (verbose) 
+				GetLog() << "Iter=" << iter << " Ribiere quotient beta restart: " << numerator << " / " << denominator << "\n";
+			beta =0;
+		}
+
+		//beta = ChMax(0.0, beta); //***NOT NEEDED!!! (may be negative in not positive def.matrices!)
+
+		// p = z + beta * p;   
+		mtmp = mp;
+		mtmp.MatrScale(beta);
+		mp = mz;
+		mp.MatrInc(mtmp);
+
+
+		// Np = NMr + beta*Np;   // Optimization!! avoid matr x vect!!! (if no 'p' projection has been done)
+		mNp.MatrScale(beta);
+		mNp.MatrInc(mNMr);
+
+
+
+		// ---------------------------------------------
+		// METRICS - convergence, plots, etc
+
+		// For recording into correction/residuals/violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(r_proj_resid, maxdeltalambda, iter);
+			
+	}
+
+
+	// Resulting DUAL variables:
+	// store ml temporary vector into ChLcpConstraint 'l_i' multipliers
+	sysd.FromVectorToConstraints(ml); 
+
+
+	// Resulting PRIMAL variables:
+	// compute the primal variables as   v = (M^-1)(k + D*l) 
+
+		// v = (M^-1)*k  ...    (by rewinding to the backup vector computed ad the beginning)
+	sysd.FromVectorToVariables(mq);
+
+
+		// ... + (M^-1)*D*l     (this increment and also stores 'qb' in the ChLcpVariable items)
+	for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+	{	
+		if (mconstraints[ic]->IsActive())
+			mconstraints[ic]->Increment_q( mconstraints[ic]->Get_l_i() );
+	}
+
+	if (verbose) GetLog() <<"-----\n";
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////
+
+
+
+double ChLcpIterativePMINRES::Solve_SupportingStiffness(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				)
+{
+	bool do_preconditioning = this->diag_preconditioning;
+
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+	std::vector<ChLcpKstiffness*>& mstiffness	= sysd.GetKstiffnessList();
+
+	this->tot_iterations = 0;
+
+	// Allocate auxiliary vectors;
+	
+	int nv = sysd.CountActiveVariables();
+	int nc = sysd.CountActiveConstraints();
+	int nx = nv+nc;  // total scalar unknowns, in x vector for full KKT system Z*x-d=0
+
+	if (verbose) 
+		GetLog() <<"\n-----Projected MINRES -supporting stiffness-, n.vars nx=" << nx << "  max.iters=" << max_iterations << "\n";
+
+	ChMatrixDynamic<> mx(nx,1);
+	ChMatrixDynamic<> md(nx,1);
+	ChMatrixDynamic<> mp(nx,1);
+	ChMatrixDynamic<> mr(nx,1);
+	ChMatrixDynamic<> mz(nx,1);
+	ChMatrixDynamic<> mz_old(nx,1);
+	ChMatrixDynamic<> mZp(nx,1);
+	ChMatrixDynamic<> mMZp(nx,1);
+	ChMatrixDynamic<> mZMr(nx,1);
+	ChMatrixDynamic<> mZMr_old(nx,1);
+	ChMatrixDynamic<> mtmp(nx,1);
+	ChMatrixDynamic<> mDi (nx,1);
+
+	this->tot_iterations = 0;
+	double maxviolation = 0.;
+
+
+	//
+	// --- Compute a diagonal (scaling) preconditioner for the KKT system:
+    //
+
+	// Initialize the mDi vector with the diagonal of the Z matrix
+	sysd.BuildDiagonalVector(mDi);
+
+	// Pre-invert the values, to avoid wasting time with divisions in the following.
+	// From now, mDi contains the inverse of the diagonal of Z.
+	// Note, for constraints, the diagonal is 0, so set inverse of D as 1 assuming
+	// a constraint preconditioning and assuming the dot product of jacobians is already about 1.
+	for (int nel=0; nel < mDi.GetRows(); nel++)
+	{
+		if (fabs(mDi(nel)) > 1e-9)
+			mDi(nel) = 1.0/mDi(nel);
+		else 
+			mDi(nel) = 1.0;
+	}
+
+
+	//
+	// --- Vector initialization and book-keeping 
+    //
+
+
+	// Initialize the x vector of unknowns x ={q; -l} (if warm starting needed, initialize 
+	// x with current values of q and l in variables and constraints)
+	if (warm_start)
+		sysd.FromUnknownsToVector(mx);
+	else
+		mx.FillElem(0);
+
+	// Initialize the d vector filling it with {f, -b}
+	sysd.BuildDiVector(md);
+
+
+	//
+	// --- THE P-MINRES ALGORITHM
+	//
+
+	double rel_tol = this->rel_tolerance;
+	double abs_tol = this->tolerance;
+	double rel_tol_d = md.NormInf() * rel_tol;
+
+	// Initial projection of mx   ***TO DO***?
+	sysd.UnknownsProject(mx);
+
+	// r = d - Z*x;
+	sysd.SystemProduct(mr, &mx);				// 1)  r = Z*x ...        #### MATR.MULTIPLICATION!!!### can be avoided if no warm starting!
+	mr.MatrNeg();								// 2)  r =-Z*x
+	mr.MatrInc(md);								// 3)  r =-Z*x+d
+/*
+	// r = (project_orthogonal(x+diff*r, fric) - x)/diff;
+	mr.MatrScale(this->grad_diffstep);
+	mr.MatrInc(mx);
+	sysd.UnknownsProject(mr);					// p = P(x+diff*p) ...
+	mr.MatrDec(mx);
+	mr.MatrScale(1.0/this->grad_diffstep);		// p = (P(x+diff*p)-x)/diff
+*/
+	// p = Mi * r;
+	mp = mr;  
+	if (do_preconditioning)
+		mp.MatrScale(mDi);
+	
+	// z = Mi * r;
+	mz = mp;
+
+	// ZMr = Z*M*r = Z*z
+	sysd.SystemProduct(mZMr, &mz);		// ZMr = Z*z    #### MATR.MULTIPLICATION!!!###
+
+	// Zp = Z*p  
+	sysd.SystemProduct(mZp, &mp);		// Zp = Z*p    #### MATR.MULTIPLICATION!!!###
+
+	//
+	// THE LOOP
+	//
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// MZp = Mi*Zp; % = Mi*Z*p                  %% -- Precond
+		mMZp = mZp;
+		if (do_preconditioning)
+			mMZp.MatrScale(mDi);
+
+		// alpha = (z'*(ZMr))/((MZp)'*(Zp));
+		double zZMr =  mz.MatrDot(&mz,&mZMr);		// 1)  zZMr = z'* ZMr
+		double MZpZp = mMZp.MatrDot(&mMZp,&mZp);	// 2)  MZpZp = ((MZp)'*(Zp))
+		
+		// Robustness improver: case of division by zero
+		if (fabs(MZpZp)<10e-30) 
+		{
+			if (verbose) GetLog() << "Rayleygh alpha denominator breakdown: " << zZMr << " / " << MZpZp << "=" << (zZMr/MZpZp) << "  iter=" << iter << "\n";
+			MZpZp=10e-30;
+		}
+		// Robustness improver: case when r is orthogonal to Z*r (ex at first iteration, if f=0, x=0, with constraints)
+		if (fabs(zZMr)<10e-30) 
+		{
+			if (verbose) GetLog() << "Rayleygh alpha numerator breakdown: " << zZMr << " / " << MZpZp << "=" << (zZMr/MZpZp) << "  iter=" << iter << "\n";
+			zZMr=1;
+			MZpZp=1;
+		}
+		 
+		double alpha = zZMr/MZpZp;					// 3)  alpha = (z'*(ZMr))/((MZp)'*(Zp));
+
+		// x = x + alpha * p;
+		mtmp = mp;
+		mtmp.MatrScale(alpha);
+		mx.MatrInc(mtmp);
+
+		double maxdeltaunknowns = mtmp.NormTwo(); //***better NormInf() for speed reasons?
+
+
+		// x = Proj(x)
+		sysd.UnknownsProject(mx);				// x = P(x) 
+
+
+		// r = d - Z*x;
+		sysd.SystemProduct(mr, &mx);				// 1)  r = Z*x ...        #### MATR.MULTIPLICATION!!!###
+		mr.MatrNeg();								// 2)  r =-Z*x
+		mr.MatrInc(md);								// 3)  r =-Z*x+d
+/*	
+		// r = (project_orthogonal(x+diff*r, fric) - x)/diff; 
+		mr.MatrScale(this->grad_diffstep);
+		mr.MatrInc(mx);
+		sysd.UnknownsProject(mr);				// r = P(x+diff*r) ...
+		mr.MatrDec(mx);
+		mr.MatrScale(1.0/this->grad_diffstep);	// r = (P(x+diff*r)-x)/diff 
+*/	
+		this->tot_iterations++;
+
+		// Terminate iteration when the projected r is small, if (norm(r,2) <= max(rel_tol_d,abs_tol))
+		double r_proj_resid = mr.NormTwo();
+		if (r_proj_resid < ChMax(rel_tol_d, abs_tol) )
+		{
+			if (verbose) 
+				GetLog() << "P(r)-converged! iter=" << iter <<  " |P(r)|=" << r_proj_resid << "\n";
+			break;
+		}
+
+		// z_old = z;
+		mz_old = mz;
+    
+		// z = Mi*r;                                 %% -- Precond
+		mz = mr;
+		if (do_preconditioning)
+			mz.MatrScale(mDi);
+
+		// ZMr_old = ZMr;
+		mZMr_old = mZMr;
+   
+		// ZMr = Z*z;                             
+		sysd.SystemProduct(mZMr, &mz);		// ZMr = Z*z;    #### MATR.MULTIPLICATION!!!###
+
+		// beta = z'*(ZMr-ZMr_old)/(z_old'*(ZMr_old));
+		mtmp.MatrSub(mZMr,mZMr_old);
+		double numerator = mz.MatrDot(&mz,&mtmp);
+		double denominator = mz_old.MatrDot(&mz_old, &mZMr_old);
+	 
+		double beta = numerator / denominator;
+		
+		// Robustness improver: restart if beta=0 or too large 
+		if (fabs(denominator)<10e-30 || fabs(numerator)<10e-30)
+		{
+			if (verbose) GetLog() << "Ribiere quotient beta restart: " << numerator << " / " << denominator <<  "  iter=" << iter << "\n";
+			beta =0;
+		}
+
+		// p = z + beta * p;   
+		mtmp = mp;
+		mtmp.MatrScale(beta);
+		mp = mz;
+		mp.MatrInc(mtmp);
+
+		// Zp = ZMr + beta*Zp;   // Optimization!! avoid matr x vect!!! (if no 'p' projection has been done)
+		mZp.MatrScale(beta);
+		mZp.MatrInc(mZMr);
+
+
+		// ---------------------------------------------
+		// METRICS - convergence, plots, etc
+
+		// For recording into correction/residuals/violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(r_proj_resid, maxdeltaunknowns, iter);
+			
+	}
+
+	// After having solved for unknowns x={q;-l}, now copy those values from x vector to
+	// the q values in ChLcpVariable items and to l values in ChLcpConstraint items
+	sysd.FromVectorToUnknowns(mx);  
+
+
+	if (verbose) GetLog() <<"-----\n";
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.h b/SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.h
new file mode 100644
index 0000000..c928a92
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativePMINRES.h
@@ -0,0 +1,132 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVEPMINRES_H
+#define CHLCPITERATIVEPMINRES_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativePMINRES.h
+//
+//  An iterative LCP solver based on modified 
+//  Krylov iteration of MINRES type with gradient
+//  projections.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+/// An iterative LCP solver based on modified 
+/// Krylov iteration of MINRES type with gradient 
+/// projections (similar to nonlinear CG with Polyak-Ribiere)
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpIterativePMINRES : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+	double	grad_diffstep;
+	double  rel_tolerance;
+	bool    diag_preconditioning;
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativePMINRES(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0   ///< tolerance for termination criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,0.2)
+			{
+				grad_diffstep = 0.01; // too small can cause numerical roundoff troubles!
+				rel_tolerance = 0.0;
+				diag_preconditioning = true;
+			};
+				
+	virtual ~ChLcpIterativePMINRES() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				);
+
+
+				/// Same as Solve(), but this also supports the presence of
+				/// ChLcpKstiffness blocks. If Solve() is called and stiffness is present,
+				/// Solve() automatically falls back to this function.
+				/// It does not solve the Schur complement N*l-r=0 as Solve does, here the 
+				/// entire system KKT matrix with duals l and primals q is used.
+	virtual double Solve_SupportingStiffness(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	 
+				);
+
+				/// For the case where inequalities are introduced, the 
+				/// gradient is projected. A numerical differentiation is used, this is the delta. 
+	void   SetGradDiffStep (double mf) {this->grad_diffstep = mf;}
+	double GetGradDiffStep () {return this->grad_diffstep;}
+
+				/// Set relative tolerance. the iteration stops when
+				/// the (projected) residual r is smaller than absolute tolerance,
+				/// that you set via SetTolerance(), OR it is smaller than 'rhs_rel_tol' i.e. the norm
+				/// of the right hand side multiplied by this relative tolerance. 
+				/// Set to 0 if you do not want relative tolerance to enter into play.
+	void   SetRelTolerance (double mrt) {this->rel_tolerance = mrt;}
+	double GetRelTolerance () {return this->rel_tolerance;}
+
+				/// Enable diagonal preconditioning. It a simple but fast
+				/// preconditioning technique that is expecially useful to 
+				/// fix slow convergence in case variables have very different orders
+				/// of magnitude.
+	void SetDiagonalPreconditioning(bool mp) {this->diag_preconditioning = mp;}
+	bool GetDiagonalPreconditioning() {return this->diag_preconditioning;}
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativePMINRES.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeSOR.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativeSOR.cpp
new file mode 100644
index 0000000..1101325
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeSOR.cpp
@@ -0,0 +1,229 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativeSOR.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpIterativeSOR.h"
+
+
+namespace chrono
+{
+
+double ChLcpIterativeSOR::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	tot_iterations = 0;
+	double maxviolation = 0.;
+	double maxdeltalambda = 0.;
+	int i_friction_comp = 0;
+	double old_lambda_friction[3];
+
+
+	// 1)  Update auxiliary data in all constraints before starting,
+	//     that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) 
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}	
+	}
+
+
+	// 2)  Compute, for all items with variables, the initial guess for
+	//     still unconstrained system:
+
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb 
+
+
+	// 3)  For all items with variables, add the effect of initial (guessed)
+	//     lagrangian reactions of contraints, if a warm start is desired.
+	//     Otherwise, if no warm start, simply resets initial lagrangians to zero.
+	if (warm_start)
+	{
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+			if (mconstraints[ic]->IsActive())
+				mconstraints[ic]->Increment_q(mconstraints[ic]->Get_l_i());
+	}
+	else
+	{
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+			mconstraints[ic]->Set_l_i(0.);
+	}
+
+	// 4)  Perform the iteration loops
+	//
+
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// The iteration on all constraints
+		//
+
+		maxviolation = 0;
+		maxdeltalambda = 0;
+		i_friction_comp = 0;
+
+		for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+		{
+			// skip computations if constraint not active.
+			if (mconstraints[ic]->IsActive())
+			{
+				// compute residual  c_i = [Cq_i]*q + b_i + cfm_i*l_i
+				double mresidual = mconstraints[ic]->Compute_Cq_q() + mconstraints[ic]->Get_b_i()
+								 + mconstraints[ic]->Get_cfm_i() * mconstraints[ic]->Get_l_i();
+
+				// true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
+				double candidate_violation = fabs(mconstraints[ic]->Violation(mresidual));
+
+				// compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i + cfm_i*l_i )
+				double deltal = ( omega / mconstraints[ic]->Get_g_i() ) *
+								( -mresidual );
+
+				if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+				{
+					candidate_violation = 0;
+
+					// update:   lambda += delta_lambda;
+					old_lambda_friction[i_friction_comp] = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda_friction[i_friction_comp]  + deltal);
+					i_friction_comp++;
+					
+					if (i_friction_comp==1)
+						candidate_violation = fabs(ChMin(0.0,mresidual));
+
+					if (i_friction_comp==3)
+					{ 
+						mconstraints[ic-2]->Project(); // the N normal component will take care of N,U,V
+						double new_lambda_0 = mconstraints[ic-2]->Get_l_i() ;
+						double new_lambda_1 = mconstraints[ic-1]->Get_l_i() ;
+						double new_lambda_2 = mconstraints[ic-0]->Get_l_i() ;
+						// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+						if (this->shlambda!=1.0)
+						{
+							new_lambda_0 = shlambda*new_lambda_0 + (1.0-shlambda)*old_lambda_friction[0];
+							new_lambda_1 = shlambda*new_lambda_1 + (1.0-shlambda)*old_lambda_friction[1];
+							new_lambda_2 = shlambda*new_lambda_2 + (1.0-shlambda)*old_lambda_friction[2];
+							mconstraints[ic-2]->Set_l_i(new_lambda_0);
+							mconstraints[ic-1]->Set_l_i(new_lambda_1);
+							mconstraints[ic-0]->Set_l_i(new_lambda_2);
+						}
+						double true_delta_0 = new_lambda_0 - old_lambda_friction[0];
+						double true_delta_1 = new_lambda_1 - old_lambda_friction[1];
+						double true_delta_2 = new_lambda_2 - old_lambda_friction[2];
+						mconstraints[ic-2]->Increment_q(true_delta_0);
+						mconstraints[ic-1]->Increment_q(true_delta_1);
+						mconstraints[ic-0]->Increment_q(true_delta_2);
+						
+						if (this->record_violation_history)
+						{
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_0));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_1));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_2));
+						}
+						i_friction_comp =0;
+					}
+				} 
+				else
+				{
+					// update:   lambda += delta_lambda;
+					double old_lambda = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda + deltal);
+
+					// If new lagrangian multiplier does not satisfy inequalities, project
+					// it into an admissible orthant (or, in general, onto an admissible set)
+					mconstraints[ic]->Project();
+
+					// After projection, the lambda may have changed a bit..
+					double new_lambda = mconstraints[ic]->Get_l_i() ;
+
+					// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+					if (this->shlambda!=1.0)
+					{
+						new_lambda = shlambda*new_lambda + (1.0-shlambda)*old_lambda;
+						mconstraints[ic]->Set_l_i(new_lambda);
+					}
+
+					double true_delta = new_lambda - old_lambda;
+
+					// For all items with variables, add the effect of incremented
+					// (and projected) lagrangian reactions:
+					mconstraints[ic]->Increment_q(true_delta);
+
+					if (this->record_violation_history)
+						maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta)); 
+				}
+
+				maxviolation = ChMax(maxviolation, fabs(candidate_violation));
+
+			}	// end IsActive()
+
+		}	// end loop on constraints
+ 
+		// For recording into violaiton history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxviolation, maxdeltalambda, iter);
+
+			tot_iterations++;
+			// Terminate the loop if violation in constraints has been succesfully limited.
+			if (maxviolation < tolerance)
+				break;
+
+	} // end iteration loop
+
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeSOR.h b/SRC/ChronoEngine/lcp/ChLcpIterativeSOR.h
new file mode 100644
index 0000000..849c837
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeSOR.h
@@ -0,0 +1,100 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVESOR_H
+#define CHLCPITERATIVESOR_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeSOR.h
+//
+//  An iterative LCP solver based on projective
+//  fixed point method, with overrelaxation
+//  and immediate variable update as in SOR methods.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+
+/// An iterative LCP solver based on projective
+/// fixed point method, with overrelaxation
+/// and immediate variable update as in SOR methods.
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpIterativeSOR : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeSOR(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0,  ///< tolerance for termination criterion
+				double momega=1.0       ///< overrelaxation criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,momega)
+			{};
+				
+	virtual ~ChLcpIterativeSOR() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				);
+
+
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeSOR.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeSORmultithread.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativeSORmultithread.cpp
new file mode 100644
index 0000000..ca9d53d
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeSORmultithread.cpp
@@ -0,0 +1,473 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativeSOR.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpIterativeSORmultithread.h"
+#include "parallel/ChThreadsSync.h"
+#include "ChLcpConstraintTwoFrictionT.h"
+#include "ChLcpConstraintTwoRollingN.h"
+#include "ChLcpConstraintTwoRollingT.h"
+#include <stdio.h>
+
+
+
+
+namespace chrono
+{
+
+
+// Each thread will own an instance of the following data:
+
+struct thread_data 
+{
+	ChLcpIterativeSORmultithread* solver;		// reference to solver 
+	ChMutexSpinlock* mutex;	// this will be used to avoid race condition when writing to shared memory.
+	
+	enum solver_stage
+	{
+		STAGE1_PREPARE = 0,
+		STAGE2_ADDFORCES,
+		STAGE3_LOOPCONSTRAINTS
+	};
+
+	solver_stage stage;
+
+				// the range of scanned multipliers (for loops on multipliers)
+	unsigned int constr_from;	
+	unsigned int constr_to;
+		
+				// the range of scanned 'variables' objects (for loops on variables, aka rigid bodies)
+	unsigned int var_from;
+	unsigned int var_to;
+
+	std::vector<ChLcpConstraint*>* mconstraints;
+	std::vector<ChLcpVariables*>*  mvariables;
+};
+
+
+
+
+// Don't create local store memory, just return 0
+
+void*	SolverMemoryFunc()
+{
+	return 0;
+}
+
+
+// The following is the function which will be executed by 
+// each thread, when threads are launched at each Solve()  
+
+
+void SolverThreadFunc(void* userPtr,void* lsMemory)
+{
+	double maxviolation = 0.;
+	double maxdeltalambda = 0.;
+	int i_friction_comp = 0;
+	double old_lambda_friction[3];
+
+	thread_data* tdata = (thread_data*)userPtr;
+
+	std::vector<ChLcpConstraint*>* mconstraints = tdata->mconstraints;
+	std::vector<ChLcpVariables*>*  mvariables = tdata->mvariables;
+
+	switch (tdata->stage)
+	{
+	case thread_data::STAGE1_PREPARE:
+		{
+			//    Update auxiliary data in all constraints before starting,
+			//    that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+			//
+			for (unsigned int ic = tdata->constr_from; ic< tdata->constr_to; ic++)
+				(*mconstraints)[ic]->Update_auxiliary();
+
+			//    Average all g_i for the triplet of contact constraints n,u,v.
+			//
+			int j_friction_comp = 0;
+			double gi_values[3];
+			for (unsigned int ic = tdata->constr_from; ic< tdata->constr_to; ic++)
+			{
+				if ((*mconstraints)[ic]->GetMode() == CONSTRAINT_FRIC) 
+				{
+					gi_values[j_friction_comp] = (*mconstraints)[ic]->Get_g_i();
+					j_friction_comp++;
+					if (j_friction_comp==3)
+					{
+						double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+						(*mconstraints)[ic-2]->Set_g_i(average_g_i);
+						(*mconstraints)[ic-1]->Set_g_i(average_g_i);
+						(*mconstraints)[ic-0]->Set_g_i(average_g_i);
+						j_friction_comp=0;
+					}
+				}	
+			}
+
+			break; // end stage
+		}
+
+	case thread_data::STAGE2_ADDFORCES:
+		{
+			//     Compute, for all items with variables, the initial guess for
+			//     still unconstrained system:
+			//
+			for (unsigned int iv = tdata->var_from; iv< tdata->var_to; iv++)
+				if ((*mvariables)[iv]->IsActive())
+					(*mvariables)[iv]->Compute_invMb_v((*mvariables)[iv]->Get_qb(), (*mvariables)[iv]->Get_fb()); // q = [M]'*fb 
+			
+			break; // end stage
+		}
+
+	case thread_data::STAGE3_LOOPCONSTRAINTS:
+		{
+			//     For all items with variables, add the effect of initial (guessed)
+			//     lagrangian reactions of contraints, if a warm start is desired.
+			//     Otherwise, if no warm start, simply resets initial lagrangians to zero.
+			//
+			if (tdata->solver->GetWarmStart() )
+			{
+				for (unsigned int ic = tdata->constr_from; ic< tdata->constr_to; ic++)
+					if ((*mconstraints)[ic]->IsActive())
+					{
+					//	tdata->mutex->Lock();   // this avoids double writing on shared q vector
+						 (*mconstraints)[ic]->Increment_q((*mconstraints)[ic]->Get_l_i());
+					//	tdata->mutex->Unlock(); // end critical section
+					}
+			}
+			else
+			{
+				for (unsigned int ic = tdata->constr_from; ic< tdata->constr_to; ic++)
+					(*mconstraints)[ic]->Set_l_i(0.);
+			}
+
+			//    Perform the solver iteration loops
+			//
+			for (int iter = 0; iter < tdata->solver->GetMaxIterations(); iter++)
+			{
+				// The iteration on all constraints
+				//
+
+				maxviolation = 0;
+				maxdeltalambda = 0;
+				i_friction_comp = 0;
+
+				for (unsigned int ic = tdata->constr_from; ic < tdata->constr_to; ic++)
+				{
+					// skip computations if constraint not active.
+					if ((*mconstraints)[ic]->IsActive())
+					{
+
+						// compute residual  c_i = [Cq_i]*q + b_i + cfm_i*l_i
+						double mresidual = (*mconstraints)[ic]->Compute_Cq_q() + (*mconstraints)[ic]->Get_b_i()
+								         + (*mconstraints)[ic]->Get_cfm_i() * (*mconstraints)[ic]->Get_l_i();
+
+						// true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
+						double candidate_violation = fabs((*mconstraints)[ic]->Violation(mresidual));
+
+						// compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i + cfm_i*l_i )
+						double deltal = (  tdata->solver->GetOmega() / (*mconstraints)[ic]->Get_g_i() ) *
+										( -mresidual );
+
+						if ((*mconstraints)[ic]->GetMode() == CONSTRAINT_FRIC)
+						{
+							candidate_violation = 0;
+
+							// update:   lambda += delta_lambda;
+							old_lambda_friction[i_friction_comp] = (*mconstraints)[ic]->Get_l_i();
+							(*mconstraints)[ic]->Set_l_i( old_lambda_friction[i_friction_comp]  + deltal);
+							i_friction_comp++;
+							
+							if (i_friction_comp==1)
+								candidate_violation = fabs(ChMin(0.0,mresidual));
+
+							if (i_friction_comp==3)
+							{ 
+								(*mconstraints)[ic-2]->Project(); // the N normal component will take care of N,U,V
+								double new_lambda_0 = (*mconstraints)[ic-2]->Get_l_i() ;
+								double new_lambda_1 = (*mconstraints)[ic-1]->Get_l_i() ;
+								double new_lambda_2 = (*mconstraints)[ic-0]->Get_l_i() ;
+								// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+								if (tdata->solver->GetSharpnessLambda()!=1.0)
+								{
+									double shlambda = tdata->solver->GetSharpnessLambda();
+									new_lambda_0 = shlambda*new_lambda_0 + (1.0-shlambda)*old_lambda_friction[0];
+									new_lambda_1 = shlambda*new_lambda_1 + (1.0-shlambda)*old_lambda_friction[1];
+									new_lambda_2 = shlambda*new_lambda_2 + (1.0-shlambda)*old_lambda_friction[2];
+									(*mconstraints)[ic-2]->Set_l_i(new_lambda_0);
+									(*mconstraints)[ic-1]->Set_l_i(new_lambda_1);
+									(*mconstraints)[ic-0]->Set_l_i(new_lambda_2);
+								}
+								double true_delta_0 = new_lambda_0 - old_lambda_friction[0];
+								double true_delta_1 = new_lambda_1 - old_lambda_friction[1];
+								double true_delta_2 = new_lambda_2 - old_lambda_friction[2];
+							//	tdata->mutex->Lock();   // this avoids double writing on shared q vector
+								 (*mconstraints)[ic-2]->Increment_q(true_delta_0);
+								 (*mconstraints)[ic-1]->Increment_q(true_delta_1);
+								 (*mconstraints)[ic-0]->Increment_q(true_delta_2);
+							//	tdata->mutex->Unlock(); // end critical section
+								/*
+								if (this->record_violation_history)
+								{
+									maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_0));
+									maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_1));
+									maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_2));
+								}
+								*/  //***TO DO***
+								i_friction_comp =0;
+							}
+						} 
+						else
+						{
+							// update:   lambda += delta_lambda;
+							double old_lambda = (*mconstraints)[ic]->Get_l_i();
+							(*mconstraints)[ic]->Set_l_i( old_lambda + deltal);
+
+							// If new lagrangian multiplier does not satisfy inequalities, project
+							// it into an admissible orthant (or, in general, onto an admissible set)
+							(*mconstraints)[ic]->Project();
+
+							// After projection, the lambda may have changed a bit..
+							double new_lambda = (*mconstraints)[ic]->Get_l_i() ;
+
+							// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+							if (tdata->solver->GetSharpnessLambda()!=1.0)
+							{
+								double shlambda = tdata->solver->GetSharpnessLambda();
+								new_lambda = shlambda*new_lambda + (1.0-shlambda)*old_lambda;
+								(*mconstraints)[ic]->Set_l_i(new_lambda);
+							}
+
+							double true_delta = new_lambda - old_lambda;
+
+							// For all items with variables, add the effect of incremented
+							// (and projected) lagrangian reactions:
+							tdata->mutex->Lock();   // this avoids double writing on shared q vector
+							 (*mconstraints)[ic]->Increment_q(true_delta);
+							tdata->mutex->Unlock(); // end critical section
+							/*
+							if (this->record_violation_history)
+								maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta)); 
+							*/  //***TO DO***
+						}
+
+						maxviolation = ChMax(maxviolation, fabs(candidate_violation));
+
+					}	// end IsActive()
+
+				}	// end loop on constraints
+		 
+
+				// For recording into violaiton history, if debugging
+				//if (this->record_violation_history)
+				//	AtIterationEnd(maxviolation, maxdeltalambda, iter);  //***TO DO***
+
+				// Terminate the loop if violation in constraints has been succesfully limited.
+				if (maxviolation < tdata->solver->GetTolerance() )
+					break;
+
+			} // end iteration loop
+		
+			break;
+		} // end stage 
+
+	default:
+		{
+			break;
+		}
+	} // end stage  switching
+
+}
+
+
+
+// When the solver object is created, threads are also
+// created and initialized, in 'wait' mode.
+
+ChLcpIterativeSORmultithread::ChLcpIterativeSORmultithread(
+				char* uniquename,
+				int nthreads,
+				int mmax_iters,   
+				bool mwarm_start,
+				double mtolerance,  
+				double momega
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,momega)
+{
+	ChThreadConstructionInfo create_args ( uniquename, 
+						SolverThreadFunc, 
+						SolverMemoryFunc, 
+						nthreads);
+
+	solver_threads = new ChThreads(create_args); 
+};
+
+ChLcpIterativeSORmultithread::~ChLcpIterativeSORmultithread() 
+{
+	if (solver_threads)
+	{
+		solver_threads->flush();
+		delete (solver_threads); solver_threads =0;
+	}
+};
+
+
+
+
+// The SOR solver process has been modified so that some 
+// parallelizable code has been moved to the SolverThreadFunc().
+// So, the N threads must be started (each executing SolverThreadFunc() )
+// and, after waiting for all them to be completed, with flush(), the
+// solution is done.
+
+double ChLcpIterativeSORmultithread::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	double maxviolation = 0.;
+	double maxdeltalambda = 0.;
+	int i_friction_comp = 0;
+
+
+	/////////////////////////////////////////////
+	/// THE PARALLEL SOLVER, PERFORMED IN STAGES 
+
+
+	ChMutexSpinlock spinlock;
+
+	// --0--  preparation: 
+	//        subdivide the workload to the threads and prepare their 'thread_data':
+
+	int numthreads = this->solver_threads->getNumberOfThreads();
+	std::vector<thread_data> mdataN(numthreads);
+
+	int var_slice = 0;
+	int constr_slice = 0;
+	for (int nth = 0; nth < numthreads; nth++)
+	{
+		unsigned int var_from = var_slice;
+		unsigned int var_to = var_from + (mvariables.size()-var_from) / (numthreads-nth);
+		unsigned int constr_from = constr_slice;
+		unsigned int constr_to = constr_from + (mconstraints.size()-constr_from) / (numthreads-nth);
+		if(constr_to < mconstraints.size()) // do not slice the three contact multipliers (or six in case of rolling)
+		{
+			if (dynamic_cast<ChLcpConstraintTwoFrictionT*>(mconstraints[constr_to]))
+				constr_to++;
+			if (dynamic_cast<ChLcpConstraintTwoFrictionT*>(mconstraints[constr_to]))
+				constr_to++;
+			if (constr_to < mconstraints.size())
+			{
+				if (dynamic_cast<ChLcpConstraintTwoRollingN*>(mconstraints[constr_to]))
+					constr_to++;
+				if (dynamic_cast<ChLcpConstraintTwoRollingT*>(mconstraints[constr_to]))
+					constr_to++;
+				if (dynamic_cast<ChLcpConstraintTwoRollingT*>(mconstraints[constr_to]))
+					constr_to++;
+			}
+		}
+		mdataN[nth].solver = this;
+		mdataN[nth].mutex = &spinlock;
+		mdataN[nth].constr_from = constr_from;
+		mdataN[nth].constr_to   = constr_to;
+		mdataN[nth].var_from = var_from;
+		mdataN[nth].var_to = var_to;
+		mdataN[nth].mconstraints = &mconstraints;
+		mdataN[nth].mvariables = &mvariables;
+
+		var_slice = var_to;
+		constr_slice = constr_to;
+	}
+
+
+	// LAUNCH THE PARALLEL COMPUTATION ON THREADS !!!!
+
+
+	// --1--  stage: 
+	//        precompute aux variables in constraints. 
+	for (int nth = 0; nth < numthreads; nth++)
+	{
+		mdataN[nth].stage = thread_data::STAGE1_PREPARE;
+		solver_threads->sendRequest(1, &mdataN[nth], nth);
+	}
+	//... must wait that the all the threads finished their stage!!!
+	solver_threads->flush();	
+
+
+	// --2--  stage: 
+	//        add external forces and mass effects, on variables.
+	for (int nth = 0; nth < numthreads; nth++)
+	{
+		mdataN[nth].stage = thread_data::STAGE2_ADDFORCES; 
+		solver_threads->sendRequest(1, &mdataN[nth], nth);
+	}
+	//... must wait that the all the threads finished their stage!!!
+	solver_threads->flush();	
+
+
+	// --3--  stage: 
+	//        loop on constraints.
+	for (int nth = 0; nth < numthreads; nth++)
+	{
+		mdataN[nth].stage = thread_data::STAGE3_LOOPCONSTRAINTS; 
+		solver_threads->sendRequest(1, &mdataN[nth], nth);
+	}
+	//... must wait that the all the threads finished their stage!!!
+	solver_threads->flush();
+
+
+	return 0;
+
+}
+
+
+
+void ChLcpIterativeSORmultithread::ChangeNumberOfThreads(int mthreads)
+{
+	if (mthreads <1)
+		mthreads =1;
+
+	char mname[100]; strcpy(mname, solver_threads->getUniqueName().c_str() ) ;
+
+	solver_threads->flush();
+	delete (solver_threads); solver_threads =0;
+
+
+	ChThreadConstructionInfo create_args ( mname, 
+						SolverThreadFunc, 
+						SolverMemoryFunc, 
+						mthreads);
+
+	solver_threads = new ChThreads(create_args);
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeSORmultithread.h b/SRC/ChronoEngine/lcp/ChLcpIterativeSORmultithread.h
new file mode 100644
index 0000000..3b48994
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeSORmultithread.h
@@ -0,0 +1,92 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVESORMULTITHREAD_H
+#define CHLCPITERATIVESORMULTITHREAD_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeSORmultithread.h
+//
+//  An iterative VI solver based on projective
+//  fixed point method, with overrelaxation
+//  and immediate variable update as in SOR methods,
+//  implemented on multicore processors.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+#include "parallel/ChThreads.h"
+
+
+namespace chrono
+{
+
+
+class ChApi ChLcpIterativeSORmultithread : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+	ChThreads* solver_threads;
+
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeSORmultithread(
+				char* uniquename,		///< this name must be unique.
+				int nthreads=2,			///< number of threads
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0,  ///< tolerance for termination criterion
+				double momega=1.0       ///< overrelaxation criterion
+				);  
+				
+	virtual ~ChLcpIterativeSORmultithread();
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables
+				);
+
+
+
+				/// Changes the number of threads which run in parallel (should be > 1 )
+	void ChangeNumberOfThreads(int mthreads = 2);
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeSORmultithread.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeSolver.h b/SRC/ChronoEngine/lcp/ChLcpIterativeSolver.h
new file mode 100644
index 0000000..9b473a8
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeSolver.h
@@ -0,0 +1,191 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVESOLVER_H
+#define CHLCPITERATIVESOLVER_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeSolver.h
+//
+//    Base class for all solution methods
+//   based on iterative schemes, such as the
+//   SOR method and so on.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpSolver.h"
+
+
+namespace chrono
+{
+
+
+/// Base class for ITERATIVE solvers aimed at solving
+/// LCP linear complementarity problems arising
+/// from QP optimization problems.
+/// This class does nothing: it is up to inherited
+/// classes to implement specific solution methods,
+/// such as simplex, iterative SOR, etc.
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+
+class ChApi ChLcpIterativeSolver : public ChLcpSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+	int		max_iterations;
+	int		tot_iterations;		///The total number of iterations performed by the solver
+	bool	warm_start;
+	double	tolerance;	
+	double  omega;
+	double  shlambda;
+
+	bool	record_violation_history;
+	std::vector<double> violation_history;
+	std::vector<double>	dlambda_history;
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeSolver(
+				int    mmax_iters=50,		///< max.number of iterations
+				bool   mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0,		///< tolerance for termination criterion
+				double momega=1.0,			///< overrelaxation, if any
+				double mshlambda=1.0		///< sharpness, if any 
+				)
+			: max_iterations(mmax_iters), 
+			  tot_iterations(0),
+			  warm_start(mwarm_start), 
+			  tolerance(mtolerance),
+			  omega(momega),
+			  shlambda(mshlambda),
+              record_violation_history(false)
+			{
+				violation_history.clear();
+				dlambda_history.clear();
+			};
+
+	virtual ~ChLcpIterativeSolver() {};
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Set the maximum number of iterations (if the 
+				/// solver exceed this limit, it should stop even if
+				/// the required tolerance isn't yet reached.
+				/// Default limit: 50 iterations.
+	virtual void   SetMaxIterations(int mval) {max_iterations=mval;}
+	virtual double GetMaxIterations() {return max_iterations;}
+	virtual double GetTotalIterations() {return tot_iterations;}
+
+				/// Set the overrelaxation factor, if used; it can be 
+				/// used by SOR-like methods.  
+				/// Default=1. Value clamped if lower than 0. 
+	virtual void   SetOmega(double mval) {if (mval>0.) omega= mval;}
+	virtual double GetOmega() {return omega;}
+
+				/// Set the sharpness factor, if used; it can be 
+				/// used by SOR-like methods with projection (see Mangasarian LCP method)
+				/// Default=1. Usual range in 0..1. Value clamped if lower than 0. 
+	virtual void   SetSharpnessLambda(double mval) {if (mval>0.) shlambda= mval;}
+	virtual double GetSharpnessLambda() {return shlambda;}
+
+				///	Set if the solver should 'warm start' from the
+				/// actual values of the variables. Useful if the
+				/// variables are already near to the solution. In 
+				/// most iterative schemes, this is often a good trick.
+	virtual void   SetWarmStart(bool mval) {warm_start = mval;}
+	virtual bool   GetWarmStart() {return warm_start;}
+	
+				/// Set the tolerance (default is 0.) for stopping
+				/// criterion. The iteration is stopped when the 
+				/// constraint feasability error goes under this 
+				/// tolerance.
+	virtual void   SetTolerance(double mval) {tolerance = mval;}
+	virtual double GetTolerance() {return tolerance;}
+
+				/// Set 'true' if you want the iterative solver to 
+				/// record the values of constraint violation into 
+				/// a vector with the history (for tuning and debugging,
+				/// so you can plot a graph of how the residual decreases
+				/// during iterations until solution is reached)
+	void   SetRecordViolation(bool mval) {record_violation_history = mval;}
+	double GetRecordViolation() {return record_violation_history;}
+
+				/// Access the vector with the (hopefully decreasing:)
+				/// history of values showing the max constraint violation 
+				/// changing during iterations, up to solution.
+				/// Note that you must set SetRecordViolation(true) to use it.
+	std::vector<double>& GetViolationHistory() {return violation_history;};
+
+				/// Access the vector with the (hopefully decreasing:)
+				/// history of max delta in lambda multiplier values.
+				/// Note that you must set SetRecordViolation(true) to use it.
+	std::vector<double>& GetDeltalambdaHistory() {return dlambda_history;};
+
+
+protected:
+				// This method MUST be called by all iterative
+				// methods INSIDE their iteration loops (at the end). If you use
+				// SetRecordViolation(true), the violation history 
+				// will be automatically updated by this callback.
+				// Note: 'iternum' must be 0 for 1st iteration, etc.
+	void AtIterationEnd(double mmaxviolation, double mdeltalambda, unsigned int iternum)
+			{
+				if (!record_violation_history) return;
+				if (iternum!= violation_history.size())
+				{
+					violation_history.clear();
+					violation_history.resize(iternum);
+				}
+				if (iternum!= dlambda_history.size())
+				{
+					dlambda_history.clear();
+					dlambda_history.resize(iternum);
+				}
+				violation_history.push_back(mmaxviolation);
+				dlambda_history.push_back(mdeltalambda);
+			}
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeSolver.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.cpp b/SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.cpp
new file mode 100644
index 0000000..65283dc
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.cpp
@@ -0,0 +1,337 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpIterativeSymmSOR.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include "ChLcpIterativeSymmSOR.h"
+
+
+namespace chrono 
+{
+
+double ChLcpIterativeSymmSOR::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	   
+					)
+{ 
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	double maxviolation = 0.;
+	double maxdeltalambda = 0.;
+	int i_friction_comp = 0;
+	double old_lambda_friction[3];
+
+	// 1)  Update auxiliary data in all constraints before starting,
+	//     that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// Average all g_i for the triplet of contact constraints n,u,v.
+	//
+	int j_friction_comp = 0;
+	double gi_values[3];
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) 
+		{
+			gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
+			j_friction_comp++;
+			if (j_friction_comp==3)
+			{
+				double average_g_i = (gi_values[0]+gi_values[1]+gi_values[2])/3.0;
+				mconstraints[ic-2]->Set_g_i(average_g_i);
+				mconstraints[ic-1]->Set_g_i(average_g_i);
+				mconstraints[ic-0]->Set_g_i(average_g_i);
+				j_friction_comp=0;
+			}
+		}	
+	}
+
+	// 2)  Compute, for all items with variables, the initial guess for
+	//     still uncostrained system:
+
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+		if (mvariables[iv]->IsActive())
+			mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb
+
+	// 3)  For all items with variables, add the effect of initial (guessed)
+	//     lagrangian reactions of contraints, if a warm start is desired.
+	//     Otherwise, if no warm start, simply resets initial lagrangians to zero.
+	if (warm_start)
+	{
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+			if (mconstraints[ic]->IsActive())
+				mconstraints[ic]->Increment_q(mconstraints[ic]->Get_l_i());
+	}
+	else
+	{
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+			mconstraints[ic]->Set_l_i(0.);
+	}
+
+	// 4)  Perform the iteration loops
+	//
+	for (int iter = 0; iter < max_iterations; )
+	{
+		//
+		// Forward sweep, for symmetric SOR
+		//
+
+		maxviolation = 0;
+		maxdeltalambda = 0;
+		i_friction_comp = 0;
+
+		for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+		{
+			// skip computations if constraint not active.
+			if (mconstraints[ic]->IsActive())
+			{
+
+				// compute residual  c_i = [Cq_i]*q + b_i + cfm_i*l_i
+				double mresidual = mconstraints[ic]->Compute_Cq_q() + mconstraints[ic]->Get_b_i()
+								 + mconstraints[ic]->Get_cfm_i() * mconstraints[ic]->Get_l_i();
+
+				// true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
+				double candidate_violation = fabs(mconstraints[ic]->Violation(mresidual));
+
+				// compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i + cfm_i*l_i )
+				double deltal = ( omega / mconstraints[ic]->Get_g_i() ) *
+								( -mresidual );
+
+				if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+				{
+					candidate_violation = 0;
+					// update:   lambda += delta_lambda;
+					old_lambda_friction[i_friction_comp] = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda_friction[i_friction_comp]  + deltal);
+					i_friction_comp++;
+
+					if (i_friction_comp==1)
+						candidate_violation = fabs(ChMin(0.0,mresidual));
+
+					if (i_friction_comp==3)
+					{ 
+						mconstraints[ic-2]->Project(); // the N normal component will take care of N,U,V
+
+						double new_lambda_0 = mconstraints[ic-2]->Get_l_i() ;
+						double new_lambda_1 = mconstraints[ic-1]->Get_l_i() ;
+						double new_lambda_2 = mconstraints[ic-0]->Get_l_i() ;
+						// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+						if (this->shlambda!=1.0)
+						{
+							new_lambda_0 = shlambda*new_lambda_0 + (1.0-shlambda)*old_lambda_friction[0];
+							new_lambda_1 = shlambda*new_lambda_1 + (1.0-shlambda)*old_lambda_friction[1];
+							new_lambda_2 = shlambda*new_lambda_2 + (1.0-shlambda)*old_lambda_friction[2];
+							mconstraints[ic-2]->Set_l_i(new_lambda_0);
+							mconstraints[ic-1]->Set_l_i(new_lambda_1);
+							mconstraints[ic-0]->Set_l_i(new_lambda_2);
+						}
+						double true_delta_0 = new_lambda_0 - old_lambda_friction[0];
+						double true_delta_1 = new_lambda_1 - old_lambda_friction[1];
+						double true_delta_2 = new_lambda_2 - old_lambda_friction[2];
+						mconstraints[ic-2]->Increment_q(true_delta_0);
+						mconstraints[ic-1]->Increment_q(true_delta_1);
+						mconstraints[ic-0]->Increment_q(true_delta_2);
+						
+						if (this->record_violation_history)
+						{
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_0));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_1));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_2));
+						}
+						i_friction_comp =0;
+					}
+				} 
+				else
+				{
+					// update:   lambda += delta_lambda;
+					double old_lambda = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda + deltal);
+
+					// If new lagrangian multiplier does not satisfy inequalities, project
+					// it into an admissible orthant (or, in general, onto an admissible set)
+					mconstraints[ic]->Project();
+
+					// After projection, the lambda may have changed a bit..
+					double new_lambda = mconstraints[ic]->Get_l_i() ;
+
+					// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+					if (this->shlambda!=1.0)
+					{
+						new_lambda = shlambda*new_lambda + (1.0-shlambda)*old_lambda;
+						mconstraints[ic]->Set_l_i(new_lambda);
+					}
+
+					double true_delta = new_lambda - old_lambda;
+
+					// For all items with variables, add the effect of incremented
+					// (and projected) lagrangian reactions:
+					mconstraints[ic]->Increment_q(true_delta);
+
+					if (this->record_violation_history)
+						maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta)); 
+				}
+			 	
+				maxviolation = ChMax(maxviolation, fabs(candidate_violation));
+			
+			} // end IsActive()
+		
+		} // end constraint loop 
+
+		// Terminate the loop if violation in constraints has been succesfully limited.
+		//if (maxviolation < tolerance)
+		//	break;
+
+		// For recording into violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxviolation, maxdeltalambda, iter);
+
+		// Increment iter count (each sweep, either forward or backward, is considered
+		// as a complete iteration, to be fair when comparing to the non-symmetric SOR :)
+		iter++;
+
+
+		//
+		// Backward sweep, for symmetric SOR
+		//
+		maxviolation = 0.;
+		maxdeltalambda = 0.;
+		i_friction_comp = 0;
+
+		for (int ic = ((mconstraints.size())-1); ic >= 0 ; ic--)
+		{
+			// skip computations if constraint not active.
+			if (mconstraints[ic]->IsActive())
+			{
+
+				// compute residual  c_i = [Cq_i]*q + b_i + cfm_i*l_i
+				double mresidual = mconstraints[ic]->Compute_Cq_q() + mconstraints[ic]->Get_b_i()
+								 + mconstraints[ic]->Get_cfm_i() * mconstraints[ic]->Get_l_i();
+
+				// true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
+				double candidate_violation = fabs(mconstraints[ic]->Violation(mresidual));
+
+				// compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i + cfm_i*l_i )
+				double deltal = ( omega / mconstraints[ic]->Get_g_i() ) *
+								( -mresidual );
+
+				if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)
+				{
+					candidate_violation = 0;
+					// update:   lambda += delta_lambda;
+					old_lambda_friction[i_friction_comp] = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda_friction[i_friction_comp]  + deltal);
+					i_friction_comp++;
+					if (i_friction_comp==3)
+					{ 
+						mconstraints[ic]->Project(); // the N normal component will take care of N,U,V
+
+						double new_lambda_0 = mconstraints[ic+2]->Get_l_i() ;
+						double new_lambda_1 = mconstraints[ic+1]->Get_l_i() ;
+						double new_lambda_2 = mconstraints[ic+0]->Get_l_i() ;
+						// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+						if (this->shlambda!=1.0)
+						{
+							new_lambda_0 = shlambda*new_lambda_0 + (1.0-shlambda)*old_lambda_friction[0];
+							new_lambda_1 = shlambda*new_lambda_1 + (1.0-shlambda)*old_lambda_friction[1];
+							new_lambda_2 = shlambda*new_lambda_2 + (1.0-shlambda)*old_lambda_friction[2];
+							mconstraints[ic-2]->Set_l_i(new_lambda_0);
+							mconstraints[ic-1]->Set_l_i(new_lambda_1);
+							mconstraints[ic-0]->Set_l_i(new_lambda_2);
+						}
+						double true_delta_0 = new_lambda_0 - old_lambda_friction[0];
+						double true_delta_1 = new_lambda_1 - old_lambda_friction[1];
+						double true_delta_2 = new_lambda_2 - old_lambda_friction[2];
+						mconstraints[ic+2]->Increment_q(true_delta_0);
+						mconstraints[ic+1]->Increment_q(true_delta_1);
+						mconstraints[ic+0]->Increment_q(true_delta_2);
+
+						candidate_violation = fabs(ChMin(0.0,mresidual));
+
+						if (this->record_violation_history)
+						{
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_0));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_1));
+							maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta_2));
+						}
+						i_friction_comp =0;
+					}
+				} 
+				else
+				{
+					// update:   lambda += delta_lambda;
+					double old_lambda = mconstraints[ic]->Get_l_i();
+					mconstraints[ic]->Set_l_i( old_lambda + deltal);
+
+					// If new lagrangian multiplier does not satisfy inequalities, project
+					// it into an admissible orthant (or, in general, onto an admissible set)
+					mconstraints[ic]->Project();
+
+					// After projection, the lambda may have changed a bit..
+					double new_lambda = mconstraints[ic]->Get_l_i() ;
+
+					// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+					if (this->shlambda!=1.0)
+					{
+						new_lambda = shlambda*new_lambda + (1.0-shlambda)*old_lambda;
+						mconstraints[ic]->Set_l_i(new_lambda);
+					}
+
+					double true_delta = new_lambda - old_lambda;
+
+					// For all items with variables, add the effect of incremented
+					// (and projected) lagrangian reactions:
+					mconstraints[ic]->Increment_q(true_delta);
+
+					if (this->record_violation_history)
+						maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta));  
+				}
+				
+				maxviolation = ChMax(maxviolation, fabs(candidate_violation));
+			
+			} // end IsActive()
+		
+		} // end loop on constraints
+ 
+		// For recording into violation history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxviolation, maxdeltalambda, iter);
+
+		// Terminate the loop if violation in constraints has been succesfully limited.
+		if (maxviolation < tolerance)
+			break;	
+
+		iter++;
+	}
+ 
+	return maxviolation;
+
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.h b/SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.h
new file mode 100644
index 0000000..5b1eeb0
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpIterativeSymmSOR.h
@@ -0,0 +1,107 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPITERATIVESYMMSOR_H
+#define CHLCPITERATIVESYMMSOR_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpIterativeSOR.h
+//
+//   An iterative VI solver based on symmetric projective
+//   fixed point method, with overrelaxation
+//   and immediate variable update as in SSOR methods.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+
+/// An iterative LCP solver based on symmetric projective
+/// fixed point method, with overrelaxation
+/// and immediate variable update as in SSOR methods.
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpIterativeSymmSOR : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpIterativeSymmSOR(
+				int mmax_iters=50,      ///< max.number of iterations
+				bool mwarm_start=false,	///< uses warm start?
+				double mtolerance=0.0,  ///< tolerance for termination criterion
+				double momega=1.0       ///< overrelaxation criterion
+				)  
+			: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance, momega) 
+			{};
+				
+	virtual ~ChLcpIterativeSymmSOR() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				);
+
+
+				/// Set the overrelaxation factor, as in SOR methods. This
+				/// factor may accelerate convergence if greater than 1. Optimal 
+				/// value depends on the type of problem and it may be difficult 
+				/// to extimate. 
+				/// Default=1. Value clamped if less than 0.
+	//void   SetOmega(double mval) {if (mval>0.) omega= mval;}
+	//double GetOmega() {return omega;}
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeSymmSOR.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpKstiffness.h b/SRC/ChronoEngine/lcp/ChLcpKstiffness.h
new file mode 100644
index 0000000..eac53cb
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpKstiffness.h
@@ -0,0 +1,126 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPKSTIFFNESS_H
+#define CHLCPKSTIFFNESS_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpKstiffness.h
+//
+//    Base class for representing a block-sparse stiffness
+//   matrix between some variables in a VI problem.
+//   Used for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+#include "core/ChMatrix.h"
+#include "core/ChSpmatrix.h"
+#include "lcp/ChLcpVariables.h"
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  Base class for representing items which introduce block-sparse
+/// 'stiffness matrices', that is blocks that connect some 'variables'
+/// and build a matrix K in a sparse variational inequality VI(Z*x-d,K):
+///
+///  | M+K -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq   -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M+K  Cq'|*| q|-| f|=|0|  
+///                                           |Cq    E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+/// Note that 'stiffness' blocks do not necessarily have a physical 
+/// interpretation as stiffness, for example they can represent hessians.
+/// Note that all stiffness blocks in K, all masses and constraint
+/// jacobians Cq are not really assembled in large matrices, so to
+/// exploit sparsity).
+
+
+class ChApi ChLcpKstiffness
+{
+	CH_RTTI_ROOT(ChLcpKstiffness)
+
+private:
+			//
+			// DATA
+			//
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+	ChLcpKstiffness()
+				{
+				}
+
+	virtual ~ChLcpKstiffness()
+				{
+				};
+
+
+			//
+			// FUNCTIONS
+			//
+				/// Returns the number of referenced ChLcpVariables items
+	virtual unsigned int GetNvars() const =0;
+
+
+				/// Access the K stiffness matrix as a single block,
+				/// referring only to the referenced ChVariable objects 
+	virtual ChMatrix<double>* Get_K() =0;
+
+				/// Computes the product of the corresponding blocks in the 
+				/// system matrix (ie. the K matrix blocks) by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' and 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect.
+	virtual void MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect) = 0;
+
+				/// Add the diagonal of the stiffness matrix block(s) as a column vector to 'result'.
+				/// NOTE: the 'result' vector must already have the size of system unknowns, ie
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) as index.
+	virtual void DiagonalAdd(ChMatrix<double>& result) = 0;
+
+				/// Writes (and adds) the K matrix associated to these variables into 
+				/// a global 'storage' matrix, at the offsets of variables. 
+				/// Most solvers do not need this: the sparse 'storage' matrix is used for testing, for
+				/// direct solvers, for dumping full matrix to Matlab for checks, etc.
+	virtual void Build_K(ChSparseMatrix& storage, bool add= true) = 0;
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#endif  // END of ChLcpKstiffness.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.cpp b/SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.cpp
new file mode 100644
index 0000000..14be22d
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.cpp
@@ -0,0 +1,206 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpKstiffnessGeneric.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver 
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+#include "ChLcpKstiffnessGeneric.h" 
+
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpKstiffnessGeneric> a_registration_ChLcpKstiffnessGeneric;
+
+
+
+ChLcpKstiffnessGeneric& ChLcpKstiffnessGeneric::operator=(const ChLcpKstiffnessGeneric& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	//ChLcpKstiffness::operator=(other);
+
+	this->variables = other.variables;
+
+	if (other.K)
+	{
+		if (K==0)
+			K = new ChMatrixDynamic<double>;
+		K->CopyFromMatrix(*other.K);
+	}
+	else
+	{
+		if (K) delete K; K=NULL;
+	}
+	
+	return *this;
+}
+
+
+void  ChLcpKstiffnessGeneric::SetVariables(std::vector<ChLcpVariables*> mvariables)
+{
+	assert (mvariables.size() >0);
+
+	variables = mvariables;
+
+	// destroy the K matrix if needed
+	if (K) delete K; K=0;
+
+	int msize = 0;
+	for (unsigned int iv = 0; iv < variables.size(); iv++)
+		msize += variables[iv]->Get_ndof();
+	
+	// reallocate the K matrix 
+	K = new ChMatrixDynamic<double>(msize, msize);
+}
+
+
+void ChLcpKstiffnessGeneric::MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect) 
+{
+	assert(K);
+
+	int kio =0;
+	for (unsigned int iv = 0; iv< this->GetNvars(); iv++)
+	{
+		int io = this->GetVariableN(iv)->GetOffset();
+		int in = this->GetVariableN(iv)->Get_ndof();
+
+		int kjo =0;
+		for (unsigned int jv = 0; jv< this->GetNvars(); jv++)
+		{
+			int jo = this->GetVariableN(jv)->GetOffset();
+			int jn = this->GetVariableN(jv)->Get_ndof();
+	
+			// Multiply the iv,jv sub block of K
+			for (int r = 0; r< in; r++)
+			{
+				double tot = 0;
+				for (int c = 0; c< jn; c++)
+				{
+					tot += (*this->K)(kio+r,kjo+c) * vect(jo+c);
+				}
+				result(io+r) += tot;
+			}
+
+			kjo += jn;
+		}
+		kio += in;
+	}
+
+}
+
+
+void ChLcpKstiffnessGeneric::DiagonalAdd(ChMatrix<double>& result)  
+{
+	assert(result.GetColumns()==1);
+
+	int kio =0;
+	for (unsigned int iv = 0; iv< this->GetNvars(); iv++)
+	{
+		int io = this->GetVariableN(iv)->GetOffset();
+		int in = this->GetVariableN(iv)->Get_ndof();
+
+		for (int r = 0; r < in; r++)
+		{
+			//GetLog() << "Summing" << result(io+r) << " to " << (*this->K)(kio+r,kio+r) << "\n";
+			result(io+r) += (*this->K)(kio+r,kio+r);
+		}
+		kio += in;
+	}
+
+}
+
+
+void ChLcpKstiffnessGeneric::Build_K(ChSparseMatrix& storage, bool add)
+{
+	if (!K) 
+		return;
+
+	int kio =0;
+	for (unsigned int iv = 0; iv< this->GetNvars(); iv++)
+	{
+		int io = this->GetVariableN(iv)->GetOffset();
+		int in = this->GetVariableN(iv)->Get_ndof();
+
+		int kjo =0;
+		for (unsigned int jv = 0; jv< this->GetNvars(); jv++)
+		{
+			int jo = this->GetVariableN(jv)->GetOffset();
+			int jn = this->GetVariableN(jv)->Get_ndof();
+			if (add)
+				storage.PasteSumClippedMatrix(this->K, kio, kjo, in, jn,  io,jo);
+			else
+				storage.PasteClippedMatrix   (this->K, kio, kjo, in, jn,  io,jo);
+			kjo += jn;
+		}
+		kio += in;
+	}
+}
+
+
+
+/*
+void ChLcpKstiffnessGeneric::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLcpKstiffness::StreamOUT(mstream);
+
+		// stream out all member data
+	// NOTHING INTERESTING TO SERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream << Cq_a;
+	// mstream << Cq_b;
+}
+ 
+
+
+
+void ChLcpKstiffnessGeneric::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLcpKstiffness::StreamIN(mstream);
+
+		// stream in all member data
+	// NOTHING INTERESTING TO DESERIALIZE (the Cq jacobians are not so
+	// important to waste disk space.. they may be recomputed run-time,
+	// and pointers to variables must be rebound in run-time.)
+	// mstream >> Cq_a;
+	// mstream >> Cq_b;
+}
+*/
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.h b/SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.h
new file mode 100644
index 0000000..ebf4582
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpKstiffnessGeneric.h
@@ -0,0 +1,159 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPKSTIFFNESSGENERIC_H
+#define CHLCPKSTIFFNESSGENERIC_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpKstiffnessGeneric.h
+//
+//    Base class for representing a block-sparse stiffness
+//   matrix between N vector-variables in a VI problem
+//   Used for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "lcp/ChLcpKstiffness.h"
+
+
+namespace chrono
+{
+
+/// Class that represent nxn sparse blocks to put into K global
+/// matrix, that is blocks that connect N 'variables'
+/// and build a matrix K in a sparse variational inequality VI(Z*x-d,K):
+///
+///  | M+K -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq   -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M+K  Cq'|*| q|-| f|=|0|  
+///                                           |Cq    E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+/// Note that 'stiffness' blocks do not necessarily have a physical 
+/// interpretation as stiffness, for example they can represent hessians.
+/// Note that all stiffness blocks in K, all masses and constraint
+/// jacobians Cq are not really assembled in large matrices, so to
+/// exploit sparsity).
+
+
+class ChApi ChLcpKstiffnessGeneric : public ChLcpKstiffness
+{
+	CH_RTTI(ChLcpKstiffnessGeneric, ChLcpKstiffness)
+
+private:
+			//
+			// DATA
+			//
+
+	ChMatrixDynamic<double>* K;
+
+	std::vector<ChLcpVariables*> variables;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpKstiffnessGeneric()
+				{
+					K=0;
+				}
+
+	ChLcpKstiffnessGeneric(std::vector<ChLcpVariables*> mvariables)
+				{
+					K=0;
+					this->SetVariables(mvariables);
+				}
+
+	ChLcpKstiffnessGeneric(ChLcpVariables* mvariableA, ChLcpVariables* mvariableB)
+				{
+					K=0;
+					std::vector<ChLcpVariables*> mvars;
+					mvars.push_back(mvariableA);
+					mvars.push_back(mvariableB);
+					this->SetVariables(mvars);
+				}
+
+	virtual ~ChLcpKstiffnessGeneric()
+				{
+					if (K) delete K; K=0;
+				};
+
+	
+				/// Assignment operator: copy from other object
+	ChLcpKstiffnessGeneric& operator=(const ChLcpKstiffnessGeneric& other);
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Set references to the constrained objects, each of ChLcpVariables type,
+				/// automatically creating/resizing K matrix if needed.
+	void SetVariables(std::vector<ChLcpVariables*> mvariables);
+
+				/// Returns the number of referenced ChLcpVariables items
+	virtual unsigned int GetNvars() const {return variables.size();}
+
+				/// Access the m-th vector variable object
+	virtual ChLcpVariables* GetVariableN(unsigned int m_var) {return variables[m_var];}
+
+
+
+				/// Access the K stiffness matrix as a single block,
+				/// referring only to the referenced ChVariable objects 
+	virtual ChMatrix<double>* Get_K()
+				{
+					return K;
+				}
+
+				/// Computes the product of the corresponding blocks in the 
+				/// system matrix (ie. the K matrix blocks) by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' and 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect.
+	virtual void MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect);
+
+				/// Add the diagonal of the stiffness matrix block(s) as a column vector to 'result'.
+				/// NOTE: the 'result' vector must already have the size of system unknowns, ie
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) as index.
+	virtual void DiagonalAdd(ChMatrix<double>& result);
+
+				/// Writes the K matrix associated to these variables into 
+				/// a global 'storage' matrix, at the offsets of variables. 
+				/// Most solvers do not need this: the sparse 'storage' matrix is used for testing, for
+				/// direct solvers, for dumping full matrix to Matlab for checks, etc.
+	virtual void Build_K(ChSparseMatrix& storage, bool add=true);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#endif  // END of ChLcpKstiffnessGeneric.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpSimplexSolver.cpp b/SRC/ChronoEngine/lcp/ChLcpSimplexSolver.cpp
new file mode 100644
index 0000000..7c3b1e1
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSimplexSolver.cpp
@@ -0,0 +1,217 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpSimplexSolver.cpp
+//
+//     ***OBSOLETE****
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpSimplexSolver.h"
+#include "core/ChSpmatrix.h"
+ 
+ 
+namespace chrono 
+{
+
+ChLcpSimplexSolver::ChLcpSimplexSolver()
+{
+	MC = new ChSparseMatrix(30,30); // at least as big as 30x30
+	X  = new ChMatrixDynamic<>(30,1); // at least as big as 30x1
+	B  = new ChMatrixDynamic<>(30,1); // at least as big as 30x1
+	unilaterals = 0;
+	truncation_step=0;
+}
+				
+ChLcpSimplexSolver::~ChLcpSimplexSolver()
+{
+	if (MC) delete MC; MC=0;
+	if (X) delete X; X=0;
+	if (B) delete B; B=0;
+	if (unilaterals) delete[]unilaterals;
+}
+ 
+
+
+double ChLcpSimplexSolver::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	double maxviolation = 0.;
+
+	// --
+	// Count active linear constraints..
+
+	int n_c=0;
+	int n_d=0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->IsActive())
+		  if (mconstraints[ic]->IsLinear())
+			if (mconstraints[ic]->IsUnilateral())
+				n_d++;
+			else
+				n_c++;
+	}
+
+	// --
+	// Count active variables, by scanning through all variable blocks..
+
+	int n_q=0;
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+	{
+		if (mvariables[iv]->IsActive())
+		{
+			mvariables[iv]->SetOffset(n_q);	// also store offsets in state and MC matrix
+			n_q += mvariables[iv]->Get_ndof();
+		}
+	} 
+
+	if (n_q==0) return 0;
+
+	int n_docs = n_c + n_d;
+	int n_vars = n_q + n_docs;
+	
+	// --
+	// Reset and resize (if needed) auxiliary vectors
+
+	MC->Reset(n_vars,n_vars);	// fast! Reset() method does not realloc if size doesn't change
+	B->Reset(n_vars,1);
+	X->Reset(n_vars,1);
+
+	if (unilaterals != 0)
+		{delete[]unilaterals; unilaterals = 0;}
+	if (n_d > 0)
+	{
+		unilaterals = new ChUnilateralData[n_d];
+	}
+
+
+
+	// -- 
+	// Fills the MC matrix and B vector, to pass to the sparse LCP simplex solver.
+	// The original problem, stated as
+	//  | M -Cq'|*|q|- | f|= |0| ,   c>=0, l>=0, l*c=0;
+    //  | Cq  0 | |l|  |-b|  |c|
+	// will be used with a small modification as:
+	//  | M  Cq'|*| q|- | f|= |0| ,   c>=0, l>=0, l*c=0;
+    //  | Cq  0 | |-l|  |-b|  |c|
+	// so that it uses a symmetric MC matrix (the LDL factorization at each
+	// pivot is happier:)
+
+	// .. fills M submasses and 'f' part of B
+	int s_q=0;
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+	{
+		if (mvariables[iv]->IsActive())
+		{
+			mvariables[iv]->Build_M(*MC, s_q, s_q);				// .. fills  MC (M part)
+			B->PasteMatrix(&mvariables[iv]->Get_fb(),s_q, 0);	// .. fills  B  (f part)
+
+			s_q += mvariables[iv]->Get_ndof();
+		}
+	}  
+	
+	// .. fills M jacobians (only lower part) and 'b' part of B
+	int s_c=0;
+	int s_d=0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->IsActive())
+		  if (mconstraints[ic]->IsLinear())
+			if (mconstraints[ic]->IsUnilateral())
+			{
+				mconstraints[ic]->Build_Cq (*MC, n_q + n_c + s_d);// .. fills MC (Cq  part)
+				mconstraints[ic]->Build_CqT(*MC, n_q + n_c + s_d);// .. fills MC (Cq' part)
+				B->SetElement(n_q + n_c + s_d, 0, 
+						-mconstraints[ic]->Get_b_i() );			// .. fills B  (c part)
+						unilaterals[s_d].status = CONSTR_UNILATERAL_OFF;
+				s_d++;
+			}
+			else
+			{
+				mconstraints[ic]->Build_Cq (*MC, n_q + s_c);
+				mconstraints[ic]->Build_CqT(*MC, n_q + s_c);
+				B->SetElement(n_q + s_c,       0,
+						-mconstraints[ic]->Get_b_i() );
+				s_c++;
+			}
+	}
+
+	// -- 
+	// Solve the LCP
+ 
+	MC->SolveLCP(B, X,
+				   n_c, n_d,
+				   truncation_step, 
+				   false,
+				   unilaterals);
+
+	// --
+	// Update results into variable-interface objects
+	s_q=0;
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+	{
+		if (mvariables[iv]->IsActive())
+		{
+			mvariables[iv]->Get_qb().PasteClippedMatrix(X, 
+						s_q,0, 
+						mvariables[iv]->Get_ndof(),1, 
+						0,0);
+			s_q += mvariables[iv]->Get_ndof();
+		}
+	}
+	 
+	// --
+	// Update results into constraint-interface objects 
+	s_c=0;
+	s_d=0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->IsActive())
+		  if (mconstraints[ic]->IsLinear())
+			if (mconstraints[ic]->IsUnilateral())
+			{   //(change sign of multipliers!)
+				mconstraints[ic]->Set_l_i( -X->GetElement(n_q + n_c + s_d , 0));
+				s_d++;
+			}
+			else
+			{   //(change sign of multipliers!)
+				mconstraints[ic]->Set_l_i( -X->GetElement(n_q + s_c ,  0));
+				s_c++;
+			}
+	}
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpSimplexSolver.h b/SRC/ChronoEngine/lcp/ChLcpSimplexSolver.h
new file mode 100644
index 0000000..48b9431
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSimplexSolver.h
@@ -0,0 +1,124 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPSIMPLEXSOLVER_H
+#define CHLCPSIMPLEXSOLVER_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpSimplexSolver.h
+//
+//     ***OBSOLETE****
+//
+//    A simplex (pivoting) method which solves LCP
+//   problems by activating/deactivating constraints
+//   and solving a linear problem each time (using a
+//   custom sparse solver)
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpDirectSolver.h"
+
+
+
+namespace chrono
+{
+
+// forward reference
+class ChSparseMatrix;
+class ChUnilateralData;
+
+///     ***OBSOLETE****
+///    A simplex (pivoting) method which solves LCP
+///   problems by activating/deactivating constraints
+///   and solving a linear problem each time (using a
+///   custom sparse solver)
+///    It is by far slower than iterative methods, but
+///   it gives an almost exact solution (within numerical 
+///   roundoff and accumulation errors, of course).
+///    It can handle redundant constraints.
+///    This solver must be used for mixed-linear
+///   complementarity problems (MLCP) in this
+///   form:
+///
+///    | M -Cq'|*|q|- | f|= |0| ,   c>=0, l>=0, l*c=0;
+///    | Cq  0 | |l|  |-b|  |c|
+///
+///   as arising in the solution of QP with
+///   inequalities or in multibody problems.
+
+
+class ChApi ChLcpSimplexSolver : public ChLcpDirectSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+	int truncation_step; // if 0 no effect, if >0 steps are truncated 
+	ChSparseMatrix* MC;  // the sparse matrix for direct solution [MC]X=B (auto fill)
+	ChMatrix<>* X;		 // the unknown vector (automatically filled) 
+	ChMatrix<>* B;		 // the known vector (automatically filled)
+	ChUnilateralData* unilaterals; // array with temporary info for pivoting
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpSimplexSolver();
+				
+	virtual ~ChLcpSimplexSolver();
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP, using the simplex method.
+				///  If you must solve many LCP problems with the same amount of
+				/// variables and constraints, we suggest you to use the same 
+				/// ChLcpSimplexSolver object, because it exploits coherency: avoids
+				/// reallocating the sparse matrix each time.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				);
+
+				/// Set truncation step (that is, the method stops anyway after
+				/// this amount of pivots in simplex explorations, even if the 
+				/// solution isn't reached). NOTE!! This limits cases with exponential 
+				/// complexity explosion, but premature termination can give _meaningless_
+				/// results (differently from premature termination of iterative methods).
+				/// For truncation step = 0 continue endlessly up to exact solution 
+				/// (default) 
+	void   SetTruncationStep(int mstep) {truncation_step= mstep;}
+	void   SetNoTruncation() {truncation_step=0;}
+	double GetTruncationStep() {return truncation_step;}
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpSimplexSolver.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpSolver.cpp b/SRC/ChronoEngine/lcp/ChLcpSolver.cpp
new file mode 100644
index 0000000..4e731fc
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSolver.cpp
@@ -0,0 +1,42 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpSolver.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include "ChLcpSolver.h"
+ 
+ 
+namespace chrono 
+{
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpSolver.h b/SRC/ChronoEngine/lcp/ChLcpSolver.h
new file mode 100644
index 0000000..671d3e5
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSolver.h
@@ -0,0 +1,110 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPSOLVER_H
+#define CHLCPSOLVER_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpSolver.h
+//
+//    Base class for all solvers aimed at solving
+//   LCP linear complementarity problems, as arising
+//   from QP optimization problems.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <vector>
+#include "ChLcpConstraint.h"
+#include "ChLcpVariables.h"
+#include "ChLcpSystemDescriptor.h"
+
+namespace chrono
+{
+
+///  Base class for solvers aimed at solving
+/// LCP linear complementarity problems arising
+/// from QP optimization problems.
+///  This class does nothing: it is up to inherited
+/// classes to implement specific solution methods,
+/// such as simplex, iterative SOR, etc.
+///  The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpSolver
+{
+public:
+			//
+			// DATA
+			//
+
+	bool verbose;
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpSolver() { verbose = false; };
+
+	virtual ~ChLcpSolver() {};
+
+			//
+			// FUNCTIONS
+			//
+
+			// --Following functions are generic interfaces to the LCP solver. The
+			//   Solve() function is a pure virtual method, so it MUST be implemented
+			//   by specialized child classes:
+
+				/// Performs the solution of the LCP.
+				/// You must provide a system description using ChLcpSystemDescriptor.
+				/// This function MUST be implemented in children classes, with specialized 
+				/// methods such as iterative schemes, simplex schemes, fixed point algorithms, etc.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	 
+				) = 0;
+
+
+			//
+			// Utility functions
+			//
+
+	void SetVerbose(bool mv) {this->verbose = mv;}
+	bool GetVerbose() {return this->verbose;}
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpSolver.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpSolverDEM.cpp b/SRC/ChronoEngine/lcp/ChLcpSolverDEM.cpp
new file mode 100644
index 0000000..55d9750
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSolverDEM.cpp
@@ -0,0 +1,156 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpSolverDEM.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+  
+   
+#include "ChLcpSolverDEM.h"
+
+
+namespace chrono
+{
+
+double ChLcpSolverDEM::Solve(
+					ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	 
+					)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = sysd.GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= sysd.GetVariablesList();
+
+	double maxviolation = 0.;
+	double maxdeltalambda = 0.;
+
+	// 1)  Update auxiliary data in all constraints before starting,
+	//     that is: g_i=[Cq_i]*[invM_i]*[Cq_i]' and  [Eq_i]=[invM_i]*[Cq_i]'
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+		mconstraints[ic]->Update_auxiliary();
+
+	// 2)  Compute, for all items with variables, the initial guess for
+	//     still unconstrained system:
+
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+	{
+		if (mvariables[iv]->IsActive())
+		{
+				mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb()); // q = [M]'*fb
+		}
+	}
+
+	// 3)  For all items with variables, add the effect of initial (guessed)
+	//     lagrangian reactions of contraints, if a warm start is desired.
+	//     Otherwise, if no warm start, simply resets initial lagrangians to zero.
+	if (warm_start)
+	{
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+			if (mconstraints[ic]->IsActive())
+				mconstraints[ic]->Increment_q(mconstraints[ic]->Get_l_i());
+	}
+	else
+	{
+		for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+			mconstraints[ic]->Set_l_i(0.);
+	}
+
+	// 4)  Perform the iteration loops
+	//
+
+
+	for (int iter = 0; iter < max_iterations; iter++)
+	{
+		// The iteration on all constraints
+		//
+
+		maxviolation = 0;
+		maxdeltalambda = 0;
+
+		for (unsigned int ic = 0; ic < mconstraints.size(); ic++)
+		{
+			// skip computations if constraint not active.
+			if (mconstraints[ic]->IsActive())
+			{
+				// compute residual  c_i = [Cq_i]*q + b_i
+				double mresidual = mconstraints[ic]->Compute_Cq_q() + mconstraints[ic]->Get_b_i();
+
+				// true constraint violation may be different from 'mresidual' (ex:clamped if unilateral)
+				double candidate_violation = fabs(mconstraints[ic]->Violation(mresidual));
+
+				// compute:  delta_lambda = -(omega/g_i) * ([Cq_i]*q + b_i )
+				double deltal = ( omega / mconstraints[ic]->Get_g_i() ) *
+								( -mresidual );
+
+				// update:   lambda += delta_lambda;
+				double old_lambda = mconstraints[ic]->Get_l_i();
+				mconstraints[ic]->Set_l_i( old_lambda + deltal);
+
+				// If new lagrangian multiplier does not satisfy inequalities, project
+				// it into an admissible orthant (or, in general, onto an admissible set)
+				mconstraints[ic]->Project();
+
+				// After projection, the lambda may have changed a bit..
+				double new_lambda = mconstraints[ic]->Get_l_i() ;
+
+				// Apply the smoothing: lambda= sharpness*lambda_new_projected + (1-sharpness)*lambda_old
+				if (this->shlambda!=1.0)
+				{
+					new_lambda = shlambda*new_lambda + (1.0-shlambda)*old_lambda;
+					mconstraints[ic]->Set_l_i(new_lambda);
+				}
+
+				double true_delta = new_lambda - old_lambda;
+
+				// For all items with variables, add the effect of incremented
+				// (and projected) lagrangian reactions:
+				mconstraints[ic]->Increment_q(true_delta);
+
+				if (this->record_violation_history)
+					maxdeltalambda = ChMax(maxdeltalambda, fabs(true_delta));
+
+
+				maxviolation = ChMax(maxviolation, fabs(candidate_violation));
+
+			}	// end IsActive()
+
+		}	// end loop on constraints
+
+		// For recording into violaiton history, if debugging
+		if (this->record_violation_history)
+			AtIterationEnd(maxviolation, maxdeltalambda, iter);
+
+		// Terminate the loop if violation in constraints has been succesfully limited.
+		if (maxviolation < tolerance)
+			break;
+
+	} // end iteration loop
+
+	return maxviolation;
+
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpSolverDEM.h b/SRC/ChronoEngine/lcp/ChLcpSolverDEM.h
new file mode 100644
index 0000000..23c0fdf
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSolverDEM.h
@@ -0,0 +1,98 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPSOLVERDEM_H
+#define CHLCPSOLVERDEM_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpSolverDEM.h
+//
+//  A solver for DEM type simulations, currently
+//  without any support for bilateral constraints.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "ChLcpIterativeSolver.h"
+
+
+namespace chrono
+{
+
+
+///  A penalty-based solver for complementarity problem
+/// as arising in DEM formulations.
+/// The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+
+class ChApi ChLcpSolverDEM : public ChLcpIterativeSolver
+{
+protected:
+			//
+			// DATA
+			//
+
+
+public:
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpSolverDEM(
+					int mmax_iters=50,      ///< max.number of iterations
+					bool mwarm_start=false,	///< uses warm start?
+					double mtolerance=0.0,  ///< tolerance for termination criterion
+					double momega=1.0       ///< overrelaxation criterion
+					)
+		: ChLcpIterativeSolver(mmax_iters,mwarm_start, mtolerance,momega)
+		{};
+				
+	virtual ~ChLcpSolverDEM() {};
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Performs the solution of the LCP.
+				/// \return  the maximum constraint violation after termination.
+
+	virtual double Solve(
+				ChLcpSystemDescriptor& sysd		///< system description with constraints and variables	
+				);
+
+
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpIterativeSOR.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.cpp b/SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.cpp
new file mode 100644
index 0000000..7b8c19c
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.cpp
@@ -0,0 +1,811 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpSystemDescriptor.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpSystemDescriptor.h"
+#include "ChLcpConstraintTwoFrictionT.h"
+#include "ChLcpConstraintTwoRollingN.h"
+#include "ChLcpConstraintTwoRollingT.h"
+
+ 
+namespace chrono 
+{
+
+#define CH_SPINLOCK_HASHSIZE 203
+
+ChLcpSystemDescriptor::ChLcpSystemDescriptor()
+{
+	vconstraints.clear();
+	vvariables.clear();
+	vstiffness.clear();
+	
+	n_q=0;
+	n_c=0;
+	freeze_count = false;
+
+	this->num_threads = CHOMPfunctions::GetNumProcs();
+
+	spinlocktable = new ChSpinlock[CH_SPINLOCK_HASHSIZE];
+};
+
+
+ChLcpSystemDescriptor::~ChLcpSystemDescriptor()
+{
+	vconstraints.clear();
+	vvariables.clear();
+	vstiffness.clear();
+
+	if (spinlocktable)
+		delete[] spinlocktable;
+	spinlocktable=0;
+
+};
+
+
+
+
+
+
+
+void ChLcpSystemDescriptor::ComputeFeasabilityViolation(
+				double& resulting_maxviolation,		///< gets the max constraint violation (either bi- and unilateral.)
+				double& resulting_lcpfeasability	///< gets the max feasability as max |l*c| , for unilateral only
+				)
+{
+	resulting_maxviolation = 0;
+	resulting_lcpfeasability = 0;
+
+	for (unsigned int ic = 0; ic < vconstraints.size(); ic++)
+	{
+		// the the residual of the constraint..
+		double mres_i = vconstraints[ic]->Compute_c_i();
+
+		double candidate_violation = fabs(vconstraints[ic]->Violation(mres_i));
+
+		if (candidate_violation > resulting_maxviolation)
+			resulting_maxviolation = candidate_violation;
+
+		if (vconstraints[ic]->IsUnilateral())
+		{
+			double candidate_feas = fabs( mres_i * vconstraints[ic]->Get_l_i() ); // =|c*l|
+			if (candidate_feas > resulting_lcpfeasability)
+				resulting_lcpfeasability = candidate_feas;
+		}
+
+	}
+}
+
+
+
+
+int ChLcpSystemDescriptor::CountActiveVariables()
+{
+	if (this->freeze_count) // optimization, avoid list count all times 
+		return n_q;
+
+	n_q=0;
+	for (unsigned int iv = 0; iv< vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+		{
+			vvariables[iv]->SetOffset(n_q);	// also store offsets in state and MC matrix
+			n_q += vvariables[iv]->Get_ndof();
+		}
+	}
+	return n_q;
+}
+
+				
+int ChLcpSystemDescriptor::CountActiveConstraints()
+{
+	if (this->freeze_count) // optimization, avoid list count all times 
+		return n_c;
+
+	n_c=0;
+	for (unsigned int ic = 0; ic< vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			vconstraints[ic]->SetOffset(n_c);	// also store offsets in state and MC matrix
+			n_c++;
+		}
+	}
+	return n_c;
+}
+
+
+void ChLcpSystemDescriptor::UpdateCountsAndOffsets()
+{
+	freeze_count = false;
+	CountActiveVariables();
+	CountActiveConstraints();
+	freeze_count = true;
+}
+
+
+
+void ChLcpSystemDescriptor::ConvertToMatrixForm (
+								  ChSparseMatrix* Cq, 
+								  ChSparseMatrix* M, 
+								  ChSparseMatrix* E,  
+								  ChMatrix<>* Fvector,
+								  ChMatrix<>* Bvector,
+								  ChMatrix<>* Frict,  
+								bool only_bilaterals, 
+								bool skip_contacts_uv)
+{
+	std::vector<ChLcpConstraint*>& mconstraints = this->GetConstraintsList();
+	std::vector<ChLcpVariables*>&  mvariables	= this->GetVariablesList();
+
+	// Count bilateral and other constraints.. (if wanted, bilaterals only)
+
+	int mn_c=0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->IsActive())
+		  if (! ((mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) && only_bilaterals))
+			  if ( ! (( dynamic_cast<ChLcpConstraintTwoFrictionT*> (mconstraints[ic])) && skip_contacts_uv))
+			  {
+				mn_c++;
+			  }
+	}
+
+	// Count active variables, by scanning through all variable blocks,
+	// and set offsets
+
+	n_q = this->CountActiveVariables();
+
+	
+	// Reset and resize (if needed) auxiliary vectors
+
+	if (Cq) 
+		Cq->Reset(mn_c, n_q);
+	if (M)
+		M->Reset (n_q, n_q);
+	if (E)
+		E->Reset (mn_c, mn_c);
+	if (Fvector)
+		Fvector->Reset (n_q, 1);
+	if (Bvector)
+		Bvector->Reset (mn_c, 1);
+	if (Frict)
+		Frict->Reset (mn_c, 1);
+
+	// Fills M submasses and 'f' vector,
+	// by looping on variables
+	int s_q=0;
+	for (unsigned int iv = 0; iv< mvariables.size(); iv++)
+	{
+		if (mvariables[iv]->IsActive())
+		{
+			if (M)
+				mvariables[iv]->Build_M(*M, s_q, s_q);				// .. fills  M 
+			if (Fvector)
+				Fvector->PasteMatrix(&vvariables[iv]->Get_fb(), s_q, 0);// .. fills  'f' 
+			s_q += mvariables[iv]->Get_ndof();
+		}
+	}  
+	
+	// If some stiffness / hessian matrix has been added to M ,
+	// also add it to the sparse M
+	int s_k=0;
+	for (unsigned int ik = 0; ik< this->vstiffness.size(); ik++)
+	{
+		this->vstiffness[ik]->Build_K(*M, true); 
+	} 
+
+	// Fills Cq jacobian, E 'compliance' matrix , the 'b' vector and friction coeff.vector, 
+	// by looping on constraints
+	int s_c=0;
+	for (unsigned int ic = 0; ic< mconstraints.size(); ic++)
+	{
+		if (mconstraints[ic]->IsActive())
+		  if (! ((mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) && only_bilaterals))
+			  if ( ! (( dynamic_cast<ChLcpConstraintTwoFrictionT*> (mconstraints[ic])) && skip_contacts_uv))
+			  {
+					if (Cq)
+						mconstraints[ic]->Build_Cq (*Cq, s_c);// .. fills Cq
+					if (E)
+						E->SetElement(s_c,s_c, - mconstraints[ic]->Get_cfm_i() ); // .. fills E ( = - cfm )
+					if (Bvector)
+						(*Bvector)(s_c) = mconstraints[ic]->Get_b_i(); // .. fills 'b'   
+					if (Frict) // .. fills vector of friction coefficients
+					{
+						(*Frict)(s_c) = -2; // mark with -2 flag for bilaterals (default)
+						if (ChLcpConstraintTwoContactN* mcon = dynamic_cast<ChLcpConstraintTwoContactN*> (mconstraints[ic])) 
+							(*Frict)(s_c) = mcon->GetFrictionCoefficient(); // friction coeff only in row of normal component 
+						if (ChLcpConstraintTwoFrictionT* mcon = dynamic_cast<ChLcpConstraintTwoFrictionT*> (mconstraints[ic])) 
+							(*Frict)(s_c) = -1; // mark with -1 flag for rows of tangential components
+					}
+					s_c++;
+			  }
+	}
+
+}
+
+void  ChLcpSystemDescriptor::BuildMatrices (ChSparseMatrix* Cq,
+								ChSparseMatrix* M,	
+								bool only_bilaterals, 
+								bool skip_contacts_uv)
+{
+	this->ConvertToMatrixForm(Cq,M,0,0,0,0,only_bilaterals,skip_contacts_uv);
+}
+void  ChLcpSystemDescriptor::BuildVectors (ChSparseMatrix* f,
+								ChSparseMatrix* b,	
+								bool only_bilaterals, 
+								bool skip_contacts_uv)
+{
+	this->ConvertToMatrixForm(0,0,0,f,b,0,only_bilaterals,skip_contacts_uv);
+}
+
+
+
+int ChLcpSystemDescriptor::BuildFbVector(
+								ChMatrix<>& Fvector	///< matrix which will contain the entire vector of 'f'
+						)
+{
+	n_q=CountActiveVariables();
+	Fvector.Reset(n_q,1);		// fast! Reset() method does not realloc if size doesn't change
+
+	// Fills the 'f' vector
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+		{
+			Fvector.PasteMatrix(&vvariables[iv]->Get_fb(), vvariables[iv]->GetOffset(), 0);
+		}
+	}
+	return  this->n_q;
+}
+
+int ChLcpSystemDescriptor::BuildBiVector(
+								ChMatrix<>& Bvector	///< matrix which will contain the entire vector of 'b'
+						)
+{
+	n_c=CountActiveConstraints();
+	Bvector.Resize(n_c, 1);
+	
+	// Fill the 'b' vector
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		/*
+		int rank = CHOMPfunctions::GetThreadNum();
+		int count = CHOMPfunctions::GetNumThreads();
+		GetLog() << "      BuildFbVector thread " << rank << " on " << count << "\n";
+		GetLog().Flush();
+		*/
+		if (vconstraints[ic]->IsActive())
+		{
+			Bvector(vconstraints[ic]->GetOffset()) = vconstraints[ic]->Get_b_i();
+		}
+	}
+
+	return n_c;
+}
+
+
+int ChLcpSystemDescriptor::BuildDiVector(
+								ChMatrix<>& Dvector	
+						)
+{
+	n_q=CountActiveVariables();
+	n_c=CountActiveConstraints();
+
+	Dvector.Reset(n_q+n_c,1);		// fast! Reset() method does not realloc if size doesn't change
+
+	// Fills the 'f' vector part
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+		{
+			Dvector.PasteMatrix(&vvariables[iv]->Get_fb(), vvariables[iv]->GetOffset(), 0);
+		}
+	}
+	// Fill the '-b' vector (with flipped sign!)
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			Dvector(vconstraints[ic]->GetOffset() + n_q) = - vconstraints[ic]->Get_b_i();
+		}
+	}
+
+	return  n_q+n_c; 
+}
+
+int  ChLcpSystemDescriptor::BuildDiagonalVector(
+								ChMatrix<>& Diagonal_vect  	///< matrix which will contain the entire vector of terms on M and E diagonal
+							)
+{
+	n_q=CountActiveVariables();
+	n_c=CountActiveConstraints();
+
+	Diagonal_vect.Reset(n_q+n_c,1);		// fast! Reset() method does not realloc if size doesn't change
+
+	// Fill the diagonal values given by stiffness blocks, if any
+	// (This cannot be easily parallelized because of possible write concurrency).
+	for (int is = 0; is< (int)vstiffness.size(); is++)
+	{
+		vstiffness[is]->DiagonalAdd(Diagonal_vect);
+	}
+
+	// Get the 'M' diagonal terms
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+		{
+			vvariables[iv]->DiagonalAdd(Diagonal_vect);
+		}
+	}
+
+	// Get the 'E' diagonal terms (note the sign: E_i = -cfm_i )
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			Diagonal_vect(vconstraints[ic]->GetOffset() + n_q) = - vconstraints[ic]->Get_cfm_i();
+		}
+	}
+	return n_q+n_c;
+}
+
+
+int ChLcpSystemDescriptor::FromVariablesToVector(	
+								ChMatrix<>& mvector,	
+								bool resize_vector
+								)
+{
+	// Count active variables and resize vector if necessary
+	if (resize_vector)
+	{
+		n_q= CountActiveVariables();
+		mvector.Resize(n_q, 1);
+	}
+
+	// Fill the vector
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+		{
+			mvector.PasteMatrix(&vvariables[iv]->Get_qb(), vvariables[iv]->GetOffset(), 0);
+		}
+	}
+
+	return  n_q;
+}
+
+		
+
+int ChLcpSystemDescriptor::FromVectorToVariables(
+								ChMatrix<>& mvector	
+								)
+{
+	#ifdef CH_DEBUG
+		n_q= CountActiveVariables();
+		assert(n_q == mvector.GetRows());
+		assert(mvector.GetColumns()==1);
+	#endif
+
+	// fetch from the vector
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+		{
+			vvariables[iv]->Get_qb().PasteClippedMatrix(&mvector, vvariables[iv]->GetOffset(), 0,  vvariables[iv]->Get_ndof(),1,  0,0);
+		}
+	}
+
+	return n_q;
+}
+
+
+
+int ChLcpSystemDescriptor::FromConstraintsToVector(	
+								ChMatrix<>& mvector,
+								bool resize_vector
+								)
+{
+	// Count active constraints and resize vector if necessary
+	if (resize_vector)
+	{
+		n_c=CountActiveConstraints();
+		mvector.Resize(n_c, 1);
+	}
+
+	// Fill the vector
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			mvector(vconstraints[ic]->GetOffset()) = vconstraints[ic]->Get_l_i();
+		}
+	}
+
+	return n_c;
+}
+
+		
+
+int ChLcpSystemDescriptor::FromVectorToConstraints(
+								ChMatrix<>& mvector	
+								)
+{
+	n_c=CountActiveConstraints();
+
+	#ifdef CH_DEBUG
+		assert(n_c == mvector.GetRows());
+		assert(mvector.GetColumns()==1);
+	#endif
+
+	// Fill the vector
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			vconstraints[ic]->Set_l_i( mvector(vconstraints[ic]->GetOffset()) );
+		}
+	}
+
+	return n_c;
+}
+
+
+int ChLcpSystemDescriptor::FromUnknownsToVector(	
+								ChMatrix<>& mvector,	
+								bool resize_vector
+								)
+{
+	// Count active variables & constraints and resize vector if necessary
+	n_q= CountActiveVariables();
+	n_c= CountActiveConstraints();
+
+	if (resize_vector)
+	{
+		mvector.Resize(n_q+n_c, 1);
+	}
+
+	// Fill the first part of vector, x.q ,with variables q
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+		{
+			mvector.PasteMatrix(&vvariables[iv]->Get_qb(), vvariables[iv]->GetOffset(), 0);
+		}
+	}
+	// Fill the second part of vector, x.l, with constraint multipliers -l (with flipped sign!)
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			mvector(vconstraints[ic]->GetOffset() + n_q) = -vconstraints[ic]->Get_l_i();
+		}
+	}
+
+	return  n_q+n_c;
+}
+
+		
+
+int ChLcpSystemDescriptor::FromVectorToUnknowns(
+								ChMatrix<>& mvector	
+								)
+{
+	n_q= CountActiveVariables();
+	n_c= CountActiveConstraints();
+
+	#ifdef CH_DEBUG
+		assert((n_q+n_c) == mvector.GetRows());
+		assert(mvector.GetColumns()==1);
+	#endif
+
+	// fetch from the first part of vector (x.q = q)
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		//int rank  = CHOMPfunctions::GetThreadNum();
+		//int count = CHOMPfunctions::GetNumThreads();
+		//GetLog() << "      FromVectorToUnknowns: thread " << rank << " on " << count << "\n";
+		//GetLog().Flush();
+
+		if (vvariables[iv]->IsActive())
+		{
+			vvariables[iv]->Get_qb().PasteClippedMatrix(&mvector, vvariables[iv]->GetOffset(), 0,  vvariables[iv]->Get_ndof(),1,  0,0);
+		}
+	}
+	// fetch from the second part of vector (x.l = -l), with flipped sign!
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			vconstraints[ic]->Set_l_i( - mvector( vconstraints[ic]->GetOffset() + n_q ));
+		}
+	}
+
+	return n_q+n_c;
+}
+
+
+
+
+
+
+void ChLcpSystemDescriptor::ShurComplementProduct(	
+								ChMatrix<>&	result,	
+								ChMatrix<>* lvector,
+								std::vector<bool>* enabled  
+								)
+{
+	#ifdef CH_DEBUG
+		assert(this->vstiffness.size() == 0); // currently, the case with ChLcpKstiffness items is not supported (only diagonal M is supported, no K)
+		int n_c=CountActiveConstraints();
+		assert(lvector->GetRows()   == n_c);
+		assert(lvector->GetColumns()== 1);
+		if (enabled) assert(enabled->size() == n_c);
+	#endif
+
+	result.Reset(n_c,1);  // fast! Reset() method does not realloc if size doesn't change
+
+
+	// Performs the sparse product    result = [N]*l = [ [Cq][M^(-1)][Cq'] - [E] ] *l
+	// in different phases:
+
+	// 1 - set the qb vector (aka speeds, in each ChLcpVariable sparse data) as zero
+
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+	{
+		if (vvariables[iv]->IsActive())
+			vvariables[iv]->Get_qb().FillElem(0);
+	}
+
+	// 2 - performs    qb=[M^(-1)][Cq']*l  by
+	//     iterating over all constraints (when implemented in parallel this
+	//     could be non-trivial because race conditions might occur -> reduction buffer etc.)
+	//     Also, begin to add the cfm term ( -[E]*l ) to the result.
+
+	//#pragma omp parallel for num_threads(this->num_threads)  ***NOT POSSIBLE!!! concurrent write to same q may happen
+	for (int ic = 0; ic < (int)vconstraints.size(); ic++)
+	{	
+		if (vconstraints[ic]->IsActive())
+		{
+			int s_c = vconstraints[ic]->GetOffset();
+
+			bool process=true;
+			if (enabled)
+				if ((*enabled)[s_c]==false)
+					process = false;
+
+			if (process) 
+			{
+				double li;
+				if (lvector)
+					li = (*lvector)(s_c,0);
+				else
+					li = vconstraints[ic]->Get_l_i();
+
+				// Compute qb += [M^(-1)][Cq']*l_i
+				//  NOTE! parallel update to same q data, risk of collision if parallel!!
+				vconstraints[ic]->Increment_q(li);	// <----!!!  fpu intensive
+
+				// Add constraint force mixing term  result = cfm * l_i = -[E]*l_i
+				result(s_c,0) =  vconstraints[ic]->Get_cfm_i() * li;
+
+			}
+
+		}
+	}
+
+	// 3 - performs    result=[Cq']*qb    by
+	//     iterating over all constraints 
+
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic < (int)vconstraints.size(); ic++)
+	{	
+		if (vconstraints[ic]->IsActive())
+		{
+			bool process=true;
+			if (enabled)
+				if ((*enabled)[vconstraints[ic]->GetOffset()]==false)
+					process = false;
+			
+			if (process) 
+				result(vconstraints[ic]->GetOffset(),0)+= vconstraints[ic]->Compute_Cq_q();	// <----!!!  fpu intensive
+			else
+				result(vconstraints[ic]->GetOffset(),0)= 0; // not enabled constraints, just set to 0 result 
+		}
+	}
+
+
+}
+
+
+
+
+void ChLcpSystemDescriptor::SystemProduct(	
+								ChMatrix<>&	result,			///< matrix which contains the result of matrix by x 
+								ChMatrix<>* x		        ///< optional matrix with the vector to be multiplied (if null, use current l_i and q)
+								// std::vector<bool>* enabled=0 ///< optional: vector of enable flags, one per scalar constraint. true=enable, false=disable (skip)
+								)
+{
+	n_q = this->CountActiveVariables();
+	n_c = this->CountActiveConstraints();
+
+	ChMatrix<>* x_ql = 0;
+
+	ChMatrix<>* vect;
+
+	if (x)
+	{
+		#ifdef CH_DEBUG
+			assert(x->GetRows()   == n_q+n_c);
+			assert(x->GetColumns()== 1);
+		#endif
+		vect = x;
+	}
+	else
+	{
+		x_ql = new ChMatrixDynamic<double>(n_q+n_c,1);
+		vect = x_ql;
+		this->FromUnknownsToVector(*vect);
+	}
+
+	result.Reset(n_q+n_c,1); // fast! Reset() method does not realloc if size doesn't change
+
+	// 1) First row: result.q part =  [M + K]*x.q + [Cq']*x.l
+
+	// 1.1)  do  M*x.q
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int iv = 0; iv< (int)vvariables.size(); iv++)
+		if (vvariables[iv]->IsActive())
+		{
+			vvariables[iv]->MultiplyAndAdd(result,*x);
+		}
+
+	// 1.2)  add also K*x.q  (NON straight parallelizable - risk of concurrency in writing)
+	for (int ik = 0; ik< (int)vstiffness.size(); ik++)
+	{
+		vstiffness[ik]->MultiplyAndAdd(result,*x);
+	}
+
+	// 1.3)  add also [Cq]'*x.l  (NON straight parallelizable - risk of concurrency in writing)
+	for (int ic = 0; ic < (int)vconstraints.size(); ic++)
+	{	
+		if (vconstraints[ic]->IsActive())
+		{
+			vconstraints[ic]->MultiplyTandAdd(result,  (*x)(vconstraints[ic]->GetOffset()+n_q));
+		}
+	}
+
+	// 2) Second row: result.l part =  [C_q]*x.q + [E]*x.l
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic < (int)vconstraints.size(); ic++)
+	{	
+		if (vconstraints[ic]->IsActive())
+		{
+			int s_c = vconstraints[ic]->GetOffset() + n_q;
+			vconstraints[ic]->MultiplyAndAdd(result(s_c), (*x));     // result.l_i += [C_q_i]*x.q
+			result(s_c) -= vconstraints[ic]->Get_cfm_i()* (*x)(s_c); // result.l_i += [E]*x.l_i  NOTE:  cfm = -E
+		}
+	}		
+	
+
+
+	// if a temp vector has been created because x was not provided, then delete it
+	if (x_ql)
+		delete x_ql;
+}
+
+
+
+
+void ChLcpSystemDescriptor::ConstraintsProject(	
+								ChMatrix<>&	multipliers		///< matrix which contains the entire vector of 'l_i' multipliers to be projected
+								)
+{
+	this->FromVectorToConstraints(multipliers);	
+
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic < (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+				vconstraints[ic]->Project();
+	}
+
+	this->FromConstraintsToVector(multipliers,false);		
+}
+
+
+void ChLcpSystemDescriptor::UnknownsProject(	
+								ChMatrix<>&	mx		///< matrix which contains the entire vector of unknowns x={q,-l} (only the l part is projected)
+								)
+{
+	n_q= this->CountActiveVariables();
+
+	// vector -> constraints
+	// Fetch from the second part of vector (x.l = -l), with flipped sign!
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			vconstraints[ic]->Set_l_i( - mx( vconstraints[ic]->GetOffset() + n_q ));
+		}
+	}
+		
+	// constraint projection!
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic < (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+				vconstraints[ic]->Project();
+	}
+
+	// constraints -> vector
+	// Fill the second part of vector, x.l, with constraint multipliers -l (with flipped sign!)
+	#pragma omp parallel for num_threads(this->num_threads)
+	for (int ic = 0; ic< (int)vconstraints.size(); ic++)
+	{
+		if (vconstraints[ic]->IsActive())
+		{
+			mx( vconstraints[ic]->GetOffset() + n_q ) = - vconstraints[ic]->Get_l_i();
+		}
+	}	
+}
+
+
+
+
+void ChLcpSystemDescriptor::SetNumThreads(int nthreads) 
+{
+
+	if (nthreads == this->num_threads)
+		return;
+
+	this->num_threads = nthreads;
+
+	/* not needed?
+	if (locktable)
+		delete[] locktable;
+
+	locktable = new ChMutexSpinlock[100];
+	*/
+}
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.h b/SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.h
new file mode 100644
index 0000000..fb89598
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpSystemDescriptor.h
@@ -0,0 +1,410 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPSYSTEMDESCRIPTOR_H
+#define CHLCPSYSTEMDESCRIPTOR_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpSystemDescriptor.h
+//
+//    Base class for collecting objects inherited 
+//   from ChLcpConstraint, ChLcpVariables, ChLcpStiffness. 
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "lcp/ChLcpVariables.h"
+#include "lcp/ChLcpConstraint.h"
+#include "lcp/ChLcpKstiffness.h"
+#include <vector>
+#include "parallel/ChOpenMP.h"
+#include "parallel/ChThreadsSync.h"
+
+namespace chrono
+{
+
+
+/// Base class for collecting objects inherited from ChLcpConstraint ,
+/// ChLcpVariables and, optionally ChLcpKstiffness. These objects
+/// can be used to define a sparse representation of the system.
+///  The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, c \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+/// Optionally, also objects inherited from ChLcpKstiffness can be added 
+/// too, hence M becomes M+K (but not all solvers handle ChLcpKstiffness!)
+/// All LCP solvers require that the description of
+/// the system is passed by means of a ChLcpSystemDescriptor,
+/// where all constraints, variables, masses, known terms 
+///	(ex.forces) are represented as sparse data that
+/// are objects inherited from ChLcpConstraint or ChLcpVariables. 
+/// Within this default implementation, the ChLcpSystemDescriptor
+/// simply contains vectors with pointers to the variables
+/// and constraints, but more advanced implementation (ex. for
+/// supporting parallel GPU solvers) could store constraints
+/// and variables structures with more efficient data schemes.
+
+
+class ChApi ChLcpSystemDescriptor
+{
+
+protected:
+			//
+			// DATA
+			//
+		std::vector<ChLcpConstraint*> vconstraints;
+		std::vector<ChLcpVariables*>  vvariables;
+		std::vector<ChLcpKstiffness*>  vstiffness;
+		
+		int num_threads;
+
+		ChSpinlock* spinlocktable;
+
+private:
+		int n_q; // n.active variables
+		int n_c; // n.active constraints
+		bool freeze_count; // for optimizartions
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+	ChLcpSystemDescriptor();
+
+	virtual ~ChLcpSystemDescriptor();
+
+	
+			//
+			// DATA MANAGEMENT FUNCTIONS
+			//
+
+
+		/// Access the vector of constraints
+	std::vector<ChLcpConstraint*>& GetConstraintsList() {return vconstraints;};
+
+		/// Access the vector of variables
+	std::vector<ChLcpVariables*>& GetVariablesList() {return vvariables;};
+
+		/// Access the vector of stiffness matrix blocks
+	std::vector<ChLcpKstiffness*>& GetKstiffnessList() {return vstiffness;};
+
+
+		/// Begin insertion of items
+	virtual void BeginInsertion()
+					{
+						vconstraints.clear();
+						vvariables.clear();
+						vstiffness.clear();
+					}
+
+		/// Insert reference to a ChLcpConstraint object
+	virtual void InsertConstraint(ChLcpConstraint* mc) { vconstraints.push_back(mc); }
+
+		/// Insert reference to a ChLcpVariables object
+	virtual void InsertVariables(ChLcpVariables* mv) { vvariables.push_back(mv); }
+
+		/// Insert reference to a ChLcpKstiffness object (a piece of K matrix)
+	virtual void InsertKstiffness(ChLcpKstiffness* mk) { vstiffness.push_back(mk); }
+
+
+		/// End insertion of items
+	virtual void EndInsertion()
+					{
+						UpdateCountsAndOffsets();
+					}
+
+
+				/// Count & returns the scalar variables in the system (excluding ChLcpVariable objects
+				/// that have  IsActive() as false). Note: the number of scalar variables is not necessarily
+				/// the number of inserted ChLcpVariable objects, some could be inactive.
+				/// Note: this function also updates the offsets of all variables 
+				/// in 'q' global vector (see GetOffset() in ChLcpVariables).
+	virtual int CountActiveVariables();
+
+				/// Count & returns the scalar constraints in the system (excluding ChLcpConstraint objects
+				/// that have  IsActive() as false). 
+				/// Note: this function also updates the offsets of all constraints 
+				/// in 'l' global vector (see GetOffset() in ChLcpConstraint).
+	virtual int CountActiveConstraints();
+
+				/// Updates counts of scalar variables and scalar constraints,
+				/// if you added/removed some item or if you switched some active state,
+				/// otherwise CountActiveVariables() and CountActiveConstraints() might fail.
+	virtual void UpdateCountsAndOffsets();
+
+
+			//
+			// DATA <-> MATH.VECTORS FUNCTIONS
+			//
+
+				/// Get a vector with all the 'fb' known terms ('forces'etc.) associated to all variables,
+				/// ordered into a column vector. The column vector must be passed as a ChMatrix<>
+				/// object, which will be automatically reset and resized to the proper length if necessary.
+	virtual int BuildFbVector(
+								ChMatrix<>& Fvector 	///< matrix which will contain the entire vector of 'f'
+							);
+				/// Get a vector with all the 'bi' known terms ('constraint residuals' etc.) associated to all constraints,
+				/// ordered into a column vector. The column vector must be passed as a ChMatrix<>
+				/// object, which will be automatically reset and resized to the proper length if necessary.
+	virtual int BuildBiVector(
+								ChMatrix<>& Bvector  	///< matrix which will contain the entire vector of 'b'
+							);
+
+				/// Get the d vector = {f; -b} with all the 'fb' and 'bi' known terms, as in  Z*y-d
+				/// (it is the concatenation of BuildFbVector and BuildBiVector) The column vector must be passed as a ChMatrix<>
+				/// object, which will be automatically reset and resized to the proper length if necessary.
+	virtual int BuildDiVector(
+								ChMatrix<>& Dvector  	///< matrix which will contain the entire vector of {f;-b}
+							);
+
+				/// Get the D diagonal of the Z system matrix, as a single column vector (it includes all the diagonal
+				/// masses of M, and all the diagonal E (-cfm) terms).
+				/// The Diagonal_vect must already have the size of n. of unknowns, otherwise it will be resized if necessary).
+	virtual int BuildDiagonalVector(
+								ChMatrix<>& Diagonal_vect  	///< matrix which will contain the entire vector of terms on M and E diagonal
+							);
+
+
+				/// Using this function, one may get a vector with all the variables 'q'
+				/// ordered into a column vector. The column vector must be passed as a ChMatrix<>
+				/// object, which will be automatically reset and resized to the proper length if necessary
+				/// (but if you are sure that the vector has already the proper size, you can optimize
+				/// the performance a bit by setting resize_vector as false).
+				/// \return  the number of scalar variables (i.e. the rows of the column vector).
+	virtual int FromVariablesToVector(
+								ChMatrix<>& mvector,	///< matrix which will contain the entire vector of 'q'
+								bool resize_vector=true	///< if true the vector size will be checked & resized if necessary
+								);
+
+				/// Using this function, one may go in the opposite direction of the FromVariablesToVector()
+				/// function, i.e. one gives a vector with all the variables 'q' ordered into a column vector, and
+				/// the variables objects are updated according to these values.
+				/// NOTE!!! differently from  FromVariablesToVector(), which always works, this
+				/// function will fail if mvector does not match the amount and ordering of
+				/// the variable objects!!! (it is up to the user to check this!) btw: most often,
+				/// this is called after FromVariablesToVector() to do a kind of 'undo', for example.
+				/// \return  the number of scalar variables (i.e. the rows of the column vector).
+	virtual int FromVectorToVariables(
+								ChMatrix<>& mvector					///< matrix which contains the entire vector of 'q'
+								);
+
+
+				/// Using this function, one may get a vector with all the constraint reactions 'l_i'
+				/// ordered into a column vector. The column vector must be passed as a ChMatrix<>
+				/// object, which will be automatically reset and resized to the proper length if necessary
+				/// (but uf you are sure that the vector has already the proper size, you can optimize
+				/// the performance a bit by setting resize_vector as false).
+				/// Optionally, you can pass an 'enabled' vector of bools, that must have the same
+				/// length of the l_i reactions vector; constraints with enabled=false are not handled.
+				/// \return  the number of scalar constr.multipliers (i.e. the rows of the column vector).
+	virtual int FromConstraintsToVector(
+								ChMatrix<>& mvector,		///< matrix which will contain the entire vector of 'l_i'
+								bool resize_vector=true		///< if true the vector size will be checked & resized if necessary
+								);
+
+				/// Using this function, one may go in the opposite direction of the FromConstraintsToVector()
+				/// function, i.e. one gives a vector with all the constr.reactions 'l_i' ordered into a column vector, and
+				/// the constraint objects are updated according to these values.
+				/// Optionally, you can pass an 'enabled' vector of bools, that must have the same
+				/// length of the l_i reactions vector; constraints with enabled=false are not handled.
+				/// NOTE!!! differently from  FromConstraintsToVector(), which always works, this
+				/// function will fail if mvector does not match the amount and ordering of
+				/// the variable objects!!! (it is up to the user to check this!) btw: most often,
+				/// this is called after FromConstraintsToVector() to do a kind of 'undo', for example.
+				/// \return  the number of scalar constraint multipliers (i.e. the rows of the column vector).
+	virtual int FromVectorToConstraints(
+								ChMatrix<>& mvector			///< matrix which contains the entire vector of 'l_i'
+								);
+
+
+
+				/// Using this function, one may get a vector with all the unknowns x={q,l} i.e. q variables & l_i constr.
+				/// ordered into a column vector. The column vector must be passed as a ChMatrix<>
+				/// object, which will be automatically reset and resized to the proper length if necessary
+				/// (but if you are sure that the vector has already the proper size, you can optimize
+				/// the performance a bit by setting resize_vector as false).
+				/// \return  the number of scalar unknowns
+	virtual int FromUnknownsToVector(
+								ChMatrix<>& mvector,	///< matrix which will contain the entire vector x={q,l}
+								bool resize_vector=true	///< if true the vector size will be checked & resized if necessary
+								);
+
+				/// Using this function, one may go in the opposite direction of the FromUnknownsToVector()
+				/// function, i.e. one gives a vector with all the unknowns x={q,l} ordered into a column vector, and
+				/// the variables q and constr.multipliers l objects are updated according to these values.
+				/// NOTE!!! differently from  FromUnknownsToVector(), which always works, this
+				/// function will fail if mvector does not match the amount and ordering of
+				/// the variable and constraint objects!!! (it is up to the user to check this!)
+	virtual int FromVectorToUnknowns(
+								ChMatrix<>& mvector		///< matrix which contains the entire vector x={q,l}
+								);
+
+
+			//
+			// MATHEMATICAL OPERATIONS ON DATA
+			//
+
+				/// Performs the product of N, the Shur complement of the KKT matrix, by an 
+				/// l vector (if x not provided, use current lagrangian multipliers l_i), that is 
+				///    result = [N]*l = [ [Cq][M^(-1)][Cq'] - [E] ] * l
+				/// where [Cq] are the jacobians, [M] is the mass matrix, [E] is the matrix
+				/// of the optional cfm 'constraint force mixing' terms for compliant constraints.
+				/// The N matrix is not built explicitly, to exploit sparsity, it is described by the 
+				/// inserted constraints and inserted variables.
+				/// Optionally, you can pass an 'enabled' vector of bools, that must have the same
+				/// length of the l_i reactions vector; constraints with enabled=false are not handled.
+				/// NOTE! the 'q' data in the ChVariables of the system descriptor is changed by this
+				/// operation, so it may happen that you need to backup them via FromVariablesToVector()
+				/// NOTE! currently this function does NOT support the cases that use also ChLcpKstiffness
+				/// objects, because it would need to invert the global M+K, that is not diagonal,
+				/// for doing = [N]*l = [ [Cq][(M+K)^(-1)][Cq'] - [E] ] * l
+	virtual void ShurComplementProduct(	
+								ChMatrix<>&	result,			///< matrix which contains the result of  N*l_i 
+								ChMatrix<>* lvector,		///< optional matrix with the vector to be multiplied (if null, use current constr. multipliers l_i)
+								std::vector<bool>* enabled=0 ///< optional: vector of enable flags, one per scalar constraint. true=enable, false=disable (skip)
+								);
+
+
+				/// Performs the product of the entire system matrix (KKT matrix), by a vector x ={q,l} 
+				/// (if x not provided, use values in current lagrangian multipliers l_i 
+				/// and current q variables)
+				/// NOTE! the 'q' data in the ChVariables of the system descriptor is changed by this
+				/// operation, so it may happen that you need to backup them via FromVariablesToVector()
+	virtual void SystemProduct(	
+								ChMatrix<>&	result,			///< matrix which contains the result of matrix by x 
+								ChMatrix<>* x		        ///< optional matrix with the vector to be multiplied (if null, use current l_i and q)
+								// std::vector<bool>* enabled=0 ///< optional: vector of enable flags, one per scalar constraint. true=enable, false=disable (skip)
+								);
+
+
+				/// Performs projecton of constraint multipliers onto allowed set (in case
+				/// of bilateral constraints it does not affect multipliers, but for frictional 
+				/// constraints, for example, it projects multipliers onto the friction cones)
+				/// Note! the 'l_i' data in the ChConstraints of the system descriptor are changed
+				/// by this operation (they get the value of 'multipliers' after the projection), so 
+				/// it may happen that you need to backup them via FromConstraintToVector().
+	virtual void ConstraintsProject(	
+								ChMatrix<>&	multipliers		///< matrix which contains the entire vector of 'l_i' multipliers to be projected
+								);
+
+				/// As ConstraintsProject(), but instead of passing the l vector, the entire
+				/// vector of unknowns x={q,-l} is passed. 	
+				/// Note! the 'l_i' data in the ChConstraints of the system descriptor are changed
+				/// by this operation (they get the value of 'multipliers' after the projection), so 
+				/// it may happen that you need to backup them via FromConstraintToVector().
+	virtual void UnknownsProject(	
+								ChMatrix<>&	mx		///< matrix which contains the entire vector of unknowns x={q,-l} (only the l part is projected)
+								);
+
+
+
+
+				/// The following (obsolete) function may be called after a LCP solver's 'Solve()'
+				/// operation has been performed. This gives an extimate of 'how
+				/// good' the solver had been in finding the proper solution.
+				/// Resulting estimates are passed as references in member arguments.
+
+	virtual void ComputeFeasabilityViolation(
+					double& resulting_maxviolation,		///< gets the max constraint violation (either bi- and unilateral.)
+					double& resulting_lcpfeasability	///< gets the max feasability as max |l*c| , for unilateral only
+				);
+
+
+			//
+			// MISC
+			//
+
+				/// Set the number of threads (some operations like ShurComplementProduct
+				/// are CPU intensive, so they can be run in parallel threads).
+				/// By default, the number of threads is the same of max.available OpenMP cores
+	virtual void SetNumThreads(int nthreads);
+	virtual int  GetNumThreads() {return this->num_threads;}
+
+
+			//
+			// LOGGING/OUTPUT/ETC.
+			//
+
+				/// The following function may be used to create the Jacobian and the 
+				/// mass matrix of the variational problem in matrix form, by assembling all 
+				/// the jacobians of all the constraints/contacts, all the mass matrices, all vectors,
+				/// as they are _currently_ stored in the sparse data of all ChConstraint and ChVariables 
+				/// contained in this ChLcpSystemDescriptor. 
+				/// The matrices define the VI variational inequality:
+				///
+				///  | M -Cq'|*|q|- | f|= |0| , l \in Y (es friction cone), c \in normal cone to Y  
+				///  | Cq -E | |l|  |-b|  |c|    (case no friction: LCP c>=0, l>=0, l*c=0;)        
+				///                              (case only bilaterals: linear system, c=0)
+				///
+				/// also symmetrizable by flipping the sign of l_i terms:  | M  Cq'|*| q|- | f|= |0|  
+				///                                                        | Cq -E | |-l|  |-b|  |C|
+				/// Note 1: most often you'll call ConvertToMatrixForm() right after a dynamic simulation timestep,
+				///         because the system matrices are properly initialized,
+				/// Note 2: when using Anitescu default stepper, the 'f' vector contains forces*timestep = F*dt
+				/// Note 3: when using Anitescu default stepper, q represents the 'delta speed',
+				/// Note 4: when using Anitescu default stepper, b represents the dt/phi stabilization term.
+				///  This can be useful for debugging, data dumping, and similar purposes (most solvers avoid 
+				/// using these matrices, for performance), for example you will load these matrices in Matlab.
+				/// Optionally, tangential (u,v) contact jacobians may be skipped, or only bilaterals can be considered
+				/// The matrices and vectors are automatically resized if needed.
+	virtual void ConvertToMatrixForm 
+								 (ChSparseMatrix* Cq, ///< fill this system jacobian matrix, if not null
+								  ChSparseMatrix* M,  ///< fill this system mass matrix, if not null
+								  ChSparseMatrix* E,  ///< fill this system 'compliance' matrix , if not null
+								  ChMatrix<>* Fvector,///< fill this vector as the known term 'f', if not null
+								  ChMatrix<>* Bvector,///< fill this vector as the known term 'b', if not null
+								  ChMatrix<>* Frict,  ///< fill as a vector with friction coefficients (=-1 for tangent comp.; =-2 for bilaterals), if not null
+								bool only_bilaterals = false, 
+								bool skip_contacts_uv = false);
+
+
+
+				/// OBSOLETE. Kept only for backward compability. Use rather: ConvertToMatrixForm
+	virtual void BuildMatrices (ChSparseMatrix* Cq,
+								ChSparseMatrix* M,
+								bool only_bilaterals = false, 
+								bool skip_contacts_uv = false);
+				/// OBSOLETE. Kept only for backward compability. Use rather: ConvertToMatrixForm, or BuildFbVector or BuildBiVector
+	virtual void BuildVectors (ChSparseMatrix* f, 
+								ChSparseMatrix* b,	
+								bool only_bilaterals = false, 
+								bool skip_contacts_uv = false);
+
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariables.cpp b/SRC/ChronoEngine/lcp/ChLcpVariables.cpp
new file mode 100644
index 0000000..9c1f69a
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariables.cpp
@@ -0,0 +1,77 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpConstraint.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include "ChLcpVariables.h"
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono 
+{
+
+
+ChLcpVariables& ChLcpVariables::operator=(const ChLcpVariables& other)
+{
+	if (&other == this) return *this;
+
+	this->disabled = other.disabled;
+
+	if (other.qb)
+	{
+		if (qb==NULL)
+			qb = new ChMatrixDynamic<>;
+		qb->CopyFromMatrix(*other.qb);
+	}
+	else
+	{
+		if (qb) delete qb;
+		qb=NULL;
+	}
+
+	if (other.fb)
+	{
+		if (fb==NULL)
+			fb = new ChMatrixDynamic<>;
+		fb->CopyFromMatrix(*other.fb);
+	}
+	else
+	{
+		if (fb) delete fb;
+		fb=NULL;
+	}
+
+	this->ndof = other.ndof;
+	this->offset = other.offset;
+
+	return *this;
+}
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+//ChClassRegister<ChLcpVariables> a_registration_ChLcpVariables;
+
+
+
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariables.h b/SRC/ChronoEngine/lcp/ChLcpVariables.h
new file mode 100644
index 0000000..5805a9e
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariables.h
@@ -0,0 +1,240 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPVARIABLES_H
+#define CHLCPVARIABLES_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpVariables.h
+//
+//    Base class for representing a mass matrix and
+//   associate variables, that are building blocks 
+//   for describing the system. 
+//   Used for building sparse variational problems 
+//   (VI/CCP/LCP/linear problems) described by 
+//   a ChLcpSystemDescriptor
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+#include "core/ChMatrix.h"
+#include "core/ChSpmatrix.h"
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+
+///  Base class for representing LCP items which introduce
+/// 'variables', that is variables 'v' (and associated masses M)
+/// for a sparse representation of the problem.
+///
+///  The problem is described by a variational inequality VI(Z*x-d,K):
+///
+///  | M -Cq'|*|q|- | f|= |0| , l \in Y, C \in Ny, normal cone to Y  
+///  | Cq -E | |l|  |-b|  |c|    
+///
+/// Also Z symmetric by flipping sign of l_i: |M  Cq'|*| q|-| f|=|0|  
+///                                           |Cq  E | |-l| |-b| |c|
+/// * case linear problem:  all Y_i = R, Ny=0, ex. all bilaterals
+/// * case LCP: all Y_i = R+:  c>=0, l>=0, l*c=0
+/// * case CCP: Y_i are friction cones
+///
+/// Note, all masses and variables are assembled in
+/// huge matrices, but there's no need to really
+/// build such matrices, in order to exploit sparsity).
+///  
+///  Note: in sake of highest generalization, this base
+/// class does NOT include a mass submatrix (a sub part of the M
+/// matrix) but just declares methods such as Compute_invMb_v(),
+/// (which are used by iterative solvers) which MUST
+/// be implemented by child classes. This doing, some child 
+/// classes too may implement all three methods without needing to
+/// store entire mass submatrices, if possible, in sake of efficiency.
+
+
+
+class ChApi ChLcpVariables
+{
+	CH_RTTI_ROOT(ChLcpVariables)
+
+private:
+			//
+			// DATA
+			//
+				/// the variables (accelerations, speeds, etc. depending on the problem)
+	ChMatrix<>* qb;
+				/// the known vector (forces, or impulses, etc. depending on the problem)
+	ChMatrix<>* fb;
+				/// the number of degrees of freedom (number of contained scalar variables)
+	int ndof;
+				/// user activation/deactivation of variables
+	bool disabled;
+
+protected:
+				/// offset in global q state vector (needed by some solvers)
+	int offset;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+	ChLcpVariables()
+				{
+					disabled = false;
+					ndof = 0;
+					qb = fb = NULL;
+					offset=0;
+				}
+
+	ChLcpVariables(int m_ndof)
+				{
+					disabled = false;
+					ndof = m_ndof;
+					if (Get_ndof()>0) {
+						qb = new ChMatrixDynamic<>(Get_ndof(),1);
+						fb = new ChMatrixDynamic<>(Get_ndof(),1);
+					} else {
+						qb = fb = NULL;
+					}
+					offset=0;
+				};
+
+	virtual ~ChLcpVariables()
+				{
+					if (qb) delete qb;
+					if (fb) delete fb;
+				};
+
+
+				/// Assignment operator: copy from other object
+	ChLcpVariables& operator=(const ChLcpVariables& other);
+
+
+			//
+			// FUNCTIONS
+			//
+
+
+				/// Tells if the variables have been deactivated (these 'frozen',
+				/// variables won't be modified by the LCP system solver).
+	void SetDisabled(bool mdis) { disabled = mdis; }
+
+				/// Tells if the variables have been deactivated (these 'frozen',
+				/// variables won't be modified by the LCP system solver).
+	bool IsDisabled() {return disabled;}
+
+
+				/// Tells if these variables are currently active, in general,
+				/// that is tells if they must be included into the LCP system solver or not.
+	bool IsActive() { return !disabled;}
+
+
+				/// The number of scalar variables in the vector qb
+				/// (dof=degrees of freedom)
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes.
+	virtual int Get_ndof() {return ndof;};
+
+				/// Returns reference to qb, body-relative part of degrees
+				/// of freedom q in system:
+				///    | M -Cq'|*|q|- | f|= |0| ,  c>0, l>0, l*r=0;
+				///    | Cq  0 | |l|  |-b|  |c|
+	ChMatrix<>& Get_qb() {return *qb;};
+
+				/// Compute fb, body-relative part of known
+				/// vector f in system.
+				/// *** This function MAY BE OVERRIDDEN by specialized
+				/// inherited classes (example, for impulsive multibody simulation,
+				/// this may be fb=dt*Forces+[M]*previous_v ).
+				///  Another option is to set values into fb vectors, accessing
+				/// them by Get_fb() from an external procedure, for each body,
+				/// before starting the LCP solver.
+	virtual void Compute_fb() {/* do nothing */};
+
+				/// Returns reference to fb, body-relative part of known
+				/// vector f in system.
+				///    | M -Cq'|*|q|- | f|= |0| ,  c>0, l>0, l*r=0;
+				///    | Cq  0 | |l|  |-b|  |c|
+				/// This function can be used to set values of fb vector
+				/// before starting the LCP solver.
+	ChMatrix<>& Get_fb() {return *fb;}
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and store in result: result = [invMb]*vect
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes
+	virtual void Compute_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect) = 0;
+	virtual void Compute_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect) = 0;
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and increment result: result += [invMb]*vect
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes
+	virtual void Compute_inc_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect) = 0;
+	virtual void Compute_inc_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect) = 0;
+
+				/// Computes the product of the mass matrix by a
+				/// vector, and increment result: result = [Mb]*vect
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes
+	virtual void Compute_inc_Mb_v(ChMatrix<float>& result, const ChMatrix<float>& vect) = 0;
+	virtual void Compute_inc_Mb_v(ChMatrix<double>& result, const ChMatrix<double>& vect) = 0;
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix (ie. the mass matrix) by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' and 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offset (that must be already updated) to know the 
+				/// indexes in result and vect.
+	virtual void MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect) const = 0;
+
+				/// Add the diagonal of the mass matrix (as a column vector) to 'result'.
+				/// NOTE: the 'result' vector must already have the size of system unknowns, ie
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offset (that must be already updated) as index.
+	virtual void DiagonalAdd(ChMatrix<double>& result) const = 0;
+
+				/// Build the mass submatrix (for these variables) storing
+				/// it in 'storage' sparse matrix, at given column/row offset.
+				/// Most iterative solvers don't need to know this matrix explicitly.
+				/// *** This function MUST BE OVERRIDDEN by specialized
+				/// inherited classes
+	virtual void Build_M(ChSparseMatrix& storage, int insrow, int inscol) = 0;
+
+				/// Set offset in global q vector (set automatically by ChLcpSystemDescriptor)
+	void SetOffset(int moff) {offset = moff;}
+				/// Get offset in global q vector 
+	int GetOffset() {return offset;}
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  // END of ChLcpVariables.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesBody.cpp b/SRC/ChronoEngine/lcp/ChLcpVariablesBody.cpp
new file mode 100644
index 0000000..2e5419c
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesBody.cpp
@@ -0,0 +1,56 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpVariablesBody.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include "ChLcpVariablesBody.h"
+ 
+
+namespace chrono 
+{
+
+
+
+ChLcpVariablesBody& ChLcpVariablesBody::operator=(const ChLcpVariablesBody& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpVariables::operator=(other);
+
+	// copy class data
+	user_data = other.user_data;
+
+	return *this;
+}
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChLcpVariablesBody> a_registration_ChLcpVariablesBody;
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesBody.h b/SRC/ChronoEngine/lcp/ChLcpVariablesBody.h
new file mode 100644
index 0000000..5d15b39
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesBody.h
@@ -0,0 +1,112 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPVARIABLESBODY_H
+#define CHLCPVARIABLESBODY_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpVariablesBody.h
+//
+//    Specialized class for representing a mass matrix
+//   and associate variables (6 element vector, ex.speed)
+//   for a 3D rigid body.
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpVariables.h"
+
+
+namespace chrono
+{
+
+///    Specialized class for representing a 6-DOF item for a
+///   LCP system, that is a 3D rigid body, with mass matrix and
+///   associate variables (a 6 element vector, ex.speed)
+///    This is an abstract class, specialized for example in 
+///   ChLcpVariablesBodyOwnMass and ChLcpVariablesBodySharedMass.
+
+class ChApi ChLcpVariablesBody :  public ChLcpVariables
+{
+	CH_RTTI(ChLcpVariablesBody, ChLcpVariables)
+
+private:
+			//
+			// DATA		//
+
+
+			void* user_data;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpVariablesBody() : ChLcpVariables(6)
+				{
+					user_data = 0;
+				};
+
+	virtual ~ChLcpVariablesBody()
+				{
+				};
+
+
+				/// Assignment operator: copy from other object
+	ChLcpVariablesBody& operator=(const ChLcpVariablesBody& other);
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Get the mass associated with translation of body
+	virtual double	GetBodyMass() =0;
+
+				/// Access the 3x3 inertia matrix
+	virtual ChMatrix33<>& GetBodyInertia() =0;
+
+				/// Access the 3x3 inertia matrix inverted
+	virtual ChMatrix33<>& GetBodyInvInertia() =0;
+
+
+
+				// IMPLEMENT PARENT CLASS METHODS
+
+
+				/// The number of scalar variables in the vector qb
+				/// (dof=degrees of freedom)
+	virtual int Get_ndof() {return 6;};
+
+
+	virtual void* GetUserData() {return this->user_data;}
+	virtual void SetUserData(void* mdata) {this->user_data = mdata;}
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpVariablesBody.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.cpp b/SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.cpp
new file mode 100644
index 0000000..248e865
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.cpp
@@ -0,0 +1,60 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpVariablesBodyOwnMass.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include "ChLcpVariablesBodyOwnMass.h"
+ 
+
+namespace chrono 
+{
+
+
+
+ChLcpVariablesBodyOwnMass& ChLcpVariablesBodyOwnMass::operator=(const ChLcpVariablesBodyOwnMass& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpVariablesBody::operator=(other);
+
+	// copy class data
+	mass= other.mass;
+	inv_mass = other.inv_mass;
+
+	inertia = other.inertia;
+	inv_inertia = other.inv_inertia;
+
+	return *this;
+}
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpVariablesBodyOwnMass> a_registration_ChLcpVariablesBodyOwnMass;
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.h b/SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.h
new file mode 100644
index 0000000..73f4b43
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesBodyOwnMass.h
@@ -0,0 +1,262 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPVARIABLESBODYOWNMASS_H
+#define CHLCPVARIABLESBODYOWNMASS_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpVariablesBodyOwnMass.h
+//
+//    Specialized class for representing a mass matrix
+//   and associate variables (6 element vector, ex.speed)
+//   for a 3D rigid body.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpVariablesBody.h"
+
+
+namespace chrono
+{
+
+///    Specialized class for representing a 6-DOF item for a
+///   LCP system, that is a 3D rigid body, with mass matrix and
+///   associate variables (a 6 element vector, ex.speed)
+///    Differently from the 'naive' implementation ChLcpVariablesGeneric,
+///   here a full 6x6 mass matrix is not built, since only the 3x3
+///   inertia matrix and the mass value are enough.
+
+class ChApi ChLcpVariablesBodyOwnMass :  public ChLcpVariablesBody
+{
+	CH_RTTI(ChLcpVariablesBodyOwnMass, ChLcpVariablesBody)
+
+private:
+			//
+			// DATA
+			//
+				/// the data (qb, variables and fb, forces, already defined in base class)
+
+			ChMatrix33<double> inertia;	// 3x3 inertia matrix
+			double mass;		// mass value
+
+			ChMatrix33<double> inv_inertia;
+			double inv_mass;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpVariablesBodyOwnMass() 
+				{
+					inertia.Set33Identity();
+					inv_inertia.Set33Identity();
+					mass = 1.;
+					inv_mass = 1.;
+				};
+
+	virtual ~ChLcpVariablesBodyOwnMass()
+				{
+				};
+
+
+				/// Assignment operator: copy from other object
+	ChLcpVariablesBodyOwnMass& operator=(const ChLcpVariablesBodyOwnMass& other);
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Get the mass associated with translation of body
+	virtual double	GetBodyMass()	 {return mass;}
+
+				/// Access the 3x3 inertia matrix
+	virtual ChMatrix33<>& GetBodyInertia() {return inertia;}
+
+				/// Access the 3x3 inertia matrix inverted
+	ChMatrix33<>& GetBodyInvInertia() {return inv_inertia;}
+
+
+
+				/// Set the inertia matrix
+	void    SetBodyInertia(const ChMatrix33<>* minertia)
+						{
+							inertia.CopyFromMatrix(*minertia);
+							inertia.FastInvert(&inv_inertia);
+						}
+
+				/// Set the mass associated with translation of body
+	void    SetBodyMass(const double mmass)
+						{
+							mass = mmass;
+							inv_mass = 1.0 / mass;
+						}
+
+
+				// IMPLEMENT PARENT CLASS METHODS
+
+
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and set in result: result = [invMb]*vect
+	virtual void Compute_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)= (float)inv_mass * vect(0);
+						result(1)= (float)inv_mass * vect(1);
+						result(2)= (float)inv_mass * vect(2);
+						result(3)= (float)(inv_inertia(0,0)*vect(3) + inv_inertia(0,1)*vect(4) + inv_inertia(0,2)*vect(5));
+						result(4)= (float)(inv_inertia(1,0)*vect(3) + inv_inertia(1,1)*vect(4) + inv_inertia(1,2)*vect(5));
+						result(5)= (float)(inv_inertia(2,0)*vect(3) + inv_inertia(2,1)*vect(4) + inv_inertia(2,2)*vect(5));
+					};
+	virtual void Compute_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)= inv_mass * vect(0);
+						result(1)= inv_mass * vect(1);
+						result(2)= inv_mass * vect(2);
+						result(3)= inv_inertia(0,0)*vect(3) + inv_inertia(0,1)*vect(4) + inv_inertia(0,2)*vect(5);
+						result(4)= inv_inertia(1,0)*vect(3) + inv_inertia(1,1)*vect(4) + inv_inertia(1,2)*vect(5);
+						result(5)= inv_inertia(2,0)*vect(3) + inv_inertia(2,1)*vect(4) + inv_inertia(2,2)*vect(5);
+					};
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and increment result: result += [invMb]*vect
+	virtual void Compute_inc_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= (float)inv_mass * vect(0);
+						result(1)+= (float)inv_mass * vect(1);
+						result(2)+= (float)inv_mass * vect(2);
+						result(3)+= (float)(inv_inertia(0,0)*vect(3) + inv_inertia(0,1)*vect(4) + inv_inertia(0,2)*vect(5));
+						result(4)+= (float)(inv_inertia(1,0)*vect(3) + inv_inertia(1,1)*vect(4) + inv_inertia(1,2)*vect(5));
+						result(5)+= (float)(inv_inertia(2,0)*vect(3) + inv_inertia(2,1)*vect(4) + inv_inertia(2,2)*vect(5));
+					};
+	virtual void Compute_inc_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= inv_mass * vect(0);
+						result(1)+= inv_mass * vect(1);
+						result(2)+= inv_mass * vect(2);
+						result(3)+= inv_inertia(0,0)*vect(3) + inv_inertia(0,1)*vect(4) + inv_inertia(0,2)*vect(5);
+						result(4)+= inv_inertia(1,0)*vect(3) + inv_inertia(1,1)*vect(4) + inv_inertia(1,2)*vect(5);
+						result(5)+= inv_inertia(2,0)*vect(3) + inv_inertia(2,1)*vect(4) + inv_inertia(2,2)*vect(5);
+					};
+
+
+				/// Computes the product of the mass matrix by a
+				/// vector, and set in result: result = [Mb]*vect
+	virtual void Compute_inc_Mb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (result.GetRows() == Get_ndof());
+						assert (vect.GetRows()   == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= (float)mass * vect(0);
+						result(1)+= (float)mass * vect(1);
+						result(2)+= (float)mass * vect(2);
+						result(3)+= (float)(inertia(0,0)*vect(3) + inertia(0,1)*vect(4) + inertia(0,2)*vect(5));
+						result(4)+= (float)(inertia(1,0)*vect(3) + inertia(1,1)*vect(4) + inertia(1,2)*vect(5));
+						result(5)+= (float)(inertia(2,0)*vect(3) + inertia(2,1)*vect(4) + inertia(2,2)*vect(5));
+					};
+	virtual void Compute_inc_Mb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= mass * vect(0);
+						result(1)+= mass * vect(1);
+						result(2)+= mass * vect(2);
+						result(3)+= (inertia(0,0)*vect(3) + inertia(0,1)*vect(4) + inertia(0,2)*vect(5));
+						result(4)+= (inertia(1,0)*vect(3) + inertia(1,1)*vect(4) + inertia(1,2)*vect(5));
+						result(5)+= (inertia(2,0)*vect(3) + inertia(2,1)*vect(4) + inertia(2,2)*vect(5));
+					};
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix (ie. the mass matrix) by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' and 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect.
+	virtual void MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect) const
+					{
+						assert(result.GetColumns()==1 && vect.GetColumns()==1);
+						// optimized unrolled operations
+						double q0 = vect(this->offset+0);
+						double q1 = vect(this->offset+1);
+						double q2 = vect(this->offset+2);
+						double q3 = vect(this->offset+3);
+						double q4 = vect(this->offset+4);
+						double q5 = vect(this->offset+5);
+						result(this->offset+0)+= mass * q0;
+						result(this->offset+1)+= mass * q1;
+						result(this->offset+2)+= mass * q2;
+						result(this->offset+3)+= (inertia(0,0)*q3 + inertia(0,1)*q4 + inertia(0,2)*q5);
+						result(this->offset+4)+= (inertia(1,0)*q3 + inertia(1,1)*q4 + inertia(1,2)*q5);
+						result(this->offset+5)+= (inertia(2,0)*q3 + inertia(2,1)*q4 + inertia(2,2)*q5);
+					}
+	
+				/// Add the diagonal of the mass matrix (as a column vector) to 'result'.
+				/// NOTE: the 'result' vector must already have the size of system unknowns, ie
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offset (that must be already updated) as index.
+	virtual void DiagonalAdd(ChMatrix<double>& result) const 
+					{
+						assert(result.GetColumns()==1);
+						result(this->offset+0)+= mass;
+						result(this->offset+1)+= mass;
+						result(this->offset+2)+= mass;
+						result(this->offset+3)+= inertia(0,0);
+						result(this->offset+4)+= inertia(1,1);
+						result(this->offset+5)+= inertia(2,2);
+					}
+
+				/// Build the mass matrix (for these variables) storing
+				/// it in 'storage' sparse matrix, at given column/row offset.
+				/// Note, most iterative solvers don't need to know mass matrix explicitly.
+				/// Optimised: doesn't fill unneeded elements except mass and 3x3 inertia.
+	virtual void Build_M(ChSparseMatrix& storage, int insrow, int inscol)
+					{
+						storage.SetElement(insrow+0, inscol+0, mass);
+						storage.SetElement(insrow+1, inscol+1, mass);
+						storage.SetElement(insrow+2, inscol+2, mass);
+						storage.PasteMatrix(&inertia, insrow+3, inscol+3);
+					};
+
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesBodySharedMass.cpp b/SRC/ChronoEngine/lcp/ChLcpVariablesBodySharedMass.cpp
new file mode 100644
index 0000000..20142a0
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesBodySharedMass.cpp
@@ -0,0 +1,56 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpVariablesBodySharedMass.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include "ChLcpVariablesBodySharedMass.h"
+ 
+
+namespace chrono 
+{
+
+
+
+ChLcpVariablesBodySharedMass& ChLcpVariablesBodySharedMass::operator=(const ChLcpVariablesBodySharedMass& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpVariablesBody::operator=(other);
+
+	// copy class data
+	sharedmass = other.sharedmass;
+
+	return *this;
+}
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpVariablesBodySharedMass> a_registration_ChLcpVariablesBodySharedMass;
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesBodySharedMass.h b/SRC/ChronoEngine/lcp/ChLcpVariablesBodySharedMass.h
new file mode 100644
index 0000000..780ee19
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesBodySharedMass.h
@@ -0,0 +1,304 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPVARIABLESBODYSHAREDMASS_H
+#define CHLCPVARIABLESBODYSHAREDMASS_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpVariablesBodySharedMass.h
+//
+//    Specialized class for representing a mass matrix
+//   and associate variables (6 element vector, ex.speed)
+//   for a 3D rigid body, in a LCP problem of the type:
+//
+//    | M -Cq'|*|q|- | f|= |0| ,  c>0, l>0, l*c=0;
+//    | Cq  0 | |l|  |-b|  |c|
+//
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpVariablesBody.h"
+
+
+namespace chrono
+{
+
+
+///  Used by ChLcpVariablesBodySharedMass objects to 
+/// reference a single mass propery.
+
+class ChApi ChSharedMassBody
+{
+public:
+
+	ChMatrix33<double> inertia;	// 3x3 inertia matrix
+	double mass;		// mass value
+
+	ChMatrix33<double> inv_inertia;
+	double inv_mass;
+
+public:
+	
+	ChSharedMassBody()
+				{
+					inertia.Set33Identity();
+					inv_inertia.Set33Identity();
+					mass = 1.;
+					inv_mass = 1.;
+				}
+
+				/// Set the inertia matrix
+	void    SetBodyInertia(const ChMatrix33<>* minertia)
+						{
+							inertia.CopyFromMatrix(*minertia);
+							inertia.FastInvert(&inv_inertia);
+						}
+
+				/// Set the mass associated with translation of body
+	void    SetBodyMass(const double mmass)
+						{
+							mass = mmass;
+							inv_mass = 1.0 / mass;
+						}
+
+				/// Access the 3x3 inertia matrix
+	ChMatrix33<>& GetBodyInertia() {return inertia;}
+
+				/// Access the 3x3 inertia matrix inverted
+	ChMatrix33<>& GetBodyInvInertia() {return inv_inertia;}
+
+				/// Get the mass associated with translation of body
+	double	GetBodyMass()	 {return mass;}
+
+};
+
+
+///    Specialized class for representing a 6-DOF item for a
+///   LCP system, that is a 3D rigid body, with mass matrix and
+///   associate variables (a 6 element vector, ex.speed)
+///    Differently from the 'naive' implementation ChLcpVariablesGeneric,
+///   here a full 6x6 mass matrix is not built, since only the 3x3
+///   inertia matrix and the mass value are enough.
+///    This is very similar to ChLcpVariablesBodyOwnMass, but the 
+///   mass and inertia values are shared, that can be useful for
+///   problems with thousands of equally-shaped objects.
+
+class ChApi ChLcpVariablesBodySharedMass :  public ChLcpVariablesBody
+{
+	CH_RTTI(ChLcpVariablesBodySharedMass, ChLcpVariablesBody)
+
+private:
+			//
+			// DATA
+			//
+				/// the data (qb, variables and fb, forces, already defined in base class)
+
+			ChSharedMassBody* sharedmass;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpVariablesBodySharedMass() 
+				{
+					sharedmass = 0;
+				};
+
+	virtual ~ChLcpVariablesBodySharedMass()
+				{
+				};
+
+
+				/// Assignment operator: copy from other object
+	ChLcpVariablesBodySharedMass& operator=(const ChLcpVariablesBodySharedMass& other);
+
+
+			//
+			// FUNCTIONS
+			//
+
+
+				/// Get the pointer to shared mass
+	ChSharedMassBody* GetSharedMass() {return sharedmass;};
+
+				/// Set pointer to shared mass
+	void SetSharedMass(ChSharedMassBody* ms) {sharedmass = ms;};
+
+
+
+				// IMPLEMENT PARENT CLASS METHODS
+
+
+				/// Get the mass associated with translation of body
+	virtual double	GetBodyMass()	 {return sharedmass->GetBodyMass();}
+
+				/// Access the 3x3 inertia matrix
+	virtual ChMatrix33<>& GetBodyInertia() {return sharedmass->GetBodyInertia();}
+
+					/// Access the 3x3 inertia matrix inverted
+	virtual ChMatrix33<>& GetBodyInvInertia() {return sharedmass->GetBodyInvInertia();};
+
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and set in result: result = [invMb]*vect
+	virtual void Compute_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (vect.GetRows() == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)= (float)(sharedmass->inv_mass) * vect(0);
+						result(1)= (float)(sharedmass->inv_mass) * vect(1);
+						result(2)= (float)(sharedmass->inv_mass) * vect(2);
+						result(3)= (float)(sharedmass->inv_inertia(0,0)*vect(3) + sharedmass->inv_inertia(0,1)*vect(4) + sharedmass->inv_inertia(0,2)*vect(5));
+						result(4)= (float)(sharedmass->inv_inertia(1,0)*vect(3) + sharedmass->inv_inertia(1,1)*vect(4) + sharedmass->inv_inertia(1,2)*vect(5));
+						result(5)= (float)(sharedmass->inv_inertia(2,0)*vect(3) + sharedmass->inv_inertia(2,1)*vect(4) + sharedmass->inv_inertia(2,2)*vect(5));
+					};
+	virtual void Compute_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (vect.GetRows() == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)= sharedmass->inv_mass * vect(0);
+						result(1)= sharedmass->inv_mass * vect(1);
+						result(2)= sharedmass->inv_mass * vect(2);
+						result(3)= sharedmass->inv_inertia(0,0)*vect(3) + sharedmass->inv_inertia(0,1)*vect(4) + sharedmass->inv_inertia(0,2)*vect(5);
+						result(4)= sharedmass->inv_inertia(1,0)*vect(3) + sharedmass->inv_inertia(1,1)*vect(4) + sharedmass->inv_inertia(1,2)*vect(5);
+						result(5)= sharedmass->inv_inertia(2,0)*vect(3) + sharedmass->inv_inertia(2,1)*vect(4) + sharedmass->inv_inertia(2,2)*vect(5);
+					};
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and increment result: result += [invMb]*vect
+	virtual void Compute_inc_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (vect.GetRows() == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= (float)(sharedmass->inv_mass) * vect(0);
+						result(1)+= (float)(sharedmass->inv_mass) * vect(1);
+						result(2)+= (float)(sharedmass->inv_mass) * vect(2);
+						result(3)+= (float)(sharedmass->inv_inertia(0,0)*vect(3) + sharedmass->inv_inertia(0,1)*vect(4) + sharedmass->inv_inertia(0,2)*vect(5));
+						result(4)+= (float)(sharedmass->inv_inertia(1,0)*vect(3) + sharedmass->inv_inertia(1,1)*vect(4) + sharedmass->inv_inertia(1,2)*vect(5));
+						result(5)+= (float)(sharedmass->inv_inertia(2,0)*vect(3) + sharedmass->inv_inertia(2,1)*vect(4) + sharedmass->inv_inertia(2,2)*vect(5));
+					};
+	virtual void Compute_inc_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (vect.GetRows() == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= sharedmass->inv_mass * vect(0);
+						result(1)+= sharedmass->inv_mass * vect(1);
+						result(2)+= sharedmass->inv_mass * vect(2);
+						result(3)+= sharedmass->inv_inertia(0,0)*vect(3) + sharedmass->inv_inertia(0,1)*vect(4) + sharedmass->inv_inertia(0,2)*vect(5);
+						result(4)+= sharedmass->inv_inertia(1,0)*vect(3) + sharedmass->inv_inertia(1,1)*vect(4) + sharedmass->inv_inertia(1,2)*vect(5);
+						result(5)+= sharedmass->inv_inertia(2,0)*vect(3) + sharedmass->inv_inertia(2,1)*vect(4) + sharedmass->inv_inertia(2,2)*vect(5);
+					};
+
+
+				/// Computes the product of the mass matrix by a
+				/// vector, and set in result: result = [Mb]*vect
+	virtual void Compute_inc_Mb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (result.GetRows() == Get_ndof());
+						assert (vect.GetRows()   == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= (float)(sharedmass->mass) * vect(0);
+						result(1)+= (float)(sharedmass->mass) * vect(1);
+						result(2)+= (float)(sharedmass->mass) * vect(2);
+						result(3)+= (float)(sharedmass->inertia(0,0)*vect(3) + sharedmass->inertia(0,1)*vect(4) + sharedmass->inertia(0,2)*vect(5));
+						result(4)+= (float)(sharedmass->inertia(1,0)*vect(3) + sharedmass->inertia(1,1)*vect(4) + sharedmass->inertia(1,2)*vect(5));
+						result(5)+= (float)(sharedmass->inertia(2,0)*vect(3) + sharedmass->inertia(2,1)*vect(4) + sharedmass->inertia(2,2)*vect(5));
+					};
+	virtual void Compute_inc_Mb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (result.GetRows() == Get_ndof());
+						assert (vect.GetRows()   == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= sharedmass->mass * vect(0);
+						result(1)+= sharedmass->mass * vect(1);
+						result(2)+= sharedmass->mass * vect(2);
+						result(3)+= (sharedmass->inertia(0,0)*vect(3) + sharedmass->inertia(0,1)*vect(4) + sharedmass->inertia(0,2)*vect(5));
+						result(4)+= (sharedmass->inertia(1,0)*vect(3) + sharedmass->inertia(1,1)*vect(4) + sharedmass->inertia(1,2)*vect(5));
+						result(5)+= (sharedmass->inertia(2,0)*vect(3) + sharedmass->inertia(2,1)*vect(4) + sharedmass->inertia(2,2)*vect(5));
+					};
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix (ie. the mass matrix) by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' and 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect.
+	virtual void MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect) const
+					{
+						assert(result.GetColumns()==1 && vect.GetColumns()==1);
+						// optimized unrolled operations
+						double q0 = vect(this->offset+0);
+						double q1 = vect(this->offset+1);
+						double q2 = vect(this->offset+2);
+						double q3 = vect(this->offset+3);
+						double q4 = vect(this->offset+4);
+						double q5 = vect(this->offset+5);
+						result(this->offset+0)+= sharedmass->mass * q0;
+						result(this->offset+1)+= sharedmass->mass * q1;
+						result(this->offset+2)+= sharedmass->mass * q2;
+						result(this->offset+3)+= (sharedmass->inertia(0,0)*q3 + sharedmass->inertia(0,1)*q4 + sharedmass->inertia(0,2)*q5);
+						result(this->offset+4)+= (sharedmass->inertia(1,0)*q3 + sharedmass->inertia(1,1)*q4 + sharedmass->inertia(1,2)*q5);
+						result(this->offset+5)+= (sharedmass->inertia(2,0)*q3 + sharedmass->inertia(2,1)*q4 + sharedmass->inertia(2,2)*q5);
+					}
+
+				/// Add the diagonal of the mass matrix (as a column vector) to 'result'.
+				/// NOTE: the 'result' vector must already have the size of system unknowns, ie
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offset (that must be already updated) as index.
+	virtual void DiagonalAdd(ChMatrix<double>& result) const 
+					{
+						assert(result.GetColumns()==1);
+						result(this->offset+0)+= sharedmass->mass;
+						result(this->offset+1)+= sharedmass->mass;
+						result(this->offset+2)+= sharedmass->mass;
+						result(this->offset+3)+= sharedmass->inertia(0,0);
+						result(this->offset+4)+= sharedmass->inertia(1,1);
+						result(this->offset+5)+= sharedmass->inertia(2,2);
+					}
+
+				/// Build the mass matrix (for these variables) storing
+				/// it in 'storage' sparse matrix, at given column/row offset.
+				/// Note, most iterative solvers don't need to know mass matrix explicitly.
+				/// Optimised: doesn't fill unneeded elements except mass and 3x3 inertia.
+	virtual void Build_M(ChSparseMatrix& storage, int insrow, int inscol)
+					{
+						storage.SetElement(insrow+0, inscol+0, sharedmass->mass);
+						storage.SetElement(insrow+1, inscol+1, sharedmass->mass);
+						storage.SetElement(insrow+2, inscol+2, sharedmass->mass);
+						storage.PasteMatrix(&(sharedmass->inertia), insrow+3, inscol+3);
+					};
+
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpVariablesBody.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.cpp b/SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.cpp
new file mode 100644
index 0000000..a8e07a5
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.cpp
@@ -0,0 +1,80 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpVariablesGeneric.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include "ChLcpVariablesGeneric.h"
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono 
+{
+
+
+ChLcpVariablesGeneric& ChLcpVariablesGeneric::operator=(const ChLcpVariablesGeneric& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpVariables::operator=(other);
+
+	// copy class data
+
+	if (other.Mmass)
+	{
+		if (Mmass==NULL)
+			Mmass = new ChMatrixDynamic<>;
+		Mmass->CopyFromMatrix(*other.Mmass);
+	}
+	else
+	{
+		if (Mmass) delete Mmass;
+		Mmass=NULL;
+	}
+
+	if (other.inv_Mmass)
+	{
+		if (inv_Mmass==NULL)
+			inv_Mmass = new ChMatrixDynamic<>;
+		inv_Mmass->CopyFromMatrix(*other.inv_Mmass);
+	}
+	else
+	{
+		if (inv_Mmass) delete inv_Mmass;
+		inv_Mmass=NULL;
+	}
+
+
+	return *this;
+}
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpVariablesGeneric> a_registration_ChLcpVariablesGeneric;
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.h b/SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.h
new file mode 100644
index 0000000..b74b08f
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesGeneric.h
@@ -0,0 +1,211 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPVARIABLESGENERIC_H
+#define CHLCPVARIABLESGENERIC_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpVariablesGeneric.h
+//
+//    Specialized class for representing a N-DOF item for a
+//   LCP system, that is an item with mass matrix and
+//   associate variables.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpVariables.h"
+#include "core/ChMemory.h" // must be after system's include (memory leak debugger).
+
+
+namespace chrono
+{
+
+///    Specialized class for representing a N-DOF item for a
+///   LCP system, that is an item with mass matrix and
+///   associate variables.
+///    The main difference from the base class ChLcpVariables
+///   is that the base class does not create any mass matrix,
+///   while this minimal specialization at least creates a
+///   NxN mass matrix. Of course a generic (uncompressed) NxN
+///   matrix is used. This means that, for example, this
+///   class could  be used for 3D rigid bodies if N=6, however
+///   it would be better to implement a more optimized class
+///   which does not create a full 6x6 matrix (since only few
+///   elements on the diagonal would be different from 0 in case
+///   of rigid bodies), so use the ChLcpVariablesBody in this case..
+
+
+class ChApi ChLcpVariablesGeneric :  public ChLcpVariables
+{
+	CH_RTTI(ChLcpVariablesGeneric, ChLcpVariables)
+
+private:
+			//
+			// DATA
+			//
+				/// the data (qb, variables and fb, forces, already defined in base class)
+
+			ChMatrixDynamic<>* Mmass;
+			ChMatrixDynamic<>* inv_Mmass;
+			int ndof;
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+	ChLcpVariablesGeneric(int m_ndof= 1)
+							: ChLcpVariables(m_ndof)
+				{
+					ndof = m_ndof;
+					Mmass = new ChMatrixDynamic<>(ndof, ndof);
+					Mmass->SetIdentity();
+					inv_Mmass = new ChMatrixDynamic<>(ndof, ndof);
+					inv_Mmass->SetIdentity();
+				};
+
+	virtual ~ChLcpVariablesGeneric()
+				{
+					if (Mmass) delete Mmass; Mmass= NULL;
+					if (inv_Mmass) delete inv_Mmass; inv_Mmass= NULL;
+				};
+
+
+				/// Assignment operator: copy from other object
+	ChLcpVariablesGeneric& operator=(const ChLcpVariablesGeneric& other);
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Access the inertia matrix
+	ChMatrix<>& GetMass() {return *Mmass;}
+
+				/// Access the inverted inertia matrix
+	ChMatrix<>& GetInvMass() {return *inv_Mmass;}
+
+
+				// IMPLEMENT PARENT CLASS METHODS
+
+
+				/// The number of scalar variables in the vector qb
+				/// (dof=degrees of freedom)
+	virtual int Get_ndof() {return this->ndof;};
+
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and add to result: result = [invMb]*vect
+	virtual void Compute_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						result = (*inv_Mmass)*vect;
+					};
+	virtual void Compute_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						result = (*inv_Mmass)*vect;
+					};
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and increment result: result += [invMb]*vect
+	virtual void Compute_inc_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						result += (*inv_Mmass)*vect;
+					};
+	virtual void Compute_inc_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						result += (*inv_Mmass)*vect;
+					};
+
+				/// Computes the product of the mass matrix by a
+				/// vector, and set in result: result = [Mb]*vect
+	virtual void Compute_inc_Mb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						result += (*Mmass)*vect;
+					};
+	virtual void Compute_inc_Mb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						result += (*Mmass)*vect;
+					};
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix (ie. the mass matrix) by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' and 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect.
+	virtual void MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect) const
+					{
+						assert(result.GetColumns()==1 && vect.GetColumns()==1);
+	
+						for (int i = 0; i < Mmass->GetRows(); i++)
+						{
+							double tot = 0;
+							for (int j = 0; j < Mmass->GetColumns(); j++)
+							{
+								tot += (*Mmass)(i,j)* vect(this->offset + i);
+							}
+							result(this->offset + i) += tot;
+						}
+					}
+
+				/// Add the diagonal of the mass matrix (as a column vector) to 'result'.
+				/// NOTE: the 'result' vector must already have the size of system unknowns, ie
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offset (that must be already updated) as index.
+	virtual void DiagonalAdd(ChMatrix<double>& result) const 
+					{
+						assert(result.GetColumns()==1);
+						for (int i = 0; i < Mmass->GetRows(); i++)
+						{
+							result(this->offset + i) += (*Mmass)(i,i);
+						}
+					}
+
+				/// Build the mass matrix (for these variables) storing
+				/// it in 'storage' sparse matrix, at given column/row offset.
+				/// Note, most iterative solvers don't need to know mass matrix explicitly.
+	virtual void Build_M(ChSparseMatrix& storage, int insrow, int inscol)
+					{
+						storage.PasteMatrix(Mmass, insrow, inscol);
+					};
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#include "core/ChMemorynomgr.h" // back to default new/delete/malloc/calloc etc. Avoid conflicts with system libs.
+
+
+#endif  // END of ChLcpVariablesGeneric.h
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesNode.cpp b/SRC/ChronoEngine/lcp/ChLcpVariablesNode.cpp
new file mode 100644
index 0000000..83b7723
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesNode.cpp
@@ -0,0 +1,57 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLcpVariablesNode.cpp
+//
+//
+//    file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include "ChLcpVariablesNode.h"
+ 
+
+namespace chrono 
+{
+
+
+
+ChLcpVariablesNode& ChLcpVariablesNode::operator=(const ChLcpVariablesNode& other)
+{
+	if (&other == this) return *this;
+
+	// copy parent class data
+	ChLcpVariables::operator=(other);
+
+	// copy class data
+	user_data = other.user_data;
+	mass = other.mass;
+
+	return *this;
+}
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLcpVariablesNode> a_registration_ChLcpVariablesNode;
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/lcp/ChLcpVariablesNode.h b/SRC/ChronoEngine/lcp/ChLcpVariablesNode.h
new file mode 100644
index 0000000..fe9f852
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/ChLcpVariablesNode.h
@@ -0,0 +1,220 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLCPVARIABLESNODE_H
+#define CHLCPVARIABLESNODE_H
+
+//////////////////////////////////////////////////
+//
+//   ChLcpVariablesNode.h
+//
+//    Specialized class for representing a mass matrix
+//   and associate variables (3 element vector, ex.speed)
+//   for a 3D point 'node'.
+//
+//   HEADER file for CHRONO HYPEROCTANT LCP solver
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChLcpVariables.h"
+
+
+namespace chrono
+{
+
+///    Specialized class for representing a 3-DOF item for a
+///   LCP system, that is a 3D point node, with mass matrix and
+///   associate variables (a 3 element vector, ex.speed)
+
+
+class ChApi ChLcpVariablesNode :  public ChLcpVariables
+{
+	CH_RTTI(ChLcpVariablesNode, ChLcpVariables)
+
+private:
+			//
+			// DATA		//
+
+
+			void* user_data;
+
+			double mass;		// mass value
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChLcpVariablesNode() : ChLcpVariables(3)
+				{
+					user_data = 0;
+					mass = 1.0;
+				};
+
+	virtual ~ChLcpVariablesNode()
+				{
+				};
+
+
+				/// Assignment operator: copy from other object
+	ChLcpVariablesNode& operator=(const ChLcpVariablesNode& other);
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Get the mass associated with translation of node
+	virtual double	GetNodeMass() const {return mass;};
+
+				/// Set the mass associated with translation of node
+	void SetNodeMass(const double mmass)
+						{
+							mass = mmass;
+						}
+
+
+				// IMPLEMENT PARENT CLASS METHODS
+
+
+				/// The number of scalar variables in the vector qb
+				/// (dof=degrees of freedom)
+	virtual int Get_ndof() {return 3;};
+
+
+	virtual void* GetUserData() {return this->user_data;}
+	virtual void SetUserData(void* mdata) {this->user_data = mdata;}
+
+
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and set in result: result = [invMb]*vect
+	virtual void Compute_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						double inv_mass = 1.0/mass;
+						result(0)= (float)inv_mass * vect(0);
+						result(1)= (float)inv_mass * vect(1);
+						result(2)= (float)inv_mass * vect(2);
+					};
+	virtual void Compute_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						double inv_mass = 1.0/mass;
+						result(0)= inv_mass * vect(0);
+						result(1)= inv_mass * vect(1);
+						result(2)= inv_mass * vect(2);
+					};
+
+				/// Computes the product of the inverse mass matrix by a
+				/// vector, and increment result: result += [invMb]*vect
+	virtual void Compute_inc_invMb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						double inv_mass = 1.0/mass;
+						result(0)+= (float)inv_mass * vect(0);
+						result(1)+= (float)inv_mass * vect(1);
+						result(2)+= (float)inv_mass * vect(2);
+					};
+	virtual void Compute_inc_invMb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (vect.GetRows()   == Get_ndof());
+						assert (result.GetRows() == Get_ndof());
+						// optimized unrolled operations
+						double inv_mass = 1.0/mass;
+						result(0)+= inv_mass * vect(0);
+						result(1)+= inv_mass * vect(1);
+						result(2)+= inv_mass * vect(2);
+					};
+
+
+				/// Computes the product of the mass matrix by a
+				/// vector, and set in result: result = [Mb]*vect
+	virtual void Compute_inc_Mb_v(ChMatrix<float>& result, const ChMatrix<float>& vect)
+					{
+						assert (result.GetRows() == Get_ndof());
+						assert (vect.GetRows()   == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= (float)mass * vect(0);
+						result(1)+= (float)mass * vect(1);
+						result(2)+= (float)mass * vect(2);
+					};
+	virtual void Compute_inc_Mb_v(ChMatrix<double>& result, const ChMatrix<double>& vect)
+					{
+						assert (result.GetRows() == vect.GetRows());
+						assert (vect.GetRows()   == Get_ndof());
+						// optimized unrolled operations
+						result(0)+= mass * vect(0);
+						result(1)+= mass * vect(1);
+						result(2)+= mass * vect(2);
+					};
+
+				/// Computes the product of the corresponding block in the 
+				/// system matrix (ie. the mass matrix) by 'vect', and add to 'result'. 
+				/// NOTE: the 'vect' and 'result' vectors must already have
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offsets (that must be already updated) to know the 
+				/// indexes in result and vect.
+	virtual void MultiplyAndAdd(ChMatrix<double>& result, const ChMatrix<double>& vect) const
+					{
+						assert(result.GetColumns()==1 && vect.GetColumns()==1);
+						// optimized unrolled operations
+						result(this->offset  )+= mass * vect(this->offset  );
+						result(this->offset+1)+= mass * vect(this->offset+1);
+						result(this->offset+2)+= mass * vect(this->offset+2);
+					}
+
+				/// Add the diagonal of the mass matrix (as a column vector) to 'result'.
+				/// NOTE: the 'result' vector must already have the size of system unknowns, ie
+				/// the size of the total variables&constraints in the system; the procedure
+				/// will use the ChVariable offset (that must be already updated) as index.
+	virtual void DiagonalAdd(ChMatrix<double>& result) const 
+					{
+						assert(result.GetColumns()==1);
+						result(this->offset  )+= mass;
+						result(this->offset+1)+= mass;
+						result(this->offset+2)+= mass;
+					}
+
+				/// Build the mass matrix (for these variables) storing
+				/// it in 'storage' sparse matrix, at given column/row offset.
+				/// Note, most iterative solvers don't need to know mass matrix explicitly.
+				/// Optimised: doesn't fill unneeded elements except mass.
+	virtual void Build_M(ChSparseMatrix& storage, int insrow, int inscol)
+					{
+						storage.SetElement(insrow+0, inscol+0, mass);
+						storage.SetElement(insrow+1, inscol+1, mass);
+						storage.SetElement(insrow+2, inscol+2, mass);
+					};
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChLcpVariablesBody.h
diff --git a/SRC/ChronoEngine/lcp/Empty.cpp b/SRC/ChronoEngine/lcp/Empty.cpp
new file mode 100644
index 0000000..af5f79b
--- /dev/null
+++ b/SRC/ChronoEngine/lcp/Empty.cpp
@@ -0,0 +1,8 @@
+// This must remain in this directory. It is used as a stub
+// for generating an empty .obj when the CUDA compilation is 
+// turned off.
+
+struct foo 
+{
+   int ifoo;
+};
\ No newline at end of file
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Base.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Base.cpp
new file mode 100644
index 0000000..740ecbf
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Base.cpp
@@ -0,0 +1,289 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Base.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+
+#include "ChFunction_Base.h"
+#include "physics/ChGlobal.h"
+
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChFunction> a_registration;
+
+
+double ChFunction::Get_y_dN (double x, int derivate)
+{
+	switch (derivate)
+	{
+	case 0:
+		return Get_y(x);
+	case 1:
+		return Get_y_dx(x);
+	case 2:
+		return Get_y_dxdx(x);
+	default:
+		return Get_y(x);
+	}
+}
+
+void ChFunction::Extimate_y_range (double xmin, double xmax, double& ymin, double& ymax, int derivate)
+{
+	ymin= 10000;
+	ymax=-10000;
+	for (double mx = xmin; mx < xmax; mx+= (xmax-xmin)/100.0)
+	{
+		if (Get_y_dN(mx, derivate) < ymin) ymin = Get_y_dN(mx, derivate);
+		if (Get_y_dN(mx, derivate) > ymax) ymax = Get_y_dN(mx, derivate);
+	}
+	if (fabs(ymax - ymin) <10e-12) {ymin= -0.5; ymax= +1.0;}
+	ymax += 0.12 * (ymax-ymin);
+	ymin -= 0.12 * (ymax-ymin);
+}
+
+// some analysis functions
+double ChFunction::Compute_max(double xmin, double xmax, double sampling_step, int derivate)
+{
+	double mret = -1E30;
+	for (double mx = xmin; mx<= xmax; mx +=sampling_step)
+	{
+		if (this->Get_y_dN(mx, derivate) > mret)
+			mret = this->Get_y_dN(mx, derivate);
+	}
+	return mret;
+}
+
+double ChFunction::Compute_min(double xmin, double xmax, double sampling_step, int derivate)
+{
+	double mret = +1E30;
+	for (double mx = xmin; mx<= xmax; mx += sampling_step)
+	{
+		if (this->Get_y_dN(mx, derivate) < mret)
+			mret = this->Get_y_dN(mx, derivate);
+	}
+	return mret;
+}
+
+double ChFunction::Compute_mean(double xmin, double xmax, double sampling_step, int derivate)
+{
+	double mret = 0;
+	int numpts = 0;
+	for (double mx = xmin; mx<= xmax; mx = mx+sampling_step)
+	{
+		numpts++;
+		mret += this->Get_y_dN(mx, derivate);
+	}
+	return mret/((double)numpts);
+
+}
+
+double ChFunction::Compute_sqrmean(double xmin, double xmax, double sampling_step, int derivate)
+{
+	double mret = 0;
+	int numpts = 0;
+	for (double mx = xmin; mx<= xmax; mx = mx+sampling_step)
+	{
+		numpts++;
+		mret += pow (this->Get_y_dN(mx, derivate) , 2.);
+	}
+	return sqrt (mret/((double)numpts));
+}
+
+double ChFunction::Compute_int(double xmin, double xmax, double sampling_step, int derivate)
+{
+	double mret = 0;
+	double ya = this->Get_y_dN(xmin, derivate);
+	double yb = 0;
+	for (double mx = xmin+sampling_step; mx<= xmax; mx += sampling_step)
+	{
+		yb = this->Get_y_dN(mx, derivate);
+		mret += sampling_step*(ya+yb)*0.5; // trapezoidal quadrature
+		ya = yb;
+	}
+	return mret;
+}
+
+
+////////////
+
+
+int ChFunction::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	const char** mvars= this->GetOptVariables();
+	int i=0;
+	while (*(mvars+i)!=0)
+	{
+		chjs_propdata* mdata = new chjs_propdata;
+		strcpy(mdata->propname, *(mvars+i));
+		strcpy(mdata->label,    *(mvars+i));
+		mdata->haschildren = FALSE;
+		mtree->AddTail(mdata);
+		i++;
+	}
+/*
+	// now dirty trick, because of 'C' variable is inherited by all functions,
+	// but used by plain base class only..
+	if (this->Get_Type()==FUNCT_CONST)
+	{
+		chjs_propdata* mdata = new chjs_propdata;
+		strcpy(mdata->propname, "C");
+		strcpy(mdata->label,    mdata->propname);
+		mdata->haschildren = FALSE;
+		mtree->AddTail(mdata);
+		i++;
+	}
+*/
+	return i;
+}
+
+
+static int _recurse_VariableTreeToFullNameVar(ChList<chjs_propdata>* mtree, ChList<chjs_fullnamevar>* mlist, char* maccumulator)
+{
+	int i= 0;
+
+	int mentrypos = strlen (maccumulator);
+
+	ChNode<chjs_propdata>* mnode = mtree->GetHead();
+	while(mnode)
+	{
+		if (strlen(maccumulator)+strlen(mnode->data->propname) < 120-1)
+		{
+			strcat(maccumulator, mnode->data->label);
+
+			if (mnode->data->children.Count())
+			{
+				strcat(maccumulator, ".");
+				_recurse_VariableTreeToFullNameVar(&mnode->data->children, mlist, maccumulator);
+			}
+			else
+			{
+				chjs_fullnamevar* mfullname = new chjs_fullnamevar;
+				strcpy(mfullname->propname, maccumulator);
+				strcpy(mfullname->label, maccumulator);
+				mfullname->active= TRUE;
+				mfullname->script=NULL;
+				mlist->AddTail(mfullname);
+				i++;
+			}
+
+			maccumulator[mentrypos]=0;
+		}
+
+		mnode = mnode->next;
+	}
+	return i;
+}
+
+int ChFunction::VariableTreeToFullNameVar(ChList<chjs_propdata>* mtree, ChList<chjs_fullnamevar>* mlist)
+{
+	char accumulator[120];
+	strcpy(accumulator, "context().");
+
+	int i= _recurse_VariableTreeToFullNameVar(mtree, mlist, accumulator);
+
+	return i;
+}
+
+
+int ChFunction::OptVariableCount()
+{
+	ChList<chjs_propdata> mtree;
+	ChList<chjs_fullnamevar> mlist;
+	MakeOptVariableTree(&mtree);
+	VariableTreeToFullNameVar(&mtree, &mlist);
+	return mlist.Count();
+};
+
+
+
+
+////////////
+
+void ChFunction::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// stream out all member data
+}
+
+void ChFunction::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in all member data
+}
+
+void ChFunction::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_BASE  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+int ChFunction::FileAsciiPairsSave(ChStreamOutAscii& m_file, double mxmin, double mxmax, int msamples)
+{
+	if (msamples<=1) throw (ChException("Warning! too short range or too long sampling period: no points can be saved"));
+	if (msamples>=100000) throw (ChException("Warning! Too many points should be saved"));
+	if (mxmax<=mxmin) throw (ChException("Warning! Cannot save ChFunction if Xmax < Xmin"));
+
+	m_file.SetNumFormat((char* )"%0.8f");
+	
+	double period = (mxmax-mxmin)/((double)msamples-1);
+	
+	double mX = mxmin;
+	for (int cnt = 1; cnt <= msamples ; cnt++)
+	{
+		m_file << mX;
+		m_file << "    ";
+		m_file << this->Get_y(mX);
+		m_file.CR();
+		mX += period;
+	}
+	return 1;
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Base.h b/SRC/ChronoEngine/motion_functions/ChFunction_Base.h
new file mode 100644
index 0000000..560567b
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Base.h
@@ -0,0 +1,213 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_BASE_H
+#define CHFUNCT_BASE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Base.h
+//
+//   Base class for all ChFunction objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+#include <list>
+
+#include "core/ChApiCE.h"
+#include "core/ChMath.h"
+#include "core/ChRunTimeType.h"
+#include "physics/ChProplist.h"
+
+
+
+namespace chrono 
+{
+
+
+#define CHF_FILE_HEADER_ID  1234.56
+
+
+#define OPT_VARIABLES_START virtual const char** GetOptVariables() {static const char* mOptVars[]={
+#define OPT_VARIABLES_END   0};return mOptVars;}
+
+
+
+
+/// THE INTERFACE BASE CLASS FOR SCALAR FUNCTIONS OF TYPE:
+/// 
+///  y= f(x)
+///
+///
+///  The ChFunction class defines the base class for all Chrono
+/// functions of type y=f(x), that is scalar functions of an 
+/// input variable x (usually, the time). ChFunctions are often
+/// used to set time-dependent properties, for example to set
+/// motion laws in linear actuators, engines, etc.
+///  This base class just represent a constant function of
+/// the type y= C.  Inherited classes must override at least the
+/// Get_y() method, in order to represent more complex functions.
+
+class ChApi ChFunction
+{
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI_ROOT(ChFunction_base);
+
+public:
+	ChFunction () {};
+	virtual ~ChFunction () {};
+	//virtual void Copy (ChFunction* source) =0;
+	virtual ChFunction* new_Duplicate () =0;
+
+				/// Each class inherited from the ChFunction class must
+				/// return an unique integer identifier with the virtual
+				/// function Get_type(). This is useful for fast run-time downcasting etc.
+	virtual int Get_Type () {return -1;}				
+	
+	
+		///// THE MOST IMPORTANT MEMBER FUNCTIONS /////    
+		//       At least Get_y() should be overridden
+		//       by inherited classes.
+
+				/// Returns the y value of the function, at position x. (For this
+				/// base class, it will be a constant value y=C).
+	virtual double Get_y      (double x) =0;
+
+				/// Returns the dy/dx derivative of the function, at position x. 
+				///  Note that inherited classes may also avoid overriding this method,
+				/// because this base method already provide a general-purpose numerical differentiation
+				/// to get dy/dx only from the Get_y() function. (however, if the analytical derivative
+				/// is known, it may better to implement a custom method).
+	virtual double Get_y_dx   (double x) {return ((Get_y(x+ BDF_STEP_LOW) - Get_y(x)) / BDF_STEP_LOW); }
+	
+				/// Returns the ddy/dxdx double derivative of the function, at position x. 
+				///  Note that inherited classes may also avoid overriding this method,
+				/// because this base method already provide a general-purpose numerical differentiation
+				/// to get ddy/dxdx only from the Get_y() function. (however, if the analytical derivative
+				/// is known, it may be better to implement a custom method).
+	virtual double Get_y_dxdx (double x) {return ((Get_y_dx(x+BDF_STEP_LOW) - Get_y_dx(x)) / BDF_STEP_LOW);}; 
+
+		//
+		////////////////////////////////////////
+	
+				/// Returns the weight of the function (useful for 
+				/// applications where you need to mix different weighted ChFunctions)
+	virtual double Get_weight (double) {return 1.0;};
+	
+				/// These functions can be used to implement automatic zooming 
+				/// on the most representative range of function (if GUI is implemented)
+	virtual void Extimate_x_range (double& xmin, double& xmax) {xmin = 0.0; xmax = 1.2;};
+	virtual void Extimate_y_range (double xmin, double xmax, double& ymin, double& ymax, int derivate);
+	
+				/// Generic derivative: if derivate=0 is like Get_y(), if derivate=1 
+				/// is like Get_y_dx(), etc. 
+				/// Note: in current release 'derivate' can be only 0,1,2
+	virtual double Get_y_dN (double x, int derivate);
+			
+
+		//
+		// Some analysis functions. If derivate=0, they are applied on y(x), if derivate =1, on dy/dx, etc.
+		// 
+
+				/// Computes the maximum of y(x) in a range xmin-xmax, using a sampling method.
+	virtual double Compute_max(double xmin, double xmax, double sampling_step, int derivate);
+				/// Computes the minimum of y(x) in a range xmin-xmax, using a sampling method.
+	virtual double Compute_min(double xmin, double xmax, double sampling_step, int derivate);
+				/// Computes the mean value of y(x) in a range xmin-xmax, using a sampling method.
+	virtual double Compute_mean(double xmin, double xmax, double sampling_step, int derivate);
+				/// Computes the square mean val. of y(x) in a range xmin-xmax, using sampling.
+	virtual double Compute_sqrmean(double xmin, double xmax, double sampling_step, int derivate);
+				/// Computes the integral of y(x) in a range xmin-xmax, using a sampling method.
+	virtual double Compute_int(double xmin, double xmax, double sampling_step, int derivate);
+				/// Computes the positive acceleration coefficient (inherited classes should customize this).
+	virtual double Get_Ca_pos () {return 0;};
+				/// Computes the positive acceleration coefficient (inherited classes should customize this).
+	virtual double Get_Ca_neg () {return 0;};
+				/// Computes the speed coefficient (inherited classes must customize this).
+	virtual double Get_Cv () {return 0;};
+
+
+		// Functions which build the tree of optimization variables (or expands it, from given tree)
+		// Each function class should implement (at least) the OPT_VARIABLES_START/END macro, that is return a null-terminated
+		// array of variables which can be get/set as floating point during optimizations.
+		// Variables are strings in C++ /Java/Javascript syntax, that must be interpreted with 
+		// some scripting engine (ex. the Javascript one); see OptVariablesToVector and VectorToOptVariables js tools.
+
+	virtual int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+	static int  VariableTreeToFullNameVar(ChList<chjs_propdata>* mtree, ChList<chjs_fullnamevar>* mlist);
+	virtual int OptVariableCount();
+
+
+	OPT_VARIABLES_START		// here expose no vars ('C' var is added hard-wired in MakeOptVariableTree)
+	OPT_VARIABLES_END		// Inherited classes, at least implement this. If they enclose children funct. obj, also implement the MakeOptVariableTree().
+
+
+				/// If the function has some handles (mouse-sensible markers on screen), 
+				/// implement these functions:
+	virtual int HandleNumber() {return 0;}		// Returns the number of handles of the function
+				/// Gets the x and y position of handle, given identifier. 
+				/// If set mode, x and y values are stored. Return false if handle not found.
+	virtual int HandleAccess(int, double, double, bool) {return TRUE;};
+
+
+			//
+			// STREAMING
+			//
+
+			// Persistent data serialization: file functions. 
+			// Inherited classes may inherit these methods because they could
+			// have additional data.
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii& mstream);
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+		
+				/// Plot function in graph space of the ChFile_ps postscript file
+				/// where zoom factor, centering, colour, thickness etc. are already defined.
+				/// Save function as X-Y pairs separated by space, with CR at each pair,
+				/// into an Ascii file. 
+				/// The output file can be later loaded into Excel, GnuPlot or other tools.
+				/// The function is 'sampled' for nsteps times, from xmin to xmax.
+	virtual int FileAsciiPairsSave(ChStreamOutAscii& m_file, double xmin=0, double xmax=1, int msamples=200);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Const.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Const.cpp
new file mode 100644
index 0000000..bfc76f0
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Const.cpp
@@ -0,0 +1,86 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Const.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Const.h"
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Const> a_registration_const;
+
+void ChFunction_Const::Copy (ChFunction_Const* source)
+{
+	Set_yconst  (source->C);
+}
+
+ChFunction* ChFunction_Const::new_Duplicate ()
+{
+	ChFunction_Const* m_func;
+	m_func = new ChFunction_Const;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+
+void ChFunction_Const::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << C;
+}
+
+void ChFunction_Const::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> C;
+}
+
+void ChFunction_Const::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_CONST  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Const.h b/SRC/ChronoEngine/motion_functions/ChFunction_Const.h
new file mode 100644
index 0000000..af750eb
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Const.h
@@ -0,0 +1,96 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_CONST_H
+#define CHFUNCT_CONST_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Const.h
+//
+//   Function object, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_CONST		0
+
+
+
+/// THE CONSTANT FUNCTION:
+/// 
+///  y= C
+/// 
+
+class ChApi ChFunction_Const : public ChFunction
+{
+		// Chrono simulation of RTTI, needed for serialization 
+		// Btw. should be "CH_RTTI(ChFunction_Const, ..",  but for backward compatibilty with streaming & class factory:
+	CH_RTTI(ChFunction, ChFunction);
+
+private:
+	
+	double C;
+
+public:
+	ChFunction_Const () {C = 0;};
+	ChFunction_Const (double y_constant) {C = y_constant;};
+	virtual ~ChFunction_Const () {};
+	virtual void Copy (ChFunction_Const* source);
+	virtual ChFunction* new_Duplicate ();
+
+	virtual int Get_Type () {return (FUNCT_CONST);}				
+	
+				/// Set the constant C for the function, y=C.
+	void   Set_yconst (double y_constant) {C = y_constant;};
+				/// Get the constant C for the function, y=C.
+	double Get_yconst () {return C;};
+
+				// Override the Get_y(), Get_y_dx etc. functions with analytical formulas.
+
+	virtual double Get_y      (double) {return C;};
+	virtual double Get_y_dx   (double) {return 0;};
+	virtual double Get_y_dxdx (double) {return 0;};
+				
+
+				// Expose the parameters which can be used for optimizations, ex. as Javascript vars.
+
+	OPT_VARIABLES_START
+		"C",
+	OPT_VARIABLES_END
+
+				// Streaming
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_ConstAcc.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_ConstAcc.cpp
new file mode 100644
index 0000000..e33266c
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_ConstAcc.cpp
@@ -0,0 +1,175 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_ConstAcc.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_ConstAcc.h"
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_ConstAcc> a_registration_constacc;
+
+
+void ChFunction_ConstAcc::Copy (ChFunction_ConstAcc* source)
+{
+	h = source->h;
+	av = source->av;
+	aw = source->aw;
+	end = source->end;
+}
+
+ChFunction* ChFunction_ConstAcc::new_Duplicate ()
+{
+	ChFunction_ConstAcc* m_func;
+	m_func = new ChFunction_ConstAcc;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+
+double ChFunction_ConstAcc::Get_y      (double x)
+{
+	double ret = 0;
+	if (x<=0) return 0;
+	if (x>=end) return h;
+	double ev = av*end;
+	double ew = aw*end;
+	double A = 2*h/((ev)*(end-ev+ew));
+	double B = 2*h/((end-ew)*(end-ev+ew));
+	if ((x>0)&&(x<ev))
+	{
+		ret = 0.5*A*x*x;
+	}
+	if ((x>=ev)&&(x<=ew))
+	{
+		ret = A*ev*(x-ev*0.5);
+	}
+	if ((x>ew)&&(x<end))
+	{
+		ret = A*ev*(x-ev*0.5) - B*0.5*pow((x-ew),2);
+	}
+	return ret;
+}
+
+double ChFunction_ConstAcc::Get_y_dx   (double x)
+{
+	double ret = 0;
+	double ev = av*end;
+	double ew = aw*end;
+	double A = 2*h/((ev)*(end-ev+ew));
+	double B = 2*h/((end-ew)*(end-ev+ew));
+	if ((x>0)&&(x<ev))
+	{
+		ret = A*x;
+	}
+	if ((x>=ev)&&(x<=ew))
+	{
+		ret = A*ev;
+	}
+	if ((x>ew)&&(x<end))
+	{
+		ret = A*ev - B*(x-ew);
+	}
+	return ret;
+}
+
+double ChFunction_ConstAcc::Get_y_dxdx (double x)
+{
+	double ret = 0;
+	double ev = av*end;
+	double ew = aw*end;
+	double A = 2*h/((ev)*(end-ev+ew));
+	double B = 2*h/((end-ew)*(end-ev+ew));
+	if ((x>0)&&(x<ev))
+	{
+		ret = A;
+	}
+	if ((x>=ev)&&(x<=ew))
+	{
+		ret = 0;
+	}
+	if ((x>ew)&&(x<end))
+	{
+		ret = -B;
+	}
+	return ret;
+}
+
+double ChFunction_ConstAcc::Get_Ca_pos ()
+{
+	return 2*(end*end)/(av*end*(end - av*end + aw*end));
+}
+double ChFunction_ConstAcc::Get_Ca_neg ()
+{
+	return 2*(end*end)/((end - aw*end)*(end - av*end + aw*end));
+}
+double ChFunction_ConstAcc::Get_Cv ()
+{
+	return 2*(end)/(end - av*end + aw*end);
+}
+
+void ChFunction_ConstAcc::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << h;
+	mstream << aw;
+	mstream << av;
+	mstream << end;
+}
+
+void ChFunction_ConstAcc::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> h;
+	mstream >> aw;
+	mstream >> av;
+	mstream >> end;
+}
+
+void ChFunction_ConstAcc::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_CONST  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_ConstAcc.h b/SRC/ChronoEngine/motion_functions/ChFunction_ConstAcc.h
new file mode 100644
index 0000000..909d06e
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_ConstAcc.h
@@ -0,0 +1,103 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_CONSTACC_H
+#define CHFUNCT_CONSTACC_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_ConstAcc.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_CONSTACC	8
+
+
+
+/// CONSTANT ACCELERATION FUNCTION:  
+/// h = height, amount of displacement
+/// end = duration of motion,
+/// av  = fraction of 1st acceleration end  (0..1)  
+/// aw  = fraction of 2nd acceleration start (0..1) , with aw>av;
+
+class ChApi ChFunction_ConstAcc : public ChFunction
+{
+	CH_RTTI(ChFunction_ConstAcc, ChFunction);
+private:
+	double h;
+	double av;
+	double aw;
+	double end;
+public:
+	ChFunction_ConstAcc () {h =1; av=0.5; aw=0.5;  end=1;}
+	ChFunction_ConstAcc (double m_h, double m_av, double m_aw, double m_end)  {h = m_h; Set_end(m_end); Set_avw(m_av,m_aw);};
+	~ChFunction_ConstAcc () {};
+	void Copy (ChFunction_ConstAcc* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_end  (double m_end)  {if (m_end<0) m_end = 0; end = m_end;}
+	void Set_av   (double m_av)   {if (m_av<0) m_av = 0; if (m_av>1) m_av = 1; av = m_av; if (av>aw) av = aw;}
+	void Set_aw   (double m_aw)   {if (m_aw<0) m_aw = 0; if (m_aw>1) m_aw = 1; aw = m_aw; if (aw<av) aw = av;}
+	void Set_h    (double m_h)    {h = m_h;}
+	void Set_avw  (double m_av, double m_aw)	{av=0; aw=1; Set_av(m_av); Set_aw(m_aw);}
+
+	double Get_end () {return end;}
+	double Get_av ()  {return av;}
+	double Get_aw ()  {return aw;}
+	double Get_h ()   {return h;}
+
+	double Get_y      (double x) ;
+	double Get_y_dx   (double x) ;
+	double Get_y_dxdx (double x) ;
+
+	double Get_Ca_pos ();
+	double Get_Ca_neg ();
+	double Get_Cv ();
+
+	void Extimate_x_range (double& xmin, double& xmax) {xmin = 0.0; xmax = end;};
+
+	int Get_Type () {return (FUNCT_CONSTACC);}
+
+	OPT_VARIABLES_START
+		"h",
+		"end",
+		"aw",
+		"av",
+	OPT_VARIABLES_END
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Derive.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Derive.cpp
new file mode 100644
index 0000000..f4e450f
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Derive.cpp
@@ -0,0 +1,119 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Derive.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Derive.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Derive> a_registration_derive;
+
+
+void ChFunction_Derive::Copy (ChFunction_Derive* source)
+{
+	order = source->order;
+	fa = source->fa->new_Duplicate();
+}
+
+ChFunction* ChFunction_Derive::new_Duplicate ()
+{
+	ChFunction_Derive* m_func;
+	m_func = new ChFunction_Derive;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+double ChFunction_Derive::Get_y      (double x)
+{
+	return fa->Get_y_dx(x);
+}
+
+void ChFunction_Derive::Extimate_x_range (double& xmin, double& xmax)
+{
+	fa->Extimate_x_range(xmin,xmax);
+}
+
+
+int ChFunction_Derive::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	int i=0;
+
+	// inherit parent behaviour
+	ChFunction::MakeOptVariableTree(mtree);
+
+	// expand tree for children..
+
+	chjs_propdata* mdataA = new chjs_propdata;
+	strcpy(mdataA->propname, "fa");
+	strcpy(mdataA->label,    mdataA->propname);
+	mdataA->haschildren = TRUE;
+	mtree->AddTail(mdataA);
+
+	i += this->fa->MakeOptVariableTree(&mdataA->children);
+
+	return i;
+}
+
+void ChFunction_Derive::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << order;
+	mstream.AbstractWrite(fa);
+}
+
+void ChFunction_Derive::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> order;
+
+	if (fa) delete fa; fa=NULL;
+	mstream.AbstractReadCreate(&fa);
+}
+
+void ChFunction_Derive::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_DERIVE  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Derive.h b/SRC/ChronoEngine/motion_functions/ChFunction_Derive.h
new file mode 100644
index 0000000..dc61718
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Derive.h
@@ -0,0 +1,87 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_DERIVE_H
+#define CHFUNCT_DERIVE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Derive.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+#include "ChFunction_Const.h"
+
+
+namespace chrono 
+{
+
+
+#define FUNCT_DERIVE	16
+
+
+/// DERIVATIVE OF A FUNCTION:
+///  y = df/dx  
+///
+/// Uses a numerical differentiation method to compute the derivative
+/// of a generic function.
+
+class ChApi ChFunction_Derive : public ChFunction
+{
+	CH_RTTI(ChFunction_Derive, ChFunction);
+private:
+	ChFunction* fa;
+	int order;			// 1= derive one time, 2= two times, etc.
+
+public:
+	ChFunction_Derive() {order = 1; fa = new ChFunction_Const;}
+	~ChFunction_Derive () {if (fa) delete fa;};
+	void Copy (ChFunction_Derive* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_order  (int m_order)  {order = m_order;}
+	int Get_order () {return order;}
+
+	void Set_fa  (ChFunction* m_fa)  {fa = m_fa;}
+	ChFunction* Get_fa () {return fa;}
+	
+	double Get_y      (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax);
+	
+	int Get_Type () {return (FUNCT_DERIVE);}
+
+	int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Fillet3.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Fillet3.cpp
new file mode 100644
index 0000000..8cf2acf
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Fillet3.cpp
@@ -0,0 +1,163 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Fillet3.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Fillet3.h"
+#include "core/ChLinearAlgebra.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Fillet3> a_registration_fillet3;
+
+
+void ChFunction_Fillet3::Copy (ChFunction_Fillet3* source)
+{
+	end = source->end;
+	y1  = source->y1;
+	y2 = source->y2;
+	dy1 = source->dy1;
+	dy2 = source->dy2;
+
+	SetupCoefficients();
+}
+
+ChFunction* ChFunction_Fillet3::new_Duplicate ()
+{
+	ChFunction_Fillet3* m_func;
+	m_func = new ChFunction_Fillet3;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+
+double ChFunction_Fillet3::Get_y      (double x)
+{
+	double ret = 0;
+	if (x<=0) return y1;
+	if (x>=end) return y2;
+	double a = x/end;
+	ret = c1*pow(x,3) + c2*pow(x,2) + c3*x + c4;
+ 	return ret;
+}
+
+double ChFunction_Fillet3::Get_y_dx      (double x)
+{
+	double ret = 0;
+	if (x<=0) return 0;
+	if (x>=end) return 0;
+	double a = x/end;
+	ret = 3*c1*pow(x,2) + 2*c2*x + c3;
+ 	return ret;
+}
+
+double ChFunction_Fillet3::Get_y_dxdx      (double x)
+{
+	double ret = 0;
+	if (x<=0) return 0;
+	if (x>=end) return 0;
+	double a = x/end;
+	ret = 6*c1*x + 2*c2;
+ 	return ret;
+}
+
+int ChFunction_Fillet3::SetupCoefficients()
+{
+	ChMatrixDynamic<> ma(4,4);
+	ChMatrixDynamic<> mb(4,1);
+	ChMatrixDynamic<> mx(4,1);
+
+	mb(0,0) = y1;
+	mb(1,0) = y2;
+	mb(2,0) = dy1;
+	mb(3,0) = dy2;
+
+	ma(0,3) = 1.0;
+
+	ma(1,0) = pow(end,3);
+	ma(1,1) = pow(end,2);
+	ma(1,2) = end;
+	ma(1,3) = 1.0;
+
+	ma(2,2) = 1.0;
+
+	ma(3,0) = 3*pow(end,2);
+	ma(3,1) = 2*end;
+	ma(3,2) = 1.0;
+
+	ChLinearAlgebra::Solve_LinSys(ma, &mb, &mx);
+
+	c1= mx(0,0);	c2= mx(1,0);	c3= mx(2,0);	c4= mx(3,0);
+
+ 	return TRUE;
+}
+
+void ChFunction_Fillet3::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << end;
+	mstream << y1;
+	mstream << y2;
+	mstream << dy1;
+	mstream << dy2;
+}
+
+void ChFunction_Fillet3::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> end;
+	mstream >> y1;
+	mstream >> y2;
+	mstream >> dy1;
+	mstream >> dy2;
+	SetupCoefficients();
+}
+
+void ChFunction_Fillet3::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_FILLET3  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Fillet3.h b/SRC/ChronoEngine/motion_functions/ChFunction_Fillet3.h
new file mode 100644
index 0000000..ac9b72d
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Fillet3.h
@@ -0,0 +1,98 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_FILLET3_H
+#define CHFUNCT_FILLET3_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Fillet3.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+
+#define FUNCT_FILLET3	10
+
+
+/// A CUBIC FILLET (cubic poly with C0 C1 boundary conditions)  
+///  - y1 = y at the beginning
+///  - dy1 = y' at the beginning
+///  - y2 = y at the end
+///  - dy2 = y' at the end
+
+class ChApi ChFunction_Fillet3 : public ChFunction
+{
+	CH_RTTI(ChFunction_Fillet, ChFunction);
+private:
+	double end;
+	double y1;
+	double y2;
+	double dy1;
+	double dy2;
+
+	double c1, c2, c3, c4;	// used internally...
+
+public:
+	ChFunction_Fillet3 () {y1 = y2 = dy1 = dy2 = c1 = c2 = c3 = c4 = 0; end = 1.0;}
+	~ChFunction_Fillet3 () {};
+	void Copy (ChFunction_Fillet3* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_end  (double m_end)  {if (m_end<0) m_end = 0; end = m_end; SetupCoefficients();}
+	double Get_end () {return end;}
+
+	int SetupCoefficients();
+
+	void Set_y1(double my1) {y1 = my1; SetupCoefficients();}
+	void Set_y2(double my2) {y2 = my2; SetupCoefficients();}
+	void Set_dy1(double mdy1) {dy1 = mdy1; SetupCoefficients();}
+	void Set_dy2(double mdy2) {dy2 = mdy2; SetupCoefficients();}
+
+	double Get_y1() {return y1;}
+	double Get_y2() {return y2;}
+	double Get_dy1() {return dy1;}
+	double Get_dy2() {return dy2;}	
+
+	double Get_y      (double x) ;
+	double Get_y_dx   (double x) ;
+	double Get_y_dxdx (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax) {xmin = 0.0; xmax = end;};
+	int Get_Type () {return (FUNCT_FILLET3);}
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Integrate.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Integrate.cpp
new file mode 100644
index 0000000..3ae037f
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Integrate.cpp
@@ -0,0 +1,185 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Integrate.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Integrate.h"
+#include "ChFunction_Const.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Integrate> a_registration_integrate;
+
+
+ChFunction_Integrate::ChFunction_Integrate()
+{
+	order = 1;
+	fa = new ChFunction_Const; // default 
+	C_start= x_start=0;
+	x_end=1;
+	num_samples=2000;
+	array_x = new ChMatrixDynamic<>(num_samples,1);
+}
+
+void ChFunction_Integrate::Copy (ChFunction_Integrate* source)
+{
+	order = source->order;
+	fa = source->fa->new_Duplicate();
+	C_start = source->C_start;
+	x_start = source->x_start;
+	x_end = source->x_end;
+	num_samples= source->num_samples;
+	array_x->CopyFromMatrix(*source->array_x);
+}
+
+ChFunction* ChFunction_Integrate::new_Duplicate ()
+{
+	ChFunction_Integrate* m_func;
+	m_func = new ChFunction_Integrate;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+void ChFunction_Integrate::ComputeIntegral()
+{
+	double mstep= (x_end - x_start)/((double)(num_samples-1));
+	double x_a , x_b, y_a, y_b, F_b;
+
+	double F_sum = this->Get_C_start();
+
+	this->array_x->SetElement(0,0, this->Get_C_start());
+
+	for (int i=1; i<this->num_samples; i++)
+	{
+		x_b = x_start + ((double)i)*(mstep);
+		x_a = x_b - mstep;
+		y_a = this->fa->Get_y(x_a);
+		y_b = this->fa->Get_y(x_b);
+		 // trapezoidal rule..
+		F_b = F_sum + mstep * (y_a + y_b )* 0.5;
+		this->array_x->SetElement(i,0, F_b );
+		F_sum = F_b;
+	}
+}
+
+double ChFunction_Integrate::Get_y      (double x)
+{
+	if ((x<x_start)||(x>x_end))
+		return 0.0;
+	int i_a, i_b;
+	double position = (double)(num_samples-1)*((x-x_start)/(x_end-x_start));
+	i_a = (int)(floor(position));
+	i_b = i_a+1;
+
+	if (i_a==num_samples-1)
+		return array_x->GetElement(num_samples-1,0);
+
+	if ((i_a<0)||(i_b>=num_samples))
+		return 0.0;
+
+	double weightB = position - (double)i_a;
+	double weightA = 1- weightB;
+
+	return ( weightA*(array_x->GetElement(i_a,0)) +
+			 weightB*(array_x->GetElement(i_b,0))   );
+}
+
+void ChFunction_Integrate::Extimate_x_range (double& xmin, double& xmax)
+{
+	xmin = x_start;
+	xmax = x_end;
+}
+
+int ChFunction_Integrate::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	int i=0;
+
+	// inherit parent behaviour
+	ChFunction::MakeOptVariableTree(mtree);
+
+	// expand tree for children..
+
+	chjs_propdata* mdataA = new chjs_propdata;
+	strcpy(mdataA->propname, "fa");
+	strcpy(mdataA->label,    mdataA->propname);
+	mdataA->haschildren = TRUE;
+	mtree->AddTail(mdataA);
+
+	i += this->fa->MakeOptVariableTree(&mdataA->children);
+
+	return i;
+}
+
+void ChFunction_Integrate::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << Get_order();
+	mstream << Get_C_start();
+	mstream << Get_x_start();
+	mstream << Get_x_end();
+	mstream << Get_num_samples();
+	mstream.AbstractWrite(fa);
+}
+
+void ChFunction_Integrate::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	int ifoo;
+	double dfoo;
+	mstream >> ifoo;			Set_order(ifoo);
+	mstream >> dfoo;			Set_C_start(dfoo);
+	mstream >> dfoo;			Set_x_start(dfoo);
+	mstream >> dfoo;			Set_x_end(dfoo);
+	mstream >> ifoo;			Set_num_samples(ifoo);
+	if (fa) delete fa; fa=NULL;
+	mstream.AbstractReadCreate(&fa);
+}
+
+void ChFunction_Integrate::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_INTEGRATE  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Integrate.h b/SRC/ChronoEngine/motion_functions/ChFunction_Integrate.h
new file mode 100644
index 0000000..e599ce1
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Integrate.h
@@ -0,0 +1,101 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_INTEGRATE_H
+#define CHFUNCT_INTEGRATE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Integrate.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_INTEGRATE	17
+
+
+/// INTEGRAL OF A FUNCTION:
+/// y = int{ f(x) dx  
+///
+/// Uses a numerical quadrature method to compute the definite integral. 
+
+class ChApi ChFunction_Integrate : public ChFunction
+{
+	CH_RTTI(ChFunction_Integrate, ChFunction);
+private:
+	ChFunction* fa;
+	int order;			// 1= Integrate one time, 2= two times, etc.
+	double C_start;
+	double x_start;
+	double x_end;
+	int num_samples;
+	ChMatrix<>* array_x;
+public:
+	ChFunction_Integrate();
+	~ChFunction_Integrate () {if (fa) delete fa; if (array_x) delete array_x;};
+	void Copy (ChFunction_Integrate* source);
+	ChFunction* new_Duplicate ();
+
+	void ComputeIntegral();
+	
+	void Set_order  (int m_order)  {order = m_order;}
+	int Get_order () {return order;}
+	void Set_num_samples  (int m_samples)  {num_samples = m_samples; array_x->Reset(num_samples,1);  ComputeIntegral();}
+	int Get_num_samples() {return num_samples;}
+	void Set_C_start  (double m_val)  {C_start = m_val; ComputeIntegral();}
+	double Get_C_start () {return C_start;}
+	void Set_x_start  (double m_val)  {x_start = m_val; ComputeIntegral();}
+	double Get_x_start () {return x_start;}
+	void Set_x_end  (double m_val)  {x_end = m_val; ComputeIntegral();}
+	double Get_x_end () {return x_end;}
+	void Set_fa  (ChFunction* m_fa)  {fa = m_fa; ComputeIntegral();}
+	ChFunction* Get_fa () {return fa;}
+
+	double Get_y      (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax);
+	
+	int Get_Type () {return (FUNCT_INTEGRATE);}
+
+	int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+	OPT_VARIABLES_START
+		"C_start",
+	OPT_VARIABLES_END
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Matlab.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Matlab.cpp
new file mode 100644
index 0000000..8a0ebda
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Matlab.cpp
@@ -0,0 +1,111 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Matlab.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Matlab.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Matlab> a_registration_matlab;
+
+ChFunction_Matlab::ChFunction_Matlab ()
+{
+	strcpy(this->mat_command,"x*2+x^2");
+}
+
+void ChFunction_Matlab::Copy (ChFunction_Matlab* source)
+{
+	strcpy(this->mat_command, source->mat_command);
+}
+
+ChFunction* ChFunction_Matlab::new_Duplicate ()
+{
+	ChFunction_Matlab* m_func;
+	m_func = new ChFunction_Matlab;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+double ChFunction_Matlab::Get_y      (double x)
+{
+	double ret = 0;
+
+	static char m_eval_command[CHF_MATLAB_STRING_LEN+20];
+
+	#ifdef CH_MATLAB
+	 // no function: shortcut!
+	if (*this->mat_command == NULL) return 0.0;
+
+	 // set string as "x=[x];ans=[mat_command]"
+	 sprintf (m_eval_command, "x=%g;ans=%s;", x,this->mat_command);
+
+	 // EVAL string, retrieving y = "ans"
+	 ret = CHGLOBALS().Mat_Eng_Eval(m_eval_command);
+
+	#else
+	 ret = 0.0;
+	#endif
+
+	return ret;
+}
+
+void ChFunction_Matlab::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << mat_command;
+}
+
+void ChFunction_Matlab::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> mat_command;
+}
+
+void ChFunction_Matlab::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_MATLAB  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Matlab.h b/SRC/ChronoEngine/motion_functions/ChFunction_Matlab.h
new file mode 100644
index 0000000..d34f9b2
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Matlab.h
@@ -0,0 +1,80 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_MATLAB_H
+#define CHFUNCT_MATLAB_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Matlab.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+
+#define FUNCT_MATLAB    13
+
+#define CHF_MATLAB_STRING_LEN 200
+
+
+
+/// MATLAB FUNCTION:
+/// y = matlab evaluation of function y=f(x)  
+/// 
+
+class ChApi ChFunction_Matlab : public ChFunction
+{
+	CH_RTTI(ChFunction_Matlab, ChFunction);
+private:
+	char mat_command[CHF_MATLAB_STRING_LEN];			// matlab command
+public:
+	ChFunction_Matlab();
+	~ChFunction_Matlab() {};
+	void Copy (ChFunction_Matlab* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_Command  (char* m_command)  {strcpy (mat_command, m_command);};
+	char* Get_Command  ()  {return mat_command;};
+
+	double Get_y      (double x);
+	double Get_y_dx   (double x) {return ((Get_y(x+ BDF_STEP_HIGH) - Get_y(x)) / BDF_STEP_HIGH); }//((Get_y(x+BDF_STEP_VERYLOW) - Get_y(x)) / BDF_STEP_VERYLOW);};  // return 0;
+	double Get_y_dxdx (double x) {return ((Get_y_dx(x+BDF_STEP_HIGH) - Get_y_dx(x)) / BDF_STEP_HIGH);}; // return 0;
+
+	int Get_Type () {return (FUNCT_MATLAB);}
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Mirror.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Mirror.cpp
new file mode 100644
index 0000000..0682160
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Mirror.cpp
@@ -0,0 +1,120 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Mirror.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Mirror.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Mirror> a_registration_mirror;
+
+
+void ChFunction_Mirror::Copy (ChFunction_Mirror* source)
+{
+	mirror_axis = source->mirror_axis;
+	fa = source->fa->new_Duplicate();
+}
+
+ChFunction* ChFunction_Mirror::new_Duplicate ()
+{
+	ChFunction_Mirror* m_func;
+	m_func = new ChFunction_Mirror;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+double ChFunction_Mirror::Get_y      (double x)
+{
+	if (x<= this->mirror_axis)
+		return fa->Get_y(x);
+	return fa->Get_y(2*this->mirror_axis - x);
+}
+
+void ChFunction_Mirror::Extimate_x_range (double& xmin, double& xmax)
+{
+	fa->Extimate_x_range(xmin,xmax);
+}
+
+int ChFunction_Mirror::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	int i=0;
+
+	// inherit parent behaviour
+	ChFunction::MakeOptVariableTree(mtree);
+
+	// expand tree for children..
+
+	chjs_propdata* mdataA = new chjs_propdata;
+	strcpy(mdataA->propname, "fa");
+	strcpy(mdataA->label,    mdataA->propname);
+	mdataA->haschildren = TRUE;
+	mtree->AddTail(mdataA);
+
+	i += this->fa->MakeOptVariableTree(&mdataA->children);
+
+	return i;
+}
+
+
+void ChFunction_Mirror::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << mirror_axis;
+	mstream.AbstractWrite(fa);
+}
+
+void ChFunction_Mirror::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> mirror_axis;
+	if (fa) delete fa; fa=NULL;
+	mstream.AbstractReadCreate(&fa);
+}
+
+void ChFunction_Mirror::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_MIRROR  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Mirror.h b/SRC/ChronoEngine/motion_functions/ChFunction_Mirror.h
new file mode 100644
index 0000000..e9fa203
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Mirror.h
@@ -0,0 +1,89 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_MIRROR_H
+#define CHFUNCT_MIRROR_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Mirror.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+#include "ChFunction_Const.h"
+
+
+namespace chrono 
+{
+
+
+#define FUNCT_MIRROR	18
+
+
+
+/// MIRROR FUNCTION:
+/// y = __/\__ 
+///
+/// Mirrors a function about a vertical axis.
+
+class ChApi ChFunction_Mirror : public ChFunction
+{
+	CH_RTTI(ChFunction_Mirror, ChFunction);
+private:
+	ChFunction* fa;
+	double mirror_axis;			// simmetry axis position on x
+
+public:
+	ChFunction_Mirror() {mirror_axis = 0; fa = new ChFunction_Const;}
+	~ChFunction_Mirror () {if (fa) delete fa;};
+	void Copy (ChFunction_Mirror* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_mirror_axis  (double m_axis)  {mirror_axis = m_axis;}
+	double Get_mirror_axis () {return mirror_axis;}
+
+	void Set_fa  (ChFunction* m_fa)  {fa = m_fa;}
+	ChFunction* Get_fa () {return fa;}
+	
+	double Get_y      (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax);
+	int Get_Type () {return (FUNCT_MIRROR);}
+
+	int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+	OPT_VARIABLES_START
+		"mirror_axis",
+	OPT_VARIABLES_END
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Mocap.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Mocap.cpp
new file mode 100644
index 0000000..b814265
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Mocap.cpp
@@ -0,0 +1,269 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Mocap.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Mocap.h"
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Mocap> a_registration_mocap;
+
+
+ChFunction_Mocap::ChFunction_Mocap ()
+{
+	array_y = NULL;
+	array_y_dt = NULL;
+	array_y_dtdt = NULL;
+
+	Set_samples (2);	// this creates arrays
+	Set_samp_freq(50);
+}
+
+ChFunction_Mocap::ChFunction_Mocap (int m_samples, double freq)
+{
+	array_y = NULL;
+	array_y_dt = NULL;
+	array_y_dtdt = NULL;
+
+	Set_samples (m_samples); 	// this creates arrays
+	Set_samp_freq(freq);
+}
+
+ChFunction_Mocap::~ChFunction_Mocap ()
+{
+	if (array_y != NULL) delete array_y;
+	if (array_y_dt != NULL) delete array_y_dt;
+	if (array_y_dtdt != NULL) delete array_y_dtdt;
+}
+
+void ChFunction_Mocap::Copy (ChFunction_Mocap* source)
+{
+	Set_samples (source->samples);	// this creates arrays
+	Set_samp_freq(source->samp_freq);
+
+	if (source->Get_array_y()) array_y->CopyFromMatrix(*source->Get_array_y());
+	if (source->Get_array_y_dt()) array_y_dt->CopyFromMatrix(*source->Get_array_y_dt());
+	if (source->Get_array_y_dtdt()) array_y_dtdt->CopyFromMatrix(*source->Get_array_y_dtdt());
+}
+
+ChFunction* ChFunction_Mocap::new_Duplicate ()
+{
+	ChFunction_Mocap* m_func;
+	m_func = new ChFunction_Mocap;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+void ChFunction_Mocap::Extimate_x_range (double& xmin, double& xmax)
+{
+	xmin = 0.0;
+	xmax = Get_timetot();
+}
+
+
+void ChFunction_Mocap::Set_samp_freq (double m_fr)
+{
+	samp_freq = m_fr;
+	timetot = ((double)samples / samp_freq);
+}
+
+void ChFunction_Mocap::Set_samples (int m_samples)
+{
+	samples = m_samples;
+
+	if (samples<2)
+		samples =2;
+
+	timetot = ((double)samples / samp_freq);
+
+	if (array_y != NULL) delete array_y;
+	if (array_y_dt != NULL) delete array_y_dt;
+	if (array_y_dtdt != NULL) delete array_y_dtdt;
+
+	array_y = new ChMatrixDynamic<> (1, samples);
+	array_y_dt = new ChMatrixDynamic<> (1, samples);
+	array_y_dtdt = new ChMatrixDynamic<> (1, samples);
+}
+
+
+
+// compute all the y_dt basing on y, using the
+// trapezioidal rule for numerical differentiation
+
+void ChFunction_Mocap::Compute_array_dt  (ChMatrix<>* array_A, ChMatrix<>* array_A_dt)
+{
+	int i, ia, ib;
+	double y_dt;
+
+	for (i=0; i < samples; i++)
+	{
+		ia = i - 1;		// boundaries cases
+		if (ia <= 0) { ia = 0;};
+		ib = i + 1;
+		if (ib >= samples) {ib = i;};
+						// trapezioidal differentiation
+		y_dt= ( (array_A->GetElement(0,ib))-
+			    (array_A->GetElement(0,ia))  ) / Get_timeslice();
+
+		array_A_dt->SetElement(0,i, y_dt);
+	}
+}
+
+
+// Interpolation of the in-between values, given the discrete
+// sample array (uniformly spaced points)
+
+double ChFunction_Mocap::LinInterp (ChMatrix<>* m_array, double x, double x_max)
+{
+	double position;
+	double weightA, weightB;
+	int ia, ib;
+
+	position =((double)samples * (x/x_max));
+
+	ia = (int) floor(position);
+	if (ia < 0) {ia = 0;};
+	if (ia >=samples) {ia= samples-1;}
+
+	ib = ia + 1;
+	if (ib < 0) {ib = 0;};
+	if (ib >= samples) {ib = samples-1;};
+
+	weightB = position - (int) position;
+	weightA = 1- weightB;
+
+	return ( weightA*(m_array->GetElement(0,ia)) +
+			 weightB*(m_array->GetElement(0,ib))   );
+}
+
+
+// Setup of arrays, provided as external vectors of
+// samples. These functions automatically compute the
+// derivatives (the arrays .._y_dt and y_dtdt)
+
+void ChFunction_Mocap::Set_array_y	  (ChMatrix<>* m_array_y)
+{
+	array_y->CopyFromMatrix(*m_array_y);
+
+	Compute_array_dt (array_y,    array_y_dt);
+	Compute_array_dt (array_y_dt, array_y_dtdt);
+}
+
+void ChFunction_Mocap::Set_array_y_dt	  (ChMatrix<>* m_array_y_dt)
+{
+	// *** TO DO  ***
+}
+
+void ChFunction_Mocap::Set_array_y_dtdt   (ChMatrix<>* m_array_y_dtdt)
+{
+	// *** TO DO  ***
+}
+
+
+// Parsing of external files, to create mocap streams
+// from the output of mocap devices
+
+int  ChFunction_Mocap::Parse_array_AOA ()
+{
+	// *** TO DO **** //
+	return TRUE;
+}
+
+int	 ChFunction_Mocap::Parse_array_Elite ()
+{
+	// *** TO DO **** //
+	return TRUE;
+}
+
+
+
+
+// Return the value of the evaluated function, using
+// linear interpolation to guess the in-between points,
+// having the array samples as references.
+
+double ChFunction_Mocap::Get_y      (double x)
+{
+	return LinInterp (array_y, x, timetot);
+}
+
+double ChFunction_Mocap::Get_y_dx   (double x)
+{
+	return LinInterp (array_y_dt, x, timetot);
+}
+
+double ChFunction_Mocap::Get_y_dxdx (double x)
+{
+	return LinInterp (array_y_dtdt, x, timetot);
+}
+
+
+
+// File parsing and dumping
+
+void ChFunction_Mocap::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->Get_samples();
+	mstream << this->Get_samp_freq();
+	mstream << *this->array_y;
+}
+
+void ChFunction_Mocap::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	double dfoo;
+	int ifoo;
+	mstream >> ifoo;	Set_samples(ifoo);
+	mstream >> dfoo;	Set_samp_freq(dfoo);
+	mstream >> *this->array_y;
+}
+
+void ChFunction_Mocap::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_MOCAP  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Mocap.h b/SRC/ChronoEngine/motion_functions/ChFunction_Mocap.h
new file mode 100644
index 0000000..2985a7b
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Mocap.h
@@ -0,0 +1,102 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_MOCAP_H
+#define CHFUNCT_MOCAP_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Mocap.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_MOCAP		3
+
+
+/// MOTION CAPTURE (SAMPLE) FUNCTION
+/// y = (linear interpolated array of samples)
+
+class ChApi ChFunction_Mocap : public ChFunction
+{
+	CH_RTTI(ChFunction_Mocap, ChFunction);
+private:
+	ChMatrix<>* array_y;
+	ChMatrix<>* array_y_dt;
+	ChMatrix<>* array_y_dtdt;
+
+	double samp_freq;
+	int    samples;
+	double timetot;
+
+public:
+	ChFunction_Mocap (); //  see .cpp
+	ChFunction_Mocap (int m_samples, double freq);  //  see .cpp
+	~ChFunction_Mocap ();	//  see .cpp
+	void Copy (ChFunction_Mocap* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_samp_freq (double m_fr) ; // see .cpp
+	void Set_samples (int m_samples) ; // see .cpp
+
+	double Get_samp_freq () {return samp_freq;};
+	int	   Get_samples	 () {return samples;};
+	double Get_timetot	 () {return ((double)samples/samp_freq);};
+	double Get_timeslice () {return (1/samp_freq);};
+
+	ChMatrix<>* Get_array_y() {return array_y;};
+	ChMatrix<>* Get_array_y_dt() {return array_y_dt;};
+	ChMatrix<>* Get_array_y_dtdt() {return array_y_dtdt;};
+	
+	void Set_array_y	  (ChMatrix<>* m_array_y); // see cpp
+	void Set_array_y_dt	  (ChMatrix<>* m_array_y_dt);  // *** TO DO
+	void Set_array_y_dtdt (ChMatrix<>* m_array_y_dtdt);// *** TO DO
+
+	int  Parse_array_AOA ();	// *** TO DO
+	int	 Parse_array_Elite ();	// *** TO DO
+
+	void   Compute_array_dt   (ChMatrix<>* array_A, ChMatrix<>* array_A_dt);
+	double LinInterp (ChMatrix<>* m_array, double x, double x_max);
+
+	double Get_y      (double x);	// see.cpp
+	double Get_y_dx   (double x);	// see.cpp
+	double Get_y_dxdx (double x);	// see.cpp
+
+	void Extimate_x_range (double& xmin, double& xmax);
+	int Get_Type () {return (FUNCT_MOCAP);}
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Noise.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Noise.cpp
new file mode 100644
index 0000000..42c1cd2
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Noise.cpp
@@ -0,0 +1,105 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Noise.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Noise.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Noise> a_registration_noise;
+
+
+ChFunction_Noise::ChFunction_Noise ()
+{
+	this->amp = 1;
+	this->octaves = 2;
+	this->amp_ratio = 0.5;
+	this->freq = 1;
+}
+
+void ChFunction_Noise::Copy (ChFunction_Noise* source)
+{
+	this->amp = source->amp;
+	this->freq = source->freq;
+	this->amp_ratio = source->amp_ratio;
+	this->octaves = source->octaves;
+}
+
+ChFunction* ChFunction_Noise::new_Duplicate ()
+{
+	ChFunction_Noise* m_func;
+	m_func = new ChFunction_Noise;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+double ChFunction_Noise::Get_y      (double x)
+{
+	return ChNoise(x,amp,freq,octaves,amp_ratio);
+}
+
+void ChFunction_Noise::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << amp;
+	mstream << freq;
+	mstream << amp_ratio;
+	mstream << octaves;
+}
+
+void ChFunction_Noise::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> amp;
+	mstream >> freq;
+	mstream >> amp_ratio;
+	mstream >> octaves;
+}
+
+void ChFunction_Noise::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_NOISE  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Noise.h b/SRC/ChronoEngine/motion_functions/ChFunction_Noise.h
new file mode 100644
index 0000000..eb130a9
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Noise.h
@@ -0,0 +1,81 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_NOISE_H
+#define CHFUNCT_NOISE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Noise.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_NOISE		15
+
+
+/// NOISE FUNCTION:
+/// y = multi-octave noise with cubic interpolation  
+/// 
+
+class ChApi ChFunction_Noise : public ChFunction
+{
+	CH_RTTI(ChFunction_Noise, ChFunction);
+private:
+	double amp;
+	double freq;
+	double amp_ratio;
+	int octaves;
+public:
+	ChFunction_Noise();
+	~ChFunction_Noise() {};
+	void Copy (ChFunction_Noise* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_Amp (double mamp) {amp = mamp;} 
+	double Get_Amp ()  {return amp;};
+	void Set_Freq (double mf) {freq = mf;} 
+	double Get_Freq ()  {return freq;};
+	void Set_AmpRatio (double ma) {amp_ratio = ma;} 
+	double Get_AmpRatio ()  {return amp_ratio;};
+	void Set_Octaves (int mo) {octaves = mo;} 
+	int Get_Octaves ()  {return octaves;};
+
+	double Get_y      (double x);
+
+	int Get_Type () {return (FUNCT_NOISE);}
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Operation.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Operation.cpp
new file mode 100644
index 0000000..d06e8be
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Operation.cpp
@@ -0,0 +1,176 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Operation.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Operation.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Operation> a_registration_operation;
+
+
+void ChFunction_Operation::Copy (ChFunction_Operation* source)
+{
+	op_type = source->op_type;
+	fa = source->fa->new_Duplicate();
+	fb = source->fb->new_Duplicate();
+}
+
+ChFunction* ChFunction_Operation::new_Duplicate ()
+{
+	ChFunction_Operation* m_func;
+	m_func = new ChFunction_Operation;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+double ChFunction_Operation::Get_y      (double x)
+{
+	double res;
+
+	switch (op_type)
+	{
+	case ChOP_ADD:
+		res = fa->Get_y(x) + fb->Get_y(x); break;
+	case ChOP_SUB:
+		res = fa->Get_y(x) - fb->Get_y(x); break;
+	case ChOP_MUL:
+		res = fa->Get_y(x) * fb->Get_y(x); break;
+	case ChOP_DIV:
+		res = fa->Get_y(x) / fb->Get_y(x); break;
+	case ChOP_POW:
+		res = pow (fa->Get_y(x), fb->Get_y(x)); break;
+	case ChOP_MAX:
+		res = ChMax (fa->Get_y(x), fb->Get_y(x)); break;
+	case ChOP_MIN:
+		res = ChMin (fa->Get_y(x), fb->Get_y(x)); break;
+	case ChOP_MODULO:
+		res = fmod (fa->Get_y(x), fb->Get_y(x)); break;
+	case ChOP_FABS :
+		res = fabs (fa->Get_y(x)); break;
+	case ChOP_FUNCT :
+		res = fa->Get_y(fb->Get_y(x)); break;
+	default:
+		res = 0; break;
+	}
+	return res;
+}
+/*
+double ChFunction_Operation::Get_y_dx   (double x)
+{
+	double res = 0;
+	res = ChFunction::Get_y_dx(x); // default: numerical differentiation
+	return res;
+}
+
+double ChFunction_Operation::Get_y_dxdx (double x)
+{
+	double res = 0;
+	res = ChFunction::Get_y_dxdx(x); // default: numerical differentiation
+	return res;
+}
+*/
+void ChFunction_Operation::Extimate_x_range (double& xmin, double& xmax)
+{
+	double amin, amax, bmin, bmax;
+	fa->Extimate_x_range(amin,amax);
+	fb->Extimate_x_range(bmin,bmax);
+	xmin = ChMin(amin, bmin);
+	xmax = ChMax(amax, bmax);
+}
+
+int ChFunction_Operation::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	int i=0;
+
+	// inherit parent behaviour
+	ChFunction::MakeOptVariableTree(mtree);
+
+	// expand tree for the two children..
+
+	chjs_propdata* mdataA = new chjs_propdata;
+	strcpy(mdataA->propname, "fa");
+	strcpy(mdataA->label,    mdataA->propname);
+	mdataA->haschildren = TRUE;
+	mtree->AddTail(mdataA);
+
+	i += this->fa->MakeOptVariableTree(&mdataA->children);
+
+	chjs_propdata* mdataB = new chjs_propdata;
+	strcpy(mdataB->propname, "fb");
+	strcpy(mdataB->label,    mdataB->propname);
+	mdataB->haschildren = TRUE;
+	mtree->AddTail(mdataB);
+
+	i += this->fb->MakeOptVariableTree(&mdataB->children);
+
+	return i;
+}
+
+void ChFunction_Operation::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << op_type;
+	mstream.AbstractWrite(fa);
+	mstream.AbstractWrite(fb);
+}
+
+void ChFunction_Operation::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> op_type;
+
+	if (fa) delete fa; fa=NULL;
+	mstream.AbstractReadCreate(&fa);
+	if (fb) delete fb; fb=NULL;
+	mstream.AbstractReadCreate(&fb);
+}
+
+void ChFunction_Operation::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_OPERATION  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Operation.h b/SRC/ChronoEngine/motion_functions/ChFunction_Operation.h
new file mode 100644
index 0000000..75039b8
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Operation.h
@@ -0,0 +1,104 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_OPERATION_H
+#define CHFUNCT_OPERATION_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Operation.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+#include "ChFunction_Const.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_OPERATION 12
+
+
+enum {
+	ChOP_ADD = 0,
+	ChOP_SUB,
+	ChOP_MUL,
+	ChOP_DIV,
+	ChOP_POW,
+	ChOP_MAX,
+	ChOP_MIN,
+	ChOP_MODULO,
+	ChOP_FABS,
+	ChOP_FUNCT,
+};
+
+/// OPERATION BETWEEN FUNCTIONS
+/// (math operation between A and  B operands  
+///   - fa = first operand function
+///   - fb = second operand function
+
+class ChApi ChFunction_Operation : public ChFunction
+{
+	CH_RTTI(ChFunction_Operation, ChFunction);
+private:
+	ChFunction* fa;
+	ChFunction* fb;
+	int op_type;		// see operation type IDS
+
+public:
+	ChFunction_Operation() {op_type = ChOP_ADD; fa = new ChFunction_Const; fb = new ChFunction_Const; }
+	~ChFunction_Operation () {if (fa) delete fa; if (fb) delete fb;};
+	void Copy (ChFunction_Operation* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_optype  (int m_op)  {op_type = m_op;}
+	int Get_optype () {return op_type;}
+
+	void Set_fa  (ChFunction* m_fa)  {fa = m_fa;}
+	ChFunction* Get_fa () {return fa;}
+	
+	void Set_fb  (ChFunction* m_fb)  {fb = m_fb;}
+	ChFunction* Get_fb () {return fb;}
+
+	double Get_y      (double x) ;
+	//	double Get_y_dx   (double x) ;
+	//	double Get_y_dxdx (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax);
+
+	int Get_Type () {return (FUNCT_OPERATION);}
+	
+	int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+	
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Oscilloscope.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Oscilloscope.cpp
new file mode 100644
index 0000000..235128d
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Oscilloscope.cpp
@@ -0,0 +1,168 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Oscilloscope.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Oscilloscope.h"
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Oscilloscope> a_registration_oscilloscope;
+
+
+void ChFunction_Oscilloscope::Copy (ChFunction_Oscilloscope* source)
+{
+	this->values = source->values;
+	this->dx = source->dx;
+	this->end_x = source->end_x;
+	this->amount = source->amount;
+	this->max_amount = source->max_amount;
+}
+
+ChFunction* ChFunction_Oscilloscope::new_Duplicate ()
+{
+	ChFunction_Oscilloscope* m_func;
+	m_func = new ChFunction_Oscilloscope;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+void ChFunction_Oscilloscope::Extimate_x_range (double& xmin, double& xmax)
+{
+	xmin = this->end_x - this->dx*(this->amount-1);
+	xmax = this->end_x;
+	if (xmin >= xmax) xmax = xmin+ 0.5;
+}
+
+
+int ChFunction_Oscilloscope::AddLastPoint (double mx, double my)
+{
+	if (mx < end_x)
+		this->Reset();
+	this->end_x=mx;
+	this->values.push_back(my);
+	if (this->amount < this->max_amount)
+		this->amount++;
+	else
+		this->values.pop_front();
+
+	assert(this->values.size()==this->amount);
+	return TRUE;
+}
+
+
+
+double ChFunction_Oscilloscope::Get_y      (double x)
+{
+	double y = 0;
+
+	double start_x = this->end_x - this->dx*(this->amount-1);
+	if (x > end_x) return 0;
+	if (x < start_x) return 0;
+	
+	int i1 = (int)floor( (x - start_x)/this->dx );
+	int i2 = i1+1;
+	double p1x = start_x + dx*(double)i1;
+	double p2x = start_x + dx*(double)i2;
+	double p2y,p1y = 0;
+	int count = 0;
+	std::list<double>::iterator iter = values.begin();
+	while(iter != values.end())
+	{
+		if (count == i1)
+		{
+			p2y = *iter;
+			iter++;
+			p1y = *iter;
+			break;
+		}
+		count++;
+		iter++;
+	}
+
+	y = ((x - p1x)*p2y + (p2x -x)*p1y)/(p2x - p1x);
+
+	return y;
+}
+
+
+
+
+void ChFunction_Oscilloscope::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << dx;
+	mstream << end_x;
+	mstream << max_amount;
+	mstream << amount;
+	std::list<double>::iterator iter = values.begin();
+	while(iter != values.end())
+	{
+		mstream << *iter;
+		iter++;
+	}
+}
+
+void ChFunction_Oscilloscope::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> dx;
+	mstream >> end_x;
+	mstream >> max_amount;
+	mstream >> amount;
+	values.clear();
+	int i = 0;
+	while(i < amount)
+	{
+		double mval;
+		mstream >> mval;
+		this->values.push_back(mval);
+	}
+}
+
+void ChFunction_Oscilloscope::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_OSCILLOSCOPE \n";
+
+	//***TO DO***
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Oscilloscope.h b/SRC/ChronoEngine/motion_functions/ChFunction_Oscilloscope.h
new file mode 100644
index 0000000..2802066
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Oscilloscope.h
@@ -0,0 +1,117 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_OSCILLOSCOPE_H
+#define CHFUNCT_OSCILLOSCOPE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Oscilloscope.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_OSCILLOSCOPE	20
+
+
+/// OSCILLOSCOPE FUNCTION
+/// y = interpolation of array of (x,y) data, 
+///     where (x,y) points must be inserted one
+///     after the other, strictly with a fixed dx
+///     interval. After a maximum amount of recordable
+///     points is reached, the firsts are deleted. 
+/// Note: differently from ChFunction_Recorder, this
+/// 'basic' function does not allow not-uniform dx spacing
+/// between points, but may be faster and simplier to
+/// use in many cases.
+
+class ChApi ChFunction_Oscilloscope : public ChFunction
+{
+	CH_RTTI(ChFunction_Oscilloscope, ChFunction);
+private:
+	std::list<double> values;
+	double end_x;
+	double dx;
+	int max_amount;
+	int amount;
+
+public:
+	ChFunction_Oscilloscope () {dx = 0.01; amount = 0; max_amount = 100; end_x=0;};
+	~ChFunction_Oscilloscope () {};
+	void Copy (ChFunction_Oscilloscope* source);
+	ChFunction* new_Duplicate ();
+		
+		/// Add a point at the head (right side of point array).
+		/// Note that it is user's responsability to add points
+		/// which are spaced uniformily (by dx) on the X axis!
+		/// No checks are done on the correctness of the dx spacing,
+		/// except that if you enter a point whose mx is less than the
+		/// mx of the one you previously entered, the array is cleared.
+	int AddLastPoint (double mx, double my);
+
+		/// Reset the array or recorded points.
+	void Reset() {values.clear(); amount =0; end_x= 0;};
+
+		/// Access directly the list of points.
+	std::list<double>&  GetPointList() {return values;};
+
+		/// Get the dx spacing between recorded points. It is assumed uniform!
+	double Get_dx() {return dx;}
+		/// Set the dx spacing between recorded points. It is assumed uniform!
+	void Set_dx(double mdx) {dx = fabs(mdx);}
+
+		/// Get the maximum amount of points which can be entered (after this,
+		/// the first one will be deleted, as in a FIFO)
+	int Get_max_amount() {return max_amount;}
+		/// Set the maximum amount of points which can be entered (after this,
+		/// the first one will be deleted, as in a FIFO)
+	void Set_max_amount(int mnum) {if (mnum > 0) max_amount = mnum;}
+
+		/// Get the amount of recorded points
+	double Get_amount() {return amount;}
+
+	double Get_y      (double x) ;
+	//double Get_y_dx   (double x) ;
+	//double Get_y_dxdx (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax);
+
+	int Get_Type () {return (FUNCT_OSCILLOSCOPE);}
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Poly.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Poly.cpp
new file mode 100644
index 0000000..fb8b0bb
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Poly.cpp
@@ -0,0 +1,170 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Poly.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Poly.h"
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Poly> a_registration_poly;
+
+
+ChFunction_Poly::ChFunction_Poly ()
+{
+	order = 0;
+	for (int i=0; i< POLY_COEFF_ARRAY; i++)
+		{coeff[i]=0 ;};
+}
+
+void ChFunction_Poly::Copy (ChFunction_Poly* source)
+{
+	order = source->order;
+	for (int i = 0; i< POLY_COEFF_ARRAY; i++)
+	{
+		Set_coeff (source->Get_coeff(i), i);
+	}
+}
+
+ChFunction* ChFunction_Poly::new_Duplicate ()
+{
+	ChFunction_Poly* m_func;
+	m_func = new ChFunction_Poly;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+double ChFunction_Poly::Get_y      (double x)
+{
+	double total = 0;
+	int i;
+	for (i=0; i<=order; i++)
+	{
+		total += (coeff[i] * pow(x, (double)i));
+	}
+	return total;
+}
+
+double ChFunction_Poly::Get_y_dx   (double x)
+{
+	double total = 0;
+	int i;
+
+	if (order < 1) return 0; // constant function
+
+	for (i=1; i<=order; i++)
+	{
+		total += ( (double)i * coeff[i] * pow(x, ((double)(i-1))) );
+	}
+	return total;
+}
+
+double ChFunction_Poly::Get_y_dxdx (double x)
+{
+	double total = 0;
+	int i;
+
+	if (order < 2) return 0; // constant function
+
+	for (i=2; i<=order; i++)
+	{
+		total += ( (double)(i*(i-1)) * coeff[i] * pow(x, ((double)(i-2))) );
+	}
+	return total;
+}
+
+int ChFunction_Poly::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	int i=0;
+
+	// inherit parent behaviour
+	ChFunction::MakeOptVariableTree(mtree);
+
+	// add variables to own tree
+	char msubvar[50];
+	for (int mord=0; mord<this->order; mord++)
+	{
+		sprintf(msubvar,"C%d", mord);
+
+		chjs_propdata* mdataA = new chjs_propdata;
+		strcpy(mdataA->propname, msubvar);
+		strcpy(mdataA->label,    mdataA->propname);
+		mdataA->haschildren = FALSE;
+		mtree->AddTail(mdataA);
+		i++;
+	}
+
+	return i;
+}
+
+void ChFunction_Poly::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->order;
+	for (int i= 0; i<= order; i++)
+	{
+		mstream << Get_coeff(i);
+	}
+
+}
+
+void ChFunction_Poly::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	int ifoo;
+	double dfoo;
+	mstream >> ifoo;		this->Set_order(ifoo);
+	for (int i= 0; i<= order; i++)
+	{
+		mstream >> dfoo;
+		Set_coeff(dfoo,i);
+	}
+}
+
+void ChFunction_Poly::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_POLY  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Poly.h b/SRC/ChronoEngine/motion_functions/ChFunction_Poly.h
new file mode 100644
index 0000000..5199d23
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Poly.h
@@ -0,0 +1,85 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_POLY_H
+#define CHFUNCT_POLY_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Poly.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_POLY		4
+
+#define POLY_COEFF_ARRAY  6
+
+
+
+/// POLYNOMIAL FUNCTION:
+/// y = a + bx + cx^2 + dx^3 + ...
+
+
+class ChApi ChFunction_Poly : public ChFunction
+{
+	CH_RTTI(ChFunction_Poly, ChFunction);
+private:
+	double	coeff[POLY_COEFF_ARRAY]; // vector of coefficients
+	int		order;					 // 0= const, 1= linear, etc... 
+public:
+	ChFunction_Poly ();
+	~ChFunction_Poly () {};
+	void Copy (ChFunction_Poly* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_coeff (double m_coeff, int m_ind) {if (m_ind >= POLY_COEFF_ARRAY) {return;}; coeff[m_ind]= m_coeff;};
+	void Set_order (int m_order)  {if (m_order >= POLY_COEFF_ARRAY) {m_order= (POLY_COEFF_ARRAY -1);} order= m_order;};
+	double Get_coeff (int m_ind) {if (m_ind >= POLY_COEFF_ARRAY) {return 0;};  return coeff[m_ind];};
+	int Get_order () {return order;};
+
+	double Get_y      (double x);
+	double Get_y_dx   (double x);
+	double Get_y_dxdx (double x);
+
+	int Get_Type () {return (FUNCT_POLY);}
+
+	int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Poly345.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Poly345.cpp
new file mode 100644
index 0000000..d2501d0
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Poly345.cpp
@@ -0,0 +1,119 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Poly345.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Poly345.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Poly345> a_registration_poly345;
+
+
+void ChFunction_Poly345::Copy (ChFunction_Poly345* source)
+{
+	h = source->h;
+	end = source->end;
+}
+
+ChFunction* ChFunction_Poly345::new_Duplicate ()
+{
+	ChFunction_Poly345* m_func;
+	m_func = new ChFunction_Poly345;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+
+double ChFunction_Poly345::Get_y      (double x)
+{
+	double ret = 0;
+	if (x<=0) return 0;
+	if (x>=end) return h;
+	double a = x/end;
+	ret = h* ( 10*pow(a,3) - 15*pow(a,4) + 6*pow(a,5) );
+	return ret;
+}
+
+double ChFunction_Poly345::Get_y_dx   (double x)
+{
+	double ret = 0;
+	if (x<=0) return 0;
+	if (x>=end) return 0;
+	double a = x/end;
+	ret = h*(1/end) * ( 30*pow(a,2) - 60*pow(a,3) + 30*pow(a,4) );
+	return ret;
+}
+
+double ChFunction_Poly345::Get_y_dxdx (double x)
+{
+	double ret = 0;
+	if (x<=0) return 0;
+	if (x>=end) return 0;
+	double a = x/end;
+	ret = h*(1/(end*end)) * ( 60*a - 180*pow(a,2) + 120*pow(a,3) );
+	return ret;
+}
+
+void ChFunction_Poly345::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << h;
+	mstream << end;
+}
+
+void ChFunction_Poly345::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> h;
+	mstream >> end;
+}
+
+void ChFunction_Poly345::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_CONST  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Poly345.h b/SRC/ChronoEngine/motion_functions/ChFunction_Poly345.h
new file mode 100644
index 0000000..75bc77c
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Poly345.h
@@ -0,0 +1,94 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_POLY345_H
+#define CHFUNCT_POLY345_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Poly345.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_POLY345	9
+
+
+
+/// A RAMP, AS 3-4-5 POLYNOMIAL FUNCTION:  
+///   - h   = height, amount of displacement
+///   - end = duration of motion,
+
+class ChApi ChFunction_Poly345 : public ChFunction
+{
+	CH_RTTI(ChFunction_Poly345, ChFunction);
+private:
+	double h;
+	double end;
+public:
+	ChFunction_Poly345 () {h =1;  end=1;}
+	ChFunction_Poly345 (double m_h, double m_end)  {h = m_h; Set_end(m_end);};
+	~ChFunction_Poly345 () {};
+	void Copy (ChFunction_Poly345* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_end  (double m_end)  {if (m_end<0) m_end = 0; end = m_end;}
+	void Set_h    (double m_h)    {h = m_h;}
+
+	double Get_end () {return end;}
+	double Get_h ()   {return h;}
+
+	double Get_y      (double x) ;
+	double Get_y_dx   (double x) ;
+	double Get_y_dxdx (double x) ;
+
+	double Get_Ca_pos () {return 5.8;};
+	double Get_Ca_neg () {return 5.8;};
+	double Get_Cv () {return 1.9;};
+
+	void Extimate_x_range (double& xmin, double& xmax) {xmin = 0.0; xmax = end;};
+
+	int Get_Type () {return (FUNCT_POLY345);}
+	
+	OPT_VARIABLES_START
+		"h",
+		"end",
+	OPT_VARIABLES_END
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Ramp.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Ramp.cpp
new file mode 100644
index 0000000..c2dd103
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Ramp.cpp
@@ -0,0 +1,86 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Ramp.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Ramp.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Ramp> a_registration_ramp;
+
+void ChFunction_Ramp::Copy (ChFunction_Ramp* source)
+{
+	Set_y0  (source->y0);
+	Set_ang (source->ang);
+}
+
+ChFunction* ChFunction_Ramp::new_Duplicate ()
+{
+	ChFunction_Ramp* m_func;
+	m_func = new ChFunction_Ramp;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+
+void ChFunction_Ramp::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << y0;
+	mstream << ang;
+}
+
+void ChFunction_Ramp::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> y0;
+	mstream >> ang;
+}
+
+void ChFunction_Ramp::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_RAMP  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Ramp.h b/SRC/ChronoEngine/motion_functions/ChFunction_Ramp.h
new file mode 100644
index 0000000..0f35ced
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Ramp.h
@@ -0,0 +1,98 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_RAMP_H
+#define CHFUNCT_RAMP_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Ramp.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_RAMP		1
+
+
+
+/// LINEAR FUNCTION (like a straight ramp)
+/// y = y0 + x * speed
+/// 
+
+class ChApi ChFunction_Ramp : public ChFunction
+{
+	CH_RTTI(ChFunction_Ramp, ChFunction);
+private:
+	double y0;
+	double ang;
+public:
+	ChFunction_Ramp () {y0 = 0; ang=1;};
+	ChFunction_Ramp (double m_y0, double m_ang)  {y0 = m_y0; ang = m_ang;};
+	~ChFunction_Ramp () {};
+	void Copy (ChFunction_Ramp* source);
+	ChFunction* new_Duplicate ();
+
+	int Get_Type () {return (FUNCT_RAMP);}			
+	
+			// Custom data
+
+				/// The value for x=0;
+	void	Set_y0   (double m_y0)   {y0 = m_y0;};	
+	double	Get_y0 ()  {return y0;};
+
+				/// The angular coefficient.
+	void	Set_ang  (double m_ang)  {ang = m_ang;};
+	double	Get_ang () {return ang;};
+
+
+			// Override the Get_y(), Get_y_dx etc. functions with analytical formulas.
+
+	double Get_y      (double x) {return (y0 + (x*ang))  ;};
+	double Get_y_dx   (double) {return (ang)			 ;};
+	double Get_y_dxdx (double) {return  0				 ;};
+
+			// Expose the parameters which can be used for optimizations, as Javascript vars.
+
+	OPT_VARIABLES_START
+		"C",
+		"ang",
+	OPT_VARIABLES_END
+	
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Recorder.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Recorder.cpp
new file mode 100644
index 0000000..fd51694
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Recorder.cpp
@@ -0,0 +1,444 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Recorder.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Recorder.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Recorder> a_registration_recorder;
+
+
+void ChFunction_Recorder::Copy (ChFunction_Recorder* source)
+{
+	points.KillAll();
+	lastnode = NULL;
+	ChRecPoint* mpt;
+	for (ChNode<ChRecPoint>* mnode = source->points.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		mpt = new ChRecPoint;
+		mpt->x = mnode->data->x;
+		mpt->y = mnode->data->y;
+		mpt->w = mnode->data->w;
+		points.AddTail(mpt);
+	}
+}
+
+ChFunction* ChFunction_Recorder::new_Duplicate ()
+{
+	ChFunction_Recorder* m_func;
+	m_func = new ChFunction_Recorder;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+void ChFunction_Recorder::Extimate_x_range (double& xmin, double& xmax)
+{
+	if (!points.GetTail())
+	{
+		xmin = 0.0; xmax = 1.2;
+		return;
+	}
+	xmin = points.GetHead()->data->x;
+	xmax = points.GetTail()->data->x;
+	if (xmin == xmax) xmax = xmin+ 0.5;
+}
+
+
+int ChFunction_Recorder::AddPoint (double mx, double my, double mw)
+{
+	ChRecPoint* mpt = new ChRecPoint;
+	mpt->x = mx;  	mpt->y = my;  	mpt->w = mw;
+	double dist;
+
+	if (!points.GetTail())
+	{
+		points.AddTail(mpt);
+		return TRUE;
+	}
+
+	for (ChNode<ChRecPoint>* mnode = points.GetTail(); mnode != NULL; mnode= mnode->prev)
+	{
+		dist = mx - mnode->data->x;
+		if (fabs(dist) < CH_RECORDER_EPSILON)
+		{
+			mnode->data = mpt;	// copy to preexisting node
+			return TRUE;
+		}
+		if (dist > 0.0)
+		{
+			points.InsertAfter(mnode, mpt);  // insert
+			return TRUE;
+		}
+	}
+
+
+	points.AddHead(mpt); // was 1st in list
+	return TRUE;
+}
+
+int ChFunction_Recorder::AddPointClean (double mx, double my, double dx_clean)
+{
+	ChRecPoint* mpt = new ChRecPoint;
+	mpt->x = mx;  	mpt->y = my;  	mpt->w = 0;
+	double dist;
+	ChNode<ChRecPoint>* msetnode = NULL;
+
+	if (!points.GetHead())
+	{
+		points.AddHead(mpt);
+		lastnode = msetnode = points.GetHead();
+		return TRUE;
+	}
+
+	if (!lastnode)
+		lastnode = points.GetHead();
+
+	if (lastnode->data->x < mx) // 1 forward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->next)
+		{
+			if (mnode->data->x >= mx)
+			{
+				lastnode = mnode;
+				dist = - mx + mnode->data->x;
+				if (fabs(dist) < CH_RECORDER_EPSILON) {
+					mnode->data = mpt;
+					msetnode = mnode;}	// copy to preexisting node
+				else {
+					points.InsertBefore(mnode, mpt);
+					msetnode = mnode->prev;} // insert
+				break;
+
+			}
+		}
+		if (!msetnode)
+		{			// ..oh, it should be tail..
+			points.AddTail(mpt);
+			msetnode = points.GetTail();
+		}
+	}
+	else						// 2 backward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->prev)
+		{
+			if (mnode->data->x <= mx)
+			{
+				lastnode = mnode;
+				dist =  mx - mnode->data->x;
+				if (fabs(dist) < CH_RECORDER_EPSILON) {
+					mnode->data = mpt;	// copy to preexisting node
+					msetnode = mnode;}
+				else {
+					points.InsertAfter(mnode, mpt);  // insert
+					msetnode = mnode->next; }
+				break;
+			}
+		}
+		if (!msetnode)
+		{			// ..oh, it should be head
+			points.AddHead(mpt);
+			msetnode = points.GetHead();
+		}
+	}
+
+	lastnode = msetnode;
+
+	// clean on dx
+	if (dx_clean >0)
+	{
+		ChNode<ChRecPoint>* mnode = msetnode->next;
+		ChNode<ChRecPoint>* mnextnode = NULL;
+		while (mnode != NULL)
+		{
+			mnextnode = mnode->next;
+			if ((mnode->data->x - mx) < dx_clean)
+			{
+				points.Kill(mnode);
+			}
+			mnode = mnextnode;
+		}
+	}
+
+	return TRUE;
+}
+
+double ChFunction_Recorder::Get_y      (double x)
+{
+	double y = 0;
+
+	ChRecPoint p1;
+	p1.w = 1;
+	p1.x = 0;
+	p1.y = 0;
+	ChRecPoint p2;
+	p2 = p1;
+	p2.x = p1.x + 1.0;
+
+	if (points.GetHead() == NULL) return 0.0;
+
+	if (x < points.GetHead()->data->x) return 0.0;
+	if (x > points.GetTail()->data->x) return 0.0;
+
+	if (!lastnode) lastnode = points.GetHead();
+
+	if (lastnode->data->x < x) // forward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->next)
+		{
+			if (mnode->data->x >= x)
+			{
+				p2 = *mnode->data; lastnode = mnode;
+				if (mnode->prev)	{ p1 = *mnode->prev->data; }
+				break;
+			}
+		}
+	}
+	else	// backward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->prev)
+		{
+			if (mnode->data->x <= x)
+			{
+				p1 = *mnode->data;	lastnode = mnode;
+				if (mnode->next)	{ p2 = *mnode->next->data; }
+				break;
+			}
+		}
+	}
+
+
+	y = ((x - p1.x)*p2.y + (p2.x -x)*p1.y)/(p2.x - p1.x);
+
+	return y;
+}
+
+double ChFunction_Recorder::Get_y_dx   (double x)
+{
+	double dy = 0;
+
+	ChRecPoint p1;					//    p0...p1..x...p2.....p3
+	p1.x = x;	p1.y = 0;	p1.w = 1;
+	ChRecPoint p2;
+	p2 = p1;	p2.x += 100.0;
+	ChRecPoint p0;
+	p0 = p1;	p0.x -= 100.0;
+	ChRecPoint p3;
+	p3 = p1;	p3.x += 200.0;
+
+	if (points.GetHead() == NULL) return 0.0;
+
+	if (x < points.GetHead()->data->x) return 0.0;
+	if (x > points.GetTail()->data->x) return 0.0;
+
+	if (!lastnode) lastnode = points.GetHead();
+
+	if (lastnode->data->x < x) // forward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->next)
+		{
+			if (mnode->data->x >= x)
+			{
+				p2 = *mnode->data; lastnode = mnode;
+				if (mnode->prev) {
+					p1 = *mnode->prev->data;
+					if (mnode->prev->prev) {
+						p0 = *mnode->prev->prev->data;
+						if (mnode->next) {
+							p3 = *mnode->next->data;
+						}else { p3 = p2; p3.x += 1.0;}
+					}else { p0 = p1; p0.x -= 1.0;}
+				}else { p1 = p2; p1.x -= 1.0;}
+
+				break;
+			}
+		}
+	}
+	else	// backward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->prev)
+		{
+			if (mnode->data->x <= x)
+			{
+				p1 = *mnode->data;	lastnode = mnode;
+				if (mnode->next)  {
+					p2 = *mnode->next->data;
+					if (mnode->prev)  {
+						p0 = *mnode->prev->data;
+						if (mnode->next->next)  {
+							p3 = *mnode->next->next->data;
+						}else { p3 = p2; p3.x += 1.0;}
+					}else { p0 = p1; p0.x -= 1.0;}
+				}else { p2 = p1; p2.x += 1.0;}
+
+				break;
+			}
+		}
+	}
+
+	double vA = (p1.y -p0.y)/(p1.x -p0.x);
+	double vB = (p2.y -p1.y)/(p2.x -p1.x);
+	double vC = (p3.y -p2.y)/(p3.x -p2.x);
+
+	double v1 = 0.5* (vA + vB);
+	double v2 = 0.5* (vB + vC);
+
+	dy = ((x - p1.x)* v2 + (p2.x -x)* v1)  /  (p2.x - p1.x);
+
+	return dy;
+}
+
+double ChFunction_Recorder::Get_y_dxdx (double x)
+{
+	double ddy = 0;
+
+	ChRecPoint p1;					//    p0...p1..x...p2.....p3
+	p1.x = x;	p1.y = 0;	p1.w = 1;
+	ChRecPoint p2;
+	p2 = p1;	p2.x = p1.x + 100.0;
+	ChRecPoint p0;
+	p0 = p1;	p0.x = p1.x - 100.0;
+	ChRecPoint p3;
+	p3 = p1;	p3.x = p1.x + 200.0;
+
+	if (points.GetHead() == NULL) return 0.0;
+
+	if (x < points.GetHead()->data->x) return 0.0;
+	if (x > points.GetTail()->data->x) return 0.0;
+
+	if (!lastnode) lastnode = points.GetHead();
+
+	if (lastnode->data->x < x) // forward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->next)
+		{
+			if (mnode->data->x >= x)
+			{
+				p2 = *mnode->data; lastnode = mnode;
+				if (mnode->prev) {
+					p1 = *mnode->prev->data;
+					if (mnode->prev->prev) {
+						p0 = *mnode->prev->prev->data;
+						if (mnode->next) {
+							p3 = *mnode->next->data;
+						}else { p3 = p2; p3.x += 1.0;}
+					}else { p0 = p1; p0.x -= 1.0;}
+				}else { p1 = p2; p1.x -= 1.0;}
+
+				break;
+			}
+		}
+	}
+	else	// backward search
+	{
+		for (ChNode<ChRecPoint>* mnode = lastnode; mnode != NULL; mnode= mnode->prev)
+		{
+			if (mnode->data->x <= x)
+			{
+				p1 = *mnode->data;	lastnode = mnode;
+				if (mnode->next)  {
+					p2 = *mnode->next->data;
+					if (mnode->prev)  {
+						p0 = *mnode->prev->data;
+						if (mnode->next->next)  {
+							p3 = *mnode->next->next->data;
+						}else { p3 = p2; p3.x += 1.0;}
+					}else { p0 = p1; p0.x -= 1.0;}
+				}else { p2 = p1; p2.x += 1.0;}
+
+				break;
+			}
+		}
+	}
+
+	double vA = (p1.y -p0.y)/(p1.x -p0.x);
+	double vB = (p2.y -p1.y)/(p2.x -p1.x);
+	double vC = (p3.y -p2.y)/(p3.x -p2.x);
+
+	double a1 = 2.0 * (vB - vA)/(p2.x - p0.x);
+	double a2 = 2.0 * (vC - vB)/(p3.x - p1.x);
+
+	ddy = ((x - p1.x)* a2 + (p2.x -x)* a1)  /  (p2.x - p1.x);
+
+	return ddy;
+}
+
+
+void ChFunction_Recorder::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << (int)(points.Count());
+
+	for (ChNode<ChRecPoint>* mnode = points.GetTail(); mnode != NULL; mnode= mnode->prev)
+	{
+		mstream << mnode->data->x;
+		mstream << mnode->data->y;
+		mstream << mnode->data->w;
+	}
+}
+
+void ChFunction_Recorder::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	int mcount;
+	mstream >> mcount;
+
+	for (int i = 0; i < mcount; i++)
+	{
+		ChRecPoint* mpt = new ChRecPoint;
+		mstream >> mpt->x;
+		mstream >> mpt->y;
+		mstream >> mpt->w;
+		points.AddHead(mpt);
+	}
+
+}
+
+void ChFunction_Recorder::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_RECORDER  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Recorder.h b/SRC/ChronoEngine/motion_functions/ChFunction_Recorder.h
new file mode 100644
index 0000000..7082c69
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Recorder.h
@@ -0,0 +1,96 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_RECORDER_H
+#define CHFUNCT_RECORDER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Recorder.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_RECORDER	11
+
+
+
+class ChApi ChRecPoint 
+{
+public:
+	double x;	
+	double y;
+	double w;  // weight
+};
+
+#define CH_RECORDER_EPSILON 1.e-10
+
+
+/////////////////////////////////////////////
+/// RECORDER FUNCTION
+/// y = interpolation of array of (x,y) data, 
+///     where (x,y) points can be inserted randomly.
+
+class ChApi ChFunction_Recorder : public ChFunction
+{
+	CH_RTTI(ChFunction_Recorder, ChFunction);
+private:
+	ChList<ChRecPoint> points;		// the list of points
+	ChNode<ChRecPoint>* lastnode;	// speed optimization: remember the last used pointer
+
+public:
+	ChFunction_Recorder () {lastnode = NULL;};
+	~ChFunction_Recorder () {points.KillAll();};
+	void Copy (ChFunction_Recorder* source);
+	ChFunction* new_Duplicate ();
+
+	int AddPoint (double mx, double my, double mw);
+	int AddPoint (double mx, double my) {return AddPoint(mx,my,1.0);};
+	int AddPointClean (double mx, double my, double dx_clean); // also clean nodes to the right, upt to dx interval
+	void Reset() {points.KillAll(); lastnode = NULL;};
+
+	ChList<ChRecPoint>*  GetPointList() {return &points;};
+
+	double Get_y      (double x) ;
+	double Get_y_dx   (double x) ;
+	double Get_y_dxdx (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax);
+
+	int Get_Type () {return (FUNCT_RECORDER);}
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Repeat.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Repeat.cpp
new file mode 100644
index 0000000..bbd5711
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Repeat.cpp
@@ -0,0 +1,119 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Repeat.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Repeat.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Repeat> a_registration_repeat;
+
+
+void ChFunction_Repeat::Copy (ChFunction_Repeat* source)
+{
+	window_start = source->window_start;
+	window_length = source->window_length;
+	fa = source->fa->new_Duplicate();
+}
+
+ChFunction* ChFunction_Repeat::new_Duplicate ()
+{
+	ChFunction_Repeat* m_func;
+	m_func = new ChFunction_Repeat;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+double ChFunction_Repeat::Get_y      (double x)
+{
+	return fa->Get_y(this->window_start + fmod(x,this->window_length) );
+}
+
+void ChFunction_Repeat::Extimate_x_range (double& xmin, double& xmax)
+{
+	fa->Extimate_x_range(xmin,xmax);
+}
+
+int ChFunction_Repeat::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	int i=0;
+
+	// inherit parent behaviour
+	ChFunction::MakeOptVariableTree(mtree);
+
+	// expand tree for children..
+
+	chjs_propdata* mdataA = new chjs_propdata;
+	strcpy(mdataA->propname, "fa");
+	strcpy(mdataA->label,    mdataA->propname);
+	mdataA->haschildren = TRUE;
+	mtree->AddTail(mdataA);
+
+	i += this->fa->MakeOptVariableTree(&mdataA->children);
+
+	return i;
+}
+
+void ChFunction_Repeat::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << window_start;
+	mstream << window_length;
+	mstream.AbstractWrite(fa);
+}
+
+void ChFunction_Repeat::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> window_start;
+	mstream >> window_length;
+	if (fa) delete fa; fa=NULL;
+	mstream.AbstractReadCreate(&fa);
+}
+
+void ChFunction_Repeat::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_REPEAT  \n";
+
+	//***TO DO***
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Repeat.h b/SRC/ChronoEngine/motion_functions/ChFunction_Repeat.h
new file mode 100644
index 0000000..46ba796
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Repeat.h
@@ -0,0 +1,88 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_REPEAT_H
+#define CHFUNCT_REPEAT_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Repeat.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+#include "ChFunction_Const.h"
+
+namespace chrono 
+{
+
+#define FUNCT_REPEAT	19
+
+
+/// REPEAT FUNCTION:
+/// y = __/__/__/ 
+///
+/// Repeats a 'window' of a function, periodically.
+
+class ChApi ChFunction_Repeat : public ChFunction
+{
+	CH_RTTI(ChFunction_Repeat, ChFunction);
+private:
+	ChFunction* fa;
+	double window_start;			// window begin position
+	double window_length;			// window length
+public:
+	ChFunction_Repeat() {window_start=0;window_length=1;  fa = new ChFunction_Const;}
+	~ChFunction_Repeat () {if (fa) delete fa;};
+	void Copy (ChFunction_Repeat* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_window_start  (double m_v)  {window_start = m_v;}
+	double Get_window_start () {return window_start;}
+	void Set_window_length  (double m_v)  {window_length = m_v;}
+	double Get_window_length () {return window_length;}
+
+	void Set_fa  (ChFunction* m_fa)  {fa = m_fa;}
+	ChFunction* Get_fa () {return fa;}
+	
+	double Get_y      (double x) ;
+
+	void Extimate_x_range (double& xmin, double& xmax);
+	int Get_Type () {return (FUNCT_REPEAT);}
+
+	int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+	OPT_VARIABLES_START
+		"window_start",
+		"window_length",
+	OPT_VARIABLES_END
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Sequence.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Sequence.cpp
new file mode 100644
index 0000000..ee3974d
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Sequence.cpp
@@ -0,0 +1,498 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Sequence.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Sequence.h"
+#include "ChFunction_Fillet3.h"
+
+
+namespace chrono
+{
+
+
+ChFseqNode::ChFseqNode(ChFunction* myfx, double mdur)
+{
+	fx = myfx;
+	duration = mdur;
+	weight = 1;
+	t_start = 0; t_end = t_start+ duration;
+	Iy = Iydt = Iydtdt = 0.0;
+	y_cont = ydt_cont = ydtdt_cont = FALSE;
+}
+
+ChFseqNode::~ChFseqNode()
+{
+	if (fx) delete fx; fx = NULL;
+}
+
+void ChFseqNode::Copy(ChFseqNode* source)
+{
+	if (fx) delete fx;
+	fx = source->fx->new_Duplicate();
+	duration = source->duration;
+	weight = source->weight;
+	t_start = source->t_start;
+	t_end = source->t_end;
+	Iy = source->Iy;
+	Iydt = source->Iydt;
+	Iydtdt = source->Iydtdt;
+	y_cont = source->y_cont;
+	ydt_cont = source->ydt_cont;
+	ydtdt_cont = source->ydtdt_cont;
+}
+
+void ChFseqNode::SetDuration(double mdur)
+{
+	duration = mdur;
+	if (duration<0)
+		duration =0;
+	t_end = t_start+duration;
+};
+
+void ChFseqNode::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// stream out all member data
+	mstream << this->duration;
+	mstream << this->weight;
+	mstream << this->t_start;
+	mstream << this->t_end;
+	mstream << this->Iy;
+	mstream << this->Iydt;
+	mstream << this->Iydtdt;
+	mstream << this->y_cont;
+	mstream << this->ydt_cont;
+	mstream << this->ydtdt_cont;
+	mstream.AbstractWrite(this->fx);
+}
+
+void ChFseqNode::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in all member data
+	mstream >> this->duration;
+	mstream >> this->weight;
+	mstream >> this->t_start;
+	mstream >> this->t_end;
+	mstream >> this->Iy;
+	mstream >> this->Iydt;
+	mstream >> this->Iydtdt;
+	mstream >> this->y_cont;
+	mstream >> this->ydt_cont;
+	mstream >> this->ydtdt_cont;
+	if (fx) delete fx; fx=NULL;
+	mstream.AbstractReadCreate(&this->fx);
+}
+
+
+/////////
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Sequence> a_registration_sequence;
+
+
+
+ChFunction_Sequence::ChFunction_Sequence ()
+{
+	start = 0;
+}
+
+ChFunction_Sequence::~ChFunction_Sequence ()
+{
+	functions.KillAll();
+}
+
+void ChFunction_Sequence::Copy (ChFunction_Sequence* source)
+{
+	start = source->start;
+	functions.KillAll();
+	ChFseqNode* mfxs;
+	for (ChNode<ChFseqNode>* mnode = source->functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		mfxs = new ChFseqNode(NULL, 0.0);
+		mfxs->Copy(mnode->data);
+		functions.AddTail(mfxs);
+	}
+}
+
+ChFunction* ChFunction_Sequence::new_Duplicate ()
+{
+	ChFunction_Sequence* m_func;
+	m_func = new ChFunction_Sequence;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+int ChFunction_Sequence::InsertFunct (ChFunction* myfx, double duration, double weight, bool c0, bool c1, bool c2, int position)
+{
+	ChFseqNode* mfxsegment = new ChFseqNode(myfx, duration);
+	mfxsegment->y_cont = c0;
+	mfxsegment->ydt_cont = c1;
+	mfxsegment->ydtdt_cont = c2;
+	mfxsegment->weight = weight;
+
+	int inserted = FALSE;
+	if (position == 0)
+		{ functions.AddHead(mfxsegment); inserted = TRUE;}
+	if (position == -1)
+		{ functions.AddTail(mfxsegment); inserted = TRUE;}
+	if (!inserted)
+	{
+		int ind = 1;
+		for (ChNode<ChFseqNode>* mnode = functions.GetHead(); mnode != NULL; mnode= mnode->next)
+		{
+			if (ind == position)
+				{ functions.InsertAfter(mnode, mfxsegment); inserted = TRUE;  break; }
+			ind ++;
+		}
+	}
+	if (!inserted)
+		{ functions.AddTail(mfxsegment);}
+				// update the continuity offsets and timings
+	this->Setup();
+	return inserted;
+}
+
+int ChFunction_Sequence::KillFunct (int position)
+{
+	int fcount = functions.Count();
+	if (fcount == 0)
+		return FALSE;
+	if ((position == -1)||(position > fcount))
+		{ functions.Kill(functions.GetTail()); return TRUE;}
+	if (position == 0)
+		{ functions.Kill(functions.GetHead()); return TRUE;}
+	functions.Kill(functions.GetNum(position));
+
+	this->Setup();
+	return TRUE;
+}
+
+ChFunction* ChFunction_Sequence::GetNthFunction (int position)
+{
+	int fcount = functions.Count();
+	if (fcount == 0)
+		return NULL;
+	if ((position == -1)||(position > fcount))
+		{ return functions.GetTail()->data->fx;}
+	if (position == 0)
+		{ return functions.GetHead()->data->fx;}
+	return  functions.GetNum(position)->data->fx;
+}
+
+double ChFunction_Sequence::GetNthDuration(int position)
+{
+	static double default_dur =0.0;
+	int fcount = functions.Count();
+	if (fcount == 0)
+		return default_dur;
+	if ((position == -1)||(position > fcount))
+		{ return functions.GetTail()->data->duration;}
+	if (position == 0)
+		{ return functions.GetHead()->data->duration;}
+	return  functions.GetNum(position)->data->duration;
+}
+
+ChFseqNode* ChFunction_Sequence::GetNthNode(int position)
+{
+	int fcount = functions.Count();
+	if (fcount == 0)
+		return NULL;
+	if ((position == -1)||(position > fcount))
+		{ return functions.GetTail()->data;}
+	if (position == 0)
+		{ return functions.GetHead()->data;}
+	return  functions.GetNum(position)->data;
+}
+
+void ChFunction_Sequence::Setup()
+{
+	double basetime = this->start;
+	double lastIy = 0;
+	double lastIy_dt = 0;
+	double lastIy_dtdt = 0;
+
+	for (ChNode<ChFseqNode>* mnode = functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		mnode->data->t_start = basetime;
+		mnode->data->t_end   = basetime + mnode->data->duration;
+		mnode->data->Iy		= 0;
+		mnode->data->Iydt	= 0;
+		mnode->data->Iydtdt = 0;
+
+		if (mnode->data->fx->Get_Type() == FUNCT_FILLET3)	// C0 C1 fillet
+		{
+			((ChFunction_Fillet3*)mnode->data->fx)->Set_y1(lastIy);
+			((ChFunction_Fillet3*)mnode->data->fx)->Set_dy1(lastIy_dt);
+			if (mnode->next)
+			{
+				((ChFunction_Fillet3*)mnode->data->fx)->Set_y2(mnode->next->data->fx->Get_y(0));
+				((ChFunction_Fillet3*)mnode->data->fx)->Set_dy2(mnode->next->data->fx->Get_y_dx(0));
+			}else
+			{
+				((ChFunction_Fillet3*)mnode->data->fx)->Set_y2(0);
+				((ChFunction_Fillet3*)mnode->data->fx)->Set_dy2(0);
+			}
+			((ChFunction_Fillet3*)mnode->data->fx)->Set_end(mnode->data->duration);
+			mnode->data->Iy = mnode->data->Iydt = mnode->data->Iydtdt = 0;
+		}
+		else	// generic continuity conditions
+		{
+			if (mnode->data->y_cont)
+				mnode->data->Iy = lastIy - mnode->data->fx->Get_y(0);
+			if (mnode->data->ydt_cont)
+				mnode->data->Iydt = lastIy_dt - mnode->data->fx->Get_y_dx(0);
+			if (mnode->data->ydtdt_cont)
+				mnode->data->Iydtdt = lastIy_dtdt - mnode->data->fx->Get_y_dxdx(0);
+		}
+
+		lastIy = mnode->data->fx->Get_y(mnode->data->duration) +
+				 mnode->data->Iy +
+				 mnode->data->Iydt *  mnode->data->duration +
+				 mnode->data->Iydtdt *  mnode->data->duration *  mnode->data->duration;
+		lastIy_dt =
+				 mnode->data->fx->Get_y_dx(mnode->data->duration) +
+				 mnode->data->Iydt +
+				 mnode->data->Iydtdt *  mnode->data->duration;
+		lastIy_dtdt =
+				 mnode->data->fx->Get_y_dxdx(mnode->data->duration) +
+				 mnode->data->Iydtdt;
+
+		basetime += mnode->data->duration;
+	}
+}
+
+double ChFunction_Sequence::Get_y      (double x)
+{
+	double res = 0;
+	double localtime;
+	for (ChNode<ChFseqNode>* mnode = functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		if ((x >= mnode->data->t_start)&&(x < mnode->data->t_end))
+		{
+			localtime = x - mnode->data->t_start;
+			res = mnode->data->fx->Get_y(localtime) +
+				  mnode->data->Iy +
+				  mnode->data->Iydt *  localtime +
+				  mnode->data->Iydtdt *  localtime *  localtime;
+		}
+	}
+	return res;
+}
+
+double ChFunction_Sequence::Get_y_dx   (double x)
+{
+	double res = 0;
+	double localtime;
+	for (ChNode<ChFseqNode>* mnode = functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		if ((x >= mnode->data->t_start)&&(x < mnode->data->t_end))
+		{
+			localtime = x - mnode->data->t_start;
+			res = mnode->data->fx->Get_y_dx(localtime) +
+				  mnode->data->Iydt +
+				  mnode->data->Iydtdt *  localtime;
+		}
+	}
+	return res;
+}
+
+double ChFunction_Sequence::Get_y_dxdx (double x)
+{
+	double res = 0;
+	double localtime;
+	for (ChNode<ChFseqNode>* mnode = functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		if ((x >= mnode->data->t_start)&&(x < mnode->data->t_end))
+		{
+			localtime = x - mnode->data->t_start;
+			res = mnode->data->fx->Get_y_dxdx(localtime) +
+				  mnode->data->Iydtdt;
+		}
+	}
+	return res;
+}
+
+
+double ChFunction_Sequence::Get_weight (double x)
+{
+	double res = 1.0;
+	for (ChNode<ChFseqNode>* mnode = functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		if ((x >= mnode->data->t_start)&&(x < mnode->data->t_end))
+		{
+			res = mnode->data->weight;
+		}
+	}
+	return res;
+}
+
+void ChFunction_Sequence::Extimate_x_range (double& xmin, double& xmax)
+{
+	xmin = start;
+	xmax = functions.GetTail()->data->t_end;
+	if (xmin == xmax) xmax = xmin + 1.1;
+}
+
+
+int ChFunction_Sequence::MakeOptVariableTree(ChList<chjs_propdata>* mtree)
+{
+	int i=0;
+
+	// inherit parent behaviour
+	ChFunction::MakeOptVariableTree(mtree);
+
+	// expand tree for all children..
+	int cnt=1;
+	char msubduration[50];
+	char msubfunction[50];
+	for (ChNode<ChFseqNode>* mnode = this->functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		sprintf(msubduration,"node_n(%d).duration", cnt);
+
+		chjs_propdata* mdataA = new chjs_propdata;
+		strcpy(mdataA->propname, msubduration);
+		strcpy(mdataA->label,    mdataA->propname);
+		mdataA->haschildren = FALSE;
+		mtree->AddTail(mdataA);
+		i++;
+
+		sprintf(msubfunction,"node_n(%d).fx", cnt);
+
+		chjs_propdata* mdataB = new chjs_propdata;
+		strcpy(mdataB->propname, msubfunction);
+		strcpy(mdataB->label,    mdataB->propname);
+		mdataB->haschildren = TRUE;
+		mtree->AddTail(mdataB);
+
+		i += mnode->data->fx->MakeOptVariableTree(&mdataB->children);
+
+		cnt++;
+	}
+
+	return i;
+}
+
+
+int ChFunction_Sequence::HandleNumber()
+{
+	int tot = 1;
+	for (ChNode<ChFseqNode>* mnode = this->functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		tot++;
+	}
+	return tot;
+}
+
+int ChFunction_Sequence::HandleAccess(int handle_id, double mx, double my, bool set_mode)
+{
+	if (handle_id==0)
+	{
+		if (!set_mode)
+			mx = this->Get_start();
+		else
+			this->Set_start(mx);
+		return TRUE;
+	}
+	int tot = 1;
+	for (ChNode<ChFseqNode>* mnode = this->functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		if (handle_id==tot)
+		{
+			if (!set_mode)
+				mx = mnode->data->t_end;
+			else
+			{
+				mnode->data->SetTend(mx);
+				this->Setup();
+			}
+			return TRUE;
+		}
+
+	}
+
+	return FALSE;
+}
+
+
+void ChFunction_Sequence::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	int stopID = 0;
+	int goID = 1;
+
+	mstream << Get_start();
+
+	for (ChNode<ChFseqNode>* mnode = functions.GetHead(); mnode != NULL; mnode= mnode->next)
+	{
+		mstream << goID;
+		mstream << *mnode->data;
+	}
+	mstream << stopID;
+
+}
+
+void ChFunction_Sequence::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	double dfoo;
+	mstream >> dfoo;		Set_start(dfoo);
+	int mgoID;
+	mstream >> mgoID;
+	while (mgoID == 1)
+	{
+		ChFseqNode* mynode = new ChFseqNode(NULL, 0.0);
+		mstream >> *mynode;
+		functions.AddTail(mynode);
+		mstream >> mgoID;
+	}
+}
+
+void ChFunction_Sequence::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_SEQUENCE  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Sequence.h b/SRC/ChronoEngine/motion_functions/ChFunction_Sequence.h
new file mode 100644
index 0000000..e929599
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Sequence.h
@@ -0,0 +1,167 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_SEQUENCE_H
+#define CHFUNCT_SEQUENCE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Sequence.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_SEQUENCE	7
+
+
+/// Node for the list of functions 
+/// in a ChFunction_Sequence object.
+
+class ChApi ChFseqNode
+{
+public:
+	ChFunction* fx;
+	double duration;
+	double weight;
+	double t_start;
+	double t_end;
+	double Iy;
+	double Iydt;
+	double Iydtdt;
+	bool y_cont;
+	bool ydt_cont;
+	bool ydtdt_cont;
+
+	void SetDuration(double mdur);
+	void SetTend(double mt_end) {t_end = mt_end; if (t_end < t_start) t_end= t_start; duration = t_end - t_start;};
+
+	ChFseqNode(ChFunction* myfx, double mdur);
+	~ChFseqNode();
+	void Copy(ChFseqNode* source);
+
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+/// SEQUENCE FUNCTION:
+///   y = sequence_of_functions(f1(y), f2(y), f3(y))  
+/// All other function types can be inserted into this.
+/// This function is very important because very complex motion
+/// laws can be created by sequencing many basic ChFunctions.
+
+class ChApi ChFunction_Sequence : public ChFunction
+{
+	CH_RTTI(ChFunction_Sequence, ChFunction);
+private:
+	ChList<ChFseqNode> functions;	// the list of sub functions
+	double start;					// start time for sequence
+public:
+	ChFunction_Sequence();
+	~ChFunction_Sequence();
+	void Copy (ChFunction_Sequence* source);
+	ChFunction* new_Duplicate ();
+	
+	int Get_Type () {return (FUNCT_SEQUENCE);}		
+
+
+				/// The sequence of functions starts at this x value.
+	void	Set_start  (double m_start)  {start = m_start;};
+	double	Get_start  ()  {return start;};
+
+				/// Access the list of the sub-functions.
+	ChList<ChFseqNode>* Get_list() {return &functions;};
+
+				/// Scans all the seq.of functions and setup the timings and continuity 
+				/// offsets, to satisfy all constraints.
+				/// This must be called whenever a new function is inserted, or its 
+				/// timing and continuity constraints are changed.
+	void Setup();
+
+				/// Insert function after the fx with defined "position" index in list.
+				///  - If index is higher than available objects, it simply goes to the end. 
+				///  - If index = 0 insert at the beginning, 
+				///  - If index = -1 insert at the end.
+				/// Inserted functions will be deleted automatically when this object will be deleted.
+				/// The fx segment has its own 'weight': use 1.0 for default, or different weights 
+				/// if you want that Get_weight() will give different results depending on the "x" parameter.
+				/// Set c0=true if you want to force C0 continuity with previous function (an offset
+				/// will be implicitly added to the function, as y=f(x)+Offset). Same for C1 and C2 continuity,
+				/// using c1 and c2 flags.
+	int InsertFunct (ChFunction* myfx, double duration, double weight=1, bool c0=false, bool c1=false, bool c2=false, int position=-1);
+
+				/// Remove and deletes function with defined "position", and returns TRUE. 
+				///	 - If position = 0, removes always head (beginning), 
+				///  - If position = -1 removes tail (end). 
+				///  - If position > max number of current nodes, removes tail anyway, but returns NULL.
+	int KillFunct (int position);
+
+				/// Returns the ChFunction with given "position". 
+				///  - If position = 0, returns always head (beginning), 
+				///  - If position = -1 returns tail (end). 
+				///  - If position > max number of current nodes, returns tail fx anyway.
+	ChFunction* GetNthFunction (int position);		
+
+				/// As above, but returns the function node (containing function pointer, 
+				/// function duration, continuity flags with previous node, etc.) 
+	ChFseqNode* GetNthNode(int position);
+
+				/// As above, but returning duration. (return value is reference, so it 
+				/// can be also changed later, but remember Setup() for the 
+				/// ChFunction_Sequence after you modified this return value by reference ***TO DO***). 
+				/// If no function, returns 0.
+	double GetNthDuration(int position);
+
+		
+	double Get_y      (double x);
+	double Get_y_dx   (double x);
+	double Get_y_dxdx (double x);
+
+	double Get_weight (double x);
+
+	void Extimate_x_range (double& xmin, double& xmax);
+
+
+	int MakeOptVariableTree(ChList<chjs_propdata>* mtree);
+
+	int HandleNumber();			
+	int HandleAccess(int handle_id, double mx, double my, bool set_mode);
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Sigma.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Sigma.cpp
new file mode 100644
index 0000000..8b05118
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Sigma.cpp
@@ -0,0 +1,131 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Sigma.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Sigma.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Sigma> a_registration_sigma;
+
+void ChFunction_Sigma::Copy (ChFunction_Sigma* source)
+{
+	Set_start (source->start);
+	Set_end (source->end);
+	Set_amp (source->amp);
+}
+
+ChFunction* ChFunction_Sigma::new_Duplicate ()
+{
+	ChFunction_Sigma* m_func;
+	m_func = new ChFunction_Sigma;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+void ChFunction_Sigma::Extimate_x_range (double& xmin, double& xmax)
+{
+	double mdx = end-start;
+	xmin = start +mdx*0.1;
+	xmax = end -mdx*0.1;
+}
+
+double ChFunction_Sigma::Get_y      (double x)
+{
+	double ret;
+	double A = (end - start);
+	if (x < start) return 0;
+	if (x > end) return amp;
+	else
+	{
+		ret = amp *( (3*(pow(((x-start)/A),2))) - 2*(pow(((x-start)/A),3)) );
+	}
+	return ret;
+}
+
+double ChFunction_Sigma::Get_y_dx   (double x)
+{
+	double ret;
+	double A = (end - start);
+	if ((x < start) || (x > end)) ret = 0;
+	else
+	{
+		ret = amp * ( 6*((x-start) / pow(A,2)) - 6*(pow((x-start),2)/pow(A,3))  );
+	}
+	return ret;
+}
+
+double ChFunction_Sigma::Get_y_dxdx (double x)
+{
+	double ret;
+	double A = (end - start);
+	if ((x < start) || (x > end)) ret = 0;
+	else
+	{
+		ret = amp * ( 6*(1/pow(A,2)) - 12*((x-start)/pow(A,3))  );
+	}
+	return ret;
+}
+
+void ChFunction_Sigma::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << start;
+	mstream << end;
+	mstream << amp;
+}
+
+void ChFunction_Sigma::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> start;
+	mstream >> end;
+	mstream >> amp;
+}
+
+void ChFunction_Sigma::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_CONST  \n";
+
+	//***TO DO***
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Sigma.h b/SRC/ChronoEngine/motion_functions/ChFunction_Sigma.h
new file mode 100644
index 0000000..d8a2e5d
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Sigma.h
@@ -0,0 +1,93 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_SIGMA_H
+#define CHFUNCT_SIGMA_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Sigma.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_SIGMA     5
+
+
+
+/// SIGMA FUNCTION:           
+/// y = polynomial smooth ramp 
+
+class ChApi ChFunction_Sigma : public ChFunction
+{
+	CH_RTTI(ChFunction_Sigma, ChFunction);
+private:
+	double amp;
+	double start;
+	double end;
+public:
+	ChFunction_Sigma () {amp =1; start=0;  end=1;}
+	ChFunction_Sigma (double m_amp, double m_start, double m_end)  {start = m_start; end = m_end; amp = m_amp;};
+	~ChFunction_Sigma () {};
+	void Copy (ChFunction_Sigma* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_start (double m_start) {start = m_start;}
+	void Set_end   (double m_end)   {end = m_end;}
+	void Set_amp   (double m_amp)   {amp = m_amp;}
+	double Get_start ()   {return start;}
+	double Get_end ()   {return end;}
+	double Get_amp ()   {return amp;}
+
+	double Get_y      (double x) ;
+	double Get_y_dx   (double x) ;
+	double Get_y_dxdx (double x) ;
+
+	double Get_Ca_pos () {return 6.0;};
+	double Get_Ca_neg () {return 6.0;};
+	double Get_Cv () {return 1.5;};
+
+	void Extimate_x_range (double& xmin, double& xmax);
+	int Get_Type () {return (FUNCT_SIGMA);}
+
+	OPT_VARIABLES_START
+		"start",
+		"end",
+		"amp",
+	OPT_VARIABLES_END
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Sine.cpp b/SRC/ChronoEngine/motion_functions/ChFunction_Sine.cpp
new file mode 100644
index 0000000..3e22d84
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Sine.cpp
@@ -0,0 +1,90 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction_Sine.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Sine.h"
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChFunction_Sine> a_registration_sine;
+
+
+void ChFunction_Sine::Copy (ChFunction_Sine* source)
+{
+	Set_phase (source->phase);
+	Set_freq(source->freq);
+	Set_amp (source->amp);
+}
+
+ChFunction* ChFunction_Sine::new_Duplicate ()
+{
+	ChFunction_Sine* m_func;
+	m_func = new ChFunction_Sine;
+	m_func->Copy(this);
+	return (m_func);
+}
+
+void ChFunction_Sine::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChFunction::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << phase;
+	mstream << freq;
+	mstream << amp;
+}
+
+void ChFunction_Sine::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChFunction::StreamIN(mstream);
+
+		// stream in all member data
+	double dfoo;
+	mstream >> dfoo; Set_phase(dfoo);
+	mstream >> dfoo; Set_freq(dfoo);
+	mstream >> dfoo; Set_amp(dfoo);
+}
+
+void ChFunction_Sine::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FUNCT_SINE  \n";
+
+	//***TO DO***
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/motion_functions/ChFunction_Sine.h b/SRC/ChronoEngine/motion_functions/ChFunction_Sine.h
new file mode 100644
index 0000000..08a2a6c
--- /dev/null
+++ b/SRC/ChronoEngine/motion_functions/ChFunction_Sine.h
@@ -0,0 +1,92 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFUNCT_SINE_H
+#define CHFUNCT_SINE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChFunction_Sine.h
+//
+//   Function objects, 
+//   as scalar functions of scalar variable y=f(t)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChFunction_Base.h"
+
+
+namespace chrono 
+{
+
+#define FUNCT_SINE		2
+
+
+
+/// SINE FUNCTION:
+/// y = sin (phase + w*x )     w=2*PI*freq
+
+class ChApi ChFunction_Sine : public ChFunction
+{
+	CH_RTTI(ChFunction_Sine, ChFunction);
+private:
+	double amp;
+	double phase;
+	double freq;
+	double w;
+public:
+	ChFunction_Sine () {phase =0; freq=1;  w=2*CH_C_PI*freq; amp = 1;};
+	ChFunction_Sine (double m_phase, double m_freq, double m_amp)  {phase = m_phase; freq = m_freq; w=2*CH_C_PI*freq; amp = m_amp;};
+	~ChFunction_Sine () {};
+	void Copy (ChFunction_Sine* source);
+	ChFunction* new_Duplicate ();
+
+	void Set_phase (double m_phase) {phase = m_phase;};
+	void Set_freq  (double m_freq)  {freq = m_freq; w=2*CH_C_PI*freq;};
+	void Set_w	   (double m_w)		{w = m_w;		freq = w/(2*CH_C_PI);};
+	void Set_amp   (double m_amp)   {amp = m_amp;}
+	double Get_phase () {return phase;};
+	double Get_freq ()  {return freq;};
+	double Get_w	()  {return w;};
+	double Get_amp ()   {return amp;}
+
+	double Get_y      (double x) {return amp * (sin(phase + w*x)) ;};
+	double Get_y_dx   (double x) {return amp * w*(cos(phase + w*x))	;};
+	double Get_y_dxdx (double x) {return amp * -w*w*(sin(phase + w*x));};
+
+	int Get_Type () {return (FUNCT_SINE);}
+
+	OPT_VARIABLES_START
+		"amp",
+		"phase",
+		"freq",
+	OPT_VARIABLES_END
+
+	void StreamOUT(ChStreamOutAscii& mstream);
+	void StreamIN(ChStreamInBinary& mstream);
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/parallel/ChOpenMP.h b/SRC/ChronoEngine/parallel/ChOpenMP.h
new file mode 100644
index 0000000..8ef631f
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChOpenMP.h
@@ -0,0 +1,171 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHOPENMP_H
+#define CHOPENMP_H
+
+
+//////////////////////////////////////////////////
+//
+//   ChOpenMP.h
+//
+//   Interface for mutex utilities to be
+//   used when doing multithreading via OpenMP
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+
+#ifdef _OPENMP
+ # include <omp.h>
+#endif
+
+
+namespace chrono
+{
+
+#ifdef _OPENMP
+
+		/// Class that wraps a 'omp_lock_t' for doing a mutex
+		/// in OpenMP parallel sections.
+	class ChApi CHOMPmutex
+	{
+	public:
+	   CHOMPmutex() { omp_init_lock(&lock); }
+	   ~CHOMPmutex() { omp_destroy_lock(&lock); }
+	   void Lock() { omp_set_lock(&lock); }
+	   void Unlock() { omp_unset_lock(&lock); }
+	   
+	   CHOMPmutex(const CHOMPmutex& ) { omp_init_lock(&lock); }
+	   CHOMPmutex& operator= (const CHOMPmutex& ) { return *this; }
+	private:
+	   omp_lock_t lock;
+	};
+
+		/// Class that wraps some useful functions in OpenMP
+		/// (in case no OpenMP is used, it defaults to dummy functions
+		/// that do nothing)
+	class ChApi CHOMPfunctions
+	{
+	public: 
+				/// Sets the number of threads in subsequent parallel 
+				/// regions, unless overridden by a 'num_threads' clause
+		static void SetNumThreads(int mth) { omp_set_num_threads(mth); }
+
+				/// Returns the number of threads in the parallel region.
+		static int  GetNumThreads() { return omp_get_num_threads(); }
+
+				/// Returns the thread number of the thread executing 
+				/// within its thread team.
+		static int  GetThreadNum() { return omp_get_thread_num(); }
+
+				/// Returns the number of available processors on this machine
+		static int  GetNumProcs() { return omp_get_num_procs(); }
+
+				/// Returns the max.number of threads that would be used
+				/// by default if num_threads not specified. This is the same 
+				/// number as GetNumProcs() on most OMP implementations.
+		static int  GetMaxThreads() { return omp_get_max_threads(); }
+	};
+	
+
+ #else
+		/// Dummy mmutex that does nothing in case that no parallel 
+		/// multithreading via OpenMP is available.
+	class ChApi CHOMPmutex
+	{
+	public:
+		void Lock() {}
+		void Unlock() {}
+	};
+
+		/// Dummy functions that do nothing in case that no parallel 
+		/// multithreading via OpenMP is available.
+	class ChApi CHOMPfunctions
+	{
+	public: 
+		static void SetNumThreads(int) { }
+		static int  GetNumThreads() { return 1;}
+		static int  GetThreadNum() { return 0;}
+		static int  GetNumProcs() { return 1;}
+		static int  GetMaxThreads() { return 1;}
+	};
+
+ #endif
+ 
+
+
+
+
+
+
+
+
+
+
+
+		/// Exception-safe wrapper to a mutex: it automatically locks the 
+		/// mutex as soon as the wrapper is created, and releases the 
+		/// mutex when the wrapper is deleted (you simply put the wrapper in
+		/// a code section delimited by {} parentheses, so it is deleted
+		/// by the compiler when exiting the scope of the section or in case
+		/// of premature exit because of an exception throw)
+ struct CHOMPscopedLock
+ {
+   explicit CHOMPscopedLock(CHOMPmutex& m) : 
+						mut(m), 
+						locked(true) 
+		{ 
+			mut.Lock(); 
+		}
+
+   ~CHOMPscopedLock() 
+		{ 
+			Unlock(); 
+		}
+
+   void Unlock() 
+		{ 
+			if(!locked) return; 
+			locked=false; 
+			mut.Unlock(); 
+		}
+
+   void LockAgain() 
+		{ 
+			if(locked) return; 
+			mut.Lock(); 
+			locked=true; 
+		}
+
+ private:
+	CHOMPmutex& mut;
+	bool locked;
+
+ private: // trick to prevent copying the scoped lock.
+	void operator=(const CHOMPscopedLock&);
+	CHOMPscopedLock(const CHOMPscopedLock&);
+ };
+
+
+
+
+};  // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/parallel/ChThreads.cpp b/SRC/ChronoEngine/parallel/ChThreads.cpp
new file mode 100644
index 0000000..c37d466
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreads.cpp
@@ -0,0 +1,46 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChThreads.cpp
+//
+//	 CHRONO
+//   ------
+//   Multibody dinamics engine
+//
+//   Math functions for:
+//
+//	 - COORDINATES
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "parallel/ChThreads.h"
+ 
+
+namespace chrono
+{
+
+/*
+ChThreads::~ChThreads()
+{
+
+}
+*/
+
+
+
+} // end namespace
+
diff --git a/SRC/ChronoEngine/parallel/ChThreads.h b/SRC/ChronoEngine/parallel/ChThreads.h
new file mode 100644
index 0000000..cbf4ede
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreads.h
@@ -0,0 +1,107 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTHREADS_H
+#define CHTHREADS_H
+
+
+//////////////////////////////////////////////////
+//
+//   ChThreads.h
+//
+//   Interface for multithreading (for multi-core 
+//   processors, SPUs etc.)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+
+
+#if ((defined WIN32)|| (defined WIN64))
+	#include "ChThreadsWIN32.h"
+#endif
+
+#if (defined(__linux__) || defined(__APPLE__))
+    #include "ChThreadsPOSIX.h"
+#endif
+
+
+namespace chrono
+{
+
+
+class ChApi ChThreads : private ChThreadsPlatformImplementation
+{
+public:
+
+	ChThreads (ChThreadConstructionInfo& threadConstructionInfo) : ChThreadsPlatformImplementation(threadConstructionInfo) {};
+
+	virtual ~ChThreads() {};
+
+		///send messages to threads-fibers, executing the user function
+	virtual	void sendRequest(unsigned int uiCommand, void* uiUserPtr, unsigned int threadId) 
+		{
+			ChThreadsPlatformImplementation::sendRequest(uiCommand, uiUserPtr, threadId);
+		};
+
+		///check for messages from threads-fibers
+	virtual	void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
+		{
+			ChThreadsPlatformImplementation::waitForResponse(puiArgument0, puiArgument1);
+		};
+
+		///start the threads-fibers 
+	virtual	void startSPU()
+		{
+			ChThreadsPlatformImplementation::startSPU();
+		};
+
+		///tell the task scheduler we are done with the threads-fibers
+	virtual	void stopSPU()
+		{
+			ChThreadsPlatformImplementation::stopSPU();
+		};
+
+		/// Wait for all the threads/fibers to finish
+	virtual void flush()
+		{
+			ChThreadsPlatformImplementation::flush();
+		};
+
+		/// Returns the number of threads handled by this pool
+	virtual int getNumberOfThreads()
+		{
+			return ChThreadsPlatformImplementation::getNumberOfThreads();
+		};
+
+	virtual std::string getUniqueName() 
+		{
+			return ChThreadsPlatformImplementation::getUniqueName();
+		}
+};
+
+
+
+
+
+
+
+
+};  // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/parallel/ChThreadsFunct.h b/SRC/ChronoEngine/parallel/ChThreadsFunct.h
new file mode 100644
index 0000000..a9f7802
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreadsFunct.h
@@ -0,0 +1,73 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTHREADSFUNCT_H
+#define CHTHREADSFUNCT_H
+
+
+//////////////////////////////////////////////////
+//
+//   ChThreadsFunct.h
+//
+//   Stuff used by interface for multithreading (for multi-core 
+//   processors) on the Window platform
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+
+namespace chrono
+{
+
+
+typedef void  (*ChThreadFunc)(void* userPtr,void* lsMemory);
+
+typedef void* (*ChMemorySetupFunc)();
+
+
+struct	ChThreadConstructionInfo
+	{
+		ChThreadConstructionInfo(char* uniqueName,
+									ChThreadFunc userThreadFunc,
+									ChMemorySetupFunc	lsMemoryFunc,
+									int numThreads=1,
+									int threadStackSize=65535
+									)
+									:m_uniqueName(uniqueName),
+									m_userThreadFunc(userThreadFunc),
+									m_lsMemoryFunc(lsMemoryFunc),
+									m_numThreads(numThreads),
+									m_threadStackSize(threadStackSize)
+		{
+
+		}
+
+		char*					m_uniqueName;
+		ChThreadFunc			m_userThreadFunc;
+		ChMemorySetupFunc		m_lsMemoryFunc;
+		int						m_numThreads;
+		int						m_threadStackSize;
+
+	};
+
+
+};  // END_OF_NAMESPACE____
+
+#endif
+
+
diff --git a/SRC/ChronoEngine/parallel/ChThreadsPOSIX.cpp b/SRC/ChronoEngine/parallel/ChThreadsPOSIX.cpp
new file mode 100644
index 0000000..221deb6
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreadsPOSIX.cpp
@@ -0,0 +1,227 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChThreadsPOSIX.cpp
+//
+//	 CHRONO
+//   ------
+//   Multibody dinamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#if (defined(__linux__)||defined(__APPLE__))
+
+
+#define DWORD unsigned int
+
+
+#include <stdio.h>
+#include "parallel/ChThreadsPOSIX.h"
+
+#define checkPThreadFunction(returnValue) \
+    if(0 != returnValue) { \
+        printf("PThread problem at line %i in file %s: %i\n", __LINE__, __FILE__, returnValue); \
+    }
+
+
+namespace chrono
+{
+
+
+
+
+ChThreadsPOSIX::ChThreadsPOSIX(ChThreadConstructionInfo& threadConstructionInfo)
+{
+	makeThreads(threadConstructionInfo);
+}
+
+
+ChThreadsPOSIX::~ChThreadsPOSIX()
+{
+	stopSPU();
+}
+
+
+
+
+
+
+
+static void *threadFunction(void *argument) 
+{
+
+	ChThreadStatePOSIX* status = (ChThreadStatePOSIX*)argument;
+
+	
+	while (1)
+	{
+        	checkPThreadFunction(sem_wait(&status->startSemaphore));
+		
+		void* userPtr = status->m_userPtr;
+
+		if (userPtr)
+		{
+			status->m_userThreadFunc(userPtr,status->m_lsMemory);
+			status->m_status = 2;
+			checkPThreadFunction(sem_post(status->mainSemaphore));
+
+            		//status->threadUsed++;
+		} else {
+			//exit Thread
+			//status->m_status = 3; //??? needed ???
+			//checkPThreadFunction(sem_post(&this->mainSemaphore)); //??? needed ???
+			break;
+		}
+		
+	}
+
+	return 0;
+
+}
+
+///send messages to SPUs
+void ChThreadsPOSIX::sendRequest(uint32_t uiCommand, void* uiUserPtr, unsigned int threadId)//(uint32_t uiCommand, uint32_t uiArgument0, uint32_t taskId)
+{
+	ChThreadStatePOSIX&	spuStatus = m_activeSpuStatus[threadId];
+
+	spuStatus.m_commandId = uiCommand;
+	spuStatus.m_status = 1;
+	spuStatus.m_userPtr = uiUserPtr;
+
+			// fire event to start new task
+        checkPThreadFunction(sem_post(&spuStatus.startSemaphore));
+}
+
+
+///check for messages from SPUs
+void ChThreadsPOSIX::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
+{
+	///We should wait for (one of) the first tasks to finish (or other SPU messages), and report its response
+	
+	///A possible response can be 'yes, SPU handled it', or 'no, please do a PPU fallback'
+
+
+	btAssert(m_activeSpuStatus.size());
+
+    // wait for any of the threads to finish
+    checkPThreadFunction(sem_wait(&this->mainSemaphore));
+        
+	// get at least one thread which has finished
+        int last = -1;
+        
+        for(int t=0; t < m_activeSpuStatus.size(); ++t) {
+            if(2 == m_activeSpuStatus[t].m_status) {
+                last = t;
+                break;
+            }
+        }
+
+	ChThreadStatePOSIX& spuStatus = m_activeSpuStatus[last];
+
+	btAssert(spuStatus.m_status > 1);
+	spuStatus.m_status = 0;
+
+	// need to find an active spu
+	btAssert(last >= 0);
+
+	*puiArgument0 = spuStatus.m_taskId;
+	*puiArgument1 = spuStatus.m_status;
+}
+
+
+
+void ChThreadsPOSIX::makeThreads(ChThreadConstructionInfo& threadConstructionInfo)
+{
+	m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
+
+	uniqueName = threadConstructionInfo.m_uniqueName;
+
+    checkPThreadFunction(sem_init(&this->mainSemaphore, 0, 0));
+
+	for (int i=0;i < threadConstructionInfo.m_numThreads;i++)
+	{
+
+		ChThreadStatePOSIX&	spuStatus = m_activeSpuStatus[i];
+                
+		spuStatus.mainSemaphore = &this->mainSemaphore;
+
+        checkPThreadFunction(sem_init(&spuStatus.startSemaphore, 0, 0));
+        checkPThreadFunction(pthread_create(&spuStatus.thread, NULL, &threadFunction, (void*)&spuStatus));
+
+		spuStatus.m_userPtr=0;
+
+		spuStatus.m_taskId = i;
+		spuStatus.m_commandId = 0;
+		spuStatus.m_status = 0;
+		spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
+		spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
+        spuStatus.threadUsed = 0;
+		
+	}
+
+}
+
+void ChThreadsPOSIX::flush()
+{ 
+	int nthreads = m_activeSpuStatus.size();
+
+	while (1)
+	{
+		bool stillrunning = false;
+		for (int i=0; i<nthreads; i++)
+		{
+			if (m_activeSpuStatus[i].m_status !=0)
+			{
+				stillrunning = true;
+				unsigned int mtaskid; unsigned int mres2;
+				waitForResponse(&mtaskid, &mres2);
+			}
+		}
+		if (!stillrunning)
+			return;
+	}
+}
+
+
+void ChThreadsPOSIX::startSPU()
+{
+}
+
+
+///tell the task scheduler we are done with the SPU tasks
+void ChThreadsPOSIX::stopSPU()
+{
+	for(size_t t=0; t < m_activeSpuStatus.size(); ++t) 
+	{
+            ChThreadStatePOSIX&	spuStatus = m_activeSpuStatus[t];
+
+            checkPThreadFunction(sem_destroy(&spuStatus.startSemaphore));
+            checkPThreadFunction(pthread_cancel(spuStatus.thread));
+    }
+    checkPThreadFunction(sem_destroy(&this->mainSemaphore));
+
+	m_activeSpuStatus.clear();
+}
+
+
+
+
+
+} // end namespace
+
+
+#endif  // end POSIX  platform-specific code
diff --git a/SRC/ChronoEngine/parallel/ChThreadsPOSIX.h b/SRC/ChronoEngine/parallel/ChThreadsPOSIX.h
new file mode 100644
index 0000000..04183b1
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreadsPOSIX.h
@@ -0,0 +1,123 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTHREADSPOSIX_H
+#define CHTHREADSPOSIX_H
+
+
+//////////////////////////////////////////////////
+//
+//   ChThreadsPOSIX.h
+//
+//   Interface for multithreading (for multi-core 
+//   processors) on the Window platform
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <string>
+#include "core/ChApiCE.h"
+#include "parallel/ChThreadsFunct.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+// UNIX - LINUX platform specific:
+#include <pthread.h>
+#include <semaphore.h>
+
+
+namespace chrono
+{
+
+typedef unsigned int      uint32_t;	
+
+
+
+
+struct	ChThreadStatePOSIX
+{
+	uint32_t	m_taskId;
+
+	uint32_t	m_commandId;
+	uint32_t	m_status;
+
+	ChThreadFunc	m_userThreadFunc; //user function
+	void*	m_userPtr;  //user data
+	void*	m_lsMemory; //initialized using PosixLocalStoreMemorySetupFunc
+
+    pthread_t thread;
+    sem_t startSemaphore;
+
+	sem_t* mainSemaphore;
+
+    unsigned long threadUsed;
+};
+
+
+
+
+class ChApi ChThreadsPOSIX 
+{
+
+	btAlignedObjectArray<ChThreadStatePOSIX>	m_activeSpuStatus;
+	btAlignedObjectArray<void*>				    m_completeHandles;
+
+	std::string uniqueName;
+
+	// this semaphore will signal, if and how many threads are finished with their work
+	sem_t mainSemaphore;
+
+public:
+
+	
+
+		/// Constructor: create and initialize N threads. 
+	ChThreadsPOSIX(ChThreadConstructionInfo& threadConstructionInfo);
+
+		/// Destructor: cleanup/shutdown 
+	virtual	~ChThreadsPOSIX();
+
+
+	void	makeThreads(ChThreadConstructionInfo&	threadInfo);
+
+
+	virtual	void sendRequest(uint32_t uiCommand, void* uiUserPtr, unsigned int threadId);
+
+	virtual	void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
+
+	virtual	void startSPU();
+
+	virtual	void stopSPU();
+
+	virtual void flush();
+
+	virtual int getNumberOfThreads() {return  m_activeSpuStatus.size();}
+
+	virtual std::string getUniqueName() {return uniqueName;}
+};
+
+
+
+
+typedef ChThreadsPOSIX ChThreadsPlatformImplementation;
+
+
+};  // END_OF_NAMESPACE____
+
+#endif
+
+
diff --git a/SRC/ChronoEngine/parallel/ChThreadsSync.h b/SRC/ChronoEngine/parallel/ChThreadsSync.h
new file mode 100644
index 0000000..8d8f984
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreadsSync.h
@@ -0,0 +1,298 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2007 Starbreeze Studios
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event will the authors be held liable for any damages arising from the use of this software.
+Permission is granted to anyone to use this software for any purpose, 
+including commercial applications, and to alter it and redistribute it freely, 
+subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Written by: Marten Svanfeldt
+
+Modified by: Alessandro Tasora
+
+*/
+
+#ifndef SPU_SYNC_H
+#define	SPU_SYNC_H
+
+
+//#include "PlatformDefinitions.h"
+
+
+#if defined(WIN32)||defined(WIN64)
+
+#define WIN32_LEAN_AND_MEAN
+
+#ifdef _XBOX
+#include <Xtl.h>
+#else
+#include <windows.h>
+#include <intrin.h>
+#endif
+
+
+		/// Class that wraps a thread mutex, a locking mechanism to avoid,
+		/// for instance, multiple thread concurrent access to the same data.
+class ChMutexSpinlock
+{
+public:
+
+	ChMutexSpinlock ()
+	{
+		//if (!InitializeCriticalSectionAndSpinCount(&_cs, 4000))
+		//	throw SystemException("cannot create mutex");
+		InitializeCriticalSection(&_cs);
+	}
+	~ChMutexSpinlock()
+	{
+		DeleteCriticalSection(&_cs); //???
+	}
+
+	void Lock ()
+	{
+		EnterCriticalSection(&_cs);
+	}
+
+	void Unlock ()
+	{
+		LeaveCriticalSection(&_cs);
+	}
+
+private:
+	CRITICAL_SECTION _cs;
+};
+
+
+
+#define EBUSY 16
+//#pragma intrinsic(_InterlockedExchange)
+//#pragma intrinsic(_ReadWriteBarrier)
+
+		/// Class that wraps a spinlock, a very fast locking mutex 
+		/// that should be used only for short wait periods.
+		/// This uses MSVC intrinsics to mimic a fast spinlock as 
+		/// in pthreads.h, but without the need of including 
+		/// the pthreads library for windows.
+		/// See http://locklessinc.com/articles/pthreads_on_windows/
+class ChApi ChSpinlock
+{
+public:
+   ChSpinlock() 
+			{ 
+				lock = 0;
+			}
+   ~ChSpinlock() 
+			{ 
+			}
+   void Lock() 
+			{ 
+				while (_InterlockedExchange(&lock, EBUSY))
+				{
+					/* Don't lock the bus whilst waiting */
+					while (lock)
+					{
+						YieldProcessor();
+						/* Compiler barrier.  Prevent caching of *l */
+						_ReadWriteBarrier();
+					}
+				}
+			}
+   void Unlock() 
+			{ 
+				_ReadWriteBarrier();
+				lock = 0;
+			}
+   
+
+private:
+	 typedef long pseudo_pthread_spinlock_t;
+	pseudo_pthread_spinlock_t lock;
+};
+
+
+
+
+#endif
+
+
+
+//
+// LINUX CODE
+//
+
+
+#if (defined(__linux__)||defined(__APPLE__))
+
+
+#include <pthread.h>
+#include <semaphore.h>
+//pthread_spin functions are not defined on APPLE
+//this is a work around, no clue if it works. - Hammad
+#if defined(__APPLE__)
+#include <cerrno>
+typedef int pthread_spinlock_t;
+
+static inline int pthread_spin_init(pthread_spinlock_t *lock, int pshared) {
+	__asm__ __volatile__ ("" ::: "memory");
+	*lock = 0;
+	return 0;
+}
+
+static inline int pthread_spin_destroy(pthread_spinlock_t *lock) {
+	return 0;
+}
+
+static inline int pthread_spin_lock(pthread_spinlock_t *lock) {
+	while (1) {
+		int i;
+		for (i = 0; i < 10000; i++) {
+			if (__sync_bool_compare_and_swap(lock, 0, 1)) {
+				return 0;
+			}
+		}
+		sched_yield();
+	}
+}
+
+static inline int pthread_spin_trylock(pthread_spinlock_t *lock) {
+	if (__sync_bool_compare_and_swap(lock, 0, 1)) {
+		return 0;
+	}
+	return EBUSY;
+}
+
+static inline int pthread_spin_unlock(pthread_spinlock_t *lock) {
+	__asm__ __volatile__ ("" ::: "memory");
+	*lock = 0;
+	return 0;
+}
+
+
+
+#endif
+
+
+		/// Class that wraps a thread mutex, a locking mechanism to avoid,
+		/// for instance, multiple thread concurrent access to the same data.
+class ChMutexSpinlock
+{
+public:
+	ChMutexSpinlock ()
+	{
+		pthread_mutex_init( &_cs_mutex,0);
+	}
+	~ChMutexSpinlock()
+	{
+		pthread_mutex_destroy( &_cs_mutex );
+	}
+
+	void Lock ()
+	{
+		pthread_mutex_lock( &_cs_mutex );
+	}
+
+	void Unlock ()
+	{
+		pthread_mutex_unlock( &_cs_mutex );
+	}
+
+private:
+	pthread_mutex_t _cs_mutex;
+};
+
+		/// Class that wraps a spinlock, a very fast locking mutex 
+		/// that should be used only for short wait periods. 
+		/// ***TO BE TESTED***
+class ChSpinlock
+{
+public:
+	typedef pthread_spinlock_t SpinVariable;
+
+	ChSpinlock ()
+	{
+		pthread_spin_init( &spinVariable ,0);
+	}
+	~ChSpinlock() 
+	{ 
+		pthread_spin_destroy( &spinVariable);
+	}
+
+	void Lock ()
+	{
+		pthread_spin_lock( &spinVariable);
+	}
+
+	void Unlock ()
+	{
+		pthread_spin_unlock( &spinVariable);
+	}
+
+private:
+	SpinVariable spinVariable;
+};
+
+#endif
+
+
+//
+// CELL CODE
+//
+
+
+#if defined (__CELLOS_LV2__)
+
+//#include <cell/atomic.h>
+#include <cell/sync/mutex.h>
+
+class ChSpinlock
+{
+public:
+	typedef CellSyncMutex SpinVariable;
+
+	ChSpinlock (SpinVariable* var)
+		: spinVariable (var)
+	{}
+#ifndef __SPU__
+	void Init ()
+	{
+		//*spinVariable = 1;
+		cellSyncMutexInitialize(spinVariable);
+	}
+#endif
+
+#ifdef __SPU__
+	void Lock ()
+	{
+		// lock semaphore
+		/*while (cellAtomicTestAndDecr32(atomic_buf, (uint64_t)spinVariable) == 0) 
+		{
+
+		};*/
+		cellSyncMutexLock((uint64_t)spinVariable);
+	}
+
+	void Unlock ()
+	{
+		//cellAtomicIncr32(atomic_buf, (uint64_t)spinVariable);
+		cellSyncMutexUnlock((uint64_t)spinVariable);
+	}
+#endif
+
+private:
+	SpinVariable*	spinVariable;
+	ATTRIBUTE_ALIGNED128(uint32_t		atomic_buf[32]);
+};
+
+#endif
+
+
+
+
+#endif
+
diff --git a/SRC/ChronoEngine/parallel/ChThreadsWIN32.cpp b/SRC/ChronoEngine/parallel/ChThreadsWIN32.cpp
new file mode 100644
index 0000000..a91f95e
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreadsWIN32.cpp
@@ -0,0 +1,223 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChThreadsWIN32.cpp
+//
+//	 CHRONO
+//   ------
+//   Multibody dinamics engine
+//
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#if ((defined WIN32)|| (defined WIN64))
+
+
+
+#include <stdio.h>
+#include "parallel/ChThreadsWIN32.h"
+#include <windows.h>
+#include "core/ChLog.h"
+
+namespace chrono
+{
+
+
+const wchar_t *GetWC(const char *c)
+{
+  const size_t cSize = strlen(c)+1;
+  wchar_t* wc = new wchar_t[cSize];
+  mbstowcs (wc, c, cSize);
+  return wc;
+}
+
+
+ChThreadsWIN32::ChThreadsWIN32(ChThreadConstructionInfo& threadConstructionInfo)
+{
+	makeThreads(threadConstructionInfo);
+}
+
+
+ChThreadsWIN32::~ChThreadsWIN32()
+{
+	stopSPU();
+
+	// STOP thread fx
+	
+	for (int i=0;i< m_activeSpuStatus.size() ;i++)
+		this->sendRequest(1, 0, i);
+
+	for (int i=0;i< m_activeSpuStatus.size() ;i++)
+	{
+		WaitForSingleObject (m_activeSpuStatus[i].m_threadHandle, 1000);
+		CloseHandle (m_activeSpuStatus[i].m_threadHandle);
+		CloseHandle (m_activeSpuStatus[i].m_eventCompletetHandle);
+		CloseHandle (m_activeSpuStatus[i].m_eventStartHandle);
+	}
+}
+
+
+DWORD WINAPI Thread_no_1( LPVOID lpParam ) 
+{
+
+	ChThreadStateWIN32* status = (ChThreadStateWIN32*)lpParam;
+
+	while (1)
+	{
+		WaitForSingleObject(status->m_eventStartHandle,INFINITE);
+		btAssert(status->m_status);
+
+		void* userPtr = status->m_userPtr;
+
+		if (userPtr)
+		{
+			status->m_userThreadFunc(userPtr,status->m_lsMemory);
+			status->m_status = 2;
+			SetEvent(status->m_eventCompletetHandle);
+		} else
+		{
+			//exit Thread
+			break;
+		}
+		
+	}
+
+	return 0;
+
+}
+
+///send messages to SPUs
+void ChThreadsWIN32::sendRequest(uint32_t uiCommand, void* uiUserPtr, uint32_t threadId)
+{
+
+	ChThreadStateWIN32&	spuStatus = m_activeSpuStatus[threadId];
+	btAssert(threadId>=0);
+	btAssert(threadId<m_activeSpuStatus.size());
+
+	spuStatus.m_commandId	= uiCommand;
+	spuStatus.m_status		= 1;
+	spuStatus.m_userPtr		= uiUserPtr;
+
+	///fire event to start new task
+	SetEvent(spuStatus.m_eventStartHandle);
+
+}
+ 
+
+///check for messages from SPUs
+void ChThreadsWIN32::waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1)
+{
+	btAssert(m_activeSpuStatus.size());
+
+	int last = -1;
+
+	DWORD res = WaitForMultipleObjects(m_completeHandles.size(), &m_completeHandles[0], FALSE, INFINITE);
+	btAssert(res != WAIT_FAILED);
+	last = res - WAIT_OBJECT_0;
+
+	ChThreadStateWIN32& spuStatus = m_activeSpuStatus[last];
+	btAssert(spuStatus.m_threadHandle);
+	btAssert(spuStatus.m_eventCompletetHandle);
+
+	btAssert(spuStatus.m_status > 1);
+	spuStatus.m_status = 0;
+
+	///need to find an active spu
+	btAssert(last>=0);
+
+	*puiArgument0 = spuStatus.m_taskId;
+	*puiArgument1 = spuStatus.m_status; 
+
+}
+
+
+
+void ChThreadsWIN32::makeThreads(ChThreadConstructionInfo& threadConstructionInfo)
+{
+	m_activeSpuStatus.resize(threadConstructionInfo.m_numThreads);
+	m_completeHandles.resize(threadConstructionInfo.m_numThreads);
+
+	uniqueName = threadConstructionInfo.m_uniqueName;
+
+	for (int i=0;i<threadConstructionInfo.m_numThreads;i++)
+	{
+		ChThreadStateWIN32&	spuStatus = m_activeSpuStatus[i];
+
+		LPSECURITY_ATTRIBUTES lpThreadAttributes=NULL;
+		SIZE_T dwStackSize=threadConstructionInfo.m_threadStackSize;
+		LPTHREAD_START_ROUTINE lpStartAddress=&Thread_no_1;
+		LPVOID lpParameter=&spuStatus;
+		DWORD dwCreationFlags=0;
+		LPDWORD lpThreadId=0;
+
+		spuStatus.m_userPtr=0;
+
+		sprintf(spuStatus.m_eventStartHandleName,"eventStart%s%d",threadConstructionInfo.m_uniqueName,i);
+
+		spuStatus.m_eventStartHandle = CreateEvent(0,false,false, GetWC(spuStatus.m_eventStartHandleName));
+
+		sprintf(spuStatus.m_eventCompletetHandleName,"eventComplete%s%d",threadConstructionInfo.m_uniqueName,i);
+		spuStatus.m_eventCompletetHandle = CreateEvent(0,false,false,GetWC(spuStatus.m_eventCompletetHandleName));
+
+		m_completeHandles[i] = spuStatus.m_eventCompletetHandle;
+		HANDLE handle = CreateThread(lpThreadAttributes,dwStackSize,lpStartAddress,lpParameter,	dwCreationFlags,lpThreadId);
+		SetThreadPriority(handle,THREAD_PRIORITY_HIGHEST);
+
+		spuStatus.m_taskId = i;
+		spuStatus.m_commandId	= 0;
+		spuStatus.m_status		= 0;
+		spuStatus.m_threadHandle = handle;
+		spuStatus.m_lsMemory = threadConstructionInfo.m_lsMemoryFunc();
+		spuStatus.m_userThreadFunc = threadConstructionInfo.m_userThreadFunc;
+	}
+}
+
+void ChThreadsWIN32::flush()
+{ 
+	int nthreads = m_activeSpuStatus.size();
+
+	while (1)
+	{
+		bool stillrunning = false;
+		for (int i=0; i<nthreads; i++)
+		{
+			if (m_activeSpuStatus[i].m_status !=0)
+			{
+				stillrunning = true;
+				unsigned int mtaskid; unsigned int mres2;
+				waitForResponse(&mtaskid, &mres2);
+			}
+		}
+		if (!stillrunning)
+			return;
+	}
+}
+
+void ChThreadsWIN32::startSPU()
+{
+}
+
+void ChThreadsWIN32::stopSPU()
+{
+}
+
+
+} // end namespace
+
+
+
+#endif // end Windows platform
diff --git a/SRC/ChronoEngine/parallel/ChThreadsWIN32.h b/SRC/ChronoEngine/parallel/ChThreadsWIN32.h
new file mode 100644
index 0000000..931af2e
--- /dev/null
+++ b/SRC/ChronoEngine/parallel/ChThreadsWIN32.h
@@ -0,0 +1,119 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTHREADSWIN32_H
+#define CHTHREADSWIN32_H
+
+
+//////////////////////////////////////////////////
+//
+//   ChThreadsWIN32.h
+//
+//   Interface for multithreading (for multi-core 
+//   processors) on the Window platform
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <string>
+#include "core/ChApiCE.h"
+#include "parallel/ChThreadsFunct.h"
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+namespace chrono
+{
+
+typedef unsigned int      uint32_t;
+
+//typedef void (*Win32ThreadFunc)(void* userPtr,void* lsMemory);
+//typedef void* (*Win32lsMemorySetupFunc)();
+
+
+
+struct	ChThreadStateWIN32
+{
+	uint32_t	m_taskId;
+
+	uint32_t	m_commandId;
+	uint32_t	m_status;
+
+	ChThreadFunc	m_userThreadFunc; //user function
+	void*	m_userPtr;				  //user data
+	void*	m_lsMemory;				  //initialized using Win32LocalStoreMemorySetupFunc
+
+	void*	m_threadHandle; 
+
+	void*	m_eventStartHandle;
+	char	m_eventStartHandleName[32];
+
+	void*	m_eventCompletetHandle;
+	char	m_eventCompletetHandleName[32];
+};
+
+
+
+
+class ChApi ChThreadsWIN32 // : public ChThreads
+{
+
+	btAlignedObjectArray<ChThreadStateWIN32>	m_activeSpuStatus;
+	btAlignedObjectArray<void*>				    m_completeHandles;
+
+	std::string uniqueName;
+
+public:
+
+	
+
+		/// Constructor: create and initialize N threads. 
+	ChThreadsWIN32(ChThreadConstructionInfo& threadConstructionInfo);
+
+		/// Destructor: cleanup/shutdown 
+	virtual	~ChThreadsWIN32();
+
+
+	void	makeThreads(ChThreadConstructionInfo&	threadInfo);
+
+
+	virtual	void sendRequest(uint32_t uiCommand, void* uiUserPtr, unsigned int threadId);
+
+	virtual	void waitForResponse(unsigned int *puiArgument0, unsigned int *puiArgument1);
+
+	virtual	void startSPU();
+
+	virtual	void stopSPU();
+
+	virtual void flush();
+
+	virtual int getNumberOfThreads() {return  m_activeSpuStatus.size();}
+
+	virtual std::string getUniqueName() {return uniqueName;}
+};
+
+
+
+
+typedef ChThreadsWIN32 ChThreadsPlatformImplementation;
+
+
+};  // END_OF_NAMESPACE____
+
+#endif
+
+
diff --git a/SRC/ChronoEngine/physics/ChApidll.cpp b/SRC/ChronoEngine/physics/ChApidll.cpp
new file mode 100644
index 0000000..278898f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChApidll.cpp
@@ -0,0 +1,60 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChApidll.cpp
+//
+//   Some interfaces for using Chrono engine as dll
+//   in third party objects. 
+//
+//  
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+   
+  
+#include "physics/ChApidll.h"
+
+  #include "parallel/ChOpenMP.h"
+
+
+namespace chrono 
+{
+
+static ChGlobals* my_dll_globals = 0;
+ 
+
+extern ChGlobals* DLL_CreateGlobals()
+{
+	//if (GLOBAL_Vars==0)
+	//	GLOBAL_Vars = new ChGlobals;  //***OBOSLETE*** GLOBAL_Vars will disappear soon
+	if (my_dll_globals==0)
+	{
+		my_dll_globals = new ChGlobals;
+		SetCHGLOBALS (my_dll_globals);
+		GLOBAL_Vars = my_dll_globals;  //***OBOSLETE*** GLOBAL_Vars will disappear soon
+	}
+
+	return my_dll_globals;
+}
+
+extern void DLL_DeleteGlobals()
+{
+	if (my_dll_globals)
+		delete my_dll_globals;
+	my_dll_globals=0;
+}
+
+
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/physics/ChApidll.h b/SRC/ChronoEngine/physics/ChApidll.h
new file mode 100644
index 0000000..ee516c5
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChApidll.h
@@ -0,0 +1,58 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHAPIDLL_H
+#define CHAPIDLL_H
+
+///////////////////////////////////////////////////
+//  
+//   ChApidll.h
+//
+//   Functions to initialize and free the global
+//   variables of the library.
+//   Useful for using Chrono engine as dll
+//   in third party projects (NOT FOR R3D PLUGIN!)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include "physics/ChGlobal.h"
+#include "core/ChApiCE.h"
+
+
+extern int DLL_TEST(int a, int b);
+
+namespace chrono 
+{
+
+
+		/// Create a ChGlobal data, sets it as the default return for the CHGLOBALS() 
+		/// function, and returns the ChGlobal object.
+		/// Must be called ALWAYS once at the beginning of the program using Chrono dll.
+extern ChApi ChGlobals* DLL_CreateGlobals();
+
+		/// Deletes the global data created with DLL_CreateGlobals().
+		/// Must be called ALWAYS once at the end of the program using Chrono dll.
+extern ChApi void DLL_DeleteGlobals();
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChAssembly.cpp b/SRC/ChronoEngine/physics/ChAssembly.cpp
new file mode 100644
index 0000000..967d321
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChAssembly.cpp
@@ -0,0 +1,937 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChAssembly.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "core/ChTrasform.h"
+#include "physics/ChAssembly.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChSystem.h"
+
+#include "physics/ChExternalObject.h"
+#include "collision/ChCModelBulletDEM.h"
+#include "core/ChLinearAlgebra.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+	// Hierarchy-handling functions
+
+#define Bpointer		    (*ibody)
+#define HIER_BODY_INIT      std::vector<ChBody*>::iterator ibody = bodylist.begin();
+#define HIER_BODY_NOSTOP    (ibody != bodylist.end())
+#define HIER_BODY_NEXT	    ibody++;
+
+#define Lpointer		    (*iterlink)
+#define HIER_LINK_INIT      std::list<ChLink*>::iterator iterlink = linklist.begin();
+#define HIER_LINK_NOSTOP    (iterlink != linklist.end())
+#define HIER_LINK_NEXT	    iterlink++;
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChAssembly> a_registration_ChAssembly;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SOLID BODIES
+
+
+ChAssembly::ChAssembly ()
+{
+	do_collide = false;
+	do_limit_speed = false;
+
+	linklist.clear(); 
+	bodylist.clear();
+
+	max_speed = 0.5f;
+	max_wvel  = 2.0f*float(CH_C_PI);
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+}
+
+
+
+ChAssembly::~ChAssembly ()
+{
+	RemoveAllBodies(); 
+	RemoveAllLinks();
+}
+
+void ChAssembly::Copy(ChAssembly* source)
+{
+		// copy the parent class data...
+	ChPhysicsItem::Copy(source);
+
+	do_collide = source->do_collide;
+	do_limit_speed = source->do_limit_speed;
+
+	max_speed = source->max_speed;
+	max_wvel  = source->max_wvel;
+}
+
+void ChAssembly::SetSystem(ChSystem* m_system)
+{
+	this->system=m_system;
+	HIER_BODY_INIT
+	while (HIER_BODY_NOSTOP)
+	{
+		Bpointer->SetSystem(m_system);
+		HIER_BODY_NEXT
+	}
+	HIER_LINK_INIT
+	while (HIER_LINK_NOSTOP)
+	{
+		Lpointer->SetSystem(m_system);
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::Clear()
+{
+	RemoveAllLinks();
+	RemoveAllBodies();
+}
+
+
+void ChAssembly::RemoveAllBodies() 
+{ 
+	HIER_BODY_INIT
+	while (HIER_BODY_NOSTOP)
+	{
+		// make sure to remove bodies from collision system before calling this.
+
+		// nullify backward link to system
+		Bpointer->SetSystem(0);	
+		// this may delete the body, if none else's still referencing it..
+		Bpointer->RemoveRef();
+		HIER_BODY_NEXT
+	}	
+	bodylist.clear(); 
+}
+
+
+void ChAssembly::RemoveAllLinks() 
+{ 
+
+	HIER_LINK_INIT
+	while (HIER_LINK_NOSTOP)
+	{
+		// nullify backward link to system
+		Lpointer->SetSystem(0);	
+		// this may delete the link, if none else's still referencing it..
+		Lpointer->RemoveRef();
+		HIER_LINK_NEXT
+	}	
+	linklist.clear(); 
+}
+
+int ChAssembly::GetDOF()
+{
+	int ndof = 0;
+
+	HIER_BODY_INIT					
+	while HIER_BODY_NOSTOP		
+	{
+		ndof+=Bpointer->GetDOF();
+		HIER_BODY_NEXT
+	}
+	return ndof;
+}
+
+int ChAssembly::GetDOC_c()
+{
+	int ndoc=0;
+
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		ndoc   += Lpointer->GetDOC_c();
+		HIER_LINK_NEXT
+	}
+	return ndoc;
+}
+
+int ChAssembly::GetDOC_d()
+{
+	int ndoc=0;
+
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		ndoc   += Lpointer->GetDOC_d();
+		HIER_LINK_NEXT
+	}
+	return ndoc;
+}
+
+//// 
+void ChAssembly::InjectVariables(ChLcpSystemDescriptor& mdescriptor)
+{	
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->InjectVariables(mdescriptor);
+		HIER_BODY_NEXT
+	}
+}
+
+
+void ChAssembly::VariablesFbReset()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesFbReset();
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::VariablesFbLoadForces(double factor)
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesFbLoadForces(factor);
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::VariablesFbIncrementMq()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesFbIncrementMq();
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::VariablesQbLoadSpeed()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesQbLoadSpeed();
+		HIER_BODY_NEXT
+	}
+}
+
+
+void ChAssembly::VariablesQbSetSpeed(double step)
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesQbSetSpeed(step);
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::VariablesQbIncrementPosition(double dt_step)
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesQbIncrementPosition(dt_step);
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->InjectConstraints(mdescriptor);
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsBiReset()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsBiReset();
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp) 
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsBiLoad_C(factor, recovery_clamp, do_clamp);
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsBiLoad_Ct(double factor)
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsBiLoad_Ct(factor);
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsBiLoad_Qc(double factor)
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsBiLoad_Qc(factor);
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsFbLoadForces(double factor)
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsFbLoadForces(factor);
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsLoadJacobians()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLoadJacobians();
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiLoadSuggestedSpeedSolution();
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiLoadSuggestedPositionSolution();
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiFetchSuggestedSpeedSolution();
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiFetchSuggestedPositionSolution();
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::ConstraintsFetch_react(double factor)
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsFetch_react(factor);
+		HIER_LINK_NEXT
+	}
+}
+
+
+void ChAssembly::SetNoSpeedNoAcceleration()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->SetNoSpeedNoAcceleration();
+		HIER_BODY_NEXT
+	}
+}
+
+
+////
+void ChAssembly::ClampSpeed()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->ClampSpeed();
+		HIER_BODY_NEXT
+	}
+}
+
+
+							// UpdateALL updates the state and time
+							// of the object AND the dependant (linked)
+							// markers and forces.
+
+void ChAssembly::Update()
+{
+	ChAssembly::Update(this->GetChTime());
+}
+
+
+
+							// As before, but keeps the current state.
+							// Mostly used for world reference body.
+void ChAssembly::Update (double mytime)
+{
+	ChTime = mytime;
+	ClampSpeed();			// Apply limits (if in speed clamping mode) to speeds.
+
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->Update(mytime);
+		HIER_BODY_NEXT
+	}
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->Update(mytime);
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::AddBody (ChSharedPtr<ChBody> newbody)
+{
+	assert(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), newbody.get_ptr())==bodylist.end());
+	assert(newbody->GetSystem()==0); // should remove from other system before adding here
+
+	newbody->AddRef();
+	newbody->SetSystem (this->GetSystem());
+	bodylist.push_back((newbody).get_ptr());
+
+	// add to collision system too
+	//if (newbody->GetCollide())
+	//	newbody->AddCollisionModelsToSystem();
+}
+
+void ChAssembly::AddLink (ChLink* newlink)
+{ 
+	assert(std::find<std::list<ChLink*>::iterator>(linklist.begin(), linklist.end(), newlink)==linklist.end());
+
+	newlink->AddRef();
+	newlink->SetSystem (this->GetSystem());
+	linklist.push_back(newlink);
+}
+
+void ChAssembly::AddLink (ChSharedPtr<ChLink> newlink)
+{
+	AddLink(newlink.get_ptr());
+}
+
+void ChAssembly::RemoveBody (ChSharedPtr<ChBody> mbody)
+{
+	assert(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), mbody.get_ptr() )!=bodylist.end());
+
+	// remove from collision system
+	if (mbody->GetCollide())
+		mbody->RemoveCollisionModelsFromSystem(); 
+ 
+	// warning! linear time search, to erase pointer from container.
+	bodylist.erase(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), mbody.get_ptr() ) );
+	
+	// nullify backward link to system
+	mbody->SetSystem(0);
+	// this may delete the body, if none else's still referencing it..
+	mbody->RemoveRef();
+}
+
+// Faster than RemoveLink because it does not require the linear time search
+std::list<ChLink*>::iterator ChAssembly::RemoveLinkIter(std::list<ChLink*>::iterator& mlinkiter)
+{
+	// nullify backward link to system
+	(*mlinkiter)->SetSystem(0);
+	// this may delete the link, if none else's still referencing it..
+	(*mlinkiter)->RemoveRef();
+
+	return linklist.erase(mlinkiter);
+}
+
+void ChAssembly::RemoveLink (ChSharedPtr<ChLink> mlink)
+{
+	assert(std::find<std::list<ChLink*>::iterator>(linklist.begin(), linklist.end(), mlink.get_ptr() )!=linklist.end());
+
+	// warning! linear time search, to erase pointer from container.
+	linklist.remove(mlink.get_ptr());//erase(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), mbody.get_ptr() ) );
+	
+	// nullify backward link to system
+	mlink->SetSystem(0);
+	// this may delete the body, if none else's still referencing it..
+	mlink->RemoveRef();
+}
+
+ 
+// collision stuff
+void ChAssembly::SetCollide (bool mcoll)
+{
+	if (mcoll == do_collide) 
+		return;
+
+	if (mcoll)
+	{
+		SyncCollisionModels();
+		this->do_collide=true;
+		if (GetSystem())
+		{
+			AddCollisionModelsToSystem();
+		}
+	}
+	else 
+	{
+		this->do_collide = false;
+		if (GetSystem())
+		{
+			RemoveCollisionModelsFromSystem();
+		}
+	}
+}
+
+void ChAssembly::SyncCollisionModels()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->GetCollisionModel()->SyncPosition();
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::AddCollisionModelsToSystem() 
+{
+	assert(this->GetSystem());
+	SyncCollisionModels();
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		if (Bpointer->GetCollide())
+			this->GetSystem()->GetCollisionSystem()->Add(Bpointer->GetCollisionModel());
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::RemoveCollisionModelsFromSystem() 
+{
+	assert(this->GetSystem());
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		if (Bpointer->GetCollide())
+			this->GetSystem()->GetCollisionSystem()->Remove(Bpointer->GetCollisionModel());
+		HIER_BODY_NEXT
+	}
+}
+
+
+
+void ChAssembly::GetTotalAABB(ChVector<>& bbmin, ChVector<>& bbmax)
+{
+	//default infinite bb
+	ChVector<> mmin(-1e200, -1e200, -1e200);
+	ChVector<> mmax( 1e200,  1e200,  1e200);
+
+	bool set = false;
+	ChVector<> tmpMin;
+	ChVector<> tmpMax;
+
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		if (Bpointer->GetCollisionModel())
+		{
+			Bpointer->GetCollisionModel()->GetAABB(tmpMin, tmpMax);
+			if (!set)
+			{
+				mmin=tmpMin;
+				mmax=tmpMax;
+				set=true;
+			}
+			if (tmpMin.x<mmin.x)
+				mmin.x=tmpMin.x;
+			if (tmpMin.y<mmin.y)
+				mmin.y=tmpMin.y;
+			if (tmpMin.z<mmin.z)
+				mmin.z=tmpMin.z;
+			if (tmpMax.x>mmax.x)
+				mmax.x=tmpMax.x;
+			if (tmpMax.y>mmax.y)
+				mmax.y=tmpMax.y;
+			if (tmpMax.z>mmax.z)
+				mmax.z=tmpMax.z;
+		}
+		HIER_BODY_NEXT
+	}
+	bbmin.Set(mmin.x, mmin.y, mmin.z);
+	bbmax.Set(mmax.x, mmax.y, mmax.z);
+}
+
+void ChAssembly::Reference_LM_byID()
+{
+	ChMarker* m1;
+	ChMarker* m2;
+
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		if (ChLinkMarkers* malink = ChDynamicCast(ChLinkMarkers,Lpointer))
+		{
+			m1 = SearchMarker(malink->GetMarkID1());
+			m2 = SearchMarker(malink->GetMarkID2());
+			malink->SetMarker1(m1);
+			malink->SetMarker2(m2);
+			if (m1 && m2)
+			{
+				Lpointer->SetValid(true);
+				HIER_LINK_NEXT
+			}
+			else
+			{
+				Lpointer->SetValid(false);
+				malink->SetMarkers(0,0); // however marker IDs will survive!!
+				iterlink = RemoveLinkIter(iterlink); // may delete it...
+			}
+		}
+		else
+		{
+			HIER_LINK_NEXT
+		}
+	}
+}
+
+ChMarker* ChAssembly::SearchMarker (int markID)
+{
+	ChMarker* candidate = NULL;
+	ChMarker* res = NULL;
+
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		res = ChContainerSearchFromID<ChMarker, std::vector<ChMarker*>::iterator>
+				(markID, 
+				Bpointer->GetMarkerList()->begin(), 
+				Bpointer->GetMarkerList()->end());
+		if (res != NULL) return res;
+
+		HIER_BODY_NEXT
+	}
+
+	return 0;
+}
+
+//////// FILE I/O
+
+void ChAssembly::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << do_collide;
+	mstream << do_limit_speed;
+	
+	mstream << max_speed;
+	mstream << max_wvel;
+
+	// 2a) write how many bodies
+	mstream << (int)bodylist.size();
+
+	// 2b) write  bodies
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+			// write the body
+		//Bpointer->StreamOUT(mstream);
+		mstream.AbstractWriteAll(Bpointer);
+		//mstream.AbstractWrite(Bpointer);
+		HIER_BODY_NEXT
+	}
+
+	// 3a) write how many links
+	mstream << (int)linklist.size();
+
+	// 3b) write links links
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+			// Writethe link, using a special downcasting function Link_BinSave which saves also the
+			// inheritance info, depending on link class inheritance from base Link*
+		mstream.AbstractWrite(Lpointer);
+
+		HIER_LINK_NEXT
+	}
+}
+
+void ChAssembly::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(mstream);
+
+	mstream >> do_collide;
+	mstream >> do_limit_speed;
+	
+	mstream >> max_speed;
+	mstream >> max_wvel;
+
+	// 2a) read how many bodies
+	int mnbodies = 0;
+	mstream >> mnbodies;
+
+	// 2b) read  bodies
+	ChBody* newbody= NULL;
+	for (int i= 0; i<mnbodies; i++)
+	{
+		//mstream.AbstractReadCreate(&newbody);
+		mstream.AbstractReadAllCreate(&newbody);
+		ChSharedPtr<ChBody> shitem(newbody);
+		this->AddBody(shitem);
+		/*
+		ChSharedPtr<ChBody> newbody(new ChBody);
+		this->AddBody(newbody);
+
+		newbody->StreamIN(mstream);
+		*/
+	}
+
+	// 3a) read how many links
+	int mnlinks = 0;
+	mstream >> mnlinks;
+
+	// 3b) read  links
+	ChLink* newlink= NULL;
+	for (int j= 0; j<mnlinks; j++)
+	{
+			// read the link, using a special downcasting function Link_BinRead_Create which creates the
+			// proper inherited object, depending on its class inheritance from base Link*
+
+		mstream.AbstractReadCreate(&newlink);
+
+		ChSharedPtr<ChLink> shlink(newlink);
+		this->AddLink(shlink);
+	}
+
+	// 3c) Rebuild link pointers to markers
+	this->Reference_LM_byID();
+}
+
+
+
+
+void ChAssembly::StreamOUTstate(ChStreamOutBinary& mstream)
+{
+	// Do not serialize parent classes and do not
+	// implement versioning, because this must be efficient 
+	// and will be used just for domain decomposition.
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+			// write the body + child markers + forces
+		Bpointer->StreamOUTstate(mstream);
+		HIER_BODY_NEXT
+	}
+}
+
+void ChAssembly::StreamINstate(ChStreamInBinary& mstream)
+{
+	// Do not serialize parent classes and do not
+	// implement versioning, because this must be efficient 
+	// and will be used just for domain decomposition.
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+			// write the body + child markers + forces
+		Bpointer->StreamINstate(mstream);
+		HIER_BODY_NEXT
+	}
+}
+
+
+#define CH_CHUNK_END_ASSEM 18881
+
+int ChAssembly::StreamINall  (ChStreamInBinary& m_file)
+{
+	int mchunk = 0;
+	ChBody* newbody= NULL;
+	ChLink* newlink= NULL;
+
+	// class version number
+	int version = m_file.VersionRead();
+
+	// 0) reset system to have no sub object child
+	this->Clear();
+
+	// 1) read system class data...
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(m_file);
+
+	m_file >> do_collide;
+	m_file >> do_limit_speed;
+
+	m_file >> max_speed;
+	m_file >> max_wvel;
+
+	// 2a) read how many bodies
+	int mnbodies = 0;
+	m_file >> mnbodies;
+
+	// 2b) read  bodies
+	for (int i= 0; i<mnbodies; i++)
+	{
+		ChSharedPtr<ChBody> newbody(new ChBody);
+		this->AddBody(newbody);
+
+		if (!newbody->StreamINall(m_file)) 
+			throw ChException("Cannot read body data");
+	}
+
+	// 3a) read how many links
+	int mnlinks = 0;
+	m_file >> mnlinks;
+
+	// 3b) read  links
+	for (int j= 0; j<mnlinks; j++)
+	{
+			// read the link, using a special downcasting function Link_BinRead_Create which creates the
+			// proper inherited object, depending on its class inheritance from base Link*
+
+		m_file.AbstractReadCreate(&newlink);
+		if (!newlink) throw ChException("Cannot read link data");
+
+		ChSharedPtr<ChLink> shlink(newlink);
+		this->AddLink(shlink);
+	}
+
+	// 3c) Rebuild link pointers to markers
+	this->Reference_LM_byID();
+
+	m_file >> mchunk;
+
+	if (mchunk != CH_CHUNK_END_ASSEM) return 0;
+
+	return 1;
+}
+
+
+int ChAssembly::StreamOUTall  (ChStreamOutBinary& m_file)
+{
+	// class version number
+	m_file.VersionWrite(1);
+
+	// 1) write system class data...
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(m_file);
+
+		// stream out all member data
+	m_file << do_collide;
+	m_file << do_limit_speed;
+
+	m_file << max_speed;
+	m_file << max_wvel;
+
+	// 2a) write how many bodies
+	m_file << (int)bodylist.size();
+
+	// 2b) write  bodies
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+			// write the body + child markers + forces
+		if (!Bpointer->StreamOUTall(m_file)) return 0;
+		HIER_BODY_NEXT
+	}
+
+	// 3a) write how many links
+	m_file << (int)linklist.size(); 
+
+	// 3b) write links links
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+			// Writethe link, using a special downcasting function Link_BinSave which saves also the
+			// inheritance info, depending on link class inheritance from base Link*
+		m_file.AbstractWrite(Lpointer);
+
+		HIER_LINK_NEXT
+	}
+
+	m_file << (int)CH_CHUNK_END_ASSEM;
+
+	return 1;
+}
+
+void ChAssembly::StreamOUT(ChStreamOutAscii& mstream)
+{
+	//***TO DO***
+}
+
+
+int ChAssembly::StreamOUTall  (ChStreamOutAscii& mstream) // dump rigidbody and childrens (markers.forces)
+{
+	//***TO DO***
+
+	StreamOUT (mstream);			 // 1) dump the body attrs
+
+	return 1;
+}
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChAssembly.h b/SRC/ChronoEngine/physics/ChAssembly.h
new file mode 100644
index 0000000..8eb45e5
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChAssembly.h
@@ -0,0 +1,383 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHASSEMBLY_H
+#define CHASSEMBLY_H
+
+//////////////////////////////////////////////////
+//
+//   ChAssembly.h
+//
+//   Class for a sub-assembly of rigid bodies (with constraints).
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "core/ChShared.h"
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChForce.h"
+#include "physics/ChMarker.h"
+#include "physics/ChLinksAll.h"
+#include "lcp/ChLcpVariablesBodyOwnMass.h"
+#include "lcp/ChLcpConstraint.h"
+
+
+
+namespace chrono
+{
+
+using namespace collision;
+
+
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+///
+/// Class for a collection of rigid bodies with some constraints, that should always be cosidered together.
+/// A rigid body is an entity which can move in 3D space, and the constraints are ChLink objects.
+/// The objects have mass and inertia properties. A shape can also
+/// be associated to the bodies, for collision detection.
+///
+
+class ChApi ChAssembly : public ChPhysicsItem {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChAssembly,ChPhysicsItem);
+
+protected:
+	
+
+						// list of joints (links)
+	std::list<ChLink*>   linklist; 
+
+						// list of rigid bodies
+	std::vector<ChBody*> bodylist;
+
+private:
+			//
+	  		// DATA
+			//
+
+	bool do_collide;
+	bool do_limit_speed;
+
+	float max_speed;	// limit on linear speed (useful for VR & videagames)
+	float max_wvel;		// limit on angular vel. (useful for VR & videagames)
+
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build an assembly.
+	ChAssembly ();
+				/// Destructor
+	~ChAssembly ();
+
+				/// Copy from another ChAssembly. 
+				/// NOTE: all settings of the body are copied, but the
+				/// child hierarchy of ChForces and ChMarkers (if any) are NOT copied.
+	void Copy(ChAssembly* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+
+				/// Enable/disable the collision for this cluster of particles.
+				/// After setting ON, remember RecomputeCollisionModel()
+				/// before anim starts (it is not automatically
+				/// recomputed here because of performance issues.)
+	void  SetCollide (bool mcoll);
+	bool  GetCollide() {return do_collide;}
+
+				/// Trick. Set the maximum linear speed (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations, because it reduces the risk of bad collision detection.
+				/// The realism is limited, but the simulation is more stable.
+	void SetLimitSpeed    (bool mlimit) { do_limit_speed = mlimit;};
+	bool GetLimitSpeed()  {return do_limit_speed;};
+		
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Set the pointer to the parent ChSystem()
+	void SetSystem (ChSystem* m_system);
+
+
+				/// Removes all bodies/marker/forces/links/contacts,
+				/// also resets timers and events.
+	void Clear();
+
+
+				/// Searches a marker from its unique ID -OBSOLETE
+	ChMarker* SearchMarker(int markID);
+
+				/// Given inserted markers and links, restores the
+				/// pointers of links to markers given the information
+				/// about the marker IDs.
+	void Reference_LM_byID();
+
+				/// Number of coordinates of the rigid body =6 (internally, 3+4=7 coords are used 
+				/// since quaternions are used for large rotations, but local coords -ex. w&v velocity- are 6)
+	virtual int GetDOF  ();
+				/// Get the number of scalar constraints, if any, in this item 
+	virtual int GetDOC  ()   {return GetDOC_c()+GetDOC_d();}
+				/// Get the number of scalar constraints, if any, in this item (only bilateral constr.)
+	virtual int GetDOC_c  ();
+				/// Get the number of scalar constraints, if any, in this item (only unilateral constr.)
+	virtual int GetDOC_d  ();
+
+
+			 // Override/implement LCP system functions of ChPhysicsItem
+			 // (to assembly/manage data for LCP system solver)
+
+				/// Sets the 'fb' part of the encapsulated ChLcpVariablesBodyOwnMass to zero.
+	virtual void VariablesFbReset();
+
+				/// Adds the current forces applied to body (including gyroscopic torque) in
+				/// encapsulated ChLcpVariablesBody, in the 'fb' part: qf+=forces*factor
+	virtual void VariablesFbLoadForces(double factor=1.);
+
+				/// Initialize the 'qb' part of the ChLcpVariablesBody with the 
+				/// current value of body speeds. Note: since 'qb' is the unknown of the LCP, this
+				/// function seems unuseful, unless used before VariablesFbIncrementMq()
+	virtual void VariablesQbLoadSpeed();
+
+				/// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
+				/// with v_old using VariablesQbLoadSpeed, this method can be used in 
+				/// timestepping schemes that do: M*v_new = M*v_old + forces*dt
+	virtual void VariablesFbIncrementMq();
+
+				/// Fetches the body speed (both linear and angular) from the
+				/// 'qb' part of the ChLcpVariablesBody (does not updates the full body&markers state)
+				/// and sets it as the current body speed.
+				/// If 'step' is not 0, also computes the approximate acceleration of
+				/// the body using backward differences, that is  accel=(new_speed-old_speed)/step.
+				/// Mostly used after the LCP provided the solution in ChLcpVariablesBody .
+	virtual void VariablesQbSetSpeed(double step=0.);
+
+				/// Increment body position by the 'qb' part of the ChLcpVariablesBody,
+				/// multiplied by a 'step' factor.
+				///     pos+=qb*step
+				/// If qb is a speed, this behaves like a single step of 1-st order
+				/// numerical integration (Eulero integration).
+				/// Does not automatically update markers & forces.
+	virtual void VariablesQbIncrementPosition(double step);
+
+
+				/// Tell to a system descriptor that there are variables of type
+				/// ChLcpVariables in this object (for further passing it to a LCP solver)
+	virtual void InjectVariables(ChLcpSystemDescriptor& mdescriptor);
+
+				/// Tell to a system descriptor that there are contraints of type
+				/// ChLcpConstraint in this object (for further passing it to a LCP solver)
+				/// Basically does nothing, but maybe that inherited classes may specialize this.
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+
+				/// Sets to zero the known term (b_i) of encapsulated ChLcpConstraints
+	virtual void ConstraintsBiReset();
+
+				/// Adds the current C (constraint violation) to the known term (b_i) of
+				/// encapsulated ChLcpConstraints
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+
+				/// Adds the current Ct (partial t-derivative, as in C_dt=0-> [Cq]*q_dt=-Ct)
+				/// to the known term (b_i) of encapsulated ChLcpConstraints
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+
+				/// Adds the current Qc (the vector of C_dtdt=0 -> [Cq]*q_dtdt=Qc )
+				/// to the known term (b_i) of encapsulated ChLcpConstraints
+	virtual void ConstraintsBiLoad_Qc(double factor=1.);
+
+				/// Adds the current link-forces, if any, (caused by springs, etc.) to the 'fb' vectors
+				/// of the ChLcpVariables referenced by encapsulated ChLcpConstraints
+	virtual void ConstraintsFbLoadForces(double factor=1.);
+
+				/// Adds the current jacobians in encapsulated ChLcpConstraints
+	virtual void ConstraintsLoadJacobians();
+
+				/// Fills the solution of the constraint (the lagrangian multiplier l_i)
+				/// with an initial guess, if any. This can be used for warm-starting the 
+				/// LCP solver before starting the solution of the SPEED problem, if some 
+				/// approximate solution of constraint impulese l_i already exist (ex. cached
+				/// from a previous LCP execution)
+				/// When implementing this in sub classes, if no guess is available, set l_i as 0.
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+
+				/// As ConstraintsLiLoadSuggestedSpeedSolution(), but for the POSITION problem.
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+
+				/// After the LCP solver has found the l_i lagangian multipliers for the
+				/// SPEED problem, this function will be called to store the solutions in a
+				/// cache (to be implemented in ChLink sub classes) so that it can be later retrieved with
+				/// ConstraintsLiLoadSuggestedSpeedSolution(). If you do not plan to implement a l_i cache,
+				/// just do not override this function in child classes and do nothing.
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+
+				/// As ConstraintsLiFetchSuggestedSpeedSolution(), but for the POSITION problem.
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+
+				/// Fetches the reactions from the lagrangian multiplier (l_i)
+				/// of encapsulated ChLcpConstraints. 
+				/// Mostly used after the LCP provided the solution in ChLcpConstraints.
+				/// Also, should convert the reactions obtained from dynamical simulation,
+				/// from link space to intuitive react_force and react_torque.
+	virtual void ConstraintsFetch_react(double factor=1.);
+				
+
+			   // Other functions
+
+				/// Set no speed and no accelerations (but does not change the position)
+	void SetNoSpeedNoAcceleration();
+
+
+				/// Synchronize coll.model coordinate and bounding box to the position of the body.
+	virtual void SyncCollisionModels();
+	virtual void AddCollisionModelsToSystem();
+	virtual void RemoveCollisionModelsFromSystem();
+
+
+				/// Get the entire AABB axis-aligned bounding box of the object,
+				/// as defined by the collision model (if any).
+	virtual void GetTotalAABB(ChVector<>& bbmin, ChVector<>& bbmax);
+
+				/// Trick. Set the maximum linear speed (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations, because it reduces the risk of bad collision detection.
+				/// This speed limit is active only if you set  SetLimitSpeed(true);
+	void   SetMaxSpeed(float m_max_speed) {max_speed = m_max_speed;}
+	float  GetMaxSpeed () {return max_speed;}
+
+				/// Trick. Set the maximum angualar speed (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations, because it reduces the risk of bad collision detection.
+				/// This speed limit is active only if you set  SetLimitSpeed(true);
+	void   SetMaxWvel(float m_max_wvel) {max_wvel = m_max_wvel;}
+	float  GetMaxWvel () {return max_wvel;}
+
+				/// When this function is called, the speed of particles is clamped
+				/// into limits posed by max_speed and max_wvel  - but remember to
+				/// put the body in the SetLimitSpeed(true) mode.
+	void ClampSpeed();
+
+
+			//
+			// DATABASE HANDLING.
+			//
+			// To attach/remove items (rigid bodies, links, etc.) you must use 
+			// shared pointer, so that you don't need to care about item deletion, 
+			// which will be automatic when needed.
+			// Please don't add the same item multiple times; also, don't remove
+			// items which haven't ever been added.
+			// NOTE! After adding/removing items to the system, you should call Update() !
+
+				/// Get the number of particles
+	unsigned int GetNbodies() {return bodylist.size();}
+
+				/// Attach a body to this system. Must be an object of exactly ChBody class.
+	void AddBody (ChSharedPtr<ChBody> newbody);
+				/// Attach a link to this system. Must be an object of ChLink or derived classes.
+	void AddLink (ChSharedPtr<ChLink> newlink);
+	void AddLink (ChLink* newlink);  // _internal use
+
+				/// Remove a body from this system.
+	void RemoveBody (ChSharedPtr<ChBody> mbody); 
+				/// Remove a link from this system (faster version, mostly internal use)
+	std::list<ChLink*>::iterator RemoveLinkIter(std::list<ChLink*>::iterator& mlinkiter); 
+				/// Remove a link from this system.
+	void RemoveLink (ChSharedPtr<ChLink> mlink); 
+
+				/// Remove all bodies from this system.
+	void RemoveAllBodies();
+				/// Remove all links from this system.
+	void RemoveAllLinks();
+
+				/// Gets the list of children bodies -low level function-.
+				/// NOTE! use this list only to enumerate etc., but NOT to
+				/// remove or add items (use the appropriate Remove.. and Add..
+				/// functions instead!)
+	std::vector<ChBody*>* Get_bodylist() {return &bodylist;}
+				/// Gets the list of children links -low level function-.
+				/// NOTE! use this list only to enumerate etc., but NOT to
+				/// remove or add items (use the appropriate Remove.. and Add..
+				/// functions instead!)
+	std::list<ChLink*>* Get_linklist() {return &linklist;}
+
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the rigid body and of
+				/// its children (markers, forces..), at given time
+	virtual void Update (double mytime);
+				/// Update all auxiliary data of the rigid body and of
+				/// its children (markers, forces..)
+	virtual void Update ();
+
+
+			//
+			// STREAMING
+			//
+				
+				/// Method to deserialize only the state (position, speed)
+	virtual void StreamINstate(ChStreamInBinary& mstream);
+				/// Method to serialize only the state (position, speed)
+	virtual void StreamOUTstate(ChStreamOutBinary& mstream);	
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+				/// Save data, including child markers and child forces
+	int StreamOUTall (ChStreamOutBinary& m_file);
+				/// Read data, including child markers and child forces
+	int StreamINall  (ChStreamInBinary&  m_file);
+
+
+				/// Method to allow serialization of transient data in ascii,
+				/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream);
+
+	int  StreamOUTall  (ChStreamOutAscii& mstream);
+};
+
+
+
+typedef ChSharedPtr<ChAssembly> ChAssemblyPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChBody.cpp b/SRC/ChronoEngine/physics/ChBody.cpp
new file mode 100644
index 0000000..86400be
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChBody.cpp
@@ -0,0 +1,1200 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChBody.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "core/ChTrasform.h"
+#include "physics/ChBody.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChMarker.h"
+#include "physics/ChForce.h"
+#include "physics/ChSystem.h"
+
+#include "physics/ChExternalObject.h"
+#include "collision/ChCModelBulletBody.h"
+#include "core/ChLinearAlgebra.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChBody> a_registration_ChBody;
+
+
+// Hierarchy-handling shortcuts
+ 
+#define MARKpointer         (*imarker)
+#define HIER_MARKER_INIT    std::vector<ChMarker*>::iterator imarker = marklist.begin();
+#define HIER_MARKER_NOSTOP  (imarker != marklist.end())
+#define HIER_MARKER_NEXT    imarker++;
+
+#define FORCEpointer        (*iforce)
+#define HIER_FORCE_INIT     std::vector<ChForce*>::iterator iforce = forcelist.begin();
+#define HIER_FORCE_NOSTOP   (iforce != forcelist.end())
+#define HIER_FORCE_NEXT     iforce++;   
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SOLID BODIES
+
+
+ChBody::ChBody ()
+{
+    marklist.clear();
+    forcelist.clear();
+
+    BFlagsSetAllOFF();      // no flags
+
+    Xforce = VNULL;
+    Xtorque = VNULL;
+
+    Force_acc = VNULL;
+    Torque_acc = VNULL;
+    Scr_force = VNULL;
+    Scr_torque = VNULL;
+    cdim = VNULL;
+
+    collision_model=InstanceCollisionModel();
+
+    matsurface = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
+
+    density = 1000.0f;
+    conductivity = 0.2f;
+
+    last_coll_pos = CSYSNORM;
+
+    SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+    max_speed = 0.5f;
+    max_wvel  = 2.0f*float(CH_C_PI);
+
+    sleep_time = 0.6f;
+    sleep_starttime = 0;
+    sleep_minspeed = 0.1f;
+    sleep_minwvel = 0.04f;
+    SetUseSleeping(true); 
+
+    variables.SetUserData((void*)this);
+
+    body_id = 0;
+}
+
+ChBody::ChBody (ChCollisionModel* new_collision_model)
+{
+    marklist.clear();
+    forcelist.clear();
+
+    BFlagsSetAllOFF();      // no flags
+
+    Xforce = VNULL;
+    Xtorque = VNULL;
+
+    Force_acc = VNULL;
+    Torque_acc = VNULL;
+    Scr_force = VNULL;
+    Scr_torque = VNULL;
+    cdim = VNULL;
+
+    collision_model=new_collision_model;
+    collision_model->SetBody(this);
+
+    matsurface = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
+
+    density = 1000.0f;
+    conductivity = 0.2f;
+
+    last_coll_pos = CSYSNORM;
+
+    SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+    max_speed = 0.5f;
+    max_wvel  = 2.0f*float(CH_C_PI);
+
+    sleep_time = 0.6f;
+    sleep_starttime = 0;
+    sleep_minspeed = 0.1f;
+    sleep_minwvel = 0.04f;
+    SetUseSleeping(true);
+
+    variables.SetUserData((void*)this);
+
+    body_id = 0;
+}
+
+ChBody::~ChBody ()
+{
+    RemoveAllForces(); 
+    RemoveAllMarkers();
+
+    if (collision_model) delete collision_model;
+}
+
+void ChBody::Copy(ChBody* source)
+{
+        // copy the parent class data...
+    ChPhysicsItem::Copy(source);
+
+        // copy the parent class data...
+    ChFrameMoving<double>::operator=(*source);
+
+
+    bflag       = source->bflag;
+
+    variables = source->variables;
+    variables.SetUserData((void*)this);
+
+    gyro    = source->Get_gyro();
+
+    RemoveAllForces();  // also copy-duplicate the forces? Let the user handle this..
+    RemoveAllMarkers();  // also copy-duplicate the markers? Let the user handle this..
+
+    ChTime = source->ChTime;
+
+    collision_model->ClearModel(); // also copy-duplicate the collision model? Let the user handle this..
+
+    this->matsurface = source->matsurface;  // also copy-duplicate the material? Let the user handle this..
+
+    density = source->density;
+    conductivity = source->conductivity;
+
+    Scr_force = source->Scr_force;
+    Scr_torque = source->Scr_torque;
+    cdim = source->cdim;
+
+    last_coll_pos = source->last_coll_pos;
+
+    max_speed = source->max_speed;
+    max_wvel  = source->max_wvel;
+
+    sleep_time = source->sleep_time;
+    sleep_starttime = source->sleep_starttime;
+    sleep_minspeed = source->sleep_minspeed;
+    sleep_minwvel = source->sleep_minwvel;
+}
+
+
+ChCollisionModel* ChBody::InstanceCollisionModel(){
+    ChCollisionModel* collision_model_t= (ChModelBulletBody*) new ChModelBulletBody();
+    ((ChModelBulletBody*)collision_model_t)->SetBody(this);
+    return collision_model_t;
+}
+
+
+//// 
+void ChBody::InjectVariables(ChLcpSystemDescriptor& mdescriptor)
+{   
+    this->variables.SetDisabled(!this->IsActive());
+
+    mdescriptor.InsertVariables(&this->variables);
+}
+
+
+void ChBody::VariablesFbReset()
+{
+    this->variables.Get_fb().FillElem(0.0);
+}
+
+void ChBody::VariablesFbLoadForces(double factor)
+{
+    // add applied forces to 'fb' vector
+    this->variables.Get_fb().PasteSumVector( Xforce * factor ,0,0);
+
+    // add applied torques to 'fb' vector, including gyroscopic torque
+    if (this->GetNoGyroTorque())
+        this->variables.Get_fb().PasteSumVector((Xtorque)* factor ,3,0);
+    else
+        this->variables.Get_fb().PasteSumVector((Xtorque - gyro)* factor ,3,0);
+}
+
+
+void ChBody::VariablesFbIncrementMq()
+{
+	this->variables.Compute_inc_Mb_v(this->variables.Get_fb(), this->variables.Get_qb());
+}
+
+
+void ChBody::VariablesQbLoadSpeed()
+{
+    // set current speed in 'qb', it can be used by the LCP solver when working in incremental mode
+    this->variables.Get_qb().PasteVector(GetCoord_dt().pos,0,0);
+    this->variables.Get_qb().PasteVector(GetWvel_loc()    ,3,0);
+}
+
+
+void ChBody::VariablesQbSetSpeed(double step)
+{
+    ChCoordsys<> old_coord_dt = this->GetCoord_dt();
+
+    // from 'qb' vector, sets body speed, and updates auxiliary data
+    this->SetPos_dt(   this->variables.Get_qb().ClipVector(0,0) );
+    this->SetWvel_loc( this->variables.Get_qb().ClipVector(3,0) );
+
+    // apply limits (if in speed clamping mode) to speeds.
+    ClampSpeed(); 
+
+    // compute auxiliary gyroscopic forces
+    ComputeGyro ();
+
+    // Compute accel. by BDF (approximate by differentiation);
+    if (step)
+    {
+        this->SetPos_dtdt( (this->GetCoord_dt().pos - old_coord_dt.pos)  / step);
+        this->SetRot_dtdt( (this->GetCoord_dt().rot - old_coord_dt.rot)  / step);
+    }
+}
+
+void ChBody::VariablesQbIncrementPosition(double dt_step)
+{
+    if (!this->IsActive()) 
+        return;
+
+    // Updates position with incremental action of speed contained in the
+    // 'qb' vector:  pos' = pos + dt * speed   , like in an Eulero step.
+
+    ChVector<> newspeed = variables.Get_qb().ClipVector(0,0);
+    ChVector<> newwel   = variables.Get_qb().ClipVector(3,0);
+
+    // ADVANCE POSITION: pos' = pos + dt * vel
+    this->SetPos( this->GetPos() + newspeed * dt_step);
+
+    // ADVANCE ROTATION: rot' = [dt*wwel]%rot  (use quaternion for delta rotation)
+    ChQuaternion<> mdeltarot;
+    ChQuaternion<> moldrot = this->GetRot();
+    ChVector<> newwel_abs = Amatrix * newwel;
+    double mangle = newwel_abs.Length() * dt_step;
+    newwel_abs.Normalize();
+    mdeltarot.Q_from_AngAxis(mangle, newwel_abs);
+    ChQuaternion<> mnewrot = mdeltarot % moldrot;
+    this->SetRot( mnewrot );
+}
+
+
+
+void ChBody::SetNoSpeedNoAcceleration()
+{
+    this->SetPos_dt(VNULL);
+    this->SetWvel_loc(VNULL);
+    this->SetPos_dtdt(VNULL);
+    this->SetRot_dtdt(QNULL);
+}
+
+
+////
+void ChBody::ClampSpeed()
+{
+    if (this->GetLimitSpeed())
+    {
+        double w = 2.0*this->coord_dt.rot.Length();
+        if (w > max_wvel)
+            coord_dt.rot *= max_wvel/w;
+
+        double v = this->coord_dt.pos.Length();
+        if (v > max_speed)
+            coord_dt.pos *= max_speed/v;
+    }
+}
+
+
+//// Utilities for coordinate transformations
+///
+Vector ChBody::Point_World2Body (Vector* mpoint)
+{
+    return ChFrame<double>::TrasformParentToLocal(*mpoint);
+}
+
+Vector ChBody::Point_Body2World (Vector* mpoint)
+{
+    return ChFrame<double>::TrasformLocalToParent(*mpoint);
+}
+
+Vector ChBody::Dir_World2Body (Vector* mpoint)
+{
+    return Amatrix.MatrT_x_Vect (*mpoint);
+}
+
+Vector ChBody::Dir_Body2World (Vector* mpoint)
+{
+    return Amatrix.Matr_x_Vect (*mpoint);
+}
+
+Vector ChBody::RelPoint_AbsSpeed(Vector* mrelpoint)
+{
+    return PointSpeedLocalToParent(*mrelpoint);
+}
+
+Vector ChBody::RelPoint_AbsAcc(Vector* mrelpoint)
+{
+    return PointAccelerationLocalToParent(*mrelpoint);
+}
+
+////
+// The inertia tensor functions
+
+void ChBody::SetInertia (ChMatrix33<>* newXInertia)
+{
+    variables.SetBodyInertia(newXInertia);
+}
+
+void ChBody::SetInertiaXX (Vector iner)
+{
+    variables.GetBodyInertia().SetElement(0,0,iner.x);
+    variables.GetBodyInertia().SetElement(1,1,iner.y);
+    variables.GetBodyInertia().SetElement(2,2,iner.z);
+    variables.GetBodyInertia().FastInvert(&variables.GetBodyInvInertia());
+}
+void ChBody::SetInertiaXY (Vector iner)
+{
+    variables.GetBodyInertia().SetElement(0,1,iner.x);
+    variables.GetBodyInertia().SetElement(0,2,iner.y);
+    variables.GetBodyInertia().SetElement(1,2,iner.z);
+    variables.GetBodyInertia().SetElement(1,0,iner.x);
+    variables.GetBodyInertia().SetElement(2,0,iner.y);
+    variables.GetBodyInertia().SetElement(2,1,iner.z);
+    variables.GetBodyInertia().FastInvert(&variables.GetBodyInvInertia());
+}
+
+Vector ChBody::GetInertiaXX()
+{
+    ChVector<> iner;
+    iner.x= variables.GetBodyInertia().GetElement(0,0);
+    iner.y= variables.GetBodyInertia().GetElement(1,1);
+    iner.z= variables.GetBodyInertia().GetElement(2,2);
+    return iner;
+}
+
+Vector ChBody::GetInertiaXY()
+{
+    ChVector<> iner;
+    iner.x= variables.GetBodyInertia().GetElement(0,1);
+    iner.y= variables.GetBodyInertia().GetElement(0,2);
+    iner.z= variables.GetBodyInertia().GetElement(1,2);
+    return iner;
+}
+
+void ChBody::ComputeQInertia (ChMatrixNM<double,4,4>* mQInertia)
+{
+    ChMatrixNM<double,3,4> res ;
+    ChMatrixNM<double,3,4> Gl  ;
+    ChMatrixNM<double,4,3> GlT ;
+
+    SetMatrix_Gl(Gl, coord.rot);
+    GlT.CopyFromMatrixT(Gl);
+
+    res.MatrMultiply (*this->GetXInertia(), Gl);
+    mQInertia->MatrMultiply (GlT, res); // [Iq]=[G'][Ix][G]
+}
+
+//////
+
+
+void ChBody::To_abs_forcetorque  (Vector force, Vector appl_point, int local, Vector& resultforce, Vector& resulttorque)
+{
+    if (local)
+    {
+        // local space
+        ChVector<> mforce_abs = Dir_Body2World(&force);
+        resultforce = mforce_abs;
+        resulttorque = Vcross (Dir_Body2World(&appl_point), mforce_abs) ;
+    }
+    else
+    {
+        // absolute space
+        resultforce = force;
+        resulttorque = Vcross (Vsub(appl_point, coord.pos), force) ;
+    }
+}
+void ChBody::To_abs_torque (Vector torque, int local, Vector& resulttorque)
+{
+    if (local)
+    {
+        // local space
+        resulttorque = Dir_Body2World(&torque);
+    }
+    else
+    {
+        // absolute space
+        resulttorque = torque;
+    }
+}
+
+
+void ChBody::Add_as_lagrangian_force(Vector force, Vector appl_point, int local, ChMatrixNM<double,7,1>* mQf)
+{
+    ChVector<> mabsforce;
+    ChVector<> mabstorque;
+    To_abs_forcetorque (force, appl_point, local, mabsforce, mabstorque);
+    mQf->PasteSumVector(mabsforce,0,0);
+    mQf->PasteSumQuaternion( ChFrame<>::GlT_x_Vect(coord.rot, Dir_World2Body(&mabstorque)) , 3,0);
+}
+
+void ChBody::Add_as_lagrangian_torque(Vector torque, int local, ChMatrixNM<double,7,1>* mQf)
+{
+    ChVector<> mabstorque;
+    To_abs_torque (torque, local, mabstorque);
+    mQf->PasteSumQuaternion( ChFrame<>::GlT_x_Vect(coord.rot, Dir_World2Body(&mabstorque)), 3,0);
+}
+
+void ChBody::From_lagrangian_to_forcetorque(ChMatrixNM<double,7,1>* mQf, Vector* mforce, Vector* mtorque)
+{
+    *mforce = mQf->ClipVector(0,0);
+    ChQuaternion<> tempq;
+    tempq = mQf->ClipQuaternion(3,0);
+    *mtorque = ChFrame<>::Gl_x_Quat(coord.rot, tempq);
+    *mtorque = Vmul (*mtorque, 0.25);
+}
+
+void ChBody::From_forcetorque_to_lagrangian(Vector* mforce, Vector* mtorque, ChMatrixNM<double,7,1>* mQf)
+{
+    mQf->PasteVector(*mforce, 0,0);
+    ChQuaternion<> tempq;
+    tempq = ChFrame<>::GlT_x_Vect(coord.rot, *mtorque);
+    mQf->PasteQuaternion(tempq,3,0);
+}
+
+//////
+
+void ChBody::Accumulate_force  (Vector force, Vector appl_point, int local)
+{
+    ChVector<> mabsforce;
+    ChVector<> mabstorque;
+    To_abs_forcetorque (force, appl_point, local, mabsforce, mabstorque);
+
+    Force_acc = Vadd (Force_acc, mabsforce);
+    Torque_acc = Vadd (Torque_acc, mabstorque);
+}
+
+void ChBody::Accumulate_torque (Vector torque, int local)
+{
+    ChVector<> mabstorque;
+    To_abs_torque (torque, local, mabstorque);
+    Torque_acc = Vadd (Torque_acc, mabstorque);
+}
+
+void ChBody::Accumulate_script_force  (Vector force, Vector appl_point, int local)
+{
+    ChVector<> mabsforce;
+    ChVector<> mabstorque;
+    To_abs_forcetorque (force, appl_point, local, mabsforce, mabstorque);
+
+    Scr_force = Vadd (Scr_force, mabsforce);
+    Scr_torque = Vadd (Scr_torque, mabstorque);
+}
+/*
+void ChBody::SetCdim (Vector mcdim)
+{
+    ChVector<> cdim;
+
+    cdim = mcdim;
+}
+*/
+void ChBody::Accumulate_script_torque (Vector torque, int local)
+{
+    ChVector<> mabstorque;
+    To_abs_torque (torque, local, mabstorque);
+    Scr_torque = Vadd (Scr_torque, mabstorque);
+}
+
+
+////////
+
+
+void ChBody::ComputeGyro ()
+{
+    ChVector<> Wvel = this->GetWvel_loc();
+    gyro = Vcross ( Wvel, (variables.GetBodyInertia().Matr_x_Vect (Wvel))); 
+}
+
+bool ChBody::TrySleeping()
+{
+    if (this->GetUseSleeping())
+    {   
+        if (this->GetSleeping()) 
+            return true;
+
+        if ( (this->coord_dt.pos.LengthInf() < this->sleep_minspeed) &&
+             ( 2.0*this->coord_dt.rot.LengthInf() < this->sleep_minwvel) )
+        {
+                if ((this->GetChTime() - this->sleep_starttime) > this->sleep_time)
+                {
+                    SetSleeping(true);
+                    return true;
+                }
+        }
+        else
+        {
+            this->sleep_starttime = float(this->GetChTime());
+        }
+    }
+    return false;
+}
+
+
+void ChBody::AddMarker (ChSharedPtr<ChMarker> amarker)
+{
+    // don't allow double insertion of same object
+    assert(std::find<std::vector<ChMarker*>::iterator>(marklist.begin(), marklist.end(), amarker.get_ptr())==marklist.end());
+
+    amarker->SetBody (this);
+    amarker->AddRef();
+    marklist.push_back((amarker).get_ptr());
+    
+}
+
+void ChBody::AddForce (ChSharedPtr<ChForce> aforce)
+{
+    // don't allow double insertion of same object
+    assert(std::find<std::vector<ChForce*>::iterator>(forcelist.begin(), forcelist.end(), aforce.get_ptr())==forcelist.end());
+
+    aforce->SetBody (this);
+    aforce->AddRef();
+    forcelist.push_back((aforce).get_ptr());
+}
+   
+
+void ChBody::RemoveForce (ChSharedPtr<ChForce> mforce)
+{
+    // trying to remove objects not previously added?
+    assert(std::find<std::vector<ChForce*>::iterator>(forcelist.begin(), forcelist.end(), mforce.get_ptr() )!=forcelist.end());
+
+    // warning! linear time search
+    forcelist.erase(std::find<std::vector<ChForce*>::iterator>(forcelist.begin(), forcelist.end(), mforce.get_ptr() ) );
+
+    mforce->SetBody(0);
+    mforce->RemoveRef();
+}
+
+void ChBody::RemoveMarker (ChSharedPtr<ChMarker> mmarker)
+{
+    // trying to remove objects not previously added?
+    assert(std::find<std::vector<ChMarker*>::iterator>(marklist.begin(), marklist.end(), mmarker.get_ptr() )!=marklist.end());
+
+    // warning! linear time search
+    marklist.erase(std::find<std::vector<ChMarker*>::iterator>(marklist.begin(), marklist.end(), mmarker.get_ptr() ) );
+
+    mmarker->SetBody(0);
+    mmarker->RemoveRef();
+}
+
+
+void ChBody::RemoveAllForces() 
+{ 
+    HIER_FORCE_INIT
+    while (HIER_FORCE_NOSTOP)
+    {
+        FORCEpointer->SetBody(0);   
+        FORCEpointer->RemoveRef();
+        HIER_FORCE_NEXT
+    }   
+    forcelist.clear();
+};
+
+void ChBody::RemoveAllMarkers() 
+{ 
+    HIER_MARKER_INIT
+    while (HIER_MARKER_NOSTOP)
+    {
+        MARKpointer->SetBody(0);       
+        MARKpointer->RemoveRef();
+        HIER_MARKER_NEXT
+    }
+
+    marklist.clear();
+};
+
+/* old
+ChMarker* ChBody::SearchMarker (char* m_name)
+{
+    return ChContainerSearchFromName<ChMarker, std::vector<ChMarker*>::iterator>
+                (m_name, 
+                marklist.begin(), 
+                marklist.end());
+}
+ChForce* ChBody::SearchForce (char* m_name)
+{
+    return ChContainerSearchFromName<ChForce, std::vector<ChForce*>::iterator>
+                (m_name, 
+                forcelist.begin(), 
+                forcelist.end());
+}
+*/
+ChSharedPtr<ChMarker> ChBody::SearchMarker (char* m_name)
+{
+    ChMarker* mmark= ChContainerSearchFromName<ChMarker, std::vector<ChMarker*>::iterator>
+                (m_name, 
+                marklist.begin(), 
+                marklist.end());
+    if (mmark)
+    {
+        mmark->AddRef(); // in that container pointers were not stored as ChSharedPtr, so this is needed..
+        return (ChSharedPtr<ChMarker>(mmark));  // ..here I am not getting a new() data, but a reference to something created elsewhere
+    }
+    return (ChSharedPtr<ChMarker>()); // not found? return a void shared ptr.
+}
+ChSharedPtr<ChForce> ChBody::SearchForce (char* m_name)
+{
+    ChForce* mforce = ChContainerSearchFromName<ChForce, std::vector<ChForce*>::iterator>
+                (m_name, 
+                forcelist.begin(), 
+                forcelist.end());
+    if (mforce)
+    {
+        mforce->AddRef(); // in that container pointers were not stored as ChSharedPtr, so this is needed..
+        return (ChSharedPtr<ChForce>(mforce));  // ..here I am not getting a new() data, but a reference to something created elsewhere
+    }
+    return (ChSharedPtr<ChForce>()); // not found? return a void shared ptr.
+}
+
+
+                    //These are the members used to UPDATE
+                    //the body coordinates during the animation
+                    //Also the coordinates of forces and markers
+                    //linked to the body will be updated.
+
+void ChBody::UpdateMarkers (double mytime)
+{
+    HIER_MARKER_INIT
+    while (HIER_MARKER_NOSTOP)
+    {
+        MARKpointer->Update (mytime);
+
+        HIER_MARKER_NEXT
+    }
+}
+
+void ChBody::UpdateForces (double mytime)
+{
+    // COMPUTE LAGRANGIAN FORCES APPLIED TO BODY
+
+    Xforce = VNULL;
+    Xtorque = VNULL;
+
+    // 1 - force caused by stabilizing damper ***OFF***
+
+    // 2a- force caused by accumulation of forces in body's accumulator Force_acc
+    if (Vnotnull(&Force_acc))
+    {
+        Xforce = Force_acc;     
+    }
+
+    // 2b- force caused by accumulation of torques in body's accumulator Force_acc
+    if (Vnotnull(&Torque_acc))
+    {
+        Xtorque = Dir_World2Body(&Torque_acc); 
+    }
+
+    // 3 - accumulation of other applied forces
+    HIER_FORCE_INIT
+    while (HIER_FORCE_NOSTOP)
+    {   
+          // update positions, f=f(t,q)
+        FORCEpointer->Update (mytime);
+
+        ChVector<> mforce; 
+        ChVector<> mtorque;
+        FORCEpointer->GetBodyForceTorque(&mforce,&mtorque);
+        Xforce  += mforce;
+        Xtorque += mtorque;
+        
+        HIER_FORCE_NEXT
+    }
+
+    // 4 - accumulation of script forces
+    if (Vnotnull(&Scr_force))
+    {
+        Xforce += Scr_force;    
+    }
+    if (Vnotnull(&Scr_torque))
+    {
+        Xtorque += Dir_World2Body(&Scr_torque);
+    }
+
+    if (GetSystem())
+    {
+        Xforce += GetSystem()->Get_G_acc() * this->GetMass();
+    }
+
+}
+
+void ChBody::UpdateTime (double mytime)
+{
+    ChTime = mytime;
+}
+
+
+void ChBody::UpdateState (Coordsys mypos, Coordsys mypos_dt)
+{
+    SetCoord (mypos);       // Set the state coordsys,
+    SetCoord_dt (mypos_dt); // automatically updating auxiliary variables
+
+    //TrySleeping();            // See if the body can fall asleep; if so, put it to sleeping
+    ClampSpeed();           // Apply limits (if in speed clamping mode) to speeds.
+    ComputeGyro ();         // Set the gyroscopic momentum.
+}
+
+
+void ChBody::UpdateStateTime (Coordsys mypos, Coordsys mypos_dt, double mytime)
+{
+    UpdateTime (mytime);
+
+    UpdateState (mypos, mypos_dt);
+}
+
+
+void ChBody::Update (Coordsys mypos, Coordsys mypos_dt, double mytime)
+{
+    UpdateTime (mytime);
+
+     mypos.rot.Normalize();
+    UpdateState (mypos, mypos_dt);
+
+    Update();
+
+}
+
+
+
+                            // UpdateALL updates the state and time
+                            // of the object AND the dependant (linked)
+                            // markers and forces.
+
+void ChBody::Update()
+{
+    //TrySleeping();            // See if the body can fall asleep; if so, put it to sleeping 
+    ClampSpeed();           // Apply limits (if in speed clamping mode) to speeds.
+    ComputeGyro ();         // Set the gyroscopic momentum.
+
+        // Also update the children "markers" and
+        // "forces" depending on the body current state.
+    UpdateMarkers(ChTime);
+
+    UpdateForces(ChTime);
+}
+
+
+
+                            // As before, but keeps the current state.
+                            // Mostly used for world reference body.
+void ChBody::Update (double mytime)
+{
+                // For the body:
+    UpdateTime (mytime);
+
+    Update();
+}
+
+
+
+void ChBody::UpdateExternalGeometry ()
+{
+    if (this->GetExternalObject())
+        this->GetExternalObject()->onChronoChanged();
+
+    HIER_MARKER_INIT
+    while (HIER_MARKER_NOSTOP)
+    {
+        MARKpointer->UpdateExternalGeometry();
+        HIER_MARKER_NEXT
+    }
+
+    HIER_FORCE_INIT
+    while (HIER_FORCE_NOSTOP)
+    {
+        FORCEpointer->UpdateExternalGeometry();
+        HIER_FORCE_NEXT
+    }
+}
+
+void ChBody::SetBodyFixed (bool mev)
+{
+    variables.SetDisabled(mev);
+    if (mev == BFlagGet(BF_FIXED)) 
+            return;
+    BFlagSet(BF_FIXED, mev);
+    //RecomputeCollisionModel(); // because one may use different model types for static or dynamic coll.shapes
+}
+ 
+// collision stuff
+void ChBody::SetCollide (bool mcoll)
+{
+    if (mcoll == BFlagGet(BF_COLLIDE)) 
+        return;
+
+    if (mcoll)
+    {
+        SyncCollisionModels();
+        BFlagSetON(BF_COLLIDE);
+        if (GetSystem())
+            GetSystem()->GetCollisionSystem()->Add(this->GetCollisionModel());
+    }
+    else 
+    {
+        BFlagSetOFF(BF_COLLIDE);
+        if (GetSystem())
+            GetSystem()->GetCollisionSystem()->Remove(this->GetCollisionModel());
+    }
+}
+
+// forward reference
+int coll_model_from_r3d(ChCollisionModel* chmodel, ChBody* mbody, int lod, Vector* mt, ChMatrix33<>* mr);
+
+int ChBody::RecomputeCollisionModel()
+{
+    if (!GetCollide()) return FALSE; // do nothing unless collision enabled
+
+    collision_model->ClearModel(); // ++++ start geometry definition
+  
+    if (this->GetExternalObject())
+        this->GetExternalObject()->onAddCollisionGeometries(
+                    this->collision_model,
+                    this,
+                    1,
+                    &coord.pos,
+                    &Amatrix);
+
+    collision_model->BuildModel(); // ++++ complete geometry definition
+
+
+    return TRUE;
+}
+
+void ChBody::SyncCollisionModels()
+{
+    this->GetCollisionModel()->SyncPosition();
+}
+
+void ChBody::AddCollisionModelsToSystem() 
+{
+    assert(this->GetSystem());
+    SyncCollisionModels();
+    this->GetSystem()->GetCollisionSystem()->Add(this->GetCollisionModel());
+}
+
+void ChBody::RemoveCollisionModelsFromSystem() 
+{
+    assert(this->GetSystem());
+    this->GetSystem()->GetCollisionSystem()->Remove(this->GetCollisionModel());
+}
+
+
+
+void ChBody::GetTotalAABB(ChVector<>& bbmin, ChVector<>& bbmax)
+{
+    if (this->GetCollisionModel())
+        this->GetCollisionModel()->GetAABB(bbmin, bbmax);
+    else 
+        ChPhysicsItem::GetTotalAABB(bbmin, bbmax); // default: infinite aabb
+}
+
+
+//////// FILE I/O
+
+void ChBody::StreamOUT(ChStreamOutBinary& mstream)
+{
+            // class version number
+    mstream.VersionWrite(7);
+
+        // serialize parent class too
+    ChPhysicsItem::StreamOUT(mstream);
+
+        // serialize parent class too
+    ChFrameMoving<double>::StreamOUT(mstream);
+
+        // stream out all member data
+        ChVector<> vfoo=VNULL;
+        double dfoo=0;
+    mstream << variables.GetBodyMass();
+    vfoo = GetInertiaXX();  mstream << vfoo;
+    vfoo = GetInertiaXY();  mstream << vfoo;
+    
+    mstream << dfoo;
+    mstream << bflag;
+    dfoo=(double)density;   mstream << dfoo;
+
+    mstream << max_speed;
+    mstream << max_wvel;
+    mstream << sleep_time;
+    dfoo=(double)sleep_starttime;   mstream << dfoo;
+    mstream << sleep_minspeed;
+    mstream << sleep_minwvel;
+
+    this->collision_model->StreamOUT(mstream); // also  mstream << (*this->collision_model);
+
+    this->matsurface->StreamOUT(mstream); 
+    dfoo=(double)conductivity;  mstream << dfoo;
+}
+
+void ChBody::StreamIN(ChStreamInBinary& mstream)
+{
+        // class version number
+    int version = mstream.VersionRead();
+
+        // deserialize parent class too
+    if (version <4)
+        ChObj::StreamIN(mstream);
+    if (version >= 4)
+        ChPhysicsItem::StreamIN(mstream);
+
+    collision_model->ClearModel();
+
+
+    if (version==1)
+    {
+            // stream in all member data
+        int mlock; double dfoo;
+        mstream >> mlock;
+        mstream >> coord;       SetCoord(coord);
+        mstream >> coord_dt;    SetCoord_dt(coord_dt);
+        mstream >> coord_dtdt;  SetCoord_dtdt(coord_dtdt);
+        mstream >> dfoo;        SetMass(dfoo);
+        ChVector<> vfoo;
+        mstream >> vfoo;        SetInertiaXX(vfoo);
+        mstream >> vfoo;        SetInertiaXY(vfoo);
+        mstream >> dfoo; //bdamper;
+        if (version <7)
+        {
+            mstream >> dfoo;        matsurface->SetRestitution((float)dfoo);
+            mstream >> dfoo;        //matsurface->SetRestitutionT((float)dfoo);
+            mstream >> dfoo;        matsurface->SetKfriction((float)dfoo);
+            mstream >> dfoo;        matsurface->SetSfriction((float)dfoo);
+        }
+        mstream >> bflag;
+        mstream >> dfoo;        density = (float)dfoo;
+        SetBodyFixed(mlock != 0);
+    }
+    if (version >=2)
+    {
+            // deserialize parent class too
+        ChFrameMoving<double>::StreamIN(mstream);
+
+            // stream in all member data
+        double dfoo;
+        mstream >> dfoo;        SetMass(dfoo);
+        ChVector<> vfoo;
+        mstream >> vfoo;        SetInertiaXX(vfoo);
+        mstream >> vfoo;        SetInertiaXY(vfoo);
+        mstream >> dfoo; //bdamper;
+        if (version <7)
+        {
+            mstream >> dfoo;        matsurface->SetRestitution((float)dfoo);
+            mstream >> dfoo;        //matsurface->SetRestitutionT((float)dfoo);
+            mstream >> dfoo;        matsurface->SetKfriction((float)dfoo);
+            mstream >> dfoo;        matsurface->SetSfriction((float)dfoo);
+        }
+        mstream >> bflag;
+        mstream >> dfoo;        density = (float)dfoo;
+        if(this->GetBodyFixed())
+            SetBodyFixed(true);
+        else SetBodyFixed(false);
+    }
+    if (version <3) SetUseSleeping(true);
+    if (version >=3)
+    {
+        double dfoo;
+        mstream >> max_speed;
+        mstream >> max_wvel;
+        mstream >> sleep_time;
+        mstream >> dfoo;        sleep_starttime= (float)dfoo;
+        mstream >> sleep_minspeed;
+        mstream >> sleep_minwvel;
+    }
+    if ((version >=5) && (version < 7))
+    {
+        double dfoo;
+        mstream >> dfoo;        matsurface->SetRollingFriction((float)dfoo);
+        mstream >> dfoo;        matsurface->SetSpinningFriction((float)dfoo);
+    }
+    if (version >=6)
+    {
+        this->collision_model->StreamIN(mstream); // also   mstream >> (*collision_model);
+        this->collision_model->BuildModel(); // because previously removed from ChSystem, if any.
+    }
+    if (version >=7)
+    {
+        double dfoo;
+        this->matsurface->StreamIN(mstream);
+        mstream >> dfoo;        conductivity = (float)dfoo;
+    }
+}
+
+
+
+
+void ChBody::StreamOUTstate(ChStreamOutBinary& mstream)
+{
+    // Do not serialize parent classes and do not
+    // implement versioning, because this must be efficient 
+    // and will be used just for domain decomposition.
+    this->GetCoord().StreamOUT(mstream);
+    this->GetCoord_dt().StreamOUT(mstream);
+}
+
+void ChBody::StreamINstate(ChStreamInBinary& mstream)
+{
+    // Do not serialize parent classes and do not
+    // implement versioning, because this must be efficient 
+    // and will be used just for domain decomposition.
+    ChCoordsys<> mcoord;
+    mstream >> mcoord;
+    this->SetCoord(mcoord);
+    mstream >> mcoord;
+    this->SetCoord_dt(mcoord);
+
+    this->Update();
+    this->SyncCollisionModels();
+}
+
+
+#define CH_CHUNK_END 1234
+
+int ChBody::StreamINall  (ChStreamInBinary& m_file)
+{
+    int mchunk = 0;
+    ChMarker* newmarker= NULL;
+    //ChForce*  newforce= NULL;
+
+    // 0) reset body child lists
+    RemoveAllMarkers();
+    RemoveAllForces();
+
+
+    // 1) read body class data...
+ 
+    m_file >> *this; 
+
+    m_file >> mchunk; 
+
+    // 2) read child markers
+    while (mchunk == CHCLASS_MARKER)
+    {
+        ChSharedPtr<ChMarker> newmarker(new ChMarker);
+        this->AddMarker(newmarker);
+
+        m_file >> *newmarker;
+
+        newmarker->Impose_Abs_Coord (newmarker->GetAbsCoord());
+
+        m_file >> mchunk;
+    }
+
+    // 3) read child links
+    while (mchunk == CHCLASS_FORCE)
+    {
+        ChSharedPtr<ChForce> newforce(new ChForce);
+        this->AddForce(newforce);
+
+        m_file >> *newforce;
+
+        m_file >> mchunk;
+    }
+
+
+    if (mchunk != CH_CHUNK_END) return 0;
+
+
+    return 1;
+}
+
+
+int ChBody::StreamOUTall  (ChStreamOutBinary& m_file)
+{
+
+    // 1) read body class data...
+    m_file << *this;
+
+    // 2) read child bodies
+    HIER_MARKER_INIT
+    while HIER_MARKER_NOSTOP
+    {
+        m_file << (int)CHCLASS_MARKER;
+        m_file << *MARKpointer;
+        HIER_MARKER_NEXT
+    }
+
+    // 3) read child links
+    HIER_FORCE_INIT
+    while HIER_FORCE_NOSTOP
+    {
+        m_file << (int)CHCLASS_FORCE;
+        m_file << *FORCEpointer;
+        HIER_FORCE_NEXT
+    }
+
+    m_file << (int)CH_CHUNK_END;
+
+    return 1;
+}
+
+void ChBody::StreamOUT(ChStreamOutAscii& mstream)
+{
+    mstream << "BODY   " << GetName() <<"\n";
+
+    ChFrameMoving<double>::StreamOUT(mstream);
+
+    //***TO DO***
+}
+
+
+int ChBody::StreamOUTall  (ChStreamOutAscii& mstream) // dump rigidbody and childrens (markers.forces)
+{
+    StreamOUT (mstream);             // 1) dump the body attrs
+
+    HIER_MARKER_INIT
+    while (HIER_MARKER_NOSTOP)   // 2) dump the markers
+    {
+        MARKpointer->StreamOUT (mstream);
+        HIER_MARKER_NEXT
+    }
+
+    HIER_FORCE_INIT
+    while (HIER_FORCE_NOSTOP) // 3) dump the forces
+    {
+        FORCEpointer->StreamOUT (mstream);
+        HIER_FORCE_NEXT
+    }
+
+    return 1;
+}
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChBody.h b/SRC/ChronoEngine/physics/ChBody.h
new file mode 100644
index 0000000..3473ca0
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChBody.h
@@ -0,0 +1,681 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHBODY_H
+#define CHBODY_H
+
+//////////////////////////////////////////////////
+//
+//   ChBody.h
+//
+//   Class for rigid bodies, that is rigid moving
+//   parts with mass and maybe collision geometry.
+//   A rigid body encloses markers and forces too
+//
+//   HEADER file for CHRONO,
+//   Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "core/ChFrameMoving.h"
+#include "core/ChShared.h"
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChForce.h"
+#include "physics/ChMarker.h"
+#include "physics/ChMaterialSurface.h"
+#include "lcp/ChLcpVariablesBodyOwnMass.h"
+#include "lcp/ChLcpConstraint.h"
+#include "collision/ChCCollisionSystem.h"
+
+
+namespace chrono
+{
+
+using namespace collision;
+
+
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+typedef ChSharedPtr<ChForce>  ChSharedForcePtr;
+typedef ChSharedPtr<ChMarker> ChSharedMarkerPtr;
+
+
+/////////////////////////////////////
+// Define body specific flags
+
+#define BF_COLLIDE          (1L << 0)  // detects collisions
+#define BF_CDINVISIBLE      (1L << 1)  // collision detection invisible
+#define BF_EVAL_CONTACT_CN  (1L << 2)  // evaluate CONTACT_CN channel (normal restitution)
+#define BF_EVAL_CONTACT_CT  (1L << 3)  // evaluate CONTACT_CT channel (tangential rest.)
+#define BF_EVAL_CONTACT_KF  (1L << 4)  // evaluate CONTACT_KF channel (kinetic friction coeff)
+#define BF_EVAL_CONTACT_SF  (1L << 5)  // evaluate CONTACT_SF channel (static friction coeff)
+#define BF_SHOW_COLLMESH    (1L << 6)  // show collision mesh - obsolete
+#define BF_FIXED            (1L << 7)  // body is fixed to ground
+#define BF_LIMITSPEED       (1L << 8)  // body angular and linar speed is limited (clamped)
+#define BF_SLEEPING         (1L << 9)  // body is sleeping [internal]
+#define BF_USESLEEPING      (1L <<10)  // if body remains in same place for too long time, it will be frozen
+#define BF_NOGYROTORQUE     (1L <<11)  // body do not get the gyroscopic (quadratic) term, for low-fi but stable RT simulations.
+
+///
+/// Class for rigid bodies. A rigid body is an entity which
+/// can move in 3D space, and can be constrained to other rigid
+/// bodies using ChLink objects. Rigid bodies can contain auxiliary
+/// references (the ChMarker objects) and forces (the ChForce objects).
+/// These objects have mass and inertia properties. A shape can also
+/// be associated to the body, for collision detection.
+///
+
+class ChApi ChBody : public ChPhysicsItem , public ChFrameMoving<double> {
+
+                        // Chrono simulation of RTTI, needed for serialization
+    CH_RTTI(ChBody,ChPhysicsItem);
+
+protected:
+    
+                        // Pointer to the collision model, including the
+                        // colliding geometry .
+    ChCollisionModel* collision_model;
+
+protected:
+            //
+            // DATA
+            //
+
+    int bflag;          // body-specific flags.
+    unsigned int body_id; // HM - body specific identifier, used for indexing
+
+                        // list of child markers
+    std::vector<ChMarker*> marklist;
+
+                        // list of child forces
+    std::vector<ChForce*>  forcelist;
+    
+
+
+    ChVector<> gyro;        // The Qm gyroscopic torque, i.e. Qm= Wvel x (XInertia*Wvel)
+
+    ChVector<> Xforce;      // The force  acting on body, applied to COG -in abs. coords-
+    ChVector<> Xtorque;     // The torque acting on body  -in body rel. coords-
+
+
+    ChVector<> Force_acc;   // force accumulator; (in abs space, applied to COG)
+    ChVector<> Torque_acc;  // torque accumulator;(in abs space)
+
+    ChVector<> Scr_force;   // script force accumulator; (in abs space, applied to COG)
+    ChVector<> Scr_torque;  // script torque accumulator;(in abs space)
+
+                        // data for surface contact and impact (can be shared):
+    ChSharedPtr<ChMaterialSurface> matsurface;
+
+                        // Auxiliary, stores position/rotation once a while
+                        // when collision detection routines require to know
+                        // the last time that coll.detect. was satisfied.
+    ChCoordsys<> last_coll_pos;
+                        
+
+    float density;      // used when doing the 'recompute mass' operation.
+
+    float conductivity; // electric conductivity of material
+
+    ChVector<> cdim;    // characteristic dimension of the body
+
+                        // used to store mass matrix and coordinates, as
+                        // an interface to the LCP solver.
+    ChLcpVariablesBodyOwnMass   variables;
+
+    float max_speed;    // limit on linear speed (useful for VR & videagames)
+    float max_wvel;     // limit on angular vel. (useful for VR & videagames)
+
+    float  sleep_time;
+    float  sleep_minspeed;
+    float  sleep_minwvel;
+    float  sleep_starttime;
+
+public:
+
+            //
+            // CONSTRUCTORS
+            //
+
+                /// Build a rigid body.
+    ChBody ();
+                /// Build a rigid body with a different collision model.
+    ChBody (ChCollisionModel* new_collision_model);
+                /// Destructor
+    ~ChBody ();
+
+                /// Copy from another ChBody. 
+                /// NOTE: all settings of the body are copied, but the
+                /// child hierarchy of ChForces and ChMarkers (if any) are NOT copied.
+    void Copy(ChBody* source);
+
+
+            //
+            // FLAGS
+            //
+
+
+                /// Sets the 'fixed' state of the body. If true, it does not move
+                /// respect to the absolute world, despite constraints, forces, etc.
+    void SetBodyFixed (bool mev);
+    bool GetBodyFixed()    {return BFlagGet(BF_FIXED);}
+
+                /// If true, the normal restitution coefficient is evaluated
+                /// from painted material channel.
+    void SetEvalContactCn (bool mev) { BFlagSet(BF_EVAL_CONTACT_CN, mev);}
+    bool GetEvalContactCn() {return BFlagGet(BF_EVAL_CONTACT_CN);}
+
+                /// If true, the tangential restitution coefficient is evaluated
+                /// from painted material channel.
+    void SetEvalContactCt (bool mev) { BFlagSet(BF_EVAL_CONTACT_CT, mev);}
+    bool GetEvalContactCt() {return BFlagGet(BF_EVAL_CONTACT_CT);}
+
+                /// If true, the kinetic friction coefficient is evaluated
+                /// from painted material channel.
+    void SetEvalContactKf (bool mev) { BFlagSet(BF_EVAL_CONTACT_KF, mev);}
+    bool GetEvalContactKf() {return BFlagGet(BF_EVAL_CONTACT_KF);}
+
+                /// If true, the static friction coefficient is evaluated
+                /// from painted material channel.
+    void SetEvalContactSf (bool mev) { BFlagSet(BF_EVAL_CONTACT_SF, mev);}
+    bool GetEvalContactSf() {return BFlagGet(BF_EVAL_CONTACT_SF);}
+
+                /// Enable/disable the collision for this rigid body.
+                /// (After setting ON, you may need RecomputeCollisionModel()
+                /// before anim starts, if you added an external object 
+                /// that implements onAddCollisionGeometries(), ex. in a plugin for a CAD)
+    void  SetCollide (bool mcoll);
+    bool  GetCollide() {return BFlagGet(BF_COLLIDE);}
+
+                /// Show collision mesh in 3D views.
+    void SetShowCollisionMesh    (bool mcoll) { BFlagSet(BF_SHOW_COLLMESH, mcoll);};
+    bool GetShowCollisionMesh () {return BFlagGet(BF_SHOW_COLLMESH);};
+
+                /// Trick. Set the maximum linear speed (beyond this limit it will
+                /// be clamped). This is useful in virtual reality and real-time
+                /// simulations, because it reduces the risk of bad collision detection.
+                /// The realism is limited, but the simulation is more stable.
+    void SetLimitSpeed    (bool mlimit) { BFlagSet(BF_LIMITSPEED, mlimit);};
+    bool GetLimitSpeed()  {return BFlagGet(BF_LIMITSPEED);};
+
+                /// Trick. Deactivate the gyroscopic torque (quadratic term).
+                /// This is useful in virtual reality and real-time
+                /// simulations, where objects that spin too fast with non-uniform inertia
+                /// tensors (ex thin cylinders) might cause the integration to diverge quickly.
+                /// The realism is limited, but the simulation is more stable.
+    void SetNoGyroTorque    (bool mnogyro) { BFlagSet(BF_NOGYROTORQUE, mnogyro);};
+    bool GetNoGyroTorque()  {return BFlagGet(BF_NOGYROTORQUE);};
+
+                /// Trick. If use sleeping= true, bodies which stay in same place
+                /// for too long time will be deactivated, for optimization.
+                /// The realism is limited, but the simulation is faster.
+    void SetUseSleeping    (bool ms) { BFlagSet(BF_USESLEEPING, ms);};
+    bool GetUseSleeping()  {return BFlagGet(BF_USESLEEPING);};
+
+                /// Force the body in sleeping mode or not (usually this state change is not
+                /// handled by users, anyway, because it is mostly automatic).
+    void SetSleeping    (bool ms) { BFlagSet(BF_SLEEPING, ms);};
+                /// Tell if the body is actually in sleeping state.
+    bool GetSleeping()  {return BFlagGet(BF_SLEEPING);};
+
+                /// Put the body in sleeping state if requirements are satisfied.
+    bool TrySleeping();
+
+                /// Tell if the body is active, i.e. it is neither fixed to ground nor
+                /// it is in sleep mode.
+    bool IsActive() {return !BFlagGet(BF_SLEEPING | BF_FIXED);}
+                /// Set the body identifier - HM
+    void SetId(int identifier) { body_id = identifier; }
+                /// Set the body identifier - HM
+    unsigned int GetId() { return body_id;}
+
+            //
+            // FUNCTIONS
+            //
+
+                /// Number of coordinates of the rigid body =6 (internally, 3+4=7 coords are used 
+                /// since quaternions are used for large rotations, but local coords -ex. w&v velocity- are 6)
+    virtual int GetDOF  ()   {return 6;}
+
+                /// Returns reference to the encapsulated ChLcpVariablesBody,
+                /// representing body variables (pos, speed or accel.- see VariablesLoad...() )
+                /// and forces.
+                /// The ChLcpVariablesBodyOwnMass is the interface ta the LCP system solver.
+    ChLcpVariablesBodyOwnMass& Variables() {return variables;}
+
+
+             // Override/implement LCP system functions of ChPhysicsItem
+             // (to assembly/manage data for LCP system solver)
+
+                /// Sets the 'fb' part of the encapsulated ChLcpVariablesBodyOwnMass to zero.
+    void VariablesFbReset();
+
+                /// Adds the current forces applied to body (including gyroscopic torque) in
+                /// encapsulated ChLcpVariablesBody, in the 'fb' part: qf+=forces*factor
+    void VariablesFbLoadForces(double factor=1.);
+
+                /// Initialize the 'qb' part of the ChLcpVariablesBody with the 
+                /// current value of body speeds. Note: since 'qb' is the unknown of the LCP, this
+				/// function seems unuseful, unless used before VariablesFbIncrementMq()
+    void VariablesQbLoadSpeed();
+
+				/// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
+				/// with v_old using VariablesQbLoadSpeed, this method can be used in 
+				/// timestepping schemes that do: M*v_new = M*v_old + forces*dt
+	void VariablesFbIncrementMq();
+
+                /// Fetches the body speed (both linear and angular) from the
+                /// 'qb' part of the ChLcpVariablesBody (does not updates the full body&markers state)
+                /// and sets it as the current body speed.
+                /// If 'step' is not 0, also computes the approximate acceleration of
+                /// the body using backward differences, that is  accel=(new_speed-old_speed)/step.
+                /// Mostly used after the LCP provided the solution in ChLcpVariablesBody .
+    void VariablesQbSetSpeed(double step=0.);
+
+                /// Increment body position by the 'qb' part of the ChLcpVariablesBody,
+                /// multiplied by a 'step' factor.
+                ///     pos+=qb*step
+                /// If qb is a speed, this behaves like a single step of 1-st order
+                /// numerical integration (Eulero integration).
+                /// Does not automatically update markers & forces.
+    void VariablesQbIncrementPosition(double step);
+
+
+                /// Tell to a system descriptor that there are variables of type
+                /// ChLcpVariables in this object (for further passing it to a LCP solver)
+    virtual void InjectVariables(ChLcpSystemDescriptor& mdescriptor);
+
+
+                /// Instantiate the collision model
+    virtual ChCollisionModel* InstanceCollisionModel();
+
+               // Other functions
+
+                /// Set no speed and no accelerations (but does not change the position)
+    void SetNoSpeedNoAcceleration();
+
+
+                /// Acess the collision model for the collision engine.
+                /// To get a non-null pointer, remember to SetCollide(true), before.
+    ChCollisionModel* GetCollisionModel() {return collision_model;}
+
+                /// Synchronize coll.model coordinate and bounding box to the position of the body.
+    virtual void SyncCollisionModels();
+    virtual void AddCollisionModelsToSystem();
+    virtual void RemoveCollisionModelsFromSystem();
+
+                /// Update the optimization structures (OOBB, ABB, etc.)
+                /// of the collision model, from the associated geometry in some external object (es.CAD).
+    int RecomputeCollisionModel();
+
+                /// Gets the last position when the collision detection was
+                /// performed last time (i.e. last time SynchronizeLastCollPos() was used)
+    ChCoordsys<> GetLastCollPos () { return last_coll_pos; }
+                /// Stores the current position in the last-collision-position buffer.
+    void SynchronizeLastCollPos() {last_coll_pos = this->coord;}
+
+                /// Get the rigid body coordinate system that represents
+                /// the GOG (Center of Gravity). The mass and inertia tensor
+                /// are defined respect to this coordinate system, that is also
+                /// assumed the default main coordinates of the body. 
+                /// By default, doing mybody.GetPos() etc. is like mybody.GetFrame_COG_abs().GetPos() etc.
+    virtual ChFrame<>& GetFrame_COG_to_abs() {return *this;}
+
+                /// Get the rigid body coordinate system that is used for
+                /// defining the collision shapes and the ChMarker objects.
+                /// For the base ChBody, this is always the same reference of the COG.
+    virtual ChFrame<>& GetFrame_REF_to_abs() {return *this;}
+
+
+                /// Get the entire AABB axis-aligned bounding box of the object,
+                /// as defined by the collision model (if any).
+    virtual void GetTotalAABB(ChVector<>& bbmin, ChVector<>& bbmax);
+
+                /// Method to deserialize only the state (position, speed)
+    virtual void StreamINstate(ChStreamInBinary& mstream);
+                /// Method to serialize only the state (position, speed)
+    virtual void StreamOUTstate(ChStreamOutBinary& mstream);    
+
+                /// Access the material surface properties, referenced by this 
+                /// rigid body. The material surface contains properties such as friction, etc. 
+                /// The ChMaterialSurface can be a shared object! (by default, each body creates its
+                /// own as soon as instanced, but later the material object can be replaced).
+    ChSharedPtr<ChMaterialSurface>& GetMaterialSurface() {return this->matsurface;}
+                /// Set the material surface properties by passing a ChMaterialSurface object.
+                /// Thank to smart pointers, the one that was previously used is replaced and,
+                /// if needed, it is automatically dereferenced and deleted.
+                /// The ChMaterialSurface can be a shared object! (by default, each body creates its
+                /// own as soon as instanced, but later the material object can be replaced).
+    void SetMaterialSurface(ChSharedPtr<ChMaterialSurface>& mnewsurf) {this->matsurface = mnewsurf;}
+
+
+                /// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+    float  GetImpactC() {return this->matsurface->GetRestitution();}
+    void   SetImpactC(float mval) {this->matsurface->SetRestitution(mval);}
+                /// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+    float  GetImpactCt() {return 0;}
+    void   SetImpactCt(float) {}
+                /// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+    float  GetKfriction() {return this->matsurface->GetKfriction();}
+    void   SetKfriction(float mval) {this->matsurface->SetKfriction(mval);}
+                /// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+    float  GetSfriction() {return this->matsurface->GetSfriction();}
+    void   SetSfriction(float mval) {this->matsurface->SetSfriction(mval);}
+                /// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+    void   SetFriction(float mval) {this->matsurface->SetFriction(mval);}
+                /// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+    float  GetRollingFriction() {return this->matsurface->GetRollingFriction();}
+    void   SetRollingFriction(float mval) {this->matsurface->SetRollingFriction(mval);}
+                /// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+    float  GetSpinningFriction() {return this->matsurface->GetSpinningFriction();}
+    void   SetSpinningFriction(float mval) {this->matsurface->SetSpinningFriction(mval);}
+
+
+                /// The density of the rigid body, as [mass]/[unit volume]. Used just if
+                /// the inertia tensor and mass are automatically recomputed from the
+                /// geometry (in case a CAD plugin for example provides the surfaces.)
+    float  GetDensity() {return density;}
+    void   SetDensity(float mdensity) {density = mdensity;}
+
+                // Electric conductivity of material
+    float  GetConductivity() {return conductivity;}
+    void   SetConductivity(float mconductivity) {conductivity = mconductivity;}
+                // Caracteristic dimensions of the body 
+    ChVector<> GetCdim() {return cdim;}
+    void   SetCdim(ChVector<> mcdim) {cdim = mcdim;}
+
+
+            //
+            // DATABASE HANDLING.
+            //
+            // To attach/remove items (rigid bodies, links, etc.) you must use 
+            // shared pointer, so that you don't need to care about item deletion, 
+            // which will be automatic when needed.
+            // Please don't add the same item multiple times; also, don't remove
+            // items which haven't ever been added.
+            // NOTE! After adding/removing items to the system, you should call Update() !
+
+                /// Attach a marker to this body. 
+    void AddMarker (ChSharedPtr<ChMarker> amarker);
+                /// Attach a force to this body. 
+    void AddForce (ChSharedPtr<ChForce> aforce);
+
+                /// Remove a specific marker from this body. Warning: linear time search.
+    void RemoveMarker (ChSharedPtr<ChMarker> amarker);
+                /// Remove a specific force from this body. Warning: linear time search.
+    void RemoveForce  (ChSharedPtr<ChForce> aforce);
+
+                /// Remove all markers at once. Faster than doing multiple RemoveForce()
+                /// Don't care about deletion: it is automatic, only when needed.
+    void RemoveAllForces();
+                /// Remove all markers at once. Faster than doing multiple RemoveForce()
+                /// Don't care about deletion: it is automatic, only when needed.
+    void RemoveAllMarkers();
+
+                /// Finds a marker from its ChObject name
+    //ChMarker* SearchMarker (char* m_name); // Old 
+    ChSharedPtr<ChMarker> SearchMarker (char* m_name);
+                /// Finds a force from its ChObject name
+    //ChForce*  SearchForce (char* m_name); // Old
+    ChSharedPtr<ChForce>  SearchForce (char* m_name);
+
+                /// Gets the list of children markers.
+                /// NOTE! use this list only to enumerate etc., but NOT to
+                /// remove or add items (use the appropriate Remove.. and Add.. 
+                /// functions instead!)
+    std::vector<ChMarker*>* GetMarkerList() {return &marklist;} 
+
+                /// Gets the list of children forces.
+                /// NOTE! use this list only to enumerate etc., but NOT to
+                /// remove or add items (use the appropriate Remove.. and Add.. 
+                /// functions instead!)
+    std::vector<ChForce*>* GetForceList() {return &forcelist;}
+
+    
+
+
+
+            //
+            // Point/vector transf.(NOTE! you may also use operators of ChMovingFrame)
+            //
+
+    ChVector<> Point_World2Body (ChVector<>* mpoint);
+    ChVector<> Point_Body2World (ChVector<>* mpoint);
+    ChVector<> Dir_World2Body (ChVector<>* mpoint);
+    ChVector<> Dir_Body2World (ChVector<>* mpoint);
+    ChVector<> RelPoint_AbsSpeed(ChVector<>* mrelpoint);
+    ChVector<> RelPoint_AbsAcc(ChVector<>* mrelpoint);
+
+                /// Mass of the rigid body. Must be positive.
+                /// Try not to mix bodies with too high/too low values of mass, for numerical stability.
+    void   SetMass (double newmass) { if (newmass>0.) variables.SetBodyMass(newmass);}
+    double GetMass() {return variables.GetBodyMass();}
+
+                /// Set the inertia tensor of the body
+    void SetInertia (ChMatrix33<>* newXInertia);
+                /// Set the diagonal part of the inertia tensor (Ixx, Iyy, Izz values)
+    void SetInertiaXX (ChVector<> iner);
+                /// Get the diagonal part of the inertia tensor (Ixx, Iyy, Izz values)
+    ChVector<> GetInertiaXX();
+                /// Set the extradiagonal part of the inertia tensor
+                /// (Ixy, Iyz, Izx values, the rest is symmetric)
+                /// Warning about sign: in some books they write the inertia tensor as 
+                /// I=[Ixx, -Ixy, -Ixz; etc.] but here is I=[Ixx, Ixy, Ixz; etc.]
+    void SetInertiaXY (ChVector<> iner);
+                /// Get the extradiagonal part of the inertia tensor
+                /// (Ixy, Iyz, Izx values, the rest is symmetric)
+                /// Warning about sign: in some books they write the inertia tensor as 
+                /// I=[Ixx, -Ixy, -Ixz; etc.] but here is I=[Ixx, Ixy, Ixz; etc.]
+    ChVector<> GetInertiaXY();
+
+
+                /// Trick. Set the maximum linear speed (beyond this limit it will
+                /// be clamped). This is useful in virtual reality and real-time
+                /// simulations, because it reduces the risk of bad collision detection.
+                /// This speed limit is active only if you set  SetLimitSpeed(true);
+    void   SetMaxSpeed(float m_max_speed) {max_speed = m_max_speed;}
+    float  GetMaxSpeed () {return max_speed;}
+
+                /// Trick. Set the maximum angualar speed (beyond this limit it will
+                /// be clamped). This is useful in virtual reality and real-time
+                /// simulations, because it reduces the risk of bad collision detection.
+                /// This speed limit is active only if you set  SetLimitSpeed(true);
+    void   SetMaxWvel(float m_max_wvel) {max_wvel = m_max_wvel;}
+    float  GetMaxWvel () {return max_wvel;}
+
+                /// When this function is called, the speed of the body is clamped
+                /// into limits posed by max_speed and max_wvel  - but remember to
+                /// put the body in the SetLimitSpeed(true) mode.
+    void ClampSpeed();
+
+                /// Set the amount of time which must pass before going automatically in
+                /// sleep mode when the body has very small movements.
+    void   SetSleepTime(float m_t) {sleep_time = m_t;}
+    float GetSleepTime () {return sleep_time;}
+
+                /// Set the max linear speed to be kept for 'sleep_time' before freezing.
+    void   SetSleepMinSpeed(float m_t) {sleep_minspeed = m_t;}
+    float GetSleepMinSpeed () {return sleep_minspeed;}
+
+                /// Set the max linear speed to be kept for 'sleep_time' before freezing.
+    void   SetSleepMinWvel(float m_t) {sleep_minwvel = m_t;}
+    float GetSleepMinWvel () {return sleep_minwvel;}
+
+
+
+                /// Computes the 4x4 inertia tensor in quaternion space, if needed
+    void ComputeQInertia(ChMatrixNM<double,4,4>* mQInertia);
+
+                /// Computes the gyroscopic torque. In fact, in sake of highest
+                /// speed, the gyroscopic torque isn't automatically updated each time a
+                /// SetCoord() or SetCoord_dt() etc. is called, but only if necessary,
+                /// for each UpdateState().
+    void ComputeGyro ();
+
+
+                /// Transform and adds a cartesian force to a generic 7x1 vector of body lagrangian forces mQf .
+                /// The carthesian force must be passed as vector and application point, and vcan be either in local
+                /// (local = TRUE) or absolute reference (local = FALSE)
+    void Add_as_lagrangian_force(ChVector<> force, ChVector<> appl_point, int local, ChMatrixNM<double,7,1>* mQf);
+    void Add_as_lagrangian_torque(ChVector<> torque, int local, ChMatrixNM<double,7,1>* mQf);
+
+                /// Given a lagrangian force (in a 7x1 matrix), computes the fore and torque as vectors.
+    void From_lagrangian_to_forcetorque(ChMatrixNM<double,7,1>* mQf, ChVector<>* mforce, ChVector<>* mtorque);
+                /// Given force and torque as vectors, computes the lagrangian force (in a 7x1 matrix)
+    void From_forcetorque_to_lagrangian(ChVector<>* mforce, ChVector<>* mtorque, ChMatrixNM<double,7,1>* mQf);
+
+
+            //
+            // UTILITIES FOR FORCES/TORQUES:
+            //
+
+                /// Trasform generic cartesian force into absolute force+torque applied to body COG.
+                /// If local=1, force & application point are intended as expressed in local
+                /// coordinates, if =0, in absolute.
+    void To_abs_forcetorque  (ChVector<> force, ChVector<> appl_point, int local, ChVector<>& resultforce, ChVector<>& resulttorque);
+
+                /// Trasform generic cartesian torque into absolute torque applied to body COG.
+                /// If local=1, torque is intended as expressed in local coordinates, if =0, in absolute.
+    void To_abs_torque (ChVector<> torque, int local, ChVector<>& resulttorque);
+
+                /// As before, but puts the result into the "accumulators", as increment.
+                /// Forces and torques currently in accumulators will affect the body.
+                /// It's up to the user to remember to empty them and/or set again at each 
+                /// integration step. Useful to apply forces to bodies without needing to
+                /// add ChForce() objects. If local=true, force,appl.point or torque are considered
+                /// expressed in body coordinates, otherwise are considered in absolute coordinates.
+    void Accumulate_force  (ChVector<> force, ChVector<> appl_point, int local);
+    void Accumulate_torque (ChVector<> torque, int local);
+    ChVector<> Get_accumulated_force  () {return Force_acc;};
+    ChVector<> Get_accumulated_torque () {return Torque_acc;};
+    void Empty_forces_accumulators () {Force_acc = VNULL; Torque_acc = VNULL;};
+
+                /// To get & set the 'script' force buffers(only accessed by external scripts, so
+                /// It's up to the script to remember to set& reset them -link class just add them to
+                /// all other forces. Script forces&torques are considered applied to COG, in abs csys.
+    ChVector<>* Get_Scr_force() {return &Scr_force;};
+    ChVector<>* Get_Scr_torque() {return &Scr_torque;};
+    void Set_Scr_force(ChVector<> mf) {Scr_force = mf;};
+    void Set_Scr_torque(ChVector<> mf) {Scr_torque = mf;};
+    void Accumulate_script_force (ChVector<> force, ChVector<> appl_point, int local);
+    void Accumulate_script_torque (ChVector<> torque, int local);
+
+                /// Return the gyroscopic torque.
+    ChVector<>  Get_gyro() {return gyro;}
+
+                /// Get the total force applied to the rigid body (applied at center of mass.
+                /// expressed in absolute coordinates).
+    ChVector<> Get_Xforce () {return Xforce;}
+                /// Get the total torque applied to the rigid body (expressed in body coordinates).
+                /// This does not include the gyroscopic torque.
+    ChVector<> Get_Xtorque() {return Xtorque;}
+
+                /// Get the address of the inertia tensor, as a 3x3 matrix,
+                /// expressed in local coordinate system.
+    ChMatrix33<>* GetXInertia () { return &variables.GetBodyInertia();}
+
+
+            // Body-specific flag handling
+
+    void BFlagsSetAllOFF () {bflag = 0;}
+    void BFlagsSetAllON () {bflag = 0; bflag = ~ bflag;}
+    void BFlagSetON  (int mask) {bflag |= mask ;}
+    void BFlagSetOFF (int mask) {bflag &= ~ mask;}
+    bool BFlagGet    (int mask) {return (bflag & mask)!=0;};
+    void BFlagSet    (int mask, bool state) {if (state) bflag |= mask; else bflag &= ~ mask;};
+
+            //
+            // UPDATE FUNCTIONS
+            //
+
+                /// Update all children markers of the rigid body, at current body state
+    void UpdateMarkers (double mytime);
+                /// Update all children forces of the rigid body, at current body state.
+    void UpdateForces (double mytime);
+                /// Update local time of rigid body, and time-dependant data
+    void UpdateTime (double mytime);
+                /// Update all auxiliary data of the rigid body, at given time
+    void UpdateState (ChCoordsys<> mypos, ChCoordsys<> mypos_dt);
+                /// Update all auxiliary data of the rigid body, at given time and state
+    void UpdateStateTime (ChCoordsys<> mypos, ChCoordsys<> mypos_dt, double mytime);
+                /// Update all auxiliary data of the rigid body and of
+                /// its children (markers, forces..), at given time and state
+    void Update (ChCoordsys<> mypos, ChCoordsys<> mypos_dt, double mytime);
+
+
+                /// Update all auxiliary data of the rigid body and of
+                /// its children (markers, forces..), at given time
+    virtual void Update (double mytime);
+                /// Update all auxiliary data of the rigid body and of
+                /// its children (markers, forces..)
+    virtual void Update ();
+
+
+                /// Tells to the associated external object ChExternalObject() ,if any,
+                /// that its 3D shape must be updated in order to syncronize to ChBody
+                /// coordinates
+    void UpdateExternalGeometry ();
+
+
+            //
+            // STREAMING
+            //
+
+
+                /// Method to allow deserializing a persistent binary archive (ex: a file)
+                /// into transient data.
+    void StreamIN(ChStreamInBinary& mstream);
+
+                /// Method to allow serializing transient data into a persistent
+                /// binary archive (ex: a file).
+    void StreamOUT(ChStreamOutBinary& mstream);
+
+                /// Save data, including child markers and child forces
+    int StreamOUTall (ChStreamOutBinary& m_file);
+                /// Read data, including child markers and child forces
+    int StreamINall  (ChStreamInBinary&  m_file);
+
+
+                /// Method to allow serialization of transient data in ascii,
+                /// as a readable item, for example   "chrono::GetLog() << myobject;"
+    void StreamOUT(ChStreamOutAscii& mstream);
+
+    int  StreamOUTall  (ChStreamOutAscii& mstream);
+
+};
+
+
+
+
+const int BODY_DOF = 6;  ///< degrees of freedom of body in 3d space
+const int BODY_QDOF = 7; ///< degrees of freedom with quaternion rotation state
+const int BODY_ROT = 3;  ///< rotational dof in Newton dynamics
+
+
+typedef ChSharedPtr<ChBody> ChSharedBodyPtr; 
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChBodyAuxRef.cpp b/SRC/ChronoEngine/physics/ChBodyAuxRef.cpp
new file mode 100644
index 0000000..4144449
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChBodyAuxRef.cpp
@@ -0,0 +1,185 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChBodyAuxRef.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include "physics/ChBodyAuxRef.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChBodyAuxRef> a_registration_ChBodyAuxRef;
+
+
+// Hierarchy-handling shortcuts
+ 
+#define MARKpointer		    (*imarker)
+#define HIER_MARKER_INIT	std::vector<ChMarker*>::iterator imarker = marklist.begin();
+#define HIER_MARKER_NOSTOP	(imarker != marklist.end())
+#define HIER_MARKER_NEXT	imarker++;
+
+#define FORCEpointer		(*iforce)
+#define HIER_FORCE_INIT		std::vector<ChForce*>::iterator iforce = forcelist.begin();
+#define HIER_FORCE_NOSTOP	(iforce != forcelist.end())
+#define HIER_FORCE_NEXT		iforce++;	
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SOLID BODIES WITH AUXILIARY REFERENCE
+
+
+ChBodyAuxRef::ChBodyAuxRef ()
+{
+	
+}
+
+
+
+ChBodyAuxRef::~ChBodyAuxRef ()
+{
+	
+}
+
+void ChBodyAuxRef::Copy(ChBodyAuxRef* source)
+{
+		// copy the parent class data...
+	ChBody::Copy(source);
+	
+		// copy own data
+	this->auxref_to_cog = source->auxref_to_cog;
+	this->auxref_to_abs = source->auxref_to_abs;
+}
+
+
+
+void ChBodyAuxRef::SetFrame_COG_to_REF(const ChFrame<>& mloc) 
+{	
+	ChFrameMoving<> old_cog_to_abs = *this;
+
+	ChFrameMoving<> tmpref_to_abs;
+	this->TrasformLocalToParent(this->auxref_to_cog, tmpref_to_abs);
+	tmpref_to_abs.TrasformLocalToParent(ChFrameMoving<>(mloc), *this);
+	// or, also, using overloaded operators for frames: 
+	//   tmpref_to_abs = auxref_to_cog >> *this;
+	//   *this         = ChFrameMoving<>(mloc) >> tmpref_to_abs;
+	
+	ChFrameMoving<> new_cog_to_abs = *this;
+
+	auxref_to_cog = mloc.GetInverse();
+	this->TrasformLocalToParent(this->auxref_to_cog, this->auxref_to_abs);
+	// or, also, using overloaded operators for frames: 
+	//   *this->auxref_to_abs = this->auxref_to_cog.GetInverse() >> this;
+
+
+	// Restore marker/forces positions, keeping unchanged respect to aux ref.
+	ChFrameMoving<> cog_oldnew = old_cog_to_abs >> new_cog_to_abs.GetInverse();
+
+	HIER_MARKER_INIT
+	while (HIER_MARKER_NOSTOP)
+	{
+		MARKpointer->ConcatenatePreTransformation(cog_oldnew);
+		MARKpointer->Update(this->ChTime);
+
+		HIER_MARKER_NEXT
+	}
+
+	// Forces: ?? to do...
+	/*
+	HIER_FORCE_INIT
+	while (HIER_FORCE_NOSTOP)
+	{	
+		FORCEpointer->
+		FORCEpointer->Update (mytime);
+		
+		HIER_FORCE_NEXT
+	}
+	*/
+};
+
+void ChBodyAuxRef::SetFrame_REF_to_abs(const ChFrame<>& mfra)
+{
+	mfra.TrasformLocalToParent(this->auxref_to_cog.GetInverse(), *this);
+	// or, also, using overloaded operators for frames: 
+	//   *this = this->auxref_to_cog.GetInverse() >> mfra;
+}
+
+
+
+void ChBodyAuxRef::Update()
+{
+		// update parent class
+	ChBody::Update();
+
+		// update own data
+	this->TrasformLocalToParent(this->auxref_to_cog, this->auxref_to_abs);
+}
+
+
+
+//////// FILE I/O
+
+void ChBodyAuxRef::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChBody::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << auxref_to_cog;
+	mstream << auxref_to_abs;
+}
+
+void ChBodyAuxRef::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChBody::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> auxref_to_cog;
+	mstream >> auxref_to_abs;
+}
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChBodyAuxRef.h b/SRC/ChronoEngine/physics/ChBodyAuxRef.h
new file mode 100644
index 0000000..ec9b9b9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChBodyAuxRef.h
@@ -0,0 +1,131 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHBODYAUXREF_H
+#define CHBODYAUXREF_H
+
+//////////////////////////////////////////////////
+//
+//   ChBodyAuxRef.h
+//
+//   Class for rigid bodie with an auxiliary reference
+//   that is separated from the COG.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChBody.h"
+
+
+
+namespace chrono
+{
+
+
+
+
+/// Class for rigid bodies with an auxiliary reference that can be used
+/// for the collision shapes and marker positions; that reference can be
+/// different from the center of gravity (COG), differently from the
+/// base class ChBody where the COG is used also as reference.
+/// Because of the auxilary reference, this type of rigid bodies can be
+/// a bit less efficient thatn the ChBody simple class. 
+
+class ChApi ChBodyAuxRef : public ChBody {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChBodyAuxRef,ChBody);
+
+	
+private:
+			//
+	  		// DATA
+			//
+	ChFrameMoving<> auxref_to_cog;	// auxiliary REF location, relative to COG
+	ChFrameMoving<> auxref_to_abs;	// for speeding up code: REF location relative to abs coords (needs Update() )
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a rigid body.
+	ChBodyAuxRef ();
+				/// Destructor
+	~ChBodyAuxRef ();
+
+				/// Copy from another ChBodyAuxRef. 
+				/// NOTE: all settings of the body are copied, but the
+				/// child hierarchy of ChForces and ChMarkers (if any) are NOT copied.
+	void Copy(ChBodyAuxRef* source);
+
+
+				/// Get the location of the auxiliary reference respect to COG.
+				/// Viceversa, if you need to know the COG respect to auxiliary 
+				/// reference, use GetREF_to_COG().GetInverse() 
+	virtual const ChFrame<>& GetFrame_REF_to_COG() {return auxref_to_cog;};
+
+				/// Set the location of the auxiliary reference respect to COG,
+				/// and do not move the body absolute COG (the COG is fixed).
+	virtual void SetFrame_REF_to_COG(const ChFrame<>& mloc) {auxref_to_cog = mloc;};
+
+				/// Set the location of the COG respect to the auxiliary reference,
+				/// and move the body absolute COG (the REF is fixed).
+				/// Note! the position of contained ChMarker objects, if any, is 
+				/// not changed respect to the reference!
+	virtual void SetFrame_COG_to_REF(const ChFrame<>& mloc);
+
+				/// Set the absolute location of the auxiliary reference, 
+				/// moving the entire body. The body COG is rigidly moved as well.
+	virtual void SetFrame_REF_to_abs(const ChFrame<>& mfra);
+
+				/// Get the rigid body coordinate system that is used for
+				/// defining the collision shapes and the ChMarker objects, respect
+				/// to the absolute system.
+				/// In this ChBodyAuxRef class, differently form ChBody, this is
+				/// not necessarily the same reference of GetFrame_COG_to_abs().
+	virtual ChFrame<>& GetFrame_REF_to_abs() {return auxref_to_abs;}
+
+				/// Update all auxiliary data of the rigid body and of
+				/// its children (markers, forces..)
+	virtual void Update ();
+
+
+
+			//
+			// STREAMING
+			//
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChBodyDEM.cpp b/SRC/ChronoEngine/physics/ChBodyDEM.cpp
new file mode 100644
index 0000000..8b2ffeb
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChBodyDEM.cpp
@@ -0,0 +1,163 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChBodyDEM.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "core/ChTrasform.h"
+#include "physics/ChBodyDEM.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChSystem.h"
+
+#include "physics/ChExternalObject.h"
+#include "collision/ChCModelBulletDEM.h"
+#include "core/ChLinearAlgebra.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChBodyDEM> a_registration_ChBodyDEM;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SOLID BODIES
+
+
+ChBodyDEM::ChBodyDEM ()
+{
+	collision_model=ChBodyDEM::InstanceCollisionModel();
+
+	//kn=392400.0;
+	//gn=420.0;
+	kn=2e5; //2e5		//2e8
+	gn=7.5e2;   //5		//15000
+	kt=kn;
+}
+
+
+ChBodyDEM::~ChBodyDEM ()
+{
+
+}
+
+void ChBodyDEM::Copy(ChBodyDEM* source)
+{
+		// copy the parent class data...
+	ChBody::Copy(source);
+
+	kn = source->kn;
+	gn = source->gn;
+	kt = source->kt;
+}
+
+
+ChCollisionModel* ChBodyDEM::InstanceCollisionModel(){
+	ChCollisionModel* collision_model_t= (ChModelBulletDEM*) new ChModelBulletDEM();
+	((ChModelBulletDEM*)collision_model_t)->SetBody(this);
+	return collision_model_t;
+}
+
+//////// FILE I/O
+
+void ChBodyDEM::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChBody::StreamOUT(mstream);
+
+	mstream << kn;
+	mstream << gn;
+	mstream << kt;
+}
+
+void ChBodyDEM::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChBody::StreamIN(mstream);
+
+	float ffoo;
+
+	mstream >> ffoo;		SetSpringCoefficient(ffoo);
+	mstream >> ffoo;		SetDampingCoefficient(ffoo);
+	mstream >> kt;
+}
+
+
+#define CH_CHUNK_END_DEM 98765
+
+int ChBodyDEM::StreamINall  (ChStreamInBinary& m_file)
+{
+	int mchunk = 0;
+
+	// 1) read body class data...
+ 
+	ChBody::StreamINall(m_file);
+
+	m_file >> kn;
+	m_file >> gn;
+	m_file >> kt;
+
+	m_file >> mchunk; 
+
+	if (mchunk != CH_CHUNK_END_DEM) return 0;
+
+
+	return 1;
+}
+
+
+int ChBodyDEM::StreamOUTall  (ChStreamOutBinary& m_file)
+{
+
+	// 1) read body class data...
+	ChBody::StreamOUTall(m_file);
+
+	m_file << kn;
+	m_file << gn;
+	m_file << kt;
+
+	m_file << (int)CH_CHUNK_END_DEM;
+
+	return 1;
+}
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChBodyDEM.h b/SRC/ChronoEngine/physics/ChBodyDEM.h
new file mode 100644
index 0000000..66c29bb
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChBodyDEM.h
@@ -0,0 +1,153 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHBODYDEM_H
+#define CHBODYDEM_H
+
+//////////////////////////////////////////////////
+//
+//   ChBodyDEM.h
+//
+//   Class for rigid bodies, that is rigid moving
+//   parts with mass and collision geometry 
+//   which interact through DEM approach.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "physics/ChBody.h"
+#include "core/ChFrameMoving.h"
+#include "core/ChShared.h"
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChForce.h"
+#include "physics/ChMarker.h"
+#include "lcp/ChLcpVariablesBodyOwnMass.h"
+#include "lcp/ChLcpConstraint.h"
+
+
+
+namespace chrono
+{
+
+using namespace collision;
+
+
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+///
+/// Class for rigid bodies. A rigid body is an entity which
+/// can move in 3D space, and can be constrained to other rigid
+/// bodies using ChLink objects.
+/// These objects have mass and inertia properties. A shape can also
+/// be associated to the body, for collision detection.
+///
+
+class ChApi ChBodyDEM: public ChBody {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChBodyDEM, ChBody);
+
+
+private:
+			//
+	  		// DATA
+			//
+
+	float kn;	// normal spring constant for DEM contacts
+	float gn;   // normal damping constant for DEM contacts
+	float kt;   // tangential spring constant for DEM contacts
+	 
+
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a rigid body.
+	ChBodyDEM ();
+				/// Destructor
+	~ChBodyDEM ();
+
+				/// Copy from another ChBodyDEM. 
+				/// NOTE: all settings of the body are copied, but the
+				/// child hierarchy of ChForces and ChMarkers (if any) are NOT copied.
+	void Copy(ChBodyDEM* source);
+
+				/// Instantiate the collision model
+	virtual ChCollisionModel* InstanceCollisionModel();
+
+				/// The spring coefficient for DEM contacts.
+				/// Default 392400.0
+	float  GetSpringCoefficient() {return kn;}
+	void   SetSpringCoefficient(float mval) {kn = mval;}
+				
+				/// The damping coefficient for DEM contacts.
+				/// Default 420.0
+	float  GetDampingCoefficient() {return gn;}
+	void   SetDampingCoefficient(float mval) {gn = mval;}
+
+				/// The spring coefficient for DEM friction.
+				/// Default 392400.0
+	float  GetSpringCoefficientTangential() {return kt;}
+	void   SetSpringCoefficientTangential(float mval) {kt = mval;}
+
+				/// accumulate force on this body, or reset the force to zero
+	//void AccumulateForce(ChVector<> ff) {Xforce+=ff;}
+	//void ResetBodyForce() {Xforce = VNULL;}
+	//void AccumulateTorque(ChVector<> tt) {Xtorque+=tt;}
+	//void ResetBodyTorque() {Xtorque = VNULL;}
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+				/// Save data, including child markers and child forces
+	int StreamOUTall (ChStreamOutBinary& m_file);
+				/// Read data, including child markers and child forces
+	int StreamINall  (ChStreamInBinary&  m_file);
+
+};
+
+
+
+typedef ChSharedPtr<ChBodyDEM> ChSharedBodyDEMPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChConstraint.cpp b/SRC/ChronoEngine/physics/ChConstraint.cpp
new file mode 100644
index 0000000..2e3fec3
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChConstraint.cpp
@@ -0,0 +1,333 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChConstraint.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+
+#include "physics/ChConstraint.h"
+
+
+namespace chrono 
+{
+
+
+
+////////////////////////////////////
+//
+// CLASS  ChConstraint
+//
+////////////////////////////////////
+
+
+ChConstraint::ChConstraint() 
+{
+	valid = false; 
+	disabled = false;
+	C=NULL;
+
+	Reset_Cn(Get_Cn()); 
+};
+
+
+ChConstraint::~ChConstraint()
+{
+	if (C) delete C; C=NULL;
+}
+
+		// Sets the number of equations in this constraints (reset the 
+		// size of the C residual vector).
+int ChConstraint::Reset_Cn(int mCn)
+{
+	if (mCn >0)
+	{
+		Cn = mCn;
+		if (C) {delete C; C=NULL;}
+		C= new ChMatrixDynamic<>(Cn,1);
+	}
+	else 
+	{
+		Cn = 0;
+		if (C) {delete C; C=NULL;} 
+		C= NULL;
+	}
+	return Cn;
+}
+
+
+
+
+////////////////////////////////////
+//
+// CLASS  ChConstraint_Chf
+//
+////////////////////////////////////
+
+ChConstraint_Chf::ChConstraint_Chf()
+{
+	root_function = NULL;
+}
+
+ChConstraint_Chf::ChConstraint_Chf(ChFunction* mRootFunct, char* mTreeIDs)
+{
+	this->root_function = mRootFunct;
+	this->target_function.SetTreeIDs(mTreeIDs);
+	this->target_function.RestoreReference(this->root_function);
+}
+
+bool ChConstraint_Chf::RestoreReferences(ChFunction* mroot) 
+{
+	root_function = mroot; 
+	if (mroot)
+	{
+		valid = this->target_function.RestoreReference(mroot);
+		return (valid);
+	}
+	else
+	{
+		return (valid=false);
+	}
+};
+
+
+
+////////////////////////////////////
+//
+// CLASS  ChConstraint_Chf_ImposeVal
+//
+////////////////////////////////////
+
+ChConstraint_Chf_ImposeVal::ChConstraint_Chf_ImposeVal(ChFunction* mRootFunct, char* mTreeIDs, double mval, double mtime)
+{
+	this->target_function.SetTreeIDs(mTreeIDs);
+	this->RestoreReferences(mRootFunct);
+
+	this->SetT(mtime);
+	this->SetValue(mval);
+	this->Reset_Cn(Get_Cn());
+	this->Update();
+}
+
+bool ChConstraint_Chf_ImposeVal::Update()
+{
+	// INHERIT parent behaviour:
+	if (!ChConstraint_Chf::Update()) return false;
+
+	// Implement method:
+
+			// CONSTRAINT EQUATION (residual of mc=0);
+	double mc= this->Get_target_function()->Get_y(this->T) - this->value;
+
+	if (C)
+		C->SetElement(0,0, mc);
+
+	return true;
+}
+
+
+ 
+
+
+
+
+////////////////////////////////////
+//
+// CLASS  ChConstraint_Chf_Continuity
+//
+////////////////////////////////////
+
+ChConstraint_Chf_Continuity::ChConstraint_Chf_Continuity(ChFunction* mRootFunct, char* mTreeIDs, int cont_ord, int interf_num)
+{
+	this->target_function.SetTreeIDs(mTreeIDs);
+	this->RestoreReferences(mRootFunct);
+
+	this->SetContinuityOrder(cont_ord);
+	this->SetInterfaceNum(interf_num);
+
+	this->Reset_Cn(Get_Cn());
+	this->Update();
+}
+	
+
+bool ChConstraint_Chf_Continuity::Update()
+{
+	// INHERIT parent behaviour:
+	if (!ChConstraint_Chf::Update()) return false;
+
+	// Implement method:
+ 
+		// a- cast target function to sequence, if correct
+	if (this->Get_target_function()->Get_Type()!=FUNCT_SEQUENCE)
+		return false;
+
+	ChFunction_Sequence* mfun = (ChFunction_Sequence*) this->Get_target_function();
+
+		// b- computes the time instant of discontinuity
+	double mt;
+	double mc=0;
+	if ((this->interface_num > mfun->Get_list()->Count() ) || 
+		(this->interface_num < 0) )								// NO!out of range... 
+	{
+		if (C) C->SetElement(0,0, 0.0);
+		return false;
+	}
+	if (this->interface_num == mfun->Get_list()->Count())		// ok, last discontinuity
+	{
+		mt=mfun->GetNthNode(this->interface_num)->t_end;
+	}
+
+	mt= mfun->GetNthNode(this->interface_num)->t_start;	// ok, inner interface
+		
+			// CONSTRAINT EQUATION (residual of mc=0);
+	double mstep = 1e-9;
+	double v_a, v_b;
+	switch (this->continuity_order)
+	{
+	case 0:	// C0
+		v_a = mfun->Get_y(mt-mstep);
+		v_b = mfun->Get_y(mt+mstep);
+		break;
+	case 1:	// C1
+		v_a = mfun->Get_y_dx(mt-mstep);
+		v_b = mfun->Get_y_dx(mt+mstep);
+		break;
+	case 2:	// C2
+		v_a = mfun->Get_y_dxdx(mt-mstep);
+		v_b = mfun->Get_y_dxdx(mt+mstep);
+		break;
+	default: 
+		v_a=v_b=0;
+	}
+	mc = v_b - v_a;  
+
+	if (C)
+		C->SetElement(0,0, mc);
+
+	return true;
+}
+
+
+
+
+
+
+////////////////////////////////////
+//
+// CLASS  ChConstraint_Chf_HorDistance
+//
+////////////////////////////////////
+
+ChConstraint_Chf_HorDistance::ChConstraint_Chf_HorDistance(ChFunction* mRootFunct, char* mTreeIDs, int mhA, int mhB)
+{
+	this->target_function.SetTreeIDs(mTreeIDs);
+	this->RestoreReferences(mRootFunct);
+
+	this->SetHandleA(mhA);
+	this->SetHandleB(mhB);
+
+	this->Reset_Cn(Get_Cn());
+	this->Update();
+}
+	
+
+bool ChConstraint_Chf_HorDistance::Update()
+{
+	// INHERIT parent behaviour:
+	if (!ChConstraint_Chf::Update()) return false;
+
+	// Implement method:
+ 
+		// a- cast target function to sequence, if correct
+	if (this->Get_target_function()->Get_Type()!=FUNCT_SEQUENCE)
+		return false;
+
+	ChFunction_Sequence* mfun = (ChFunction_Sequence*) this->Get_target_function();
+
+		// b- computes the time instants of the two handles
+
+	double x_a= mfun->GetNthNode(this->handleA)->t_start;	// ok, first  handle X value
+	double x_b= mfun->GetNthNode(this->handleB)->t_start;	// ok, second handle X value
+
+			// CONSTRAINT EQUATION (residual of mc=0);
+
+	double mc = x_b - x_a;  
+
+	if (C)
+		C->SetElement(0,0, mc);
+
+	return true;
+}
+
+
+////////////////////////////////////
+//
+// CLASS  ChConstraint_Chf_VertDistance
+//
+////////////////////////////////////
+
+ChConstraint_Chf_VertDistance::ChConstraint_Chf_VertDistance(ChFunction* mRootFunct, char* mTreeIDs, int mhA, int mhB)
+{
+	this->target_function.SetTreeIDs(mTreeIDs);
+	this->RestoreReferences(mRootFunct);
+
+	this->SetHandleA(mhA);
+	this->SetHandleB(mhB);
+
+	this->Reset_Cn(Get_Cn());
+	this->Update();
+}
+	
+
+bool ChConstraint_Chf_VertDistance::Update()
+{
+	// INHERIT parent behaviour:
+	if (!ChConstraint_Chf::Update()) return false;
+
+	// Implement method:
+    
+			// a- cast target function to sequence, if correct
+	if (this->Get_target_function()->Get_Type()!=FUNCT_SEQUENCE)
+		return false;
+
+	ChFunction_Sequence* mfun = (ChFunction_Sequence*) this->Get_target_function();
+
+		// b- computes the time instants of the two handles
+
+	double x_a= mfun->GetNthNode(this->handleA)->t_start;	// ok, first  handle X value
+	double x_b= mfun->GetNthNode(this->handleB)->t_start;	// ok, second handle X value
+	
+	double y_a= mfun->Get_y(x_a);
+	double y_b= mfun->Get_y(x_b);
+
+			// CONSTRAINT EQUATION (residual of mc=0);
+
+	double mc = y_b - y_a;  
+
+	if (C)
+		C->SetElement(0,0, mc);
+
+	return true;
+}
+
+
+} // END_OF_NAMESPACE____
+
+	
+
diff --git a/SRC/ChronoEngine/physics/ChConstraint.h b/SRC/ChronoEngine/physics/ChConstraint.h
new file mode 100644
index 0000000..fca526d
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChConstraint.h
@@ -0,0 +1,302 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONSTRAINT_H
+#define CHCONSTRAINT_H
+
+//////////////////////////////////////////////////
+//  
+//   ChConstraints.h
+//
+//   Class for generic constraint, (NOT MECHANICAL)
+//   ex. for constrained optimizations etc. 
+// 
+//   Note that the 'mechanical' constraints are 
+//   defined in another header, i.e. ChLink.h,
+//   and they are a different stuff.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+
+#include <math.h>
+
+#include "physics/ChRef.h"
+#include "core/ChApiCE.h"
+
+namespace chrono 
+{
+
+
+
+/// Class for basic algebraic constraints (not to be confused with
+/// ChLink objects, which are complex kinematical constraints between rigid
+/// bodies in 3D, containing ChLcpConstraint objects)
+///
+/// This is the base data for algebraic constraints. 
+/// The base implemetation is basically _useless_ unless it has some 
+/// inherited implementation (see other classes below)
+///
+/// Child classes should implement at least Update() RestoreReferences() Get_Cn().
+
+
+class ChApi ChConstraint {
+
+ private:
+
+ protected:
+			// some flags
+	bool valid;
+	bool disabled;
+
+			// constraints equations in this constraint
+	int  Cn; 
+			// residual matrix
+	ChMatrix<>* C;
+
+ public:
+
+	ChConstraint();
+	~ChConstraint();
+
+		/// Tells if the constraint data is currently valid.
+		/// Instead of implementing it, child classes may simply
+		/// set valif=false (or true) depending on the result of their
+	    /// implementations of RestoreReference();
+	virtual bool IsValid() {return valid;}
+		
+		/// Tells if the constraint is currently turned on or off by the user.
+	virtual bool IsDisabled() {return disabled;}
+	virtual void SetDisabled(bool mon) {disabled = mon;}
+
+		/// Tells if the constraint is currently active, in general, 
+		/// that is tells if it must be included into the system solver or not.
+	virtual bool IsActive() {return (valid & !disabled & (Cn>0));}
+
+
+	
+		/// Returns the matrix of residuals (a column vector with Cn elements)
+		/// If constraint is not active, returns NULL because no equations can be used.
+	virtual ChMatrix<>* Get_C() {if (IsActive()) return C; else return NULL;}
+
+
+		/// ---TO IMPLEMENT-- w.overriding
+		/// Returns the number of equations in this constraints (the 
+		/// size of the C residual vector)
+	virtual int Get_Cn() {return 0;}
+		/// Changes the number of equations in this constraints (reset the 
+		/// size of the C residual vector).
+	virtual int Reset_Cn(int mCn);
+
+		/// ---TO IMPLEMENT-- w.overloading
+		/// This may be overloaded by child classes. Argument should be
+		/// the 'database' where the reference restoring takes place.
+		/// Should return false if referencing was not possible.
+		/// Should set valid=true/false depending on referencing success.
+	virtual bool RestoreReferences() {return true;};
+
+		/// ---TO IMPLEMENT-- w.overloading
+		/// This MUST be overloaded by child classes.
+		/// It should compute the residuals (vector 'C') of the 
+		/// constraint equations, where C=0 is for satisfied constraints.
+		/// Should return false if updating was not possible.
+	virtual bool Update() {if (IsActive()) return true; else return false;};
+};
+		
+
+
+
+
+
+
+/// Constraint between parameters in a ChFunction
+///
+/// This is the base data for all types of constraints which 
+/// define relations between parameters of a ChFunction (mostly, of
+/// type ChFunctionSequence).
+
+
+
+class ChApi ChConstraint_Chf : public ChConstraint{
+
+ private:
+
+ protected:
+	ChFunction* root_function;
+
+	ChRefFunctionSegment target_function;
+
+ public:
+	ChConstraint_Chf();
+	ChConstraint_Chf(ChFunction* mRootFunct, char* mTreeIDs);
+		
+		// for easy access to inner data
+	ChFunction* Get_root_function() {return root_function;}
+	ChFunction* Get_target_function() {return target_function.GetFunction();}
+		// if needed, for accessing the target funct.reference and change the tree-IDs, for new target..
+	ChRefFunctionSegment* Get_target_reference() {return &target_function;}
+
+		// --Note: this may be overloaded by children-
+		// (Child classes may need also to restore references in other encapsulated ChRef objects).
+	virtual bool RestoreReferences(ChFunction* mroot);
+
+};
+		
+
+
+
+
+///
+/// Algebraic constraint on ChFunctions, of the type  y(T)=A
+/// Impose a value of the function (or its derivative) at given time T.
+///
+
+
+class ChApi ChConstraint_Chf_ImposeVal : public ChConstraint_Chf{
+
+ private:
+	double T;
+	double value;
+	int derivation_order;
+
+ protected:
+
+ public:
+	ChConstraint_Chf_ImposeVal()  {T=0; value=0; derivation_order=0;};
+	ChConstraint_Chf_ImposeVal(ChFunction* mRootFunct, char* mTreeIDs, double mtime, double mval);
+	
+	double GetT()          {return T;}
+	void   SetT(double mT) {T=mT; }
+	double GetValue()          {return value;}
+	void   SetValue(double mv) {value=mv; }
+	int    GetDerivationOrder()			{return derivation_order;}
+	void   SetDerivationOrder(int mo)	{derivation_order = mo; }
+
+	int  Get_Cn() {return 1;};
+
+	//virtual bool RestoreReferences(ChFunction* mroot);
+	
+	virtual bool Update();		// --> see in .cpp
+};
+
+
+
+///
+/// Algebraic constraint on ChFunctions,
+/// Impose continuity between two function segments
+///
+
+
+class ChApi ChConstraint_Chf_Continuity : public ChConstraint_Chf{
+
+ private:
+	int continuity_order;
+	int interface_num;
+ protected:
+
+ public:
+	ChConstraint_Chf_Continuity() {continuity_order=0; interface_num=0;};
+	ChConstraint_Chf_Continuity(ChFunction* mRootFunct, char* mTreeIDs, int cont_ord, int interf_num);
+	
+	int    GetInterfaceNum()          {return interface_num;}
+	void   SetInterfaceNum(int mi) {interface_num = mi;}
+	int    GetContinuityOrder()			{return continuity_order;}
+	void   SetContinuityOrder(int mc)	{continuity_order = mc; }
+
+	int  Get_Cn() {return 1;};
+
+	//virtual bool RestoreReferences(ChFunction* mroot);
+	
+	virtual bool Update();		// --> see in .cpp
+};
+
+
+
+///
+/// Algebraic constraint on ChFunctions.
+/// Impose handle distance along X axis
+///
+
+
+class ChApi ChConstraint_Chf_HorDistance : public ChConstraint_Chf{
+
+ private:
+
+	double distance;
+	int handleA;
+	int handleB;
+
+ protected:
+
+ public:
+	ChConstraint_Chf_HorDistance() {distance=1;};
+	ChConstraint_Chf_HorDistance(ChFunction* mRootFunct, char* mTreeIDs, int mhA, int mhB);
+
+	double GetDistance()          {return distance;}
+	void   SetDistance(double md) {distance = md;}
+
+	int    GetHandleA()          {return handleA;}
+	int    GetHandleB()          {return handleB;}
+	void   SetHandleA(int mh) {handleA = mh;}
+	void   SetHandleB(int mh) {handleB = mh;}
+
+	//virtual bool RestoreReferences(ChFunction* mroot);
+	
+	virtual bool Update();		// --> see in .cpp
+};
+
+
+
+///
+/// Algebraic constraint on ChFunctions.
+/// Impose segment vertical separation on Y axis, between two handles
+///
+
+class ChApi ChConstraint_Chf_VertDistance : public ChConstraint_Chf{
+
+ private:
+
+	double distance;
+	int handleA;
+	int handleB;
+
+ protected:
+
+ public:
+	ChConstraint_Chf_VertDistance() {distance=1;};
+	ChConstraint_Chf_VertDistance(ChFunction* mRootFunct, char* mTreeIDs, int mhA, int mhB);
+
+	double GetDistance()          {return distance;}
+	void   SetDistance(double md) {distance = md;}
+
+	int    GetHandleA()          {return handleA;}
+	int    GetHandleB()          {return handleB;}
+	void   SetHandleA(int mh) {handleA = mh;}
+	void   SetHandleB(int mh) {handleB = mh;}
+
+	//virtual bool RestoreReferences(ChFunction* mroot);
+	
+	virtual bool Update();		// --> see in .cpp
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of ChConstraint.h 
diff --git a/SRC/ChronoEngine/physics/ChContact.cpp b/SRC/ChronoEngine/physics/ChContact.cpp
new file mode 100644
index 0000000..42ec7df
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContact.cpp
@@ -0,0 +1,341 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContact.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContact.h"
+#include "physics/ChSystem.h"
+#include "lcp/ChLcpConstraintTwoContactN.h"
+#include "collision/ChCModelBulletBody.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+ChContact::ChContact ()
+{ 
+	Nx.SetTangentialConstraintU(&Tu);
+	Nx.SetTangentialConstraintV(&Tv);
+}
+
+ChContact::ChContact (	collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		  ///< pass A frame
+						const ChFrame<>* frameB,		  ///< pass B frame
+						const ChVector<>& vpA,		  ///< pass coll.point on A
+						const ChVector<>& vpB,		  ///< pass coll.point on B
+						const ChVector<>& vN, 		  ///< pass coll.normal, respect to A
+						double mdistance,		  ///< pass the distance (negative for penetration)
+						float* mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				)
+{ 
+	Nx.SetTangentialConstraintU(&Tu);
+	Nx.SetTangentialConstraintV(&Tv);
+
+	Reset(	mmodA, mmodB,
+			varA, ///< pass A vars
+			varB, ///< pass B vars
+			frameA,		  ///< pass A frame
+			frameB,		  ///< pass B frame
+			vpA,		  ///< pass coll.point on A
+			vpB,		  ///< pass coll.point on B
+			vN, 		  ///< pass coll.normal, respect to A
+			mdistance,		  ///< pass the distance (negative for penetration)
+			mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+			mmaterial
+				);
+}
+
+ChContact::~ChContact ()
+{
+
+}
+
+void ChContact::Reset(	collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+					    const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		  ///< pass A frame
+						const ChFrame<>* frameB,		  ///< pass B frame
+						const ChVector<>& vpA,		  ///< pass coll.point on A
+						const ChVector<>& vpB,		  ///< pass coll.point on B
+						const ChVector<>& vN, 		  ///< pass coll.normal, respect to A
+						double mdistance,		  ///< pass the distance (negative for penetration)
+						float* mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				)
+{
+	assert (varA);
+	assert (varB);
+	assert (frameA);
+	assert (frameB);
+
+	this->modA = mmodA;
+	this->modB = mmodB;
+
+	Nx.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesBody*>(varB));
+	Tu.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesBody*>(varB));
+	Tv.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesBody*>(varB));
+
+	Nx.SetFrictionCoefficient(mmaterial.static_friction);
+	Nx.SetCohesion(mmaterial.cohesion);
+	//GetLog() <<"SetCohesion = " << Nx.GetCohesion() << "\n";
+	this->restitution = mmaterial.restitution;
+	this->dampingf = mmaterial.dampingf;
+	this->compliance = mmaterial.compliance;
+	this->complianceT = mmaterial.complianceT;
+
+	ChVector<> VN = vN;
+	ChVector<double> Vx, Vy, Vz;
+	ChVector<double> singul(VECT_Y);
+	XdirToDxDyDz(&VN, &singul, &Vx,  &Vy, &Vz);
+	contact_plane.Set_A_axis(Vx,Vy,Vz);
+
+	this->p1 = vpA;
+	this->p2 = vpB;
+	this->normal = vN;
+	this->norm_dist = mdistance;
+	this->reactions_cache = mreaction_cache;
+
+	ChVector<> Pl1 = frameA->TrasformParentToLocal(p1);
+	ChVector<> Pl2 = frameB->TrasformParentToLocal(p2);
+
+			// compute jacobians
+	ChMatrix33<> Jx1, Jx2, Jr1, Jr2;
+	ChMatrix33<> Ps1, Ps2, Jtemp;
+	Ps1.Set_X_matrix(Pl1);
+	Ps2.Set_X_matrix(Pl2);
+
+	Jx1.CopyFromMatrixT(this->contact_plane);
+	Jx2.CopyFromMatrixT(this->contact_plane);
+	Jx1.MatrNeg();
+
+	Jtemp.MatrMultiply(*( const_cast<ChFrame<>*>(frameA)->GetA()), Ps1);
+	Jr1.MatrTMultiply(this->contact_plane, Jtemp);
+
+	Jtemp.MatrMultiply(*( const_cast<ChFrame<>*>(frameB)->GetA()), Ps2);
+	Jr2.MatrTMultiply(this->contact_plane, Jtemp);
+	Jr2.MatrNeg();
+
+	Nx.Get_Cq_a()->PasteClippedMatrix(&Jx1, 0,0, 1,3, 0,0);
+	Tu.Get_Cq_a()->PasteClippedMatrix(&Jx1, 1,0, 1,3, 0,0);
+	Tv.Get_Cq_a()->PasteClippedMatrix(&Jx1, 2,0, 1,3, 0,0);
+	Nx.Get_Cq_a()->PasteClippedMatrix(&Jr1, 0,0, 1,3, 0,3);
+	Tu.Get_Cq_a()->PasteClippedMatrix(&Jr1, 1,0, 1,3, 0,3);
+	Tv.Get_Cq_a()->PasteClippedMatrix(&Jr1, 2,0, 1,3, 0,3);
+
+	Nx.Get_Cq_b()->PasteClippedMatrix(&Jx2, 0,0, 1,3, 0,0);
+	Tu.Get_Cq_b()->PasteClippedMatrix(&Jx2, 1,0, 1,3, 0,0);
+	Tv.Get_Cq_b()->PasteClippedMatrix(&Jx2, 2,0, 1,3, 0,0);
+	Nx.Get_Cq_b()->PasteClippedMatrix(&Jr2, 0,0, 1,3, 0,3);
+	Tu.Get_Cq_b()->PasteClippedMatrix(&Jr2, 1,0, 1,3, 0,3);
+	Tv.Get_Cq_b()->PasteClippedMatrix(&Jr2, 2,0, 1,3, 0,3);
+
+	react_force = VNULL;
+
+	//***TO DO***  C_dt? C_dtdt? (may be never used..)
+}
+
+
+
+ChCoordsys<> ChContact::GetContactCoords()
+{
+	ChCoordsys<> mcsys;
+	ChQuaternion<float> mrot = this->contact_plane.Get_A_quaternion();
+	mcsys.rot.Set(mrot.e0, mrot.e1, mrot.e2, mrot.e3);
+	mcsys.pos = this->p2;
+	return mcsys;
+}
+
+
+ 
+
+
+void ChContact::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	mdescriptor.InsertConstraint(&Nx);
+	mdescriptor.InsertConstraint(&Tu);
+	mdescriptor.InsertConstraint(&Tv); 
+}
+
+void ChContact::ConstraintsBiReset()
+{
+	Nx.Set_b_i(0.);
+	Tu.Set_b_i(0.);
+	Tv.Set_b_i(0.);
+}
+ 
+void ChContact::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	bool bounced = false;
+
+	// Elastic Restitution model (use simple Newton model with coeffcient e=v(+)/v(-))
+	// Note that this works only if the two connected items are two ChBody.
+
+	ChModelBulletBody* bm1 = dynamic_cast<ChModelBulletBody*>(this->modA);
+	ChModelBulletBody* bm2 = dynamic_cast<ChModelBulletBody*>(this->modB);
+	if (bm1&&bm2)
+	{
+		ChBody* bb1 = bm1->GetBody();
+		ChBody* bb2 = bm2->GetBody();
+		if (this->restitution)
+		{
+			//compute normal rebounce speed 
+			double Ct = 0;
+	//GetLog()<< "Restitution " << (int)this << "\n";
+			Vector Pl1 = bb1->Point_World2Body(&this->p1);
+			Vector Pl2 = bb2->Point_World2Body(&this->p2);
+			Vector V1_w = bb1->PointSpeedLocalToParent(Pl1);
+			Vector V2_w = bb2->PointSpeedLocalToParent(Pl2);
+			Vector Vrel_w = V2_w-V1_w;
+			Vector Vrel_cplane = this->contact_plane.MatrT_x_Vect(Vrel_w);
+		 
+			double neg_rebounce_speed = Vrel_cplane.x * this->restitution;
+			if (neg_rebounce_speed < -  bb1->GetSystem()->GetMinBounceSpeed() )
+			{
+				// CASE: BOUNCE
+				bounced = true;
+				Nx.Set_b_i( Nx.Get_b_i() + neg_rebounce_speed );
+			}
+		}
+	}
+ 
+	if (!bounced)
+	{
+		// CASE: SETTLE (most often, and also default if two colliding items are not two ChBody)
+
+		if (this->compliance)
+		{
+			//  inverse timestep is factor
+			double h = 1.0/factor;
+
+			double alpha=this->dampingf; // [R]=alpha*[K]
+			double inv_hpa = 1.0/(h+alpha); // 1/(h+a)
+			double inv_hhpa = 1.0/(h*(h+alpha)); // 1/(h*(h+a)) 
+
+			Nx.Set_cfm_i( (inv_hhpa)*this->compliance  ); // was (inv_hh)* ...   //***TEST DAMPING***//
+			Tu.Set_cfm_i( (inv_hhpa)*this->complianceT );
+			Tv.Set_cfm_i( (inv_hhpa)*this->complianceT );
+
+    //GetLog()<< "compliance " << (int)this << "  compl=" << this->compliance << "  damping=" << this->dampingf << "  h=" << h << "\n";
+
+			// no clamping of residual
+			Nx.Set_b_i( Nx.Get_b_i() + inv_hpa * this->norm_dist  ); // was (inv_h)* ...   //***TEST DAMPING***//
+		}
+		else
+		{
+	//GetLog()<< "rigid " << (int)this << "  recov_clamp=" << recovery_clamp << "\n";
+			if (do_clamp)
+				if (this->Nx.GetCohesion())
+					Nx.Set_b_i( Nx.Get_b_i() + ChMin( 0.0, ChMax (factor * this->norm_dist, -recovery_clamp) ) );
+				else
+					Nx.Set_b_i( Nx.Get_b_i() + ChMax (factor * this->norm_dist, -recovery_clamp)  );
+			else
+				Nx.Set_b_i( Nx.Get_b_i() + factor * this->norm_dist  );
+		}
+		
+	}
+
+	//Tu.Set_b_i(Tu.Get_b_i +0.);  // nothing to add in tangential dir
+	//Tv.Set_b_i(Tv.Get_b_i +0.);
+}
+
+void ChContact::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	react_force.x = Nx.Get_l_i() * factor;  
+	react_force.y = Tu.Get_l_i() * factor;
+	react_force.z = Tv.Get_l_i() * factor;
+}
+
+
+void  ChContact::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	// Fetch the last computed impulsive reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP speed solver): 
+	if (this->reactions_cache)
+	{
+		Nx.Set_l_i(reactions_cache[0]);
+		Tu.Set_l_i(reactions_cache[1]);  
+		Tv.Set_l_i(reactions_cache[2]);
+	}
+	//GetLog() << "++++      " << (int)this << "  fetching N=" << (double)mn <<"\n"; 
+}
+
+void  ChContact::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	// Fetch the last computed 'positional' reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP position stabilization solver):
+	if (this->reactions_cache)
+	{
+		Nx.Set_l_i(reactions_cache[3]);
+		Tu.Set_l_i(reactions_cache[4]);  
+		Tv.Set_l_i(reactions_cache[5]);
+	}
+}
+
+void  ChContact::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	// Store the last computed reactions into the persistent contact manifold (might
+	// be used for warm starting CCP the speed solver):
+	if (reactions_cache)
+	{
+		reactions_cache[0] = (float)Nx.Get_l_i();
+		reactions_cache[1] = (float)Tu.Get_l_i();
+		reactions_cache[2] = (float)Tv.Get_l_i();
+	}
+	//GetLog() << "         " << (int)this << "  storing  N=" << Nx.Get_l_i() <<"\n";
+}
+
+void  ChContact::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	// Store the last computed 'positional' reactions into the persistent contact manifold (might
+	// be used for warm starting the CCP position stabilization solver):
+	if (reactions_cache)
+	{
+		reactions_cache[3] = (float)Nx.Get_l_i();
+		reactions_cache[4] = (float)Tu.Get_l_i();
+		reactions_cache[5] = (float)Tv.Get_l_i();
+	}
+}
+
+
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContact.h b/SRC/ChronoEngine/physics/ChContact.h
new file mode 100644
index 0000000..55b57a1
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContact.h
@@ -0,0 +1,192 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACT_H
+#define CHCONTACT_H
+
+///////////////////////////////////////////////////
+//
+//   ChContact.h
+//
+//   Classes for enforcing constraints (contacts)
+//   created by collision detection.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChFrame.h"
+#include "lcp/ChLcpConstraintTwoContactN.h"
+#include "lcp/ChLcpSystemDescriptor.h"
+#include "collision/ChCCollisionModel.h"
+#include "physics/ChMaterialCouple.h"
+
+
+namespace chrono
+{
+
+
+///
+/// Class representing an unilateral contact constraint
+/// between two 6DOF rigid bodies.
+///
+
+class ChApi ChContact {
+
+protected:
+				//
+	  			// DATA
+				//
+	collision::ChCollisionModel* modA;	///< model A
+	collision::ChCollisionModel* modB;  ///< model B
+
+	ChVector<> p1;			///< max penetration point on geo1, after refining, in abs space
+	ChVector<> p2;			///< max penetration point on geo2, after refining, in abs space
+	ChVector<float> normal;	///< normal, on surface of master reference (geo1)
+
+							///< the plane of contact (X is normal direction)
+	ChMatrix33<float> contact_plane;
+	
+	double norm_dist;	    ///< penetration distance (negative if going inside) after refining
+
+	float* reactions_cache; ///< points to an array[3] of N,U,V reactions which might be stored in a persistent contact manifold in the collision engine
+
+							// The three scalar constraints, to be feed into the 
+							// system solver. They contain jacobians data and special functions.
+	ChLcpConstraintTwoContactN  Nx;
+	ChLcpConstraintTwoFrictionT Tu;
+	ChLcpConstraintTwoFrictionT Tv; 
+
+	ChVector<> react_force;
+
+	float compliance;
+	float complianceT;
+	float restitution;
+	float dampingf;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContact ();
+
+	ChContact (			collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		///< pass A frame
+						const ChFrame<>* frameB,		///< pass B frame
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				);
+
+	virtual ~ChContact ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Initialize again this constraint.
+	virtual void Reset(	collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		///< pass A frame
+						const ChFrame<>* frameB,		///< pass B frame
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				);
+
+					/// Get the contact coordinate system, expressed in absolute frame.
+					/// This represents the 'main' reference of the link: reaction forces 
+					/// are expressed in this coordinate system. Its origin is point P2.
+					/// (It is the coordinate system of the contact plane and normal)
+	virtual ChCoordsys<> GetContactCoords();
+
+					/// Returns the pointer to a contained 3x3 matrix representing the UV and normal
+					/// directions of the contact. In detail, the X versor (the 1s column of the 
+					/// matrix) represents the direction of the contact normal.
+	ChMatrix33<float>* GetContactPlane() {return &contact_plane;};
+
+
+					/// Get the contact point 1, in absolute coordinates
+	virtual ChVector<> GetContactP1() {return p1; };
+
+					/// Get the contact point 2, in absolute coordinates
+	virtual ChVector<> GetContactP2() {return p2; };
+
+					/// Get the contact normal, in absolute coordinates
+	virtual ChVector<float> GetContactNormal()  {return normal; };
+
+					/// Get the contact distance
+	virtual double	   GetContactDistance()  {return norm_dist; };
+	
+					/// Get the contact force, if computed, in contact coordinate system
+	virtual ChVector<> GetContactForce() {return react_force; };
+
+					/// Get the contact friction coefficient
+	virtual float GetFriction() {return Nx.GetFrictionCoefficient(); };
+					/// Set the contact friction coefficient
+	virtual void SetFriction(float mf) { Nx.SetFrictionCoefficient(mf); };
+
+					/// Get the collision model A, with point P1
+	virtual collision::ChCollisionModel* GetModelA() {return this->modA;}
+					/// Get the collision model B, with point P2
+	virtual collision::ChCollisionModel* GetModelB() {return this->modB;}
+
+				//
+				// UPDATING FUNCTIONS
+				//
+
+	
+	void  InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+
+	void  ConstraintsBiReset();
+
+	void  ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+
+	void  ConstraintsFetch_react(double factor);
+
+	void  ConstraintsLiLoadSuggestedSpeedSolution();
+
+	void  ConstraintsLiLoadSuggestedPositionSolution();
+
+	void  ConstraintsLiFetchSuggestedSpeedSolution();
+
+	void  ConstraintsLiFetchSuggestedPositionSolution();
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContactContainer.cpp b/SRC/ChronoEngine/physics/ChContactContainer.cpp
new file mode 100644
index 0000000..dc54012
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainer.cpp
@@ -0,0 +1,508 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainer.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContactContainer.h"
+#include "physics/ChSystem.h"
+#include "physics/ChBody.h"
+#include "physics/ChParticlesClones.h"
+#include "lcp/ChLcpConstraintTwoContactN.h"
+#include "collision/ChCModelBulletBody.h"
+#include "collision/ChCModelBulletParticle.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChContactContainer> a_registration_ChContactContainer;
+ 
+
+ChContactContainer::ChContactContainer ()
+{ 
+	contactlist.clear();
+	n_added = 0;
+
+	contactlist_roll.clear();
+	n_added_roll = 0;
+}
+
+
+ChContactContainer::~ChContactContainer ()
+{
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		delete (*itercontact);
+		(*itercontact) = 0;
+		++itercontact;
+		//contactlist.erase(itercontact); //no! do later with clear(), all together
+	}
+	contactlist.clear();
+
+	lastcontact = contactlist.begin();
+	n_added = 0;
+
+
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		delete (*itercontact_roll);
+		(*itercontact_roll) = 0;
+		++itercontact_roll;
+	}
+	contactlist_roll.clear();
+
+	lastcontact_roll = contactlist_roll.begin();
+	n_added_roll = 0;
+}
+
+
+
+void ChContactContainer::Update (double mytime)
+{
+    // Inherit time changes of parent class, basically doing nothing :)
+    ChContactContainerBase::Update(mytime);
+
+}
+
+
+void ChContactContainer::RemoveAllContacts()
+{
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		delete (*itercontact);
+		(*itercontact) = 0;
+		++itercontact;
+		//contactlist.erase(itercontact); //no! do later with clear(), all together
+	}
+	contactlist.clear();
+
+	lastcontact = contactlist.begin();
+	n_added = 0;
+
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		delete (*itercontact_roll);
+		(*itercontact_roll) = 0;
+		++itercontact_roll;
+	}
+	contactlist_roll.clear();
+
+	lastcontact_roll = contactlist_roll.begin();
+	n_added_roll = 0;
+}
+
+
+void ChContactContainer::BeginAddContact()
+{
+	lastcontact = contactlist.begin();
+	n_added = 0;
+
+	lastcontact_roll = contactlist_roll.begin();
+	n_added_roll = 0;
+}
+
+void ChContactContainer::EndAddContact()
+{
+	// remove contacts that are beyond last contact
+	while (lastcontact != contactlist.end())
+	{
+		delete (*lastcontact);
+		lastcontact = contactlist.erase(lastcontact);
+	}
+	while (lastcontact_roll != contactlist_roll.end())
+	{
+		delete (*lastcontact_roll);
+		lastcontact_roll = contactlist_roll.erase(lastcontact_roll);
+	}
+}
+
+
+void ChContactContainer::AddContact(const collision::ChCollisionInfo& mcontact)
+{
+	// Fetch the frames of that contact and other infos
+
+	ChFrame<>* frameA =0;
+	ChFrame<>* frameB =0;
+	bool inactiveA = false;
+	bool inactiveB = false;
+	ChLcpVariablesBody* varA = 0;
+	ChLcpVariablesBody* varB = 0;
+	ChSharedPtr<ChMaterialSurface> mmatA;
+	ChSharedPtr<ChMaterialSurface> mmatB;
+
+	if (ChModelBulletBody* mmboA = dynamic_cast<ChModelBulletBody*>(mcontact.modelA))
+	{
+		frameA = mmboA->GetBody();
+		varA    =&mmboA->GetBody()->Variables();
+		inactiveA = !mmboA->GetBody()->IsActive();
+		mmatA = mmboA->GetBody()->GetMaterialSurface();
+	}
+	if (ChModelBulletParticle* mmpaA = dynamic_cast<ChModelBulletParticle*>(mcontact.modelA))
+	{
+		frameA = &(mmpaA->GetParticles()->GetParticle(mmpaA->GetParticleId()));
+		varA   = (ChLcpVariablesBody*) &(mmpaA->GetParticles()->GetParticle(mmpaA->GetParticleId())).Variables();
+		if (ChParticlesClones* mpclone = dynamic_cast<ChParticlesClones*>(mmpaA->GetParticles()))
+		{
+			mmatA = mpclone->GetMaterialSurface();
+		}
+	}
+
+	if (ChModelBulletBody* mmboB = dynamic_cast<ChModelBulletBody*>(mcontact.modelB))
+	{
+		frameB = mmboB->GetBody();
+		varB    =&mmboB->GetBody()->Variables();
+		inactiveB = !mmboB->GetBody()->IsActive();
+		mmatB = mmboB->GetBody()->GetMaterialSurface();
+	}
+	if (ChModelBulletParticle* mmpaB = dynamic_cast<ChModelBulletParticle*>(mcontact.modelB))
+	{
+		frameB = &(mmpaB->GetParticles()->GetParticle(mmpaB->GetParticleId()));
+		varB   = (ChLcpVariablesBody*) &(mmpaB->GetParticles()->GetParticle(mmpaB->GetParticleId())).Variables();
+		if (ChParticlesClones* mpclone = dynamic_cast<ChParticlesClones*>(mmpaB->GetParticles()))
+		{
+			mmatB = mpclone->GetMaterialSurface();
+		}
+	}
+
+	if (!(frameA && frameB))
+		return;
+
+	assert (varA);
+	assert (varB);
+
+	if ((inactiveA && inactiveB))
+		return;
+
+	// Compute default material-couple values.
+
+	ChMaterialCouple mat;
+
+	mat.static_friction		= (float)ChMin( mmatA->static_friction,		mmatB->static_friction);
+	mat.rolling_friction	= (float)ChMin( mmatA->rolling_friction,	mmatB->rolling_friction);
+	mat.spinning_friction	= (float)ChMin( mmatA->spinning_friction,	mmatB->spinning_friction);
+	mat.restitution			= (float)ChMin( mmatA->restitution,			mmatB->restitution);
+	mat.cohesion			= (float)ChMin( mmatA->cohesion,			mmatB->cohesion);
+	mat.dampingf			= (float)ChMin( mmatA->dampingf,			mmatB->dampingf);
+	mat.compliance			= (float)(mmatA->compliance+mmatB->compliance);
+	mat.complianceT			= (float)(mmatA->complianceT+mmatB->complianceT);
+	mat.complianceRoll		= (float)(mmatA->complianceRoll+mmatB->complianceRoll);
+	mat.complianceSpin      = (float)(mmatA->complianceSpin+mmatB->complianceSpin);
+
+	// Launch the contact callback, if any, to set custom friction & material 
+	// properties, if implemented by the user:
+
+	if (this->add_contact_callback)
+	{
+		this->add_contact_callback->ContactCallback(mcontact, mat);
+	}
+
+	// %%%%%%% Create and add a ChContact object (or ChContactRolling if there is spinn. or roll.friction) %%%%%%%
+
+	if ((mat.rolling_friction == 0) && (mat.spinning_friction == 0))
+	{
+		if (lastcontact != contactlist.end())
+		{
+			// reuse old contacts
+			(*lastcontact)->Reset(		  mcontact.modelA,
+										  mcontact.modelB,
+										  varA, varB,
+										  frameA, frameB,
+										  mcontact.vpA, 
+										  mcontact.vpB, 
+										  mcontact.vN,
+										  mcontact.distance, 
+										  mcontact.reaction_cache,
+										  mat);
+			lastcontact++;
+		}
+		else
+		{
+			// add new contact
+			ChContact* mc = new ChContact(mcontact.modelA,
+										  mcontact.modelB,
+										  varA, varB,
+										  frameA, frameB,
+										  mcontact.vpA, 
+										  mcontact.vpB, 
+										  mcontact.vN,
+										  mcontact.distance, 
+										  mcontact.reaction_cache,
+										  mat);
+			contactlist.push_back(mc);
+			lastcontact = contactlist.end();
+		}
+		n_added++;
+	}
+	else
+	{
+		if (lastcontact_roll != contactlist_roll.end())
+		{
+			// reuse old rolling contacts
+			(*lastcontact_roll)->Reset(	  mcontact.modelA,
+										  mcontact.modelB,
+										  varA, varB,
+										  frameA, frameB,
+										  mcontact.vpA, 
+										  mcontact.vpB, 
+										  mcontact.vN,
+										  mcontact.distance, 
+										  mcontact.reaction_cache,
+										  mat);
+			lastcontact_roll++;
+		}
+		else
+		{
+			// add new contact
+			ChContactRolling* mc = new ChContactRolling(mcontact.modelA,
+										  mcontact.modelB,
+										  varA, varB,
+										  frameA, frameB,
+										  mcontact.vpA, 
+										  mcontact.vpB, 
+										  mcontact.vN,
+										  mcontact.distance, 
+										  mcontact.reaction_cache,
+										  mat);
+			contactlist_roll.push_back(mc);
+			lastcontact_roll = contactlist_roll.end();
+		}
+		n_added_roll ++;
+	}
+
+	
+}
+
+
+
+void ChContactContainer::ReportAllContacts(ChReportContactCallback* mcallback)
+{
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		bool proceed = mcallback->ReportContactCallback(
+					(*itercontact)->GetContactP1(),
+					(*itercontact)->GetContactP2(),
+					*(*itercontact)->GetContactPlane(),
+					(*itercontact)->GetContactDistance(),
+					(*itercontact)->GetFriction(),
+					(*itercontact)->GetContactForce(),
+					VNULL, // no react torques
+					(*itercontact)->GetModelA(), 
+					(*itercontact)->GetModelB()  
+					);
+		if (!proceed) 
+			break;
+		++itercontact;
+	}
+
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		bool proceed = mcallback->ReportContactCallback(
+					(*itercontact_roll)->GetContactP1(),
+					(*itercontact_roll)->GetContactP2(),
+					*(*itercontact_roll)->GetContactPlane(),
+					(*itercontact_roll)->GetContactDistance(),
+					(*itercontact_roll)->GetFriction(),
+					(*itercontact_roll)->GetContactForce(),
+					(*itercontact_roll)->GetContactTorque(),
+					(*itercontact_roll)->GetModelA(), 
+					(*itercontact_roll)->GetModelB()  
+					);
+		if (!proceed) 
+			break;
+		++itercontact_roll;
+	}
+}
+
+
+////////// LCP INTERFACES ////
+
+
+void ChContactContainer::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->InjectConstraints(mdescriptor);
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->InjectConstraints(mdescriptor);
+		++itercontact_roll;
+	}
+}
+
+void ChContactContainer::ConstraintsBiReset()
+{
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsBiReset();
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->ConstraintsBiReset();
+		++itercontact_roll;
+	}
+}
+ 
+void ChContactContainer::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsBiLoad_C(factor, recovery_clamp, do_clamp);
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->ConstraintsBiLoad_C(factor, recovery_clamp, do_clamp);
+		++itercontact_roll;
+	}
+}
+
+
+void ChContactContainer::ConstraintsLoadJacobians()
+{
+	// already loaded when ChContact objects are created
+}
+ 
+
+void ChContactContainer::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsFetch_react(factor);
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->ConstraintsFetch_react(factor);
+		++itercontact_roll;
+	}
+}
+
+
+// Following functions are for exploiting the contact persistence
+
+
+void  ChContactContainer::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	// Fetch the last computed impulsive reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP speed solver):
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiLoadSuggestedSpeedSolution();
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->ConstraintsLiLoadSuggestedSpeedSolution();
+		++itercontact_roll;
+	}
+}
+
+void  ChContactContainer::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	// Fetch the last computed 'positional' reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP position stabilization solver):
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiLoadSuggestedPositionSolution();
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->ConstraintsLiLoadSuggestedPositionSolution();
+		++itercontact_roll;
+	}
+}
+
+void  ChContactContainer::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	// Store the last computed reactions into the persistent contact manifold (might
+	// be used for warm starting CCP the speed solver):
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiFetchSuggestedSpeedSolution();
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->ConstraintsLiFetchSuggestedSpeedSolution();
+		++itercontact_roll;
+	}
+}
+
+void  ChContactContainer::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	// Store the last computed 'positional' reactions into the persistent contact manifold (might
+	// be used for warm starting the CCP position stabilization solver):
+	std::list<ChContact*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiFetchSuggestedPositionSolution();
+		++itercontact;
+	}
+	std::list<ChContactRolling*>::iterator itercontact_roll = contactlist_roll.begin();
+	while(itercontact_roll != contactlist_roll.end())
+	{
+		(*itercontact_roll)->ConstraintsLiFetchSuggestedPositionSolution();
+		++itercontact_roll;
+	}
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContactContainer.h b/SRC/ChronoEngine/physics/ChContactContainer.h
new file mode 100644
index 0000000..06556af
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainer.h
@@ -0,0 +1,156 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACTCONTAINER_H
+#define CHCONTACTCONTAINER_H
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainer.h
+//
+//   Class for container of many contacts, as CPU
+//   typical linked list of ChContact objects (that
+//   is contacts between two 6DOF bodies)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChContactContainerBase.h"
+#include "physics/ChContact.h"
+#include "physics/ChContactRolling.h"
+#include <list>
+
+namespace chrono
+{
+
+
+///
+/// Class representing a container of many contacts, 
+/// implemented as a typical linked list of ChContact 
+/// objects (that is, contacts between two 6DOF bodies).
+/// It also contains rolling contact objects, if needed.
+/// This is the default contact container used in most
+/// cases.
+///
+
+class ChApi ChContactContainer : public ChContactContainerBase {
+
+	CH_RTTI(ChContactContainer,ChContactContainerBase);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	std::list<ChContact*>   contactlist; 
+
+	int n_added;
+
+	std::list<ChContact*>::iterator lastcontact;
+
+
+	std::list<ChContactRolling*>   contactlist_roll; 
+
+	int n_added_roll;
+
+	std::list<ChContactRolling*>::iterator lastcontact_roll;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContactContainer ();
+
+	virtual ~ChContactContainer ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+					/// Tell the number of added contacts
+	virtual int GetNcontacts  () {return n_added + n_added_roll;}
+
+					/// Return the contact List
+	virtual std::list<ChContact*> & GetContactList() {return contactlist;}
+
+					/// Remove (delete) all contained contact data.
+	virtual void RemoveAllContacts();
+
+					/// The collision system will call BeginAddContact() before adding
+					/// all contacts (for example with AddContact() or similar). Instead of
+					/// simply deleting all list of the previous contacts, this optimized implementation
+					/// rewinds the link iterator to begin and tries to reuse previous contact objects
+					/// until possible, to avoid too much allocation/deallocation.
+	virtual void BeginAddContact();
+
+					/// Add a contact between two frames.
+	virtual void AddContact(const collision::ChCollisionInfo& mcontact);
+
+					/// The collision system will call BeginAddContact() after adding
+					/// all contacts (for example with AddContact() or similar). This optimized version
+					/// purges the end of the list of contacts that were not reused (if any).
+	virtual void EndAddContact();
+
+					/// Scans all the contacts and for each contact exacutes the ReportContactCallback()
+					/// function of the user object inherited from ChReportContactCallback.
+					/// Child classes of ChContactContainerBase should try to implement this (although
+					/// in some highly-optimized cases as in ChContactContainerGPU it could be impossible to
+					/// report all contacts).
+	virtual void ReportAllContacts(ChReportContactCallback* mcallback);
+
+
+
+
+					/// Tell the number of scalar bilateral constraints (actually, friction
+					/// constraints aren't exactly as unilaterals, but count them too)
+	virtual int GetDOC_d  () {return (n_added * 3) + (n_added_roll * 6);}
+
+					/// In detail, it computes jacobians, violations, etc. and stores 
+					/// results in inner structures of contacts.
+	virtual void Update (double mtime);			
+	
+				//
+				// LCP INTERFACE
+				//
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	//virtual void ConstraintsBiLoad_Ct(double factor=1.) {};
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContactContainerBase.cpp b/SRC/ChronoEngine/physics/ChContactContainerBase.cpp
new file mode 100644
index 0000000..ef19daf
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainerBase.cpp
@@ -0,0 +1,40 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainerBase.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContactContainerBase.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChContactContainerBase> a_registration_ChContactContainerBase;
+ 
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContactContainerBase.h b/SRC/ChronoEngine/physics/ChContactContainerBase.h
new file mode 100644
index 0000000..7e8c64d
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainerBase.h
@@ -0,0 +1,175 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACTCONTAINERBASE_H
+#define CHCONTACTCONTAINERBASE_H
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainerBase.h
+//
+//   Class for container of many contacts
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChContact.h"
+#include "physics/ChMaterialCouple.h"
+#include "collision/ChCCollisionInfo.h"
+
+namespace chrono
+{
+
+/// Class to be used as a callback interface for some user defined
+/// action to be taken each time a contact is added to the container.
+/// It can be used to modify the friction value (as default it is the
+/// average of the friction of the two bodies).
+/// The user should implement an inherited class and
+/// implement a custom ContactCallback() function.
+
+class ChApi ChAddContactCallback
+{
+public:
+			/// Callback, used to report contact points being added to the container.
+			/// This must be implemented by a child class of ChAddContactCallback
+	virtual void ContactCallback (const  collision::ChCollisionInfo& mcontactinfo, ///< get info about contact (cannot change it)
+								  ChMaterialCouple&  material 			  		   ///< you can modify this! 
+								) = 0;			
+};
+
+
+/// Class to be used as a callback interface for some user defined
+/// action to be taken for each contact (already added to the container,
+/// maybe with already computed forces).
+/// The user should implement an inherited class and
+/// implement a custom ReportContactCallback() function.
+
+class ChApi ChReportContactCallback
+{
+public:
+			/// Callback, used to report contact points already added to the container.
+			/// This must be implemented by a child class of ChReportContactCallback.
+			/// If returns false, the contact scanning will be stopped.
+	virtual bool ReportContactCallback (
+					const ChVector<>& pA,				///< get contact pA
+					const ChVector<>& pB,				///< get contact pB
+					const ChMatrix33<>& plane_coord,	///< get contact plane coordsystem (A column 'X' is contact normal)
+					const double& distance,				///< get contact distance
+					const float& mfriction,			  	///< get friction info
+					const ChVector<>& react_forces,		///< get react.forces (if already computed). In coordsystem 'plane_coord'
+					const ChVector<>& react_torques,	///< get react.torques, if rolling friction (if already computed).
+					collision::ChCollisionModel* modA,	///< get model A (note: some containers may not support it and could be zero!)
+					collision::ChCollisionModel* modB	///< get model B (note: some containers may not support it and could be zero!)
+										) = 0;			
+};
+
+
+
+
+
+///
+/// Class representing a container of many contacts.
+/// There might be implementations of this interface
+/// in form of plain CPU linked lists of ChContact objects,
+/// or highly optimized GPU buffers, etc. etc. 
+/// This is only the basic interface with the features that are in common.
+///
+
+class ChApi ChContactContainerBase : public ChPhysicsItem {
+
+	CH_RTTI(ChContactContainerBase,ChPhysicsItem);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	ChAddContactCallback* add_contact_callback;	
+	ChReportContactCallback* report_contact_callback; 
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContactContainerBase () 
+				{ 
+					add_contact_callback =0;
+					report_contact_callback =0;
+				};
+
+	virtual ~ChContactContainerBase () {};
+
+				//
+	  			// FUNCTIONS 
+				//
+
+					/// Tell the number of added contacts. To be implemented by child classes.
+	virtual int  GetNcontacts  () = 0;
+
+					/// Remove (delete) all contained contact data. To be implemented by child classes.
+	virtual void RemoveAllContacts() = 0;
+
+					/// The collision system will call BeginAddContact() before adding
+					/// all contacts (for example with AddContact() or similar). By default
+					/// it deletes all previous contacts. Custom more efficient implementations
+					/// might reuse contacts if possible.
+	virtual void BeginAddContact() { RemoveAllContacts(); }
+
+					/// Add a contact between two models, storing it into this container.
+					/// To be implemented by child classes.
+					/// Some specialized child classes (ex. one that uses GPU buffers)
+					/// could implement also other more efficient functions to add many contacts
+					/// in a batch (so that, for example, a special GPU collision system can exploit it);
+					/// yet most collision system might still fall back to this function if no other 
+					/// specialized add-functions are found.
+	virtual void AddContact(const collision::ChCollisionInfo& mcontact) =0;
+
+					/// The collision system will call EndAddContact() after adding
+					/// all contacts (for example with AddContact() or similar). By default
+					/// it does nothing.
+	virtual void EndAddContact() {};
+
+
+
+
+					/// Sets a callback to be used each time a contact point is 
+					/// added to the container. Note that not all child classes can
+					/// support this function in all circumstances (example, the GPU container
+					/// won't launch the callback for all its points because of performance optimization)
+	void SetAddContactCallback(ChAddContactCallback* mcallback) {add_contact_callback = mcallback;}
+
+					/// Scans all the contacts and for each contact exacutes the ReportContactCallback()
+					/// function of the user object inherited from ChReportContactCallback.
+					/// Child classes of ChContactContainerBase should try to implement this (although
+					/// in some highly-optimized cases as in ChContactContainerGPU it could be impossible to
+					/// report all contacts).
+	virtual void ReportAllContacts(ChReportContactCallback* mcallback) =0;
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContactContainerDEM.cpp b/SRC/ChronoEngine/physics/ChContactContainerDEM.cpp
new file mode 100644
index 0000000..496d3bf
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainerDEM.cpp
@@ -0,0 +1,307 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainerDEM.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContactContainerDEM.h"
+#include "physics/ChSystem.h"
+#include "physics/ChIndexedNodes.h"
+#include "physics/ChBodyDEM.h"
+#include "collision/ChCModelBulletDEM.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChContactContainerDEM> a_registration_ChContactContainerDEM;
+ 
+
+ChContactContainerDEM::ChContactContainerDEM ()
+{ 
+	contactlist.clear();
+	n_added = 0;
+
+}
+
+
+ChContactContainerDEM::~ChContactContainerDEM ()
+{
+	std::list<ChContactDEM*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		delete (*itercontact);
+		(*itercontact) = 0;
+		++itercontact;
+		//contactlist.erase(itercontact); //no! do later with clear(), all together
+	}
+	contactlist.clear();
+}
+
+
+
+void ChContactContainerDEM::Update (double mytime)
+{
+	/*
+	ChContactDEM* cntct;
+	ChModelBulletDEM* modelA;;
+	ChModelBulletDEM* modelB;;
+	ChBodyDEM* bodyA;
+	ChBodyDEM* bodyB;
+	ChVector<> contactForce;
+	ChVector<> absForceA, absForceB;
+	ChVector<> absTorqueA, absTorqueB;
+	ChVector<> pA, pB;
+	bool apply_force;
+	std::list<ChContactDEM*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		cntct = (ChContactDEM*)(*itercontact);
+		modelA = (ChModelBulletDEM*)(cntct->GetModelA());
+		modelB = (ChModelBulletDEM*)(cntct->GetModelB());
+		bodyA = modelA->GetBody();
+		bodyB = modelB->GetBody();
+
+		apply_force=true;
+		if (ChSystemMPI* syss = dynamic_cast<ChSystemMPI*>(this->GetSystem()))
+		{
+			if( ~(*syss).nodeMPI.IsInto( (cntct->GetContactP1() + cntct->GetContactP2())/2.0 ) )
+			{
+				apply_force=false;
+			}
+		}
+		if (apply_force)
+		{
+			contactForce = cntct->GetContactForce();
+
+			bodyA->AccumulateForce(contactForce);
+			bodyB->AccumulateForce(-contactForce);
+			
+			pA = cntct->GetContactP1();
+			pB = cntct->GetContactP2();
+			bodyA->To_abs_forcetorque(contactForce, pA, 0, absForceA, absTorqueA);
+			bodyB->To_abs_forcetorque(-contactForce, pB, 0, absForceB, absTorqueB);
+
+			bodyA->AccumulateTorque(absTorqueA);
+			bodyB->AccumulateTorque(absTorqueB);
+
+		}
+
+		++itercontact;
+	}
+	*/
+    // Inherit time changes of parent class, basically doing nothing :)
+    ChContactContainerBase::Update(mytime);
+
+}
+
+void ChContactContainerDEM::ConstraintsFbLoadForces(double factor)
+{
+	ChContactDEM* cntct;
+
+	std::list<ChContactDEM*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		cntct = (ChContactDEM*)(*itercontact);
+		if ((cntct->GetContactDistance()<0) )
+		{
+			(*itercontact)->ConstraintsFbLoadForces(factor);
+		}
+		++itercontact;
+	}
+}
+
+void ChContactContainerDEM::RemoveAllContacts()
+{
+	std::list<ChContactDEM*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		delete (*itercontact);
+		(*itercontact) = 0;
+		++itercontact;
+		//contactlist.erase(itercontact); //no! do later with clear(), all together
+	}
+	contactlist.clear();
+
+	lastcontact = contactlist.begin();
+	n_added = 0;
+}
+
+
+void ChContactContainerDEM::BeginAddContact()
+{
+	lastcontact = contactlist.begin();
+	n_added = 0;
+}
+
+void ChContactContainerDEM::EndAddContact()
+{
+	// remove contacts that are beyond last contact
+	while (lastcontact != contactlist.end())
+	{
+		delete (*lastcontact);
+		lastcontact = contactlist.erase(lastcontact);
+	}
+}
+
+
+void ChContactContainerDEM::AddContact(const collision::ChCollisionInfo& mcontact)
+{
+	// Fetch the frames of that contact and other infos
+	if(mcontact.distance < 0)
+	{
+		ChFrame<>* frameA =0;
+		ChFrame<>* frameB =0;
+		bool inactiveA = false;
+		bool inactiveB = false;
+		ChLcpVariablesBody* varA = 0;
+		ChLcpVariablesBody* varB = 0;
+		double springA=0;
+		double springB=0;
+		double dampingA=0;
+		double dampingB=0;
+		double springAT=0;
+		double springBT=0;
+		double muA=0;
+		double muB=0;
+
+		if (ChModelBulletDEM* mmboA = dynamic_cast<ChModelBulletDEM*>(mcontact.modelA))
+		{
+			frameA = mmboA->GetBody();
+			varA    =&mmboA->GetBody()->Variables();
+			springA = mmboA->GetBody()->GetSpringCoefficient();
+			dampingA= mmboA->GetBody()->GetDampingCoefficient();
+			springAT = mmboA->GetBody()->GetSpringCoefficientTangential();
+			muA = mmboA->GetBody()->GetSfriction();
+			inactiveA = !mmboA->GetBody()->IsActive();
+		}
+		if (ChModelBulletDEM* mmboB = dynamic_cast<ChModelBulletDEM*>(mcontact.modelB))
+		{
+			frameB = mmboB->GetBody();
+			varB    =&mmboB->GetBody()->Variables();
+			springB = mmboB->GetBody()->GetSpringCoefficient();
+			dampingB= mmboB->GetBody()->GetDampingCoefficient();
+			springBT = mmboB->GetBody()->GetSpringCoefficientTangential();
+			muB = mmboB->GetBody()->GetSfriction();
+			inactiveB = !mmboB->GetBody()->IsActive();
+		}
+
+		if (!(frameA && frameB))
+			return;
+
+		assert (varA);
+		assert (varB);
+
+		if ((inactiveA && inactiveB))
+			return;
+
+		// compute the contact spring and damping coefficients
+		//double kn_eff = 1/((1/springA)+(1/springB));
+		//double gn_eff = 1/((1/dampingA)+(1/dampingB));
+		double kn_eff = (springA+springB)/2.0;
+		double gn_eff = (dampingA+dampingB)/2.0;
+		double kt_eff = (springAT+springBT)/2.0;
+		double mu_eff = (muA+muB)/2.0;
+
+		// %%%%%%% Create and add a ChContact object  %%%%%%%
+
+		if (lastcontact != contactlist.end())
+		{
+			// reuse old contacts
+			(*lastcontact)->Reset(		  mcontact.modelA,
+										  mcontact.modelB,
+										  varA, varB,
+										  frameA, frameB,
+										  mcontact.vpA, 
+										  mcontact.vpB, 
+										  mcontact.vN,
+										  mcontact.distance, 
+										  mcontact.reaction_cache,
+										  kn_eff,
+										  gn_eff,
+										  kt_eff,
+										  mu_eff);
+			lastcontact++;
+		}
+		else
+		{
+			// add new contact
+			ChContactDEM* mc = new ChContactDEM(mcontact.modelA,
+											  mcontact.modelB,
+											  varA, varB,
+											  frameA, frameB,
+											  mcontact.vpA,
+											  mcontact.vpB,
+											  mcontact.vN,
+											  mcontact.distance,
+											  mcontact.reaction_cache,
+											  kn_eff,
+											  gn_eff,
+											  kt_eff,
+											  mu_eff);
+			contactlist.push_back(mc);
+			lastcontact = contactlist.end();
+		}
+		ChModelBulletDEM* mmboA = dynamic_cast<ChModelBulletDEM*>(mcontact.modelA);
+		n_added++;
+	}
+	
+}
+
+
+
+void ChContactContainerDEM::ReportAllContacts(ChReportContactCallback* mcallback)
+{
+	std::list<ChContactDEM*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		bool proceed = mcallback->ReportContactCallback(
+					(*itercontact)->GetContactP1(),
+					(*itercontact)->GetContactP2(),
+					*(*itercontact)->GetContactPlane(),
+					(*itercontact)->GetContactDistance(),
+					0.0,
+					(*itercontact)->GetContactForce(),
+					VNULL, // no react torques
+					(*itercontact)->GetModelA(), 
+					(*itercontact)->GetModelB()  
+					);
+		if (!proceed) 
+			break;
+		++itercontact;
+	}
+
+}
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContactContainerDEM.h b/SRC/ChronoEngine/physics/ChContactContainerDEM.h
new file mode 100644
index 0000000..ed09c93
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainerDEM.h
@@ -0,0 +1,128 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACTCONTAINERDEM_H
+#define CHCONTACTCONTAINERDEM_H
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainerDEM.h
+//
+//   Class for container of many contacts, as CPU
+//   typical linked list of ChContactDEM objects
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChContactContainerBase.h"
+#include "physics/ChContactDEM.h"
+#include <list>
+
+namespace chrono
+{
+
+
+///
+/// Class representing a container of many contacts, 
+/// implemented as a typical linked list of ChContactNode
+/// objects (contacts between 3DOF nodes and 6DOF bodies)
+///
+
+class ChApi ChContactContainerDEM : public ChContactContainerBase {
+
+	CH_RTTI(ChContactContainerDEM,ChContactContainerBase);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	std::list<ChContactDEM*>   contactlist; 
+
+	int n_added;
+
+	std::list<ChContactDEM*>::iterator lastcontact;
+
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContactContainerDEM ();
+
+	virtual ~ChContactContainerDEM ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Gets the list of contacts -low level function-.
+					/// NOTE! use this list only to enumerate etc., but NOT to
+					/// remove or add items (use the appropriate Remove.. and Add..
+					/// functions instead!)
+	std::list<ChContactDEM*>* Get_contactlist() {return &contactlist;}
+
+					/// Tell the number of added contacts
+	virtual int GetNcontacts  () {return n_added;};
+
+					/// Remove (delete) all contained contact data.
+	virtual void RemoveAllContacts();
+
+					/// The collision system will call BeginAddContact() before adding
+					/// all contacts (for example with AddContact() or similar). Instead of
+					/// simply deleting all list of the previous contacts, this optimized implementation
+					/// rewinds the link iterator to begin and tries to reuse previous contact objects
+					/// until possible, to avoid too much allocation/deallocation.
+	virtual void BeginAddContact();
+
+					/// Add a contact between two frames.
+	virtual void AddContact(const collision::ChCollisionInfo& mcontact);
+
+					/// The collision system will call BeginAddContact() after adding
+					/// all contacts (for example with AddContact() or similar). This optimized version
+					/// purges the end of the list of contacts that were not reused (if any).
+	virtual void EndAddContact();
+
+					/// Scans all the contacts and for each contact exacutes the ReportContactCallback()
+					/// function of the user object inherited from ChReportContactCallback.
+					/// Child classes of ChContactContainerBase should try to implement this (although
+					/// in some highly-optimized cases as in ChContactContainerGPU it could be impossible to
+					/// report all contacts).
+	virtual void ReportAllContacts(ChReportContactCallback* mcallback);
+
+
+
+					/// In detail, it computes jacobians, violations, etc. and stores 
+					/// results in inner structures of contacts.
+	virtual void Update (double mtime);			
+
+	virtual void ConstraintsFbLoadForces(double factor);
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContactContainerNodes.cpp b/SRC/ChronoEngine/physics/ChContactContainerNodes.cpp
new file mode 100644
index 0000000..b6b269a
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainerNodes.cpp
@@ -0,0 +1,352 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainerNodes.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContactContainerNodes.h"
+#include "physics/ChSystem.h"
+#include "physics/ChIndexedNodes.h"
+#include "physics/ChBody.h"
+#include "lcp/ChLcpConstraintNodeContactN.h"
+#include "collision/ChCModelBulletBody.h"
+#include "collision/ChCModelBulletNode.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChContactContainerNodes> a_registration_ChContactContainerNodes;
+ 
+
+ChContactContainerNodes::ChContactContainerNodes ()
+{ 
+	contactlist.clear();
+	n_added = 0;
+
+}
+
+
+ChContactContainerNodes::~ChContactContainerNodes ()
+{
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		delete (*itercontact);
+		(*itercontact) = 0;
+		++itercontact;
+		//contactlist.erase(itercontact); //no! do later with clear(), all together
+	}
+	contactlist.clear();
+}
+
+
+
+void ChContactContainerNodes::Update (double mytime)
+{
+    // Inherit time changes of parent class, basically doing nothing :)
+    ChContactContainerBase::Update(mytime);
+
+}
+
+
+void ChContactContainerNodes::RemoveAllContacts()
+{
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		delete (*itercontact);
+		(*itercontact) = 0;
+		++itercontact;
+		//contactlist.erase(itercontact); //no! do later with clear(), all together
+	}
+	contactlist.clear();
+
+	lastcontact = contactlist.begin();
+	n_added = 0;
+}
+
+
+void ChContactContainerNodes::BeginAddContact()
+{
+	lastcontact = contactlist.begin();
+	n_added = 0;
+}
+
+void ChContactContainerNodes::EndAddContact()
+{
+	// remove contacts that are beyond last contact
+	while (lastcontact != contactlist.end())
+	{
+		delete (*lastcontact);
+		lastcontact = contactlist.erase(lastcontact);
+	}
+}
+
+
+void ChContactContainerNodes::AddContact(const collision::ChCollisionInfo& mcontact)
+{
+	// Fetch the frames of that contact and other infos
+
+	ChModelBulletBody* mmboA=0;
+	ChModelBulletNode* mmnoB=0;
+	bool swapped = false;
+
+	if (mmnoB = dynamic_cast<ChModelBulletNode*>(mcontact.modelA))
+	{
+		mmboA = dynamic_cast<ChModelBulletBody*>(mcontact.modelB);
+		swapped = true;
+	}
+	else
+	{
+		if (mmnoB = dynamic_cast<ChModelBulletNode*>(mcontact.modelB))
+			mmboA = dynamic_cast<ChModelBulletBody*>(mcontact.modelA);
+	}
+
+	if (!(mmboA && mmnoB))
+		return;	// bailout if no body-node or node-body case
+
+	ChFrame<>*  frameA =0;
+	ChVector<>* posB =0;
+	bool fixedA = false;
+	bool fixedB = false;
+	float frictionA; //float frictionB;
+	ChLcpVariablesBody* varA = 0;
+	ChLcpVariablesNode* varB = 0;
+
+	ChVector<> mvN  = mcontact.vN;
+	ChVector<> mvpA = mcontact.vpA;
+	ChVector<> mvpB = mcontact.vpB;
+	if (swapped)
+	{
+		mvN  = -mcontact.vN;
+		mvpA =  mcontact.vpB;
+		mvpB =  mcontact.vpA;
+	}
+
+	frameA    = mmboA->GetBody();
+	varA      =&mmboA->GetBody()->Variables();
+	//fixedA    = mmboA->GetBody()->GetBodyFixed();
+	frictionA = mmboA->GetBody()->GetSfriction();
+	
+	ChNodeXYZ* mnode = (ChNodeXYZ*)mmnoB->GetNodes()->GetNode(mmnoB->GetNodeId());
+	posB      = &mnode->pos;
+	varB      = (ChLcpVariablesNode*)&mnode->Variables();
+	//fixedB    = mmnoB->GetNodes()->GetBodyFixed();
+	//frictionB = mmnoB->GetNodes()->GetSfriction();
+
+	// Compute default material-couple values
+
+	ChMaterialCouple mat;
+	mat.static_friction   =frictionA; //(frictionA     + frictionB)*0.5f;
+	mat.rolling_friction  =0;
+	mat.spinning_friction =0;
+
+	// Launch the contact callback, if any, to set custom friction & material 
+	// properties, if implemented by the user:
+
+	if (this->add_contact_callback)
+	{
+		this->add_contact_callback->ContactCallback(mcontact, mat);
+	}
+
+	// %%%%%%% Create and add a ChContactNode object  %%%%%%%
+
+	if (lastcontact != contactlist.end())
+	{
+		// reuse old contacts
+		(*lastcontact)->Reset(		  mmboA,
+									  mmnoB,
+									  varA, varB,
+									  frameA, posB,
+									  mvpA,
+									  mvpB, 
+									  mvN,
+									  mcontact.distance, 
+									  mcontact.reaction_cache,
+									  mat.static_friction);
+		lastcontact++;
+	}
+	else
+	{
+		// add new contact
+		ChContactNode* mc = new ChContactNode(mmboA,
+									  mmnoB,
+									  varA, varB,
+									  frameA, posB,
+									  mvpA,
+									  mvpB, 
+									  mvN,
+									  mcontact.distance, 
+									  mcontact.reaction_cache,
+									  mat.static_friction);
+		contactlist.push_back(mc);
+		lastcontact = contactlist.end();
+	}
+	n_added++;
+	
+}
+
+
+
+void ChContactContainerNodes::ReportAllContacts(ChReportContactCallback* mcallback)
+{
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		bool proceed = mcallback->ReportContactCallback(
+					(*itercontact)->GetContactP1(),
+					(*itercontact)->GetContactP2(),
+					*(*itercontact)->GetContactPlane(),
+					(*itercontact)->GetContactDistance(),
+					(*itercontact)->GetFriction(),
+					(*itercontact)->GetContactForce(),
+					VNULL, // no react torques
+					(*itercontact)->GetModelA(), 
+					(*itercontact)->GetModelB()  
+					);
+		if (!proceed) 
+			break;
+		++itercontact;
+	}
+
+}
+
+
+////////// LCP INTERFACES ////
+
+
+void ChContactContainerNodes::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->InjectConstraints(mdescriptor);
+		++itercontact;
+	}
+}
+
+void ChContactContainerNodes::ConstraintsBiReset()
+{
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsBiReset();
+		++itercontact;
+	}
+}
+ 
+void ChContactContainerNodes::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsBiLoad_C(factor, recovery_clamp, do_clamp);
+		++itercontact;
+	}
+}
+
+
+void ChContactContainerNodes::ConstraintsLoadJacobians()
+{
+	// already loaded when ChContact objects are created
+}
+ 
+
+void ChContactContainerNodes::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsFetch_react(factor);
+		++itercontact;
+	}
+}
+
+
+// Following functions are for exploiting the contact persistence
+
+
+void  ChContactContainerNodes::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	// Fetch the last computed impulsive reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP speed solver):
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiLoadSuggestedSpeedSolution();
+		++itercontact;
+	}
+}
+
+void  ChContactContainerNodes::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	// Fetch the last computed 'positional' reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP position stabilization solver):
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiLoadSuggestedPositionSolution();
+		++itercontact;
+	}
+}
+
+void  ChContactContainerNodes::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	// Store the last computed reactions into the persistent contact manifold (might
+	// be used for warm starting CCP the speed solver):
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiFetchSuggestedSpeedSolution();
+		++itercontact;
+	}
+}
+
+void  ChContactContainerNodes::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	// Store the last computed 'positional' reactions into the persistent contact manifold (might
+	// be used for warm starting the CCP position stabilization solver):
+	std::list<ChContactNode*>::iterator itercontact = contactlist.begin();
+	while(itercontact != contactlist.end())
+	{
+		(*itercontact)->ConstraintsLiFetchSuggestedPositionSolution();
+		++itercontact;
+	}
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContactContainerNodes.h b/SRC/ChronoEngine/physics/ChContactContainerNodes.h
new file mode 100644
index 0000000..3f32c38
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactContainerNodes.h
@@ -0,0 +1,141 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACTCONTAINERNODES_H
+#define CHCONTACTCONTAINERNODES_H
+
+///////////////////////////////////////////////////
+//
+//   ChContactContainerNodes.h
+//
+//   Class for container of many contacts, as CPU
+//   typical linked list of ChContactNode objects
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChContactContainerBase.h"
+#include "physics/ChContactNode.h"
+#include <list>
+
+namespace chrono
+{
+
+
+///
+/// Class representing a container of many contacts, 
+/// implemented as a typical linked list of ChContactNode
+/// objects (contacts between 3DOF nodes and 6DOF bodies)
+///
+
+class ChApi ChContactContainerNodes : public ChContactContainerBase {
+
+	CH_RTTI(ChContactContainerNodes,ChContactContainerBase);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	std::list<ChContactNode*>   contactlist; 
+
+	int n_added;
+
+	std::list<ChContactNode*>::iterator lastcontact;
+
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContactContainerNodes ();
+
+	virtual ~ChContactContainerNodes ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+					/// Tell the number of added contacts
+	virtual int GetNcontacts  () {return n_added;}
+
+					/// Remove (delete) all contained contact data.
+	virtual void RemoveAllContacts();
+
+					/// The collision system will call BeginAddContact() before adding
+					/// all contacts (for example with AddContact() or similar). Instead of
+					/// simply deleting all list of the previous contacts, this optimized implementation
+					/// rewinds the link iterator to begin and tries to reuse previous contact objects
+					/// until possible, to avoid too much allocation/deallocation.
+	virtual void BeginAddContact();
+
+					/// Add a contact between two frames.
+	virtual void AddContact(const collision::ChCollisionInfo& mcontact);
+
+					/// The collision system will call BeginAddContact() after adding
+					/// all contacts (for example with AddContact() or similar). This optimized version
+					/// purges the end of the list of contacts that were not reused (if any).
+	virtual void EndAddContact();
+
+					/// Scans all the contacts and for each contact exacutes the ReportContactCallback()
+					/// function of the user object inherited from ChReportContactCallback.
+					/// Child classes of ChContactContainerBase should try to implement this (although
+					/// in some highly-optimized cases as in ChContactContainerGPU it could be impossible to
+					/// report all contacts).
+	virtual void ReportAllContacts(ChReportContactCallback* mcallback);
+
+
+
+
+					/// Tell the number of scalar bilateral constraints (actually, friction
+					/// constraints aren't exactly as unilaterals, but count them too)
+	virtual int GetDOC_d  () {return (n_added * 3);}
+
+					/// In detail, it computes jacobians, violations, etc. and stores 
+					/// results in inner structures of contacts.
+	virtual void Update (double mtime);			
+	
+				//
+				// LCP INTERFACE
+				//
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	//virtual void ConstraintsBiLoad_Ct(double factor=1.) {};
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContactDEM.cpp b/SRC/ChronoEngine/physics/ChContactDEM.cpp
new file mode 100644
index 0000000..dbbb57b
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactDEM.cpp
@@ -0,0 +1,203 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContactDEM.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContactDEM.h"
+#include "physics/ChSystem.h"
+#include "physics/ChBodyDEM.h"
+#include "lcp/ChLcpConstraintTwoContactN.h"
+#include "collision/ChCModelBulletDEM.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+ChContactDEM::ChContactDEM ()
+{ 
+	
+}
+
+ChContactDEM::ChContactDEM (		collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		///< pass A frame
+						const ChFrame<>* frameB,		///< pass B frame
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						double  mkn,				///< spring coeff.
+						double  mgn,				///< damping coeff.
+						double  mkt,				///< tangential spring coeff.
+						double mfriction			///< friction coeff.
+				)
+{ 
+	Reset(	mmodA, mmodB,
+			varA, ///< pass A vars
+			varB, ///< pass B vars
+			frameA,		  ///< pass A frame
+			frameB,		  ///< pass B frame
+			vpA,		  ///< pass coll.point on A
+			vpB,		  ///< pass coll.point on B
+			vN, 		  ///< pass coll.normal, respect to A
+			mdistance,		  ///< pass the distance (negative for penetration)
+			mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+			mkn,
+			mgn,
+			mkt,
+			mfriction
+				);
+}
+
+ChContactDEM::~ChContactDEM ()
+{
+
+}
+
+void ChContactDEM::Reset(	collision::ChCollisionModel* mmodA,	///< model A
+							collision::ChCollisionModel* mmodB,	///< model B
+							const ChLcpVariablesBody* varA, ///< pass A vars
+							const ChLcpVariablesBody* varB, ///< pass B vars
+							const ChFrame<>* frameA,		///< pass A frame
+							const ChFrame<>* frameB,		///< pass B frame
+							const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+							const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+							const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+							double mdistance,				///< pass the distance (negative for penetration)
+							float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+							double  mkn,				///< spring coeff.
+							double  mgn,				///< damping coeff.
+							double  mkt,				///< tangential spring coeff.
+							double mfriction			///< friction coeff.
+				)
+{
+	assert (varA);
+	assert (varB);
+	assert (frameA);
+	assert (frameB);
+
+
+	this->modA = mmodA;
+	this->modB = mmodB;
+
+	ChVector<> VN = vN;
+	ChVector<double> Vx, Vy, Vz;
+	ChVector<double> singul(VECT_Y);
+	XdirToDxDyDz(&VN, &singul, &Vx,  &Vy, &Vz);
+	contact_plane.Set_A_axis(Vx,Vy,Vz);
+
+	this->p1 = vpA;
+	this->p2 = vpB;
+	this->normal = vN;
+	this->norm_dist = mdistance;
+	this->gnn=mgn;
+	this->knn=mkn;
+
+	react_force = VNULL;
+	if (mdistance<0)
+	{
+		ChModelBulletDEM* modelA = (ChModelBulletDEM*)mmodA;
+		ChBodyDEM* bodyA = modelA->GetBody();
+		ChModelBulletDEM* modelB = (ChModelBulletDEM*)mmodB;
+		ChBodyDEM* bodyB = modelB->GetBody();
+
+		//spring force
+		react_force-=mkn*pow(fabs(mdistance), 1.5)*vN;
+
+		//damping force
+		ChVector<> local_pA = bodyA->Point_World2Body(&p1);
+		ChVector<> local_pB = bodyB->Point_World2Body(&p2);
+		ChVector<> v_BA = (bodyB->RelPoint_AbsSpeed(&local_pB))-(bodyA->RelPoint_AbsSpeed(&local_pA));
+		ChVector<> v_n = (v_BA.Dot(vN))*vN;
+		react_force+=mgn*pow(fabs(mdistance), 0.5)*v_n;
+
+		//Friction force
+		ChVector<> v_t = v_BA-v_n;
+
+		double dT = bodyA->GetSystem()->GetStep();
+		double slip = v_t.Length()*dT;
+		if (v_t.Length()>1e-4)
+		{
+			v_t.Normalize();
+		}
+		else
+		{
+			v_t.SetNull();
+		}
+
+		double tmppp= (mkt*slip)<(mfriction*react_force.Length()) ? (mkt*slip) : (mfriction*react_force.Length());
+		//double tmppp = mfriction*react_force.Length();
+		react_force+=tmppp*v_t;
+
+		//bodyA->AccumulateForce(react_force);
+		//bodyB->AccumulateForce(-react_force);
+	}
+}
+
+
+void ChContactDEM::ConstraintsFbLoadForces(double factor)
+{
+	ChModelBulletDEM* modelA = (ChModelBulletDEM*)modA;
+	ChBodyDEM* bodyA = modelA->GetBody();
+	ChModelBulletDEM* modelB = (ChModelBulletDEM*)modB;
+	ChBodyDEM* bodyB = modelB->GetBody();
+
+	ChVector<> pt1_loc = bodyA->Point_World2Body(&p1);
+	ChVector<> pt2_loc = bodyB->Point_World2Body(&p2);
+	ChVector<> force1_loc = bodyA->Dir_World2Body(&react_force);
+	ChVector<> force2_loc = bodyB->Dir_World2Body(&react_force);
+	ChVector<> torque1_loc = Vcross(pt1_loc, force1_loc);
+	ChVector<> torque2_loc = Vcross(pt2_loc, -force2_loc);
+
+	//bodyA->To_abs_forcetorque (react_force, p1, 0, mabsforceA, mabstorqueA);
+	//bodyB->To_abs_forcetorque (-react_force, p2, 0, mabsforceB, mabstorqueB);
+
+	bodyA->Variables().Get_fb().PasteSumVector( react_force*factor ,0,0);
+	//bodyA->Variables().Get_fb().PasteSumVector( (bodyA->Dir_World2Body(&mabstorqueA))*factor,3,0);
+	bodyA->Variables().Get_fb().PasteSumVector( torque1_loc*factor,3,0);
+
+	bodyB->Variables().Get_fb().PasteSumVector( -react_force*factor ,0,0);
+	//bodyB->Variables().Get_fb().PasteSumVector( (bodyB->Dir_World2Body(&mabstorqueB))*factor,3,0);
+	bodyB->Variables().Get_fb().PasteSumVector( torque2_loc*factor,3,0);
+}
+
+
+ChCoordsys<> ChContactDEM::GetContactCoords()
+{
+	ChCoordsys<> mcsys;
+	ChQuaternion<float> mrot = this->contact_plane.Get_A_quaternion();
+	mcsys.rot.Set(mrot.e0, mrot.e1, mrot.e2, mrot.e3);
+	mcsys.pos = this->p2;
+	return mcsys;
+}
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContactDEM.h b/SRC/ChronoEngine/physics/ChContactDEM.h
new file mode 100644
index 0000000..816529c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactDEM.h
@@ -0,0 +1,169 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACTDEM_H
+#define CHCONTACTDEM_H
+
+///////////////////////////////////////////////////
+//
+//   ChContactDEM.h
+//
+//   Classes for enforcing constraints between DEM bodies
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChFrame.h"
+#include "lcp/ChLcpConstraintTwoContactN.h"
+#include "lcp/ChLcpSystemDescriptor.h"
+#include "collision/ChCCollisionModel.h"
+
+namespace chrono
+{
+
+
+///
+/// Class representing a contact between DEM bodies
+///
+
+class ChApi ChContactDEM {
+
+protected:
+				//
+	  			// DATA
+				//
+	collision::ChCollisionModel* modA;	///< model A
+	collision::ChCollisionModel* modB;  ///< model B
+
+	ChVector<> p1;			///< max penetration point on geo1, after refining, in abs space
+	ChVector<> p2;			///< max penetration point on geo2, after refining, in abs space
+	ChVector<float> normal;	///< normal, on surface of master reference (geo1)
+
+							///< the plane of contact (X is normal direction)
+	ChMatrix33<float> contact_plane;
+	
+	double norm_dist;	    ///< penetration distance (negative if going inside) after refining
+	double knn;  ///< spring coefficient for this contact
+	double gnn;  ///< damping coefficient for this contact
+
+	ChVector<> react_force;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContactDEM ();
+
+	ChContactDEM (		collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		///< pass A frame
+						const ChFrame<>* frameB,		///< pass B frame
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						double  mkn,				///< spring coeff.
+						double  mgn,				///< damping coeff.
+						double  mkt,				///< tangential spring coeff.
+						double mfriction			///< friction coeff.
+				);
+
+	virtual ~ChContactDEM ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Initialize again this constraint.
+	virtual void Reset(	collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		///< pass A frame
+						const ChFrame<>* frameB,		///< pass B frame
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						double  mkn,				///< spring coeff.
+						double  mgn,				///< damping coeff.
+						double  mkt,				///< tangential spring coeff.
+						double mfriction			///< friction coeff.
+);
+
+
+					/// Get the contact coordinate system, expressed in absolute frame.
+					/// This represents the 'main' reference of the link: reaction forces 
+					/// are expressed in this coordinate system. Its origin is point P2.
+					/// (It is the coordinate system of the contact plane and normal)
+	virtual ChCoordsys<> GetContactCoords();
+
+					/// Returns the pointer to a contained 3x3 matrix representing the UV and normal
+					/// directions of the contact. In detail, the X versor (the 1s column of the 
+					/// matrix) represents the direction of the contact normal.
+	ChMatrix33<float>* GetContactPlane() {return &contact_plane;};
+
+
+					/// Get the contact point 1, in absolute coordinates
+	virtual ChVector<> GetContactP1() {return p1; };
+
+					/// Get the contact point 2, in absolute coordinates
+	virtual ChVector<> GetContactP2() {return p2; };
+
+					/// Get the contact normal, in absolute coordinates
+	virtual ChVector<float> GetContactNormal()  {return normal; };
+
+					/// Get the contact distance
+	virtual double	   GetContactDistance()  {return norm_dist; };
+	
+					/// Get the contact force, if computed, in absolute coordinates
+	virtual ChVector<> GetContactForce() {return react_force; };
+
+					/// Get the spring coefficient
+	virtual double GetSpringStiffness() {return knn; };
+					/// Set the spring coefficient
+	virtual void SetSpringStiffness(float mk) { knn=mk; };
+					/// Get the damping coefficient
+	virtual double GetDampingStiffness() {return gnn; };
+					/// Set the damping coefficient
+	virtual void SetDampingStiffness(float mg) { gnn=mg; };
+
+					/// Get the collision model A, with point P1
+	virtual collision::ChCollisionModel* GetModelA() {return this->modA;};
+					/// Get the collision model B, with point P2
+	virtual collision::ChCollisionModel* GetModelB() {return this->modB;};
+
+	virtual void ConstraintsFbLoadForces(double factor);
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContactNode.cpp b/SRC/ChronoEngine/physics/ChContactNode.cpp
new file mode 100644
index 0000000..08bc669
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactNode.cpp
@@ -0,0 +1,257 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContactNode.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContactNode.h"
+#include "physics/ChSystem.h"
+#include "lcp/ChLcpConstraintNodeContactN.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+ChContactNode::ChContactNode ()
+{ 
+	Nx.SetTangentialConstraintU(&Tu);
+	Nx.SetTangentialConstraintV(&Tv);
+}
+
+ChContactNode::ChContactNode (		collision::ChCollisionModel* mmodA,	///< model A (body)
+						collision::ChCollisionModel* mmodB,	///< model B (node)
+						const ChLcpVariablesBody* varA, ///< pass B vars (body)
+						const ChLcpVariablesNode* varB, ///< pass A vars (node)
+						const ChFrame<>*  frameA,		///< pass A frame
+						const ChVector<>* posB,			///< pass B position
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						float  mfriction				///< friction coeff.
+				)
+{ 
+	Nx.SetTangentialConstraintU(&Tu);
+	Nx.SetTangentialConstraintV(&Tv);
+
+	this->Reset(	mmodA, mmodB,
+			varA, ///< pass A vars
+			varB, ///< pass B vars
+			frameA,		  ///< pass A frame
+			posB,		  ///< pass B frame
+			vpA,		  ///< pass coll.point on A
+			vpB,		  ///< pass coll.point on B
+			vN, 		  ///< pass coll.normal, respect to A
+			mdistance,		  ///< pass the distance (negative for penetration)
+			mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+			mfriction			  ///< friction coeff.
+				);
+}
+
+ChContactNode::~ChContactNode ()
+{
+
+}
+
+void ChContactNode::Reset(		collision::ChCollisionModel* mmodA,	///< model A (body)
+						collision::ChCollisionModel* mmodB,	///< model B (node)
+						const ChLcpVariablesBody* varA, ///< pass B vars (body)
+						const ChLcpVariablesNode* varB, ///< pass A vars (node)
+						const ChFrame<>*  frameA,		///< pass A frame
+						const ChVector<>* posB,			///< pass B position
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						float  mfriction				///< friction coeff.
+				)
+{
+	assert (varA);
+	assert (varB);
+	assert (frameA);
+	assert (posB);
+
+
+	this->modA = mmodA;
+	this->modB = mmodB;
+
+	Nx.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesNode*>(varB));
+	Tu.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesNode*>(varB));
+	Tv.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesNode*>(varB));
+
+	Nx.SetFrictionCoefficient(mfriction);
+
+	ChVector<> VN = vN;
+	ChVector<double> Vx, Vy, Vz;
+	ChVector<double> singul(VECT_Y);
+	XdirToDxDyDz(&VN, &singul, &Vx,  &Vy, &Vz);
+	contact_plane.Set_A_axis(Vx,Vy,Vz);
+
+	this->p1 = vpA;
+	this->p2 = vpB;
+	this->normal = vN;
+	this->norm_dist = mdistance;
+	this->reactions_cache = mreaction_cache;
+
+	ChVector<> Pl1 = frameA->TrasformParentToLocal(p1);
+	ChVector<> Pl2 = p2  - *posB; 
+
+			// compute jacobians
+	ChMatrix33<> Jx1, Jx2, Jr1;
+	ChMatrix33<> Ps1, Ps2, Jtemp;
+	Ps1.Set_X_matrix(Pl1);
+	Ps2.Set_X_matrix(Pl2);
+
+	Jx1.CopyFromMatrixT(this->contact_plane);
+	Jx2.CopyFromMatrixT(this->contact_plane);
+	Jx1.MatrNeg();
+
+	Jtemp.MatrMultiply(*( const_cast<ChFrame<>*>(frameA)->GetA()), Ps1);
+	Jr1.MatrTMultiply(this->contact_plane, Jtemp);
+
+	Nx.Get_Cq_a()->PasteClippedMatrix(&Jx1, 0,0, 1,3, 0,0);
+	Tu.Get_Cq_a()->PasteClippedMatrix(&Jx1, 1,0, 1,3, 0,0);
+	Tv.Get_Cq_a()->PasteClippedMatrix(&Jx1, 2,0, 1,3, 0,0);
+	Nx.Get_Cq_a()->PasteClippedMatrix(&Jr1, 0,0, 1,3, 0,3);
+	Tu.Get_Cq_a()->PasteClippedMatrix(&Jr1, 1,0, 1,3, 0,3);
+	Tv.Get_Cq_a()->PasteClippedMatrix(&Jr1, 2,0, 1,3, 0,3);
+
+	Nx.Get_Cq_b()->PasteClippedMatrix(&Jx2, 0,0, 1,3, 0,0);
+	Tu.Get_Cq_b()->PasteClippedMatrix(&Jx2, 1,0, 1,3, 0,0);
+	Tv.Get_Cq_b()->PasteClippedMatrix(&Jx2, 2,0, 1,3, 0,0);
+
+	react_force = VNULL;
+}
+
+
+
+ChCoordsys<> ChContactNode::GetContactCoords()
+{
+	ChCoordsys<> mcsys;
+	ChQuaternion<float> mrot = this->contact_plane.Get_A_quaternion();
+	mcsys.rot.Set(mrot.e0, mrot.e1, mrot.e2, mrot.e3);
+	mcsys.pos = this->p2;
+	return mcsys;
+}
+
+
+ 
+
+
+void ChContactNode::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	mdescriptor.InsertConstraint(&Nx);
+	mdescriptor.InsertConstraint(&Tu);
+	mdescriptor.InsertConstraint(&Tv); 
+}
+
+void ChContactNode::ConstraintsBiReset()
+{
+	Nx.Set_b_i(0.);
+	Tu.Set_b_i(0.);
+	Tv.Set_b_i(0.);
+}
+ 
+void ChContactNode::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	if (do_clamp)
+		Nx.Set_b_i( Nx.Get_b_i() + ChMax (factor * this->norm_dist, -recovery_clamp)  );
+	else
+		Nx.Set_b_i( Nx.Get_b_i() + factor * this->norm_dist  );
+}
+
+void ChContactNode::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	react_force.x = Nx.Get_l_i() * factor;  
+	react_force.y = Tu.Get_l_i() * factor;
+	react_force.z = Tv.Get_l_i() * factor;
+}
+
+
+void  ChContactNode::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	// Fetch the last computed impulsive reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP speed solver): 
+	if (this->reactions_cache)
+	{
+		Nx.Set_l_i(reactions_cache[0]);
+		Tu.Set_l_i(reactions_cache[1]);  
+		Tv.Set_l_i(reactions_cache[2]);
+	} 
+}
+
+void  ChContactNode::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	// Fetch the last computed 'positional' reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP position stabilization solver):
+	if (this->reactions_cache)
+	{
+		Nx.Set_l_i(reactions_cache[3]);
+		Tu.Set_l_i(reactions_cache[4]);  
+		Tv.Set_l_i(reactions_cache[5]);
+	}
+}
+
+void  ChContactNode::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	// Store the last computed reactions into the persistent contact manifold (might
+	// be used for warm starting CCP the speed solver):
+	if (reactions_cache)
+	{
+		reactions_cache[0] = (float)Nx.Get_l_i();
+		reactions_cache[1] = (float)Tu.Get_l_i();
+		reactions_cache[2] = (float)Tv.Get_l_i();
+	}
+}
+
+void  ChContactNode::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	// Store the last computed 'positional' reactions into the persistent contact manifold (might
+	// be used for warm starting the CCP position stabilization solver):
+	if (reactions_cache)
+	{
+		reactions_cache[3] = (float)Nx.Get_l_i();
+		reactions_cache[4] = (float)Tu.Get_l_i();
+		reactions_cache[5] = (float)Tv.Get_l_i();
+	}
+}
+
+
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContactNode.h b/SRC/ChronoEngine/physics/ChContactNode.h
new file mode 100644
index 0000000..b6e010d
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactNode.h
@@ -0,0 +1,185 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACTNODE_H
+#define CHCONTACTNODE_H
+
+///////////////////////////////////////////////////
+//
+//   ChContactNode.h
+//
+//   Classes for enforcing constraints (contacts)
+//   between nodes (3DOF) and bodies (6DOF)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChFrame.h"
+#include "lcp/ChLcpConstraintNodeContactN.h"
+#include "lcp/ChLcpSystemDescriptor.h"
+#include "collision/ChCCollisionModel.h"
+
+namespace chrono
+{
+
+
+///
+/// Class representing an unilateral contact constraint
+/// between a 3DOF node and a 6DOF body
+///
+
+class ChApi ChContactNode {
+
+protected:
+				//
+	  			// DATA
+				//
+	collision::ChCollisionModel* modA;	///< model A
+	collision::ChCollisionModel* modB;  ///< model B
+
+	ChVector<> p1;			///< max penetration point on geo1, after refining, in abs space
+	ChVector<> p2;			///< max penetration point on geo2, after refining, in abs space
+	ChVector<float> normal;	///< normal, on surface of master reference (geo1)
+
+							///< the plane of contact (X is normal direction)
+	ChMatrix33<float> contact_plane;
+	
+	double norm_dist;	    ///< penetration distance (negative if going inside) after refining
+
+	float* reactions_cache; ///< points to an array[3] of N,U,V reactions which might be stored in a persistent contact manifold in the collision engine
+
+							// The three scalar constraints, to be feed into the 
+							// system solver. They contain jacobians data and special functions.
+	ChLcpConstraintNodeContactN  Nx;
+	ChLcpConstraintNodeFrictionT Tu;
+	ChLcpConstraintNodeFrictionT Tv; 
+
+	ChVector<> react_force;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContactNode ();
+
+	ChContactNode (		collision::ChCollisionModel* mmodA,	///< model A (body)
+						collision::ChCollisionModel* mmodB,	///< model B (node)
+						const ChLcpVariablesBody* varA, ///< pass B vars (body)
+						const ChLcpVariablesNode* varB, ///< pass A vars (node)
+						const ChFrame<>*  frameA,		///< pass A frame
+						const ChVector<>* posB,			///< pass B position
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						float  mfriction				///< friction coeff.
+				);
+
+	virtual ~ChContactNode ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Initialize again this constraint.
+	virtual void Reset(		collision::ChCollisionModel* mmodA,	///< model A (body)
+						collision::ChCollisionModel* mmodB,	///< model B (node)
+						const ChLcpVariablesBody* varA, ///< pass B vars (body)
+						const ChLcpVariablesNode* varB, ///< pass A vars (node)
+						const ChFrame<>*  frameA,		///< pass A frame
+						const ChVector<>* posB,			///< pass B position
+						const ChVector<>& vpA,			///< pass coll.point on A, in absolute coordinates
+						const ChVector<>& vpB,			///< pass coll.point on B, in absolute coordinates
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A, in absolute coordinates
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						float  mfriction				///< friction coeff.
+				);
+
+					/// Get the contact coordinate system, expressed in absolute frame.
+					/// This represents the 'main' reference of the link: reaction forces 
+					/// are expressed in this coordinate system. Its origin is point P2.
+					/// (It is the coordinate system of the contact plane and normal)
+	virtual ChCoordsys<> GetContactCoords();
+
+					/// Returns the pointer to a contained 3x3 matrix representing the UV and normal
+					/// directions of the contact. In detail, the X versor (the 1s column of the 
+					/// matrix) represents the direction of the contact normal.
+	ChMatrix33<float>* GetContactPlane() {return &contact_plane;};
+
+
+					/// Get the contact point 1, in absolute coordinates
+	virtual ChVector<> GetContactP1() {return p1; };
+
+					/// Get the contact point 2, in absolute coordinates
+	virtual ChVector<> GetContactP2() {return p2; };
+
+					/// Get the contact normal, in absolute coordinates
+	virtual ChVector<float> GetContactNormal()  {return normal; };
+
+					/// Get the contact distance
+	virtual double	   GetContactDistance()  {return norm_dist; };
+	
+					/// Get the contact force, if computed, in contact coordinate system
+	virtual ChVector<> GetContactForce() {return react_force; };
+
+					/// Get the contact friction coefficient
+	virtual float GetFriction() {return Nx.GetFrictionCoefficient(); };
+					/// Set the contact friction coefficient
+	virtual void SetFriction(float mf) { Nx.SetFrictionCoefficient(mf); };
+
+					/// Get the collision model A, with point P1
+	virtual collision::ChCollisionModel* GetModelA() {return this->modA;}
+					/// Get the collision model B, with point P2
+	virtual collision::ChCollisionModel* GetModelB() {return this->modB;}
+
+				//
+				// UPDATING FUNCTIONS
+				//
+
+	
+	void  InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+
+	void  ConstraintsBiReset();
+
+	void  ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+
+	void  ConstraintsFetch_react(double factor);
+
+	void  ConstraintsLiLoadSuggestedSpeedSolution();
+
+	void  ConstraintsLiLoadSuggestedPositionSolution();
+
+	void  ConstraintsLiFetchSuggestedSpeedSolution();
+
+	void  ConstraintsLiFetchSuggestedPositionSolution();
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContactRolling.cpp b/SRC/ChronoEngine/physics/ChContactRolling.cpp
new file mode 100644
index 0000000..5461ff2
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactRolling.cpp
@@ -0,0 +1,245 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContact.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChContactRolling.h"
+#include "physics/ChSystem.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+ChContactRolling::ChContactRolling ()
+{ 
+	Rx.SetRollingConstraintU(&Ru);
+	Rx.SetRollingConstraintV(&Rv);
+	Rx.SetNormalConstraint(&Nx);
+}
+
+ChContactRolling::ChContactRolling (collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		  ///< pass A frame
+						const ChFrame<>* frameB,		  ///< pass B frame
+						const ChVector<>& vpA,		  ///< pass coll.point on A
+						const ChVector<>& vpB,		  ///< pass coll.point on B
+						const ChVector<>& vN, 		  ///< pass coll.normal, respect to A
+						double mdistance,		  ///< pass the distance (negative for penetration)
+						float* mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				)
+{ 
+	Rx.SetRollingConstraintU(&Ru);
+	Rx.SetRollingConstraintV(&Rv);
+	Rx.SetNormalConstraint(&Nx);
+
+	Reset(	mmodA, mmodB,
+			varA, ///< pass A vars
+			varB, ///< pass B vars
+			frameA,		  ///< pass A frame
+			frameB,		  ///< pass B frame
+			vpA,		  ///< pass coll.point on A
+			vpB,		  ///< pass coll.point on B
+			vN, 		  ///< pass coll.normal, respect to A
+			mdistance,		  ///< pass the distance (negative for penetration)
+			mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+			mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				);
+}
+
+ChContactRolling::~ChContactRolling ()
+{
+
+}
+
+void ChContactRolling::Reset(	collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+					    const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		  ///< pass A frame
+						const ChFrame<>* frameB,		  ///< pass B frame
+						const ChVector<>& vpA,		  ///< pass coll.point on A
+						const ChVector<>& vpB,		  ///< pass coll.point on B
+						const ChVector<>& vN, 		  ///< pass coll.normal, respect to A
+						double mdistance,		  ///< pass the distance (negative for penetration)
+						float* mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				)
+{
+	// Base method call:
+	ChContact::Reset(	mmodA, mmodB,
+			varA, ///< pass A vars
+			varB, ///< pass B vars
+			frameA,		  ///< pass A frame
+			frameB,		  ///< pass B frame
+			vpA,		  ///< pass coll.point on A
+			vpB,		  ///< pass coll.point on B
+			vN, 		  ///< pass coll.normal, respect to A
+			mdistance,		  ///< pass the distance (negative for penetration)
+			mreaction_cache,	  ///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+			mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				);
+
+	Rx.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesBody*>(varB));
+	Ru.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesBody*>(varB));
+	Rv.SetVariables(const_cast<ChLcpVariablesBody*>(varA),const_cast<ChLcpVariablesBody*>(varB));
+
+	Rx.SetRollingFrictionCoefficient(mmaterial.rolling_friction);
+	Rx.SetSpinningFrictionCoefficient(mmaterial.spinning_friction);
+
+	ChMatrix33<> Jx1, Jx2, Jr1, Jr2;
+
+	Jr1.MatrTMultiply(this->contact_plane, *(const_cast<ChFrame<>*>(frameA)->GetA()));
+	Jr2.MatrTMultiply(this->contact_plane, *(const_cast<ChFrame<>*>(frameB)->GetA()));
+	Jr1.MatrNeg();
+
+	Rx.Get_Cq_a()->PasteClippedMatrix(&Jx1, 0,0, 1,3, 0,0);
+	Ru.Get_Cq_a()->PasteClippedMatrix(&Jx1, 1,0, 1,3, 0,0);
+	Rv.Get_Cq_a()->PasteClippedMatrix(&Jx1, 2,0, 1,3, 0,0);
+	Rx.Get_Cq_a()->PasteClippedMatrix(&Jr1, 0,0, 1,3, 0,3);
+	Ru.Get_Cq_a()->PasteClippedMatrix(&Jr1, 1,0, 1,3, 0,3);
+	Rv.Get_Cq_a()->PasteClippedMatrix(&Jr1, 2,0, 1,3, 0,3);
+
+	Rx.Get_Cq_b()->PasteClippedMatrix(&Jx2, 0,0, 1,3, 0,0);
+	Ru.Get_Cq_b()->PasteClippedMatrix(&Jx2, 1,0, 1,3, 0,0);
+	Rv.Get_Cq_b()->PasteClippedMatrix(&Jx2, 2,0, 1,3, 0,0);
+	Rx.Get_Cq_b()->PasteClippedMatrix(&Jr2, 0,0, 1,3, 0,3);
+	Ru.Get_Cq_b()->PasteClippedMatrix(&Jr2, 1,0, 1,3, 0,3);
+	Rv.Get_Cq_b()->PasteClippedMatrix(&Jr2, 2,0, 1,3, 0,3);
+
+	this->complianceRoll = mmaterial.complianceRoll;
+	this->complianceSpin = mmaterial.complianceSpin;
+
+	react_torque = VNULL;
+
+}
+
+
+
+
+ 
+
+
+void ChContactRolling::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	// base behaviour too
+	ChContact::InjectConstraints(mdescriptor);
+
+	mdescriptor.InsertConstraint(&Rx);
+	mdescriptor.InsertConstraint(&Ru);
+	mdescriptor.InsertConstraint(&Rv); 
+}
+
+void ChContactRolling::ConstraintsBiReset()
+{
+	// base behaviour too
+	ChContact::ConstraintsBiReset();
+
+	Rx.Set_b_i(0.);
+	Ru.Set_b_i(0.);
+	Rv.Set_b_i(0.);
+}
+ 
+void ChContactRolling::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	// base behaviour too
+	ChContact::ConstraintsBiLoad_C(factor,recovery_clamp,do_clamp);
+	
+	// If rolling and spinning compliance, set the cfm terms
+
+	double h = 1.0/factor;  // timestep is inverse of factor
+			
+	double alpha=this->dampingf; // [R]=alpha*[K]
+	double inv_hpa = 1.0/(h+alpha); // 1/(h+a)
+	double inv_hhpa = 1.0/(h*(h+alpha)); // 1/(h*(h+a)) 
+
+	this->Ru.Set_cfm_i( (inv_hhpa)*this->complianceRoll  );
+	this->Rv.Set_cfm_i( (inv_hhpa)*this->complianceRoll  );
+	this->Rx.Set_cfm_i( (inv_hhpa)*this->complianceSpin  );
+
+	// Assume no residual ever, do not load in C
+}
+
+void ChContactRolling::ConstraintsFetch_react(double factor)
+{
+	// base behaviour too
+	ChContact::ConstraintsFetch_react(factor);
+
+	// From constraints to react torque:
+	react_torque.x = Rx.Get_l_i() * factor;  
+	react_torque.y = Ru.Get_l_i() * factor;
+	react_torque.z = Rv.Get_l_i() * factor;
+}
+
+
+void  ChContactRolling::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	// base behaviour too
+	ChContact::ConstraintsLiLoadSuggestedSpeedSolution();
+
+	// [Note: no persistent cache used for rolling multipliers - do nothing]
+}
+
+void  ChContactRolling::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	// base behaviour too
+	ChContact::ConstraintsLiLoadSuggestedPositionSolution();
+
+	// [Note: no persistent cache used for rolling multipliers - do nothing]
+}
+
+void  ChContactRolling::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	// base behaviour too
+	ChContact::ConstraintsLiFetchSuggestedSpeedSolution();
+
+	// [Note: no persistent cache used for rolling multipliers - do nothing]
+}
+
+void  ChContactRolling::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	// base behaviour too
+	ChContact::ConstraintsLiFetchSuggestedPositionSolution();
+
+	// [Note: no persistent cache used for rolling multipliers - do nothing]
+}
+
+
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChContactRolling.h b/SRC/ChronoEngine/physics/ChContactRolling.h
new file mode 100644
index 0000000..9f8691d
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContactRolling.h
@@ -0,0 +1,149 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTACTROLLING_H
+#define CHCONTACTROLLING_H
+
+///////////////////////////////////////////////////
+//
+//   ChContactRolling.h
+//
+//   Class for enforcing constraints (contacts) with
+//   friction and rolling resistance.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChContact.h"
+#include "lcp/ChLcpConstraintTwoRollingN.h"
+
+namespace chrono
+{
+
+
+///
+/// Class representing an unilateral contact constraint, used by
+/// ChContactContainer, that has also rolling friction. 
+///
+
+class ChApi ChContactRolling : public ChContact {
+
+protected:
+				//
+	  			// DATA
+				//
+	ChLcpConstraintTwoRollingN   Rx;
+	ChLcpConstraintTwoRollingT   Ru;
+	ChLcpConstraintTwoRollingT   Rv; 
+
+	ChVector<> react_torque;
+
+	float complianceRoll;
+	float complianceSpin;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChContactRolling ();
+
+	ChContactRolling (	collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		///< pass A frame
+						const ChFrame<>* frameB,		///< pass B frame
+						const ChVector<>& vpA,			///< pass coll.point on A
+						const ChVector<>& vpB,			///< pass coll.point on B
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				);
+
+	virtual ~ChContactRolling ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Initialize again this constraint.
+	virtual void Reset(	collision::ChCollisionModel* mmodA,	///< model A
+						collision::ChCollisionModel* mmodB,	///< model B
+						const ChLcpVariablesBody* varA, ///< pass A vars
+						const ChLcpVariablesBody* varB, ///< pass B vars
+						const ChFrame<>* frameA,		///< pass A frame
+						const ChFrame<>* frameB,		///< pass B frame
+						const ChVector<>& vpA,			///< pass coll.point on A
+						const ChVector<>& vpB,			///< pass coll.point on B
+						const ChVector<>& vN, 			///< pass coll.normal, respect to A
+						double mdistance,				///< pass the distance (negative for penetration)
+						float* mreaction_cache,			///< pass the pointer to array of N,U,V reactions: a cache in contact manifold. If not available=0.
+						ChMaterialCouple& mmaterial		///< pass the reference to the material with friction, stiffness, etc.
+				);
+
+	
+					/// Get the contact force, if computed, in contact coordinate system
+	virtual ChVector<> GetContactTorque() {return react_torque; };
+
+					/// Get the contact rolling friction coefficient
+	virtual float GetRollingFriction() {return Rx.GetRollingFrictionCoefficient(); };
+					/// Set the contact rolling friction coefficient
+	virtual void SetRollingFriction(float mf) { Rx.SetRollingFrictionCoefficient(mf); };
+
+					/// Get the contact spinning friction coefficient
+	virtual float GetSpinningFriction() {return Rx.GetSpinningFrictionCoefficient(); };
+					/// Set the contact spinning friction coefficient
+	virtual void SetSpinningFriction(float mf) { Rx.SetSpinningFrictionCoefficient(mf); };
+
+
+				//
+				// UPDATING FUNCTIONS
+				//
+
+	// warning, following are not virtual, for optimization
+
+	void  InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+
+	void  ConstraintsBiReset();
+
+	void  ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+
+	void  ConstraintsFetch_react(double factor);
+
+	void  ConstraintsLiLoadSuggestedSpeedSolution();
+
+	void  ConstraintsLiLoadSuggestedPositionSolution();
+
+	void  ConstraintsLiFetchSuggestedSpeedSolution();
+
+	void  ConstraintsLiFetchSuggestedPositionSolution();
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChContinuumMaterial.cpp b/SRC/ChronoEngine/physics/ChContinuumMaterial.cpp
new file mode 100644
index 0000000..8e8ab89
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContinuumMaterial.cpp
@@ -0,0 +1,416 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChContinuumMaterial.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "ChContinuumMaterial.h"
+
+namespace chrono 
+{
+namespace fem 
+{
+
+
+void ChContinuumMaterial::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// stream out all member data
+	mstream << this->density;
+}
+
+void ChContinuumMaterial::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in all member data
+	mstream >> this->density;
+}
+
+
+
+
+////////////////////////////////////////
+
+
+
+
+ChContinuumElastic::ChContinuumElastic(double myoung, double mpoisson, double mdensity) 
+		: ChContinuumMaterial(mdensity)
+{
+	E = myoung;
+	Set_v(mpoisson); // sets also G and l
+	ComputeStressStrainMatrix(); // sets Elasticity matrix
+	this->damping_M = 0;
+	this->damping_K = 0;
+}
+
+ChContinuumElastic::~ChContinuumElastic()
+{
+}
+
+void ChContinuumElastic::Set_E (double m_E)
+{
+	E = m_E;
+	G = E/(2*(1+v));	// fixed v, E, get G
+	l = (v*E)/((1+v)*(1-2*v));	// Lame's constant l
+	ComputeStressStrainMatrix(); // updates Elasticity matrix
+}
+
+void ChContinuumElastic::Set_v (double m_v)
+{
+	v = m_v;
+	G = E/(2*(1+v));	// fixed v, E, get G
+	l = (v*E)/((1+v)*(1-2*v));	// Lame's constant l
+	ComputeStressStrainMatrix(); // updates Elasticity matrix
+}
+
+void ChContinuumElastic::Set_G (double m_G)
+{
+	G = m_G;
+	v = (E/(2*G))-1;	// fixed G, E, get v
+	l = (v*E)/((1+v)*(1-2*v)); // Lame's constant l
+	ComputeStressStrainMatrix(); // updates Elasticity matrix
+}
+
+void ChContinuumElastic::ComputeStressStrainMatrix()
+{
+	StressStrainMatrix.Resize(6,6);
+	StressStrainMatrix.SetElement(0,0,(E *(1-v))/(1+v)/(1-2*v));
+	//StressStrainMatrix.SetElement(1,1,StressStrainMatrix.GetElement(0,0));	//
+	//StressStrainMatrix.SetElement(2,2,StressStrainMatrix.GetElement(0,0));	//per non ricalcolare; qual'� meglio?
+	StressStrainMatrix.SetElement(1,1,(E*(1-v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(2,2,(E*(1-v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(0,1,(E*(v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(0,2,(E*(v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(1,0,(E*(v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(1,2,(E*(v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(2,0,(E*(v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(2,1,(E*(v))/(1+v)/(1-2*v));
+	StressStrainMatrix.SetElement(3,3,(E*(1-2*v))/(1+v)/(1-2*v)/2);
+	StressStrainMatrix.SetElement(4,4,(E*(1-2*v))/(1+v)/(1-2*v)/2);
+	StressStrainMatrix.SetElement(5,5,(E*(1-2*v))/(1+v)/(1-2*v)/2);
+}
+
+void ChContinuumElastic::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+			// stream in parent class
+	ChContinuumMaterial::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->E;
+	mstream << this->v;
+	mstream << this->G;
+	mstream << this->l;
+	mstream << this->damping_M;
+	mstream << this->damping_K;
+}
+
+void ChContinuumElastic::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in parent class
+	ChContinuumMaterial::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> this->E;
+	mstream >> this->v;
+	mstream >> this->G;
+	mstream >> this->l;
+	mstream >> this->damping_M;
+	mstream >> this->damping_K;
+}
+
+
+
+///////////////////////////////
+//////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ChContinuumPlasticVonMises::ChContinuumPlasticVonMises(double myoung, double mpoisson, double mdensity,
+												   double melastic_yeld, double  mplastic_yeld) : 
+							ChContinuumElastoplastic(myoung, mpoisson, mdensity)
+{
+	elastic_yeld = melastic_yeld;
+	plastic_yeld = mplastic_yeld;
+	flow_rate = 1;
+}
+
+double ChContinuumPlasticVonMises::ComputeYeldFunction(const ChStressTensor<>& mstress) const
+{
+	return (mstress.GetEquivalentVonMises() - this->elastic_yeld);
+}
+
+void ChContinuumPlasticVonMises::ComputeReturnMapping(ChStrainTensor<>& mplasticstrainflow, 
+									const ChStrainTensor<>&	mincrementstrain, 
+									const ChStrainTensor<>& mlastelasticstrain,
+									const ChStrainTensor<>& mlastplasticstrain) const
+{
+	ChStrainTensor<> guesselstrain(mlastelasticstrain);
+	guesselstrain.MatrInc(mincrementstrain); // assume increment is all elastic
+
+	double vonm = guesselstrain.GetEquivalentVonMises();
+	if (vonm > this->elastic_yeld)
+	{
+		ChVoightTensor<> mdev;
+		guesselstrain.GetDeviatoricPart(mdev);
+		mplasticstrainflow.CopyFromMatrix(mdev * ((vonm - this->elastic_yeld)/(vonm)));
+	}
+	else
+	{
+		mplasticstrainflow.FillElem(0);
+	}
+}
+
+
+void ChContinuumPlasticVonMises::ComputePlasticStrainFlow(ChStrainTensor<>& mplasticstrainflow, const ChStrainTensor<>& mtotstrain) const
+{
+	double vonm = mtotstrain.GetEquivalentVonMises();
+	if (vonm > this->elastic_yeld)
+	{
+		ChVoightTensor<> mdev;
+		mtotstrain.GetDeviatoricPart(mdev);
+		mplasticstrainflow.CopyFromMatrix(mdev * ((vonm - this->elastic_yeld)/(vonm)));
+	}
+	else
+	{
+		mplasticstrainflow.FillElem(0);
+	}
+}
+
+void ChContinuumPlasticVonMises::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// stream out parent class
+	ChContinuumElastoplastic::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->elastic_yeld;
+	mstream << this->plastic_yeld;
+	mstream << this->flow_rate;
+}
+
+void ChContinuumPlasticVonMises::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in parent class
+	ChContinuumElastoplastic::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> this->elastic_yeld;
+	mstream >> this->plastic_yeld;
+	mstream >> this->flow_rate;
+}
+
+
+
+
+///////////////////////////////
+//////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////
+
+
+ChContinuumDruckerPrager::ChContinuumDruckerPrager(double myoung, double mpoisson, double mdensity,
+							double melastic_yeld, double  malpha, double mdilatancy) : 
+						ChContinuumElastoplastic(myoung, mpoisson, mdensity)
+{
+	elastic_yeld = melastic_yeld;
+	alpha = malpha;
+	dilatancy = mdilatancy;
+	hardening_limit = elastic_yeld;
+	hardening_speed =0;
+	flow_rate = 1;
+}
+
+void ChContinuumDruckerPrager::Set_from_MohrCoulomb(double phi, double cohesion, bool inner_approx)
+{
+	if (inner_approx)
+	{
+		alpha =			(2*sin(phi))/(sqrt(3.0)*(3.0-sin(phi)));
+		elastic_yeld =  (6*cohesion*cos(phi))/(sqrt(3.0)*(3.0-sin(phi)));
+	} else
+	{
+		alpha =			(2*sin(phi))/(sqrt(3.0)*(3.0+sin(phi)));
+		elastic_yeld =  (6*cohesion*cos(phi))/(sqrt(3.0)*(3.0+sin(phi)));
+	}
+}
+
+double ChContinuumDruckerPrager::ComputeYeldFunction(const ChStressTensor<>& mstress) const
+{
+	return (mstress.GetInvariant_I1() * this->alpha + sqrt (mstress.GetInvariant_J2()) - this->elastic_yeld);
+}
+
+void ChContinuumDruckerPrager::ComputeReturnMapping( 
+									ChStrainTensor<>& mplasticstrainflow,
+									const ChStrainTensor<>&	mincrementstrain, 
+									const ChStrainTensor<>& mlastelasticstrain,
+									const ChStrainTensor<>& mlastplasticstrain) const
+{
+	ChStrainTensor<> guesselstrain(mlastelasticstrain);
+	guesselstrain.MatrInc(mincrementstrain); // assume increment is all elastic
+	
+	ChStressTensor<> mstress;
+	this->ComputeElasticStress(mstress,guesselstrain);
+	double fprager = this->ComputeYeldFunction(mstress);
+
+	if (fprager >0 )
+	{
+		if (mstress.GetInvariant_I1() * this->alpha - sqrt (mstress.GetInvariant_J2()) * this->alpha * this->alpha - this->elastic_yeld > 0)
+		{
+			// Case: tentative stress is in polar cone; a singular region where the gradient of
+			// the yeld function (or flow potential) is not defined. Just project to vertex.
+			ChStressTensor<> vertexstress;
+			double vertcoord = this->elastic_yeld / (3*this->alpha);
+			vertexstress.XX() = vertcoord;
+			vertexstress.YY() = vertcoord;
+			vertexstress.ZZ() = vertcoord;
+			ChStrainTensor<> vertexstrain;
+			this->ComputeElasticStrain(vertexstrain, vertexstress);
+			mplasticstrainflow.MatrSub(guesselstrain, vertexstrain);
+		}
+		else
+		{
+			// Case: tentative stress is out of the yeld cone.
+			// Just project using the yeld (or flow potential) gradient.
+			ChStrainTensor<> dFdS;
+			ChStrainTensor<> dGdS;
+			double devsq = sqrt(mstress.GetInvariant_J2());
+			if (devsq > 10e-16)
+			{
+				double sixdevsq = 6 * devsq;
+
+				dFdS.XX() = this->alpha + (2* mstress.XX() - mstress.YY()   - mstress.ZZ() )/sixdevsq;
+				dFdS.YY() = this->alpha + (- mstress.XX() + 2*mstress.YY()  - mstress.ZZ() )/sixdevsq;
+				dFdS.ZZ() = this->alpha + (- mstress.XX() -  mstress.YY() + 2*mstress.ZZ() )/sixdevsq;
+				dFdS.XY() = mstress.XY()/devsq;
+				dFdS.YZ() = mstress.YZ()/devsq;
+				dFdS.XZ() = mstress.XZ()/devsq;
+
+				dGdS.XX() = this->dilatancy + (2* mstress.XX() - mstress.YY()   - mstress.ZZ() )/sixdevsq;
+				dGdS.YY() = this->dilatancy + (- mstress.XX() + 2*mstress.YY()  - mstress.ZZ() )/sixdevsq;
+				dGdS.ZZ() = this->dilatancy + (- mstress.XX() -  mstress.YY() + 2*mstress.ZZ() )/sixdevsq;
+				dGdS.XY() = mstress.XY()/devsq;
+				dGdS.YZ() = mstress.YZ()/devsq;
+				dGdS.XZ() = mstress.XZ()/devsq;
+			}
+			else
+			{
+				GetLog() << "      ... axial singularity - SHOULD NEVER OCCUR  - handled by polar cone\n";
+				dFdS.FillElem(0); 
+				dFdS.XX() = 1; dFdS.YY() = 1; dFdS.ZZ() = 1;
+				dGdS.FillElem(0); 
+				dGdS.XX() = 1; dGdS.YY() = 1; dGdS.ZZ() = 1;
+			}
+			ChStressTensor<> aux_dFdS_C;
+			this->ComputeElasticStress(aux_dFdS_C, dFdS);
+
+			ChMatrixNM<double,1,1> inner_up;
+			inner_up.MatrTMultiply(aux_dFdS_C, mincrementstrain);
+			ChMatrixNM<double,1,1> inner_dw;
+			inner_dw.MatrTMultiply(aux_dFdS_C, dGdS);
+
+			mplasticstrainflow.CopyFromMatrix(dGdS);
+			mplasticstrainflow.MatrScale(inner_up(0)/inner_dw(0));
+		}
+	} 
+	else
+	{
+		mplasticstrainflow.FillElem(0);
+	}
+}
+
+//***OBSOLETE***
+void ChContinuumDruckerPrager::ComputePlasticStrainFlow(ChStrainTensor<>& mplasticstrainflow, const ChStrainTensor<>& mestrain) const
+{
+	ChStressTensor<> mstress;
+	this->ComputeElasticStress(mstress,mestrain);
+	double prager = mstress.GetInvariant_I1() * this->alpha + sqrt (mstress.GetInvariant_J2());
+	if (prager > this->elastic_yeld)
+	{
+		ChVoightTensor<> mdev;
+		mstress.GetDeviatoricPart(mdev);
+		double divisor = 2.*sqrt(mstress.GetInvariant_J2());
+		if (divisor>10e-20)
+			mdev.MatrScale(1./ divisor );
+		mdev.XX()+=this->dilatancy;
+		mdev.YY()+=this->dilatancy;
+		mdev.ZZ()+=this->dilatancy;
+		mplasticstrainflow.CopyFromMatrix(mdev);
+	}
+	else
+	{
+		mplasticstrainflow.FillElem(0);
+	}
+}
+
+void ChContinuumDruckerPrager::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// stream out parent class
+	ChContinuumElastic::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->elastic_yeld;
+	mstream << this->alpha;
+	mstream << this->dilatancy;
+	mstream << this->hardening_speed;
+	mstream << this->hardening_limit;
+	mstream << this->flow_rate;
+}
+
+void ChContinuumDruckerPrager::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in parent class
+	ChContinuumElastic::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> this->elastic_yeld;
+	mstream >> this->alpha;
+	mstream >> this->dilatancy;
+	mstream >> this->hardening_speed;
+	mstream >> this->hardening_limit;
+	mstream >> this->flow_rate;
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/physics/ChContinuumMaterial.h b/SRC/ChronoEngine/physics/ChContinuumMaterial.h
new file mode 100644
index 0000000..e8b39c5
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChContinuumMaterial.h
@@ -0,0 +1,408 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTINUUMMATERIAL_H
+#define CHCONTINUUMMATERIAL_H
+
+//////////////////////////////////////////////////
+//  
+//   ChContinuumMaterial.h
+//
+//   Class for material of elastoplatic continuum
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChApiCE.h"
+#include "core/ChMath.h"
+#include "core/ChShared.h"
+#include "physics/ChTensors.h"
+
+namespace chrono 
+{
+namespace fem
+{
+
+
+
+/// Base class for properties of materials 
+/// in a continuum. 
+
+class ChApi ChContinuumMaterial : public ChShared
+{
+private:
+	double density;
+
+public:
+
+	ChContinuumMaterial(double mdensity=1000) : density(mdensity) {};
+
+	virtual ~ChContinuumMaterial() {};
+	
+			/// Set the density of the material, in kg/m^2.
+	void   Set_density (double m_density) {density = m_density;}
+			/// Get the density of the material, in kg/m^2.
+	double Get_density () {return density;}
+
+				/// Method to allow deserializing
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing 
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+/// Class for the basic properties of materials 
+/// in an elastic continuum. 
+/// This is a base material with isothropic hookean 
+/// elasticity.
+
+class ChApi ChContinuumElastic : public ChContinuumMaterial
+{
+private:
+
+	double E;			// Young Modulus
+	double v;			// Poisson ratio
+	double G;			// shear modulus
+	double l;			// Lame's modulus
+	ChMatrixDynamic<> StressStrainMatrix;		//Elasticity (stiffness) matrix		σ = [E] ε
+
+	double damping_M;	// Raleigh_damping, M proportional
+	double damping_K;	// Raleigh_damping, K proportional
+
+
+public:
+
+			/// Create a continuum isothropic hookean material. 
+			/// Default value for Young elastic modulus is low (like a 
+			/// rubber-type material), and same for density.
+	ChContinuumElastic(double myoung = 10000000, double mpoisson=0.4, double mdensity=1000);
+
+	virtual ~ChContinuumElastic();
+	
+
+			/// Set the Young E elastic modulus, in Pa (N/m^2), as the ratio of the uniaxial 
+			/// stress over the uniaxial strain, for hookean materials. Intuitively, the 
+			/// tensile pressure on a side of a parallelepiped in order to double its length.
+			/// Note that most metal materials require very high values, ex. steel 
+			/// has E=210GPa (E=210e9), aluminium E=69e9, and this can cause numerical 
+			/// problems if you do not set up the simulation integrator properly.
+	void   Set_E (double m_E);
+			/// Get the Young E elastic modulus, in Pa (N/m^2).
+	double Get_E () {return E;}
+
+
+			/// Set the Poisson v ratio, as v=-transverse_strain/axial_strain, so
+			/// takes into account the 'squeezing' effect of materials that are pulled (so,
+			/// if zero, when you push the two sizes of a cube, it won't inflate). Most
+			/// materials have some 0<v<0.5, for example steel has v=0.27..0.30, aluminium v=0.33,
+			/// rubber=0.49, etc. Note! v=0.5 means perfectly incompressible material, that 
+			/// could give problems with some type of solvers.
+			/// Setting v also changes G.
+	void   Set_v (double m_v);
+			/// Get the Young v ratio, as v=-transverse_strain/axial_strain.
+	double Get_v () {return v;}
+
+			/// Set the shear modulus G, in Pa (N/m^2), as the ratio of shear stress to 
+			/// the shear strain. Setting G also changes Poisson ratio v.
+	void   Set_G (double m_G);
+			/// Get the shear modulus G, in Pa (N/m^2)
+	double Get_G () {return G;}
+
+			/// Get Lamé first parameter (the second is shear modulus, so Get_G() )
+	double Get_l () {return l;}
+
+			/// Get bulk modulus (increase of pressure for decrease of volume), in Pa. 
+	double Get_BulkModulus () {return E/(3.*(1.-2.*v));}
+
+			/// Get P-wave modulus (if V=speed of propagation of a P-wave, then (M/density)=V^2 ) 
+	double Get_WaveModulus () {return E*((1.-v)/(1.+v)*(1.-2.*v));}
+
+
+			/// Computes Elasticity matrix and stores the value in this->StressStrainMatrix
+			/// Note: is performed every time you change a material parameter
+	void ComputeStressStrainMatrix();
+			/// Get the Elasticity matrix 
+	ChMatrixDynamic<> Get_StressStrainMatrix () {return StressStrainMatrix;}
+
+
+			/// Compute elastic stress from elastic strain
+			/// (using column tensors, in Voight notation)
+	void ComputeElasticStress(ChStressTensor<>& mstress, const ChStrainTensor<>& mstrain) const
+				{
+					mstress.XX() = mstrain.XX() * (l+2*G) + mstrain.YY() * l       + mstrain.ZZ() * l;
+					mstress.YY() = mstrain.XX() * l		  + mstrain.YY() * (l+2*G) + mstrain.ZZ() * l;
+					mstress.ZZ() = mstrain.XX() * l       + mstrain.YY() * l	   + mstrain.ZZ() * (l+2*G);
+					mstress.XY() = mstrain.XY() * 2*G;
+					mstress.XZ() = mstrain.XZ() * 2*G;
+					mstress.YZ() = mstrain.YZ() * 2*G;
+				}
+
+			/// Compute elastic strain from elastic stress
+			/// (using column tensors, in Voight notation)
+	void ComputeElasticStrain(ChStrainTensor<>& mstrain, const ChStressTensor<>& mstress) const
+				{
+					double invE = 1./E;
+					double invhG = 0.5/G;
+					mstrain.XX() = invE*( mstress.XX()		- mstress.YY() * v	- mstress.ZZ() * v);
+					mstrain.YY() = invE*(-mstress.XX() * v	+ mstress.YY()		- mstress.ZZ() * v);
+					mstrain.ZZ() = invE*(-mstress.XX() * v	- mstress.YY() * v	+ mstress.ZZ()    );
+					mstrain.XY() = mstress.XY() * invhG;
+					mstrain.XZ() = mstress.XZ() * invhG;
+					mstrain.YZ() = mstress.YZ() * invhG;
+				}
+
+			/// Set the Rayleigh mass-proportional damping factor, to 
+			/// build damping R as  R=alpha*M + beta*K
+	void   Set_RayleighDampingM (double m_d) {this->damping_M = m_d;}
+			/// Set the Rayleigh mass-proportional damping factor, in R=alpha*M + beta*K
+	double Get_RayleighDampingM () {return this->damping_M;}
+
+			/// Set the Rayleigh stiffness-proportional damping factor alpha, to 
+			/// build damping R as  R=alpha*M + beta*K
+	void   Set_RayleighDampingK (double m_d) {this->damping_K = m_d;}
+			/// Set the Rayleigh stiffness-proportional damping factor beta, in R=alpha*M + beta*K
+	double Get_RayleighDampingK () {return this->damping_K;}
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+
+/// Class for all elastic materials that can undergo plastic flow
+/// Defines simply some interface functions.
+
+class ChApi ChContinuumElastoplastic : public ChContinuumElastic
+{
+public:
+	ChContinuumElastoplastic(double myoung = 10000000, double mpoisson=0.4, double mdensity=1000) : ChContinuumElastic(myoung,mpoisson,mdensity) {};
+
+			/// Return a scalar value that is 0 on the yeld surface, <0 inside (elastic), >0 outside (incompatible->plastic flow)
+	virtual double ComputeYeldFunction(const ChStressTensor<>& mstress) const = 0;
+
+			/// Compute plastic strain flow (flow derivative dE_plast/dt) from strain,
+			/// according to VonMises strain yeld theory. 
+	virtual void ComputePlasticStrainFlow(ChStrainTensor<>& mplasticstrainflow, const ChStrainTensor<>& mtotstrain) const =0;
+
+			/// Correct the strain-stress by enforcing that elastic stress must remain on the yeld 
+			/// surface, computing a plastic flow to be added to plastic strain while integrating.
+	virtual void ComputeReturnMapping(ChStrainTensor<>& mplasticstrainflow, 
+									const ChStrainTensor<>&	mincrementstrain, 
+									const ChStrainTensor<>& mlastelasticstrain,
+									const ChStrainTensor<>& mlastplasticstrain) const = 0;
+
+			/// Set the plastic flow rate, i.e. the 'creep' speed. The lower the value, the slower 
+			/// the plastic flow during dynamic simulations, with delayed plasticity. 
+	virtual void   Set_flow_rate (double mflow_rate)=0;
+			/// Set the plastic flow rate.
+	virtual double Get_flow_rate ()=0;
+};
+
+
+
+
+
+/// Class for the basic properties of materials 
+/// in an elastoplastic continuum, with strain yeld limit
+/// based on Von Mises yeld
+
+class ChApi ChContinuumPlasticVonMises : public ChContinuumElastoplastic
+{
+private:
+
+	double elastic_yeld;
+	double plastic_yeld;
+	
+	double flow_rate;
+
+public:
+
+			/// Create a continuum isothropic elastoplastic material,
+			/// where you can define also plastic and elastic max. stress (yeld limits
+			/// for transition elastic->blastic and plastic->fracture).
+	ChContinuumPlasticVonMises(double myoung = 10000000, double mpoisson=0.4, double mdensity=1000,
+							double melastic_yeld = 0.1, double  mplastic_yeld = 0.2);
+
+	virtual ~ChContinuumPlasticVonMises() {};
+	
+
+			/// Set the elastic yeld modulus as the maximum VonMises
+			/// equivalent strain that can be withstood by material before
+			/// starting plastic flow. It defines the transition elastic->plastic.
+	void   Set_elastic_yeld (double melastic_yeld) {elastic_yeld = melastic_yeld;};
+			/// Get the elastic yeld modulus.
+	double Get_elastic_yeld () {return elastic_yeld;}
+
+			/// Set the plastic yeld modulus as the maximum VonMises
+			/// equivalent strain that can be withstood by material before
+			/// fracture. It defines the transition plastic->fracture.
+	void   Set_plastic_yeld (double mplastic_yeld) {plastic_yeld = mplastic_yeld;};
+			/// Get the plastic yeld modulus.
+	double Get_plastic_yeld () {return plastic_yeld;}
+
+			/// Set the plastic flow rate. The lower the value, the slower 
+			/// the plastic flow during dynamic simulations.
+	void   Set_flow_rate (double mflow_rate) {flow_rate = mflow_rate;};
+			/// Set the plastic flow rate.
+	double Get_flow_rate () {return flow_rate;}
+
+
+	virtual double ComputeYeldFunction(const ChStressTensor<>& mstress) const;
+
+	virtual void ComputeReturnMapping(ChStrainTensor<>& mplasticstrainflow, 
+									const ChStrainTensor<>&	mincrementstrain, 
+									const ChStrainTensor<>& mlastelasticstrain,
+									const ChStrainTensor<>& mlastplasticstrain) const;
+
+
+			/// Compute plastic strain flow (flow derivative dE_plast/dt) from strain,
+			/// according to VonMises strain yeld theory. 
+	void ComputePlasticStrainFlow(ChStrainTensor<>& mplasticstrainflow, const ChStrainTensor<>& mestrain) const;
+
+
+			//
+			// STREAMING
+			//
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+/// Class for the basic properties of elastoplastic materials 
+/// of Drucker-Prager type, that are useful for simulating
+/// soils
+
+class ChApi ChContinuumDruckerPrager : public ChContinuumElastoplastic
+{
+private:
+
+	double elastic_yeld;
+	double alpha;
+	double dilatancy;
+	double hardening_speed;
+	double hardening_limit;
+	double flow_rate;
+
+public:
+
+			/// Create a continuum isothropic Drucker-Prager material
+	ChContinuumDruckerPrager(double myoung = 10000000, double mpoisson=0.4, double mdensity=1000,
+							double melastic_yeld = 0.1, double  malpha = 0.5, double mdilatancy = 0);
+
+	virtual ~ChContinuumDruckerPrager() {};
+	
+
+			/// Set the D-P yeld modulus C, for Drucker-Prager
+			/// yeld. It defines the transition elastic->plastic.
+	void   Set_elastic_yeld (double melastic_yeld) {elastic_yeld = melastic_yeld;};
+			/// Get the elastic yeld modulus C
+	double Get_elastic_yeld () {return elastic_yeld;}
+
+			/// Set the internal friction coefficient A
+	void   Set_alpha (double malpha) {alpha = malpha;};
+			/// Get the internal friction coefficient A
+	double Get_alpha () {return alpha;}	
+
+			/// Sets the C and A parameters of the Drucker-Prager model
+			/// starting from more 'practical' values of inner friction angle phi
+			/// and cohesion, as used in the faceted Mohr-Coulomb model. 
+			/// Use the optional parameter inner_approx to set if the faceted
+			/// Mohr-Coulomg must be approximated with D-P inscribed (default) or circumscribed.
+	void   Set_from_MohrCoulomb(double phi, double cohesion, bool inner_approx=true);
+
+			/// Set the plastic flow rate multiplier. The lower the value, the slower 
+			/// the plastic flow during dynamic simulations.
+	void   Set_flow_rate (double mflow_rate) {flow_rate = mflow_rate;};
+			/// Get the flow rate multiplier.
+	double Get_flow_rate () {return flow_rate;}
+
+			/// Set the internal dilatancy coefficient (usually 0.. < int.friction)
+	void   Set_dilatancy (double mdilatancy) {dilatancy = mdilatancy;};
+			/// Get the internal dilatancy coefficient 
+	double Get_dilatancy () {return dilatancy;}
+
+			/// Set the hardening limit (usually a bit larger than yeld), or softening
+	void   Set_hardening_limit (double mhl) {hardening_limit = mhl;};
+			/// Get the hardening limit 
+	double Get_hardening_limit () {return hardening_limit;}
+
+			/// Set the hardening inverse speed coeff. for exponential hardening 
+			/// (the larger, the slower the hardening or softening process that 
+			/// will asymptotycally make yeld = hardening_limit )
+	void   Set_hardening_speed (double mhl) {hardening_speed = mhl;};
+			/// Get the hardening speed
+	double Get_hardening_speed () {return hardening_speed;}
+
+
+	virtual double ComputeYeldFunction(const ChStressTensor<>& mstress) const;
+
+	virtual void ComputeReturnMapping(ChStrainTensor<>& mplasticstrainflow, 
+									const ChStrainTensor<>&	mincrementstrain, 
+									const ChStrainTensor<>& mlastelasticstrain,
+									const ChStrainTensor<>& mlastplasticstrain) const;
+
+			/// Compute plastic strain flow direction from strain
+			/// according to Drucker-Prager. 
+	void ComputePlasticStrainFlow(ChStrainTensor<>& mplasticstrainflow, const ChStrainTensor<>& mestrain) const;
+
+
+			//
+			// STREAMING
+			//
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+#endif 
diff --git a/SRC/ChronoEngine/physics/ChController.cpp b/SRC/ChronoEngine/physics/ChController.cpp
new file mode 100644
index 0000000..b72c85f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChController.cpp
@@ -0,0 +1,120 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChController.cpp
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include <math.h>
+
+#include "physics/ChController.h"
+#include "physics/ChGlobal.h"
+
+
+namespace chrono 
+{ 
+
+
+
+///   CLASS
+///
+/// 
+
+
+ChControllerPID::ChControllerPID()
+{
+	this->SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	P= 1.;
+	I= 0.;
+	D= 0.;
+	
+	Reset();
+}
+
+ChControllerPID::~ChControllerPID()
+{
+}
+
+
+
+// Use Reset to set accumulator to zero, at beginning. For integrative part.
+
+
+void ChControllerPID::Reset()
+{
+	this->In_int = 0.0;
+	this->In_dt  = 0.0;
+	this->In = 0;
+	this->Out = 0;
+	this->Pcomp = 0;
+	this->Icomp = 0;
+	this->Dcomp = 0;
+	this->last_t = 0;
+}
+
+
+//
+// Compute controller output value
+//
+ 
+double ChControllerPID::Get_Out(double new_in, double new_t)
+{
+	double mdt = (new_t - last_t);
+	
+	// please, no backward calling sequence!
+	if (mdt < 0)
+	{
+		this->Reset();
+		return 0.0;
+	}
+
+	// please, multiple calls at same time do not perform updates!
+	if (mdt == 0)
+	{
+		return this->Out;
+	}
+
+	// OK......
+
+	// compute derivative of in (simple Bdf differentiation)
+	In_dt   = (new_in - In) / mdt;
+	
+	// compute integration of in  (trapezoidal rule ) 
+	In_int += (new_in + In)*0.5 * mdt;
+
+	// Go forward... synchronize time and last input recorder
+	In		= new_in;
+	last_t	= new_t;
+	this->SetChTime(new_t);
+
+	// ===  Compute PID components ================
+
+	Pcomp = P * In;
+	Icomp = I * In_int;
+	Dcomp = D * In_dt;
+
+	Out = Pcomp + Icomp + Dcomp;
+	
+	return Out;
+}
+			
+				
+
+
+} // END_OF_NAMESPACE____
+
+
+////// end
diff --git a/SRC/ChronoEngine/physics/ChController.h b/SRC/ChronoEngine/physics/ChController.h
new file mode 100644
index 0000000..f908b54
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChController.h
@@ -0,0 +1,97 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTROLLER_H
+#define CHCONTROLLER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChController.h
+//
+//   Class for controllers (PID etc)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include "core/ChApiCE.h"
+#include "core/ChMath.h"
+#include "physics/ChObject.h"
+
+
+
+namespace chrono 
+{
+
+
+///
+/// Class for a basic PID controller
+///
+///  A basic PID controller, used as a 'black box'. Depending on 
+/// input, it produces a controlled output proportional to input, 
+/// input derivative by time, input integration
+///
+
+class ChApi ChControllerPID : public ChObj  {
+
+private:
+	double In;			// internal, last input set into controller, at time 'last_t'
+	double In_int;		// internal, last integral, for integrative part of controller
+	double In_dt;		// internal, last derivative, for derivative part of controller
+	double last_t;		// internal, last time
+	double Pcomp;	// internal, 
+	double Icomp;	// internal, 
+	double Dcomp;	// internal, 
+	double Out;		// internal, last output value
+
+public:
+	ChControllerPID();
+	~ChControllerPID();
+	
+	double P;	///< proportional coefficient
+	double I;	///< integrative coefficient
+	double D;	///< derivative coefficient
+				
+				/// COMPUTE CONTROL value!
+				/// Given an input i, returns the output o=P*i+D*di/dt+I*Int(i dt)
+				/// that is o = Pcomp+Icomp+Dcomp
+				/// Calls to Get_Output must be done in (possibly uniform) time steps, 
+				/// otherwise remember to call Reset() before other sequences of calls.
+	double Get_Out(double mInput, double mTime);
+
+				/// Same, but just returns last computed output
+	double Get_Out() {return Out;};
+
+				// Read-only values, telling which was the components 
+				// of the last outputted control, divided by proportional or
+				// integrative or derivative part.
+	double Get_Pcomp() {return Pcomp;}	
+	double Get_Icomp() {return Icomp;}
+	double Get_Dcomp() {return Dcomp;}
+	double Get_In_int()  {return In_int;}
+	double Get_In_dt()   {return In_dt;}
+	double Get_In()   {return In;}
+
+				/// Use Reset to set accumulator to zero, at beginning. For integrative part.
+	void Reset(); 
+};
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of ChController.h 
diff --git a/SRC/ChronoEngine/physics/ChControls.cpp b/SRC/ChronoEngine/physics/ChControls.cpp
new file mode 100644
index 0000000..6f40680
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChControls.cpp
@@ -0,0 +1,78 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChControls.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+ 
+
+#include "physics/ChControls.h"
+  
+namespace chrono 
+{
+
+
+
+/////////////////////////////////////////////////////////
+/// 
+///   CLASS
+///
+///
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence 
+ChClassRegisterABSTRACT<ChControls> a_registration_ChControls;
+
+
+
+// 
+// FILE I/O
+//
+
+void ChControls::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number 
+	mstream.VersionWrite(1); 
+		// serialize parent class too
+	ChObj::StreamOUT(mstream);
+
+		// stream out all member data
+
+}
+				
+void ChControls::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number 
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChObj::StreamIN(mstream);
+
+		// stream in all member data
+
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____ 
+
+
+
+////// end
diff --git a/SRC/ChronoEngine/physics/ChControls.h b/SRC/ChronoEngine/physics/ChControls.h
new file mode 100644
index 0000000..d673d90
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChControls.h
@@ -0,0 +1,88 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONTROLS_H
+#define CHCONTROLS_H
+
+//////////////////////////////////////////////////
+//  
+//   ChControls.h
+//
+//   Class for controls
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+
+#include "physics/ChObject.h"
+
+
+namespace chrono 
+{
+
+
+
+///
+/// Basic interface class for 'controls', that are objects that change parameters
+/// during the simulation, ex. to simulate PIDs, etc.
+/// Must be inherited and implemented by user.
+/// 
+
+
+class ChApi ChControls : public ChObj 
+{
+								// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChControls,ChObj);
+
+public:
+
+	ChControls() {};
+	virtual ~ChControls() {};
+	
+	//void Copy(ChControls* source);
+
+			//
+			// FUNCTIONS - interface to be implemeted -
+			//
+
+	virtual int ExecuteForStart() = 0;
+	virtual int ExecuteForUpdate() = 0;
+	virtual int ExecuteForStep() = 0;
+	virtual int ExecuteFor3DStep() = 0;
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+		
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of header
diff --git a/SRC/ChronoEngine/physics/ChConveyor.cpp b/SRC/ChronoEngine/physics/ChConveyor.cpp
new file mode 100644
index 0000000..faa7f58
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChConveyor.cpp
@@ -0,0 +1,335 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChConveyor.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "core/ChTrasform.h"
+#include "physics/ChConveyor.h"
+#include "physics/ChSystem.h"
+
+#include "collision/ChCModelBulletBody.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChConveyor> a_registration_ChConveyor;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR CONVEYOR
+
+
+ChConveyor::ChConveyor (double xlength, double ythick, double zwidth)
+{
+	conveyor_speed = 1.0; 
+	
+	conveyor_plate = new ChBody;
+
+	conveyor_plate->SetMaterialSurface(this->GetMaterialSurface());
+
+	conveyor_plate->GetCollisionModel()->ClearModel();
+	conveyor_plate->GetCollisionModel()->AddBox(xlength*0.5, ythick*0.5, zwidth*0.5); 
+	conveyor_plate->GetCollisionModel()->BuildModel();
+	conveyor_plate->SetCollide(true);
+
+
+	internal_link  = new ChLinkLockLock;
+	internal_link->SetMotion_X(new ChFunction_Ramp);
+
+	ChSharedPtr<ChMarker> mmark1(new ChMarker);
+	ChSharedPtr<ChMarker> mmark2(new ChMarker);
+	this->AddMarker(mmark1);
+	this->conveyor_plate->AddMarker(mmark2);
+
+	internal_link->ReferenceMarkers(mmark1.get_ptr(), mmark2.get_ptr());
+}
+
+
+ChConveyor::~ChConveyor ()
+{
+	if (internal_link) delete internal_link;
+	if (conveyor_plate) delete conveyor_plate;
+}
+
+void ChConveyor::Copy(ChConveyor* source)
+{
+		// copy the parent class data...
+	ChBody::Copy(source);
+
+	this->conveyor_speed	= source->conveyor_speed;
+
+	this->internal_link = source->internal_link;
+	this->conveyor_plate = source->conveyor_plate;
+}
+
+
+
+
+
+
+//// LCP INTERFACE
+
+void ChConveyor::InjectVariables(ChLcpSystemDescriptor& mdescriptor)
+{	
+			// inherit parent class
+	ChBody::InjectVariables(mdescriptor);
+
+	this->conveyor_plate->InjectVariables(mdescriptor);
+}
+
+
+void ChConveyor::VariablesFbReset()
+{
+				// inherit parent class
+	ChBody::VariablesFbReset();
+
+	this->conveyor_plate->VariablesFbReset();
+}
+
+
+void ChConveyor::VariablesFbLoadForces(double factor)
+{
+					// inherit parent class
+	ChBody::VariablesFbLoadForces(factor);
+
+	this->conveyor_plate->VariablesFbLoadForces(factor);
+}
+
+void ChConveyor::VariablesFbIncrementMq()
+{
+					// inherit parent class
+	ChBody::VariablesFbIncrementMq();
+
+	this->conveyor_plate->VariablesFbIncrementMq();
+}
+
+void ChConveyor::VariablesQbLoadSpeed()
+{
+					// inherit parent class
+	ChBody::VariablesQbLoadSpeed();
+
+	this->conveyor_plate->VariablesQbLoadSpeed();
+}
+
+
+void ChConveyor::VariablesQbSetSpeed(double step)
+{
+						// inherit parent class
+	ChBody::VariablesQbSetSpeed(step);
+
+	this->conveyor_plate->VariablesQbSetSpeed(step);
+}
+
+
+void ChConveyor::VariablesQbIncrementPosition(double dt_step)
+{
+					// inherit parent class
+	ChBody::VariablesQbIncrementPosition(dt_step);
+
+	this->conveyor_plate->VariablesQbIncrementPosition(dt_step);
+}
+
+
+void ChConveyor::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	this->internal_link->InjectConstraints(mdescriptor);
+}
+
+void ChConveyor::ConstraintsBiReset()
+{
+	this->internal_link->ConstraintsBiReset();
+}
+ 
+void ChConveyor::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	this->internal_link->ConstraintsBiLoad_C(factor, recovery_clamp, do_clamp);
+}
+
+void ChConveyor::ConstraintsBiLoad_Ct(double factor)
+{
+	this->internal_link->ConstraintsBiLoad_Ct(factor);
+}
+
+void ChConveyor::ConstraintsBiLoad_Qc(double factor)
+{
+	this->internal_link->ConstraintsBiLoad_Qc(factor);
+}
+
+void ChConveyor::ConstraintsLoadJacobians()
+{
+	this->internal_link->ConstraintsLoadJacobians();
+}
+ 
+void ChConveyor::ConstraintsFetch_react(double factor)
+{
+	this->internal_link->ConstraintsFetch_react(factor);
+}
+
+void  ChConveyor::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	this->internal_link->ConstraintsLiLoadSuggestedSpeedSolution();
+}
+
+void  ChConveyor::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	this->internal_link->ConstraintsLiLoadSuggestedPositionSolution();
+}
+
+void  ChConveyor::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	this->internal_link->ConstraintsLiFetchSuggestedSpeedSolution();
+}
+
+void  ChConveyor::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	this->internal_link->ConstraintsLiFetchSuggestedPositionSolution();
+}
+
+
+
+
+
+
+					
+void ChConveyor::Update (double mytime)
+{
+				// inherit parent class function
+	ChBody::Update(mytime);
+	
+	if (this->GetBodyFixed())
+	{
+		double largemass = 100000;
+		this->conveyor_plate->SetMass(largemass);
+		this->conveyor_plate->SetInertiaXX(ChVector<>(largemass,largemass,largemass));
+		this->conveyor_plate->SetInertiaXY(ChVector<>(0,0,0));
+	}
+	else
+	{
+		this->conveyor_plate->SetMass(this->GetMass());
+		this->conveyor_plate->SetInertiaXX(this->GetInertiaXX());
+		this->conveyor_plate->SetInertiaXY(this->GetInertiaXY());
+	}
+
+	this->conveyor_plate->SetSystem(this->GetSystem());
+
+	this->conveyor_plate->SetMaterialSurface(this->GetMaterialSurface());
+
+				// keep the plate always at the same position of the main reference
+	this->conveyor_plate->SetCoord(this->GetCoord());
+	this->conveyor_plate->SetCoord_dt(this->GetCoord_dt());
+				// keep the plate always at the same speed of the main reference, plus the conveyor speed on X local axis
+	this->conveyor_plate->SetPos_dt(this->GetPos_dt() + (ChVector<>(conveyor_speed,0,0) >> (*this) ) );
+
+	conveyor_plate->Update(mytime);
+
+	this->internal_link->SetSystem(this->GetSystem());
+
+	((ChFunction_Ramp*)internal_link->GetMotion_X())->Set_ang(-conveyor_speed); 
+	((ChFunction_Ramp*)internal_link->GetMotion_X())->Set_y0(+conveyor_speed*this->GetChTime()); // always zero pos. offset (trick)
+
+	this->internal_link->Update(mytime);
+}
+
+
+
+
+
+void ChConveyor::SyncCollisionModels()
+{
+						// inherit parent class
+	ChBody::SyncCollisionModels();
+
+	this->conveyor_plate->SetSystem(this->GetSystem());
+
+	this->conveyor_plate->SyncCollisionModels();
+}
+
+void ChConveyor::AddCollisionModelsToSystem() 
+{
+						// inherit parent class
+	ChBody::AddCollisionModelsToSystem();
+
+	this->conveyor_plate->SetSystem(this->GetSystem());
+
+	this->conveyor_plate->AddCollisionModelsToSystem();
+}
+
+void ChConveyor::RemoveCollisionModelsFromSystem() 
+{
+						// inherit parent class
+	ChBody::RemoveCollisionModelsFromSystem();
+
+	this->conveyor_plate->SetSystem(this->GetSystem());
+
+	this->conveyor_plate->RemoveCollisionModelsFromSystem();
+}
+
+
+
+//////// FILE I/O
+
+void ChConveyor::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChBody::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->conveyor_speed;
+	this->conveyor_plate->StreamOUT(mstream);
+	this->internal_link->StreamOUT(mstream);
+}
+
+void ChConveyor::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChBody::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> this->conveyor_speed;
+	this->conveyor_plate->StreamIN(mstream);
+	this->internal_link->StreamIN(mstream);
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChConveyor.h b/SRC/ChronoEngine/physics/ChConveyor.h
new file mode 100644
index 0000000..3e89bce
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChConveyor.h
@@ -0,0 +1,165 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHCONVEYOR_H
+#define CHCONVEYOR_H
+
+//////////////////////////////////////////////////
+//
+//   ChConveyor.h
+//
+//   Class for conveyor belt (approximated by 
+//   parallelepiped with moving surface)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "physics/ChBody.h"
+#include "physics/ChLinkLock.h"
+
+
+
+namespace chrono
+{
+
+
+
+
+///
+/// Class for conveyor belt. 
+/// A conveyor belt is approximated by a box collision
+/// shape, where the upper surface has continuous motion
+/// in X direction. No cylindrical rounding is used at the ends.
+///
+
+class ChApi ChConveyor : public ChBody 
+{
+
+	CH_RTTI(ChConveyor,ChBody);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double conveyor_speed;	// speed of conveyor, along the X direction of the box.
+		
+						// link between this body and conveyor plate 
+	ChLinkLockLock* internal_link;
+
+						// used for the conveyor plate
+	ChBody* 		conveyor_plate;
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a conveyor belt, with motion along x axis
+	ChConveyor (double xlength = 1, double ythick = 0.1, double zwidth =0.5);
+				/// Destructor
+	~ChConveyor ();
+
+				/// Copy from another ChChConveyor. 
+	void Copy(ChConveyor* source);
+
+
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Set the speed of the conveyor belt (upper part, X direction)
+	void   SetConveyorSpeed(double mspeed) {conveyor_speed = mspeed;}
+				/// Get the speed of the conveyor belt (upper part, X direction)
+	double GetConveyorSpeed() {return conveyor_speed;}
+
+
+				/// Number of coordinates of the rigid body =6 (but other 6 variables are
+				/// used internally for the motion of the belt surface, as a rigid 3d plate)
+	virtual int GetDOF  ()   {return 6;}
+
+
+			 // Override/implement LCP system functions of ChPhysicsItem
+			 // (to assembly/manage data for LCP system solver)
+
+	virtual void InjectVariables(ChLcpSystemDescriptor& mdescriptor);
+	virtual void VariablesFbReset();
+	virtual void VariablesFbLoadForces(double factor=1.);
+	virtual void VariablesQbLoadSpeed();
+	virtual void VariablesFbIncrementMq();
+	virtual void VariablesQbSetSpeed(double step=0.);
+	virtual void VariablesQbIncrementPosition(double step);
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsBiLoad_Qc(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+
+			   // Other functions
+
+	virtual bool GetCollide() {return true;};
+	virtual void SyncCollisionModels();
+	virtual void AddCollisionModelsToSystem();
+	virtual void RemoveCollisionModelsFromSystem();
+
+	
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the conveyor at given time
+	virtual void Update (double mytime);
+
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+	
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChEvents.cpp b/SRC/ChronoEngine/physics/ChEvents.cpp
new file mode 100644
index 0000000..f9133df
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChEvents.cpp
@@ -0,0 +1,103 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChEvents.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+#include "physics/ChEvents.h"
+
+namespace chrono 
+{ 
+ 
+/////////////////////////////////////////////////////////
+/// 
+///   EVENT BUFFER CLASS
+///
+///
+
+
+ChEvents::ChEvents (int m_events)
+{
+	maxevents = m_events;
+	current_event = 0;
+	ebuffer = (int*) calloc (maxevents, sizeof(int));
+	memset(ebuffer, 0, (sizeof(int)*maxevents));
+}
+
+ChEvents::ChEvents ()
+{
+	maxevents = CHCLASS_EVENTS_DEFAULTNUM;
+	current_event = 0;
+	ebuffer = (int*) calloc (maxevents, sizeof(int));
+	memset(ebuffer, 0, (sizeof(int)*maxevents));
+}
+
+ChEvents::~ChEvents ()
+{
+	free(ebuffer);
+}
+
+void ChEvents::ResetAllEvents()
+{
+	memset(ebuffer, 0, (sizeof(int)*maxevents));
+}
+
+void ChEvents::Record (int m_event)
+{
+	// increase pointer 
+	current_event++;
+	// if end of buffer, repeat cycle
+	if (current_event>=maxevents) current_event = 0;
+	// store new;
+	*(ebuffer+current_event) = m_event; 
+}	
+
+int ChEvents::GetN(int n_back)
+{
+	if (n_back >= maxevents) n_back = maxevents -1; 
+	int po = current_event - n_back;
+	if (po < 0) po = maxevents + po;
+	return *(ebuffer+po);
+}
+
+void ChEvents::SetN(int n_back, int m_event)
+{
+	if (n_back >= maxevents) n_back = maxevents -1; 
+	int po = current_event - n_back;
+	if (po < 0) po = maxevents + po;
+	*(ebuffer+po) = m_event;
+}
+	
+int ChEvents::GetLast()
+{
+	return *(ebuffer+current_event);
+}
+
+
+ 
+} // END_OF_NAMESPACE____
+
+////// end
diff --git a/SRC/ChronoEngine/physics/ChEvents.h b/SRC/ChronoEngine/physics/ChEvents.h
new file mode 100644
index 0000000..dbd7df3
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChEvents.h
@@ -0,0 +1,101 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHEVENTS_H
+#define CHEVENTS_H
+
+//////////////////////////////////////////////////
+//  
+//   ChEvents.h
+//
+//   Class for simple event recorder (cyclic buffer)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include <string>
+#include "core/ChApiCE.h"
+
+namespace chrono 
+{
+ 
+	
+
+#define CHCLASS_EVENTS_DEFAULTNUM 100		
+
+///
+/// Class for a quick cyclic event recorder. It takes
+/// really few resources and CPU cycles.
+///
+
+class ChApi ChEvents {
+protected:
+
+
+	int*	ebuffer;
+	int		current_event;
+	int		maxevents;
+public:	
+	ChEvents ();
+	ChEvents (int m_events);
+	~ChEvents ();
+
+		// Store the event coded "m_event" and increment position
+	void Record (int m_event);
+	
+		// Get the event "n_back" positions before the last one,
+		// n_back = 0 returns the last, n_back = 1 the one before the last, etc.
+	int GetN(int n_back);
+		// Same, but sets events.
+	void SetN(int n_back, int m_event);
+
+		// Get the last recorded event.
+	int GetLast();
+
+	int GetMaxEvents () {return maxevents;};
+		
+		// Reset all events to zero, and rewind counter to beginning.
+	void ResetAllEvents();
+};
+
+
+
+
+
+// Some CHRONO-specific event identifiers...
+
+#define	CHEVENT_NONE		0
+#define	CHEVENT_SETUP		1
+#define	CHEVENT_UPDATE		2
+#define	CHEVENT_INTSTEP		3
+#define	CHEVENT_REDOSTEP	4
+#define	CHEVENT_ASSEMBLY	5
+#define	CHEVENT_LIMIT		6
+#define	CHEVENT_R3DSTEP		7
+#define CHEVENT_COMPUTEYDT  8
+#define CHEVENT_TIMESTEP    9
+#define CHEVENT_COLLISION  10
+#define CHEVENT_OPENMONOL  11
+#define	CHEVENT_REWINDCOLL 12
+
+#define	CHEVENTS_TOTAL	   12	// ***TO UPDATE all times a new event type is added above.
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif  // END of ChEvents.h 
diff --git a/SRC/ChronoEngine/physics/ChExternalObject.h b/SRC/ChronoEngine/physics/ChExternalObject.h
new file mode 100644
index 0000000..f76122b
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChExternalObject.h
@@ -0,0 +1,158 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHEXTERNALOBJECT_H
+#define CHEXTERNALOBJECT_H
+
+//////////////////////////////////////////////////
+//
+//   ChExternalObject.h
+//
+//   Interface to external object (3rd party objects
+//   in 3d modelers, for example).
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChMatrix.h"  // ***g++
+#include "core/ChApiCE.h"
+
+
+namespace chrono
+{
+
+
+// Forward references
+namespace collision
+{
+class ChCollisionModel;
+}
+class ChBody;
+
+
+
+///
+///  This class is used by ChObj as an interface to external
+/// object, that is 3rd party objects which may 'encapsulate'
+/// chrono objects inherited by the ChObj class.
+///  For example, a chrono ChBody object may be a property of a
+/// geometric object in a 3D modeler (for example a R3OBJ* in case
+/// of a plugin for the Realsoft3D software, or a SceneNode in case
+/// of Irrlicht rendering engine, etc.)
+///  Thank to this abstract interface, the chrono engine can 'talk'
+/// to the external encapsulator.
+///  Each custom implementation will provide the proper inherited version
+/// of this class, for example there may be a ChExtrenalObjectIrrlicht
+/// class, etc.
+///
+
+class ChApi ChExternalObject
+{
+	CH_RTTI_ROOT(ChExternalObject);
+
+public:
+
+			//
+			// DATA
+			//
+
+	// No data in this 'default' reference, doing nothing...
+	// 3rd party developers should derive from this class in order to
+	// make references to external objects.
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChExternalObject() {};
+	virtual ~ChExternalObject() {};
+
+				/// Important!!! Derived classes MUST implement this
+				/// function!
+	virtual ChExternalObject* new_Duplicate() = 0;
+
+			//
+			// FUNCTIONS AND 'CALLBACKS'.
+			//
+
+				/// Interface to get the name of r3d-party encapsulator object,
+				/// Derived classes may implement this.
+	virtual char* GetName() {return NULL;};
+
+				/// Interface to move the r3d-party encapsulator object.
+				/// This function will be called each time a chrono object moves
+				/// at the end of a frame simulation.
+				/// Derived classes may implement this and take the proper actions.
+	virtual void onChronoChanged() {};
+
+				/// Interface used by ChProbe() objects to tell that Chrono has completed a
+				/// simulation step, at time 'mtime', and recording of data
+				/// into external probe object is required for that time instant.
+				/// Derived classes may implement this and take the proper actions.
+	virtual void onChronoProbeRecord(double mtime) {};
+
+				/// Interface used by ChProbe() objects to tell that Chrono wants the
+				/// recorded data in external probe object to be reset/deleted.
+				/// Derived classes may implement this and take the proper actions.
+	virtual void onChronoProbeReset() {};
+
+				/// Interface to tell that Chrono wants the 3rd-party encapsulator
+				/// object to add collision geometries (for example, in a plugin implementation,
+				/// here a conversion to native 3d objects to chrono collision objects may take
+				/// place.) The required level of detail of conversion is 'lod'.
+	virtual void onAddCollisionGeometries(collision::ChCollisionModel* chmodel, ChBody* mbody, int lod, ChVector<double>* mt, ChMatrix33<double>* mr) {};
+
+				/// Interface to access the N-th sub-object 
+				/// (n-th child in tree hieararchy, if any).
+				/// This _creates_ a ChExternalObject object enclosing the n-th child.
+				/// If not success, or nc too high, return 0.
+				/// Derived classes may implement this and take the proper actions.
+	virtual ChExternalObject* GetNthChild(int nc) {return 0;};
+	
+				/// Given a name, _creates_ a ChExternalObject object enclosing
+				/// an item whose name matches.
+				/// If not success, returned 0.
+				/// Derived classes may implement this and take the proper actions.
+	virtual ChExternalObject* GetChildByName(char* mname) {return 0;};
+
+				/// Returns position as ChCoordsys, if possible
+	virtual ChCoordsys<> GetPos() {return CSYSNULL;}
+				/// Set position, if possible
+	virtual void SetPos(ChCoordsys<> mpos) {}
+
+				/// Computes position at parametric u,v values, if it's a surface
+	virtual ChVector<> Eval(double u, double v, double w) {return VNULL;}
+				/// Computes normal at parametric u,v values, if it's a surface
+	virtual ChVector<> Normal(double u, double v, double w) {return VNULL;}
+
+};
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif  // END of ChCoordsys.h
diff --git a/SRC/ChronoEngine/physics/ChForce.cpp b/SRC/ChronoEngine/physics/ChForce.cpp
new file mode 100644
index 0000000..10634e7
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChForce.cpp
@@ -0,0 +1,484 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChForce.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+
+#include <math.h>
+
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+#include "physics/ChForce.h"
+#include "physics/ChBody.h"
+#include "physics/ChExternalObject.h"
+ 
+
+namespace chrono
+{
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+// CLASS FOR FORCES
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChForce> a_registration_ChForce;
+
+
+
+///////////////////////////////////////
+
+ChForce::ChForce()
+{
+	Body = NULL;
+
+	Qf = new ChMatrixDynamic<double>(BODY_QDOF,1);
+	vpoint = VNULL;
+	vrelpoint = VNULL;
+	force = VNULL;
+	relforce = VNULL;
+	vdir   = VECT_X;
+	vreldir = VECT_X;
+	restpos = VNULL;
+	mforce = 0;
+	modula =   new ChFunction_Const (1);
+
+	align = FDIR_BODY;
+	frame = FPOS_BODY;
+	mode = FTYPE_FORCE;
+
+	move_x = new ChFunction_Const (0);
+	move_y = new ChFunction_Const (0);
+	move_z = new ChFunction_Const (0);
+	f_x = new ChFunction_Const (0);
+	f_y = new ChFunction_Const (0);
+	f_z = new ChFunction_Const (0);
+
+	ChTime = 0;
+}
+
+ChForce::~ChForce ()
+{
+	delete Qf;
+	if (modula) delete modula;
+	if (move_x) delete move_x;
+	if (move_y) delete move_y;
+	if (move_z) delete move_z;
+	if (f_x) delete f_x;
+	if (f_y) delete f_y;
+	if (f_z) delete f_z;
+}
+
+void ChForce::Copy(ChForce* source)
+{
+	// first copy the parent class data...
+	ChObj::Copy(source);
+
+	Body = source->Body;
+
+	mforce = source->mforce;
+	force = source->force;
+	relforce = source->relforce;
+	vdir   = source->vdir;
+	vreldir = source->vreldir;
+	vpoint = source->vpoint;
+	vrelpoint = source->vrelpoint;
+	restpos = source->restpos;
+	align = source->align;
+	frame = source->frame;
+	mode = source->mode;
+
+	ChTime = source->ChTime;
+
+	Qf->CopyFromMatrix(*source->Qf);
+
+	if (modula) delete modula;
+	if (source->modula) modula = source->modula->new_Duplicate();
+		else modula = NULL;
+	if (move_x) delete move_x;
+	if (source->move_x) move_x = source->move_x->new_Duplicate();
+		else move_x = NULL;
+	if (move_y) delete move_y;
+	if (source->move_y) move_y = source->move_y->new_Duplicate();
+		else move_y = NULL;
+	if (move_z) delete move_z;
+	if (source->move_z) move_z = source->move_z->new_Duplicate();
+		else move_z = NULL;
+	if (f_x) delete f_x;
+	if (source->f_x) f_x = source->f_x->new_Duplicate();
+		else f_x = NULL;
+	if (f_y) delete f_y;
+	if (source->f_y) f_y = source->f_y->new_Duplicate();
+		else f_y = NULL;
+	if (f_z) delete f_z;
+	if (source->f_z) f_z = source->f_z->new_Duplicate();
+		else f_z = NULL;
+}
+
+//////
+
+
+
+void ChForce::SetModulation	(ChFunction* m_funct)
+{
+	if (modula) delete modula;
+	modula = m_funct;
+}
+void ChForce::SetMove_x	(ChFunction* m_funct)
+{
+	if (move_x) delete move_x;
+	move_x = m_funct;
+}
+void ChForce::SetMove_y	(ChFunction* m_funct)
+{
+	if (move_y) delete move_y;
+	move_y = m_funct;
+}
+void ChForce::SetMove_z	(ChFunction* m_funct)
+{
+	if (move_z) delete move_z;
+	move_z = m_funct;
+}
+void ChForce::SetF_x	(ChFunction* m_funct)
+{
+	if (f_x) delete f_x;
+	f_x = m_funct;
+}
+void ChForce::SetF_y	(ChFunction* m_funct)
+{
+	if (f_y) delete f_y;
+	f_y = m_funct;
+}
+void ChForce::SetF_z	(ChFunction* m_funct)
+{
+	if (f_z) delete f_z;
+	f_z = m_funct;
+}
+
+
+
+////// Impose absolute or relative positions, also
+//     setting the correct "rest position".
+
+void ChForce::SetVpoint (Vector mypoint)
+{
+			// abs pos
+	vpoint   = mypoint;
+			// rel pos
+	vrelpoint= GetBody()->Point_World2Body(&vpoint);
+			// computes initial rest position.
+	Vector displace = VNULL;
+	if (move_x) displace.x = move_x->Get_y(ChTime);
+	if (move_y) displace.y = move_y->Get_y(ChTime);
+	if (move_z) displace.z = move_z->Get_y(ChTime);
+	if (frame == FPOS_WORLD)
+		restpos = Vsub (vpoint, displace);
+	if (frame == FPOS_BODY)
+		restpos = Vsub (vrelpoint, displace);
+};
+
+void ChForce::SetVrelpoint (Vector myrelpoint)
+{
+			// rel pos
+	vrelpoint= myrelpoint;
+			// abs pos
+	vpoint   = GetBody()->Point_Body2World(&vrelpoint);
+			// computes initial rest position.
+	Vector displace = VNULL;
+	if (move_x) displace.x = move_x->Get_y(ChTime);
+	if (move_y) displace.y = move_y->Get_y(ChTime);
+	if (move_z) displace.z = move_z->Get_y(ChTime);
+	if (frame == FPOS_WORLD)
+		restpos = Vsub (vpoint, displace);
+	if (frame == FPOS_BODY)
+		restpos = Vsub (vrelpoint, displace);
+};
+
+
+////// Impose absolute or relative force directions
+
+void ChForce::SetDir (Vector newf)
+{
+	vdir = Vnorm(newf);
+	vreldir = GetBody()->Dir_World2Body(&vdir);
+	UpdateState(); // update also F
+}
+
+void ChForce::SetRelDir (Vector newf)
+{
+	vreldir = Vnorm(newf);
+	vdir = GetBody()->Dir_Body2World(&vreldir);
+	UpdateState(); // update also F
+}
+
+////// Impose module
+
+void ChForce::SetMforce (double newf)
+{
+	mforce = newf;
+	UpdateState(); // update also F
+}
+
+
+////// force as applied to body
+void ChForce::GetBodyForceTorque (Vector* body_force, Vector* body_torque)
+{
+	ChMatrix33<> Xpos;
+
+	switch (mode)
+	{
+	case FTYPE_FORCE:
+		*body_force = this->force;				  // Fb = F.w
+
+		Xpos.Set_X_matrix (this->vrelpoint);
+		*body_torque= Xpos.MatrT_x_Vect(this->relforce);
+		*body_torque= Vmul (*body_torque, -1.0);  // Mb = - [u]'[A]'F,w   = - [u]'F,l
+		break;
+
+	case FTYPE_TORQUE:
+		*body_force = VNULL;				 	 // Fb = 0;
+		*body_torque = relforce;				 // Mb = [A]'F,w   = F,l
+		break;
+
+	default:
+		break;
+	}
+}
+
+//////
+////// Updating
+//////
+
+
+
+void ChForce::UpdateTime (double mytime)
+{
+	ChTime = mytime;
+
+	//... put time-sensitive stuff here..
+}
+
+void ChForce::UpdateState ()
+{
+	ChBody* my_body;
+	double modforce;
+	Vector vectforce;
+	Vector vmotion;
+	Vector xyzforce;
+	ChMatrixNM<double,3,1> mat_force;
+	ChMatrix33<> Xpos;
+	ChMatrixNM<double,4,1> Qfrot;
+
+	my_body = GetBody();
+
+
+	// ====== Update the position of point of application
+
+	vmotion = VNULL;
+	if (move_x) vmotion.x = move_x->Get_y(ChTime);
+	if (move_y) vmotion.y = move_y->Get_y(ChTime);
+	if (move_z) vmotion.z = move_z->Get_y(ChTime);
+
+	switch  (frame)
+	{
+	case FPOS_WORLD:
+		vpoint = Vadd (restpos, vmotion);	// Uw
+		vrelpoint = my_body->Point_World2Body(&vpoint); // Uo1 = [A]'(Uw-Xo1)
+		break;
+	case FPOS_BODY:
+		vrelpoint = Vadd (restpos, vmotion);	// Uo1
+		vpoint = my_body->Point_Body2World(&vrelpoint); // Uw = Xo1+[A]Uo1
+		break;
+	}
+
+
+	// ====== Update the fm force vector and add fv
+
+	modforce = mforce * modula->Get_y(ChTime);
+
+	vectforce = VNULL;
+	xyzforce = VNULL;
+	if (f_x) xyzforce.x = f_x->Get_y(ChTime);
+	if (f_y) xyzforce.y = f_y->Get_y(ChTime);
+	if (f_z) xyzforce.z = f_z->Get_y(ChTime);
+
+	switch  (align)
+	{
+	case FDIR_WORLD:
+		vreldir = my_body->Dir_World2Body(&vdir);
+		vectforce = Vmul (vdir, modforce);
+		vectforce = Vadd (vectforce, xyzforce);
+		break;
+	case FDIR_BODY:
+		vdir = my_body->Dir_Body2World(&vreldir);
+		vectforce = Vmul (vdir, modforce);
+		xyzforce = my_body->Dir_Body2World(&xyzforce);
+		vectforce = Vadd (vectforce, xyzforce);
+		break;
+	}
+
+	force = vectforce;	// Fw
+	relforce = my_body->Dir_World2Body(&force); // Fo1 = [A]'Fw
+
+	// ====== Update the Qc lagrangian!
+
+	switch (mode)
+	{
+	case FTYPE_FORCE:
+		{
+		Qf->SetElement(0,0,force.x);	// pos.lagrangian Qfx
+		Qf->SetElement(1,0,force.y);
+		Qf->SetElement(2,0,force.z);
+											//   Qfrot= (-[A][u][G])'f
+		Vector VQtemp;
+
+		Xpos.Set_X_matrix (vrelpoint);
+
+		VQtemp= Xpos.MatrT_x_Vect(relforce);  // = [u]'[A]'F,w
+
+		mat_force.PasteVector (VQtemp,0,0);
+
+		ChMatrixNM<double,3,4> mGl;
+		ChFrame<>::SetMatrix_Gl(mGl, my_body->GetCoord().rot);
+
+		Qfrot.MatrTMultiply (mGl, mat_force);
+		Qfrot.MatrNeg();				// Q = - [Gl]'[u]'[A]'F,w
+		Qf->PasteMatrix (&Qfrot, 3,0);
+		break;
+		}
+
+	case FTYPE_TORQUE:
+		Qf->SetElement(0,0,0);	// pos.lagrangian Qfx
+		Qf->SetElement(1,0,0);
+		Qf->SetElement(2,0,0);
+
+								// rot.lagangian
+		mat_force.PasteVector (relforce,0,0);
+
+		ChMatrixNM<double,3,4> mGl;
+		ChFrame<>::SetMatrix_Gl(mGl, my_body->GetCoord().rot);
+
+		Qfrot.MatrTMultiply (mGl, mat_force);
+		Qf->PasteMatrix (&Qfrot, 3,0);
+
+		break;
+	}
+}
+
+void ChForce::Update (double mytime)
+{
+	UpdateTime (mytime);
+	UpdateState ();
+}
+
+
+void ChForce::UpdateExternalGeometry ()
+{
+	if (GetExternalObject())
+		GetExternalObject()->onChronoChanged();
+}
+
+
+
+
+////// File  I/O
+
+
+
+void ChForce::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChObj::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << GetMode();
+	mstream << GetFrame();
+	mstream << GetAlign();
+	mstream << vrelpoint;
+	mstream << vpoint;
+	mstream.AbstractWrite(this->move_x);
+	mstream.AbstractWrite(this->move_y);
+	mstream.AbstractWrite(this->move_z);
+	mstream << restpos;
+	mstream.AbstractWrite(this->f_x);
+	mstream.AbstractWrite(this->f_y);
+	mstream.AbstractWrite(this->f_z);
+	mstream << GetMforce();
+	mstream.AbstractWrite(this->modula);
+	mstream << vreldir;
+	mstream << vdir;
+}
+
+void ChForce::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChObj::StreamIN(mstream);
+
+		// stream in all member data
+	double dfoo;
+	int    ifoo;
+	Vector vfoo;
+	ChFunction* ffoo;
+
+	mstream >> ifoo;				SetMode(ifoo);
+	mstream >> ifoo;				SetFrame(ifoo);
+	mstream >> ifoo;				SetAlign(ifoo);
+	mstream >> vfoo;				SetVrelpoint(vfoo);
+	mstream >> vfoo;				SetVpoint(vfoo);
+	mstream.AbstractReadCreate(&ffoo);			SetMove_x(ffoo);
+	mstream.AbstractReadCreate(&ffoo);			SetMove_y(ffoo);
+	mstream.AbstractReadCreate(&ffoo);			SetMove_z(ffoo);
+	mstream >> vfoo;				//SetRestpos(dfoo);//not needed,
+	mstream.AbstractReadCreate(&ffoo);			SetF_x(ffoo);
+	mstream.AbstractReadCreate(&ffoo);			SetF_y(ffoo);
+	mstream.AbstractReadCreate(&ffoo);			SetF_z(ffoo);
+	mstream >> dfoo;				SetMforce(dfoo);
+	mstream.AbstractReadCreate(&ffoo);			SetModulation(ffoo);
+	mstream >> vfoo;				SetRelDir(vfoo);
+	mstream >> vfoo;				SetDir(vfoo);
+}
+
+void ChForce::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream << "FORCE   " << GetName() <<"\n";
+
+	//***TO DO***
+}
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+///// eof
+
diff --git a/SRC/ChronoEngine/physics/ChForce.h b/SRC/ChronoEngine/physics/ChForce.h
new file mode 100644
index 0000000..4c51be2
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChForce.h
@@ -0,0 +1,246 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFORCE_H
+#define CHFORCE_H
+
+//////////////////////////////////////////////////
+//
+//   ChForce.h
+//
+//   Force definition.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+#include "core/ChLog.h"
+#include "core/ChMath.h"
+#include "physics/ChFunction.h"
+#include "physics/ChObject.h"
+
+
+namespace chrono
+{
+
+// Forward reference
+class ChBody;
+
+
+#define CHCLASS_FORCE 3
+
+///////////////////////////////
+
+// Types of force application
+
+#define FTYPE_FORCE   0
+#define FTYPE_TORQUE  1
+
+// Reference for alignment
+
+#define FDIR_BODY     0
+#define FDIR_WORLD    1
+
+// Reference for position frame
+
+#define FPOS_BODY     0
+#define FPOS_WORLD    1
+
+
+//  CHFORCE
+/// Forces are objects which must be attached to
+/// rigid bodies in order to apply torque or force to
+/// such body. ChForce objects are able to represent
+/// either forces and torques, depending on a flag.
+
+class ChApi ChForce : public ChObj
+{
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChForce,ChObj);
+
+private:
+				//
+	  			// DATA
+				//
+
+	ChBody* Body;		// object of application
+
+	int mode;			// force or torque
+
+	int frame;			// fix position  in body csys or world csys
+	int align;			// fix direction in body csys or world csys
+
+	Vector vpoint;		// absolute point of application
+	Vector vrelpoint;	// relative point of application
+
+	ChFunction* move_x;	// motion x (abs or rel, depends on 'frame')
+	ChFunction* move_y;	// motion y  ""
+	ChFunction* move_z;	// motion z  ""
+	Vector restpos;		// t=0 position (abs or rel, depends on 'frame')
+
+	ChFunction* f_x;	// fv strengh x (abs or rel, see 'align')
+	ChFunction* f_y;	// fv strengh y  ""
+	ChFunction* f_z;	// fv strengh z  ""
+
+	double mforce;		// fm scalar force strenght
+	ChFunction* modula;	// scalar force fm modulation
+
+	Vector vdir;		// force/torque abs.direction
+	Vector vreldir;		// force/torque rel direction
+
+	Vector force;		// TOTAL force vect (abs.coord) = fm*vdir +fx+fy+fz
+	Vector relforce;	// TOTAL force vect (rel.coord) = fm*vdir +fx+fy+fz
+
+	ChMatrixDynamic<>* Qf;// lagrangian force
+
+public:
+				//
+	  			// CONSTRUCTION
+				//
+	ChForce ();
+	~ChForce();
+	void Copy(ChForce* source);
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Return the parent body (the force belongs to this rigid body)
+	ChBody* GetBody () { return Body;}
+					/// Sets the parent body (the force belongs to this rigid body)
+	void SetBody (ChBody* newRB) {Body = newRB;}
+
+					/// Sets the mode: FTYPE_FORCE or FTYPE_TORQUE
+	void SetMode (int m_mode) {mode = m_mode;};
+	int GetMode () {return mode;};
+
+					/// Sets the alignment method: FDIR_BODY or FDIR_WORLD. (the
+					/// force will rotate together with this reference.
+	void SetAlign (int m_align) {align = m_align;};
+	int  GetAlign () {return align;};
+
+					/// Sets the alignment method: FPOS_BODY or FPOS_WORLD. (the
+					/// force application point will follow this reference)
+	void SetFrame (int m_frame) {frame = m_frame; SetVpoint(vpoint);};
+	int  GetFrame () {return frame;};
+
+					/// Gets the application point, in absolute coordinates.
+	Vector GetVpoint () {return vpoint;};
+					/// Gets the application point, in rigid body coordinates.
+	Vector GetVrelpoint () {return vrelpoint;};
+
+					/// Gets the application point, in absolute coordinates.
+	void SetVpoint (Vector mypoint);
+					/// Gets the application point, in rigid body coordinates.
+	void SetVrelpoint (Vector myrelpoint);
+
+					/// Gets the force (or torque) direction, in absolute coordinates.
+	Vector GetDir () {return vdir;};
+					/// Gets the force (or torque) direction, in rigid body coordinates.
+	Vector GetRelDir () {return vreldir;};
+					/// Sets the force (or torque) direction, in absolute coordinates.
+	void SetDir (Vector newf);
+					/// Sets the force (or torque) direction, in rigid body coordinates.
+	void SetRelDir (Vector newf);
+
+					/// Sets force (or torque) modulus.
+	void SetMforce (double newf);
+					/// Gets force (or torque) modulus.
+	double GetMforce () {return mforce;};
+
+					/// Sets a f(t) function for time-modulation of the force.
+	void SetModulation	(ChFunction* m_funct);
+	ChFunction* GetModulation() {return modula;};
+
+					/// Sets a f(t) function for time dependency of position (on x axis)
+	void SetMove_x	(ChFunction* m_funct);
+	ChFunction* GetMove_x() {return move_x;};
+					/// Sets a f(t) function for time dependency of position (on y axis)
+	void SetMove_y	(ChFunction* m_funct);
+	ChFunction* GetMove_y() {return move_y;};
+					/// Sets a f(t) function for time dependency of position (on z axis)
+	void SetMove_z	(ChFunction* m_funct);
+	ChFunction* GetMove_z() {return move_z;};
+
+					/// Sets a f(t) function for time dependency of force X component.
+	void SetF_x	(ChFunction* m_funct);
+	ChFunction* GetF_x() {return f_x;};
+					/// Sets a f(t) function for time dependency of force Y component.
+	void SetF_y	(ChFunction* m_funct);
+	ChFunction* GetF_y() {return f_y;};
+					/// Sets a f(t) function for time dependency of force Z component.
+	void SetF_z	(ChFunction* m_funct);
+	ChFunction* GetF_z() {return f_z;};
+
+					/// Gets the instant force vector -or torque vector- in absolute coordinates.
+	Vector GetForce () {return force;};
+					/// Gets the instant force vector -or torque vector- in rigid body coordinates.
+	Vector GetRelForce () {return relforce;};
+					/// Gets the instant force vector -or torque vector- modulus.
+	double GetForceMod () {return Vlenght(force);};
+
+					/// Gets force-torque applied to rigid body, as lagrangian generalized force (7x1 matrix).
+	ChMatrix<>* GetQf () {return Qf;}
+					/// Gets force-torque applied to rigid body, as force vector (in absol.coords)
+					/// and torque vector (in body coords).
+	void GetBodyForceTorque (Vector* body_force, Vector* body_torque);
+
+			// Updating
+
+	void UpdateTime (double mytime);
+	void UpdateState ();
+	void Update (double mytime);
+
+				/// Tells to the associated external object ChExternalObject() ,if any,
+				/// that its 3D shape must be updated in order to syncronize to ChForce
+				/// coordinates
+	void UpdateExternalGeometry ();
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream);
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChFunction.cpp b/SRC/ChronoEngine/physics/ChFunction.cpp
new file mode 100644
index 0000000..f2aea7a
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChFunction.cpp
@@ -0,0 +1,34 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChFunction.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChFunction.h"
+
+
+namespace chrono
+{
+
+
+
+} // END_OF_NAMESPACE____
+
+
+// eof
diff --git a/SRC/ChronoEngine/physics/ChFunction.h b/SRC/ChronoEngine/physics/ChFunction.h
new file mode 100644
index 0000000..6e43d35
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChFunction.h
@@ -0,0 +1,31 @@
+#ifndef CHFUNCT_H
+#define CHFUNCT_H
+
+
+// 
+// FOR BACKWARD COMPABILITY:  INCLUDE HEADERS OF 19 FUNCTIONS THAT ONCE WERE HERE IN SAME FILE
+//
+
+#include "motion_functions/ChFunction_Const.h"
+#include "motion_functions/ChFunction_Const.h"
+#include "motion_functions/ChFunction_ConstAcc.h"
+#include "motion_functions/ChFunction_Derive.h"
+#include "motion_functions/ChFunction_Fillet3.h"
+#include "motion_functions/ChFunction_Integrate.h"
+#include "motion_functions/ChFunction_Matlab.h"
+#include "motion_functions/ChFunction_Mirror.h"
+#include "motion_functions/ChFunction_Mocap.h"
+#include "motion_functions/ChFunction_Noise.h"
+#include "motion_functions/ChFunction_Operation.h"
+#include "motion_functions/ChFunction_Oscilloscope.h"
+#include "motion_functions/ChFunction_Poly345.h"
+#include "motion_functions/ChFunction_Poly.h"
+#include "motion_functions/ChFunction_Ramp.h"
+#include "motion_functions/ChFunction_Recorder.h"
+#include "motion_functions/ChFunction_Repeat.h"
+#include "motion_functions/ChFunction_Sequence.h"
+#include "motion_functions/ChFunction_Sigma.h"
+#include "motion_functions/ChFunction_Sine.h"
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChFx.cpp b/SRC/ChronoEngine/physics/ChFx.cpp
new file mode 100644
index 0000000..d1c08b7
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChFx.cpp
@@ -0,0 +1,34 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChFx.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChFx.h"
+
+
+
+namespace chrono
+{
+
+
+
+} // END_OF_NAMESPACE____
+
+// eof
+
diff --git a/SRC/ChronoEngine/physics/ChFx.h b/SRC/ChronoEngine/physics/ChFx.h
new file mode 100644
index 0000000..c7aff26
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChFx.h
@@ -0,0 +1,157 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHFX_H
+#define CHFX_H
+
+//////////////////////////////////////////////////
+//
+//   ChFx.h
+//
+//   Classes for object defining math functions of 
+//   the type A=f(B) , to be used in optimization/etc.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "core/ChMath.h"
+
+
+namespace chrono
+{
+
+
+/// Abstract interface class for math functions of the type A=f(B)
+/// where A and B are vectors of real values (to the limit, also
+/// single scalar values).
+
+class ChFx 
+{
+public:
+		/// INTERFACE: 
+		/// Evaluate A=f(B) 
+		/// Pure virtual member: it _must_ be implemented by inherited classes.
+		/// The parameters B and the results A are column-matrices (vectors of scalars).
+	virtual void Eval  (      ChMatrix<>& A,	///< result output variables here
+						const ChMatrix<>& B		///< input variables here
+					   ) =0;
+};
+
+
+
+
+/// Class for A=f(B) math functions, where the function
+/// is defined by wrapping a C function of the 'old' type,
+/// i.e. a pointer to simple C call that works over arrays of doubles and return one value:
+///   double (*func)(double p[], void* my_data);
+/// as often used in C/C++ math libraries.
+
+class ChFxCfunctionS : public ChFx
+{
+public:
+		/// Create the function wrapper.
+	ChFxCfunctionS(	double (*mfunc)(double p[],void* my_data), ///< the pointer to the C function
+					int minvars,	///< the number of input vars (the size of double p[])
+					void* mdata=0	///< generic user data, if needed as my_data for C function.
+					)
+		{
+			func = mfunc;
+			n_invars = minvars; 
+			user_data = mdata;
+			invars  = new double[n_invars];
+		}
+	virtual ~ChFxCfunctionS()
+		{
+			delete[] invars;
+		}
+
+		/// INTERFACE: 
+		/// Evaluate A=f(B) 
+	virtual void Eval  (ChMatrix<>& A,			///< result  here
+						const ChMatrix<>& B		///< input here
+					   )
+		{
+			for(int i=0; i<A.GetRows(); i++) invars[i] = B(i,0);
+			double out = this->func(this->invars, this->user_data);
+			A(0,0)= out;
+		}
+private:
+	void* user_data;
+	int n_invars;
+	double* invars;
+	double (*func)(double p[], void* my_data);
+};
+
+
+
+/// Class for A=f(B) math functions, where the function
+/// is defined by wrapping a C function of the 'old' type,
+/// i.e. a pointer to simple C call that works over arrays of values and return array of values:
+///   double (*func)(double p[], void* my_data);
+/// as often used in C/C++ math libraries.
+
+class ChFxCfunction : public ChFx
+{
+public:
+		/// Create the function wrapper.
+	ChFxCfunction(	void (*mfunc)(double in[], double ou[], void* my_data), ///< the pointer to the C function
+					int minvars,	///< the number of input vars (the size of double in[])
+					int moutvars,	///< the number of output vars (the size of double ou[])
+					void* mdata=0	///< generic user data, if needed as my_data for C function.
+					)
+		{
+			func = mfunc;
+			n_invars = minvars;
+			n_outvars = moutvars;
+			user_data = mdata;
+			invars  = new double[n_invars];
+			outvars  = new double[n_outvars];
+		}
+	virtual ~ChFxCfunction()
+		{
+			delete[] invars;
+			delete[] outvars;
+		}
+
+		/// INTERFACE: 
+		/// Evaluate A=f(B) 
+	virtual void Eval  (	  ChMatrix<>& A,	///< results here
+						const ChMatrix<>& B		///< input here
+					   )
+		{
+			for(int i=0; i<A.GetRows(); i++) invars[i] = B(i,0);
+			this->func(this->invars, this->outvars, this->user_data);
+			for(int j=0; j<B.GetRows(); j++) A(j,0) = outvars[j];
+		}
+private:
+	void* user_data;
+	int n_invars;
+	int n_outvars;
+	double* invars;
+	double* outvars;
+	void (*func)(double in[], double out[], void* my_data);
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChGlobal.cpp b/SRC/ChronoEngine/physics/ChGlobal.cpp
new file mode 100644
index 0000000..317787f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChGlobal.cpp
@@ -0,0 +1,102 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//  
+//   ChGlobal.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include <string.h> 
+#include <time.h>
+
+#include "physics/ChGlobal.h" 
+#include "physics/ChBody.h" 
+#include "physics/ChSystem.h" 
+ 
+ 
+namespace chrono 
+{
+
+//
+//
+// The global object pointer, and global functions
+//
+
+ChGlobals* GLOBAL_Vars =0;
+ 
+
+
+
+// The class members
+
+  
+ChGlobals::ChGlobals()
+{
+	WriteComments = 1;
+	WriteAllFeatures = 0;
+
+	t_duration = 0;
+
+	SkipNframesOutput = 0; 
+
+
+	time_t ltime;		// setup a safe unique first ID
+	struct tm *nt;
+	time (&ltime);
+	nt = localtime(&ltime);
+	int_identifier = (int)(3600*nt->tm_hour + 60*nt->tm_min + nt->tm_sec);
+
+}
+
+
+
+ChGlobals::~ChGlobals() 
+{
+	
+};
+
+
+
+//
+// The pointer to the global 'ChGlobals'
+//
+
+static ChGlobals*  GlobalGlobals = 0 ;
+
+ChGlobals& CHGLOBALS()
+{
+	if ( GlobalGlobals != NULL )
+        return (*GlobalGlobals);
+	else
+	{
+		static ChGlobals static_globals;
+		return static_globals;
+	}
+}
+
+void SetCHGLOBALS(ChGlobals* my_globals)
+{
+	GlobalGlobals = my_globals;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+// End
diff --git a/SRC/ChronoEngine/physics/ChGlobal.h b/SRC/ChronoEngine/physics/ChGlobal.h
new file mode 100644
index 0000000..ee8589c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChGlobal.h
@@ -0,0 +1,118 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHGLOBAL_H
+#define CHGLOBAL_H
+
+//////////////////////////////////////////////////
+//  
+//   ChGlobal.h
+//
+//   Global variables.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <time.h>
+#include <math.h>
+
+#include "core/ChLog.h"
+#include "core/ChApiCE.h"
+
+
+namespace chrono 
+{
+
+
+
+
+//////////////////////////////////////////////////
+/// Class for global CHRONO data, such as 
+/// serial number, static variables, static functions, 
+/// timers, etc.
+/// To be documented better...
+
+
+class ChApi ChGlobals
+{
+private:
+
+	int int_identifier;
+
+public:
+	ChGlobals();
+	~ChGlobals();
+
+	int WriteComments;
+	int WriteAllFeatures;
+	int SkipNframesOutput;
+	int angle_units;
+
+
+
+			/// Time utilities (better: use ChTime.h)
+	clock_t t_start, t_stop;
+    double  t_duration; 
+	double  t_simtime, t_geometrytime;
+	void Timer_START() {t_start = clock(); t_duration= 0;}
+	void Timer_STOP() {t_stop = clock(); t_duration +=  ((double)((double)(t_stop - t_start) / CLOCKS_PER_SEC));}
+	void Timer_RESTART() {t_start = clock();}
+
+
+			/// Return an unique identifier, of type integer. 
+	int GetUniqueIntID() {int_identifier++; return int_identifier;};
+
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////
+
+///
+///  DECLARE THAT THERE'S A GLOBAL POINTER TO A "GLOBAL_Vars" OBJECT!!!
+///  
+
+extern
+ChGlobals* GLOBAL_Vars;  ///***OBSOLETE*** better use the following..
+
+
+	/// Global function to get the current ChGlobals object
+	/// (this is an easy way to access a single instance of globally visible
+	/// data)
+ChApi 
+ChGlobals& CHGLOBALS();
+
+	/// Create an istance of ChGlobals, then use this function at the beginning 
+	/// of your program to set it as a globally visible data. 
+	/// So that following calls to CHGLOBALS() will always return it.
+	/// If setting 0, the default static globals will be returned by CHGLOBALS().
+ChApi 
+void SetCHGLOBALS(ChGlobals* my_globals);
+
+
+//
+//////////////////////////////////////////////////////////////////////////
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChHistory.cpp b/SRC/ChronoEngine/physics/ChHistory.cpp
new file mode 100644
index 0000000..e45706f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChHistory.cpp
@@ -0,0 +1,340 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChHistory.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChHistory.h"
+
+
+namespace chrono
+{
+
+ChHistory::ChHistory(int nvars, int nsteps)
+{
+	if (nsteps <1) {nsteps = 1;}
+
+	steps = nsteps;
+	vars = nvars;
+	current_Y = 0;
+
+	times = (double*) calloc (steps, sizeof(double));
+	Yvectors = (ChMatrix<>**) calloc (steps, sizeof(ChMatrix<>*));
+
+	for (int i=0; i < steps; ++i)
+	{
+		*(times + i) = 0;
+		ChMatrix<>* m_Y = new ChMatrixDynamic<>(vars,1);
+		*(Yvectors + i) = m_Y;
+	}
+}
+
+
+ChHistory::~ChHistory()
+{
+	for (int i=0; i < steps; ++i)
+	{
+		delete *(Yvectors + i);
+	}
+
+	free (Yvectors);
+	free (times);
+}
+
+void ChHistory::Setup(int newvars, int newsteps)
+{
+			// delete old matrices
+    int i;
+
+	for (i=0; i < steps; ++i)
+	{
+		delete *(Yvectors + i);
+	}
+
+	free (Yvectors);
+	free (times);
+
+			// instance new ones
+	steps = newsteps;
+	vars = newvars;
+	current_Y = 0;
+
+	times = (double*) calloc (steps, sizeof(double));
+	Yvectors = (ChMatrix<>**) calloc (steps, sizeof(ChMatrix<>*));
+
+	for (i=0; i < steps; ++i)
+	{
+		*(times + i) = 0;
+		*(Yvectors +i) = new ChMatrixDynamic<>(vars,1);
+	}
+}
+
+void ChHistory::Copy(ChHistory* source)
+{
+	Setup ( source->vars, source->steps);
+	current_Y = source->current_Y;
+
+	for (int i=0; i < steps; ++i)
+	{
+		*(times +i) = source->times[i];
+		(*(Yvectors +i))->CopyFromMatrix(**(source->Yvectors + i));
+	}
+}
+
+
+void ChHistory::Restart()
+{
+	for (int i=0; i < steps; ++i)
+	{
+		*(times + i) = 0;
+	}
+}
+
+
+int ChHistory::Get_arr_offset (int i)
+{
+		// range only in  -(steps-2) ...0..1
+	if (i < (2-steps)) {i = (2-steps);}
+	if (i >	   1	 ) {i = 1;}
+
+	int selected;
+	selected = (current_Y + i);
+
+		// modular cycling
+	if (selected >= steps) { selected = selected - steps;}
+	if (selected < 0)	   { selected = steps + selected;}
+
+	return (selected);
+}
+
+
+ChMatrix<>* ChHistory::Get_Y(int i)
+{
+	int sel;
+	sel = Get_arr_offset(i);
+
+	return *(Yvectors + sel);
+}
+
+double ChHistory::Get_Ytime(int i)
+{
+	int sel;
+	sel = Get_arr_offset(i);
+
+	return *(times + sel);
+}
+
+void ChHistory::Set_Ytime(int i, double newtime)
+{
+	int sel;
+	sel = Get_arr_offset(i);
+
+	*(times + sel) = newtime;
+}
+
+
+
+
+
+void ChHistory::ForwardStep()
+{
+	current_Y++;	// increments the offset of one,
+
+	if (current_Y >= steps)
+	{
+		current_Y = 0;	// if end of array, cycle back!
+	}
+}
+
+void ChHistory::BackwardStep()
+{
+	current_Y--;	// increments the offset of one,
+
+	if (current_Y < 0)
+	{
+		current_Y = (steps -1);	// if begin of array, go to end!
+	}
+}
+
+void ChHistory::ProceedStep(double m_dt)
+{
+	double newtime;
+
+	if (m_dt>0)
+	{
+		newtime= (Get_Ytime(0) + m_dt);
+		ForwardStep();
+		Set_now_time (newtime);
+	}
+
+	if (m_dt<0)
+	{
+		newtime= (Get_Ytime(0) + m_dt);
+		BackwardStep();
+		Set_now_time (newtime);
+	}
+}
+
+
+int ChHistory::GetNsequenced(double maxstep)
+{
+	int sequence = 1;
+	double timeA, timeB;
+	int i;
+	for (i= 0; i <= (steps-2); ++i)
+	{
+		timeA = Get_Ytime (-i);
+		timeB = Get_Ytime (-i-1);
+
+		if ((timeA == timeB) ||
+		    ((timeA - timeB) > (maxstep + 0.00000001)) ||
+		    (timeA <  timeB)  ) break;
+
+		sequence++;
+	}
+	return sequence;
+}
+
+
+
+// POLYNOMIAL EXTRAPOLATION AND INTERPOLATION FUNCTIONS
+// FOR PREDICTIONS
+
+void ChHistory::PredictY(int order, double m_dt, ChMatrix<>* Ypredicted)
+{
+	int nJ, nI;
+	double newX, iX, jX;
+
+	// build Lagrange interpolation coefficients
+
+	newX = Get_now_time() + m_dt;
+
+	if (order < 1) order = 1;
+	if (order >= steps) {order = (steps - 1);}
+
+	int points = order +1;
+
+	ChMatrix<>* li = new ChMatrixDynamic<>(1, points);
+
+	for (nJ = 0; nJ < points; nJ++)
+	{
+		double lu = 1;
+		double ll = 1;
+		jX = Get_Ytime(nJ - order);
+
+		for (nI = 0; nI < points; nI++)
+		{
+			if (nI != nJ)
+			{
+				iX = Get_Ytime(nI - order);
+				lu *= (newX - iX);
+				ll *= (jX - iX);
+			}
+		}
+
+		li->SetElement(0,nJ, (lu/ll));
+	}
+
+	// fill the predicted Y with extrapolation
+	int ivar, istep;
+	double newel;
+
+	for (ivar = 0; ivar < vars ; ivar++)
+	{
+		newel = 0;
+		for (istep= 0; istep < points; istep++)
+		{
+			newel += (Get_Y(istep - order)->GetElement(ivar,0) *
+					  (li->GetElement(0,istep)));
+		}
+		Ypredicted->SetElement (ivar, 0,newel);
+	}
+
+}
+
+void ChHistory::PredictYnew(int order, double m_dt)
+{
+	if (order > (steps-2)) {order = (steps - 2);}
+
+	// fill the Ynew with the prediction
+	PredictY (order, m_dt, Get_Ynew());
+
+	// set the new time for extrapolated Ynew:
+	Set_Ytime (1, (Get_now_time() + m_dt));
+}
+
+
+double ChHistory::PredictionError(int order)
+{
+	int nJ, nI;
+	double newX, iX, jX;
+
+	// build Lagrange interpolation coefficients
+
+	newX = Get_Ytime(1);
+
+	if (order < 1) order = 1;
+	if (order > (steps-2)) {order = (steps - 2);}
+	if (order == 0) return 0; // at least linear interpolation (order >= 1)...
+
+	int points = order +1;
+
+	ChMatrix<>* li = new ChMatrixDynamic<>(1, points);
+
+	for (nJ = 0; nJ < points; nJ++)
+	{
+		double lu = 1;
+		double ll = 1;
+		jX = Get_Ytime(nJ - order);
+
+		for (nI = 0; nI < points; nI++)
+		{
+			if (nI != nJ)
+			{
+				iX = Get_Ytime(nI - order);
+				lu *= (newX - iX);
+				ll *= (jX - iX);
+			}
+		}
+
+		li->SetElement(0,nJ, (lu/ll));
+	}
+
+	// fill the predicted Y with extrapolation
+	int ivar, istep;
+	double newel;
+	double m_error = 0;
+	ChMatrix<>* m_newY = Get_Ynew();
+
+	for (ivar = 0; ivar < vars ; ivar++)
+	{
+		newel = 0;
+		for (istep= 0; istep < points; istep++)
+		{
+			newel += (Get_Y(istep - order)->GetElement(ivar,0) *
+					  (li->GetElement(0,istep)));
+		}
+		m_error += pow ((newel - m_newY->GetElement(ivar, 0)),2);
+	}
+
+	return sqrt(m_error);
+}
+
+
+
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/physics/ChHistory.h b/SRC/ChronoEngine/physics/ChHistory.h
new file mode 100644
index 0000000..1e3c6ee
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChHistory.h
@@ -0,0 +1,137 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHHISTORY_H
+#define CHHISTORY_H
+
+//////////////////////////////////////////////////
+//  
+//   ChHistory.h
+//
+//   global state vector Y (pos. and vel of bodies)
+//   time history data.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChMath.h"
+#include "core/ChApiCE.h"
+
+
+namespace chrono 
+{
+
+
+
+////////////////////////////////////////////////////
+/// Class for time history of system vector states.
+/// 
+/// Example, for nsteps= 3
+///
+///  - Ypointer->	Y (i=-2) time=0.03
+///	 -	    		Y (i=-1) time=0.05
+///	 -		    	Y (i= 0) time=0.06  (Y, the current Y)
+///	 -			    Y (i=+1) time=0.09	(Ynew, for predictions, etc)
+
+class ChApi ChHistory
+{
+private:
+	int steps;
+	int vars; 
+	int current_Y;		// the actual Y pointer in array
+	double* times;		// array of times
+	ChMatrix<>** Yvectors;// array of pointer to Y vectors
+
+public:
+	ChHistory(int nvars, int nsteps);
+	~ChHistory();
+	void Copy(ChHistory* source);
+
+	void Setup(int newvars, int newsteps);
+	void Restart();
+
+		/// Returns the offset in the arrays given the
+		/// cyclic position "i", ranging from and to:
+		/// (-steps+2)....0....(+1)
+
+	int Get_arr_offset (int i);
+
+
+		/// Gets the address of the Y vector, for instant "i",
+		/// with 0= current, -1= previous, etc.
+	ChMatrix<>* Get_Y(int i);
+
+		/// Gets/sets the time of the instant "i".
+	double Get_Ytime(int i);
+	void   Set_Ytime(int i, double newtime);
+
+		/// Rotates one step further the pointer to the
+		/// actual Y vector, after the user has properly set a
+		/// good acceptable Y(+1), which will become Y(0) this way.
+	void ForwardStep();
+	void BackwardStep();
+	void ProceedStep(double m_dt);
+
+		/// shortcuts:
+		/// Gets the current Y address, and the 
+		/// address of the future "Ynew".(the "work in progress" Y, at
+		/// time t(+1);
+
+	double Get_now_time () { return *(times + current_Y);}
+	void Set_now_time (double m_time) { *(times + current_Y) = m_time;}
+	ChMatrix<>* Get_Y()		{ return *(Yvectors + current_Y);}
+	ChMatrix<>* Get_Ynew()	{ return Get_Y(1);}
+
+		/// Returns the number of correctly sequenced 
+		/// recordings of history, where the step difference
+	    /// is not null (neither it is higher than "stepmax").
+		/// it is 1 for a hjistory just started, and it is
+	    /// equal to the nsteps for a well started procedure.
+	int GetNsequenced(double maxstep);
+
+
+	// PREDICTION / EXTRAPOLATION / INTERPOLATION FEATURES
+
+		///  Fills the Ynew  -that is, Y(+1)- with an extrapolation
+		/// of the time-history, using polynomial interpolation of
+		/// given order.
+		///  The time step between current Y and Ynew must be provided,
+		/// and must be different from 0.
+		///  Note: if "steps" is 2, there are only two Y vectors,
+		/// that is Y and Ynew, so the extrapolation have no sense, at
+		/// least Y(0) and Y(-1) must exist for simple linear extrapolation.
+
+	void PredictYnew(int order, double m_dt);
+
+		/// As before, but does not fill the Ynew with the 
+		/// prediction: here an external Y must be provided. 
+	void PredictY(int order, double m_dt, ChMatrix<>* Ypredicted);
+
+		/// As before, but the resulting predicted vector is 
+		/// not needed, because it returns directly the norm of 
+		/// the error between predicted and actual Ynew (which 
+		/// is supposed to be just computed and with correct time).
+		/// This is because it's very memory-efficient.
+
+	double PredictionError(int order);
+
+};
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChIndexedNodes.cpp b/SRC/ChronoEngine/physics/ChIndexedNodes.cpp
new file mode 100644
index 0000000..6625813
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIndexedNodes.cpp
@@ -0,0 +1,167 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChIndexedNodes.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "physics/ChIndexedNodes.h"
+#include "physics/ChSystem.h"
+
+#include "physics/ChExternalObject.h"
+#include "collision/ChCModelBulletNode.h"
+#include "core/ChLinearAlgebra.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChIndexedNodes> a_registration_ChIndexedNodes;
+
+	
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// BASE CLASS FOR NODES
+
+
+ChNodeBase::ChNodeBase()
+{
+}
+
+ChNodeBase::~ChNodeBase()
+{
+}
+
+ChNodeBase::ChNodeBase (const ChNodeBase& other) 
+{
+}
+
+ChNodeBase& ChNodeBase::operator= (const ChNodeBase& other)
+{
+	if (&other == this) 
+		return *this;
+
+	return *this;
+}
+
+
+//////////////////////////////////////
+
+/// CLASS FOR A PARTICLE
+
+
+ChNodeXYZ::ChNodeXYZ()
+{
+	this->pos = VNULL;
+	this->pos_dt = VNULL;
+	this->pos_dtdt = VNULL;
+}
+
+ChNodeXYZ::~ChNodeXYZ()
+{
+}
+
+ChNodeXYZ::ChNodeXYZ (const ChNodeXYZ& other) :
+					ChNodeBase(other) 
+{
+	this->pos = other.pos;
+	this->pos_dt = other.pos_dt;
+	this->pos_dtdt = other.pos_dtdt;
+}
+
+ChNodeXYZ& ChNodeXYZ::operator= (const ChNodeXYZ& other)
+{
+	if (&other == this) 
+		return *this;
+
+	ChNodeBase::operator=(other);
+
+	this->pos = other.pos;
+	this->pos_dt = other.pos_dt;
+	this->pos_dtdt = other.pos_dtdt;
+
+	return *this;
+}
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR INDEXED NODES CONTAINER
+
+
+ChIndexedNodes::ChIndexedNodes ()
+{
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+}
+
+
+ChIndexedNodes::~ChIndexedNodes ()
+{
+
+}
+
+
+
+//////// FILE I/O
+
+void ChIndexedNodes::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+
+}
+
+void ChIndexedNodes::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(mstream);
+
+		// stream in all member data
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChIndexedNodes.h b/SRC/ChronoEngine/physics/ChIndexedNodes.h
new file mode 100644
index 0000000..5c482ca
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIndexedNodes.h
@@ -0,0 +1,235 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHINDEXEDNODES_H
+#define CHINDEXEDNODES_H
+
+//////////////////////////////////////////////////
+//
+//   ChIndexedNodes.h
+//
+//   Interface class for clusters of points that can
+//   be accessed with an index.
+//   Must be inherited by children classes.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "physics/ChPhysicsItem.h"
+#include "lcp/ChLcpVariablesBodyOwnMass.h"
+#include "collision/ChCCollisionSystem.h"
+
+
+namespace chrono
+{
+
+using namespace collision;
+
+
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+/// Class for a node, that has some degrees of 
+/// freedom and that contain a proxy to the solver.
+
+class ChApi ChNodeBase    
+{
+public:
+	ChNodeBase ();
+	virtual ~ChNodeBase ();
+
+	ChNodeBase (const ChNodeBase& other); // Copy constructor
+	ChNodeBase& operator= (const ChNodeBase& other); //Assignment operator
+
+					//
+					// FUNCTIONS
+					//
+
+
+			// Access the 'LCP variables' of the node. To be implemented in children classes
+	virtual ChLcpVariables& Variables() =0; 
+
+			/// Get the number of degrees of freedom
+	int Get_ndof() { return this->Variables().Get_ndof();}
+
+
+			//
+			// Functions for interfacing to the LCP solver
+			//
+
+				/// Sets the 'fb' part (the known term) of the encapsulated ChLcpVariables to zero.
+	virtual void VariablesFbReset() { Variables().Get_fb().FillElem(0.0); }
+
+				/// Adds the current forces (applied to node) into the
+				/// encapsulated ChLcpVariables, in the 'fb' part: qf+=forces*factor
+	virtual void VariablesFbLoadForces(double =1.) {};
+
+				/// Initialize the 'qb' part of the ChLcpVariables with the 
+				/// current value of speeds. 
+	virtual void VariablesQbLoadSpeed() {};
+
+				/// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
+				/// with v_old using VariablesQbLoadSpeed, this method can be used in 
+				/// timestepping schemes that do: M*v_new = M*v_old + forces*dt
+	virtual void VariablesFbIncrementMq() {};
+
+				/// Fetches the item speed (ex. linear velocity, in xyz nodes) from the
+				/// 'qb' part of the ChLcpVariables and sets it as the current item speed.
+				/// If 'step' is not 0, also should compute the approximate acceleration of
+				/// the item using backward differences, that is  accel=(new_speed-old_speed)/step.
+				/// Mostly used after the LCP provided the solution in ChLcpVariables.
+	virtual void VariablesQbSetSpeed(double =0.) {};
+
+				/// Increment node positions by the 'qb' part of the ChLcpVariables,
+				/// multiplied by a 'step' factor.
+				///     pos+=qb*step
+				/// If qb is a speed, this behaves like a single step of 1-st order
+				/// numerical integration (Eulero integration).
+	virtual void VariablesQbIncrementPosition(double ) {};
+
+
+};
+
+
+/// Class for a single 'point' node, that has 3 DOF degrees of
+/// freedom and a mass.
+
+class ChApi ChNodeXYZ : public ChNodeBase 
+{
+public:
+	ChNodeXYZ ();
+	virtual ~ChNodeXYZ ();
+
+	ChNodeXYZ (const ChNodeXYZ& other); // Copy constructor
+	ChNodeXYZ& operator= (const ChNodeXYZ& other); //Assignment operator
+
+					//
+					// FUNCTIONS
+					//
+
+			// Position of the node - in absolute csys.
+	ChVector<> GetPos() {return pos;}
+			// Position of the node - in absolute csys.
+	void SetPos(const ChVector<>& mpos) {pos = mpos;}
+
+			// Velocity of the node - in absolute csys.
+	ChVector<> GetPos_dt() {return pos_dt;}
+			// Velocity of the node - in absolute csys.
+	void SetPos_dt(const ChVector<>& mposdt) {pos_dt = mposdt;}
+
+			// Acceleration of the node - in absolute csys.
+	ChVector<> GetPos_dtdt() {return pos_dtdt;}
+			// Acceleration of the node - in absolute csys.
+	void SetPos_dtdt(const ChVector<>& mposdtdt) {pos_dtdt = mposdtdt;}
+
+			// Get mass of the node. To be implemented in children classes
+	virtual double GetMass() const = 0;
+			// Set mass of the node. To be implemented in children classes
+	virtual void SetMass(double mm) = 0;
+
+					//
+					// DATA
+					// 
+	ChVector<> pos;		
+	ChVector<> pos_dt;
+	ChVector<> pos_dtdt;
+};
+
+
+/// Interface class for clusters of points that can
+/// be accessed with an index.
+/// Must be inherited by children classes.
+
+class ChApi ChIndexedNodes : public ChPhysicsItem
+{
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChIndexedNodes,ChPhysicsItem);
+
+private:
+			//
+	  		// DATA
+			//
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a cluster of nodes 
+	ChIndexedNodes ();
+
+				/// Destructor
+	~ChIndexedNodes ();
+
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Get the number of nodes
+	virtual unsigned int GetNnodes() =0;
+
+				/// Access the N-th node 
+	virtual ChNodeBase* GetNode(unsigned int n) =0;
+
+				/// Add a new node to the particle cluster, passing a 
+				/// vector as initial position.
+//	virtual void AddNode(ChVector<double> initial_state) =0;
+
+				/// Resize the node cluster. Also clear the state of 
+				/// previously created particles, if any.
+//	virtual void ResizeNnodes(int newsize) =0;
+
+				/// Number of coordinates of the node cluster
+//	virtual int GetDOF  ()   {return 3*GetNnodes();} 
+
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+typedef ChSharedPtr<ChIndexedNodes> ChSharedIndexedNodesPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChIndexedParticles.cpp b/SRC/ChronoEngine/physics/ChIndexedParticles.cpp
new file mode 100644
index 0000000..3042c04
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIndexedParticles.cpp
@@ -0,0 +1,134 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChParticles.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "core/ChTrasform.h"
+#include "physics/ChIndexedParticles.h"
+#include "physics/ChSystem.h"
+#include "physics/ChGlobal.h"
+
+#include "physics/ChExternalObject.h"
+#include "collision/ChCModelBulletParticle.h"
+#include "core/ChLinearAlgebra.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChIndexedParticles> a_registration_ChIndexedParticles;
+
+	
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR A PARTICLE
+
+
+ChParticleBase::ChParticleBase()
+{
+}
+
+ChParticleBase::~ChParticleBase()
+{
+}
+
+ChParticleBase::ChParticleBase (const ChParticleBase& other) :
+					ChFrameMoving<double>(other)
+{
+}
+
+ChParticleBase& ChParticleBase::operator= (const ChParticleBase& other)
+{
+	if (&other == this) 
+		return *this;
+
+	// parent class copy
+	ChFrameMoving<double>::operator=(other);
+	
+	return *this;
+}
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR PARTICLE CLUSTER
+
+
+ChIndexedParticles::ChIndexedParticles ()
+{
+	
+}
+
+
+ChIndexedParticles::~ChIndexedParticles ()
+{
+	
+}
+
+
+
+//////// FILE I/O
+
+void ChIndexedParticles::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+
+}
+
+void ChIndexedParticles::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(mstream);
+
+		// stream in all member data
+
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChIndexedParticles.h b/SRC/ChronoEngine/physics/ChIndexedParticles.h
new file mode 100644
index 0000000..198ee7f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIndexedParticles.h
@@ -0,0 +1,152 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHINDEXEDPARTICLES_H
+#define CHINDEXEDPARTICLES_H
+
+//////////////////////////////////////////////////
+//
+//   ChIndexedParticles.h
+//
+//   Interface class for clusters of 'particles' that can
+//   be accessed with an index. Particles have 6 DOF.
+//   Must be inherited by children classes.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "core/ChFrameMoving.h"
+#include "physics/ChPhysicsItem.h"
+#include "collision/ChCCollisionSystem.h"
+
+
+namespace chrono
+{
+
+using namespace collision;
+
+
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+/// Base class for a single particle to be used in ChIndexedParticles containers.
+/// It is an item that has 6 degrees of freedom, like a moving frame.
+
+class ChApi ChParticleBase : public ChFrameMoving<double>  
+{
+public:
+	ChParticleBase();
+	virtual ~ChParticleBase();
+
+	ChParticleBase (const ChParticleBase& other); // Copy constructor
+	ChParticleBase& operator= (const ChParticleBase& other); //Assignment operator
+
+			// Access the 'LCP variables' of the node
+	virtual ChLcpVariables& Variables() =0; 
+};
+
+
+/// Interface class for clusters of particles that can
+/// be accessed with an index.
+/// Must be inherited by children classes.
+
+class ChApi ChIndexedParticles : public ChPhysicsItem 
+{
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChIndexedParticles,ChPhysicsItem);
+
+private:
+			//
+	  		// DATA
+			//
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a cluster of particles.
+				/// By default the cluster will contain 0 particles.
+	ChIndexedParticles ();
+
+				/// Destructor
+	~ChIndexedParticles ();
+
+
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Get the number of particles
+	virtual unsigned int GetNparticles() =0;
+
+				/// Access the N-th particle 
+	virtual ChParticleBase& GetParticle(unsigned int n) =0;
+				
+				/// Resize the particle cluster. Also clear the state of 
+				/// previously created particles, if any.
+	virtual void ResizeNparticles(int newsize) =0;
+
+				/// Add a new particle to the particle cluster, passing a 
+				/// coordinate system as initial state.
+	virtual void AddParticle(ChCoordsys<double> initial_state = CSYSNORM) =0;
+
+				/// Number of coordinates of the particle cluster
+	virtual int GetDOF  ()   {return 6*GetNparticles();}
+
+
+				/// Get the master coordinate system for the assets (this will return the 
+				/// main coordinate system of the rigid body)
+	virtual ChFrame<> GetAssetsFrame(unsigned int nclone=0) { ChFrame<> res; res = GetParticle(nclone); return(res);}
+	virtual unsigned int GetAssetsFrameNclones() {return GetNparticles();}
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+typedef ChSharedPtr<ChIndexedParticles> ChSharedIndexedParticlesPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChIntegrator.cpp b/SRC/ChronoEngine/physics/ChIntegrator.cpp
new file mode 100644
index 0000000..a834758
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIntegrator.cpp
@@ -0,0 +1,331 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChIntegrator.cpp
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChIntegrator.h"
+
+namespace chrono 
+{
+
+
+ChIntegrator::ChIntegrator()
+{
+	method = INTEG_EULEROSTD_EXP;
+}
+
+ChIntegrator::~ChIntegrator()
+{
+}
+
+void ChIntegrator::Copy(ChIntegrator* source)
+{
+	// first copy the parent class data...
+	ChObj::Copy(source);
+
+	// copy own data
+	method = source->method;
+
+}
+
+
+int ChIntegrator::ODEintegrate_step (
+					int n_eq,				// number of equations
+					ChMatrix<>* Y,				// the current state (also will contain resulting state after integration)
+					double& t,				// the starting time (also will contain final time ater integration)
+					int getdy(ChMatrix<>* m_Y, double m_t, ChMatrix<>* m_dYdt, void* m_userdata), // function which computes dy/dt=f(y,t), returning TRUE if OK, FALSE if error
+					double h,				// step lenght.
+					double& int_error,		// if possible, returns here the local error extimation
+					void* userdata)			// additional user data
+{
+	//
+	// initialize stuff..
+	//
+
+	int_error = 0.0;
+	
+	int i;
+	int m_ok = TRUE;
+
+	double a2=0.2,a3=0.3,a4=0.6,a5=1.0,a6=0.875,b21=0.2,
+		b31=3.0/40.0,b32=9.0/40.0,b41=0.3,b42 = -0.9,b43=1.2,
+		b51 = -11.0/54.0, b52=2.5,b53 = -70.0/27.0,b54=35.0/27.0,
+		b61=1631.0/55296.0,b62=175.0/512.0,b63=575.0/13824.0,
+		b64=44275.0/110592.0,b65=253.0/4096.0,c1=37.0/378.0,
+		c3=250.0/621.0,c4=125.0/594.0,c6=512.0/1771.0,
+		dc5 = -277.00/14336.0;
+	double dc1=c1-2825.0/27648.0,dc3=c3-18575.0/48384.0,
+		dc4=c4-13525.0/55296.0,dc6=c6-0.25;
+
+	//
+	// get number of equations...
+	//
+
+	int nequations = Y->GetRows();
+	if (nequations != n_eq) 
+				return FALSE;
+
+	//
+	// Initialize and reset temporary vectors, to match number
+	// of equations
+	//
+
+	ChMatrixDynamic<> Ydt;
+	ChMatrixDynamic<> Ytemp;
+	ChMatrixDynamic<> Ynew;
+	ChMatrixDynamic<> Yk1;
+	ChMatrixDynamic<> Yk2;
+	ChMatrixDynamic<> Yk3;
+	ChMatrixDynamic<> Yk4;
+	ChMatrixDynamic<> Yk5;
+	ChMatrixDynamic<> Yk6;
+
+	Ydt.Reset	(nequations, 1);
+	Ytemp.Reset (nequations, 1);
+	Yk1.Reset	(nequations, 1);
+	Yk2.Reset	(nequations, 1);
+	Yk3.Reset	(nequations, 1);
+	Yk4.Reset	(nequations, 1);
+	Yk5.Reset	(nequations, 1);
+	Yk6.Reset	(nequations, 1);
+	Ynew.Reset	(nequations, 1);
+
+
+	// 
+	// Perform step integration
+	//
+
+	switch (this->method)
+	{
+
+
+	case INTEG_EULEROSTD_EXP:
+
+				// 1-- dY/dt   at current time: t0 
+
+		m_ok=(*getdy)(Y, t,			&Yk1, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk1
+
+		Yk1.MatrScale(h);
+
+		Ynew.MatrAdd (*Y, Yk1);
+		
+		break;
+
+
+
+	case INTEG_EULEROMOD_EXP:
+
+				// 1- Yk1 = Ydt (Y, t0)
+		m_ok=(*getdy)(Y, t,		&Yk1, userdata);		// >>>>>>>>>>>>>>>>>>>>>>> Yk1
+
+
+				// 2- Yk2 = Ydt (Y+(dt/2)*Ydt,  t+dt/2)
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h*0.5* Ydt.GetElement(i,0)  );
+
+		m_ok=(*getdy)(&Ytemp, t+h/2,	&Yk2, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk2 
+
+
+				// 3- Ynew = Y + (Yk2 * dt)
+		for (i = 0; i < nequations; i++)
+			Ynew.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h* Yk2.GetElement(i,0)  );
+	
+		break;
+
+
+
+	case INTEG_HEUN_EXP:
+
+				// 1- Yk1 = Ydt (Y, t0)
+		m_ok=(*getdy)(Y, t,		&Yk1, userdata);			// >>>>>>>>>>>>>>>>>>>>>>> Yk1
+
+
+				// 2- Yk2 = Ydt (Y+ dt*Ydt,  t+dt)
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h * Yk1.GetElement(i,0)  );
+
+		m_ok=(*getdy)(&Ytemp, t+h,	&Yk2, userdata);		// >>>>>>>>>>>>>>>>>>>>>>> Yk2 
+
+				// 3- Ynew= Y + (Yk1 * dt/2) + (Yk1 * dt/2)
+		for (i = 0; i < nequations; i++)
+			Ynew.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h*0.5* Yk1.GetElement(i,0) +
+						h*0.5* Yk2.GetElement(i,0) );
+
+		break;
+
+
+
+	case INTEG_KUTTA_EXP:
+
+		// 1-- dY/dt   at current time: t0 
+		m_ok=(*getdy)(Y, t,			&Yk1, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk1
+
+		// 2-- dY/dt   at time: t0 +a2*h
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						b21*h* Yk1.GetElement(i,0)  );
+
+		m_ok=(*getdy)(&Ytemp, t +a2*h,	&Yk2, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk2
+
+		// 3-- dY/dt   at time: t0 +a3*h
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h*( b31*Yk1.GetElement(i,0) +
+						    b32*Yk2.GetElement(i,0)  )   );
+
+		m_ok=(*getdy)(&Ytemp, t +a3*h,	&Yk3, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk3
+
+
+		// 4-- dY/dt   at time: t0 +a4*h
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h*( b41*Yk1.GetElement(i,0) +
+						    b42*Yk2.GetElement(i,0) +
+							b43*Yk3.GetElement(i,0)  )   );
+		
+		m_ok=(*getdy)(&Ytemp, t +a4*h,	&Yk4, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk4
+		
+
+		// 5-- dY/dt   at time: t0 +a5*h
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h*( b51*Yk1.GetElement(i,0) +
+						    b52*Yk2.GetElement(i,0) +
+						    b53*Yk3.GetElement(i,0) +
+							b54*Yk4.GetElement(i,0)  )   );
+
+		m_ok=(*getdy)(&Ytemp, t +a5*h,	&Yk5, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk5
+
+
+		// 6-- dY/dt   at time: t0 +a6*h
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						h*( b61*Yk1.GetElement(i,0) +
+						    b62*Yk2.GetElement(i,0) +
+						    b63*Yk3.GetElement(i,0) +
+							b64*Yk4.GetElement(i,0) +
+							b65*Yk5.GetElement(i,0)  )   );
+
+		m_ok=(*getdy)(&Ytemp, t +a6*h,	&Yk6, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk6
+
+
+		// Ynew = ..  acumulate to set incremented new Y state 
+		for (i = 0; i < nequations; i++)
+			Ynew.SetElement(i,0,
+						Y->GetElement(i,0) +
+						h*( c1*Yk1.GetElement(i,0) +
+							c3*Yk3.GetElement(i,0) +
+							c4*Yk4.GetElement(i,0) +
+							c6*Yk6.GetElement(i,0)	)	);
+
+				// -- compute local error
+		for (i = 0; i < nequations; i++)
+			int_error += ChMax(int_error, fabs(
+					    h*( dc1*Yk1.GetElement(i,0) +
+							dc3*Yk3.GetElement(i,0) +
+							dc4*Yk4.GetElement(i,0) +
+							dc5*Yk5.GetElement(i,0) +
+							dc6*Yk6.GetElement(i,0)	 )    
+							));
+		break;
+
+
+
+	case INTEG_RK_EXP:
+
+		// 1-- dY/dt   at current time: t0 
+
+		m_ok=(*getdy)(Y, t,			&Yk1, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk1
+
+
+		// 2-- dY/dt   at time: t0 + h/2
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						0.5 * h * Yk1.GetElement(i,0)  );
+
+		m_ok=(*getdy)(&Ytemp, t +h/2,	&Yk2, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk2
+
+
+		// 3-- dY/dt   at time: t0 + h/2
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+						0.5 * h * Yk2.GetElement(i,0)  );
+
+		m_ok=(*getdy)(&Ytemp, t +h/2,	&Yk3, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk3
+
+
+		// 4-- dY/dt   at time: t0 + h
+		for (i = 0; i < nequations; i++)
+			Ytemp.SetElement(i,0, 
+						Y->GetElement(i,0) +
+							  h * Yk3.GetElement(i,0)  );
+				
+		m_ok=(*getdy)(&Ytemp, t +h,		&Yk4, userdata);	// >>>>>>>>>>>>>>>>>>>>>>> Yk4
+
+
+
+		// Ynew = ... acumulate to set incremented new Y state
+		for (i = 0; i < nequations; i++)
+			Ynew.SetElement(i,0,
+						Y->GetElement(i,0) +
+						h*( (1.0/6.0)*Yk1.GetElement(i,0) +
+							(1.0/3.0)*Yk2.GetElement(i,0) +
+							(1.0/3.0)*Yk3.GetElement(i,0) +
+							(1.0/6.0)*Yk4.GetElement(i,0)	)	);
+
+		break;
+
+
+
+
+
+	default:
+		
+		m_ok = FALSE;
+		break;
+	}
+
+	//
+	// Go forward.. (UPDATE TIME AND STATE)
+	//
+
+	Y->CopyFromMatrix(Ynew);
+	t = t+h;
+
+
+	return (m_ok);
+}
+
+
+} // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/physics/ChIntegrator.h b/SRC/ChronoEngine/physics/ChIntegrator.h
new file mode 100644
index 0000000..6662ef0
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIntegrator.h
@@ -0,0 +1,98 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHINTEGRATOR_H
+#define CHINTEGRATOR_H
+
+//////////////////////////////////////////////////
+//
+//   ChIntegrator.h
+//
+//   Math functions for :
+//      - ORDINARY DIFFERENTIAL EQUATIONS
+//
+//     ***OBSOLETE*** to be improved/rewritten.
+//                    Currently not used by ChSystem.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "core/ChMath.h"
+#include "physics/ChObject.h"
+
+namespace chrono
+{
+
+
+
+//#define INTEG_EULERO_EXP		0
+#define INTEG_KUTTA_EXP		1
+#define INTEG_RK_EXP		2
+#define INTEG_EULEROSTD_EXP	3
+#define INTEG_EULEROMOD_EXP	4
+#define INTEG_HEUN_EXP		5
+
+
+////////////////////////////////////////////////
+// the 'integrator' object
+
+
+
+/// Class for methods which perform numerical integration of ODEs
+/// (Ordinary Differential Equations).
+/// ***OBSOLETE*** DO NOT USE
+
+class ChApi ChIntegrator : public ChObj {
+
+private:
+
+public:
+	// ------ DATA
+
+	int method;	// Integration scheme, see methods code above
+
+
+	// ------ FUNCTIONS
+
+	ChIntegrator();
+	virtual ~ChIntegrator();
+	virtual void Copy(ChIntegrator* source);
+
+
+
+
+				// Generic ODE integrator, performs a single step of integration
+				// Returns true if ok, false if something's wrong.
+
+	int ODEintegrate_step  (
+					int n_eq,				// number of equations (must be equal to rows of y0, m_y, m_ydtdt);
+					ChMatrix<>* Y,				// the current state (also will contain resulting state after integration)
+					double& t,				// the starting time (also will contain final time ater integration)
+											// function which computes dy/dt=f(y,t), returning TRUE if OK, FALSE if error
+					int getdy(ChMatrix<>* m_y, double m_t, ChMatrix<>* m_dydt, void* m_userdata),
+					double h,				// step lenght.
+					double& error,			// if possible, returns here the local error extimation
+					void* userdata);		// generic pointer to pass aux. data to the getdy function
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChIterative.cpp b/SRC/ChronoEngine/physics/ChIterative.cpp
new file mode 100644
index 0000000..9fcf6cb
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIterative.cpp
@@ -0,0 +1,388 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+// ChIterative.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChIterative.h"
+
+namespace chrono 
+{
+
+  //: Transpose Free Quasi-Minimal Residual
+  //
+  //  Transpose free QMR. First solve Q_1 A Q_2 x = Q_1 b. Then,
+  //  return z which is Q_2 x. Here Q1 and Q2 are precondtioners.
+  //  Suppose M is about equal to A and M = M_1 * M_2, then
+  //  Q_1 = M_1^{-1} and Q_2 = M_2^{-1}
+  //  <p>
+  //  The residual holds |b - A * x_m| < sqrt{m+1} * tau_m. 
+  //  The algorithm check the latter to see if convergence arrives instead of 
+  //  checking real residual.
+  //  <p>
+  //<table align=center border=1>
+  // <tr><td> return value </td>   <td>   meaning </td> </tr>
+  // <tr><td>      0   </td><td>   convergence within maximum iterations </td> </tr>
+  // <tr><td>      1   </td><td>     no convergence after maximum iterations</td> </tr>
+  //  <tr><td>     2  </td><td>      breakdown in       tau </td> </tr>
+  //  <tr><td>     3  </td><td>      breakdown in       alpha </td> </tr>
+  //  <tr><td>     4  </td><td>      breakdown in       gamma</td> </tr>
+  //  <tr><td>     5  </td><td>      breakdown in       rho</td> </tr>
+  // </table>
+  //
+  //  <p>
+  //  See: R. W. Freund, A Transpose-Free Quasi-Minimal Residual algorithm for 
+  //  non-Hermitian linear system. SIAM J. on Sci. Comp. 14(1993), pp. 470-482
+  //
+  //!category: itl,algorithms
+  //!component: function
+  //!definition: tfqmr.h
+  //!tparam: Matrix or multiplier for matrix free methods
+  //!tparam: Vector 
+  //!tparam: Vector
+  //!tparam: Preconditioner -  Incomplete LU, Incomplete LU with threshold, SSOR or identity_preconditioner.
+  //!tparam: Iteration - Controls the stopping criteria
+  //
+
+//template <class ChMatrix<>, class ChMatrix<>, class MatrixB, class Precond1, class Precond2, class Iteration>
+
+int ch_iterative_TFQMR	(ChMatrix<>& x, ChMatrix<>& b,
+	void (*SolveAX)(ChMatrix<>& inX, ChMatrix<>& outB, void* userdata),
+	void (*M1_solve)(ChMatrix<>& eIn, ChMatrix<>& eOut, void* userdata),
+	void (*M2_solve)(ChMatrix<>& eIn, ChMatrix<>& eOut, void* userdata),
+	double min_kappa, int max_iterations, 
+	int& iter, int& error_code,
+	void* userdata)
+{
+  //using namespace mtl;
+
+  //typedef typename ChMatrix<>::value_type double;
+
+  int N = x.GetRows();
+
+  iter =0;
+
+  ChMatrixDynamic<> tmp(N,1), tmpb(N,1), r0(N,1), v(N,1);
+
+  double sigma, alpha, c, kappa, beta;
+
+  ChMatrixDynamic<>  h(N,1);
+
+  //x is initial value
+
+
+  // 1. r0 = Q1 (b - A Q2 x)
+								//M2.solve(x, r0);
+  if (M2_solve) {
+	M2_solve(x,r0,userdata);
+  } else {
+	r0.CopyFromMatrix(x);
+  }
+
+  SolveAX(r0, tmpb, userdata);	//  +++++++  mult(A, r0, tmp);
+
+
+  tmpb.MatrNeg();
+  tmp.MatrAdd(b, tmpb );		// add(b, scaled(tmp, -1.), tmp);
+
+								//M1.solve(tmp, r0);
+  if (M1_solve) {
+	M1_solve(tmp,r0,userdata);
+  } else {
+	r0.CopyFromMatrix(tmp);
+  }
+
+
+  // 2. w=y=r
+  ChMatrixDynamic<> w(N,1);
+  w.CopyFromMatrix(r0);		//copy(r0, w);
+  ChMatrixDynamic<> y1(N,1);
+  y1.CopyFromMatrix(r0);		//copy(r0, y1);
+
+  // 3. g=v=Q1AQ2y
+								// M2.solve(y1, v);
+  if (M2_solve) {
+	M2_solve(y1,v,userdata);
+  } else {
+	v.CopyFromMatrix(y1);
+  }
+
+  SolveAX(v, tmp, userdata);	// ++++++++ mult(A, v, tmp);
+							
+								//  M1.solve(tmp, v);
+  if (M1_solve) {
+	M1_solve(tmp,v,userdata);
+  } else {
+	v.CopyFromMatrix(tmp);
+  }
+
+
+
+  ChMatrixDynamic<> g(N,1);
+  g.CopyFromMatrix(v);			//		copy(v, g);
+
+  // 4. d=0
+  ChMatrixDynamic<> d(N,1); d.FillElem(0.0);
+
+  // 5. tau=||r||2
+  double tau = r0.NormTwo();	// = two_norm(r0);
+
+  // 6. theta=eta=0
+  double theta = 0.0;
+  double eta = 0.0;
+
+  // 7. rtilde=r
+  ChMatrixDynamic<> rtilde(N,1);
+  rtilde.CopyFromMatrix(r0);	// copy(r0, rtilde);
+
+  // 8. rho=dot(rtilde,r)
+  double rho = ChMatrix<>::MatrDot(&rtilde, &r0);					//= dot(rtilde, r0);
+  double rho0 = rho;
+  ChMatrixDynamic<> y0(N,1);
+  for (;;) 
+  {
+    // 9. 10. 11.
+    // sigma=dot(rtilde,v)
+    // alpha=rho/sigma 
+    // y2k=y(2k-1)-alpha*v
+	sigma = ChMatrix<>::MatrDot(&rtilde, &v);
+
+    if (sigma==0.) { error_code = 5; /*iter.fail(5, "tfqmr breakdown: sigma=0");*/ break; }
+    alpha = rho / sigma;
+    
+    //y0 = y1 - alpha * v;
+	tmpb.CopyFromMatrix(v);
+	tmpb.MatrScale(-alpha);
+    y0.MatrAdd(y1, tmpb);					//add(y1, scaled(v, -alpha), y0);
+
+    // 12. h=Q1*A*Q2*y
+											// M2.solve(y0, h);
+    if (M2_solve) {
+	  M2_solve(y0,h,userdata);
+	} else {
+  	  y0.CopyFromMatrix(h);
+	}
+
+	SolveAX(h, tmp, userdata);				// mult(A, h, tmp);
+										
+											// M1.solve(tmp, h);
+    if (M1_solve) {
+	  M1_solve(tmp,h,userdata);
+	} else {
+  	  h.CopyFromMatrix(tmp);
+	}
+
+
+    //split the loop of "for m = 2k-1, 2k" 
+
+    //The first one
+    // 13. w=w-alpha*Q1AQ2y0
+    //w = w - alpha * g;
+	tmpb.CopyFromMatrix(g);
+	tmpb.MatrScale(-alpha);
+	w.MatrInc(tmpb);					// add(w, scaled(g, -alpha), w);
+    
+	// 18. d=y0+((theta0^2)*eta0/alpha)*d         //need check breakdown
+    if (alpha==0.) { error_code = 3; /*iter.fail(3, "tfqmr breakdown: alpha=0");*/ break; }
+    
+	//d = y1 + ( theta * theta * eta / alpha ) * d;
+	tmpb.CopyFromMatrix(d);
+	tmpb.MatrScale(theta * theta * eta / alpha);
+	d.MatrAdd(y1,tmpb);			    // add(y1, scaled(d, theta * theta * eta / alpha), d);
+
+    // 14. theta=||w||_2/tau0       //need check breakdown
+    if (tau==0.) { error_code = 2; /*iter.fail(2, "tfqmr breakdown: tau=0"); */ break; }
+    theta  = w.NormTwo() / tau;
+    
+    // 15. c=1/sqrt(1+theta^2)
+    c = 1. / sqrt(1. + theta * theta);
+
+    // 16. tau=tau0*theta*c
+    tau = tau * c * theta;
+
+    // 17.  eta=(c^2)*alpha
+    eta = c * c * alpha;
+
+    // 19. x=x+eta*d
+    //x += eta * d;
+	tmpb.CopyFromMatrix(d);
+	tmpb.MatrScale(eta);
+	x.MatrInc(tmpb); // add(x, scaled(d, eta), x);
+
+    // 20. kappa=tau*sqrt(m+1)
+    kappa = tau * sqrt( 2.* (iter+1) );	// ALEX
+
+    // 21. check stopping criterion
+    if (( kappa < min_kappa )||( iter > max_iterations))
+	{
+      //before return, transform x to the solution of Ax = b
+						//M2.solve(x, tmp);
+		if (M2_solve) {
+			M2_solve(x,tmp,userdata);
+		} else {
+  			tmp.CopyFromMatrix(x);
+		}
+
+		x.CopyFromMatrix(tmp);	// copy(tmp, x);
+
+		if ( kappa < min_kappa )	// ALEX
+			error_code =0;
+		if ( iter > max_iterations)
+			error_code =1;
+
+		break;
+    }
+
+    //g = h;
+	g.CopyFromMatrix(h);		// copy(h, g);
+
+    
+	//---THE SECOND ONE---
+
+    // 13. w=w-alpha*Q1AQ2y0
+    //w = w - alpha * g;
+	tmpb.CopyFromMatrix(g);
+	tmpb.MatrScale(-alpha);
+	w.MatrInc(tmpb);			// add(w, scaled(g, -alpha), w);
+    
+    // 18. d=y0+((theta0^2)*eta0/alpha)*d
+    if (alpha==0.) { error_code = 3; /*iter.fail(3,"tfqmr breakdown: alpha=0");*/ break; }
+
+    //d = y0 + ( theta * theta * eta / alpha ) * d;
+	tmpb.CopyFromMatrix(d);
+	tmpb.MatrScale(theta * theta * eta / alpha);
+	d.MatrAdd(y0,  tmpb);		//  add(y0, scaled(d,  theta * theta * eta / alpha), d);
+
+    // 14. theta=||w||_2/tau0
+    if (tau==0.) { error_code = 2; /*iter.fail(2, "tfqmr breakdown: tau=0");*/ break; }
+    theta = w.NormTwo() / tau;
+    
+    // 15. c=1/sqrt(1+theta^2)
+    c = 1. / sqrt(1. + theta * theta);
+
+    // 16. tau=tau0*theta*c
+    tau = tau * c * theta;
+
+    // 17.  eta=(c^2)*alpha
+    eta = c * c * alpha;
+
+    // 19. x=x+eta*d
+    //x += eta * d;
+	tmpb.CopyFromMatrix(d);
+	tmpb.MatrScale(eta);
+	x.MatrInc(tmpb);			// add(x, scaled(d, eta), x);
+    
+    // 20. kappa=tau*sqrt(m+1)
+    kappa = tau * sqrt(2.* (iter+1)  + 1.);	// ALEX
+
+    // 21. check stopping criterion
+    if (( kappa < min_kappa ) || ( iter > max_iterations))
+	{
+								// M2.solve(x, tmp);
+		if (M2_solve) {
+			M2_solve(x,tmp,userdata);
+		} else {
+  			tmp.CopyFromMatrix(x);
+		}
+
+		x.CopyFromMatrix(tmp);	// copy(tmp, x);
+		
+		if ( kappa < min_kappa )	// ALEX
+			error_code =0;
+		if ( iter > max_iterations)
+			error_code =1;
+
+		break;
+    }    
+
+    // 22. rho=dot(rtilde,w)
+    // 23. beta=rho/rho0                     //need check breakdown
+    
+    rho0 = rho;
+    rho = ChMatrix<>::MatrDot(&rtilde, &w);
+    if (rho0==0.) { error_code = 4; /*iter.fail(4, "tfqmr breakdown: beta=0");*/ break; }
+    beta=rho/rho0;
+
+    // 24. y=w+beta*y0
+    //y1 = w + beta * y0;
+	tmpb.CopyFromMatrix(y0);
+	tmpb.MatrScale(beta);
+	y1.MatrAdd(w, tmpb);					// add(w, scaled(y0, beta), y1);
+
+  
+    // 25. g=Q1AQ2y
+    //g = Q1 * ( A * ( Q2 * y1) );
+											// M2.solve(y1, g);
+	if (M2_solve) {
+		M2_solve(y1,g,userdata);
+	} else {
+  		g.CopyFromMatrix(y1);
+	}
+    
+	SolveAX(g, tmp, userdata);				// mult(A, g, tmp);
+    
+											// M1.solve(tmp, g);
+	if (M1_solve) {
+		M1_solve(tmp,g,userdata);
+	} else {
+  		g.CopyFromMatrix(tmp);
+	}
+
+    // 26. v=Q1AQ2y+beta*(Q1AQ2y0+beta*v)
+
+    //v = g + beta * ( h + beta * v );
+	tmpb.CopyFromMatrix(h);
+	tmpb.MatrScale(beta);
+	v.MatrAdd(tmpb,g);
+	tmpb.CopyFromMatrix(v);
+	tmpb.MatrScale(beta*beta);
+	v.MatrInc(tmpb);		// add(g, scaled(h, beta), scaled(v, beta*beta), v);
+    
+    ++iter;
+  }
+
+  return error_code;
+}
+
+
+void __easy_prodeval(ChMatrix<>& inX, ChMatrix<>& outB, void* userdata)
+{
+	ChMatrix<>* mA = (ChMatrix<>*) userdata;
+	outB.MatrMultiply(*mA, inX);  // b = A*x    residual
+}
+
+int ch_iterative_TFQMR_easy(ChMatrix<>& A, ChMatrix<>& x, ChMatrix<>& b,
+	  double mkappa, int max_iterations)
+{
+	if (A.GetRows() != b.GetRows()) return 6;
+	if (A.GetRows() != x.GetRows()) return 6;
+	if (A.GetColumns() != A.GetRows()) return 6;
+
+	int merr, miters;
+	
+	return ch_iterative_TFQMR (x,  b,
+	__easy_prodeval,
+	NULL,NULL,
+	mkappa, max_iterations, miters, merr,
+	&A);
+}
+
+
+} // END_OF_NAMESPACE____
+
+// eof
diff --git a/SRC/ChronoEngine/physics/ChIterative.h b/SRC/ChronoEngine/physics/ChIterative.h
new file mode 100644
index 0000000..8e9fcb2
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChIterative.h
@@ -0,0 +1,92 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHITERATIVE_H
+#define CHITERATIVE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChIterative.h
+//
+//   Iterative methods for linear algebra.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include "core/ChApiCE.h"
+#include "core/ChMath.h"
+
+namespace chrono 
+{
+
+	// TO DO:
+	//   - add other Krylov methods (CG, MINRES, etc)
+	//   - enclose them in a class as in ChLinarAlgebra.h, with similar interfaces
+	//   - maybe move in core/ dir? or move both this and ChLinarAlgebra.h in a new dir 'source/numerical/' ?
+
+
+/// TF-QMR
+///
+/// TRANSPOSE-FREE QUASI-MINIMAL-RESIDUAL solver for linear systems.
+///
+/// Iterative method to solve linear systems Ax=b, applies to 
+/// both symmetric and non simmetric matrices, does not
+/// breakdown for singular matrices, accepts preconditioning.
+///
+///  x         = initial guess for X0 and also matrix to store final value;
+///  b         = known term vector in Ax=b 
+///  SolveAX   = function which computes b"=Ax (gets x as 1st parameter, 
+///              outputs in b", the 2nd param, and may use some user data as 3rd param.)
+///  M1_solve  = function which performs preconditioner M matrix solve as Out=M'*In
+///  M2_solve  = function which performs preconditioner M matrix solve as Out=M'*In
+///  min_kappa = threshold for convergence
+///  max_iterations = limit on number of iterations
+///  iter      = returns tot iterations done before exiting
+///  error_code= returns error, if any: 
+///					0:   convergence within maximum iterations 
+///					1:   no convergence after maximum iterations
+///					2:   breakdown in       tau 
+///					3:   breakdown in       alpha 
+///					4:   breakdown in       gamma
+///					5:   breakdown in       rho
+///  userdata  = generic pointer to whatever one needs (it will be passed to SolveAX
+///              as 3rd parameter, so it may be useful to pass some pointer to application, 
+///              geometric or modeling data, etc., then avoiding the use of global vars.)
+
+ChApi 
+int ch_iterative_TFQMR(ChMatrix<>& x, ChMatrix<>& b,
+	  void (*SolveAX) (ChMatrix<>& inX, ChMatrix<>& outB, void* userdata),
+	  void (*M1_solve)(ChMatrix<>& eIn, ChMatrix<>& eOut, void* userdata),
+	  void (*M2_solve)(ChMatrix<>& eIn, ChMatrix<>& eOut, void* userdata),
+	  double min_kappa, int max_iterations, 
+	  int& iter, int& error_code,
+	  void* userdata);
+
+
+/// As before, but with less parameters, easier to use.
+
+ChApi 
+int ch_iterative_TFQMR_easy(ChMatrix<>& A, ChMatrix<>& x, ChMatrix<>& b,
+	  double mkappa, int iterations);
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
+
diff --git a/SRC/ChronoEngine/physics/ChLimit.cpp b/SRC/ChronoEngine/physics/ChLimit.cpp
new file mode 100644
index 0000000..92d29f9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLimit.cpp
@@ -0,0 +1,361 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+// 
+//   ChLimit.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChLimit.h"
+
+namespace chrono 
+{
+
+ChLinkLimit::ChLinkLimit() 
+{
+	active = 0;		// default: inactive limit
+	penalty_only = 0; // use also link-locking
+	polar = 0; // default: no polar limit
+	rotation = 0;
+	max = 1;
+	min = -1;
+	maxCushion = 0.0;
+	minCushion = 0.0;
+	Kmax= 1000; Kmin = 1000;
+	Rmax= 100;  Rmin =  100;
+	minElastic = 0.0;
+	maxElastic = 0.0;
+	modul_Kmax =   new ChFunction_Const (1);  // default: const.modulation of K
+	modul_Kmin =   new ChFunction_Const (1);  // default: const.modulation of K
+	modul_Rmax =   new ChFunction_Const (1);  // default: const.modulation of K
+	modul_Rmin =   new ChFunction_Const (1);  // default: const.modulation of K
+	polar_Max  =   new ChFunction_Const (1);  // default function for polar limits
+	constr_upper.SetMode(CONSTRAINT_UNILATERAL);
+	constr_lower.SetMode(CONSTRAINT_UNILATERAL);
+}
+
+
+ChLinkLimit::~ChLinkLimit () 
+{
+	if (modul_Kmax) delete modul_Kmax;
+	if (modul_Kmin) delete modul_Kmin;
+	if (modul_Rmax) delete modul_Rmax;
+	if (modul_Rmin) delete modul_Rmin;
+	if (polar_Max)  delete polar_Max;
+}
+
+void ChLinkLimit::Copy (ChLinkLimit* source)
+{
+	active = source->active;
+	penalty_only = source->penalty_only;
+	polar = source->polar;
+	rotation = source->rotation;
+	max = source->max;
+	min = source->min;
+	maxCushion = source->maxCushion;
+	minCushion = source->minCushion;
+	Kmax= source->Kmax;   Kmin = source->Kmin;
+	Rmax= source->Rmax;   Rmin = source->Rmin;
+	minElastic = source->minElastic;
+	maxElastic = source->maxElastic;
+		// replace functions:
+	if (modul_Kmax) delete modul_Kmax;
+	if (modul_Kmin) delete modul_Kmin;
+	if (modul_Rmax) delete modul_Rmax;
+	if (modul_Rmin) delete modul_Rmin;
+	if (polar_Max)  delete polar_Max;
+	modul_Kmax =   source->modul_Kmax->new_Duplicate();
+	modul_Kmin =   source->modul_Kmin->new_Duplicate();
+	modul_Rmax =   source->modul_Rmax->new_Duplicate();
+	modul_Rmin =   source->modul_Rmin->new_Duplicate();
+	if (source->polar_Max) 
+		polar_Max =   source->polar_Max->new_Duplicate();
+	else polar_Max = NULL;
+}
+
+ChLinkLimit* ChLinkLimit::new_Duplicate ()
+{
+	ChLinkLimit* m_lim;
+	m_lim = new ChLinkLimit;
+	m_lim->Copy(this);
+	return (m_lim);
+}
+
+
+
+void ChLinkLimit::Set_max(double m_max)
+{
+	max = m_max;
+	if (max < min) min = max;
+	if ((max-maxCushion) < min) maxCushion = max - min;
+	if ((max-maxCushion) < (min+minCushion)) minCushion = max - min - maxCushion;
+}
+
+void ChLinkLimit::Set_min(double m_min)
+{
+	min = m_min;
+	if (min > max) max = min;
+	if ((min+minCushion) > max) minCushion = max - min;
+	if ((min+minCushion) > (max-maxCushion)) maxCushion = max - min - minCushion;
+}
+
+void ChLinkLimit::Set_maxCushion(double m_maxCushion)
+{
+	maxCushion = m_maxCushion;
+	if ((max-maxCushion) < min)	 maxCushion = max - min;
+	if ((max-maxCushion) < (min+minCushion)) minCushion = max - min - maxCushion;
+}
+
+void ChLinkLimit::Set_minCushion(double m_minCushion)
+{
+	minCushion = m_minCushion;
+	if ((min+minCushion) > max) minCushion = max - min;
+	if ((min+minCushion) > (max-maxCushion)) maxCushion = max - min - minCushion;
+}
+
+void ChLinkLimit::SetModul_Kmax	(ChFunction* m_funct)
+{
+	if (modul_Kmax) delete modul_Kmax;
+	modul_Kmax = m_funct;
+}
+void ChLinkLimit::SetModul_Kmin	(ChFunction* m_funct)
+{
+	if (modul_Kmin) delete modul_Kmin;
+	modul_Kmin = m_funct;
+}
+void ChLinkLimit::SetModul_Rmax	(ChFunction* m_funct)
+{
+	if (modul_Rmax) delete modul_Rmax;
+	modul_Rmax = m_funct;
+}
+void ChLinkLimit::SetModul_Rmin	(ChFunction* m_funct)
+{
+	if (modul_Rmin) delete modul_Rmin;
+	modul_Rmin = m_funct;
+}
+void ChLinkLimit::SetPolar_Max	(ChFunction* m_funct)
+{
+	if (polar_Max) delete polar_Max;
+	polar_Max = m_funct;
+}
+
+
+
+
+
+// file parsing / dumping
+
+
+
+void ChLinkLimit::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number 
+	mstream.VersionWrite(1); 
+
+		// stream out all member data
+	mstream << Get_active();
+	mstream << Get_polar();
+	mstream << Get_penalty();
+	mstream << Get_min();
+	mstream << Get_max();
+	mstream << Get_minCushion();
+	mstream << Get_maxCushion();
+	mstream << Get_minElastic();
+	mstream << Get_maxElastic();
+	mstream << Get_Kmin();
+	mstream << Get_Kmax();
+	mstream << Get_Rmin();
+	mstream << Get_Rmax();
+	mstream.AbstractWrite(GetPolar_Max());
+	mstream.AbstractWrite(GetModul_Kmin());
+	mstream.AbstractWrite(GetModul_Kmax());
+	mstream.AbstractWrite(GetModul_Rmin());
+	mstream.AbstractWrite(GetModul_Rmax());
+}
+				
+void ChLinkLimit::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number 
+	int version = mstream.VersionRead();
+
+		// stream in all member data
+	double dfoo;
+	int ifoo;
+	ChFunction* ffoo;
+	mstream >> ifoo;		Set_active(ifoo);
+	mstream >> ifoo;		Set_polar(ifoo);
+	mstream >> ifoo;		Set_penalty(ifoo);
+	mstream >> dfoo;		Set_min(dfoo);
+	mstream >> dfoo;		Set_max(dfoo);
+	mstream >> dfoo;		Set_minCushion(dfoo);
+	mstream >> dfoo;		Set_maxCushion(dfoo);	
+	mstream >> dfoo;		Set_minElastic(dfoo);
+	mstream >> dfoo;		Set_maxElastic(dfoo);
+	mstream >> dfoo;		Set_Kmin(dfoo);
+	mstream >> dfoo;		Set_Kmax(dfoo);
+	mstream >> dfoo;		Set_Rmin(dfoo);
+	mstream >> dfoo;		Set_Rmax(dfoo);
+	mstream.AbstractReadCreate(&ffoo);		SetPolar_Max(ffoo);
+	mstream.AbstractReadCreate(&ffoo);		SetModul_Kmin(ffoo);
+	mstream.AbstractReadCreate(&ffoo);		SetModul_Kmax(ffoo);
+	mstream.AbstractReadCreate(&ffoo);		SetModul_Rmin(ffoo);
+	mstream.AbstractReadCreate(&ffoo);		SetModul_Rmax(ffoo);
+}
+
+void ChLinkLimit::StreamOUT(ChStreamOutAscii& mstream)
+{
+	//***TO DO***
+}
+		
+
+
+
+
+///////////////////
+
+double ChLinkLimit::GetViolation (double x)
+{
+	if ((active == 0) || (penalty_only == 1))
+	{
+		return 0;
+	}
+	else
+	{
+		if ((x > min) && (x < max)) return 0; 
+		if (x <= min) return (x-min);
+		if (x >= max) return (x-max);
+	}
+	return 0;
+}
+
+
+double ChLinkLimit::GetForce (double x, double x_dt)
+{
+	double cush_coord;
+	double cush_coord_norm;
+	double force;
+	double m_min, m_max;
+
+	if (penalty_only == 0)
+	{
+		m_min = min;
+		m_max = max;
+	}
+	else
+	{
+		m_min = -999999999;
+		m_max =  999999999;
+	}
+
+	if ((x > m_min) && (x < (min + minCushion)) )
+	{
+		cush_coord = (min + minCushion) - x;
+
+		if (minCushion >= 0.0000001)
+			cush_coord_norm = cush_coord / minCushion;
+		else cush_coord_norm = 1;
+			
+		if (cush_coord_norm > 1) cush_coord_norm = 1;  // clip cushion forces at stopper limit
+
+		force = cush_coord * Kmin * modul_Kmin->Get_y(cush_coord_norm);
+		force +=   (-x_dt) * Rmin * modul_Rmin->Get_y(cush_coord_norm);
+		if (force < 0) {force = 0;} // damping could cause neg force while going away,
+									// so -as the limit is not "sticky"- clip force sign.	
+		
+		return (force); 
+	}
+
+	if ((x < m_max) && (x > (max - maxCushion)) )
+	{
+		cush_coord = x - (max - maxCushion);
+
+		if (maxCushion >= 0.0000001)
+			cush_coord_norm = cush_coord / maxCushion;
+		else cush_coord_norm = 1;
+
+		if (cush_coord_norm > 1) cush_coord_norm = 1;  // clip cushion forces at stopper limit
+
+		force = (-cush_coord) * Kmax * modul_Kmax->Get_y(cush_coord_norm);
+		force +=   (-x_dt) * Rmax * modul_Rmax->Get_y(cush_coord_norm);
+		if (force > 0) {force = 0;} // damping could cause pos force while going away,
+									// so -as the limit is not "sticky"- clip force sign.	
+		return (force); 
+	}
+	return 0;
+}
+
+
+////
+
+double ChLinkLimit::Get_polar_max(double pol_ang)
+{
+	if (!polar_Max) return 0.001;
+	return (polar_Max->Get_y(pol_ang));
+}
+
+//// The same, but for conical limits, in polar coordinates
+
+
+
+double ChLinkLimit::GetPolarForce(double x, double x_dt, double pol_ang)
+{
+	double cush_coord;
+	double cush_coord_norm;
+	double cushion_thick;
+	double force;
+	double m_max;
+	double ang_max;
+
+	if (!polar_Max) return 0;
+
+	if (penalty_only == 0)
+	{
+		m_max = max;
+	}
+	else
+	{
+		m_max =  999999999;
+	}
+
+	ang_max = polar_Max->Get_y(pol_ang);
+
+	if ( (x < m_max) && (x > (ang_max - maxCushion)) )
+	{
+		cushion_thick = maxCushion;
+		if (cushion_thick > ang_max) cushion_thick = ang_max;
+
+		cush_coord = x - (ang_max - maxCushion);
+
+		if (cushion_thick >= 0.0000001)
+			cush_coord_norm = cush_coord / cushion_thick;
+		else cush_coord_norm = 1;
+
+		if (cush_coord_norm > 1) cush_coord_norm = 1;  // clip cushion forces at stopper limit
+
+		force = (-cush_coord) * Kmax * modul_Kmax->Get_y(cush_coord_norm);
+		force +=   (-x_dt) * Rmax * modul_Rmax->Get_y(cush_coord_norm);
+		if (force > 0) {force = 0;} // damping could cause pos force while going away,
+									// so -as the limit is not "sticky"- clip force sign.	
+		return (force); 
+	}
+	return 0;
+}
+
+
+} // END_OF_NAMESPACE____
+
+// eof
+
+
diff --git a/SRC/ChronoEngine/physics/ChLimit.h b/SRC/ChronoEngine/physics/ChLimit.h
new file mode 100644
index 0000000..e1af771
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLimit.h
@@ -0,0 +1,150 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKLIMIT_H
+#define CHLINKLIMIT_H
+
+//////////////////////////////////////////////////
+//  
+//   ChLimit.h
+//
+//   Limit for links (costraints) coordinates.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include <float.h>
+
+#include "core/ChMath.h"
+#include "physics/ChFunction.h"
+#include "physics/ChLinkMask.h"
+#include "lcp/ChLcpConstraintTwoBodies.h"
+
+namespace chrono 
+{
+
+
+
+
+
+/// Class for limits in link joints (for example 
+/// limits on elbow or knee rotations, etc.)
+/// Old code: Must be improved..
+
+class ChApi ChLinkLimit
+{
+private:
+	int active;		// true/false
+	int penalty_only;
+	int polar;
+	int rotation;
+	double max;
+	double min;
+	double maxCushion;
+	double minCushion;
+	double Kmax;
+	double Kmin;
+	double Rmax;
+	double Rmin;
+	double maxElastic;
+	double minElastic;
+	ChFunction* modul_Kmax;
+	ChFunction* modul_Kmin;
+	ChFunction* modul_Rmax;
+	ChFunction* modul_Rmin;
+	ChFunction* polar_Max;
+
+public:
+	ChLcpConstraintTwoBodies constr_upper;
+	ChLcpConstraintTwoBodies constr_lower;
+
+	ChLinkLimit();
+	~ChLinkLimit();
+	void Copy(ChLinkLimit* source);
+	ChLinkLimit* new_Duplicate();
+
+	int	Get_active() {return active;}
+	int	Get_penalty() {return penalty_only;}
+	int Get_polar() {return polar;}
+	int Get_rotation() {return rotation;}
+	double Get_max() {return max;}
+	double Get_min() {return min;}
+	double Get_maxCushion() {return maxCushion;}
+	double Get_minCushion() {return minCushion;}
+	double Get_Kmax() {return Kmax;}
+	double Get_Kmin() {return Kmin;}
+	double Get_Rmax() {return Rmax;}
+	double Get_Rmin() {return Rmin;}
+	double Get_maxElastic() {return maxElastic;}
+	double Get_minElastic() {return minElastic;}
+	ChFunction* GetModul_Kmax() {return modul_Kmax;};
+	ChFunction* GetModul_Kmin() {return modul_Kmin;};
+	ChFunction* GetModul_Rmax() {return modul_Rmax;};
+	ChFunction* GetModul_Rmin() {return modul_Rmin;};
+	ChFunction* GetPolar_Max()  {return polar_Max;};
+	double Get_polar_max(double pol_ang);
+
+	void Set_active(int m_active) {active = m_active;}
+	void Set_penalty(int m_active) {penalty_only = m_active;}
+	void Set_polar(int m_pol) {polar = m_pol;}
+	void Set_rotation(int m_rot) {rotation = m_rot;}
+	void Set_max(double m_max);
+	void Set_min(double m_min);
+	void Set_maxCushion(double m_maxCushion);
+	void Set_minCushion(double m_minCushion);
+	void Set_Kmax(double m_K) {Kmax = m_K;}
+	void Set_Kmin(double m_K) {Kmin = m_K;}
+	void Set_Rmax(double m_R) {Rmax = m_R;}
+	void Set_Rmin(double m_R) {Rmin = m_R;}
+	void Set_maxElastic(double m_e) {maxElastic = m_e;}
+	void Set_minElastic(double m_e) {minElastic = m_e;}
+	void SetModul_Kmax	(ChFunction* m_funct);
+	void SetModul_Kmin	(ChFunction* m_funct);
+	void SetModul_Rmax	(ChFunction* m_funct);
+	void SetModul_Rmin	(ChFunction* m_funct);
+	void SetPolar_Max	(ChFunction* m_funct);
+
+	double GetViolation (double x);  // return negative violation when x<min, or positive if x>max;
+	double GetForce (double x, double x_dt); 
+
+	double GetPolarForce(double x, double x_dt, double pol_ang);
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream);
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLink.cpp b/SRC/ChronoEngine/physics/ChLink.cpp
new file mode 100644
index 0000000..d295007
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLink.cpp
@@ -0,0 +1,236 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLink.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLink.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChSystem.h"
+#include "physics/ChExternalObject.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLink> a_registration_ChLink;
+
+
+                // BUILDERS
+ChLink::ChLink ()
+{
+    Body1 = NULL;
+    Body2 = NULL;
+
+    react_force = VNULL;
+    react_torque = VNULL;
+
+	broken = false;
+	valid = true;
+    disabled = false;
+ 
+    SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+}
+
+
+
+            // DESTROYER
+ChLink::~ChLink ()
+{
+
+}
+
+
+void ChLink::Copy(ChLink* source)
+{
+    // first copy the parent class data...
+    ChPhysicsItem::Copy(source);
+
+    Body1 = 0;
+    Body2 = 0;
+    system = 0;
+
+	react_force = source->react_force;
+	react_torque = source->react_torque;
+
+	broken = source->broken;
+	valid = source->valid;
+    disabled = source->disabled;
+}
+
+
+ChLink* ChLink::new_Duplicate ()   // inherited classes:  Link* MyInheritedLink::new_Duplicate()
+{
+    ChLink* m_l;
+    m_l = new ChLink;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+ 
+
+
+void ChLink::Set2Dmode(int mode)
+{
+    // Nothing specific to do on mask, 'cause base link.
+    // Chld classes can implement this method,
+}
+
+
+
+
+
+
+////////////////////////////////////
+///
+///    UPDATING PROCEDURES
+
+
+
+/////////   1-   UPDATE TIME
+/////////
+
+void ChLink::UpdateTime (double time)
+{
+    ChTime = time;
+}
+
+
+
+
+
+
+/////////
+/////////   COMPLETE UPDATE
+/////////
+/////////
+
+void ChLink::Update (double time)
+{
+    // 1 -
+    UpdateTime(time);
+
+}
+
+
+void ChLink::Update ()
+{
+    Update(ChTime); // use the same time
+}
+
+
+
+
+
+
+void ChLink::UpdateExternalGeometry ()
+{
+	if (GetExternalObject())
+		GetExternalObject()->onChronoChanged();
+}
+
+
+
+
+/////////
+///////// FILE I/O
+/////////
+
+
+// Define some  link-specific flags for backward compatibility
+
+#define LF_INACTIVE		(1L << 0)
+#define LF_BROKEN		(1L << 2)
+#define LF_DISABLED	    (1L << 4)
+
+
+
+void ChLink::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(11);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << disabled;
+	mstream << valid;
+	mstream << broken;
+}
+
+void ChLink::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+	
+		// deserialize parent class too
+	if (version <11)
+	{	
+		ChObj::StreamIN(mstream);
+	}
+	if (version >= 11)
+	{
+		ChPhysicsItem::StreamIN(mstream);
+	}
+
+		// deserialize class data
+	if(version ==1)
+	{
+		int mylflag; // was 'long' in v.1 but 'long' streaming support is removed
+		mstream >> mylflag;
+		valid = !(mylflag & LF_INACTIVE);
+		disabled = (mylflag & LF_DISABLED)!=0;
+		broken = (mylflag & LF_BROKEN)!=0;
+	}
+	if(version >=2)
+	{
+		mstream >> disabled;
+		mstream >> valid;
+		mstream >> broken;
+	}
+	
+}
+
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLink.h b/SRC/ChronoEngine/physics/ChLink.h
new file mode 100644
index 0000000..4e7732f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLink.h
@@ -0,0 +1,275 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINK_H
+#define CHLINK_H
+
+///////////////////////////////////////////////////
+//
+//   ChLink.h
+//
+//
+//   Base class for "links", i.e. 'joints' (mechanical 
+//   constraints) between two moving parts - that is,a
+//   joint between two ChBody objects.
+//
+//   A single ChLink is basically a container of multiple
+//   scalar constraints of type ChConstraint(), for example
+//   a spherical joint uses three scalar constraints 
+//   ChConstraint(), etc., so that the ChSystem can 
+//   communicate with links through the 'LCP interface' 
+//   member methods (see above). 
+//   Another important method is the Update() one.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "core/ChLog.h"
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChBody.h"
+
+
+
+namespace chrono
+{
+
+
+// Forward references
+class ChSystem;
+
+
+
+
+// Define the link type identifier.
+//
+// Some inherited classes from Link class might override the GetType() function
+// to return a custom LNK_ identifiers. Create your own LNK_ identifier for new
+// link classes. Otherwise the default behaviour would be to return LNK_BASE.
+// This ID info is for maximum speed, to avoid to recognize a link type by RTTI.
+// Not all link classes must have a LNK_ identifer, but it is good if at least 
+// the specialized classes have their one.
+// Note that each class may implement more than one type! (see the ChLinkLock case). 
+//
+// Such LNK_ link identifiers must be _unique_. If you are not sure about uniqueness,
+// do not create them and do not use the GetType() function for your own inherited classes.
+//
+
+#define LNK_BASE		29
+
+
+
+
+
+///
+/// Base class for joints betwenn two ChBody objects.
+///
+///  Links are objects which can be created to constrain two rigid
+/// bodies (i.e. objects from the ChBody class) in 3D space, like with
+/// revolute joints, guides, etc. 
+///
+///  Note that there are many specializations of this base class,
+/// for example the ChLinkEngine class inherits this base class and
+/// implements specific functions to represent an engine between two
+/// bodies, etc. etc. (In fact, this base ChLink class does basically
+/// _nothing_ unless it is specialized by some child class).
+///
+
+class ChApi ChLink : public ChPhysicsItem 
+{
+
+	CH_RTTI(ChLink,ChPhysicsItem);
+
+protected:
+
+				//
+	  			// DATA
+				//
+
+	ChBody* Body1;		// body of marker1 (automatically set)
+	ChBody* Body2;		// body of marker2 (automatically set)
+
+
+	Vector react_force;	// store the xyz reactions, expressed in local coordinate system of link;
+	Vector react_torque;// store the torque reactions, expressed in local coordinate system of link;
+
+	bool disabled;		// all constraints of link disabled because of user needs
+	bool valid;			// link data is valid
+	bool broken;		// link is broken because of excessive pulling/pushing.
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+	ChLink ();
+	virtual ~ChLink ();
+	virtual void Copy(ChLink* source);
+	virtual ChLink* new_Duplicate ();  
+
+
+public:
+				//
+	  			// FUNCTIONS
+				//
+
+
+				/// Tells if the link data is currently valid.
+				/// (i.e. pointers to other items are correct)
+	virtual bool IsValid() {return valid;}
+				/// Set the status of link validity
+	virtual void SetValid(bool mon) {valid = mon;}
+
+				/// Tells if all constraints of this link are currently turned
+				/// on or off by the user.
+	virtual bool IsDisabled() {return disabled;}
+				/// User can use this to enable/disable all the constraint of
+				/// the link as desired.
+	virtual void SetDisabled(bool mdis) {disabled = mdis;}
+
+
+				/// Tells if the link is broken, for excess of pulling/pushing.
+	virtual bool IsBroken() {return broken;}
+				/// Ex:3rd party software can set the 'broken' status via this method
+	virtual void SetBroken(bool mon) {broken = mon;}
+
+
+				/// An important function!
+				/// Tells if the link is currently active, in general,
+				/// that is tells if it must be included into the system solver or not.
+				/// This method cumulates the effect of various flags (so a link may
+				/// be not active either because disabled, or broken, or not valid)
+	virtual bool IsActive()
+					{
+						return ( valid &&
+								!disabled &&
+								!broken);
+					}
+
+				/// If this link has been created automatically by 
+				/// collision detection, returns true (false by default). (Was used in the past, now useless)
+	virtual bool IsCreatedByCollisionDetection() {return false;};
+
+				/// Get the type identifier of this link. Use if you don't want to use RTTI for performance.
+	virtual int GetType	() {return LNK_BASE;}
+
+				/// Get the number of free degrees of freedom left by this link, between two bodies.
+	virtual int GetLeftDOF  () {return 6 - GetDOC();}
+				/// Get the number of scalar variables affected by constraints in this link 
+	int GetNumCoords() {return 14;}
+
+				/// Get the constrained body '1', the 'slave' body.
+	ChBody* GetBody1 () {return Body1;}
+				/// Get the constrained body '2', the 'master' body.
+	ChBody* GetBody2 () {return Body2;}
+
+
+				/// Get the link coordinate system, expressed relative to Body2 (the 'master'
+				/// body). This represents the 'main' reference of the link: reaction forces 
+				/// and reaction torques are expressed in this coordinate system.
+				/// By default is in the origin of Body2, but child classes should implement this.
+	virtual ChCoordsys<> GetLinkRelativeCoords() {return CSYSNORM;}
+
+
+				/// To get reaction force, expressed in link coordinate system:
+	ChVector<> Get_react_force() {return react_force;}
+				/// To get reaction torque,  expressed in link coordinate system:
+	ChVector<> Get_react_torque() {return react_torque;}
+
+
+				/// If some constraint is redundant, return to normal state  //***OBSOLETE***
+	virtual int  RestoreRedundant() {return 0;};  ///< \return number of changed constraints
+
+				// Sets the link to work only in 2D mode  //***OBSOLETE***
+				// mode=1 use only constraints for 2D xy plane, mode=0 switch back to 3D.
+	virtual void Set2Dmode(int mode);  
+
+				/// Tells if this link requires that the connected ChBody objects
+				/// must be waken if they are sleeping. By default =true, i.e. always keep awaken, but
+				/// child classes might return false for optimizing sleeping, in case no time-dependant.
+	virtual bool IsRequiringWaking() {return true;}
+
+			//
+			// UPDATING FUNCTIONS
+			//
+
+					/// Given new time, current body state, updates
+					/// time-dependant stuff in link state, for example
+					/// motion laws, moving markers, etc.
+					/// (Default: do nothing but setting new time.)
+	virtual void UpdateTime (double mytime);
+
+
+					// -----------COMPLETE UPDATE.
+					// sequence:
+					//			UpdateTime;
+
+					/// This is an important function, which is called by the 
+					/// owner ChSystem at least once per integration step.
+					/// It may update all auxiliary data of the link, such as
+					/// matrices if any, etc.
+					/// The inherited classes, for example the ChLinkMask, often
+					/// implement specialized versions of this Update(time) function,
+					/// because they might need to update inner states, forces, springs, etc.
+					/// This base version, by default, simply updates the time.
+	virtual void Update (double mytime);
+
+					/// As above, but with current time
+	virtual void Update();
+
+
+					/// Tells to the associated external object of class ChExternalObject(),
+					/// if any, that its 3D shape must be updated in order to syncronize to
+					/// link state (for example, if chrono is a plugin for a 3D modeler, the
+					/// wireframe display of the link may change depending on link state.
+	virtual void UpdateExternalGeometry ();
+
+					/// Called from a foreign software (i.e. a plugin, a CAD appl.), if any, to report 
+					/// that time has changed. Most often you can leave this unimplemented.
+	virtual void UpdatedExternalTime (double, double){}; 
+
+
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii&) {};
+
+};
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkBrake.cpp b/SRC/ChronoEngine/physics/ChLinkBrake.cpp
new file mode 100644
index 0000000..2a788a1
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkBrake.cpp
@@ -0,0 +1,231 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLink.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include "physics/ChLinkBrake.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). 
+ 
+
+namespace chrono
+{
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR BRAKE LINK
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkBrake> a_registration_ChLinkBrake;
+
+
+ChLinkBrake::ChLinkBrake ()
+{
+    type = LNK_BRAKE;       // initializes type
+
+    brake_torque = 0.0;
+    stick_ratio = 1.1;
+
+    brake_mode = BRAKE_ROTATION;
+
+    last_dir = 0;
+    must_stick = FALSE;
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(false, false, false,
+                       false, false, false, false,
+                       false, false);
+
+    ChangedLinkMask();
+}
+
+ChLinkBrake::~ChLinkBrake ()
+{
+    // ..
+}
+
+void ChLinkBrake::Copy(ChLinkBrake* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    brake_torque = source->brake_torque;
+    stick_ratio  = source->stick_ratio;
+    brake_mode  = source->brake_mode;
+
+    last_dir = source->last_dir;
+    must_stick = source->must_stick;
+}
+
+ChLink* ChLinkBrake::new_Duplicate ()
+{
+    ChLinkBrake* m_l;
+    m_l = new ChLinkBrake;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+void ChLinkBrake::Set_brake_mode(int mmode)
+{
+    if (mmode != brake_mode)
+    {
+        brake_mode = mmode;
+
+        // reset mask for default free brake
+		((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_FREE);
+        ((ChLinkMaskLF*)mask)->Constr_X().SetMode(CONSTRAINT_FREE);
+
+        ChangedLinkMask();
+    }
+}
+
+void ChLinkBrake::SetDisabled(bool mdis)
+{
+	ChLinkLock::SetDisabled(mdis);
+
+	((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_FREE);
+    ((ChLinkMaskLF*)mask)->Constr_X().SetMode(CONSTRAINT_FREE);
+
+    ChangedLinkMask();
+}
+
+// UPDATING ///
+
+
+
+// Update time: just change internal time, do not let parent class modify deltaC !
+
+void ChLinkBrake::UpdateTime (double time)
+{
+    ChTime = time;
+}
+
+// Update forces: if not sticked, apply torque
+
+void ChLinkBrake::UpdateForces (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateForces(mytime);
+
+	if (this->IsDisabled()) return;
+
+    // then, if not sticking,
+    if (this->brake_torque)
+    {
+        if (brake_mode == BRAKE_ROTATION)
+        {
+			if ( ((ChLinkMaskLF*)mask)->Constr_E3().IsActive() == false)
+            {
+                int mdir;
+
+                Vector mv_torque = Vmul(VECT_Z, this->brake_torque);
+                mdir = 0;   // clockwise torque
+
+                if (Vdot(this->relWvel, mv_torque) > 0.0)
+                {
+                    mv_torque = Vmul (mv_torque, -1.0);         // keep torque always opposed to ang speed.
+                    mdir = 1;   // counterclockwise torque
+                }
+
+                if (mdir != this->last_dir)
+                    this->must_stick = TRUE;
+                this->last_dir = mdir;
+
+                // +++ADD TO LINK TORQUE VECTOR
+                C_torque = Vadd(C_torque, mv_torque);
+            }
+        }
+        if (brake_mode == BRAKE_TRANSLATEX)
+        {
+			if ( ((ChLinkMaskLF*)mask)->Constr_X().IsActive() == false)
+            {
+                int mdir;
+
+                Vector mv_force = Vmul(VECT_X, this->brake_torque);
+                mdir = 0;       // F-->  rear motion: frontfacing break force
+
+                if (this->relM_dt.pos.x > 0.0)
+                {
+                    mv_force = Vmul (mv_force, -1.0);    // break force always opposed to speed
+                    mdir = 1;   // F<-- backfacing breakforce for front motion
+                }
+
+                if (mdir != this->last_dir)
+                    this->must_stick = TRUE;
+                this->last_dir = mdir;
+
+                // +++ADD TO LINK TORQUE VECTOR
+                C_force = Vadd(C_force, mv_force);
+            }
+        }
+    }
+
+    // turn off sticking feature if stick ration not > 1.0
+    if (this->stick_ratio <= 1.0)
+        must_stick = FALSE;
+}
+
+
+
+// FILE I/O
+
+void ChLinkBrake::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << brake_torque;
+    mstream << stick_ratio;
+    mstream << brake_mode;
+}
+
+void ChLinkBrake::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> brake_torque;
+    mstream >> stick_ratio;
+    mstream >> brake_mode;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkBrake.h b/SRC/ChronoEngine/physics/ChLinkBrake.h
new file mode 100644
index 0000000..7e673a8
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkBrake.h
@@ -0,0 +1,105 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKBRAKE_H
+#define CHLINKBRAKE_H
+
+///////////////////////////////////////////////////
+//
+//   ChLink.h
+//
+//
+//   Classes for brakes and clutches between 
+//   two rotating bodies.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkLock.h"
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_BRAKE		32
+
+
+///
+/// Link representing a brake between two rigid bodies, 
+/// including the sticking effect.
+/// It could be used to represent also linear brakes.
+/// This constraint can behave also as a clutch.
+///  ***OBSOLETE*** better add ChLinkEngine in ENG_MODE_TO_POWERTRAIN_SHAFT mode, and add a ChShaftsClutch between shafts
+
+class ChApi ChLinkBrake : public ChLinkLock {
+
+	CH_RTTI(ChLinkBrake,ChLinkLock);
+
+protected:
+	double brake_torque;	// applied torque.
+	double stick_ratio;		// static sticking torque = stick ratio * brake torque
+							// (if <1, sticking effect is turned off)
+
+	int brake_mode;			// default works as traditional rotating brake, but can also be linear, on x
+	
+	enum eChBrmode{
+		 BRAKE_ROTATION = 0,
+		 BRAKE_TRANSLATEX };
+
+	int last_dir;			// 0= clockwise, 1= anticlockw.  -- internal
+	int must_stick;			// if true, change DOF mask to add link -- internal
+public:
+						// builders and destroyers
+	ChLinkBrake ();
+	virtual ~ChLinkBrake ();
+	virtual void Copy(ChLinkBrake* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+						// UPDATING FUNCTION  -apply braking force-
+	virtual void UpdateTime (double time);
+	virtual void UpdateForces (double mytime);
+
+	virtual void SetDisabled(bool mdis);
+
+
+			// data get/set
+	double  Get_brake_torque() {return brake_torque;};
+	void  Set_brake_torque(double mset) {brake_torque = mset;}
+	double  Get_stick_ratio() {return stick_ratio;};
+	void  Set_stick_ratio(double mset) {stick_ratio = mset;}
+	int		Get_brake_mode() {return brake_mode;};
+	void  Set_brake_mode(int mmode);
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkClearance.cpp b/SRC/ChronoEngine/physics/ChLinkClearance.cpp
new file mode 100644
index 0000000..5966200
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkClearance.cpp
@@ -0,0 +1,290 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkClearance.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+ 
+#include "physics/ChLinkClearance.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). 
+
+ 
+namespace chrono
+{
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR CLEARANCE LINKS
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkClearance> a_registration_ChLinkClearance;
+
+
+ChLinkClearance::ChLinkClearance ()
+{
+    type = LNK_CLEARANCE;     // initializes type
+
+    clearance = 0.1;
+    c_friction = 0.;
+    c_viscous = 0.;
+    c_restitution = 0.9;
+    c_tang_restitution = 0.9;
+	diameter = 0.8;
+
+	contact_F_abs = VNULL;
+	contact_V_abs = VNULL;
+
+	this->limit_X->Set_active(TRUE);
+    this->limit_X->Set_max(clearance);
+    this->limit_X->Set_maxElastic(c_restitution);
+    this->limit_X->Set_min(-1000.0);
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // It was a LinkMaskLF because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(false, false, false,
+                       false, true, true, false,
+                       false, false);
+
+    ChangedLinkMask();
+
+}
+
+ChLinkClearance::~ChLinkClearance ()
+{
+
+}
+
+void ChLinkClearance::Copy(ChLinkClearance* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    clearance = source->clearance;
+	c_friction = source->c_friction;
+	c_restitution = source->c_restitution;
+	c_tang_restitution = source->c_tang_restitution;
+	c_viscous = source->c_viscous;
+	diameter = source->diameter;
+
+	contact_F_abs = source->contact_F_abs;
+	contact_V_abs = source->contact_V_abs;
+}
+
+ChLink* ChLinkClearance::new_Duplicate ()
+{
+    ChLinkClearance* m_l;
+    m_l = new ChLinkClearance;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+// easy data getting
+
+double  ChLinkClearance::Get_axis_eccentricity()
+{
+	return (this->GetDist());
+}
+double  ChLinkClearance::Get_axis_phase()
+{
+	if (!this->GetMarker2()) return 0;
+	double mangle;
+	Vector maxis;
+	Quaternion temp=this->GetMarker2()->GetCoord().rot;
+	Q_to_AngAxis(&temp, &mangle, &maxis);
+	if (maxis.z < 0.0)
+    {
+		maxis = Vmul (maxis, -1.0);
+		mangle = (2.0*CH_C_PI)-mangle;
+    }
+	return (mangle);
+}
+double  ChLinkClearance::Get_rotation_angle()
+{
+	return (this->GetRelAngle());
+}
+Vector  ChLinkClearance::Get_contact_P_abs()
+{
+	if (!this->GetMarker2()) return VNULL;
+	return Vadd(this->GetMarker2()->GetAbsCoord().pos,
+		        Vmul(this->Get_contact_N_abs(), -(this->clearance+this->diameter/2)) );
+}
+Vector  ChLinkClearance::Get_contact_N_abs()
+{
+	if (!this->GetMarker2()) return VECT_X;
+	Vector mNrel = VECT_X;
+	mNrel = Vmul(mNrel, -1);
+	return (this->GetMarker2()->Dir_Ref2World(&mNrel));
+}
+Vector  ChLinkClearance::Get_contact_F_abs()
+{
+	return (this->contact_F_abs);
+}
+double  ChLinkClearance::Get_contact_F_n()
+{
+	if (!this->GetMarker2()) return 0;
+	return (this->GetMarker2()->Dir_World2Ref(&this->contact_F_abs).x);
+}
+double  ChLinkClearance::Get_contact_F_t()
+{
+	if (!this->GetMarker2()) return 0;
+	return (this->GetMarker2()->Dir_World2Ref(&this->contact_F_abs).y);
+}
+double  ChLinkClearance::Get_contact_V_t()
+{
+	if (!this->GetMarker2()) return 0;
+	return (this->GetMarker2()->Dir_World2Ref(&this->contact_V_abs).y);
+}
+
+
+void ChLinkClearance::UpdateForces (double mytime)
+{
+    // May avoid inheriting parent class force computation, since not
+    // needed...
+    // LinkLock::UpdateForces(mytime);
+
+	Vector m_friction_F_abs = VNULL;
+	double m_norm_force = - this->react_force.x;
+
+    // Just add coloumb kinematic friction...
+
+	if (((ChLinkMaskLF*)(this->GetMask()))->Constr_X().IsActive() )
+    {
+		Vector temp=Get_contact_P_abs();
+        Vector pb1 = Body1->Point_World2Body(&temp);
+        Vector pb2 = Body2->Point_World2Body(&temp);
+        Vector m_V1_abs = Body1->RelPoint_AbsSpeed(&pb1 );
+        Vector m_V2_abs = Body2->RelPoint_AbsSpeed(&pb2 );
+		this->contact_V_abs = Vsub(m_V1_abs, m_V2_abs);
+		Vector m_tang_V_abs = Vsub(contact_V_abs,
+							  Vmul(Get_contact_N_abs(), Vdot(contact_V_abs, Get_contact_N_abs())));
+
+			// absolute friction force, as applied in contact point
+        m_friction_F_abs = Vmul(Vnorm(m_tang_V_abs), Get_c_friction()*(- m_norm_force));
+		
+			// transform the friction force in link master coords ***TO CHECK*** (new version!)
+		this->C_force += this->marker2->Dir_World2Ref(&m_friction_F_abs); 
+    }
+
+	// update internal data: the abs. vector of all contact forces, is a sum of reaction and friction
+	this->contact_F_abs = Vadd(Vmul(Get_contact_N_abs(), m_norm_force) ,
+								m_friction_F_abs);
+
+}
+
+
+
+
+
+void ChLinkClearance::UpdateTime (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateTime(mytime);
+
+
+    // Move (well, rotate...) marker 2 to align it in actuator direction
+
+        // ! Require that the BDF routine of marker won't handle speed and acc.calculus of the moved marker 2!
+    marker2->SetMotionType(ChMarker::M_MOTION_EXTERNAL);
+
+    ChMatrix33<> ma;
+    ma.Set_A_quaternion(marker2->GetAbsCoord().rot);
+
+    Vector absdist = Vsub(marker1->GetAbsCoord().pos,
+                          marker2->GetAbsCoord().pos);
+
+	Vector mz = ma.Get_A_Zaxis();
+	Vector my = Vnorm (Vcross(ma.Get_A_Zaxis(), absdist));
+	Vector mx = Vnorm (Vcross(my, ma.Get_A_Zaxis() ));
+
+    ma.Set_A_axis(mx,my,mz);
+
+    Coordsys newmarkpos;
+    newmarkpos.pos = marker2->GetAbsCoord().pos;
+    newmarkpos.rot = ma.Get_A_quaternion();
+    marker2->Impose_Abs_Coord(newmarkpos);        //rotate "main" marker2 into tangent position
+
+
+        // imposed relative positions/speeds
+    deltaC.pos = VNULL;
+    deltaC.pos.x = this->clearance;        // distance is always on M2 'X' axis
+
+    deltaC_dt.pos = VNULL;
+    deltaC_dt.pos.x = 0; // distance speed
+
+    deltaC_dtdt.pos = VNULL;
+
+        // add also the centripetal acceleration if distance vector's rotating,
+        // as centripetal acc. of point sliding on a sphere surface.
+     Vector tang_speed = GetRelM_dt().pos;
+      tang_speed.x = 0; // only z-y coords in relative tang speed vector
+	 double Rcurvature = Vlenght(absdist);
+    deltaC_dtdt.pos.x  = - pow(Vlenght(tang_speed), 2) / Rcurvature;  // An =  -(Vt^2 / r)
+
+    deltaC.rot = QUNIT;             // no relative rotations imposed!
+    deltaC_dt.rot = QNULL;
+    deltaC_dtdt.rot = QNULL;
+}
+
+
+void ChLinkClearance::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << clearance;
+    mstream << c_friction;
+    mstream << c_restitution;
+    mstream << diameter;
+    mstream << c_tang_restitution;
+    mstream << c_viscous;
+}
+
+void ChLinkClearance::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> clearance;
+    mstream >> c_friction;
+    mstream >> c_restitution;
+    mstream >> diameter;
+    mstream >> c_tang_restitution;
+    mstream >> c_viscous;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkClearance.h b/SRC/ChronoEngine/physics/ChLinkClearance.h
new file mode 100644
index 0000000..9a67745
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkClearance.h
@@ -0,0 +1,119 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKCLEARANCE_H
+#define CHLINKCLEARANCE_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkClearance.h
+//
+//
+//   Classes for revolute joints with clearance.
+//
+//   HEADER file for CHRONO, 
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkLock.h"
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_CLEARANCE	34
+
+///
+/// A class for the custom fast simulation of revolute
+/// joints with clearance.
+/// ***OBSOLETE***
+
+class ChApi ChLinkClearance : public ChLinkLock {
+
+	CH_RTTI(ChLinkClearance,ChLinkLock);
+
+protected:
+	double clearance;			// distance offset
+	double c_friction;			// friction coeff.
+	double c_restitution;		// restitution coeff.
+	double c_tang_restitution;	// restitution coeff tangential
+	double c_viscous;			// viscous friction in contact point
+
+	double diameter;			// radius of shaft (in case of circular shaft)
+
+	Vector contact_F_abs;		// [internal]
+	Vector contact_V_abs;		// [internal]
+
+public:
+						// builders and destroyers
+	ChLinkClearance ();
+	virtual ~ChLinkClearance ();
+	virtual void Copy(ChLinkClearance* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+							// UPDATING FUNCTIONS - "lin.act. link" custom implementations
+
+							// Updates marker positions, etc.
+	virtual void UpdateTime (double mytime);
+							// Updates forces
+	virtual void UpdateForces (double mytime);
+
+			// data get/set
+	double  Get_clearance() {return clearance;};
+	void  Set_clearance(double mset) {clearance = mset; limit_X->Set_max(clearance);}
+	double  Get_c_friction() {return c_friction;};
+	void  Set_c_friction(double mset) {c_friction = mset;}
+	double  Get_c_restitution() {return c_restitution;};
+	void  Set_c_restitution(double mset) {c_restitution = mset; limit_X->Set_maxElastic(c_restitution);}
+	double  Get_c_tang_restitution() {return c_tang_restitution;};
+	void  Set_c_tang_restitution(double mset) {c_tang_restitution = mset;}
+	double  Get_c_viscous() {return c_viscous;};
+	void  Set_c_viscous(double mset) {c_viscous = mset;}
+	double  Get_diameter() {return diameter;};
+	void  Set_diameter(double mset) {diameter = mset;}
+
+			// easy data getting
+	double  Get_axis_eccentricity();// distance between the two shafts
+	double  Get_axis_phase();		// phase of center of shaft, respect to hole
+	double  Get_rotation_angle();	// rotation of shafti in hole (relative)
+	Vector  Get_contact_P_abs();	// absolute contact point
+	Vector  Get_contact_N_abs();	// absolute normal to contact
+	Vector  Get_contact_F_abs();	// absolute force in contact
+	double  Get_contact_F_n();		// normal  part of force
+	double  Get_contact_F_t();		// tangent part of force
+	double  Get_contact_V_t();		// tangent part of speed
+
+	int		Get_is_in_contact();	// returns: 1= is sliding contact, 0= is flying
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkContact.cpp b/SRC/ChronoEngine/physics/ChLinkContact.cpp
new file mode 100644
index 0000000..52b0be9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkContact.cpp
@@ -0,0 +1,84 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkContact.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChLinkContact.h"
+#include "physics/ChSystem.h"
+//#include "physics/ChCollide.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR CONTACT
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChLinkContact> a_registration_ChLinkContact;
+ 
+ChLinkContact::ChLinkContact ()
+{ 
+    kin_fri = 0.0;
+    sta_fri = 0.0;
+    restitution = 0.0;
+}
+
+
+ChLinkContact::~ChLinkContact ()
+{
+
+}
+
+void ChLinkContact::Copy(ChLinkContact* source)
+{
+    // first copy the parent class data...
+    //
+    ChLink::Copy(source);
+
+    // copy custom data:
+    kin_fri =       source->kin_fri;
+    sta_fri =       source->sta_fri;
+    restitution =   source->restitution;
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkContact.h b/SRC/ChronoEngine/physics/ChLinkContact.h
new file mode 100644
index 0000000..628f29c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkContact.h
@@ -0,0 +1,125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKCONTACT_H
+#define CHLINKCONTACT_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkContact.h
+//
+//   Classes for enforcing constraints (contacts)
+//   created by collision detection.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+//***OBSOLETE***  not used anymore - see ChConcactContainer.h and ChContact.h
+
+#include "physics/ChLink.h"
+#include "collision/ChCCollisionPair.h"
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_CONTACT	40
+
+///
+/// Parent class for the ChLinkFastContact, ChLinkGPUcontact etc.
+/// Not used directly - look at the children classes.
+///
+
+class ChApi ChLinkContact : public ChLink {
+
+	CH_RTTI(ChLinkContact,ChLink);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	float kin_fri;			// kinem. friction coefficient;
+	float sta_fri;			// static friction;
+	float restitution;		// restitution coefficient;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkContact ();
+
+	virtual ~ChLinkContact ();
+	virtual void Copy(ChLinkContact* source);
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_CONTACT;}
+
+					/// Initialize again this constraint.
+	virtual void Reset(ChCollisionPair* mpair, ChBody* mbody1, ChBody* mbody2) = 0;
+
+					/// Tells IsCreatedByCollisionDetection='true' because this 
+					/// type of constraint is created automatially by ChSystem when 
+					/// collisions occours. 
+	virtual bool IsCreatedByCollisionDetection() {return true;};
+
+					/// Get the number of scalar constraints imposed by this link (only unilateral constr.)
+	virtual int GetDOC_d  () {return 3;}
+
+
+					/// Get the kinematic friction assigned to this contact
+	double Get_kin_fri() {return (double)kin_fri;};
+	void   Set_kin_fri(double mset) {kin_fri = (float)mset;}
+
+					/// Get the static friction assigned to this contact
+	double Get_sta_fri() {return (double)sta_fri;};
+	void   Set_sta_fri(double mset) {sta_fri = (float)mset;}
+
+					/// Get the restitution coefficient assigned to this contact
+	double Get_restitution() {return (double)restitution;};
+	void   Set_restitution(double mset) {restitution = (float)mset;}
+
+					/// Get the contact point on body 1, expressed in world absolute coordinates
+	virtual ChVector<> GetContactP1() = 0;
+					
+					/// Get the contact point on body 2, expressed in world absolute coordinates
+	virtual ChVector<> GetContactP2() = 0;
+		
+					/// Get the contact normal, exiting from body1 surface, expressed in world 
+					/// absolute coordinates
+	virtual ChVector<float> GetContactNormal() = 0;
+
+					/// Get the contact distance (negative if interpenetrating).
+	virtual double	   GetContactDistance() = 0;
+
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkDistance.cpp b/SRC/ChronoEngine/physics/ChLinkDistance.cpp
new file mode 100644
index 0000000..6f9d1a9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkDistance.cpp
@@ -0,0 +1,249 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkDistance.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChLinkDistance.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkDistance> a_registration_ChLinkDistance;
+ 
+
+ChLinkDistance::ChLinkDistance ()
+{ 
+	pos1 = pos2 = VNULL;
+	distance= 0;
+	curr_dist = 0;
+	cache_li_speed = cache_li_pos = 0;
+}
+
+ChLinkDistance::~ChLinkDistance ()
+{
+
+}
+
+
+
+int ChLinkDistance::Initialize(ChSharedPtr<ChBody>& mbody1,   ///< first body to link
+						   ChSharedPtr<ChBody>& mbody2,		 ///< second body to link
+						   bool pos_are_relative,///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpos1,	 ///< position of distance endpoint, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpos2,	 ///< position of distance endpoint, for 2nd body (rel. or abs., see flag above) 
+						   bool auto_distance,///< if true, initializes the imposed distance as the distance between mpos1 and mpos2
+						   double mdistance   ///< imposed distance (no need to define, if auto_distance=true.)
+						   )
+{
+	this->Body1 = mbody1.get_ptr();
+	this->Body2 = mbody2.get_ptr();
+	this->Cx.SetVariables(&this->Body1->Variables(),&this->Body2->Variables());
+
+	if (pos_are_relative)
+	{
+		this->pos1 = mpos1;
+		this->pos2 = mpos2;
+	}
+	else
+	{
+		this->pos1 = this->Body1->Point_World2Body(&mpos1);
+		this->pos2 = this->Body2->Point_World2Body(&mpos2);
+	}
+	
+	ChVector<> AbsDist = Body1->Point_Body2World(&pos1)-Body2->Point_Body2World(&pos2);
+	this->curr_dist = AbsDist.Length();
+
+	if (auto_distance)
+	{
+		this->distance = this->curr_dist;
+	}
+	else
+	{
+		this->distance = mdistance;
+	}
+
+	return true;
+}
+
+
+void ChLinkDistance::Copy(ChLinkDistance* source)
+{
+    // first copy the parent class data...
+    //
+    ChLink::Copy(source);
+
+    // copy custom data:
+	Body1 = source->Body1;
+	Body2 = source->Body2;
+	system = source->system;
+	Cx.SetVariables(&source->Body1->Variables(),&source->Body2->Variables());
+	pos1 = source->pos1;
+	pos2 = source->pos2;
+	distance = source->distance;
+	curr_dist = source->curr_dist;
+	cache_li_speed = source->cache_li_speed;
+	cache_li_pos = source->cache_li_pos;
+}
+
+ChLink* ChLinkDistance::new_Duplicate ()
+{
+    ChLinkDistance* m_l;
+    m_l = new ChLinkDistance;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+ChCoordsys<> ChLinkDistance::GetLinkRelativeCoords()
+{
+	ChVector<> D2local;
+	ChVector<> D2temp=(Vnorm(Body1->Point_Body2World(&pos1)-Body2->Point_Body2World(&pos2)));
+	ChVector<> D2rel = Body2->Dir_World2Body(&D2temp);
+	ChVector<> Vx, Vy, Vz;
+	ChVector<> Vsingul(VECT_Y);
+	ChMatrix33<> rel_matrix;
+	XdirToDxDyDz(&D2rel, &Vsingul, &Vx,  &Vy, &Vz);
+	rel_matrix.Set_A_axis(Vx,Vy,Vz);
+
+	Quaternion Ql2 = rel_matrix.Get_A_quaternion();
+	return ChCoordsys<>(pos2, Ql2); 
+}
+
+  
+void ChLinkDistance::Update (double mytime)
+{
+    // Inherit time changes of parent class (ChLink), basically doing nothing :)
+    ChLink::UpdateTime(mytime);
+
+		// compute jacobians
+	ChVector<> AbsDist = Body1->Point_Body2World(&pos1)-Body2->Point_Body2World(&pos2);
+	curr_dist          = AbsDist.Length();
+	ChVector<> D2abs   = Vnorm(AbsDist);
+	ChVector<> D2relB  = Body2->Dir_World2Body(&D2abs);
+	ChVector<> D2relA  = Body1->Dir_World2Body(&D2abs);
+
+	ChVector<> CqAx =  D2abs;
+	ChVector<> CqBx = -D2abs;
+	
+	ChVector<> CqAr = -Vcross(D2relA,pos1);
+	ChVector<> CqBr =  Vcross(D2relB,pos2);
+
+	Cx.Get_Cq_a()->ElementN(0)=(float)CqAx.x;
+	Cx.Get_Cq_a()->ElementN(1)=(float)CqAx.y;
+	Cx.Get_Cq_a()->ElementN(2)=(float)CqAx.z;
+	Cx.Get_Cq_a()->ElementN(3)=(float)CqAr.x;
+	Cx.Get_Cq_a()->ElementN(4)=(float)CqAr.y;
+	Cx.Get_Cq_a()->ElementN(5)=(float)CqAr.z;
+
+	Cx.Get_Cq_b()->ElementN(0)=(float)CqBx.x;
+	Cx.Get_Cq_b()->ElementN(1)=(float)CqBx.y;
+	Cx.Get_Cq_b()->ElementN(2)=(float)CqBx.z;
+	Cx.Get_Cq_b()->ElementN(3)=(float)CqBr.x;
+	Cx.Get_Cq_b()->ElementN(4)=(float)CqBr.y;
+	Cx.Get_Cq_b()->ElementN(5)=(float)CqBr.z;
+
+	//***TO DO***  C_dt? C_dtdt? (may be never used..)
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChLinkDistance::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	if (!this->IsActive())
+		return;
+
+	mdescriptor.InsertConstraint(&Cx); 
+}
+
+void ChLinkDistance::ConstraintsBiReset()
+{
+	Cx.Set_b_i(0.);
+}
+ 
+void ChLinkDistance::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	if (!this->IsActive())
+		return;
+
+	if (do_clamp)
+		Cx.Set_b_i( Cx.Get_b_i() + ChMin(ChMax (factor * (curr_dist-distance), -recovery_clamp), recovery_clamp)  );
+	else
+		Cx.Set_b_i( Cx.Get_b_i() + factor * (curr_dist-distance)  );
+}
+
+void ChLinkDistance::ConstraintsLoadJacobians()
+{
+	// already loaded when doing Update (which used the matrices of the scalar constraint objects)
+
+}
+ 
+
+void ChLinkDistance::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	react_force.x = Cx.Get_l_i() * factor;  
+	react_force.y = 0;
+	react_force.z = 0;
+
+	react_torque = VNULL;
+}
+
+
+
+// 
+// Following functions are for exploiting the contact persistence
+//
+
+void  ChLinkDistance::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	Cx.Set_l_i(this->cache_li_speed);
+}
+
+void  ChLinkDistance::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	Cx.Set_l_i(this->cache_li_pos);
+}
+
+void  ChLinkDistance::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	this->cache_li_speed = (float)Cx.Get_l_i();
+}
+
+void  ChLinkDistance::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	this->cache_li_pos =  (float)Cx.Get_l_i();
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkDistance.h b/SRC/ChronoEngine/physics/ChLinkDistance.h
new file mode 100644
index 0000000..bf853ab
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkDistance.h
@@ -0,0 +1,174 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKDISTANCE_H
+#define CHLINKDISTANCE_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkDistance.h
+//
+//   Class for enforcing a fixed polar distance 
+//   between two points on two ChBody objects.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkGeometric.h"
+#include "lcp/ChLcpConstraintTwoBodies.h"
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_GEOMETRICDISTANCE	37
+
+
+/// Class for enforcing a fixed polar distance 
+/// between two points on two ChBody objects.
+/// The two points which are used to define the end points
+/// of the distance are assumed not to move respect to the
+/// two owner ChBody, as well as the amount of the distance
+/// is assumed not to change during the simulation. If you
+/// need to have a time-varying distance, or distance between
+/// two points which move respect to the bodies, please use 
+/// the more advanced ChLinkLinActuator.
+
+class ChApi ChLinkDistance : public ChLinkGeometric {
+
+	CH_RTTI(ChLinkDistance,ChLinkGeometric);
+
+protected:
+				//
+	  			// DATA
+				//
+							// the imposed distance
+	double	distance;	
+							// the distance endpoints, in body rel.coords
+	ChVector<> pos1;
+	ChVector<> pos2;
+							// the constraint object
+	ChLcpConstraintTwoBodies Cx;
+
+	double curr_dist;		// used for internal optimizations
+	
+	float cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	float cache_li_pos;		// used to cache the last computed value of multiplier (solver warm starting)
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkDistance ();
+
+	virtual ~ChLinkDistance ();
+	virtual void Copy(ChLinkDistance* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_GEOMETRICDISTANCE;}
+
+					/// Initialize this constraint, given the two bodies to be connected, the
+					/// positions of the two anchor endpoints of the distance (each expressed
+					/// in body or abs. coordinates) and the imposed distance.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,		 ///< first body to link
+						   ChSharedPtr<ChBody>& mbody2,		 ///< second body to link
+						   bool pos_are_relative,///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpos1,	 ///< position of distance endpoint, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpos2,	 ///< position of distance endpoint, for 2nd body (rel. or abs., see flag above) 
+						   bool auto_distance =true,///< if true, initializes the imposed distance as the distance between mpos1 and mpos2
+						   double mdistance =0   ///< imposed distance (no need to define, if auto_distance=true.)
+						   );
+
+					/// Get the number of scalar constraints imposed by this link (only unilateral constr.)
+	virtual int GetDOC_d  () {return 1;}
+
+					/// Get the link coordinate system, expressed relative to Body2 (the 'master'
+					/// body). This represents the 'main' reference of the link: reaction forces 
+					/// are expressed in this coordinate system.
+					/// (It is the coordinate system of the contact plane relative to Body2)
+	ChCoordsys<> GetLinkRelativeCoords();
+
+					/// Get the 1st anchor endpoint for the distance (expressed in Body1 coordinate system)
+	ChVector<> GetEndPoint1Rel() {return pos1;}
+					/// Set the 1st anchor endpoint for the distance (expressed in Body1 coordinate system)
+	void       SetEndPoint1Rel(const ChVector<>& mset) {pos1 = mset;}
+					/// Get the 1st anchor endpoint for the distance (expressed in absolute coordinate system)
+	ChVector<> GetEndPoint1Abs() {return Body1->Point_Body2World(&pos1);}
+					/// Set the 1st anchor endpoint for the distance (expressed in absolute coordinate system)
+	void       SetEndPoint1Abs(ChVector<>& mset) {pos1 = Body1->Point_World2Body(&mset);}
+
+					/// Get the 2nd anchor endpoint for the distance (expressed in Body2 coordinate system)
+	ChVector<> GetEndPoint2Rel() {return pos2;};
+					/// Set the 2nd anchor endpoint for the distance (expressed in Body2 coordinate system)
+	void       SetEndPoint2Rel(const ChVector<>& mset) {pos2 = mset;}
+					/// Get the 1st anchor endpoint for the distance (expressed in absolute coordinate system)
+	ChVector<> GetEndPoint2Abs() {return Body2->Point_Body2World(&pos2);}
+					/// Set the 1st anchor endpoint for the distance (expressed in absolute coordinate system)
+	void       SetEndPoint2Abs(ChVector<>& mset) {pos2 = Body2->Point_World2Body(&mset);}
+
+
+					/// Get the imposed distance
+	double GetImposedDistance() {return distance;};
+					/// Set the imposed distance
+	void   SetImposedDistance(const double mset) {distance = mset;}
+					/// Get the distance currently existing between the two endpoints
+	double GetCurrentDistance() {return (Body1->Point_Body2World(&pos1)-Body2->Point_Body2World(&pos2)).Length(); };
+
+
+				//
+				// UPDATING FUNCTIONS
+				//
+
+					/// Override _all_ time, jacobian etc. updating.
+					/// In detail, it computes jacobians, violations, etc. and stores 
+					/// results in inner structures.
+	virtual void Update (double mtime);
+
+
+				//
+				// LCP INTERFACE
+				//
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsFetch_react(double factor=1.);
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkEngine.cpp b/SRC/ChronoEngine/physics/ChLinkEngine.cpp
new file mode 100644
index 0000000..a8d8e4e
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkEngine.cpp
@@ -0,0 +1,841 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkEngine.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+
+#include "physics/ChLinkEngine.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR ENGINE LINKS
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkEngine> a_registration_ChLinkEngine;
+
+
+ChLinkEngine::ChLinkEngine ()
+{
+    type = LNK_ENGINE;      // initializes type
+
+    rot_funct =   new ChFunction_Const (0);
+    spe_funct =   new ChFunction_Const (0);
+    tor_funct =   new ChFunction_Const (0);
+    torque_w  =   new ChFunction_Const (1);
+
+	rot_funct_x =   new ChFunction_Const (0);
+	rot_funct_y =   new ChFunction_Const (0);
+
+    mot_rot = mot_rot_dt = mot_rot_dtdt = 0.0;
+    mot_rerot = mot_rerot_dt = mot_rerot_dtdt = 0.0;
+    mot_torque = mot_retorque = 0.0;
+	last_r3mot_rot = 0;
+	last_r3mot_rot_dt = 0;
+	last_r3relm_rot = QUNIT;
+	last_r3relm_rot_dt = QNULL;
+	last_r3time = 0;
+	keyed_polar_rotation = QNULL;
+    impose_reducer = FALSE;
+
+    mot_tau = 1.0;
+    mot_eta = 1.0;
+    mot_inertia = 0.0;
+
+	cache_li_speed1 = 0;
+	cache_li_pos1 = 0;
+	torque_react1 = 0;
+	cache_li_speed2 = 0;
+	cache_li_pos2 = 0;
+	torque_react2 = 0;
+
+    eng_mode= ENG_MODE_ROTATION;
+    learn = FALSE;
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to E3 only.
+    ((ChLinkMaskLF*)mask)->SetLockMask(true, false, false,
+                       false, false, false, true,
+                       false, false);
+    ChangedLinkMask();
+            // Mask: initialize remaining LinkMaskLF (lock formulation mask) for the engine.
+            // All shaft modes at least are setting the lock on E3 (z-rotation) coordinate.
+    Set_shaft_mode(ENG_SHAFT_LOCK);
+}
+
+ChLinkEngine::~ChLinkEngine ()
+{
+    if (rot_funct) delete rot_funct;
+    if (spe_funct) delete spe_funct;
+    if (tor_funct) delete tor_funct;
+    if (torque_w)  delete torque_w;
+
+	if (rot_funct_x) delete rot_funct_x;
+	if (rot_funct_y) delete rot_funct_y;
+}
+
+void ChLinkEngine::Copy(ChLinkEngine* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    learn = source->learn;
+    eng_mode= source->eng_mode;
+    shaft_mode = source->shaft_mode;
+
+    mot_rot = source->mot_rot;
+    mot_rot_dt = source->mot_rot_dt;
+    mot_rot_dtdt = source->mot_rot_dtdt;
+    mot_rerot = source->mot_rerot;
+    mot_rerot_dt = source->mot_rerot_dt;
+    mot_rerot_dtdt = source->mot_rerot_dtdt;
+    mot_torque = source->mot_torque;
+    mot_retorque = source->mot_retorque;
+    impose_reducer = source->impose_reducer;
+	last_r3time = source->last_r3time;
+	last_r3mot_rot = source->last_r3mot_rot;
+	last_r3mot_rot_dt = source->last_r3mot_rot_dt;
+	last_r3relm_rot = source->last_r3relm_rot;
+	last_r3relm_rot_dt = source->last_r3relm_rot_dt;
+	keyed_polar_rotation = source->keyed_polar_rotation;
+
+    if (rot_funct) delete rot_funct;
+        rot_funct =   source->rot_funct->new_Duplicate();
+    if (spe_funct) delete spe_funct;
+        spe_funct =   source->spe_funct->new_Duplicate();
+    if (tor_funct) delete tor_funct;
+        tor_funct =   source->tor_funct->new_Duplicate();
+    if (torque_w)  delete torque_w;
+        torque_w =   source->torque_w->new_Duplicate();
+
+	if (rot_funct_x) delete rot_funct_x;
+        rot_funct_x =   source->rot_funct_x->new_Duplicate();
+    if (rot_funct_y) delete rot_funct_y;
+        rot_funct_y =   source->rot_funct_y->new_Duplicate();
+
+    mot_tau = source->mot_tau;
+    mot_eta = source->mot_eta;
+    mot_inertia = source->mot_inertia;
+
+	cache_li_speed1 = 0;
+	cache_li_pos1 = 0;
+	torque_react1 = source->torque_react1;
+	cache_li_speed2 = 0;
+	cache_li_pos2 = 0;
+	torque_react2 = source->torque_react2;
+}
+
+ChLink* ChLinkEngine::new_Duplicate ()
+{
+    ChLinkEngine* m_l;
+    m_l = new ChLinkEngine;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+void ChLinkEngine::Set_learn(int mset)
+{
+    learn = mset;
+
+    if ((this->eng_mode == ENG_MODE_ROTATION) ||
+        (this->eng_mode == ENG_MODE_SPEED) ||
+		(this->eng_mode == ENG_MODE_KEY_ROTATION) )
+    {
+        if (mset)
+            ((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_FREE);
+        else
+            ((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_LOCK);
+
+        ChangedLinkMask ();
+    }
+
+	if (this->eng_mode == ENG_MODE_KEY_POLAR)
+	{
+		if (mset) {
+            ((ChLinkMaskLF*)mask)->Constr_E1().SetMode(CONSTRAINT_FREE);
+			((ChLinkMaskLF*)mask)->Constr_E2().SetMode(CONSTRAINT_FREE);
+			((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_FREE);
+		}
+        else {
+            ((ChLinkMaskLF*)mask)->Constr_E1().SetMode(CONSTRAINT_LOCK);
+			((ChLinkMaskLF*)mask)->Constr_E2().SetMode(CONSTRAINT_LOCK);
+			((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_LOCK);
+        }
+        ChangedLinkMask ();
+	}
+
+    if (this->eng_mode == ENG_MODE_ROTATION)
+        if (rot_funct->Get_Type() != FUNCT_RECORDER) // if wasn't recorder f()..
+        {
+            delete (rot_funct); rot_funct = NULL;
+            rot_funct = new ChFunction_Recorder;
+        }
+
+    if (this->eng_mode == ENG_MODE_SPEED)
+        if (spe_funct->Get_Type() != FUNCT_RECORDER) // if wasn't recorder f()..
+        {
+            delete (spe_funct); spe_funct = NULL;
+            spe_funct = new ChFunction_Recorder;
+        }
+}
+
+void ChLinkEngine::Set_rot_funct(ChFunction* m_funct)
+{
+    if (rot_funct) delete rot_funct;
+        rot_funct = m_funct;
+}
+void ChLinkEngine::Set_spe_funct(ChFunction* m_funct)
+{
+    if (spe_funct) delete spe_funct;
+        spe_funct = m_funct;
+}
+void ChLinkEngine::Set_tor_funct(ChFunction* m_funct)
+{
+    if (tor_funct) delete tor_funct;
+        tor_funct = m_funct;
+}
+void ChLinkEngine::Set_torque_w_funct(ChFunction* m_funct)
+{
+    if (torque_w) delete torque_w;
+        torque_w = m_funct;
+}
+void ChLinkEngine::Set_rot_funct_x(ChFunction* m_funct_x)
+{
+    if (rot_funct_x) delete rot_funct_x;
+        rot_funct_x = m_funct_x;
+}
+void ChLinkEngine::Set_rot_funct_y(ChFunction* m_funct_y)
+{
+    if (rot_funct_y) delete rot_funct_y;
+        rot_funct_y = m_funct_y;
+}
+void ChLinkEngine::SetKeyedPolarRotation(Quaternion mq)
+{
+	keyed_polar_rotation = mq;
+}
+
+
+void ChLinkEngine::Set_eng_mode(int mset)
+{
+    if (Get_learn()) Set_learn(FALSE); // reset learn state when changing mode
+
+    if (eng_mode != mset)
+    {
+        eng_mode = mset;
+        if (this->eng_mode == ENG_MODE_ROTATION ||
+            this->eng_mode == ENG_MODE_SPEED ||
+			this->eng_mode == ENG_MODE_KEY_ROTATION)
+        {
+            ((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_LOCK);
+        }
+
+		if (this->eng_mode == ENG_MODE_KEY_POLAR)
+		{
+            ((ChLinkMaskLF*)mask)->Constr_E1().SetMode(CONSTRAINT_LOCK);
+			((ChLinkMaskLF*)mask)->Constr_E2().SetMode(CONSTRAINT_LOCK);
+			((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_LOCK);
+		}
+
+        if (this->eng_mode == ENG_MODE_TORQUE )
+        {
+            ((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_FREE);
+
+        }
+
+		if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+        {
+            ((ChLinkMaskLF*)mask)->Constr_E3().SetMode(CONSTRAINT_FREE);
+        }
+
+        ChangedLinkMask();  // update all from new mask
+    }
+
+	if (this->eng_mode == ENG_MODE_KEY_ROTATION)
+        if (rot_funct->Get_Type() != FUNCT_CONST) // if wasn't constant f()..
+        {
+            delete (rot_funct); rot_funct = NULL;
+            rot_funct = new ChFunction_Const;
+        }
+
+	if (this->eng_mode == ENG_MODE_KEY_POLAR)
+	{
+        if (rot_funct->Get_Type() != FUNCT_CONST)  {
+            delete (rot_funct); rot_funct = NULL;
+            rot_funct = new ChFunction_Const;
+        }
+		if (rot_funct_x->Get_Type() != FUNCT_CONST)  {
+            delete (rot_funct_x); rot_funct_x = NULL;
+            rot_funct_x = new ChFunction_Const;
+        }
+		if (rot_funct_y->Get_Type() != FUNCT_CONST)  {
+            delete (rot_funct_y); rot_funct_y = NULL;
+            rot_funct_y = new ChFunction_Const;
+        }
+	}
+}
+
+void ChLinkEngine::Set_shaft_mode(int mset)
+{
+    shaft_mode = mset;
+
+	eChConstraintMode curr_mode_z = ((ChLinkMaskLF*)mask)->Constr_E3().GetMode();
+
+    switch(this->shaft_mode)
+    {
+    case ENG_SHAFT_PRISM:
+        ((ChLinkMaskLF*)mask)->SetLockMask(true, true, false,
+                           false, true, true, true, // <-
+                           false, false); break;
+    case ENG_SHAFT_UNIVERSAL:
+        ((ChLinkMaskLF*)mask)->SetLockMask(true, true, true,
+                           false, false, false, true, // <-
+                           false, false); break;
+    case ENG_SHAFT_CARDANO:
+        ((ChLinkMaskLF*)mask)->SetLockMask(false, false, false,
+                           false, false, false, true, // <-
+                           false, false); break;
+    case ENG_SHAFT_OLDHAM:
+        ((ChLinkMaskLF*)mask)->SetLockMask(false, false, false,
+                           false, true, true, true, // <-
+                           false, false); break;
+    case ENG_SHAFT_LOCK:
+    default:
+        ((ChLinkMaskLF*)mask)->SetLockMask(true, true, true,
+                           false, true, true, true, // <-
+                           false, false); break;
+    }
+
+	((ChLinkMaskLF*)mask)->Constr_E3().SetMode(curr_mode_z);
+
+
+    // change datas
+    ChangedLinkMask();
+}
+
+
+void ChLinkEngine::UpdatedExternalTime (double prevtime, double time)
+{
+	last_r3time = this->ChTime;
+	last_r3mot_rot = this->Get_mot_rot();
+	last_r3mot_rot_dt = this->Get_mot_rot_dt();
+	last_r3relm_rot = this->GetRelM().rot;
+	last_r3relm_rot_dt = this->GetRelM_dt().rot;
+}
+
+void ChLinkEngine::UpdateTime (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateTime(mytime);
+
+	if (!IsActive()) 
+		return;
+
+    // DEFAULTS compute rotation vars...
+    // by default for torque control..
+
+    motion_axis = VECT_Z;       // motion axis is always the marker2 Z axis (in m2 relative coords)
+    mot_rot = this->relAngle;
+    mot_rot_dt = Vdot(this->relWvel, motion_axis);
+    mot_rot_dtdt = Vdot(this->relWacc, motion_axis);
+    mot_rerot = mot_rot / this->mot_tau;
+    mot_rerot_dt = mot_rot_dt / this->mot_tau;
+    mot_rerot_dtdt = mot_rot_dtdt / this->mot_tau;
+
+                // nothing more to do here fortorque control
+    if (this->eng_mode == ENG_MODE_TORQUE) return; // >>>>>>
+
+
+    // If LEARN MODE, just record motion
+    if (learn == TRUE)
+    {
+        deltaC.pos = VNULL;
+        deltaC_dt.pos = VNULL;
+        deltaC_dtdt.pos = VNULL;
+		if(!(limit_Rx->Get_active() ||
+			 limit_Ry->Get_active() ||
+			 limit_Rz->Get_active()))
+		{
+			deltaC.rot = QUNIT;
+			deltaC_dt.rot = QNULL;
+			deltaC_dtdt.rot = QNULL;
+		}
+
+        if (this->eng_mode == ENG_MODE_ROTATION)
+        {
+            if (rot_funct->Get_Type() != FUNCT_RECORDER) // if wasn't recorder f()..
+            {
+                delete (rot_funct); rot_funct = NULL;
+                rot_funct = new ChFunction_Recorder;
+            }
+                    // record point
+            double rec_rot = this->relAngle; // ***TO DO*** compute also rotations with cardano mode?
+            if (this->impose_reducer)
+                rec_rot = rec_rot / this->mot_tau;
+            ((ChFunction_Recorder*)rot_funct)->AddPoint(mytime, rec_rot, 1);  //  x=t
+        }
+        if (this->eng_mode == ENG_MODE_SPEED)
+        {
+            if (spe_funct->Get_Type() != FUNCT_RECORDER) // if wasn't recorder f()..
+            {
+                delete (spe_funct); spe_funct = NULL;
+                spe_funct = new ChFunction_Recorder;
+            }
+                    // record point
+            double rec_spe = Vlenght(this->relWvel); // ***TO DO*** compute also with cardano mode?
+            if (this->impose_reducer)
+                rec_spe = rec_spe / this->mot_tau;
+            ((ChFunction_Recorder*)spe_funct)->AddPoint(mytime, rec_spe, 1);  //  x=t
+        }
+    }
+
+
+    if (learn == TRUE) return; // no need to go on further...--->>>>
+                               // no need to go on further...--->>>>
+
+    // Impose relative positions/speeds
+
+    deltaC.pos = VNULL;
+    deltaC_dt.pos = VNULL;
+    deltaC_dtdt.pos = VNULL;
+
+    if (this->eng_mode == ENG_MODE_ROTATION)
+    {
+        if (this->impose_reducer)
+        {
+            mot_rerot = this->rot_funct->Get_y(ChTime);
+            mot_rerot_dt = this->rot_funct->Get_y_dx(ChTime);
+            mot_rerot_dtdt = this->rot_funct->Get_y_dxdx(ChTime);
+            mot_rot = mot_rerot * this->mot_tau;
+            mot_rot_dt = mot_rerot_dt * this->mot_tau;
+            mot_rot_dtdt = mot_rerot_dtdt * this->mot_tau;
+        } else {
+            mot_rot = this->rot_funct->Get_y(ChTime);
+            mot_rot_dt = this->rot_funct->Get_y_dx(ChTime);
+            mot_rot_dtdt = this->rot_funct->Get_y_dxdx(ChTime);
+            mot_rerot = mot_rot / this->mot_tau;
+            mot_rerot_dt = mot_rot_dt / this->mot_tau;
+            mot_rerot_dtdt = mot_rot_dtdt / this->mot_tau;
+        }
+        deltaC.rot = Q_from_AngAxis (mot_rot, motion_axis);
+        deltaC_dt.rot = Qdt_from_AngAxis (deltaC.rot, mot_rot_dt, motion_axis);
+        deltaC_dtdt.rot = Qdtdt_from_AngAxis (mot_rot_dtdt, motion_axis, deltaC.rot, deltaC_dt.rot);
+    }
+    if (this->eng_mode == ENG_MODE_SPEED)
+    {
+        if (this->impose_reducer)
+        {
+            mot_rerot_dt = this->spe_funct->Get_y(ChTime);
+            mot_rerot_dtdt = this->spe_funct->Get_y_dx(ChTime);
+            mot_rot_dt = mot_rerot_dt * this->mot_tau;
+            mot_rot_dtdt = mot_rerot_dtdt * this->mot_tau;
+        } else {
+            mot_rot_dt = this->spe_funct->Get_y(ChTime);
+            mot_rot_dtdt = this->spe_funct->Get_y_dx(ChTime);
+            mot_rerot_dt = mot_rot_dt / this->mot_tau;
+            mot_rerot_dtdt = mot_rot_dtdt / this->mot_tau;
+        }
+        deltaC.rot = Qnorm(this->GetRelM().rot);    // just keep current position, -assume always good after integration-.
+		ChMatrix33<> relA; relA.Set_A_quaternion(this->GetRelM().rot);  // ..but adjust to keep Z axis aligned to shaft, anyway!
+		ChVector<> displaced_z_axis; displaced_z_axis = relA.Get_A_Zaxis();
+		ChVector<> adjustment = Vcross(displaced_z_axis, VECT_Z);
+		deltaC.rot = Q_from_AngAxis(Vlenght(adjustment),Vnorm(adjustment)) % deltaC.rot;
+        deltaC_dt.rot = Qdt_from_AngAxis (deltaC.rot, mot_rot_dt, motion_axis);
+        deltaC_dtdt.rot = Qdtdt_from_AngAxis (mot_rot_dtdt, motion_axis, deltaC.rot, deltaC_dt.rot);
+    }
+
+}
+
+void ChLinkEngine::UpdateForces (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateForces(mytime);
+
+	if (!IsActive()) 
+		return;
+
+    // DEFAULTS set null torques
+    this->mot_torque = 0;
+    this->mot_retorque = 0;
+
+    if (this->eng_mode == ENG_MODE_TORQUE)
+    {
+        // in torque mode, apply the torque vector to both m1 and m2
+        //  -  M= f(t)
+        double my_torque = this->Get_tor_funct()->Get_y(ChTime);
+
+        if (this->impose_reducer)
+        {
+            my_torque = my_torque*this->Get_torque_w_funct()->Get_y(this->mot_rerot_dt);
+            mot_retorque = my_torque;
+            mot_torque = mot_retorque*(this->mot_eta/this->mot_tau);
+        } else {
+            my_torque = my_torque*this->Get_torque_w_funct()->Get_y(this->mot_rot_dt);
+            mot_torque = my_torque;
+            mot_retorque = mot_retorque*(this->mot_tau/this->mot_eta);
+        }
+
+        Vector mv_torque = Vmul(motion_axis, mot_torque);
+
+        // +++ADD TO LINK TORQUE VECTOR
+        C_torque = Vadd(C_torque, mv_torque);
+
+    }
+
+    if ((this->eng_mode == ENG_MODE_ROTATION) ||
+        (this->eng_mode == ENG_MODE_SPEED) ||
+		(this->eng_mode == ENG_MODE_KEY_ROTATION) )
+    {
+        this->mot_torque = this->react_torque.z;
+        this->mot_retorque = mot_torque*(mot_tau/mot_eta)+mot_rerot_dtdt*mot_inertia;
+    }
+
+    if(this->eng_mode == ENG_MODE_SPEED)
+    {
+        // trick: zeroes Z rotat. violation to tell that rot.position is always ok
+        if (C->GetRows())
+            C->SetElement(C->GetRows() -1, 0 , 0.0);
+    }
+}
+
+
+
+void ChLinkEngine::SetMarker1 (ChMarker* mark1)
+{
+	ChLinkLock::SetMarker1 (mark1);
+	
+	if(this->Body1 && this->Body2)
+	{
+		this->innerconstraint1.SetVariables(&Body1->Variables(), &innershaft1.Variables());
+		this->innerconstraint2.SetVariables(&Body2->Variables(), &innershaft2.Variables());
+	}
+}
+
+void ChLinkEngine::SetMarker2 (ChMarker* mark2)
+{
+	ChLinkLock::SetMarker2 (mark2);
+	
+	if(this->Body1 && this->Body2)
+	{
+		this->innerconstraint1.SetVariables(&Body1->Variables(), &innershaft1.Variables());
+		this->innerconstraint2.SetVariables(&Body2->Variables(), &innershaft2.Variables());
+	}
+	
+}
+
+
+//
+//  LCP functions
+//
+
+
+void ChLinkEngine::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	// First, inherit to parent class
+    ChLinkLock::InjectConstraints(mdescriptor);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		mdescriptor.InsertConstraint(&this->innerconstraint1);
+		mdescriptor.InsertConstraint(&this->innerconstraint2);
+	}
+}
+
+void ChLinkEngine::ConstraintsBiReset()
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsBiReset();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innerconstraint1.Set_b_i(0.);
+		this->innerconstraint2.Set_b_i(0.);
+	}
+}
+ 
+void ChLinkEngine::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsBiLoad_C(factor, recovery_clamp, do_clamp);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		double res = 0; // no residual
+		this->innerconstraint1.Set_b_i(innerconstraint1.Get_b_i() +  factor * res);
+		this->innerconstraint2.Set_b_i(innerconstraint2.Get_b_i() +  factor * res);
+	}
+}
+
+void ChLinkEngine::ConstraintsBiLoad_Ct(double factor)
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsBiLoad_Ct(factor);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		// nothing
+	}
+}
+
+void ChLinkEngine::ConstraintsLoadJacobians()
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsLoadJacobians();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		// compute jacobians
+		ChVector<> tempz=ChVector<>(VECT_Z);
+		ChVector<> abs_rot_axis = this->marker2->Dir_Ref2World(&tempz);
+		ChVector<> jacw = this->Body2->Dir_World2Body(&abs_rot_axis);
+
+		this->innerconstraint1.Get_Cq_a()->ElementN(0)=0;
+		this->innerconstraint1.Get_Cq_a()->ElementN(1)=0;
+		this->innerconstraint1.Get_Cq_a()->ElementN(2)=0;
+		this->innerconstraint1.Get_Cq_a()->ElementN(3)=(float)jacw.x;
+		this->innerconstraint1.Get_Cq_a()->ElementN(4)=(float)jacw.y;
+		this->innerconstraint1.Get_Cq_a()->ElementN(5)=(float)jacw.z;
+		this->innerconstraint1.Get_Cq_b()->ElementN(0)=-1;
+
+		this->innerconstraint2.Get_Cq_a()->ElementN(0)=0;
+		this->innerconstraint2.Get_Cq_a()->ElementN(1)=0;
+		this->innerconstraint2.Get_Cq_a()->ElementN(2)=0;
+		this->innerconstraint2.Get_Cq_a()->ElementN(3)=(float)jacw.x;
+		this->innerconstraint2.Get_Cq_a()->ElementN(4)=(float)jacw.y;
+		this->innerconstraint2.Get_Cq_a()->ElementN(5)=(float)jacw.z;
+		this->innerconstraint2.Get_Cq_b()->ElementN(0)=-1;
+	}
+}
+ 
+
+void ChLinkEngine::ConstraintsFetch_react(double factor)
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsFetch_react(factor);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		// From constraints to react vector:
+		this->torque_react1 = innerconstraint1.Get_l_i() * factor;  
+		this->torque_react2 = innerconstraint2.Get_l_i() * factor;  
+	}
+}
+
+void  ChLinkEngine::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsLiLoadSuggestedSpeedSolution();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		innerconstraint1.Set_l_i(this->cache_li_speed1);
+		innerconstraint2.Set_l_i(this->cache_li_speed2);
+	}
+}
+
+void  ChLinkEngine::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsLiLoadSuggestedPositionSolution();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		innerconstraint1.Set_l_i(this->cache_li_pos1);
+		innerconstraint2.Set_l_i(this->cache_li_pos2);
+	}
+}
+
+void  ChLinkEngine::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsLiFetchSuggestedSpeedSolution();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->cache_li_speed1 = (float)innerconstraint1.Get_l_i();
+		this->cache_li_speed2 = (float)innerconstraint2.Get_l_i();
+	}
+}
+
+void  ChLinkEngine::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	// First, inherit to parent class
+    ChLinkLock::ConstraintsLiFetchSuggestedPositionSolution();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->cache_li_pos1 =  (float)innerconstraint1.Get_l_i();
+		this->cache_li_pos2 =  (float)innerconstraint2.Get_l_i();
+	}
+}
+
+void ChLinkEngine::InjectVariables(ChLcpSystemDescriptor& mdescriptor)
+{	
+	// First, inherit to parent class
+    ChLinkLock::InjectVariables(mdescriptor);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innershaft1.InjectVariables(mdescriptor);
+		this->innershaft2.InjectVariables(mdescriptor);
+	}
+}
+
+void ChLinkEngine::VariablesFbReset()
+{
+	// First, inherit to parent class
+    ChLinkLock::VariablesFbReset();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innershaft1.VariablesFbReset();
+		this->innershaft2.VariablesFbReset();
+	}
+}
+
+void ChLinkEngine::VariablesFbLoadForces(double factor)
+{
+	// First, inherit to parent class
+    ChLinkLock::VariablesFbLoadForces(factor);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innershaft1.VariablesFbLoadForces(factor);
+		this->innershaft2.VariablesFbLoadForces(factor);
+	}
+}
+
+void ChLinkEngine::VariablesFbIncrementMq()
+{
+					// inherit parent class
+	ChLinkLock::VariablesFbIncrementMq();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innershaft1.VariablesFbIncrementMq();
+		this->innershaft2.VariablesFbIncrementMq();
+	}
+}
+
+void ChLinkEngine::VariablesQbLoadSpeed()
+{
+	// First, inherit to parent class
+    ChLinkLock::VariablesQbLoadSpeed();
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innershaft1.VariablesQbLoadSpeed();
+		this->innershaft2.VariablesQbLoadSpeed();
+	}
+}
+
+void ChLinkEngine::VariablesQbSetSpeed(double step)
+{
+	// First, inherit to parent class
+    ChLinkLock::VariablesQbSetSpeed(step);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innershaft1.VariablesQbSetSpeed(step);
+		this->innershaft2.VariablesQbSetSpeed(step);
+	}
+}
+
+void ChLinkEngine::VariablesQbIncrementPosition(double step)
+{
+	// First, inherit to parent class
+    ChLinkLock::VariablesQbIncrementPosition(step);
+
+	if (this->eng_mode == ENG_MODE_TO_POWERTRAIN_SHAFT )
+	{
+		this->innershaft1.VariablesQbIncrementPosition(step);
+		this->innershaft2.VariablesQbIncrementPosition(step);
+	}
+}
+
+
+
+
+
+
+
+void ChLinkEngine::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream.AbstractWrite(rot_funct);
+	mstream.AbstractWrite(spe_funct);
+    mstream.AbstractWrite(tor_funct);
+    mstream.AbstractWrite(torque_w);
+    mstream << learn;
+    mstream << impose_reducer;
+    mstream << mot_tau;
+    mstream << mot_eta;
+    mstream << mot_inertia;
+    mstream << eng_mode;
+    mstream << shaft_mode;
+}
+
+void ChLinkEngine::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	ChFunction* ffoo;
+	mstream.AbstractReadCreate(&ffoo);		Set_rot_funct(ffoo);
+	mstream.AbstractReadCreate(&ffoo);		Set_spe_funct(ffoo);
+    mstream.AbstractReadCreate(&ffoo);		Set_tor_funct(ffoo);
+    mstream.AbstractReadCreate(&ffoo);		Set_torque_w_funct(ffoo);
+    mstream >> learn;
+    mstream >> impose_reducer;
+    mstream >> mot_tau;
+    mstream >> mot_eta;
+    mstream >> mot_inertia;
+    mstream >> eng_mode;
+    mstream >> shaft_mode;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkEngine.h b/SRC/ChronoEngine/physics/ChLinkEngine.h
new file mode 100644
index 0000000..a0c0939
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkEngine.h
@@ -0,0 +1,232 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKENGINE_H
+#define CHLINKENGINE_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkEngine.h
+//
+//
+//   Classes for rotating actuators (motors)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkLock.h"
+#include "physics/ChShaft.h"
+#include "lcp/ChLcpConstraintTwoGeneric.h"
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_ENGINE		31
+
+
+///
+/// Class for links representing engines between two rigid bodies.
+/// Note that the engine can be in 'impose relative rotation' mode,
+/// as well as in 'impose speed' etc. It can also be used to represent
+/// an engine with a torque/speed custom curve. etc.
+///
+
+class ChApi ChLinkEngine : public ChLinkLock {
+
+	CH_RTTI(ChLinkEngine,ChLinkLock);
+
+protected:
+	ChFunction* rot_funct;	// rotation(t) function
+	ChFunction* spe_funct;	// speed(t) function
+	ChFunction* tor_funct;	// torque(t) function
+	ChFunction* torque_w;	// torque(w) function
+
+	int	learn;				// if TRUE, the actuator does not apply constraint, just
+							// records the motion into its rot_function.
+
+	int impose_reducer;		// if true, speed torque or rotation are imposed to the fast (motor) shaft, before reducer!
+
+	double mot_rot;			// current rotation (read only)
+	double mot_rot_dt;		// current ang speed (read only)
+	double mot_rot_dtdt;	// current ang acc  (read only)
+	double mot_torque;		// current motor torque (read only)
+	double mot_rerot;		// current rotation (read only)  before reducer
+	double mot_rerot_dt;	// current ang speed (read only) before reducer
+	double mot_rerot_dtdt;	// current ang acc  (read only)  before reducer
+	double mot_retorque;	// current motor torque (read only) before reducer
+
+	double mot_tau;			// motor: transmission ratio
+	double mot_eta;			// motor: transmission efficiency
+	double mot_inertia;		// motor: inertia (added to system)
+
+	int eng_mode;			// mode of controlling the motor (by rotation, speed etc.)
+
+	int shaft_mode;			// mode of imposing constraints on extra (non-z) degrees of freedom
+
+	ChFunction* rot_funct_x;	// rotation(t) function for keyframe polar motor
+	ChFunction* rot_funct_y;	// rotation(t) function for keyframe polar motor
+	double last_r3time;			// internal:for backward differentiation to compute speed in keyframe mode
+	double last_r3mot_rot;		// internal:for backward differentiation to compute speed in keyframe mode
+	double last_r3mot_rot_dt;	// internal:for backward differentiation to compute speed in keyframe mode
+	Quaternion last_r3relm_rot; // internal:for backward differentiation to compute speed in keyframe mode
+	Quaternion last_r3relm_rot_dt;	// internal
+	Quaternion keyed_polar_rotation;// internal
+
+	ChShaft	innershaft1;		// used in ENG_MODE_TO_POWERTRAIN_SHAFT
+	ChShaft	innershaft2;		// ''      ''
+	ChLcpConstraintTwoGeneric innerconstraint1; // ''     ''
+	ChLcpConstraintTwoGeneric innerconstraint2; // ''     ''
+	double cache_li_speed1;
+	double cache_li_pos1;
+	double torque_react1;
+	double cache_li_speed2;
+	double cache_li_pos2;
+	double torque_react2;
+
+public:
+						// builders and destroyers
+	ChLinkEngine ();
+	virtual ~ChLinkEngine ();
+	virtual void Copy(ChLinkEngine* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+							// UPDATING FUNCTIONS - "lin.act. link" custom implementations
+
+							// Updates motion laws, etc. for the impose rotation / impose speed modes
+	virtual void UpdateTime (double mytime);
+							// Updates torque for the impose torque mode
+	virtual void UpdateForces (double mytime);
+							// Updates the r3d time, so perform differentiation for computing speed in case of keyframed motion
+
+	virtual void UpdatedExternalTime (double prevtime, double time);
+
+	virtual void SetMarker1 (ChMarker* mark1);
+	virtual void SetMarker2 (ChMarker* mark2);
+
+			// data get/set
+	ChFunction* Get_rot_funct() {return rot_funct;};
+	void Set_rot_funct(ChFunction* m_funct);
+	ChFunction* Get_spe_funct() {return spe_funct;};
+	void Set_spe_funct(ChFunction* m_funct);
+	ChFunction* Get_tor_funct() {return tor_funct;};
+	void Set_tor_funct(ChFunction* m_funct);
+	ChFunction* Get_torque_w_funct() {return torque_w;};
+	void Set_torque_w_funct(ChFunction* m_funct);
+
+	ChFunction* Get_rot_funct_x() {return rot_funct_x;};
+	void Set_rot_funct_x(ChFunction* m_funct);
+	ChFunction* Get_rot_funct_y() {return rot_funct_y;};
+	void Set_rot_funct_y(ChFunction* m_funct);
+	Quaternion GetKeyedPolarRotation(){return keyed_polar_rotation;};
+	void SetKeyedPolarRotation(Quaternion mq);
+
+	int   Get_learn() {return learn;};
+	void  Set_learn(int mset);
+	int   Get_impose_reducer() {return impose_reducer;};
+	void  Set_impose_reducer(int mset) {impose_reducer = mset;};
+	int   Get_eng_mode() {return eng_mode;};
+	void  Set_eng_mode(int mset);
+        enum eCh_eng_mode {
+		ENG_MODE_ROTATION = 0,
+		ENG_MODE_SPEED,
+		ENG_MODE_TORQUE,
+		ENG_MODE_KEY_ROTATION,
+		ENG_MODE_KEY_POLAR,
+		ENG_MODE_TO_POWERTRAIN_SHAFT
+		};
+	int   Get_shaft_mode() {return shaft_mode;};
+	void  Set_shaft_mode(int mset);
+        enum eCh_shaft_mode	{
+		ENG_SHAFT_LOCK = 0,		// shafts of motor and user (markers 1 and 2) are stiffly joined 
+		ENG_SHAFT_PRISM,		// shafts of motor and user (markers 1 and 2) can shift along shaft (Z axis) 
+		ENG_SHAFT_OLDHAM,		// shafts of motor and user (markers 1 and 2) may be parallel shifting on X and Y
+		ENG_SHAFT_UNIVERSAL,	// not yet used
+		ENG_SHAFT_CARDANO		// not yet used
+		};
+	double Get_mot_rot() {return mot_rot;}
+	double Get_mot_rot_dt() {return mot_rot_dt;}
+	double Get_mot_rot_dtdt() {return mot_rot_dtdt;}
+	double Get_mot_torque() {return mot_torque;}
+	double Get_mot_rerot() {return mot_rerot;}
+	double Get_mot_rerot_dt() {return mot_rerot_dt;}
+	double Get_mot_rerot_dtdt() {return mot_rerot_dtdt;}
+	double Get_mot_retorque() {return mot_retorque;}
+	void Set_mot_tau(double mtau) {mot_tau = mtau;}
+	double Get_mot_tau() {return mot_tau;}
+	void Set_mot_eta(double meta) {mot_eta = meta;}
+	double Get_mot_eta() {return mot_eta;}
+	void Set_mot_inertia(double min) {mot_inertia = min;}
+	double Get_mot_inertia() {return mot_inertia;}
+
+			// Access the inner 1D shaft connected to the rotation of body1 about dir of motor shaft, 
+			// if in CH_ENG_MODE_TO_POWERTRAIN_SHAFT. The shaft can be
+			// connected to other shafts with ChShaftsClutch or similar items.
+	ChShaft* GetInnerShaft1() {return &this->innershaft1;}
+			// Access the inner 1D shaft connected to the rotation of body2 about dir of motor shaft, 
+			// if in CH_ENG_MODE_TO_POWERTRAIN_SHAFT. The shaft can be
+			// connected to other shafts with ChShaftsClutch or similar items.
+	ChShaft* GetInnerShaft2() {return &this->innershaft2;}
+			// Get the torque between body 1 and inner shaft 1.
+			// Note: use only if in CH_ENG_MODE_TO_POWERTRAIN_SHAFT.
+	double GetInnerTorque1() {return this->torque_react1;}
+			// Get the torque between body 2 and inner shaft 2.
+			// Note: use only if in CH_ENG_MODE_TO_POWERTRAIN_SHAFT.
+	double GetInnerTorque2() {return this->torque_react2;}
+
+			// Overload LCP system functions of ChPhysicsItem
+			// (beyond the base link implementations, it also have to 
+			// add the constraint coming from the inner shaft etc.)
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+	virtual void InjectVariables(ChLcpSystemDescriptor& mdescriptor);
+	virtual void VariablesFbReset();
+	virtual void VariablesFbLoadForces(double factor=1.);
+	virtual void VariablesQbLoadSpeed();
+	virtual void VariablesFbIncrementMq();
+	virtual void VariablesQbSetSpeed(double step=0.);
+	virtual void VariablesQbIncrementPosition(double step);
+
+
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkFastContact.cpp b/SRC/ChronoEngine/physics/ChLinkFastContact.cpp
new file mode 100644
index 0000000..3bf2e94
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkFastContact.cpp
@@ -0,0 +1,315 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkFastContact.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChLinkFastContact.h"
+#include "physics/ChSystem.h"
+//#include "physics/ChCollide.h"
+#include "lcp/ChLcpConstraintTwoContactN.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR FAST CONTACT
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkFastContact> a_registration_ChLinkFastContact;
+ 
+
+ChLinkFastContact::ChLinkFastContact ()
+{ 
+	Nx.SetTangentialConstraintU(&Tu);
+	Nx.SetTangentialConstraintV(&Tv);
+}
+
+ChLinkFastContact::ChLinkFastContact (ChCollisionPair* mpair,
+									  ChBody* mbody1, 
+									  ChBody* mbody2)
+{ 
+	Nx.SetTangentialConstraintU(&Tu);
+	Nx.SetTangentialConstraintV(&Tv);
+
+	Reset(mpair,mbody1,mbody2);
+}
+
+ChLinkFastContact::~ChLinkFastContact ()
+{
+
+}
+
+void ChLinkFastContact::Reset(ChCollisionPair* mpair, 
+							  ChBody* mbody1, 
+							  ChBody* mbody2)
+{
+	assert (mpair);
+	assert (mbody1);
+	assert (mbody2);
+
+	this->Body1 = mbody1;
+	this->Body2 = mbody2;
+
+	Nx.SetVariables(&this->Body1->Variables(),&this->Body2->Variables());
+	Tu.SetVariables(&this->Body1->Variables(),&this->Body2->Variables());
+	Tv.SetVariables(&this->Body1->Variables(),&this->Body2->Variables());
+
+	this->collision_pair = *mpair;
+
+	ChVector<float> Vx, Vy, Vz;
+	ChVector<float> singul(VECT_Y);
+	XdirToDxDyDz(&this->collision_pair.normal, &singul, &Vx,  &Vy, &Vz);
+	contact_plane.Set_A_axis(Vx,Vy,Vz);
+}
+
+
+void ChLinkFastContact::Copy(ChLinkFastContact* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkContact::Copy(source);
+	
+	this->Reset(&source->collision_pair, source->GetBody1(), source->GetBody2() );
+}
+
+ChLink* ChLinkFastContact::new_Duplicate ()
+{
+    ChLinkFastContact* m_l;
+    m_l = new ChLinkFastContact(&this->collision_pair, this->Body1, this->Body2);  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+ChCoordsys<> ChLinkFastContact::GetLinkRelativeCoords()
+{
+	Vector Pl2 = Body2->Point_World2Body(&this->collision_pair.p2);
+	ChMatrix33<> m12; 
+	m12.MatrTMultiply(*Body2->GetA(), contact_plane);
+	Quaternion Ql2 = m12.Get_A_quaternion();
+	return ChCoordsys<>(Pl2, Ql2); 
+}
+
+
+void ChLinkFastContact::Update (double mytime)
+{
+    // Inherit time changes of parent class (ChLink), basically doing nothing :)
+    ChLink::UpdateTime(mytime);
+
+		// contact point in body coordinates
+	Vector Pl1 = Body1->Point_World2Body(&this->collision_pair.p1);
+	Vector Pl2 = Body2->Point_World2Body(&this->collision_pair.p2);
+
+		// compute friction
+	//double mfriction_coeff = (Body1->GetSfriction() + Body2->GetSfriction())*0.5;
+
+	Nx.SetFrictionCoefficient(this->sta_fri);
+	
+		// compute jacobians
+	ChMatrix33<> Jx1, Jx2, Jr1, Jr2;
+	ChMatrix33<> Ps1, Ps2, Jtemp;
+	Ps1.Set_X_matrix(Pl1);
+	Ps2.Set_X_matrix(Pl2);
+
+	Jx1.CopyFromMatrixT(this->contact_plane);
+	Jx2.CopyFromMatrixT(this->contact_plane);
+	Jx1.MatrNeg();
+
+	Jtemp.MatrMultiply(*Body1->GetA(), Ps1);
+	Jr1.MatrTMultiply(this->contact_plane, Jtemp);
+
+	Jtemp.MatrMultiply(*Body2->GetA(), Ps2);
+	Jr2.MatrTMultiply(this->contact_plane, Jtemp);
+	Jr2.MatrNeg();
+
+	Nx.Get_Cq_a()->PasteClippedMatrix(&Jx1, 0,0, 1,3, 0,0);
+	Tu.Get_Cq_a()->PasteClippedMatrix(&Jx1, 1,0, 1,3, 0,0);
+	Tv.Get_Cq_a()->PasteClippedMatrix(&Jx1, 2,0, 1,3, 0,0);
+	Nx.Get_Cq_a()->PasteClippedMatrix(&Jr1, 0,0, 1,3, 0,3);
+	Tu.Get_Cq_a()->PasteClippedMatrix(&Jr1, 1,0, 1,3, 0,3);
+	Tv.Get_Cq_a()->PasteClippedMatrix(&Jr1, 2,0, 1,3, 0,3);
+
+	Nx.Get_Cq_b()->PasteClippedMatrix(&Jx2, 0,0, 1,3, 0,0);
+	Tu.Get_Cq_b()->PasteClippedMatrix(&Jx2, 1,0, 1,3, 0,0);
+	Tv.Get_Cq_b()->PasteClippedMatrix(&Jx2, 2,0, 1,3, 0,0);
+	Nx.Get_Cq_b()->PasteClippedMatrix(&Jr2, 0,0, 1,3, 0,3);
+	Tu.Get_Cq_b()->PasteClippedMatrix(&Jr2, 1,0, 1,3, 0,3);
+	Tv.Get_Cq_b()->PasteClippedMatrix(&Jr2, 2,0, 1,3, 0,3);
+
+	//***TO DO***  C_dt? C_dtdt? (may be never used..)
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChLinkFastContact::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	if (!this->IsActive())
+		return;
+
+	mdescriptor.InsertConstraint(&Nx);
+	mdescriptor.InsertConstraint(&Tu);
+	mdescriptor.InsertConstraint(&Tv); 
+}
+
+void ChLinkFastContact::ConstraintsBiReset()
+{
+	Nx.Set_b_i(0.);
+	Tu.Set_b_i(0.);
+	Tv.Set_b_i(0.);
+}
+ 
+void ChLinkFastContact::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	if (!this->IsActive())
+		return;
+
+	//Tu.Set_b_i(Tu.Get_b_i +0.);  //increment nothing
+	//Tv.Set_b_i(Tv.Get_b_i +0.);
+
+	if (do_clamp)
+		Nx.Set_b_i( Nx.Get_b_i() + ChMax (factor * this->collision_pair.norm_dist, -recovery_clamp)  );
+	else
+		Nx.Set_b_i( Nx.Get_b_i() + factor * this->collision_pair.norm_dist  );
+}
+
+void ChLinkFastContact::ConstraintsBiLoad_Ct(double factor)
+{
+	if (!this->IsActive())
+		return;
+
+	// compute normal rebounce speed (use simple Newton model)
+	double Ct = 0;
+	/* ***DEACTIVATED***
+	Vector Pl1 = Body1->Point_World2Body(&this->collision_pair.p1);
+	Vector Pl2 = Body2->Point_World2Body(&this->collision_pair.p2);
+	Vector V1_w = Body1->PointSpeedLocalToParent(Pl1);
+	Vector V2_w = Body2->PointSpeedLocalToParent(Pl2);
+	Vector Vrel_w = V2_w-V1_w;
+	Vector Vrel_cplane = this->contact_plane.MatrT_x_Vect(Vrel_w);
+ 
+	double mrest_coeff = this->restitution; // (Body1->GetImpactC() + Body2->GetImpactC())*0.5;
+	double neg_rebounce_speed = Vrel_cplane.x * mrest_coeff;
+	if (neg_rebounce_speed < - ((ChSystem*)this->system)->GetMinBounceSpeed() )
+		Ct= neg_rebounce_speed;
+	else
+		Ct= 0.0;
+
+	//Tu.Set_b_i(Tu.Get_b_i +0.);  //increment nothing
+	//Tv.Set_b_i(Tv.Get_b_i +0.);
+	Nx.Set_b_i( Nx.Get_b_i() + factor * Ct );
+	*/
+}
+
+/*
+
+
+void ChLinkFastContact::ConstraintsFbLoadForces(double factor)
+{
+	// no forces
+}
+*/
+
+void ChLinkFastContact::ConstraintsLoadJacobians()
+{
+	// already loaded when doing Update (which used the matrices of the scalar constraint objects)
+
+	  
+}
+ 
+
+void ChLinkFastContact::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	react_force.x = Nx.Get_l_i() * factor;  
+	react_force.y = Tu.Get_l_i() * factor;
+	react_force.z = Tv.Get_l_i() * factor;
+
+	react_torque = VNULL;
+}
+
+
+// 
+// Following functions are for exploiting the contact persistence
+//
+
+void  ChLinkFastContact::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	// Fetch the last computed impulsive reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP speed solver):
+	float mn,mu,mv;
+	this->collision_pair.CacheFetchSpeedSolutionFromManifold(mn,mu,mv); 
+	Nx.Set_l_i(mn);
+	Tu.Set_l_i(mu);  
+	Tv.Set_l_i(mv);
+	//GetLog() << "++++      " << (int)this << "  fetching N=" << (double)mn <<"\n"; 
+}
+
+void  ChLinkFastContact::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	// Fetch the last computed 'positional' reactions from the persistent contact manifold (could
+	// be used for warm starting the CCP position stabilization solver):
+	float mn,mu,mv;
+	this->collision_pair.CacheFetchPositionSolutionFromManifold(mn,mu,mv); 
+	Nx.Set_l_i(mn);
+	Tu.Set_l_i(mu);  
+	Tv.Set_l_i(mv);
+}
+
+void  ChLinkFastContact::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	// Store the last computed reactions into the persistent contact manifold (might
+	// be used for warm starting CCP the speed solver):
+	this->collision_pair.CacheStoreSpeedSolutionIntoManifold((float)Nx.Get_l_i(), (float)Tu.Get_l_i(), (float)Tv.Get_l_i());
+	//GetLog() << "         " << (int)this << "  storing  N=" << Nx.Get_l_i() <<"\n";
+}
+
+void  ChLinkFastContact::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	// Store the last computed 'positional' reactions into the persistent contact manifold (might
+	// be used for warm starting the CCP position stabilization solver):
+	this->collision_pair.CacheStorePositionSolutionIntoManifold((float)Nx.Get_l_i(), (float)Tu.Get_l_i(), (float)Tv.Get_l_i());
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkFastContact.h b/SRC/ChronoEngine/physics/ChLinkFastContact.h
new file mode 100644
index 0000000..e6732c0
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkFastContact.h
@@ -0,0 +1,155 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKFASTCONTACT_H
+#define CHLINKFASTCONTACT_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkFastContact.h
+//
+//   Classes for enforcing constraints (contacts)
+//   created by collision detection.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+//***OBSOLETE***  not used anymore - see ChConcactContainer.h and ChContact.h
+
+#include "physics/ChLinkContact.h"
+#include "lcp/ChLcpConstraintTwoContactN.h"
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_FASTCONTACT	35
+
+///
+/// Class representing an unilateral contact constraint. 
+/// Since such objects are automatically generated by the
+/// collision detection engine (this type of constraint is 
+/// automatically removed from the ChSystem list of links at each
+/// step, because their creation/deletion is automated by the
+/// collision engine. So, you most often do not need to create any
+/// ChLinkFastContact)
+///
+
+class ChApi ChLinkFastContact : public ChLinkContact {
+
+	CH_RTTI(ChLinkFastContact,ChLinkContact);
+
+protected:
+				//
+	  			// DATA
+				//
+
+							// the collision pair which generated the link
+	ChCollisionPair	collision_pair;
+
+							// the plane of contact (X is normal direction)
+	ChMatrix33<float> contact_plane;
+	
+							// The three scalar constraints, to be feed into the 
+							// system solver. They contain jacobians data and special functions.
+	ChLcpConstraintTwoContactN  Nx;
+	ChLcpConstraintTwoFrictionT Tu;
+	ChLcpConstraintTwoFrictionT Tv; 
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkFastContact ();
+
+	ChLinkFastContact (ChCollisionPair* mpair, 
+							ChBody* mbody1, 
+							ChBody* mbody2);
+
+	virtual ~ChLinkFastContact ();
+	virtual void Copy(ChLinkFastContact* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_FASTCONTACT;}
+
+					/// Initialize again this constraint.
+	virtual void Reset(ChCollisionPair* mpair, ChBody* mbody1, ChBody* mbody2);
+
+
+					/// Get the link coordinate system, expressed relative to Body2 (the 'master'
+					/// body). This represents the 'main' reference of the link: reaction forces 
+					/// are expressed in this coordinate system.
+					/// (It is the coordinate system of the contact plane relative to Body2)
+	virtual ChCoordsys<> GetLinkRelativeCoords();
+
+					/// Returns the pointer to a contained 3x3 matrix representing the UV and normal
+					/// directions of the contact. In detail, the X versor (the 1s column of the 
+					/// matrix) represents the direction of the contact normal.
+	ChMatrix33<float>* GetContactPlane() {return &contact_plane;};
+
+					/// Returns the ChCollisionPair info of this contact.
+	ChCollisionPair* GetCollisionPair() {return &collision_pair;};
+
+	virtual ChVector<> GetContactP1() {return collision_pair.p1; };
+	virtual ChVector<> GetContactP2() {return collision_pair.p2; };
+	virtual ChVector<float> GetContactNormal()  {return collision_pair.normal; };
+	virtual double	   GetContactDistance()  {return collision_pair.norm_dist; };
+
+				//
+				// UPDATING FUNCTIONS
+				//
+
+					/// Override _all_ time, jacobian etc. updating.
+					/// In detail, it computes jacobians, violations, etc. and stores 
+					/// results in inner structures.
+	virtual void Update (double mtime);
+
+
+				//
+				// LCP INTERFACE
+				//
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	//virtual void ConstraintsFbLoadForces(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkGear.cpp b/SRC/ChronoEngine/physics/ChLinkGear.cpp
new file mode 100644
index 0000000..3b16c17
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkGear.cpp
@@ -0,0 +1,406 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkGear.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+ 
+#include "physics/ChLinkGear.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+ 
+namespace chrono
+{
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR GEAR
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkGear> a_registration_ChLinkGear;
+
+
+ChLinkGear::ChLinkGear ()
+{
+    type = LNK_GEAR;    // initializes type
+
+    tau = 1;
+    alpha = 0;
+    beta = 0;
+    phase = 0;
+    checkphase = FALSE;
+    epicyclic = FALSE;
+    a1 = 0;
+    a2 = 0;
+    r1 = 0;
+    r2 = 0;
+
+	local_shaft1.SetIdentity();
+	local_shaft2.SetIdentity();
+
+    contact_pt = VNULL;
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to X  only. It was a LinkMaskLF because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(true, false, false,
+                       false, false, false, false,
+                       false, false);
+    ChangedLinkMask();
+}
+
+ChLinkGear::~ChLinkGear ()
+{ }
+
+void ChLinkGear::Copy(ChLinkGear* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    tau = source->tau;
+    alpha = source->alpha;
+    beta = source->beta;
+    phase = source->phase;
+    a1 = source->a1;
+    a2 = source->a2;
+    epicyclic = source->epicyclic;
+    checkphase = source->checkphase;
+    r1 = source->r1;
+    r2 = source->r2;
+	contact_pt = source->contact_pt;
+	local_shaft1 = source->local_shaft1;
+	local_shaft2 = source->local_shaft2;
+    
+}
+
+ChLink* ChLinkGear::new_Duplicate ()
+{
+    ChLinkGear* m_l;
+    m_l = new ChLinkGear;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+Vector  ChLinkGear::Get_shaft_dir1()
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body1)->TrasformLocalToParent(local_shaft1, absframe);
+		return absframe.GetA()->Get_A_Zaxis();
+	} else return VECT_Z;
+}
+
+Vector  ChLinkGear::Get_shaft_dir2() 
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body2)->TrasformLocalToParent(local_shaft2, absframe);
+		return absframe.GetA()->Get_A_Zaxis();
+	} else return VECT_Z;
+}
+
+Vector  ChLinkGear::Get_shaft_pos1() 
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body1)->TrasformLocalToParent(local_shaft1, absframe);
+		return absframe.GetPos();
+	} else return VNULL;
+}
+
+Vector  ChLinkGear::Get_shaft_pos2() 
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body2)->TrasformLocalToParent(local_shaft2, absframe);
+		return absframe.GetPos();
+	} else return VNULL;
+}
+
+
+
+
+void ChLinkGear::UpdateTime (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateTime(mytime);
+
+    // Move markers 1 and 2 to align them as gear teeth
+
+    ChMatrix33<> ma1;
+    ChMatrix33<> ma2;
+    ChMatrix33<> mrotma;
+    ChMatrix33<> marot_beta;
+    Vector mx;
+    Vector my;
+    Vector mz;
+	Vector mr;
+    Vector mmark1;
+    Vector mmark2;
+    Vector lastX;
+    Vector vrota;
+    Coordsys newmarkpos;
+
+	ChFrame<double> abs_shaft1;
+	ChFrame<double> abs_shaft2;
+
+	((ChFrame<double>*)Body1)->TrasformLocalToParent(local_shaft1, abs_shaft1);
+	((ChFrame<double>*)Body2)->TrasformLocalToParent(local_shaft2, abs_shaft2);
+
+    Vector vbdist = Vsub(Get_shaft_pos1(),
+                          Get_shaft_pos2());
+    Vector Trad1 = Vnorm(Vcross(Get_shaft_dir1(), Vnorm(Vcross(Get_shaft_dir1(),vbdist))));
+    Vector Trad2 = Vnorm(Vcross(Vnorm(Vcross(Get_shaft_dir2(),vbdist)), Get_shaft_dir2()));
+
+	double dist = Vlenght(vbdist);
+    
+
+        // compute actual rotation of the two wheels (relative to truss).
+    Vector md1 = abs_shaft1.GetA()->MatrT_x_Vect(-vbdist);
+    md1.z = 0;  md1 = Vnorm (md1);
+    Vector md2 = abs_shaft2.GetA()->MatrT_x_Vect(-vbdist);
+    md2.z = 0;  md2 = Vnorm (md2);
+
+	double periodic_a1 = ChAtan2(md1.x, md1.y);
+	double periodic_a2 = ChAtan2(md2.x, md2.y);
+	double old_a1 = a1; 
+	double old_a2 = a2;
+	double turns_a1 = floor (old_a1 / CH_C_2PI);
+	double turns_a2 = floor (old_a2 / CH_C_2PI);
+	double a1U = turns_a1 * CH_C_2PI + periodic_a1 + CH_C_2PI;
+	double a1M = turns_a1 * CH_C_2PI + periodic_a1;
+	double a1L = turns_a1 * CH_C_2PI + periodic_a1 - CH_C_2PI;
+	a1 = a1M;
+	if (fabs(a1U - old_a1) < fabs(a1M - old_a1))
+		a1 = a1U;
+	if (fabs(a1L - a1) < fabs(a1M - a1))
+		a1 = a1L;
+	double a2U = turns_a2 * CH_C_2PI + periodic_a2 + CH_C_2PI;
+	double a2M = turns_a2 * CH_C_2PI + periodic_a2;
+	double a2L = turns_a2 * CH_C_2PI + periodic_a2 - CH_C_2PI;
+	a2 = a2M;
+	if (fabs(a2U - old_a2) < fabs(a2M - old_a2))
+		a2 = a2U;
+	if (fabs(a2L - a2) < fabs(a2M - a2))
+		a2 = a2L;
+
+
+        // compute new markers coordsystem alignment
+    my = Vnorm (vbdist);
+    mz = Get_shaft_dir1();
+    mx = Vnorm(Vcross (my, mz));
+	mr = Vnorm(Vcross (mz, mx));
+    mz = Vnorm(Vcross (mx, my));
+	ChVector<> mz2, mx2, mr2, my2;
+	my2 = my;
+	mz2 = Get_shaft_dir2();
+	mx2 = Vnorm(Vcross (my2, mz2));
+	mr2 = Vnorm(Vcross (mz2, mx2));
+
+    ma1.Set_A_axis(mx,my,mz);
+
+        // rotate csys because of beta
+    vrota.x = 0.0;  vrota.y = this->beta;  vrota.z = 0.0;
+    mrotma.Set_A_Rxyz(vrota);
+    marot_beta.MatrMultiply(ma1, mrotma);
+        // rotate csys because of alpha
+    vrota.x = 0.0;  vrota.y = 0.0;  vrota.z = this->alpha;
+    if (react_force.x < 0)  vrota.z =  this->alpha;
+    else                    vrota.z = -this->alpha;
+    mrotma.Set_A_Rxyz(vrota);
+    ma1.MatrMultiply(marot_beta, mrotma);
+
+    ma2.CopyFromMatrix(ma1);
+
+		// is a bevel gear?
+	double be = acos(Vdot(Get_shaft_dir1(), Get_shaft_dir2()));
+	bool is_bevel= true;
+	if (fabs( Vdot(Get_shaft_dir1(), Get_shaft_dir2()) )>0.96)
+		is_bevel = false;
+
+        // compute wheel radii
+        // so that:
+        //            w2 = - tau * w1
+	if (!is_bevel)
+	{
+		double pardist =  Vdot(mr, vbdist);
+		double inv_tau = 1.0/tau;
+		if  (!this->epicyclic)
+		{
+			r2 = pardist - pardist / (inv_tau + 1.0);
+		}
+		else
+		{
+			r2 = pardist - (tau * pardist)/(tau-1.0);
+		}
+		r1 = r2*tau;	}
+	else
+	{
+		double gamma2;
+		if  (!this->epicyclic)
+		{
+			gamma2 = be/(tau + 1.0);
+		}
+		else
+		{
+			gamma2 = be/(-tau + 1.0);
+		}
+	   double al = CH_C_PI - acos (Vdot(Get_shaft_dir2(), my));
+		double te = CH_C_PI - al - be;
+		double fd = sin(te) * (dist/sin(be));
+		r2 = fd * tan(gamma2);
+		r1 = r2*tau;
+	}
+
+        // compute markers positions, supposing they
+        // stay on the ideal wheel contact point
+	mmark1 = Vadd(Get_shaft_pos2(), Vmul(mr2, r2));
+    mmark2 = mmark1;
+    contact_pt = mmark1;
+
+        // correct marker 1 position if phasing is not correct
+    if (this->checkphase)
+    {
+		double realtau = tau; 
+		if (this->epicyclic) 
+			realtau = -tau;
+        double m_delta;
+        m_delta = - (a2/realtau) - a1 - phase;
+
+        if (m_delta> CH_C_PI) m_delta -= (CH_C_2PI);		 // range -180..+180 is better than 0...360
+        if (m_delta> (CH_C_PI/4.0)) m_delta = (CH_C_PI/4.0); // phase correction only in +/- 45�
+        if (m_delta<-(CH_C_PI/4.0)) m_delta =-(CH_C_PI/4.0);
+
+        vrota.x = vrota.y = 0.0;  vrota.z = - m_delta;
+        mrotma.Set_A_Rxyz(vrota);   // rotate about Z of shaft to correct
+        mmark1 = abs_shaft1.GetA()->MatrT_x_Vect(Vsub(mmark1,  Get_shaft_pos1() ));
+        mmark1 = mrotma.Matr_x_Vect(mmark1);
+        mmark1 = Vadd (abs_shaft1.GetA()->Matr_x_Vect(mmark1), Get_shaft_pos1() );
+    }
+		// Move Shaft 1 along its direction if not aligned to wheel
+	double offset =  Vdot (this->Get_shaft_dir1(), (contact_pt - this->Get_shaft_pos1()) );
+	ChVector<> moff = this->Get_shaft_dir1() * offset;
+	if (fabs (offset) > 0.0001)
+		this->local_shaft1.SetPos( local_shaft1.GetPos() + Body1->Dir_World2Body(&moff) );
+		
+
+            // ! Require that the BDF routine of marker won't handle speed and acc.calculus of the moved marker 2!
+    marker2->SetMotionType(ChMarker::M_MOTION_EXTERNAL);
+    marker1->SetMotionType(ChMarker::M_MOTION_EXTERNAL);
+
+        // move marker1 in proper positions
+    newmarkpos.pos = mmark1;
+    newmarkpos.rot = ma1.Get_A_quaternion();
+    marker1->Impose_Abs_Coord(newmarkpos);        //move marker1 into teeth position
+        // move marker2 in proper positions
+    newmarkpos.pos = mmark2;
+    newmarkpos.rot = ma2.Get_A_quaternion();
+    marker2->Impose_Abs_Coord(newmarkpos);        //move marker2 into teeth position
+
+
+        // imposed relative positions/speeds
+    deltaC.pos = VNULL;
+    deltaC_dt.pos = VNULL;
+    deltaC_dtdt.pos = VNULL;
+
+    deltaC.rot = QUNIT;             // no relative rotations imposed!
+    deltaC_dt.rot = QNULL;
+    deltaC_dtdt.rot = QNULL;
+
+}
+
+
+
+void ChLinkGear::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(2);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << tau;
+    mstream << alpha;
+    mstream << beta;
+    mstream << phase;
+    mstream << checkphase;
+    mstream << epicyclic;
+    mstream << a1;
+    mstream << a2;
+    mstream << r1;
+    mstream << r2;
+	mstream << local_shaft1;
+	mstream << local_shaft2;
+}
+
+void ChLinkGear::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> tau;
+    mstream >> alpha;
+    mstream >> beta;
+    mstream >> phase;
+    mstream >> checkphase;
+    mstream >> epicyclic;
+    mstream >> a1;
+    mstream >> a2;
+    mstream >> r1;
+    mstream >> r2;
+	if (version ==1)
+	{
+		Vector mvfoo;
+		mstream >> mvfoo;
+		mstream >> mvfoo;
+		mstream >> mvfoo;
+		mstream >> mvfoo;
+	}
+	if (version >=2)
+	{
+		mstream >> local_shaft1;
+		mstream >> local_shaft2;
+	}
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkGear.h b/SRC/ChronoEngine/physics/ChLinkGear.h
new file mode 100644
index 0000000..d8be082
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkGear.h
@@ -0,0 +1,191 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKGEAR_H
+#define CHLINKGEAR_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkGear.h
+//
+//
+//   Classes for gears.
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkLock.h"
+
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_GEAR		17
+
+
+///
+/// Gear link between two rigid bodies. This can
+/// also be used to represent spur and bevel gears, and
+/// it correctly handles the direction of transmitted force
+/// given the teeth pressure angle.
+///
+
+class ChApi ChLinkGear : public ChLinkLock {
+
+	CH_RTTI(ChLinkGear,ChLinkLock);
+
+protected:
+	double tau;			// transmission coeff.
+	double alpha;		// inclination of action line
+	double beta;		// helix angle
+	double phase;		// mounting phase angle
+	int	   checkphase;	// keep gear always on phase
+	int	   epicyclic;	// epiciclyc (gear 1 is internal to gear2)  if true.
+
+	double a1;			// auxiliary
+	double a2;
+	double r1;
+	double r2;
+
+	Vector contact_pt;
+	
+	ChFrame<double> local_shaft1; // shaft1 pos & dir (as Z axis), relative to body1
+	ChFrame<double> local_shaft2; // shaft2 pos & dir (as Z axis), relative to body2
+
+public:
+						// builders and destroyers
+	ChLinkGear ();
+	virtual ~ChLinkGear ();
+	virtual void Copy(ChLinkGear* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+	virtual int GetType	() {return LNK_GEAR;}
+
+
+							// UPDATING FUNCTIONS - "gear" custom implementations
+
+							// Updates motion laws, marker positions, etc.
+	virtual void UpdateTime (double mytime);
+
+			// data get/set
+				
+						/// Get the transmission ratio. Its value is assumed always positive,
+						/// both for inner and outer gears (so use Get_epicyclic() to distinguish) 
+	double  Get_tau() {return tau;};
+						/// Set the transmission ratio. Its value is assumed always positive,
+						/// both for inner and outer gears (so use Set_epicyclic() to distinguish)
+	void	Set_tau(double mset) {tau = fabs(mset);}
+						/// Set the transmission ratio given the number of teeths (or radius) of 1st gear
+						/// and the number of teeths (or radius) of 2nd gear
+	void	Set_tau(double mz1, double mz2) {tau = fabs(mz1/mz2);}
+
+						/// Get the pressure angle (usually 20� for typical gears)
+	double  Get_alpha() {return alpha;};
+						/// Set the pressure angle (usually 20� for typical gears)
+	void	Set_alpha(double mset) {alpha = mset;}
+
+						/// Get the angle of teeth in bevel gears (0� for spur gears)
+	double  Get_beta() {return beta;};
+						/// Set the angle of teeth in bevel gears (0� for spur gears)
+	void	Set_beta(double mset) {beta = mset;}
+		
+						/// Get the initial phase of rotation of gear A respect to gear B
+	double  Get_phase() {return phase;};
+						/// Set the initial phase of rotation of gear A respect to gear B
+	void	Set_phase(double mset) {phase = mset;}
+
+						/// If true, the bigger wheel has inner (internal) teeth
+	int		Get_epicyclic() {return epicyclic;};
+						/// If true, the bigger wheel has inner (internal) teeth
+	void	Set_epicyclic(int mset) {epicyclic = mset;}
+
+						/// If true, enforce check on exact phase between gears 
+						/// (otherwise after many simulation steps the phasing
+						/// may be affected by numerical error accumulation). 
+						/// By default, it is turned off.
+						/// Note that, to ensure the correct phasing during the many
+						/// rotations, an algorithm will use the a1 and a2 total rotation
+						/// values, which might be affected by loss of numerical precision
+						/// after few thousands of revolutions, so this is NOT suited to
+						/// real-time simulators which must run for many hours.
+	void	Set_checkphase(int mset) {checkphase = mset;}
+	int		Get_checkphase() {return checkphase;};
+
+
+						/// Get total rotation of 1st gear, respect to interaxis, in radians 
+	double  Get_a1() {return a1;};
+						/// Get total rotation of 1st gear, respect to interaxis, in radians 
+	double  Get_a2() {return a2;};
+						/// Reset the total rotations of a1 and a2. 
+	void    Reset_a1a2() {a1=a2=0;};
+
+						/// Get radius of 1st gear (depends on axis position and t.ratio)
+	double  Get_r1() {return r1;};
+						/// Get radius of 2nd gear (depends on axis position and t.ratio)
+	double  Get_r2() {return r2;};
+
+	
+						/// Get shaft position and direction, for 1st gear, in body1-relative reference. 
+						/// The shaft direction is the Z axis of that frame.
+	ChFrame<double> Get_local_shaft1() {return local_shaft1;}
+						/// Set shaft position and direction, for 1st gear, in body1-relative reference. 
+						/// The shaft direction is the Z axis of that frame.
+						/// Note that the origin of shaft position may be automatically shifted along
+						/// shaft direction in order to have both wheels on same plane (for spur gears) - 
+						/// same sphere (for bevel gears). 
+	void            Set_local_shaft1(ChFrame<double> mf) {local_shaft1 = mf;}
+
+						/// Get shaft position and direction, for 2nd gear, in body2-relative reference. 
+						/// The shaft direction is the Z axis of that frame.
+	ChFrame<double> Get_local_shaft2() {return local_shaft2;}
+						/// Set shaft position and direction, for 2nd gear, in body2-relative reference. 
+						/// The shaft direction is the Z axis of that frame.
+	void            Set_local_shaft2(ChFrame<double> mf) {local_shaft2 = mf;}
+
+
+						/// Get shaft direction, for 1st gear, in absolute reference
+	Vector  Get_shaft_dir1();
+						/// Get shaft direction, for 2nd gear, in absolute reference
+	Vector  Get_shaft_dir2();
+
+						/// Get shaft position, for 1st gear, in absolute reference
+	Vector  Get_shaft_pos1();
+						/// Get shaft position, for 2nd gear, in absolute reference
+	Vector  Get_shaft_pos2();
+
+
+
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkGeometric.h b/SRC/ChronoEngine/physics/ChLinkGeometric.h
new file mode 100644
index 0000000..a26ff04
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkGeometric.h
@@ -0,0 +1,81 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKGEOMETRIC_H
+#define CHLINKGEOMETRIC_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkGeometric.h
+//
+//   Classes for enforcing constraints (contacts)
+//   between two objects given some geometric 
+//   condition to be satisfied.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLink.h"
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_GEOMETRIC	36
+
+///
+/// Classes for constraints defined by some generic geometric 
+/// condition are inherited from this class. 
+/// Note that also in the more advanced and powerful ChLinkLock 
+/// classes thare are constraints with geometric interpretation,
+/// such as the 'point on line', 'spherical joint' etc., but
+/// the difference is that the ChLinkLock constraints are 
+/// defined between two ChMarker objects (children of two 
+/// ChBody objects) so they are less optimized for speed (since
+/// the markers could be moving respect to bodies, etc.). On the
+/// other hand, links inherited from this ChLinkGeometric are
+/// supposed to be less feature-rich but faster in execution.
+///
+
+class ChApi ChLinkGeometric : public ChLink {
+
+	CH_RTTI(ChLinkGeometric,ChLink);
+
+protected:
+				//
+	  			// DATA
+				//
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkLinActuator.cpp b/SRC/ChronoEngine/physics/ChLinkLinActuator.cpp
new file mode 100644
index 0000000..5e684c5
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkLinActuator.cpp
@@ -0,0 +1,295 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLink.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+   
+
+#include "physics/ChLinkLinActuator.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR LINEAR ACTUATOR LINKS
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkLinActuator> a_registration_ChLinkLinActuator;
+
+
+ChLinkLinActuator::ChLinkLinActuator ()
+{
+    type = LNK_LINACTUATOR;     // initializes type
+
+    dist_funct =   new ChFunction_Const (0);
+    learn = FALSE;
+    offset = 0.1;
+
+    mot_tau = 1.0;
+    mot_eta = 1.0;
+    mot_inertia = 0.0;
+    mot_torque = new ChFunction_Recorder();
+    mot_rot = new ChFunction_Recorder();
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to X  only. It was a LinkMaskLF because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(true, false, false,
+                       false, false, false, false,
+                       false, false);
+
+    ChangedLinkMask();
+
+	mot_rerot = mot_rerot_dt = mot_rerot_dtdt = 0;
+}
+
+ChLinkLinActuator::~ChLinkLinActuator ()
+{
+    delete dist_funct;
+    delete mot_torque;
+    delete mot_rot;
+}
+
+void ChLinkLinActuator::Copy(ChLinkLinActuator* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    learn = source->learn;
+    offset = source->offset;
+    if (dist_funct) delete dist_funct;
+        dist_funct =   source->dist_funct->new_Duplicate();
+
+    mot_tau = source->mot_tau;
+    mot_eta = source->mot_eta;
+    mot_inertia = source->mot_inertia;
+    if (mot_torque) delete mot_torque;
+        mot_torque =   source->mot_torque->new_Duplicate();
+    if (mot_rot) delete mot_rot;
+        mot_rot =   source->mot_rot->new_Duplicate();
+}
+
+ChLink* ChLinkLinActuator::new_Duplicate ()
+{
+    ChLinkLinActuator* m_l;
+    m_l = new ChLinkLinActuator;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+void ChLinkLinActuator::Set_learn(int mset)
+{
+	if (mset)
+		SetDisabled(true);  // ..just to show it as a green wireframe...
+	else
+		SetDisabled(false);
+
+    if (mset)
+        ((ChLinkMaskLF*)mask)->Constr_X().SetMode(CONSTRAINT_FREE);
+    else
+        ((ChLinkMaskLF*)mask)->Constr_X().SetMode(CONSTRAINT_LOCK);
+
+    ChangedLinkMask ();
+
+    learn = mset;
+    if (dist_funct->Get_Type() != FUNCT_RECORDER) // if wasn't recorder f()..
+    {
+        delete (dist_funct); dist_funct = NULL;
+        dist_funct = new ChFunction_Recorder;
+    }
+}
+
+void ChLinkLinActuator::Set_dist_funct(ChFunction* m_funct)
+{
+    if (dist_funct) delete dist_funct;
+        dist_funct = m_funct;
+}
+void ChLinkLinActuator::Set_motrot_funct(ChFunction* m_funct)
+{
+    if (mot_rot) delete mot_rot;
+        mot_rot = m_funct;
+}
+void ChLinkLinActuator::Set_mottorque_funct(ChFunction* m_funct)
+{
+    if (mot_torque) delete mot_torque;
+        mot_torque = m_funct;
+}
+
+void ChLinkLinActuator::UpdateTime (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateTime(mytime);
+
+
+    // If LEARN MODE, just record motion
+    if (learn == TRUE)
+    {
+        /*   do not change deltas, in free mode maybe that 'limit on X' changed them
+        deltaC.pos = VNULL;
+        deltaC_dt.pos = VNULL;
+        deltaC_dtdt.pos = VNULL;
+        deltaC.rot = QUNIT;
+        deltaC_dt.rot = QNULL;
+        deltaC_dtdt.rot = QNULL;
+        */
+        if (dist_funct->Get_Type() != FUNCT_RECORDER) // if wasn't recorder f()..
+        {
+            delete (dist_funct); dist_funct = NULL;
+            dist_funct = new ChFunction_Recorder;
+        }
+                // record point
+        double rec_dist =  Vlenght(Vsub(marker1->GetAbsCoord().pos,
+                                        marker2->GetAbsCoord().pos));
+        rec_dist -= offset;
+        ((ChFunction_Recorder*)dist_funct)->AddPoint(mytime, rec_dist, 1);  // (x,y,w)  x=t
+        //return;
+    }
+
+    // Move (well, rotate...) marker 2 to align it in actuator direction
+
+        // ! Require that the BDF routine of marker won't handle speed and acc.calculus of the moved marker 2!
+    marker2->SetMotionType(ChMarker::M_MOTION_EXTERNAL);
+
+    ChMatrix33<> ma;
+    ma.Set_A_quaternion(marker2->GetAbsCoord().rot);
+
+    Vector absdist = Vsub(marker1->GetAbsCoord().pos,
+                          marker2->GetAbsCoord().pos);
+
+    Vector mx = Vnorm (absdist);
+
+    Vector my = ma.Get_A_Yaxis();
+    if (Vequal(&mx, &my))
+        if  (mx.x == 1.0)   my = VECT_Y;
+        else                my = VECT_X;
+    Vector mz = Vnorm (Vcross(mx, my));
+    my = Vnorm (Vcross(mz, mx));
+
+    ma.Set_A_axis(mx,my,mz);
+
+    Coordsys newmarkpos;
+	ChVector<> oldpos = marker2->GetPos(); // backup to avoid numerical err.accumulation
+    newmarkpos.pos = marker2->GetAbsCoord().pos;
+    newmarkpos.rot = ma.Get_A_quaternion();
+    marker2->Impose_Abs_Coord(newmarkpos);        //rotate "main" marker2 into tangent position (may add err.accumulation)
+	marker2->SetPos(oldpos); // backup to avoid numerical err.accumulation
+
+    if (learn == TRUE) return; // no need to go on further...--->>>>
+
+        // imposed relative positions/speeds
+    deltaC.pos = VNULL;
+    deltaC.pos.x = dist_funct->Get_y(ChTime) + this->offset;        // distance is always on M2 'X' axis
+
+    deltaC_dt.pos = VNULL;
+    deltaC_dt.pos.x = dist_funct->Get_y_dx(ChTime); // distance speed
+
+    deltaC_dtdt.pos = VNULL;
+    deltaC_dtdt.pos.x = dist_funct->Get_y_dxdx(ChTime); // distance acceleration
+        // add also the centripetal acceleration if distance vector's rotating,
+        // as centripetal acc. of point sliding on a sphere surface.
+     Vector tang_speed = GetRelM_dt().pos;
+     tang_speed.x = 0; // only z-y coords in relative tang speed vector
+    deltaC_dtdt.pos.x -= pow(Vlenght(tang_speed), 2) / Vlenght(absdist);  // An = Adelta -(Vt^2 / r)
+
+    deltaC.rot = QUNIT;             // no relative rotations imposed!
+    deltaC_dt.rot = QNULL;
+    deltaC_dtdt.rot = QNULL;
+
+        // Compute motor variables
+    //double m_rotation;
+    //double m_torque;
+	mot_rerot = (deltaC.pos.x - this->offset) / mot_tau;
+	mot_rerot_dt = deltaC_dt.pos.x / mot_tau;
+	mot_rerot_dtdt = deltaC_dtdt.pos.x / mot_tau;
+	mot_retorque = mot_rerot_dtdt * mot_inertia + (this->react_force.x * mot_tau) / mot_eta;
+  //  m_rotation = (deltaC.pos.x - this->offset) / mot_tau;
+  //  m_torque =  (deltaC_dtdt.pos.x / mot_tau) * mot_inertia + (this->react_force.x * mot_tau) / mot_eta;
+
+    if (mot_torque->Get_Type() != FUNCT_RECORDER) { // if wasn't recorder f()..
+            delete (mot_torque); mot_torque = new ChFunction_Recorder;
+        }
+    if (mot_rot->Get_Type() != FUNCT_RECORDER) { // if wasn't recorder f()..
+            delete (mot_rot); mot_rot = new ChFunction_Recorder;
+        }
+    ((ChFunction_Recorder*)mot_torque)->AddPoint(mytime, mot_retorque, 1);  // (x,y,w)  x=t
+    ((ChFunction_Recorder*)mot_rot)->AddPoint(mytime, mot_rerot, 1);   // (x,y,w)  x=t
+}
+
+
+
+void ChLinkLinActuator::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << learn;
+    mstream << offset;
+    mstream.AbstractWrite(dist_funct);
+	mstream << mot_tau;
+    mstream << mot_eta;
+    mstream << mot_inertia;
+    mstream.AbstractWrite(mot_rot);
+    mstream.AbstractWrite(mot_torque);
+}
+
+void ChLinkLinActuator::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	ChFunction* ffoo;
+	mstream >> learn;
+    mstream >> offset;
+    mstream.AbstractReadCreate(&ffoo);		Set_dist_funct(ffoo);
+	mstream >> mot_tau;
+    mstream >> mot_eta;
+    mstream >> mot_inertia;
+    mstream.AbstractReadCreate(&ffoo);		Set_motrot_funct(ffoo);
+    mstream.AbstractReadCreate(&ffoo);		Set_mottorque_funct(ffoo);
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkLinActuator.h b/SRC/ChronoEngine/physics/ChLinkLinActuator.h
new file mode 100644
index 0000000..506ba3a
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkLinActuator.h
@@ -0,0 +1,123 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKLINACTUATOR_H
+#define CHLINKLINACTUATOR_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkLinActuator.h
+//
+//
+//   Classes for linear actuators.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkLock.h"
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_LINACTUATOR	27
+
+
+///
+/// Class for linear actuators between two markers,
+/// as the actuator were joined with two spherical
+/// bearing at the origin of the two markers.
+///
+
+class ChApi ChLinkLinActuator : public ChLinkLock {
+
+	CH_RTTI(ChLinkLinActuator,ChLinkLock);
+
+protected:
+	ChFunction* dist_funct;	// distance function
+	int	learn;				// if TRUE, the actuator does not apply constraint, just
+							// records the motion into its dist_function.
+	double offset;			// distance offset
+
+	double mot_tau;			// motor: transmission ratio
+	double mot_eta;			// motor: transmission efficiency
+	double mot_inertia;		// motor: inertia (added to system)
+	ChFunction* mot_torque;	// motor: recorder of torque
+	ChFunction* mot_rot;	// motor: recorder of motor rotation
+
+	double mot_rerot;		// current rotation (read only)  before reducer
+	double mot_rerot_dt;	// current ang speed (read only) before reducer
+	double mot_rerot_dtdt;	// current ang acc  (read only)  before reducer
+	double mot_retorque;	// current motor torque (read only) before reducer
+
+public:
+						// builders and destroyers
+	ChLinkLinActuator ();
+	virtual ~ChLinkLinActuator ();
+	virtual void Copy(ChLinkLinActuator* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+							// UPDATING FUNCTIONS - "lin.act. link" custom implementations
+
+							// Updates motion laws, marker positions, etc.
+	virtual void UpdateTime (double mytime);
+
+			// data get/set
+	ChFunction* Get_dist_funct() {return dist_funct;};
+	void Set_dist_funct(ChFunction* m_funct);
+	int   Get_learn() {return learn;};
+	void  Set_learn(int mset);
+	double  Get_lin_offset() {return offset;};
+	void  Set_lin_offset(double mset) {offset = mset;}
+
+	void Set_mot_tau(double mtau) {mot_tau = mtau;}
+	double Get_mot_tau() {return mot_tau;}
+	void Set_mot_eta(double meta) {mot_eta = meta;}
+	double Get_mot_eta() {return mot_eta;}
+	void Set_mot_inertia(double min) {mot_inertia = min;}
+	double Get_mot_inertia() {return mot_inertia;}
+	ChFunction* Get_motrot_funct() {return mot_rot;};
+	void Set_motrot_funct(ChFunction* m_funct);
+	ChFunction* Get_mottorque_funct() {return mot_torque;};
+	void Set_mottorque_funct(ChFunction* m_funct);
+
+			// easy fetching of motor-reduced moments or angle-speed-accel.
+	double Get_mot_rerot() {return mot_rerot;}
+	double Get_mot_rerot_dt() {return mot_rerot_dt;}
+	double Get_mot_rerot_dtdt() {return mot_rerot_dtdt;}
+	double Get_mot_retorque() {return mot_retorque;}
+
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkLock.cpp b/SRC/ChronoEngine/physics/ChLinkLock.cpp
new file mode 100644
index 0000000..144c98d
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkLock.cpp
@@ -0,0 +1,1644 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkLock.cpp
+//
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkLock.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkLock> a_registration_ChLinkLock;
+
+
+                // BUILDERS
+ChLinkLock::ChLinkLock ()
+{
+    type = LNK_SPHERICAL;       // initializes type
+
+    relC = CSYSNORM;        // custom variables
+    relC_dt = CSYSNULL;
+    relC_dtdt = CSYSNULL;
+    deltaC = CSYSNORM;
+    deltaC_dt = CSYSNULL;
+    deltaC_dtdt = CSYSNULL;
+    Ct_temp = CSYSNULL;
+                            // matrices used by lock formulation
+    Cq1_temp    = new ChMatrixDynamic<>(7, BODY_QDOF);
+    Cq2_temp    = new ChMatrixDynamic<>(7, BODY_QDOF);
+    Qc_temp     = new ChMatrixDynamic<>(7, 1);
+
+    motion_X =   new ChFunction_Const (0);  // default: no motion
+    motion_Y =   new ChFunction_Const (0);
+    motion_Z =   new ChFunction_Const (0);
+    motion_ang  = new ChFunction_Const (0);
+    motion_ang2 = new ChFunction_Const (0);
+    motion_ang3 = new ChFunction_Const (0);
+    motion_axis = VECT_Z;
+    angleset = ANGLESET_ANGLE_AXIS;
+
+    limit_X = new ChLinkLimit;    // default: inactive limits
+    limit_Y = new ChLinkLimit;
+    limit_Z = new ChLinkLimit;
+    limit_Rx = new ChLinkLimit;
+    limit_Ry = new ChLinkLimit;
+    limit_Rz = new ChLinkLimit;
+    limit_D = new ChLinkLimit;
+    limit_Rp = new ChLinkLimit;   // the polar limit;
+    limit_Rp->Set_polar(TRUE);
+
+    if (mask) delete mask;          // delete the class mask created by base constructor, and,
+    mask = new ChLinkMaskLF();        // create the LF-mask (the extended version,for lock-formulation)
+                                    // instead.
+
+    BuildLinkType (LNK_SPHERICAL);  // default type: spherical link
+                                    // Sets the mask
+                                    // Sets up all the matrices and  n. of DOC and DOF,
+}
+
+
+            // DESTROYER
+ChLinkLock::~ChLinkLock ()
+{
+    if (Cq1_temp)   delete Cq1_temp;
+    if (Cq2_temp)   delete Cq2_temp;
+    if (Qc_temp)    delete Qc_temp;
+
+    if (motion_X) delete motion_X;
+    if (motion_Y) delete motion_Y;
+    if (motion_Z) delete motion_Z;
+    if (motion_ang)  delete motion_ang;
+    if (motion_ang2) delete motion_ang2;
+    if (motion_ang3) delete motion_ang3;
+
+    if (limit_X) delete limit_X;
+    if (limit_Y) delete limit_Y;
+    if (limit_Z) delete limit_Z;
+    if (limit_Rx) delete limit_Rx;
+    if (limit_Ry) delete limit_Ry;
+    if (limit_Rz) delete limit_Rz;
+    if (limit_Rp) delete limit_Rp;
+    if (limit_D) delete limit_D;
+
+    // jacobians etc. are deleted by base class, which also calls DestroyLinkType()
+}
+
+void ChLinkLock::Copy(ChLinkLock* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMasked::Copy(source);
+
+	type = source->type;
+
+    limit_X->Copy (source->limit_X);    // copy limits
+    limit_Y->Copy (source->limit_Y);
+    limit_Z->Copy (source->limit_Z);
+    limit_Rx->Copy (source->limit_Rx);
+    limit_Ry->Copy (source->limit_Ry);
+    limit_Rz->Copy (source->limit_Rz);
+    limit_Rp->Copy (source->limit_Rp);
+    limit_D->Copy (source->limit_D);
+
+    deltaC = source->deltaC;
+    deltaC_dt = source->deltaC_dt;
+    deltaC_dtdt = source->deltaC_dtdt;
+    relC = source->relC;
+    relC_dt = source->relC_dt;
+    relC_dtdt = source->relC_dtdt;
+    Ct_temp = source->Ct_temp;
+
+    if (motion_X)   delete motion_X;    // replace and copy functions
+    if (motion_Y)   delete motion_Y;
+    if (motion_Z)   delete motion_Z;
+    if (motion_ang) delete motion_ang;
+    if (motion_ang2) delete motion_ang2;
+    if (motion_ang3) delete motion_ang3;
+
+    motion_X =   source->motion_X->new_Duplicate();
+    motion_Y =   source->motion_Y->new_Duplicate();
+    motion_Z =   source->motion_Z->new_Duplicate();
+    motion_ang = source->motion_ang->new_Duplicate();
+    motion_ang2 = source->motion_ang2->new_Duplicate();
+    motion_ang3 = source->motion_ang3->new_Duplicate();
+
+    motion_axis = source->motion_axis;
+    angleset = source->angleset;
+}
+
+
+ChLink* ChLinkLock::new_Duplicate ()   // inherited classes:  Link* MyInheritedLink::new_Duplicate()
+{
+    ChLinkLock* m_l;
+    m_l = new ChLinkLock;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+void ChLinkLock::BuildLinkType (int link_type)
+{
+    type = link_type;
+
+    ChLinkMaskLF m_mask;
+
+    // Note that the SetLockMask() sets the costraints for the
+    // link coordinates: (X,Y,Z, E0, E1,E2,E3, P, D);
+
+    // default.. free
+    m_mask.SetLockMask (false,false,false,
+                        false,false,false,false,
+                        false,false);
+
+    if (type == LNK_FREE)
+        m_mask.SetLockMask (false,false,false,
+                        false,false,false,false,
+                        false,false);
+
+    if (type == LNK_LOCK)
+        m_mask.SetLockMask (true, true, true,
+                        false,true, true, true,
+                        false,false);
+
+    if (type == LNK_SPHERICAL)
+        m_mask.SetLockMask (true, true, true,
+                        false,false,false,false,
+                        false,false);
+
+    if (type == LNK_RACKPIN)
+        m_mask.SetLockMask (false,false,false,
+                        false,false,false,false,
+                        false,false);
+
+    if (type == LNK_POINTPLANE)
+        m_mask.SetLockMask (false,false,true,
+                        false,false,false,false,
+                        false,false);
+
+    if (type == LNK_POINTLINE)
+        m_mask.SetLockMask (false,true, true,
+                        false,false,false,false,
+                        false,false);
+
+    if (type == LNK_REVOLUTE)
+        m_mask.SetLockMask (true, true, true,
+                        false,true, true,false,
+                        false,false);
+
+    if (type == LNK_CYLINDRICAL)
+        m_mask.SetLockMask (true, true, false,
+                        false,true, true, false,
+                        false,false);
+
+    if (type == LNK_PRISMATIC)
+        m_mask.SetLockMask (true, true, false,
+                        false,true, true, true,
+                        false,false);
+
+    if (type == LNK_PLANEPLANE)
+        m_mask.SetLockMask (false,false,true,
+                        false,true, true, false,
+                        false,false);
+
+    if (type == LNK_OLDHAM)
+        m_mask.SetLockMask (false,false,true,
+                        false,true, true, true,
+                        false,false);
+
+    if (type == LNK_HOOK)
+        m_mask.SetLockMask (true, true, true,
+                        false,false,true, false,
+                        false,false);
+
+    if (type == LNK_UNIVERSAL)
+        m_mask.SetLockMask (true, true, true,
+                        false,false, false, true,
+                        false,false);
+
+    if (type == LNK_CARDANO)
+        m_mask.SetLockMask (false, false, false,
+                        false,false, false, true,
+                        false,false);
+
+    if (type == LNK_ALIGN)
+        m_mask.SetLockMask (false,false,false,
+                        false,true, true, true,
+                        false,false);
+
+    if (type == LNK_PARALLEL)
+        m_mask.SetLockMask (false,false,false,
+                        false,true, true, false,
+                        false,false);
+
+    if (type == LNK_PERPEND)
+        m_mask.SetLockMask (false,false,false,
+                        false,true, false,true,
+                        false,false);
+
+    BuildLink (&m_mask);    // , TRUE);
+}
+
+
+void ChLinkLock::ChangeLinkType (int new_link_type)
+{
+    DestroyLink ();
+    BuildLinkType (new_link_type);
+
+            // Also...
+            // reset all motions and limits!
+
+    if (motion_X) delete motion_X;
+    if (motion_Y) delete motion_Y;
+    if (motion_Z) delete motion_Z;
+    if (motion_ang)  delete motion_ang;
+    if (motion_ang2) delete motion_ang2;
+    if (motion_ang3) delete motion_ang3;
+
+    motion_X =   new ChFunction_Const (0);  // default: no motion
+    motion_Y =   new ChFunction_Const (0);
+    motion_Z =   new ChFunction_Const (0);
+    motion_ang  = new ChFunction_Const (0);
+    motion_ang2 = new ChFunction_Const (0);
+    motion_ang3 = new ChFunction_Const (0);
+    motion_axis = VECT_Z;
+    angleset = ANGLESET_ANGLE_AXIS;
+
+    if (limit_X) delete limit_X;
+    if (limit_Y) delete limit_Y;
+    if (limit_Z) delete limit_Z;
+    if (limit_Rx) delete limit_Rx;
+    if (limit_Ry) delete limit_Ry;
+    if (limit_Rz) delete limit_Rz;
+    if (limit_Rp) delete limit_Rp;
+    if (limit_D) delete limit_D;
+
+    limit_X = new ChLinkLimit;    // default: inactive limits
+    limit_Y = new ChLinkLimit;
+    limit_Z = new ChLinkLimit;
+    limit_Rx = new ChLinkLimit;
+    limit_Ry = new ChLinkLimit;
+    limit_Rz = new ChLinkLimit;
+    limit_D = new ChLinkLimit;
+    limit_Rp = new ChLinkLimit;   // the polar limit;
+    limit_Rp->Set_polar(TRUE);
+}
+
+
+void ChLinkLock::Set2Dmode(int mode)
+{
+    ChLinkMaskLF* mmask = (ChLinkMaskLF*) this->mask;
+
+    if (mmask->Set2Dmode(mode) >0)
+    {
+        ChangedLinkMask ();
+    }
+}
+
+
+// setup the functions when user changes them.
+
+void ChLinkLock::SetMotion_X  (ChFunction* m_funct)
+{
+    if (motion_X) delete motion_X;
+    motion_X = m_funct;
+}
+
+void ChLinkLock::SetMotion_Y  (ChFunction* m_funct)
+{
+    if (motion_Y) delete motion_Y;
+    motion_Y = m_funct;
+}
+
+void ChLinkLock::SetMotion_Z  (ChFunction* m_funct)
+{
+    if (motion_Z) delete motion_Z;
+    motion_Z = m_funct;
+}
+
+void ChLinkLock::SetMotion_ang    (ChFunction* m_funct)
+{
+    if (motion_ang) delete motion_ang;
+    motion_ang = m_funct;
+}
+
+void ChLinkLock::SetMotion_ang2   (ChFunction* m_funct)
+{
+    if (motion_ang2) delete motion_ang2;
+    motion_ang2 = m_funct;
+}
+
+void ChLinkLock::SetMotion_ang3   (ChFunction* m_funct)
+{
+    if (motion_ang3) delete motion_ang3;
+    motion_ang3 = m_funct;
+}
+
+void ChLinkLock::SetMotion_axis (Vector m_axis)
+{
+    motion_axis = m_axis;
+}
+
+
+
+
+
+
+
+
+
+////////////////////////////////////
+////////////////////////////////////
+///
+///    UPDATING PROCEDURES
+
+
+
+/////////   1-   UPDATE TIME
+/////////
+
+void ChLinkLock::UpdateTime (double time)
+{
+	ChLinkMasked::UpdateTime(time);
+
+    double ang, ang_dt, ang_dtdt;
+
+        // If some limit is provided, the delta values may have been
+        // changed by limits themselves, so no further modifications by motion laws..
+    if (limit_X->Get_active() ||
+        limit_Y->Get_active() ||
+        limit_Z->Get_active() ||
+        limit_Rx->Get_active() ||
+        limit_Ry->Get_active() ||
+        limit_Rz->Get_active())
+    return ;
+
+        // Update motion position/speed/acceleration by motion laws
+        // as expressed by specific link CH funcions
+    deltaC.pos.x= motion_X->Get_y(time);
+    deltaC_dt.pos.x= motion_X->Get_y_dx(time);
+    deltaC_dtdt.pos.x= motion_X->Get_y_dxdx(time);
+
+    deltaC.pos.y= motion_Y->Get_y(time);
+    deltaC_dt.pos.y= motion_Y->Get_y_dx(time);
+    deltaC_dtdt.pos.y= motion_Y->Get_y_dxdx(time);
+
+    deltaC.pos.z= motion_Z->Get_y(time);
+    deltaC_dt.pos.z= motion_Z->Get_y_dx(time);
+    deltaC_dtdt.pos.z= motion_Z->Get_y_dxdx(time);
+
+    switch (angleset) {
+    case ANGLESET_ANGLE_AXIS:
+        ang     = motion_ang->Get_y(time);
+        ang_dt  = motion_ang->Get_y_dx(time);
+        ang_dtdt= motion_ang->Get_y_dxdx(time);
+
+        if ((ang !=0)||(ang_dt !=0)||(ang_dtdt !=0))
+        {
+            deltaC.rot = Q_from_AngAxis (ang, motion_axis);
+            deltaC_dt.rot = Qdt_from_AngAxis (deltaC.rot, ang_dt, motion_axis);
+            deltaC_dtdt.rot = Qdtdt_from_AngAxis (ang_dtdt, motion_axis, deltaC.rot, deltaC_dt.rot);
+        }
+        else
+        {
+            deltaC.rot = QUNIT;
+            deltaC_dt.rot = QNULL;
+            deltaC_dtdt.rot = QNULL;
+        }
+        break;
+    case ANGLESET_EULERO:
+    case ANGLESET_CARDANO:
+    case ANGLESET_HPB:
+    case ANGLESET_RXYZ:
+        Vector vangles, vangles_dt, vangles_dtdt;
+        vangles.x = motion_ang->Get_y(time);
+        vangles.y = motion_ang2->Get_y(time);
+        vangles.z = motion_ang3->Get_y(time);
+        vangles_dt.x = motion_ang->Get_y_dx(time);
+        vangles_dt.y = motion_ang2->Get_y_dx(time);
+        vangles_dt.z = motion_ang3->Get_y_dx(time);
+        vangles_dtdt.x = motion_ang->Get_y_dxdx(time);
+        vangles_dtdt.y = motion_ang2->Get_y_dxdx(time);
+        vangles_dtdt.z = motion_ang3->Get_y_dxdx(time);
+        deltaC.rot = Angle_to_Quat(angleset, &vangles);
+        deltaC_dt.rot = AngleDT_to_QuatDT(angleset, &vangles_dt, &deltaC.rot);
+        deltaC_dtdt.rot = AngleDTDT_to_QuatDTDT(angleset, &vangles_dtdt, &deltaC.rot);
+        break;
+    }
+}
+
+
+
+/////////   2-   UPDATE RELATIVE MARKER COORDINATES
+/////////
+
+void ChLinkLock::UpdateRelMarkerCoords()
+{
+    // FOR ALL THE 6(or3) COORDINATES OF RELATIVE MOTION OF THE TWO MARKERS.
+    //  Also set some static vectors/quaternions which will be used later in the
+    // UpdateState function for the Lock-Formulation method (this customization,
+    // happens only for speed readsons, otherwise the base UpdateRelMarkerCoords()
+    // could be sufficient)
+
+    PQw = Vsub (marker1->GetAbsCoord().pos, marker2->GetAbsCoord().pos);
+    PQw_dt = Vsub (marker1->GetAbsCoord_dt().pos, marker2->GetAbsCoord_dt().pos);
+    PQw_dtdt = Vsub (marker1->GetAbsCoord_dtdt().pos, marker2->GetAbsCoord_dtdt().pos);
+
+    dist    = Vlenght (PQw);                // distance between origins, modulus
+    dist_dt = Vdot (Vnorm(PQw), PQw_dt);    // speed between origins, modulus.
+
+    Vector vtemp1;       // for intermediate calculus
+    Vector vtemp2;
+    Quaternion qtemp1;
+    ChMatrixNM<double,3,4> relGw;
+    Quaternion temp1=marker1->GetCoord_dt().rot;
+    Quaternion temp2=marker2->GetCoord_dt().rot;
+
+    if ((Qnotnull(&temp2))||
+        (Qnotnull(&temp1)) )
+    {
+      q_AD =                    //  q'qqq + qqqq'
+       Qadd (
+        Qcross (
+          Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord().rot)
+          ))),
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord_dt().rot)
+          )))
+        );
+    }
+    else
+        q_AD=QNULL;
+
+    q_BC =                  // qq'qq + qqq'q
+       Qadd (
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord_dt().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord().rot)
+          ))),
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord_dt().rot),
+          (marker1->GetCoord().rot)
+          )))
+       );
+
+                            // q_8 = q''qqq + 2q'q'qq + 2q'qq'q + 2q'qqq'
+                            //     + 2qq'q'q + 2qq'qq' + 2qqq'q' + qqqq''
+    temp2=marker2->GetCoord_dtdt().rot;
+    if (Qnotnull(&temp2))
+    q_8=Qcross(Qconjugate(marker2->GetCoord_dtdt().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord().rot)));        // q_dtdt'm2 * q'o2 * q,o1 * q,m1
+    else
+    q_8 = QNULL;
+    temp1=marker1->GetCoord_dtdt().rot;
+    if (Qnotnull(&temp1))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord_dtdt().rot)));   // q'm2 * q'o2 * q,o1 * q_dtdt,m1
+     q_8= Qadd (q_8, qtemp1);
+    }
+    temp2=marker2->GetCoord_dt().rot;
+    if (Qnotnull(&temp2))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dt().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord().rot)));
+     qtemp1= Qscale (qtemp1, 2);                // 2( q_dt'm2 * q_dt'o2 * q,o1 * q,m1)
+     q_8= Qadd (q_8, qtemp1);
+    }
+    temp2=marker2->GetCoord_dt().rot;
+    if (Qnotnull(&temp2))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord_dt().rot,
+        marker1->GetCoord().rot)));
+     qtemp1= Qscale (qtemp1, 2);                // 2( q_dt'm2 * q'o2 * q_dt,o1 * q,m1)
+     q_8= Qadd (q_8, qtemp1);
+    }
+    temp1=marker1->GetCoord_dt().rot;
+    temp2=marker2->GetCoord_dt().rot;
+    if ((Qnotnull(&temp2))&&
+        (Qnotnull(&temp1)))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord_dt().rot)));
+     qtemp1= Qscale (qtemp1, 2);                // 2( q_dt'm2 * q'o2 * q,o1 * q_dt,m1)
+     q_8= Qadd (q_8, qtemp1);
+    }
+
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dt().rot),
+        Qcross(Body1->GetCoord_dt().rot,
+        marker1->GetCoord().rot)));
+    qtemp1= Qscale (qtemp1, 2);             // 2( q'm2 * q_dt'o2 * q_dt,o1 * q,m1)
+    q_8= Qadd (q_8, qtemp1);
+    temp1=marker1->GetCoord_dt().rot;
+    if (Qnotnull(&temp1))
+    {
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dt().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord_dt().rot)));
+    qtemp1= Qscale (qtemp1, 2);             // 2( q'm2 * q_dt'o2 * q,o1 * q_dt,m1)
+    q_8= Qadd (q_8, qtemp1);
+    }
+    temp1=marker1->GetCoord_dt().rot;
+    if (Qnotnull(&temp1))
+    {
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord_dt().rot,
+        marker1->GetCoord_dt().rot)));
+    qtemp1= Qscale (qtemp1, 2);             // 2( q'm2 * q'o2 * q_dt,o1 * q_dt,m1)
+    q_8= Qadd (q_8, qtemp1);
+    }
+
+                                // q_4 = [Adtdt]'[A]'q + 2[Adt]'[Adt]'q
+                                //       + 2[Adt]'[A]'qdt + 2[A]'[Adt]'qdt
+	ChMatrix33<> m2_Rel_A_dt;
+	marker2->Compute_Adt(m2_Rel_A_dt);
+	ChMatrix33<> m2_Rel_A_dtdt;
+	marker2->Compute_Adtdt(m2_Rel_A_dtdt);
+
+    vtemp1=Body2->GetA_dt().MatrT_x_Vect(PQw);
+    vtemp2=m2_Rel_A_dt.MatrT_x_Vect(vtemp1);
+    q_4= Vmul (vtemp2, 2);          // 2[Aq_dt]'[Ao2_dt]'*Qpq,w
+
+    vtemp1=Body2->GetA()->MatrT_x_Vect(PQw_dt);
+    vtemp2=m2_Rel_A_dt.MatrT_x_Vect(vtemp1);
+    vtemp2= Vmul (vtemp2, 2);       // 2[Aq_dt]'[Ao2]'*Qpq,w_dt
+    q_4= Vadd (q_4, vtemp2);
+
+    vtemp1=Body2->GetA_dt().MatrT_x_Vect(PQw_dt);
+    vtemp2=marker2->GetA()->MatrT_x_Vect(vtemp1);
+    vtemp2= Vmul (vtemp2, 2);       // 2[Aq]'[Ao2_dt]'*Qpq,w_dt
+    q_4= Vadd (q_4, vtemp2);
+
+    vtemp1=Body2->GetA()->MatrT_x_Vect(PQw);
+    vtemp2=m2_Rel_A_dtdt.MatrT_x_Vect(vtemp1);
+    q_4= Vadd (q_4, vtemp2);        //  [Aq_dtdt]'[Ao2]'*Qpq,w
+
+
+
+            // ----------- RELATIVE MARKER COORDINATES
+
+            // relM.pos
+    relM.pos =
+        marker2->GetA()->MatrT_x_Vect(
+        Body2->GetA()->MatrT_x_Vect(PQw));
+
+            // relM.rot
+    relM.rot =
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord().rot)
+          )));
+
+            // relM_dt.pos
+    relM_dt.pos =
+        Vadd (
+        Vadd (
+        m2_Rel_A_dt.MatrT_x_Vect(
+        Body2->GetA()->MatrT_x_Vect(PQw)) ,
+        marker2->GetA()->MatrT_x_Vect(
+        Body2->GetA_dt().MatrT_x_Vect(PQw))),
+        marker2->GetA()->MatrT_x_Vect(
+        Body2->GetA()->MatrT_x_Vect(PQw_dt)));
+
+            // relM_dt.rot
+    relM_dt.rot =
+       Qadd ( q_AD, q_BC );
+
+            // relM_dtdt.pos
+    relM_dtdt.pos =
+        Vadd (
+        Vadd (
+        marker2->GetA()->MatrT_x_Vect(
+         Body2->GetA_dtdt().MatrT_x_Vect(PQw)),
+        marker2->GetA()->MatrT_x_Vect(
+         Body2->GetA()->MatrT_x_Vect(PQw_dtdt))),
+        q_4);
+
+
+            // relM_dtdt.rot
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dtdt().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord().rot)));    // ( q'm2 * q_dtdt'o2 * q,o1 * q,m1)
+    relM_dtdt.rot= Qadd (q_8, qtemp1);
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord_dtdt().rot,
+        marker1->GetCoord().rot)));    // ( q'm2 * q'o2 * q_dtdt,o1 * q,m1)
+    relM_dtdt.rot= Qadd (relM_dtdt.rot, qtemp1);    // = q_8 + qq''qq + qqq''q
+
+
+                // ... and also "user-friendly" relative coordinates:
+
+            // relAngle and relAxis
+    Q_to_AngAxis (&relM.rot, &relAngle, &relAxis);
+    // flip rel rotation axis if jerky sign
+    if (relAxis.z < 0)
+    {
+        relAxis = Vmul (relAxis, -1);
+        relAngle = -relAngle;
+    }
+            // rotation axis
+    relRotaxis = Vmul(relAxis, relAngle);
+            // relWvel
+    ChFrame<>::SetMatrix_Gw(relGw, relM.rot); // relGw.Set_Gw_matrix(relM.rot);
+    relWvel = relGw.Matr34_x_Quat (relM_dt.rot);
+            // relWacc
+    relWacc = relGw.Matr34_x_Quat (relM_dtdt.rot);
+
+}
+
+
+
+
+
+/////////   4-   UPDATE STATE
+/////////
+
+void ChLinkLock::UpdateState ()
+{
+
+
+                        // ---------------------
+                        // Updates Cq1_temp, Cq2_temp, Qc_temp,
+                        // etc., i.e. all LOCK-FORMULATION temp.matrices
+                        // ---------------------
+
+    ChVector<> vtemp1;       // for intermediate calculus
+    ChVector<> vtemp2;
+
+    ChMatrix33<> mtemp1;
+    ChMatrix33<> mtemp2;
+    ChMatrix33<> mtemp3;
+    ChMatrixNM<double,4,4> mtempQ1;
+    ChMatrixNM<double,4,4> mtempQ2;
+
+    ChMatrix33<> CqxT;     // the 3x3 piece of Cq_temp for trasl. link,   trasl.coords,
+    ChMatrixNM<double,3,4> CqxR;// the 3x4 piece of Cq_temp for trasl. link,   rotat. coords,
+    ChMatrixNM<double,4,4> CqrR;// the 4x4 piece of Cq_temp for rotat..link,   rotat. coords,
+    ChVector<>  Qcx;     // the 3x1 vector of Qc     for trasl. link
+    ChQuaternion<> Qcr;  // the 4x1 quaternion of Qc for rotat. link
+
+    // [Cq_temp]= [[CqxT] [CqxR]]     {Qc_temp} ={[Qcx]}
+    //            [[ 0  ] [CqrR]]                {[Qcr]}
+
+            // ----------- SOME PRECALCULATED VARIABLES, to optimize speed
+
+    ChMatrix33<> P1star;       // [P] star matrix of rel pos of mark1
+    P1star.Set_X_matrix(marker1->GetCoord().pos);
+    ChMatrix33<> Q2star;       // [Q] star matrix of rel pos of mark2
+    Q2star.Set_X_matrix(marker2->GetCoord().pos);
+
+
+	ChMatrixNM<double,3,4> body1Gl;
+	ChMatrixNM<double,3,4> body2Gl;
+
+	ChFrame<>::SetMatrix_Gl(body1Gl, Body1->GetCoord().rot);
+	ChFrame<>::SetMatrix_Gl(body2Gl, Body2->GetCoord().rot);
+
+
+            // ----------- RELATIVE LINK-LOCK COORDINATES (violations)
+
+            // relC.pos
+    relC.pos = Vsub (relM.pos, deltaC.pos);
+
+            // relC.rot
+    relC.rot = Qcross (Qconjugate(deltaC.rot), relM.rot);
+
+            // relC_dt.pos
+    relC_dt.pos = Vsub (relM_dt.pos, deltaC_dt.pos);
+
+            // relC_dt.rot
+    relC_dt.rot = Qadd (
+                Qcross (Qconjugate(deltaC_dt.rot),relM.rot),
+                Qcross (Qconjugate(deltaC.rot),relM_dt.rot) );
+
+            // relC_dtdt.pos
+    relC_dtdt.pos = Vsub (relM_dtdt.pos, deltaC_dtdt.pos);
+
+            // relC_dtdt.rot
+    relC_dtdt.rot = Qadd (
+                    Qadd (
+                Qcross (Qconjugate(deltaC_dtdt.rot),relM.rot),
+                Qcross (Qconjugate(deltaC.rot),relM_dtdt.rot) ),
+                Qscale (Qcross (Qconjugate(deltaC_dt.rot),relM_dt.rot),2) );
+
+
+    // +++++++++ COMPUTE THE  Cq Ct Qc    matrices (temporary, for complete lock contraint)
+
+	ChMatrix33<> m2_Rel_A_dt;
+	marker2->Compute_Adt(m2_Rel_A_dt);
+	ChMatrix33<> m2_Rel_A_dtdt;
+	marker2->Compute_Adtdt(m2_Rel_A_dtdt);
+
+            // ----------- PARTIAL DERIVATIVE Ct OF CONSTRAINT
+    Ct_temp.pos =
+        Vadd (
+          m2_Rel_A_dt.MatrT_x_Vect(
+          Body2->GetA()->MatrT_x_Vect(PQw)),
+          marker2->GetA()->MatrT_x_Vect(
+           Vsub(Body2->GetA()->MatrT_x_Vect(
+            Body1->GetA()->Matr_x_Vect(marker1->GetCoord_dt().pos)),
+            marker2->GetCoord_dt().pos))
+          );
+    Ct_temp.pos = Vsub (Ct_temp.pos,  deltaC_dt.pos);   // the deltaC contribute
+
+
+    Ct_temp.rot =       // deltaC^*(q_AD) + deltaC_dt^*q_pq
+        Qadd (
+        Qcross (Qconjugate (deltaC.rot), q_AD),
+        Qcross (Qconjugate (deltaC_dt.rot), relM.rot)
+        );
+
+
+
+            //------------ COMPLETE JACOBIANS Cq1_temp AND Cq2_temp AND Qc_temp VECTOR.
+
+            //  JACOBIANS Cq1_temp, Cq2_temp:
+
+    mtemp1.CopyFromMatrixT(*marker2->GetA());
+    CqxT.MatrMultiplyT(mtemp1,*Body2->GetA());     // [CqxT]=[Aq]'[Ao2]'
+
+    Cq1_temp->PasteMatrix(&CqxT,0,0);       // *- -- Cq1_temp(1-3)  =[Aqo2]
+
+    CqxT.MatrNeg();
+    Cq2_temp->PasteMatrix(&CqxT,0,0);       // -- *- Cq2_temp(1-3)  =-[Aqo2]
+
+
+    mtemp1.MatrMultiply(CqxT, *Body1->GetA());
+    mtemp2.MatrMultiply(mtemp1,P1star);
+
+    CqxR.MatrMultiply   (mtemp2, body1Gl);
+
+    Cq1_temp->PasteMatrix(&CqxR,0,3);       // -* -- Cq1_temp(4-7)
+
+
+    CqxT.MatrNeg();
+    mtemp1.MatrMultiply(CqxT,*Body2->GetA());
+    mtemp2.MatrMultiply(mtemp1,Q2star);
+    CqxR.MatrMultiply   (mtemp2, body2Gl);
+    Cq2_temp->PasteMatrix(&CqxR,0,3);
+
+    mtemp1.CopyFromMatrixT(*marker2->GetA());
+    mtemp2.Set_X_matrix ( Body2->GetA()->MatrT_x_Vect(PQw));
+    mtemp3.MatrMultiply (mtemp1, mtemp2);
+    CqxR.MatrMultiply    (mtemp3, body2Gl);
+
+    Cq2_temp->PasteSumMatrix(&CqxR,0,3);        // -- -* Cq1_temp(4-7)
+
+
+    mtempQ1.Set_Xq_matrix(Qcross(Qconjugate(marker2->GetCoord().rot),
+                                 Qconjugate(Body2->GetCoord().rot)));
+    CqrR.Set_Xq_matrix(marker1->GetCoord().rot);
+    CqrR.MatrXq_SemiTranspose();
+    mtempQ2.MatrMultiply (mtempQ1, CqrR);
+    mtempQ1.Set_Xq_matrix(Qconjugate(deltaC.rot));
+    CqrR.MatrMultiply (mtempQ1, mtempQ2);
+
+    Cq1_temp->PasteMatrix(&CqrR,3,3);       // =* == Cq1_temp(col 4-7, row 4-7)
+
+
+    mtempQ1.Set_Xq_matrix(Qconjugate(marker2->GetCoord().rot));
+    CqrR.Set_Xq_matrix(Qcross(Body1->GetCoord().rot,
+                          marker1->GetCoord().rot));
+    CqrR.MatrXq_SemiTranspose();
+    CqrR.MatrXq_SemiNeg();
+    mtempQ2.MatrMultiply (mtempQ1, CqrR);
+    mtempQ1.Set_Xq_matrix(Qconjugate(deltaC.rot));
+    CqrR.MatrMultiply (mtempQ1, mtempQ2);
+
+    Cq2_temp->PasteMatrix(&CqrR,3,3);       // == =* Cq2_temp(col 4-7, row 4-7)
+
+
+        //--------- COMPLETE Qc VECTOR
+
+    vtemp1= Vcross ( Body1->GetWvel_loc(), Vcross(Body1->GetWvel_loc(), marker1->GetCoord().pos));
+    vtemp1= Vadd (vtemp1, marker1->GetCoord_dtdt().pos);
+    vtemp1= Vadd (vtemp1, Vmul (Vcross (Body1->GetWvel_loc(), marker1->GetCoord_dt().pos) , 2));
+    vtemp1= Body1->GetA()->Matr_x_Vect(vtemp1);
+
+    vtemp2= Vcross ( Body2->GetWvel_loc(), Vcross(Body2->GetWvel_loc(), marker2->GetCoord().pos));
+    vtemp2= Vadd (vtemp2, marker2->GetCoord_dtdt().pos);
+    vtemp2= Vadd (vtemp2, Vmul (Vcross (Body2->GetWvel_loc(), marker2->GetCoord_dt().pos) , 2));
+    vtemp2= Body2->GetA()->Matr_x_Vect(vtemp2);
+
+    vtemp1= Vsub (vtemp1, vtemp2);
+    Qcx= CqxT.Matr_x_Vect (vtemp1);
+
+    mtemp1.Set_X_matrix ( Body2->GetWvel_loc());
+    mtemp2.MatrMultiply (mtemp1, mtemp1);
+    mtemp3.MatrMultiply (*Body2->GetA(), mtemp2);
+    mtemp3.MatrTranspose();
+    vtemp1=mtemp3.Matr_x_Vect(PQw);
+    vtemp2=marker2->GetA()->MatrT_x_Vect(vtemp1);  // [Aq]'[[A2][w2][w2]]'*Qpq,w
+    Qcx= Vadd (Qcx, vtemp2);
+
+    Qcx= Vadd (Qcx, q_4);             // [Adtdt]'[A]'q + 2[Adt]'[Adt]'q + 2[Adt]'[A]'qdt + 2[A]'[Adt]'qdt
+
+    Qcx= Vsub (Qcx, deltaC_dtdt.pos); // ... - deltaC_dtdt
+
+    Qc_temp->PasteVector(Qcx,0,0);  // * Qc_temp, for all translational coords
+
+
+
+
+    Qcr = Qcross (Qconjugate(deltaC.rot), q_8);
+    Qcr = Qadd (Qcr,
+            Qscale (Qcross(Qconjugate(deltaC_dt.rot),relM_dt.rot),2));
+    Qcr = Qadd (Qcr,
+            Qcross(Qconjugate(deltaC_dtdt.rot),relM.rot)); // = deltaC'*q_8 + 2*deltaC_dt'*q_dt,po + deltaC_dtdt'*q,po
+
+    Qc_temp->PasteQuaternion(Qcr,3,0);      // * Qc_temp, for all rotational coords
+
+
+    // *** NOTE! The definitive  Qc must change sign, to be used in
+    // lagrangian equation:    [Cq]*q_dtdt = Qc
+    // because until now we have computed it as [Cq]*q_dtdt + "Qc" = 0,
+    // but the most used form is the previous, so let's change sign!!
+
+    Qc_temp->MatrNeg();
+
+                        // FINALLY.....
+                        // ---------------------
+                        // Updates Cq1, Cq2, Qc,
+                        // C, C_dt, C_dtdt, Ct.
+                        // ---------------------
+    int index = 0;
+
+    ChLinkMaskLF* mmask = (ChLinkMaskLF*) this->mask;
+
+	if (mmask->Constr_X().IsActive()) // for X costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 0,0, 1,7, index, 0);
+        Cq2->PasteClippedMatrix (Cq2_temp, 0,0, 1,7, index, 0);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (0,0));
+
+        C->SetElement(index,0,      relC.pos.x);
+        C_dt->SetElement(index,0,   relC_dt.pos.x);
+        C_dtdt->SetElement(index,0, relC_dtdt.pos.x);
+
+        Ct->SetElement(index,0, Ct_temp.pos.x );
+
+        index ++;
+    }
+
+    if (mmask->Constr_Y().IsActive()) // for Y costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 1,0, 1,7, index, 0);
+        Cq2->PasteClippedMatrix (Cq2_temp, 1,0, 1,7, index, 0);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (1,0));
+
+        C->SetElement(index,0,      relC.pos.y);
+        C_dt->SetElement(index,0,   relC_dt.pos.y);
+        C_dtdt->SetElement(index,0, relC_dtdt.pos.y);
+
+        Ct->SetElement(index,0, Ct_temp.pos.y);
+
+        index ++;
+    }
+
+    if (mmask->Constr_Z().IsActive()) // for Z costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 2,0, 1,7, index, 0);
+        Cq2->PasteClippedMatrix (Cq2_temp, 2,0, 1,7, index, 0);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (2,0));
+
+        C->SetElement(index,0,      relC.pos.z);
+        C_dt->SetElement(index,0,   relC_dt.pos.z);
+        C_dtdt->SetElement(index,0, relC_dtdt.pos.z);
+
+        Ct->SetElement(index,0, Ct_temp.pos.z);
+
+        index ++;
+    }
+
+    if (mmask->Constr_E0().IsActive())    // for E0 costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 3,3, 1,4, index, 3);
+        Cq2->PasteClippedMatrix (Cq2_temp, 3,3, 1,4, index, 3);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (3,0));
+
+        C->SetElement(index,0,      relC.rot.e0);
+        C_dt->SetElement(index,0,   relC_dt.rot.e0);
+        C_dtdt->SetElement(index,0, relC_dtdt.rot.e0);
+
+        Ct->SetElement(index,0, Ct_temp.rot.e0);
+
+        index ++;
+    }
+
+    if (mmask->Constr_E1().IsActive())   // for E1 costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 4,3, 1,4, index, 3);
+        Cq2->PasteClippedMatrix (Cq2_temp, 4,3, 1,4, index, 3);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (4,0));
+
+        C->SetElement(index,0,      relC.rot.e1);
+        C_dt->SetElement(index,0,   relC_dt.rot.e1);
+        C_dtdt->SetElement(index,0, relC_dtdt.rot.e1);
+
+        Ct->SetElement(index,0, Ct_temp.rot.e1);
+
+        index ++;
+    }
+
+    if (mmask->Constr_E2().IsActive())    // for E2 costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 5,3, 1,4, index, 3);
+        Cq2->PasteClippedMatrix (Cq2_temp, 5,3, 1,4, index, 3);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (5,0));
+
+        C->SetElement(index,0,      relC.rot.e2);
+        C_dt->SetElement(index,0,   relC_dt.rot.e2);
+        C_dtdt->SetElement(index,0, relC_dtdt.rot.e2);
+
+        Ct->SetElement(index,0, Ct_temp.rot.e2);
+
+        index ++;
+    }
+
+    if (mmask->Constr_E3().IsActive())    // for E3 costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 6,3, 1,4, index, 3);
+        Cq2->PasteClippedMatrix (Cq2_temp, 6,3, 1,4, index, 3);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (6,0));
+
+        C->SetElement(index,0,      relC.rot.e3);
+        C_dt->SetElement(index,0,   relC_dt.rot.e3);
+        C_dtdt->SetElement(index,0, relC_dtdt.rot.e3);
+
+        Ct->SetElement(index,0, Ct_temp.rot.e3);
+
+        index ++;
+    }
+
+    if (mmask->Constr_P().IsActive()) // for P (polar, conical rotation) costraint...
+    {
+        Cq1->PasteClippedMatrix (Cq1_temp, 6,3, 1,4, index, 3);
+        Cq2->PasteClippedMatrix (Cq2_temp, 6,3, 1,4, index, 3);
+
+        Qc->SetElement(index,0,
+                      Qc_temp->GetElement (6,0));
+
+        C->SetElement(index,0,      relC.rot.e3);
+        C_dt->SetElement(index,0,   relC_dt.rot.e3);
+        C_dtdt->SetElement(index,0, relC_dtdt.rot.e3);
+
+        Ct->SetElement(index,0, Ct_temp.rot.e3);
+
+        index ++;
+    }
+
+    if (mmask->Constr_D().IsActive()) // for D (distance costraint)
+    {
+        ChMatrixNM<double,3,7> Cq1tmp;
+        ChMatrixNM<double,3,7> Cq2tmp;
+        ChMatrixNM<double,1,7> Cq1d;
+        ChMatrixNM<double,1,7> Cq2d;
+        ChMatrixNM<double,3,1> mfact;
+        double mQd;
+
+        ChVector<> vfact;
+        vfact= Vnorm(relM.pos);
+        mfact.PasteVector(vfact,0,0);
+
+        Cq1tmp.PasteClippedMatrix (Cq1_temp, 0,0, 3,7, 0,0);
+        Cq2tmp.PasteClippedMatrix (Cq2_temp, 0,0, 3,7, 0,0);
+                // Cq= (1/||relM||)*relM'*Cq_lock
+        Cq1d.MatrTMultiply(mfact,Cq1tmp);
+        Cq2d.MatrTMultiply(mfact,Cq2tmp);
+
+        Cq1->PasteClippedMatrix (&Cq1d, 0,0, 1,7, index, 0);
+        Cq2->PasteClippedMatrix (&Cq2d, 0,0, 1,7, index, 0);
+
+        ChVector<> Qvect;
+        Qvect.x = Qc_temp->GetElement(0,0);
+        Qvect.y = Qc_temp->GetElement(1,0);
+        Qvect.z = Qc_temp->GetElement(2,0);
+
+        Qvect = Vsub (Qvect, deltaC_dtdt.pos); // cut away effect of xyz deltas
+        mQd = Vdot (vfact, Qvect);
+        mQd = mQd - (1/Vlenght(relM.pos))*Vdot(relM_dt.pos, relM_dt.pos);
+        double sq_q = Vdot(relM_dt.pos, relM.pos); sq_q = sq_q*sq_q;
+        mQd = mQd + (1/Vlenght(relM.pos))*Vdot(relM.pos, relM.pos)*sq_q;
+        mQd = mQd + deltaC_dtdt.pos.x;
+
+        Qc->SetElement(index,0, mQd);
+
+        C->SetElement(index,0,      (Vlenght(relM.pos)-deltaC.pos.x));
+        C_dt->SetElement(index,0,   ((Vdot(relM_dt.pos,   Vnorm(relM.pos)))-deltaC_dt.pos.x));
+        C_dtdt->SetElement(index,0, ((Vdot(relM_dtdt.pos, Vnorm(relM.pos)))-deltaC_dtdt.pos.x));
+
+        Ct->SetElement(index,0,
+                      Vdot(vfact,Ct_temp.pos));
+
+        index ++;
+    }
+}
+
+
+
+/////////   5-   UPDATE FORCES
+/////////
+
+void ChLinkLock::UpdateForces(double mytime)
+{
+    // Inherit force computation:
+    // also base class can add its own forces.
+    ChLinkMasked::UpdateForces(mytime);
+
+    // now add:
+
+    // ========== the link-limits "cushion forces"
+
+    ChVector<> m_force = VNULL;
+    ChVector<> m_torque = VNULL;
+
+    if (limit_X->Get_active())
+    {
+        m_force.x= limit_X->GetForce(relM.pos.x, relM_dt.pos.x);
+    }
+    if (limit_Y->Get_active())
+    {
+        m_force.y= limit_Y->GetForce(relM.pos.y, relM_dt.pos.y);
+    }
+    if (limit_Z->Get_active())
+    {
+        m_force.z= limit_Z->GetForce(relM.pos.z, relM_dt.pos.z);
+    }
+
+    if (limit_D->Get_active())
+    {
+        m_force = Vadd(m_force,
+                       Vmul(Vnorm(relM.pos), limit_D->GetForce(dist, dist_dt)));
+    }
+
+    if (limit_Rx->Get_active())
+    {
+        m_torque.x= limit_Rx->GetForce(relRotaxis.x, relWvel.x);
+    }
+    if (limit_Ry->Get_active())
+    {
+        m_torque.y= limit_Ry->GetForce(relRotaxis.y, relWvel.y);
+    }
+    if (limit_Rz->Get_active())
+    {
+        m_torque.z= limit_Rz->GetForce(relRotaxis.z, relWvel.z);
+    }
+    if (limit_Rp->Get_active())
+    {
+        ChVector<> torq_axis;
+        ChVector<> arm_xaxis;
+        ChVector<> projected_arm;
+        double zenithspeed;
+        double zenith;
+        double polar;
+
+        arm_xaxis = VaxisXfromQuat (relM.rot);  // the X axis of the marker1, respect to m2.
+        zenith = VangleYZplaneNorm (&arm_xaxis);// the angle of m1 Xaxis about normal to YZ plane
+        polar  = VangleRX (&arm_xaxis);         // the polar angle of m1 Xaxis spinning about m2 Xaxis
+
+        projected_arm.x = 0; projected_arm.y= arm_xaxis.y; projected_arm.z= arm_xaxis.z;
+        ChVector<> vx = VECT_X;
+        torq_axis = Vcross (vx, projected_arm);
+        torq_axis = Vnorm (torq_axis);      // the axis of torque, laying on YZ plane.
+
+        zenithspeed = Vdot (torq_axis, relWvel);    // the speed of zenith rotation toward cone.
+
+        m_torque= Vadd (m_torque,
+            Vmul (torq_axis, limit_Rp->GetPolarForce(zenith, zenithspeed, polar)) );
+    }
+
+    C_force = Vadd(C_force, m_force);       // +++
+    C_torque = Vadd(C_torque, m_torque);    // +++
+
+
+    // ========== other forces??
+}
+
+
+
+
+
+
+//
+// Reimplement parent 'lcp stuff' because 'upper/lower limits' may 
+// add constraints
+//
+
+
+void ChLinkLock::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	// parent 
+	ChLinkMasked::InjectConstraints(mdescriptor);
+
+	if (limit_X) if (limit_X->Get_active())
+	{
+		limit_X->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_X->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		if (limit_X->constr_lower.IsActive())
+			mdescriptor.InsertConstraint(&limit_X->constr_lower);
+		if (limit_X->constr_upper.IsActive())
+			mdescriptor.InsertConstraint(&limit_X->constr_upper);
+	}
+	if (limit_Y) if (limit_Y->Get_active())
+	{
+		limit_Y->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Y->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		if (limit_Y->constr_lower.IsActive())
+			mdescriptor.InsertConstraint(&limit_Y->constr_lower);
+		if (limit_Y->constr_upper.IsActive())
+			mdescriptor.InsertConstraint(&limit_Y->constr_upper);
+	}
+	if (limit_Z) if (limit_Z->Get_active())
+	{
+		limit_Z->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Z->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		if (limit_Z->constr_lower.IsActive())
+			mdescriptor.InsertConstraint(&limit_Z->constr_lower);
+		if (limit_Z->constr_upper.IsActive())
+			mdescriptor.InsertConstraint(&limit_Z->constr_upper);
+	}
+	if (limit_Rx) if (limit_Rx->Get_active())
+	{
+		limit_Rx->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Rx->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		if (limit_Rx->constr_lower.IsActive())
+			mdescriptor.InsertConstraint(&limit_Rx->constr_lower);
+		if (limit_Rx->constr_upper.IsActive())
+			mdescriptor.InsertConstraint(&limit_Rx->constr_upper);
+	}
+	if (limit_Ry) if (limit_Ry->Get_active())
+	{
+		limit_Ry->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Ry->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		if (limit_Ry->constr_lower.IsActive())
+			mdescriptor.InsertConstraint(&limit_Ry->constr_lower);
+		if (limit_Ry->constr_upper.IsActive())
+			mdescriptor.InsertConstraint(&limit_Ry->constr_upper);
+	}
+	if (limit_Rz) if (limit_Rz->Get_active())
+	{
+		limit_Rz->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Rz->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		if (limit_Rz->constr_lower.IsActive())
+			mdescriptor.InsertConstraint(&limit_Rz->constr_lower);
+		if (limit_Rz->constr_upper.IsActive())
+			mdescriptor.InsertConstraint(&limit_Rz->constr_upper);
+	}
+}
+
+void ChLinkLock::ConstraintsBiReset()
+{
+	// parent 
+	ChLinkMasked::ConstraintsBiReset();
+
+	if (limit_X) if (limit_X->Get_active())
+	{
+		limit_X->constr_lower.Set_b_i(0.);
+		limit_X->constr_upper.Set_b_i(0.);
+	}
+	if (limit_Y) if (limit_Y->Get_active())
+	{
+		limit_Y->constr_lower.Set_b_i(0.);
+		limit_Y->constr_upper.Set_b_i(0.);
+	}
+	if (limit_Z) if (limit_Z->Get_active())
+	{
+		limit_Z->constr_lower.Set_b_i(0.);
+		limit_Z->constr_upper.Set_b_i(0.);
+	}
+	if (limit_Rx) if (limit_Rx->Get_active())
+	{
+		limit_Rx->constr_lower.Set_b_i(0.);
+		limit_Rx->constr_upper.Set_b_i(0.);
+	}
+	if (limit_Ry) if (limit_Ry->Get_active())
+	{
+		limit_Ry->constr_lower.Set_b_i(0.);
+		limit_Ry->constr_upper.Set_b_i(0.);
+	}
+	if (limit_Rz) if (limit_Rz->Get_active())
+	{
+		limit_Rz->constr_lower.Set_b_i(0.);
+		limit_Rz->constr_upper.Set_b_i(0.);
+	}
+}
+
+void ChLinkLock::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	// parent
+	ChLinkMasked::ConstraintsBiLoad_C(factor, recovery_clamp, do_clamp);
+
+	if (limit_X) if (limit_X->Get_active())
+	{
+		if (limit_X->constr_lower.IsActive())
+			if (!do_clamp)
+				limit_X->constr_lower.Set_b_i(limit_X->constr_lower.Get_b_i()+factor*(-limit_X->Get_min()+relM.pos.x));
+			else
+				limit_X->constr_lower.Set_b_i(limit_X->constr_lower.Get_b_i()+ChMax (factor*(-limit_X->Get_min()+relM.pos.x), -recovery_clamp));
+		if (limit_X->constr_upper.IsActive())
+			if (!do_clamp)
+				limit_X->constr_upper.Set_b_i(limit_X->constr_upper.Get_b_i()-factor*(-limit_X->Get_max()+relM.pos.x));
+			else
+				limit_X->constr_upper.Set_b_i(limit_X->constr_upper.Get_b_i()-ChMax (factor*(-limit_X->Get_max()+relM.pos.x), -recovery_clamp));
+	}
+	if (limit_Y) if (limit_Y->Get_active())
+	{
+		if (limit_Y->constr_lower.IsActive())
+			if (!do_clamp)
+				limit_Y->constr_lower.Set_b_i(limit_Y->constr_lower.Get_b_i()+factor*(-limit_Y->Get_min()+relM.pos.y));
+			else
+				limit_Y->constr_lower.Set_b_i(limit_Y->constr_lower.Get_b_i()+ChMax (factor*(-limit_Y->Get_min()+relM.pos.y), -recovery_clamp));
+		if (limit_Y->constr_upper.IsActive())
+			if (!do_clamp)
+				limit_Y->constr_upper.Set_b_i(limit_Y->constr_upper.Get_b_i()-factor*(-limit_Y->Get_max()+relM.pos.y));
+			else
+				limit_Y->constr_upper.Set_b_i(limit_Y->constr_upper.Get_b_i()-ChMax (factor*(-limit_Y->Get_max()+relM.pos.y), -recovery_clamp));
+	}
+	if (limit_Z) if (limit_Z->Get_active())
+	{
+		if (limit_Z->constr_lower.IsActive())
+			if (!do_clamp)
+				limit_Z->constr_lower.Set_b_i(limit_Z->constr_lower.Get_b_i()+factor*(-limit_Z->Get_min()+relM.pos.z));
+			else
+				limit_Z->constr_lower.Set_b_i(limit_Z->constr_lower.Get_b_i()+ChMax (factor*(-limit_Z->Get_min()+relM.pos.z), -recovery_clamp));
+		if (limit_Z->constr_upper.IsActive())
+			if (!do_clamp)
+				limit_Z->constr_upper.Set_b_i(limit_Z->constr_upper.Get_b_i()-factor*(-limit_Z->Get_max()+relM.pos.z));
+		else
+				limit_Z->constr_upper.Set_b_i(limit_Z->constr_upper.Get_b_i()-ChMax (factor*(-limit_Z->Get_max()+relM.pos.z), -recovery_clamp));
+	}
+	if (limit_Rx) if (limit_Rx->Get_active())
+	{
+		if (limit_Rx->constr_lower.IsActive())
+			if (!do_clamp)
+				limit_Rx->constr_lower.Set_b_i(limit_Rx->constr_lower.Get_b_i()+factor*( - sin(0.5*limit_Rx->Get_min()) +relM.rot.e1));
+			else
+				limit_Rx->constr_lower.Set_b_i(limit_Rx->constr_lower.Get_b_i()+ChMax (factor*(- sin(0.5*limit_Rx->Get_min()) +relM.rot.e1), -recovery_clamp));
+		if (limit_Rx->constr_upper.IsActive())
+			if (!do_clamp)
+				limit_Rx->constr_upper.Set_b_i(limit_Rx->constr_upper.Get_b_i()-factor*(- sin(0.5*limit_Rx->Get_max()) +relM.rot.e1));
+		else
+				limit_Rx->constr_upper.Set_b_i(limit_Rx->constr_upper.Get_b_i()-ChMax (factor*(- sin(0.5*limit_Rx->Get_max()) +relM.rot.e1), -recovery_clamp));
+	}
+	if (limit_Ry) if (limit_Ry->Get_active())
+	{
+		if (limit_Ry->constr_lower.IsActive())
+			if (!do_clamp)
+				limit_Ry->constr_lower.Set_b_i(limit_Ry->constr_lower.Get_b_i()+factor*( - sin(0.5*limit_Ry->Get_min()) +relM.rot.e2));
+			else
+				limit_Ry->constr_lower.Set_b_i(limit_Ry->constr_lower.Get_b_i()+ChMax (factor*(- sin(0.5*limit_Ry->Get_min()) +relM.rot.e2), -recovery_clamp));
+		if (limit_Ry->constr_upper.IsActive())
+			if (!do_clamp)
+				limit_Ry->constr_upper.Set_b_i(limit_Ry->constr_upper.Get_b_i()-factor*(- sin(0.5*limit_Ry->Get_max()) +relM.rot.e2));
+		else
+				limit_Ry->constr_upper.Set_b_i(limit_Ry->constr_upper.Get_b_i()-ChMax (factor*(- sin(0.5*limit_Ry->Get_max()) +relM.rot.e2), -recovery_clamp));
+	}
+	if (limit_Rz) if (limit_Rz->Get_active())
+	{
+		if (limit_Rz->constr_lower.IsActive())
+			if (!do_clamp)
+				limit_Rz->constr_lower.Set_b_i(limit_Rz->constr_lower.Get_b_i()+factor*( - sin(0.5*limit_Rz->Get_min()) +relM.rot.e3));
+			else
+				limit_Rz->constr_lower.Set_b_i(limit_Rz->constr_lower.Get_b_i()+ChMax (factor*(- sin(0.5*limit_Rz->Get_min()) +relM.rot.e3), -recovery_clamp));
+		if (limit_Rz->constr_upper.IsActive())
+			if (!do_clamp)
+				limit_Rz->constr_upper.Set_b_i(limit_Rz->constr_upper.Get_b_i()-factor*(- sin(0.5*limit_Rz->Get_max()) +relM.rot.e3));
+		else
+				limit_Rz->constr_upper.Set_b_i(limit_Rz->constr_upper.Get_b_i()-ChMax (factor*(- sin(0.5*limit_Rz->Get_max()) +relM.rot.e3), -recovery_clamp));
+	}
+}
+
+void ChLinkLock::ConstraintsBiLoad_Ct(double factor)
+{
+	// parent
+	ChLinkMasked::ConstraintsBiLoad_Ct(factor);
+}
+
+void ChLinkLock::ConstraintsBiLoad_Qc(double factor)
+{
+	// parent 
+	ChLinkMasked::ConstraintsBiLoad_Qc(factor);
+}
+
+
+template <class Real>
+void Transform_Cq_to_Cqw_row(ChMatrix<>* mCq, int qrow, ChMatrix<Real>* mCqw, int qwrow, ChBody* mbody)
+{
+    // traslational part - not changed
+    mCqw->PasteClippedMatrix(mCq, qrow,0, 1,3, qwrow,0);
+
+    // rotational part [Cq_w] = [Cq_q]*[Gl]'*1/4
+    register int col, colres;
+    double sum;
+	ChMatrixNM<double,3,4> mGl;
+	ChFrame<>::SetMatrix_Gl(mGl, mbody->GetCoord().rot);
+    for (colres=0; colres < 3; colres++)    {
+            sum = 0;
+            for (col=0; col < 4; col++)         {
+                sum+= ((mCq->GetElement (qrow,col+3))*(mGl.GetElement (colres,col)));
+            }
+            mCqw->SetElement (qwrow, colres+3, (float)(sum * 0.25));
+    }
+}
+
+
+void ChLinkLock::ConstraintsLoadJacobians()
+{
+	// parent
+	ChLinkMasked::ConstraintsLoadJacobians();
+
+	if (limit_X) if (limit_X->Get_active())
+	{
+		limit_X->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_X->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		Transform_Cq_to_Cqw_row(Cq1_temp,0, limit_X->constr_lower.Get_Cq_a() ,0, Body1);
+		Transform_Cq_to_Cqw_row(Cq2_temp,0, limit_X->constr_lower.Get_Cq_b() ,0, Body2);
+		limit_X->constr_upper.Get_Cq_a()->CopyFromMatrix(*limit_X->constr_lower.Get_Cq_a());
+		limit_X->constr_upper.Get_Cq_b()->CopyFromMatrix(*limit_X->constr_lower.Get_Cq_b());
+		limit_X->constr_upper.Get_Cq_a()->MatrNeg();
+		limit_X->constr_upper.Get_Cq_b()->MatrNeg();
+	}
+	if (limit_Y) if (limit_Y->Get_active())
+	{
+		limit_Y->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Y->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		Transform_Cq_to_Cqw_row(Cq1_temp,1, limit_Y->constr_lower.Get_Cq_a() ,0, Body1);
+		Transform_Cq_to_Cqw_row(Cq2_temp,1, limit_Y->constr_lower.Get_Cq_b() ,0, Body2);
+		limit_Y->constr_upper.Get_Cq_a()->CopyFromMatrix(*limit_Y->constr_lower.Get_Cq_a());
+		limit_Y->constr_upper.Get_Cq_b()->CopyFromMatrix(*limit_Y->constr_lower.Get_Cq_b());
+		limit_Y->constr_upper.Get_Cq_a()->MatrNeg();
+		limit_Y->constr_upper.Get_Cq_b()->MatrNeg();
+	}
+	if (limit_Z) if (limit_Z->Get_active())
+	{
+		limit_Z->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Z->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		Transform_Cq_to_Cqw_row(Cq1_temp,2, limit_Z->constr_lower.Get_Cq_a() ,0, Body1);
+		Transform_Cq_to_Cqw_row(Cq2_temp,2, limit_Z->constr_lower.Get_Cq_b() ,0, Body2);
+		limit_Z->constr_upper.Get_Cq_a()->CopyFromMatrix(*limit_Z->constr_lower.Get_Cq_a());
+		limit_Z->constr_upper.Get_Cq_b()->CopyFromMatrix(*limit_Z->constr_lower.Get_Cq_b());
+		limit_Z->constr_upper.Get_Cq_a()->MatrNeg();
+		limit_Z->constr_upper.Get_Cq_b()->MatrNeg();
+	}
+	if (limit_Rx) if (limit_Rx->Get_active())
+	{
+		limit_Rx->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Rx->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		Transform_Cq_to_Cqw_row(Cq1_temp,4, limit_Rx->constr_lower.Get_Cq_a() ,0, Body1);
+		Transform_Cq_to_Cqw_row(Cq2_temp,4, limit_Rx->constr_lower.Get_Cq_b() ,0, Body2);
+		limit_Rx->constr_upper.Get_Cq_a()->CopyFromMatrix(*limit_Rx->constr_lower.Get_Cq_a());
+		limit_Rx->constr_upper.Get_Cq_b()->CopyFromMatrix(*limit_Rx->constr_lower.Get_Cq_b());
+		limit_Rx->constr_upper.Get_Cq_a()->MatrNeg();
+		limit_Rx->constr_upper.Get_Cq_b()->MatrNeg();
+	}
+	if (limit_Ry) if (limit_Ry->Get_active())
+	{
+		limit_Ry->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Ry->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		Transform_Cq_to_Cqw_row(Cq1_temp,5, limit_Ry->constr_lower.Get_Cq_a() ,0, Body1);
+		Transform_Cq_to_Cqw_row(Cq2_temp,5, limit_Ry->constr_lower.Get_Cq_b() ,0, Body2);
+		limit_Ry->constr_upper.Get_Cq_a()->CopyFromMatrix(*limit_Ry->constr_lower.Get_Cq_a());
+		limit_Ry->constr_upper.Get_Cq_b()->CopyFromMatrix(*limit_Ry->constr_lower.Get_Cq_b());
+		limit_Ry->constr_upper.Get_Cq_a()->MatrNeg();
+		limit_Ry->constr_upper.Get_Cq_b()->MatrNeg();
+	}
+	if (limit_Rz) if (limit_Rz->Get_active())
+	{
+		limit_Rz->constr_lower.SetVariables(&Body1->Variables(),&Body2->Variables());
+		limit_Rz->constr_upper.SetVariables(&Body1->Variables(),&Body2->Variables());
+		Transform_Cq_to_Cqw_row(Cq1_temp,6, limit_Rz->constr_lower.Get_Cq_a() ,0, Body1);
+		Transform_Cq_to_Cqw_row(Cq2_temp,6, limit_Rz->constr_lower.Get_Cq_b() ,0, Body2);
+		limit_Rz->constr_upper.Get_Cq_a()->CopyFromMatrix(*limit_Rz->constr_lower.Get_Cq_a());
+		limit_Rz->constr_upper.Get_Cq_b()->CopyFromMatrix(*limit_Rz->constr_lower.Get_Cq_b());
+		limit_Rz->constr_upper.Get_Cq_a()->MatrNeg();
+		limit_Rz->constr_upper.Get_Cq_b()->MatrNeg();
+	}
+}
+
+
+void ChLinkLock::ConstraintsFetch_react(double factor)
+{
+	// parent (from ChConstraint objects to react vector)
+	ChLinkMasked::ConstraintsFetch_react(factor);
+
+	// from react vector to the 'intuitive' react_force and react_torque
+	ChLinkMaskLF* mmask = (ChLinkMaskLF*) this->mask;
+	int n_costraint = 0;
+
+	if (mmask->Constr_X().IsActive()) {
+        react_force.x = - react->GetElement(n_costraint, 0);
+        n_costraint++ ; }
+    if (mmask->Constr_Y().IsActive()) {
+        react_force.y = - react->GetElement(n_costraint, 0);
+        n_costraint++ ; }
+    if (mmask->Constr_Z().IsActive()) {
+        react_force.z = - react->GetElement(n_costraint, 0);
+        n_costraint++ ; }
+    if (mmask->Constr_E1().IsActive()) {
+        react_torque.x = - 0.5* (react->GetElement(n_costraint, 0));
+        n_costraint++ ; }
+    if (mmask->Constr_E2().IsActive()) {
+        react_torque.y = - 0.5* (react->GetElement(n_costraint, 0));
+        n_costraint++ ; }
+    if (mmask->Constr_E3().IsActive()) {
+        react_torque.z = - 0.5* (react->GetElement(n_costraint, 0));
+        n_costraint++ ; }
+    if (mmask->Constr_P().IsActive()) {
+        react_torque.z = - 0.5* (react->GetElement(n_costraint, 0));
+        n_costraint++ ; }
+    if (mmask->Constr_D().IsActive()) {
+        react_force  = Vadd (react_force,
+            Vmul (Vnorm(relM.pos),- (react->GetElement(n_costraint, 0))));
+        n_costraint++ ; }
+
+    // ***TO DO***?: TRASFORMATION FROM delta COORDS TO LINK COORDS, if non-default delta
+    // if delta rotation?
+
+	// add also the contribute from link limits to the 'intuitive' react_force and 'react_torque'.
+	if (limit_X) if (limit_X->Get_active()) {
+		react_force.x -= factor*limit_X->constr_lower.Get_l_i();
+		react_force.x += factor*limit_X->constr_upper.Get_l_i();
+		}
+	if (limit_Y) if (limit_Y->Get_active()) {
+		react_force.y -= factor*limit_Y->constr_lower.Get_l_i();
+		react_force.y += factor*limit_Y->constr_upper.Get_l_i();
+		}
+	if (limit_Z) if (limit_Z->Get_active()) {
+		react_force.z -= factor*limit_Z->constr_lower.Get_l_i();
+		react_force.z += factor*limit_Z->constr_upper.Get_l_i();
+		}
+	if (limit_Rx) if (limit_Rx->Get_active()) {
+		react_torque.x -=  0.5*factor*limit_Rx->constr_lower.Get_l_i();
+		react_torque.x +=  0.5*factor*limit_Rx->constr_upper.Get_l_i();
+		}
+	if (limit_Ry) if (limit_Ry->Get_active()) {
+		react_torque.y -=  0.5*factor*limit_Ry->constr_lower.Get_l_i();
+		react_torque.y +=  0.5*factor*limit_Ry->constr_upper.Get_l_i();
+		}
+	if (limit_Rz) if (limit_Rz->Get_active()) {
+		react_torque.z -=  0.5*factor*limit_Rz->constr_lower.Get_l_i();
+		react_torque.z +=  0.5*factor*limit_Rz->constr_upper.Get_l_i();
+		}
+    // the internal forces add their contribute to the reactions
+    // NOT NEEDED?, since C_force and react_force must stay separated???
+    //react_force  = Vadd(react_force, C_force);
+    //react_torque = Vadd(react_torque, C_torque);
+}
+
+
+
+
+/////////
+///////// FILE I/O
+/////////
+
+void ChLinkLock::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(10);
+		// serialize parent class too
+	ChLinkMasked::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << type;
+	mstream.AbstractWrite(GetMotion_X());
+    mstream.AbstractWrite(GetMotion_Y());
+    mstream.AbstractWrite(GetMotion_Z());
+    mstream.AbstractWrite(GetMotion_ang());
+    mstream.AbstractWrite(GetMotion_ang2());
+    mstream.AbstractWrite(GetMotion_ang3());
+    mstream << motion_axis;
+    mstream << angleset;
+
+	mstream << *limit_X;
+    mstream << *limit_Y;
+    mstream << *limit_Z;
+    mstream << *limit_Rx;
+    mstream << *limit_Ry;
+    mstream << *limit_Rz;
+    mstream << *limit_Rp;
+    mstream << *limit_D;
+}
+
+void ChLinkLock::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkMasked::StreamIN(mstream);
+
+		// stream in all member data
+	// To restore mask array when loading finishes, (maybe following data loading changes mask..)
+    ChLinkMask* moriginalmask = this->mask->NewDuplicate();
+	int ifoo;
+	Vector vfoo;
+	ChFunction* ffoo;
+	mstream >> ifoo;					ChangeLinkType(ifoo);
+	mstream.AbstractReadCreate(&ffoo);	SetMotion_X(ffoo);
+    mstream.AbstractReadCreate(&ffoo);	SetMotion_Y(ffoo);
+    mstream.AbstractReadCreate(&ffoo);	SetMotion_Z(ffoo);
+    mstream.AbstractReadCreate(&ffoo);	SetMotion_ang(ffoo);
+    mstream.AbstractReadCreate(&ffoo);	SetMotion_ang2(ffoo);
+    mstream.AbstractReadCreate(&ffoo);	SetMotion_ang3(ffoo);
+    mstream >> vfoo;					SetMotion_axis(vfoo);
+    mstream >> ifoo;					Set_angleset(ifoo);
+	mstream >> *limit_X;
+    mstream >> *limit_Y;
+    mstream >> *limit_Z;
+    mstream >> *limit_Rx;
+    mstream >> *limit_Ry;
+    mstream >> *limit_Rz;
+    mstream >> *limit_Rp;
+    mstream >> *limit_D;
+
+	this->mask->Copy(moriginalmask);  // restore mask array, if ChangeLinkType() modified it..
+	this->ChangedLinkMask();
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkLock.h b/SRC/ChronoEngine/physics/ChLinkLock.h
new file mode 100644
index 0000000..9b02879
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkLock.h
@@ -0,0 +1,401 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKLOCK_H
+#define CHLINKLOCK_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkLock.h
+//
+//
+//   Classes for constraints using the 'link lock'
+//   formulation. Such formulation allows the 
+//   simulation of many joint types with the same
+//   formulas (spherical joint, revolute, and many
+//   others, etc) 
+//
+//   This class is inherited from the base ChLink()
+//   class, used by all joints in 3D.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkMasked.h"
+#include "physics/ChLimit.h"
+
+
+
+namespace chrono
+{
+
+// Unique link identifiers, for detecting type faster than with rtti.
+// Using GetLinkType(), you will get this information. Also, the ChLinkLock
+// family of constraints supports ChangeLinkType(), exceptionally.
+
+#define LNK_LOCK		0
+#define LNK_SPHERICAL	1
+#define LNK_POINTPLANE	2
+#define LNK_POINTLINE	3
+#define LNK_CYLINDRICAL	4
+#define LNK_PRISMATIC	5
+#define LNK_PLANEPLANE	6
+#define LNK_OLDHAM		7
+#define LNK_REVOLUTE	8
+#define LNK_RACKPIN		9
+#define LNK_FREE		10
+#define LNK_HOOK		11
+#define LNK_ALIGN	    13
+#define LNK_PARALLEL	14
+#define LNK_PERPEND		15
+#define LNK_UNIVERSAL	16
+#define LNK_COUPLER		18
+#define LNK_DISTANCE    19
+#define LNK_CARDANO		28
+
+
+///
+/// ChLinkLock class.
+/// This class implements lot of sub types like the revolute
+/// joint, the linear guide, the spherical joint, etc. using
+/// the 'lock formulation'.
+/// Also, it optionally allows the adoption of 'limits' over
+/// upper-lower motions on all the 6 degrees of freedom,
+/// thank to the ChLinkLimit objects. 
+///
+
+class ChApi ChLinkLock : public ChLinkMasked {
+
+	CH_RTTI(ChLinkLock,ChLinkMasked);
+
+protected:
+	Coordsys relC;		// relative costraint position: relC = (relM-deltaC)
+	Coordsys relC_dt;	// relative costraint speed
+	Coordsys relC_dtdt;	// relative costraint acceleration
+
+	Coordsys deltaC;	// user-imposed rel. position
+	Coordsys deltaC_dt;	// user-imposed rel. speed
+	Coordsys deltaC_dtdt;// user-imposed rel. acceleration
+
+						//(only for intermediate calculus)
+	ChMatrix<>* Cq1_temp;	//
+	ChMatrix<>* Cq2_temp;   //   the temporary "lock" jacobians,
+	ChMatrix<>* Qc_temp;	//   i.e. the full x,y,z,r0,r1,r2,r3 joint
+	Coordsys Ct_temp;	//
+
+	Vector PQw;			// for intermediate calculus (here, for speed reasons)
+	Vector PQw_dt;		// 
+	Vector PQw_dtdt;	//
+	Quaternion q_AD;
+	Quaternion q_BC;
+	Quaternion q_8;
+	Vector q_4;
+
+		// imposed motion
+	ChFunction* motion_X;	// user imposed motion for X coord, marker relative
+	ChFunction* motion_Y;	// user imposed motion for Y coord, marker relative
+	ChFunction* motion_Z;	// user imposed motion for Z coord, marker relative
+	ChFunction* motion_ang;	// user imposed angle rotation about axis
+	ChFunction* motion_ang2;// user imposed angle rotation if three-angles rot.
+	ChFunction* motion_ang3;// user imposed angle rotation if three-angles rot.
+	Vector		motion_axis;// this is the axis for the user imposed rotation
+	int			angleset;	// type of rotation (3 Eul angles, angle/axis, etc.)
+		// limits
+	ChLinkLimit* limit_X;	// the upper/lower limits for X dof
+	ChLinkLimit* limit_Y;	// the upper/lower limits for Y dof
+	ChLinkLimit* limit_Z;	// the upper/lower limits for Z dof
+	ChLinkLimit* limit_Rx;// the upper/lower limits for Rx dof
+	ChLinkLimit* limit_Ry;// the upper/lower limits for Ry dof
+	ChLinkLimit* limit_Rz;// the upper/lower limits for Rz dof
+	ChLinkLimit* limit_Rp;// the polar (conical) limit for "shoulder"rotation
+	ChLinkLimit* limit_D; // the polar (conical) limit for "shoulder"rotation
+
+	int type;
+
+public:
+						// builders and destroyers
+	ChLinkLock ();
+	virtual ~ChLinkLock ();
+	virtual void Copy(ChLinkLock* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+	void BuildLinkType (int link_type);
+
+	void ChangeLinkType (int new_link_type);
+
+	void Set2Dmode(int mode);  // mode=1 use only constraints for 2D xy plane, mode=0 switch back to 3D.
+
+	virtual int GetType	() {return this->type;}
+
+
+
+			//
+			// UPDATING FUNCTIONS
+			//
+							// Inherits, and also updates motion laws: deltaC, deltaC_dt, deltaC_dtdt
+	virtual void UpdateTime (double mytime);
+
+							// Updates coords relM, relM_dt, relM_dtdt;
+							// dist, dist_dt et similia, just like in parent class, but
+							// overrides parent implementation of ChLinkMarkers because it can save some
+							// temporary vectors (q_4, q_8 etc.) which can be useful in UpdateState(),
+							// for speed reasons.
+	virtual void UpdateRelMarkerCoords();
+
+							// Given current time and body state, computes
+							// the constraint differentiation to get the
+							// the state matrices     Cq1,  Cq2,  Qc,  Ct , and also
+							// C, C_dt, C_dtd.   ie. the JACOBIAN matrices and friends.
+							//  NOTE!! this function uses the fast analytical approach
+							// of the "lock formulation".
+	virtual void UpdateState ();
+
+							// Inherits, and also updates the local F,M forces adding penalties from 
+							// the contained link ChLinkLimit objects, if any.
+	virtual void UpdateForces (double mytime);
+
+
+
+			//
+			// OTHER FUNCTIONS
+			//
+
+
+						// constraint violations in pos/rot coordinates
+	Coordsys GetRelC () {return relC;}
+	Coordsys GetRelC_dt () {return relC_dt;}
+	Coordsys GetRelC_dtdt () {return relC_dtdt;}
+
+						// to get the imposed clearances
+	Coordsys GetDeltaC () {return deltaC;}
+	Coordsys GetDeltaC_dt () {return deltaC_dt;}
+	Coordsys GetDeltaC_dtdt () {return deltaC_dtdt;}
+						// to set the imposed clearances (best use SetMotion() if you can..)
+	void SetDeltaC (Coordsys mc) {deltaC = mc;}
+	void SetDeltaC_dt (Coordsys mc) {deltaC_dt = mc;}
+	void SetDeltaC_dtdt (Coordsys mc) {deltaC_dtdt = mc;}
+
+						// for the imposed motion functions
+	ChFunction* GetMotion_X() {return motion_X;};
+	ChFunction* GetMotion_Y() {return motion_Y;};
+	ChFunction* GetMotion_Z() {return motion_Z;};
+	ChFunction* GetMotion_ang()  {return motion_ang;};
+	ChFunction* GetMotion_ang2() {return motion_ang2;};
+	ChFunction* GetMotion_ang3() {return motion_ang3;};
+	Vector		GetMotion_axis() {return motion_axis;};
+	void SetMotion_X	(ChFunction* m_funct);
+	void SetMotion_Y	(ChFunction* m_funct);
+	void SetMotion_Z	(ChFunction* m_funct);
+	void SetMotion_ang	(ChFunction* m_funct);
+	void SetMotion_ang2	(ChFunction* m_funct);
+	void SetMotion_ang3	(ChFunction* m_funct);
+	void SetMotion_axis (Vector m_axis);
+	int   Get_angleset() {return angleset;};
+	void  Set_angleset(int mset) {angleset = mset;}
+
+						// for the limits on free degrees
+	ChLinkLimit* GetLimit_X()  {return limit_X;}
+	ChLinkLimit* GetLimit_Y()  {return limit_Y;}
+	ChLinkLimit* GetLimit_Z()  {return limit_Z;}
+	ChLinkLimit* GetLimit_Rx() {return limit_Rx;}
+	ChLinkLimit* GetLimit_Ry() {return limit_Ry;}
+	ChLinkLimit* GetLimit_Rz() {return limit_Rz;}
+	ChLinkLimit* GetLimit_Rp() {return limit_Rp;}
+	ChLinkLimit* GetLimit_D()  {return limit_D;}
+	void SetLimit_X  (ChLinkLimit* m_limit_X)  {if (limit_X) delete limit_X; limit_X = m_limit_X;}
+	void SetLimit_Y  (ChLinkLimit* m_limit_Y)  {if (limit_Y) delete limit_Y; limit_Y = m_limit_Y;}
+	void SetLimit_Z  (ChLinkLimit* m_limit_Z)  {if (limit_Z) delete limit_Z; limit_Z = m_limit_Z;}
+	void SetLimit_Rx (ChLinkLimit* m_limit_Rx) {if (limit_Rx)delete limit_Rx; limit_Rx = m_limit_Rx;}
+	void SetLimit_Ry (ChLinkLimit* m_limit_Ry) {if (limit_Ry)delete limit_Ry; limit_Ry = m_limit_Ry;}
+	void SetLimit_Rz (ChLinkLimit* m_limit_Rz) {if (limit_Rz)delete limit_Rz; limit_Rz = m_limit_Rz;}
+	void SetLimit_Rp (ChLinkLimit* m_limit_Rp) {if (limit_Rp)delete limit_Rp; limit_Rp = m_limit_Rp;}
+	void SetLimit_D  (ChLinkLimit* m_limit_D)  {if (limit_D) delete limit_D ; limit_D  = m_limit_D;}
+
+
+			//
+			// LCP SYSTEM FUNCTIONS   ( functions to assembly/manage data for system solver)
+			//
+						// expand parent constraint stuff from ChLinkMasked because here 
+						// it may also consider the	constraints caused by 'limits'..
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsBiLoad_Qc(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+			//
+			// STREAMING
+			//
+
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+// SOME WRAPPER CLASSES, TO MAKE 'LINK LOCK' CREATION EASIER...
+
+/// Revolute joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockRevolute : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockRevolute,ChLinkLock);
+public:
+	ChLinkLockRevolute() {ChangeLinkType(LNK_REVOLUTE);}
+};
+
+/// 6-dof locked joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockLock : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockLock,ChLinkLock);
+public:
+	ChLinkLockLock() {ChangeLinkType(LNK_LOCK);}
+};
+
+/// spherical joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockSpherical : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockSpherical,ChLinkLock);
+public:
+	ChLinkLockSpherical() {ChangeLinkType(LNK_SPHERICAL);}
+};
+
+/// cylindrical joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockCylindrical : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockCylindrical,ChLinkLock);
+public:
+	ChLinkLockCylindrical() {ChangeLinkType(LNK_CYLINDRICAL);}
+};
+
+/// prismatic joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockPrismatic : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockPrismatic,ChLinkLock);
+public:
+	ChLinkLockPrismatic() {ChangeLinkType(LNK_PRISMATIC);}
+};
+
+/// point-plane joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockPointPlane : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockPointPlane,ChLinkLock);
+public:
+	ChLinkLockPointPlane() {ChangeLinkType(LNK_POINTPLANE);}
+};
+
+/// point-line joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockPointLine : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockPointLine,ChLinkLock);
+public:
+	ChLinkLockPointLine() {ChangeLinkType(LNK_POINTLINE);}
+};
+
+/// plane-plane joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockPlanePlane : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockPlanePlane,ChLinkLock);
+public:
+	ChLinkLockPlanePlane() {ChangeLinkType(LNK_PLANEPLANE);}
+};
+
+/// oldham joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockOldham : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockOldham,ChLinkLock);
+public:
+	ChLinkLockOldham() {ChangeLinkType(LNK_OLDHAM);}
+};
+
+/// free joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockFree : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockFree,ChLinkLock);
+public:
+	ChLinkLockFree() {ChangeLinkType(LNK_FREE);}
+};
+
+/// 'hook' joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockHook : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockHook,ChLinkLock);
+public:
+	ChLinkLockHook() {ChangeLinkType(LNK_HOOK);}
+};
+
+/// align joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockAlign : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockAlign,ChLinkLock);
+public:
+	ChLinkLockAlign() {ChangeLinkType(LNK_ALIGN);}
+};
+
+/// parallel joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockParallel : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockParallel,ChLinkLock);
+public:
+	ChLinkLockParallel() {ChangeLinkType(LNK_PARALLEL);}
+};
+
+/// perpendicularity joint , with the 'ChLinkLock' formulation.
+/// (allows a simplier creation of a link as a sub-type of ChLinkLock). 
+
+class ChApi ChLinkLockPerpend : public ChLinkLock 
+{
+	CH_RTTI(ChLinkLockPerpend,ChLinkLock);
+public:
+	ChLinkLockPerpend() {ChangeLinkType(LNK_PERPEND);}
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkMarkers.cpp b/SRC/ChronoEngine/physics/ChLinkMarkers.cpp
new file mode 100644
index 0000000..b6c44c8
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMarkers.cpp
@@ -0,0 +1,619 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMarkers.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkMarkers.h"
+//#include "physics/ChCollide.h"
+#include "physics/ChExternalObject.h"
+
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMarkers> a_registration_ChLinkMarkers;
+
+
+                // BUILDERS
+ChLinkMarkers::ChLinkMarkers ()
+{
+    marker1= NULL;
+    marker2= NULL;
+
+    markID1 = 0;
+    markID2 = 0;
+
+    relM = CSYSNORM;
+    relM_dt = CSYSNULL;
+    relM_dtdt = CSYSNULL;
+	relAngle=0;
+	relRotaxis=relWvel=relWacc=VNULL;
+	dist=dist_dt=0;
+
+	C_force = VNULL;
+    C_torque = VNULL;
+
+    Scr_force = VNULL;
+    Scr_torque = VNULL;
+}
+
+
+
+            // DESTROYER
+ChLinkMarkers::~ChLinkMarkers ()
+{
+
+}
+
+
+void ChLinkMarkers::Copy(ChLinkMarkers* source)
+{
+    // first copy the parent class data...
+    ChLink::Copy(source);
+
+    marker1 = 0;
+    marker2 = 0;
+
+    markID1 = source->markID1;
+    markID2 = source->markID2;
+
+    relM = source->relM;            // copy vars
+    relM_dt = source->relM_dt;
+    relM_dtdt = source->relM_dtdt;
+    relAngle = source->relAngle;
+    relRotaxis = source->relRotaxis;
+    relAxis = source->relAxis;
+    relWvel = source->relWvel;
+    relWacc = source->relWacc;
+    dist = source->dist;
+    dist_dt = source->dist_dt;
+
+    C_force = source->C_force;
+    C_torque = source->C_torque;
+
+    Scr_force = source->Scr_force;
+    Scr_torque = source->Scr_torque;
+}
+
+
+ChLink* ChLinkMarkers::new_Duplicate ()   // inherited classes:  Link* MyInheritedLink::new_Duplicate()
+{
+    ChLink* m_l;
+    m_l = new ChLinkMarkers;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+
+void ChLinkMarkers::SetMarker1 (ChMarker* mark1)
+{
+    marker1 = mark1;
+    if (mark1)
+        Body1=(ChBody*) mark1->GetBody();
+    else
+        Body1= NULL;
+}
+
+void ChLinkMarkers::SetMarker2 (ChMarker* mark2)
+{
+    marker2 = mark2;
+    if (mark2)
+        Body2=(ChBody*) mark2->GetBody();
+    else
+        Body2= NULL;
+}
+
+
+void ChLinkMarkers::SetMarkers (ChMarker* mark1, ChMarker* mark2)
+{
+    SetMarker1 (mark1);
+    SetMarker2 (mark2);
+}
+
+int ChLinkMarkers::ReferenceMarkers(ChMarker* mark1, ChMarker* mark2)
+{
+	this->SetMarkers (mark1, mark2);
+
+	if (mark1)
+		SetMarkID1(mark1->GetIdentifier());
+	else SetMarkID1(0);
+	if (mark2)
+		SetMarkID2(mark2->GetIdentifier());
+	else SetMarkID2(0);
+
+	if (mark1 && mark2) return TRUE;
+	return FALSE;
+}
+
+
+int ChLinkMarkers::Initialize(ChSharedPtr<ChMarker>& mmark1, ChSharedPtr<ChMarker>& mmark2)
+{
+	ChMarker* mm1 = mmark1.get_ptr();
+	ChMarker* mm2 = mmark2.get_ptr();
+	assert(mm1 && mm2);
+	assert(mm1 != mm2);
+	assert(mm1->GetBody() && mm2->GetBody());
+	assert(mm1->GetBody()->GetSystem() == mm2->GetBody()->GetSystem());
+
+	ReferenceMarkers(mm1, mm2);
+	SetSystem(this->Body1->GetSystem());
+	return true;
+}
+	
+int ChLinkMarkers::Initialize(ChSharedPtr<ChBody>& mbody1, ChSharedPtr<ChBody>& mbody2,  ChCoordsys<> mpos)
+{
+	return Initialize(mbody1,mbody2,false,mpos,mpos);
+	
+}
+
+int ChLinkMarkers::Initialize(ChSharedPtr<ChBody>& mbody1, ChSharedPtr<ChBody>& mbody2, bool pos_are_relative, ChCoordsys<> mpos1, ChCoordsys<> mpos2)
+{
+	assert(mbody1.get_ptr() != mbody2.get_ptr());
+	assert(mbody1->GetSystem() == mbody2->GetSystem());
+	
+	// create markers to add to the two bodies
+	ChSharedPtr<ChMarker> mmark1(new ChMarker);
+	ChSharedPtr<ChMarker> mmark2(new ChMarker);
+	mbody1->AddMarker(mmark1);
+	mbody2->AddMarker(mmark2);
+	
+	ChMarker* mm1 = mmark1.get_ptr();
+	ChMarker* mm2 = mmark2.get_ptr();
+	ReferenceMarkers(mm1, mm2);
+
+	SetSystem(this->Body1->GetSystem());	
+	
+	if (pos_are_relative)
+	{
+		mmark1->Impose_Rel_Coord(mpos1);
+		mmark2->Impose_Rel_Coord(mpos2);
+	}
+	else
+	{
+		mmark1->Impose_Abs_Coord(mpos1);
+		mmark2->Impose_Abs_Coord(mpos2);
+	}
+
+	return true;
+}
+
+
+
+void ChLinkMarkers::SwapMainSlaveMarkers()
+{
+    ChMarker* tempmarker;
+    tempmarker = marker1;
+    SetMarker1(marker2);
+    SetMarker2(tempmarker);
+
+    int tempid;
+    tempid = markID1;
+    markID1 = markID2;
+    markID2 = tempid;
+}
+
+ 
+
+
+
+
+////////////////////////////////////
+///
+///    UPDATING PROCEDURES
+
+
+
+
+
+
+/////////      UPDATE RELATIVE MARKER COORDINATES
+/////////
+
+void ChLinkMarkers::UpdateRelMarkerCoords()
+{
+    // FOR ALL THE 6(or3) COORDINATES OF RELATIVE MOTION OF THE TWO MARKERS:
+    // COMPUTE THE relM, relM_dt relM_dtdt COORDINATES, AND AUXILIARY DATA (distance,etc.)
+
+
+    Vector PQw = Vsub (marker1->GetAbsCoord().pos, marker2->GetAbsCoord().pos);
+    Vector PQw_dt = Vsub (marker1->GetAbsCoord_dt().pos, marker2->GetAbsCoord_dt().pos);
+    Vector PQw_dtdt = Vsub (marker1->GetAbsCoord_dtdt().pos, marker2->GetAbsCoord_dtdt().pos);
+
+    dist    = Vlenght (PQw);                // distance between origins, modulus
+    dist_dt = Vdot (Vnorm(PQw), PQw_dt);    // speed between origins, modulus.
+
+    Vector vtemp1;       // for intermediate calculus
+    Vector vtemp2;
+    Quaternion qtemp1;
+
+    ChMatrixNM<double,3,4> relGw;
+    Quaternion q_AD;
+    Quaternion q_BC;
+    Quaternion q_8;
+    Vector q_4;
+
+    Quaternion temp1=marker2->GetCoord_dt().rot;
+    Quaternion temp2=marker2->GetCoord_dt().rot;
+
+
+    if ((Qnotnull(&temp1))||
+        (Qnotnull(&temp2)) )
+    {
+      q_AD =                    //  q'qqq + qqqq'
+       Qadd (
+        Qcross (
+          Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord().rot)
+          ))),
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord_dt().rot)
+          )))
+        );
+    }
+    else
+        q_AD=QNULL;
+
+    q_BC =                  // qq'qq + qqq'q
+       Qadd (
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord_dt().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord().rot)
+          ))),
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord_dt().rot),
+          (marker1->GetCoord().rot)
+          )))
+       );
+
+                            // q_8 = q''qqq + 2q'q'qq + 2q'qq'q + 2q'qqq'
+                            //     + 2qq'q'q + 2qq'qq' + 2qqq'q' + qqqq''
+    temp2=marker2->GetCoord_dtdt().rot;
+    if (Qnotnull(&temp2))
+    q_8=Qcross(Qconjugate(marker2->GetCoord_dtdt().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord().rot)));        // q_dtdt'm2 * q'o2 * q,o1 * q,m1
+    else
+    q_8 = QNULL;
+    temp1=marker1->GetCoord_dtdt().rot;
+    if (Qnotnull(&temp1))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord_dtdt().rot)));   // q'm2 * q'o2 * q,o1 * q_dtdt,m1
+     q_8= Qadd (q_8, qtemp1);
+    }
+    temp2=marker2->GetCoord_dt().rot;
+    if (Qnotnull(&temp2))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dt().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord().rot)));
+     qtemp1= Qscale (qtemp1, 2);                // 2( q_dt'm2 * q_dt'o2 * q,o1 * q,m1)
+     q_8= Qadd (q_8, qtemp1);
+    }
+    temp2=marker2->GetCoord_dt().rot;
+    if (Qnotnull(&temp2))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord_dt().rot,
+        marker1->GetCoord().rot)));
+     qtemp1= Qscale (qtemp1, 2);                // 2( q_dt'm2 * q'o2 * q_dt,o1 * q,m1)
+     q_8= Qadd (q_8, qtemp1);
+    }
+    temp1=marker1->GetCoord_dt().rot;
+    temp2=marker2->GetCoord_dt().rot;
+    if ((Qnotnull(&temp2))&&
+        (Qnotnull(&temp1)))
+    {
+     qtemp1=Qcross(Qconjugate(marker2->GetCoord_dt().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord_dt().rot)));
+     qtemp1= Qscale (qtemp1, 2);                // 2( q_dt'm2 * q'o2 * q,o1 * q_dt,m1)
+     q_8= Qadd (q_8, qtemp1);
+    }
+
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dt().rot),
+        Qcross(Body1->GetCoord_dt().rot,
+        marker1->GetCoord().rot)));
+    qtemp1= Qscale (qtemp1, 2);             // 2( q'm2 * q_dt'o2 * q_dt,o1 * q,m1)
+    q_8= Qadd (q_8, qtemp1);
+    temp1=marker1->GetCoord_dt().rot;
+    if (Qnotnull(&temp1))
+    {
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dt().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord_dt().rot)));
+    qtemp1= Qscale (qtemp1, 2);             // 2( q'm2 * q_dt'o2 * q,o1 * q_dt,m1)
+    q_8= Qadd (q_8, qtemp1);
+    }
+    temp1=marker1->GetCoord_dt().rot;
+    if (Qnotnull(&temp1))
+    {
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord_dt().rot,
+        marker1->GetCoord_dt().rot)));
+    qtemp1= Qscale (qtemp1, 2);             // 2( q'm2 * q'o2 * q_dt,o1 * q_dt,m1)
+    q_8= Qadd (q_8, qtemp1);
+    }
+
+                                // q_4 = [Adtdt]'[A]'q + 2[Adt]'[Adt]'q
+                                //       + 2[Adt]'[A]'qdt + 2[A]'[Adt]'qdt
+	ChMatrix33<> m2_Rel_A_dt;
+	marker2->Compute_Adt(m2_Rel_A_dt);
+	ChMatrix33<> m2_Rel_A_dtdt;
+	marker2->Compute_Adtdt(m2_Rel_A_dtdt);
+
+    vtemp1=Body2->GetA_dt().MatrT_x_Vect(PQw);
+    vtemp2=m2_Rel_A_dt.MatrT_x_Vect(vtemp1);
+    q_4= Vmul (vtemp2, 2);          // 2[Aq_dt]'[Ao2_dt]'*Qpq,w
+
+    vtemp1=Body2->GetA()->MatrT_x_Vect(PQw_dt);
+    vtemp2=m2_Rel_A_dt.MatrT_x_Vect(vtemp1);
+    vtemp2= Vmul (vtemp2, 2);       // 2[Aq_dt]'[Ao2]'*Qpq,w_dt
+    q_4= Vadd (q_4, vtemp2);
+
+    vtemp1=Body2->GetA_dt().MatrT_x_Vect(PQw_dt);
+    vtemp2=marker2->GetA()->MatrT_x_Vect(vtemp1);
+    vtemp2= Vmul (vtemp2, 2);       // 2[Aq]'[Ao2_dt]'*Qpq,w_dt
+    q_4= Vadd (q_4, vtemp2);
+
+    vtemp1=Body2->GetA()->MatrT_x_Vect(PQw);
+    vtemp2=m2_Rel_A_dtdt.MatrT_x_Vect(vtemp1);
+    q_4= Vadd (q_4, vtemp2);        //  [Aq_dtdt]'[Ao2]'*Qpq,w
+
+
+
+            // ----------- RELATIVE MARKER COORDINATES
+
+            // relM.pos
+    relM.pos =
+        marker2->GetA()->MatrT_x_Vect(
+        Body2->GetA()->MatrT_x_Vect(PQw));
+
+            // relM.rot
+    relM.rot =
+        Qcross (
+          Qconjugate(marker2->GetCoord().rot),
+        Qcross (
+          Qconjugate(marker2->GetBody()->GetCoord().rot),
+        Qcross (
+          (marker1->GetBody()->GetCoord().rot),
+          (marker1->GetCoord().rot)
+          )));
+
+            // relM_dt.pos
+    relM_dt.pos =
+        Vadd (
+        Vadd (
+        m2_Rel_A_dt.MatrT_x_Vect(
+        Body2->GetA()->MatrT_x_Vect(PQw)) ,
+        marker2->GetA()->MatrT_x_Vect(
+        Body2->GetA_dt().MatrT_x_Vect(PQw))),
+        marker2->GetA()->MatrT_x_Vect(
+        Body2->GetA()->MatrT_x_Vect(PQw_dt)));
+
+            // relM_dt.rot
+    relM_dt.rot =
+       Qadd ( q_AD, q_BC );
+
+            // relM_dtdt.pos
+    relM_dtdt.pos =
+        Vadd (
+        Vadd (
+        marker2->GetA()->MatrT_x_Vect(
+         Body2->GetA_dtdt().MatrT_x_Vect(PQw)),
+        marker2->GetA()->MatrT_x_Vect(
+         Body2->GetA()->MatrT_x_Vect(PQw_dtdt))),
+        q_4);
+
+
+            // relM_dtdt.rot
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord_dtdt().rot),
+        Qcross(Body1->GetCoord().rot,
+        marker1->GetCoord().rot)));    // ( q'm2 * q_dtdt'o2 * q,o1 * q,m1)
+    relM_dtdt.rot= Qadd (q_8, qtemp1);
+    qtemp1=Qcross(Qconjugate(marker2->GetCoord().rot),
+        Qcross(Qconjugate(Body2->GetCoord().rot),
+        Qcross(Body1->GetCoord_dtdt().rot,
+        marker1->GetCoord().rot)));    // ( q'm2 * q'o2 * q_dtdt,o1 * q,m1)
+    relM_dtdt.rot= Qadd (relM_dtdt.rot, qtemp1);    // = q_8 + qq''qq + qqq''q
+
+
+                // ... and also "user-friendly" relative coordinates:
+
+            // relAngle and relAxis
+    Q_to_AngAxis (&relM.rot, &relAngle, &relAxis);
+        // flip rel rotation axis if jerky sign
+    if (relAxis.z < 0)
+    {
+        relAxis = Vmul (relAxis, -1);
+        relAngle = -relAngle;
+    }
+            // rotation axis
+    relRotaxis = Vmul(relAxis, relAngle);
+            // relWvel
+	ChFrame<>::SetMatrix_Gw(relGw, relM.rot); //relGw.Set_Gw_matrix(relM.rot);
+    relWvel = relGw.Matr34_x_Quat (relM_dt.rot);
+            // relWacc
+    relWacc = relGw.Matr34_x_Quat (relM_dtdt.rot);
+
+}
+
+
+/////////      UPDATE FORCES
+///////// 
+
+void ChLinkMarkers::UpdateForces(double mytime)
+{
+    C_force = VNULL;    // initialize int.forces accumulators
+    C_torque = VNULL;
+
+    // First and only operation: add the 'externally set' script forces (torques)
+    C_force  = Vadd(C_force,  Scr_force);
+    C_torque = Vadd(C_torque, Scr_torque);
+}
+
+
+
+
+/////////
+/////////   COMPLETE UPDATE
+/////////
+/////////
+
+void ChLinkMarkers::Update (double time)
+{
+    // 1 -
+    UpdateTime(time);
+
+    // 2 -
+    UpdateRelMarkerCoords();
+
+    // 3 -
+    UpdateForces(time);
+
+}
+
+
+
+/////////
+///////// LCP INTERFACE
+/////////
+
+
+void ChLinkMarkers::ConstraintsFbLoadForces(double factor)
+{
+	if(!Body1 || !Body2)
+		return;
+
+	Vector mbody_force;
+	Vector mbody_torque;
+	if (Vnotnull(&C_force))
+    {
+        Vector m_abs_force = Body2->GetA()->Matr_x_Vect(marker2->GetA()->Matr_x_Vect(C_force));
+		Body2->To_abs_forcetorque(m_abs_force,
+								  marker1->GetAbsCoord().pos,	// absolute application point is always marker1 
+								  FALSE,						// from abs. space
+								  mbody_force, mbody_torque);	// resulting force-torque, both in abs coords
+		Body2->Variables().Get_fb().PasteSumVector( mbody_force * -factor , 0,0);
+		Body2->Variables().Get_fb().PasteSumVector( Body2->Dir_World2Body(&mbody_torque) * -factor , 3,0);
+
+		Body1->To_abs_forcetorque(m_abs_force,
+								  marker1->GetAbsCoord().pos,	// absolute application point is always marker1 
+								  FALSE,						// from abs. space
+								  mbody_force, mbody_torque);	// resulting force-torque, both in abs coords
+		Body1->Variables().Get_fb().PasteSumVector( mbody_force *  factor , 0,0);
+		Body1->Variables().Get_fb().PasteSumVector( Body1->Dir_World2Body(&mbody_torque) *  factor , 3,0);	
+	}
+	if (Vnotnull(&C_torque))
+    {
+        Vector m_abs_torque = Body2->GetA()->Matr_x_Vect(marker2->GetA()->Matr_x_Vect(C_torque));
+			// load torques in 'fb' vector accumulator of body variables (torques in local coords)
+		Body1->Variables().Get_fb().PasteSumVector( Body1->Dir_World2Body(&m_abs_torque) *  factor , 3,0);
+		Body2->Variables().Get_fb().PasteSumVector( Body2->Dir_World2Body(&m_abs_torque) * -factor , 3,0);
+	}
+
+}
+
+
+
+
+/////////
+///////// FILE I/O
+/////////
+
+
+
+
+void ChLinkMarkers::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(10);
+		// serialize parent class too
+	ChLink::StreamOUT(mstream);
+
+		// stream out all member data
+    mstream << markID1;
+    mstream << markID2;
+}
+
+void ChLinkMarkers::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLink::StreamIN(mstream);
+
+		// stream in all member data
+    mstream >> markID1;
+    mstream >> markID2;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkMarkers.h b/SRC/ChronoEngine/physics/ChLinkMarkers.h
new file mode 100644
index 0000000..d1b7aaf
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMarkers.h
@@ -0,0 +1,280 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKMARKERS_H
+#define CHLINKMARKERS_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMarkers.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLink.h"
+#include "physics/ChMarker.h"
+
+
+
+namespace chrono
+{
+
+
+
+///
+/// Class for links which connect two 'markers'. The markers are two
+/// ChMarker objects each belonging to the two linked ChBody parts.
+/// Many specialized classes are based on this ChLinkMarkers class, for example
+/// the ChLinkSpring and all the family of the ChLinkLock classes - see them-.
+/// Also, ChLinkMarkers class allows an optional force vector and torque vector
+/// to be set between the two connected markers.
+///
+
+class ChApi ChLinkMarkers : public ChLink {
+
+	CH_RTTI(ChLinkMarkers,ChLink);
+
+protected:
+
+				//
+	  			// DATA
+				//
+
+	ChMarker* marker1;	// slave coordsys
+	ChMarker* marker2;	// master coordsys, =0 if liked to ground
+
+	int markID1;		// unique identifier for markers 1 & 2,
+	int markID2;		// when using plugin dynamic hierarchies
+
+	Coordsys relM;		// relative marker position 2-1
+	Coordsys relM_dt;	// relative marker speed
+	Coordsys relM_dtdt; // relative marker acceleration
+
+	double relAngle;	// relative angle of rotation
+	Vector relAxis;		// relative axis of rotation
+	Vector relRotaxis;	// relative rotaion vector =angle*axis
+	Vector relWvel;		// relative angular speed
+	Vector relWacc;		// relative angular acceleration
+	double dist;		// the distance between the two origins of markers,
+	double dist_dt;		// the speed between the two  origins of markers
+
+	Vector Scr_force;	// internal force  set by script only (just added to C_force)
+	Vector Scr_torque;	// internal torque set by script only (just added to C_force)
+	Vector C_force;		// internal force  applied by springs/dampers/actuators
+	Vector C_torque;	// internal torque applied by springs/dampers/actuators
+
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+	ChLinkMarkers ();
+	virtual ~ChLinkMarkers ();
+	virtual void Copy(ChLinkMarkers* source);
+	virtual ChLink* new_Duplicate ();  
+
+
+public:
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Get the type identifier of this link. Use if you don't want to use RTTI for performance.
+	virtual int GetType	() {return LNK_BASE;}
+
+					/// Return the 1st referenced marker (the 'slave' marker, owned by 1st body)
+	ChMarker* GetMarker1 () {return marker1;}
+					/// Return the 2nd referenced marker (the 'master' marker, owned by 2nd body)
+	ChMarker* GetMarker2 () {return marker2;}
+					/// Set the 1st referenced marker (the 'slave' marker, owned by 1st body)
+	virtual void SetMarker1 (ChMarker* mark1);
+					/// Set the 2nd referenced marker (the 'master' marker, owned by 2nd body)
+	virtual void SetMarker2 (ChMarker* mark2);
+					/// Set both constrained markers at once. Note that also Body1 and Body2 are
+					/// automatically set (they are of course the owners of the two markers)
+	void SetMarkers (ChMarker* mark1, ChMarker* mark2);
+					/// Exchange the master and the slave marker. The same happens for 
+					/// body1 and body2, automatically.
+	void SwapMainSlaveMarkers();
+					
+	void SetMarkID1(int mid) {markID1 = mid;}
+	void SetMarkID2(int mid) {markID2 = mid;}
+	int GetMarkID1() {return markID1;}
+	int GetMarkID2() {return markID2;}
+
+					/// Shortcut: performs  SetMarkers(), and SetMarkID1() SetMarkID2() at once.
+	int ReferenceMarkers(ChMarker* mark1, ChMarker* mark2);
+
+					/// Use this function after link creation, to initialize the link from 
+					/// two markers to join. 
+					/// Each marker must belong to a rigid body, and both rigid bodies 
+					/// must belong to the same ChSystem. 
+					/// The position of mark2 is used as link's position and main reference.
+	virtual int Initialize(ChSharedPtr<ChMarker>& mark1, ///< first  marker to join
+						   ChSharedPtr<ChMarker>& mark2	 ///< second marker to join (master)
+						   );
+
+					/// Use this function after link creation, to initialize the link from 
+					/// two joined rigid bodies. 
+					/// Both rigid bodies must belong to the same ChSystem. 
+					/// Two markers will be created and added to the rigid bodies (later,
+					/// you can use GetMarker1() and GetMarker2() to access them.
+					/// To specify the (absolute) position of link and markers, use 'mpos'.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1, ///< first  body to join
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to join 
+						   ChCoordsys<> mpos		///< the current absolute pos.& alignment.
+						   );
+
+					/// Use this function after link creation, to initialize the link from 
+					/// two joined rigid bodies. 
+					/// Both rigid bodies must belong to the same ChSystem. 
+					/// Two markers will be created and added to the rigid bodies (later,
+					/// you can use GetMarker1() and GetMarker2() to access them.
+					/// To specify the (absolute) position of link and markers, use 'mpos'.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1, ///< first  body to join
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to join  
+						   bool pos_are_relative,	///< if =true, following two positions are relative to bodies. If false, are absolute.
+						   ChCoordsys<> mpos1, 		///< the position & alignment of 1st marker (relative to body1 cords, or absolute)
+						   ChCoordsys<> mpos2		///< the position & alignment of 2nd marker (relative to body2 cords, or absolute)
+						   );
+
+					/// Get the link coordinate system, expressed relative to Body2 (the 'master'
+					/// body). This represents the 'main' reference of the link: reaction forces 
+					/// and torques are expressed in this coordinate system.
+					/// (It is the coordinate system of the 'master' marker2 relative to Body2)
+	ChCoordsys<> GetLinkRelativeCoords() {return this->marker2->GetCoord();};
+
+					/// Get the master coordinate system for the assets (this will return the 
+					/// absolute coordinate system of the 'master' marker2)
+	virtual ChFrame<> GetAssetsFrame(unsigned int=0) { return this->marker2->GetAbsFrame();}
+
+
+			//
+			// UPDATING FUNCTIONS
+			//
+
+
+
+					/// Updates auxiliary vars relM, relM_dt, relM_dtdt, 
+					/// dist, dist_dt et similia.
+	virtual void UpdateRelMarkerCoords();
+
+					///  Updates auxiliary forces caused by springs/dampers/etc. which may
+					/// be connected between the two bodies of the link. 
+					/// By default, it adds the forces which might have been added by the
+					/// user using Set_Scr_force() and Set_Scr_torque(). Note, these forces 
+					/// are considered in the reference coordsystem of marker2 (the MAIN marker), 
+					/// and their application point is the origin of marker1 (the SLAVE marker).
+	virtual void UpdateForces (double mytime);
+
+
+
+					// -----------COMPLETE UPDATE.
+					// sequence:
+					//			UpdateTime;
+					//          UpdateRelMarkerCoords;
+					//			UpdateForces;
+
+	virtual void Update (double mytime);
+
+
+
+			//
+			// LCP INTERFACE
+			//
+
+				/// Overrides the empty behaviour of the parent ChLink implementation, which
+				/// does not consider any user-imposed force between the two bodies.
+				/// It adds the current link-forces, if any, (caused by springs, etc.) to the 'fb' vectors
+				/// of the ChLcpVariables referenced by encapsulated ChLcpConstraints.
+				/// In details, it adds the effect caused by C_force and C_torque.
+				/// Both C_force and C_torque these forces are considered expressed in the 
+				/// reference coordsystem of marker2 (the MAIN marker), 
+				/// and their application point is the origin of marker1 (the SLAVE marker).
+	virtual void ConstraintsFbLoadForces(double factor=1.);
+
+
+			//
+			// LINK COORDINATES and other functions:
+			// 
+
+					/// Relative position of marker 1 respect to marker 2.
+	Coordsys GetRelM () {return relM;}
+					/// Relative speed of marker 1 respect to marker 2.
+	Coordsys GetRelM_dt () {return relM_dt;}
+					/// Relative acceleration of marker 1 respect to marker 2.
+	Coordsys GetRelM_dtdt () {return relM_dtdt;}
+					/// Relative rotation angle of marker 1 respect to marker 2 (best with revolute joints..).
+	double	 GetRelAngle () {return relAngle;}
+					/// Relative finite rotation axis of marker 1 respect to marker 2.
+	Vector   GetRelAxis	() {return relAxis;}
+	Vector   GetRelRotaxis	() {return relRotaxis;}
+					/// Relative angular speed of marker 1 respect to marker 2.
+	Vector   GetRelWvel () {return relWvel;}
+					/// Relative angular acceleration of marker 1 respect to marker 2.
+	Vector   GetRelWacc () {return relWacc;}
+					/// Relative 'polar' distance of marker 1 respect to marker 2.
+	double	 GetDist() {return dist;}
+					/// Relative speed of marker 1 respect to marker 2, along the polar distance vector.
+	double	 GetDist_dt() {return dist_dt;}
+
+
+
+					/// To get & set the 'script' force buffers(only accessed by
+					/// external scripts, so it's up to the script to remember
+					/// to set& reset them -link class just add them to C_force etc.
+	Vector* Get_Scr_force() {return &Scr_force;};
+	Vector* Get_Scr_torque() {return &Scr_torque;};
+	void Set_Scr_force(Vector mf) {Scr_force = mf;};
+	void Set_Scr_torque(Vector mf) {Scr_torque = mf;};
+
+					/// Get the total applied force accumulators (force, momentum) in link coords.
+					/// These forces might be affected by additional springs, dampers, etc. but they do not
+					/// include the reaction forces.
+	Vector GetC_force() {return C_force;}
+	Vector GetC_torque() {return C_torque;}
+
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii&) {};
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkMask.cpp b/SRC/ChronoEngine/physics/ChLinkMask.cpp
new file mode 100644
index 0000000..d8ef1ea
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMask.cpp
@@ -0,0 +1,513 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMask.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include "physics/ChLinkMask.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+ 
+
+namespace chrono
+{
+
+
+
+//////////////////////////////////////
+// CLASS "LinkMask"
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMask> a_registration_ChLinkMask;
+
+
+ChLinkMask::ChLinkMask()
+{
+    nconstr = 1;
+
+	constraints.resize(1);
+	constraints[0] = new ChLcpConstraintTwoBodies;
+}
+
+ChLinkMask::ChLinkMask(int mnconstr)
+{
+
+    nconstr = mnconstr;
+
+	constraints.resize(nconstr);
+	for (int i=0; i<nconstr; i++)
+		constraints[i] = new ChLcpConstraintTwoBodies;
+
+}
+
+ChLinkMask::~ChLinkMask()
+{
+    for (int i=0; i<nconstr; i++)
+	{
+		if (constraints[i])
+			delete constraints[i];
+	}
+}
+
+ChLinkMask::ChLinkMask (ChLinkMask& source)
+{
+    nconstr = 0;
+
+	nconstr = source.nconstr;
+    constraints.resize(source.nconstr);
+	for (int i=0; i<nconstr; i++)
+		constraints[i] = (ChLcpConstraintTwoBodies*) source.Constr_N(i).new_Duplicate();
+}
+
+
+void ChLinkMask::ResetNconstr(int newnconstr)
+{
+
+    if (nconstr != newnconstr)
+    {
+        int i;
+		for (i=0; i<nconstr; i++)
+			if (constraints[i]) delete constraints[i];
+
+		nconstr = newnconstr;
+
+		constraints.resize(nconstr);
+
+		for (i=0; i<nconstr; i++)
+			constraints[i] = new ChLcpConstraintTwoBodies;
+
+    }
+
+}
+
+void ChLinkMask::AddConstraint(ChLcpConstraintTwoBodies* aconstr)
+{
+	nconstr++;
+	constraints.push_back(aconstr);
+}
+
+void ChLinkMask::Copy(ChLinkMask* source)
+{
+    int i;
+	for (i=0; i<nconstr; i++)
+			if (constraints[i]) delete constraints[i];
+
+	nconstr = source->nconstr;
+
+	constraints.resize(nconstr);
+
+	for (i=0; i<nconstr; i++)
+		constraints[i] = (ChLcpConstraintTwoBodies*) source->constraints[i]->new_Duplicate();
+}
+
+ChLinkMask* ChLinkMask::NewDuplicate()
+{
+    ChLinkMask* mm = new ChLinkMask();
+    mm->Copy(this);
+    return mm;
+}
+
+void ChLinkMask::SetTwoBodiesVariables(ChLcpVariables* var1, ChLcpVariables* var2)
+{
+	for (int i=0; i<nconstr; i++)
+		constraints[i]->SetVariables(var1, var2);
+}
+
+int ChLinkMask::IsEqual(ChLinkMask& mask2)
+{
+	if (nconstr != mask2.nconstr) return FALSE;
+    for (int j= 0; j < nconstr; j++)
+    {
+        if (!( Constr_N(j) == mask2.Constr_N(j)) ) return FALSE;
+    }
+    return TRUE;
+}
+
+bool ChLinkMask::IsUnilateral(int i)
+{
+	if( Constr_N(i).IsUnilateral() )
+	   return true;
+	return false;
+}
+
+int ChLinkMask::GetMaskDoc()
+{
+	int tot = 0;
+	for (int j= 0; j < nconstr; j++)
+    {
+        if ( Constr_N(j).IsActive()) tot++;
+    }
+    return tot;
+}
+
+int ChLinkMask::GetMaskDoc_d()
+{
+    int cnt = 0;
+    for (int i= 0; i < nconstr; i++)
+    {
+		if ( Constr_N(i).IsActive())
+			if(this->IsUnilateral(i))    // if (Constr_N(i).IsUnilateral())  BETTER?
+				cnt++;
+    }
+    return cnt;
+}
+
+int ChLinkMask::GetMaskDoc_c()
+{
+    return (GetMaskDoc()-GetMaskDoc_d());
+}
+
+ChLcpConstraintTwoBodies* ChLinkMask::GetActiveConstrByNum(int mnum)
+{
+	int cnt = 0;
+	for (int i= 0; i < nconstr; i++)
+    {
+        if ( Constr_N(i).IsActive())
+        {
+            if (cnt == mnum)
+				return &Constr_N(i);
+            cnt++;
+        }
+    }
+    return NULL;
+}
+
+int ChLinkMask::SetActiveRedundantByArray(int* mvector, int mcount)
+{
+    int cnt;
+
+    ChLinkMask* newmask;
+	newmask = this->NewDuplicate();
+    for (int elem = 0; elem <mcount; elem++)
+    {
+        cnt = 0;
+        for (int i= 0; i < nconstr; i++)
+        {
+            if ( Constr_N(i).IsActive() )
+            {
+                if (cnt == mvector[elem]) newmask->Constr_N(i).SetRedundant(true);
+                cnt++;
+            }
+        }
+    }
+    this->Copy(newmask); // replace the mask with updated one.
+    return mcount;
+
+}
+
+
+
+        // set lock =ON for costraints which were disabled because redundant
+int ChLinkMask::RestoreRedundant()
+{
+	int tot = 0;
+    for (int j= 0; j < nconstr; j++)
+    {
+		if (Constr_N(j).IsRedundant())
+		{
+			Constr_N(j).SetRedundant(false);
+			tot++;
+		}
+    }
+    return tot;
+}
+
+int ChLinkMask::SetAllDisabled(bool mdis)
+{
+    int cnt = 0;
+
+	for (int i= 0; i < nconstr; i++)
+    {
+		if (Constr_N(i).IsDisabled()!=mdis)
+		{
+			Constr_N(i).SetDisabled(mdis);
+			cnt++;
+		}
+	}
+
+    return cnt;
+}
+
+
+int ChLinkMask::SetAllBroken(bool mdis)
+{
+    int cnt = 0;
+
+	for (int i= 0; i < nconstr; i++)
+    {
+		if (Constr_N(i).IsBroken()!=mdis)
+		{
+			Constr_N(i).SetBroken(mdis);
+			cnt++;
+		}
+	}
+
+    return cnt;
+}
+
+
+void ChLinkMask::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(3);
+
+		// stream out all member data
+	mstream << nconstr;
+
+	for (int i = 0; i < this->nconstr; i++)
+    {
+        mstream.AbstractWrite(this->constraints[i]);    // save the constraint states
+    }
+}
+
+
+
+void ChLinkMask::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in all member data
+	int my_nconstr;
+	mstream >> my_nconstr;
+
+	if (version==1)
+	{
+		this->ResetNconstr(my_nconstr);
+		for (int i = 0; i < nconstr; i++)
+		{
+			int loadflag;
+			mstream >> loadflag;
+			if (loadflag==4)
+				Constr_N(i).SetRedundant(true);
+			if (loadflag==5)
+				Constr_N(i).SetBroken(true);
+			if (loadflag==6)
+				Constr_N(i).SetDisabled(true);
+			if (loadflag==7)
+				Constr_N(i).SetRedundant(true);
+			if (loadflag==8)
+				Constr_N(i).SetDisabled(true);
+			if (loadflag==20)
+				Constr_N(i).SetMode(CONSTRAINT_FREE);
+			if (loadflag==30)
+				Constr_N(i).SetMode(CONSTRAINT_LOCK);
+			if (loadflag==33 || loadflag==34)
+				Constr_N(i).SetMode(CONSTRAINT_UNILATERAL);
+		}
+	}
+  
+	if (version==2)
+	{
+        int i;
+		for (i=0; i<nconstr; i++)
+			if (constraints[i]) delete constraints[i];
+		nconstr = my_nconstr;
+		constraints.resize(nconstr);
+		for (i = 0; i < this->nconstr; i++)
+		{
+			std::string cls_name;
+			mstream >> cls_name;
+			if (cls_name=="ChLcpConstraintTwo")
+				constraints[i] = new ChLcpConstraintTwoBodies();	// because in v3 ChLcpConstraintTwo is pure virtual class
+			else
+				GetLog() << "  ERROR unknown object in v2 mask:" << cls_name.c_str() <<"\n";
+			constraints[i]->ChLcpConstraintTwo::StreamIN(mstream);
+		}
+	}
+
+	if (version>=3)
+	{
+        int i;
+		for (i=0; i<nconstr; i++)
+			if (constraints[i]) delete constraints[i];
+		nconstr = my_nconstr;
+		constraints.resize(nconstr);
+		for (i = 0; i < this->nconstr; i++)
+		{
+			mstream.AbstractReadCreate(&this->constraints[i]);    // load the constraint states
+		}
+	}
+
+}
+
+
+
+
+///////////////////////////////////////////////////
+// Lock formulation LF link mask:
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMaskLF> a_registration_ChLinkMaskLF;
+
+
+
+ChLinkMaskLF::ChLinkMaskLF()
+{
+    ResetNconstr(9);    // the LF formulation uses 9 constraint flags
+}
+
+void ChLinkMaskLF::Copy(ChLinkMaskLF* source)
+{
+    ChLinkMask::Copy(source);  // first, inherit
+}
+
+ChLinkMask* ChLinkMaskLF::NewDuplicate()
+{
+    ChLinkMaskLF* mm = new ChLinkMaskLF();
+    mm->Copy(this);
+    return mm;
+}
+
+
+        // temporarely set OFF the locked costraints, because of 2D mode, and viceversa
+int ChLinkMaskLF::Set2Dmode(int mode)
+{
+    int cnt;
+
+	if (mode == 1) // switching to 2D
+    {
+        cnt = 0;
+        if (Constr_Z().IsDisabled()==false) {Constr_Z().SetDisabled(true); cnt++;}
+		if (Constr_E1().IsDisabled()==false) {Constr_E1().SetDisabled(true); cnt++;}
+		if (Constr_E2().IsDisabled()==false) {Constr_E2().SetDisabled(true); cnt++;}
+        return cnt;
+    }
+    if (mode == 0) // switching back to 3D
+    {
+        cnt = 0;
+        if (Constr_Z().IsDisabled()==true) {Constr_Z().SetDisabled(false); cnt++;}
+		if (Constr_E1().IsDisabled()==true) {Constr_E1().SetDisabled(false); cnt++;}
+		if (Constr_E2().IsDisabled()==true) {Constr_E2().SetDisabled(false); cnt++;}
+        return cnt;
+    }
+    return 0;
+
+}
+
+void ChLinkMaskLF::SetLockMask(int x, int y, int z,
+                       int e0, int e1, int e2, int e3,
+                       int p, int d)
+{
+	if (x)
+	{
+		this->Constr_X().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_X().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (y)
+	{
+		this->Constr_Y().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_Y().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (z)
+	{
+		this->Constr_Z().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_Z().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (e0)
+	{
+		this->Constr_E0().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_E0().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (e1)
+	{
+		this->Constr_E1().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_E1().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (e2)
+	{
+		this->Constr_E2().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_E2().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (e3)
+	{
+		this->Constr_E3().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_E3().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (p)
+	{
+		this->Constr_P().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_P().SetMode(CONSTRAINT_FREE);
+	}
+
+	if (d)
+	{
+		this->Constr_D().SetMode(CONSTRAINT_LOCK);
+	}else
+	{
+		this->Constr_D().SetMode(CONSTRAINT_FREE);
+	}
+}
+
+
+
+
+void ChLinkMaskLF::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkMask::StreamOUT(mstream);
+
+		// stream out all member data
+
+}
+
+void ChLinkMaskLF::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkMask::StreamIN(mstream);
+
+		// stream in all member data
+}
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkMask.h b/SRC/ChronoEngine/physics/ChLinkMask.h
new file mode 100644
index 0000000..6feb0f4
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMask.h
@@ -0,0 +1,228 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKMASK_H
+#define CHLINKMASK_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMask.h
+//
+//
+//   Array of ChConstraint() objects, used as a
+//   collection of scalar constraints in ChLink()
+//   objects.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include <vector>
+
+#include "core/ChMath.h"
+#include "lcp/ChLcpConstraintTwoBodies.h"
+
+
+namespace chrono
+{
+
+
+
+///
+/// Mask structure for N scalar constraint equations between two bodies.
+///
+
+class ChApi ChLinkMask {
+
+	CH_RTTI_ROOT(ChLinkMask);
+
+			//
+			// DATA
+			//
+
+protected:
+
+					// Array of pointers to 'n' scalar constraint states (own by this object)
+	std::vector<ChLcpConstraintTwoBodies*> constraints;
+
+
+public:
+
+
+	int nconstr;	// Number of scalar eq.of constraint.
+					// Maybe different from effective nDOC because someone may be free/redundant/etc.
+
+			//
+			// CONSTRUCTORS
+			//
+
+				/// Build a link mask with a single constraint
+				/// of class ChLcpConstraintTwoBodies().
+	ChLinkMask();
+
+				/// Build a link mask with a default array of mnconstr constraints
+				/// of class ChLcpConstraintTwoBodies().
+	ChLinkMask(int mnconstr);
+
+	virtual ~ChLinkMask();
+
+	ChLinkMask (ChLinkMask& source);
+	virtual void Copy(ChLinkMask* source);
+	virtual ChLinkMask* NewDuplicate();
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Set references to variables of two connected bodies to all
+				/// constraints at once, therefore also sets all the constraints as active.
+	void SetTwoBodiesVariables(ChLcpVariables* var1, ChLcpVariables* var2);
+
+				/// Obtain the reference to the i-th scalar constraint data
+				/// in the collection link mask.
+	ChLcpConstraintTwoBodies& Constr_N(int i) {assert((i>=0)&&(i<nconstr)); return *constraints[i];}
+
+				/// Utility: to change the size of the mask, reallocating constraints
+				/// (all of type ChConstraintTwo).
+				/// No action if newnconstr == nconstr
+	void ResetNconstr(int newnconstr);	
+
+				/// Add a ChLcpConstraintTwoBodies to mask (NOTE: later, the constraint will
+				/// be automatically deleted when the mask will be deleted)
+	void AddConstraint(ChLcpConstraintTwoBodies* aconstr);
+
+				/// To compare two masks, return TRUE if equal
+	int IsEqual(ChLinkMask& mask2);  
+
+				/// Tells if i-th equation is a unilateral constraint
+	bool IsUnilateral(int i);  
+
+				// Get the number of removed degrees of freedom (n.of costraints)
+
+				/// Count both bilaterals and unilaterals
+	int GetMaskDoc();    
+				/// Count only bilaterals
+	int GetMaskDoc_c();	 
+				/// Count only unilaterals
+	int GetMaskDoc_d(); 
+
+				/// Get the i-th active scalar costraint (not active constr. won't be considered)
+	ChLcpConstraintTwoBodies* GetActiveConstrByNum(int mnum);
+
+				/// Sets some active constraints as redundant.
+	int SetActiveRedundantByArray(int* mvector, int mcount);  
+
+
+				/// Set lock =ON for costraints which were disabled because redundant
+	int RestoreRedundant(); 
+
+
+				/// If SetAllDisabled(true), all the constraints are temporarily turned
+				/// off (inactive) at once, because marked as 'disabled'. Return n.of changed
+	int SetAllDisabled(bool mdis);
+
+				/// If SetAllBroken(true), all the constraints are temporarily turned
+				/// off (broken) at once, because marked as 'broken'. Return n.of changed.
+	int SetAllBroken(bool mdis);
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+
+
+///
+/// Specialized ChLinkMask class, for constraint equations of
+/// the ChLinkLock link.
+///
+
+class ChApi ChLinkMaskLF : public  ChLinkMask
+{
+	CH_RTTI(ChLinkMaskLF, ChLinkMask);
+
+public:
+
+			/// Create a ChLinkMaskLF which has 9 scalar constraints of
+			/// class ChLcpConstraintTwoBodies(). This is useful in case it must
+			/// be used for the ChLinkLock link.
+	ChLinkMaskLF();
+
+	void Copy(ChLinkMaskLF* source);
+	ChLinkMask* NewDuplicate();
+
+
+
+		/// set all mask data at once
+	void SetLockMask(int x, int y, int z, int e0, int e1, int e2, int e3, int p, int d);
+
+
+		/// Obtain the reference to specific scalar constraint data
+		/// in the collection of this link mask.
+	ChLcpConstraintTwoBodies& Constr_X()  {return *constraints[0];};
+	ChLcpConstraintTwoBodies& Constr_Y()  {return *constraints[1];};
+	ChLcpConstraintTwoBodies& Constr_Z()  {return *constraints[2];};
+	ChLcpConstraintTwoBodies& Constr_E0() {return *constraints[3];};
+	ChLcpConstraintTwoBodies& Constr_E1() {return *constraints[4];};
+	ChLcpConstraintTwoBodies& Constr_E2() {return *constraints[5];};
+	ChLcpConstraintTwoBodies& Constr_E3() {return *constraints[6];};
+	ChLcpConstraintTwoBodies& Constr_P()  {return *constraints[7];};
+	ChLcpConstraintTwoBodies& Constr_D()  {return *constraints[8];};
+
+
+
+		// If =1, free costraints not used for bidimensional simulation (Z movement and
+	    // Qx,Qy rotations (it is assumed that both markers have Z axis orthogonl to XY abs. plane)
+		// If =0, return to the 3d mode.
+	int Set2Dmode(int mode);
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkMasked.cpp b/SRC/ChronoEngine/physics/ChLinkMasked.cpp
new file mode 100644
index 0000000..f62f1d6
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMasked.cpp
@@ -0,0 +1,682 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMasked.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkMasked.h"
+#include "physics/ChSystem.h"
+#include "physics/ChGlobal.h"
+//#include "physics/ChCollide.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMasked> a_registration_ChLinkMasked;
+
+
+                // BUILDERS
+ChLinkMasked::ChLinkMasked ()
+{
+    force_D =  new ChLinkForce;    // defeault no forces in link dof
+    force_R =  new ChLinkForce;
+    force_X =  new ChLinkForce;
+    force_Y =  new ChLinkForce;
+    force_Z =  new ChLinkForce;
+    force_Rx = new ChLinkForce;
+    force_Ry = new ChLinkForce;
+    force_Rz = new ChLinkForce;
+
+	d_restlenght = 0;
+
+	ndoc_d = ndoc_c = ndoc =0;
+
+    C = C_dt = C_dtdt = NULL;   // initialize matrices.
+
+    react = 0;
+	cache_li_speed = cache_li_pos = 0;
+    Qc = Ct = 0;
+    Cq1 = Cq2 = 0;
+    Cqw1 = Cqw2 = 0;
+
+    mask = new ChLinkMask(1);     // create the mask;
+	mask->Constr_N(0).SetMode(CONSTRAINT_FREE); // default: one constr.eq. but not working
+
+    BuildLink ();           // setup all matrices - if any (i.e. none in this base link)-
+                            // setting automatically  n. of DOC and DOF,
+}
+
+
+
+            // DESTROYER
+ChLinkMasked::~ChLinkMasked ()
+{
+    DestroyLink();
+
+    if (force_D) delete force_D;
+    if (force_R) delete force_R;
+    if (force_X) delete force_X;
+    if (force_Y) delete force_Y;
+    if (force_Z) delete force_Z;
+    if (force_Rx) delete force_Rx;
+    if (force_Ry) delete force_Ry;
+    if (force_Rz) delete force_Rz;
+
+    delete mask;  mask = NULL;
+}
+
+
+void ChLinkMasked::Copy(ChLinkMasked* source)
+{
+    // first copy the parent class data...
+    ChLinkMarkers::Copy(source);
+
+    mask->Copy(source->mask);
+
+    // setup -alloc all needed matrices!!
+    ChangedLinkMask();
+
+    force_D->Copy (source->force_D);    // copy int.forces
+    force_R->Copy (source->force_R);
+    force_X->Copy (source->force_X);
+    force_Y->Copy (source->force_Y);
+    force_Z->Copy (source->force_Z);
+    force_Rx->Copy (source->force_Rx);
+    force_Ry->Copy (source->force_Ry);
+    force_Rz->Copy (source->force_Rz);
+
+	d_restlenght = source->d_restlenght;
+}
+
+
+ChLink* ChLinkMasked::new_Duplicate ()   // inherited classes:  Link* MyInheritedLink::new_Duplicate()
+{
+    ChLinkMasked* m_l;
+    m_l = new ChLinkMasked;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+void ChLinkMasked::BuildLink ()
+{
+                // set ndoc by counting non-dofs
+    ndoc   = mask->GetMaskDoc();
+	ndoc_c = mask->GetMaskDoc_c();
+	ndoc_d = mask->GetMaskDoc_d();
+
+
+                // create matrices
+    if (ndoc > 0)
+    {
+        C           = new ChMatrixDynamic<>(ndoc,1);
+        C_dt        = new ChMatrixDynamic<>(ndoc,1);
+        C_dtdt      = new ChMatrixDynamic<>(ndoc,1);
+        react       = new ChMatrixDynamic<>(ndoc,1);
+        Qc          = new ChMatrixDynamic<>(ndoc,1);
+        Ct          = new ChMatrixDynamic<>(ndoc,1);
+        Cq1         = new ChMatrixDynamic<>(ndoc,BODY_QDOF);
+        Cq2         = new ChMatrixDynamic<>(ndoc,BODY_QDOF);
+        Cqw1        = new ChMatrixDynamic<>(ndoc,BODY_DOF);
+        Cqw2        = new ChMatrixDynamic<>(ndoc,BODY_DOF);
+		cache_li_speed = new ChMatrixDynamic<>(ndoc,1);
+		cache_li_pos   = new ChMatrixDynamic<>(ndoc,1);
+    }
+    else
+    {
+        C           = 0;
+        C_dt        = 0;
+        C_dtdt      = 0;
+        react       = 0;
+        Qc          = 0;
+        Ct          = 0;
+        Cq1         = 0;
+        Cq2         = 0;
+        Cqw1        = 0;
+        Cqw2        = 0;
+		cache_li_speed = 0;
+		cache_li_pos   = 0;
+    }
+
+}
+
+
+void ChLinkMasked::BuildLink (ChLinkMask* new_mask)
+{
+                    // set mask
+    mask->Copy(new_mask);
+                    // setup matrices;
+    BuildLink();
+}
+
+
+void ChLinkMasked::DestroyLink()
+{
+    if (ndoc > 0)
+    {
+        if (C)      {delete C;      C = NULL;}
+        if (C_dt)   {delete C_dt;   C_dt = NULL;}
+        if (C_dtdt) {delete C_dtdt; C_dtdt = NULL;}
+        if (react)  {delete react;  react = NULL;}
+        if (Qc)     {delete Qc;     Qc = NULL;}
+        if (Ct)     {delete Ct;     Ct = NULL;}
+        if (Cq1)    {delete Cq1;    Cq1 = NULL;}
+        if (Cq2)    {delete Cq2;    Cq2 = NULL;}
+        if (Cqw1)   {delete Cqw1;   Cqw1 = NULL;}
+        if (Cqw2)   {delete Cqw2;   Cqw2 = NULL;}
+		if (react)  {delete react;  react = NULL;}
+		if (cache_li_speed)  {delete cache_li_speed;  cache_li_speed = 0;}
+		if (cache_li_pos)  {delete cache_li_pos;  cache_li_pos = 0;}
+    }
+
+    ndoc=0;
+}
+
+
+void ChLinkMasked::ChangeLinkMask (ChLinkMask* new_mask)
+{
+    DestroyLink ();
+    BuildLink (new_mask);
+}
+
+void ChLinkMasked::ChangedLinkMask ()
+{
+    DestroyLink ();
+    BuildLink();
+}
+
+
+
+void ChLinkMasked::SetDisabled(bool mdis)
+{
+	ChLinkMarkers::SetDisabled(mdis);
+
+    if (mask->SetAllDisabled(mdis) >0)
+        ChangedLinkMask ();
+}
+
+void ChLinkMasked::SetBroken(bool mbro)
+{
+	ChLinkMarkers::SetBroken(mbro);
+
+    if (mask->SetAllBroken(mbro) >0)
+        ChangedLinkMask ();
+}
+
+
+int ChLinkMasked::RestoreRedundant()
+{
+    int mchanges = mask->RestoreRedundant();
+    if (mchanges)
+        ChangedLinkMask ();
+    return mchanges;
+}
+
+
+void ChLinkMasked::SetMarker1 (ChMarker* mark1)
+{
+	ChLinkMarkers::SetMarker1 (mark1);
+
+	if(this->Body1 && this->Body2)
+	{
+		((ChLinkMaskLF*)this->mask)->SetTwoBodiesVariables(&Body1->Variables(), &Body2->Variables());
+					// This is needed because only if all constraints in mask are now active, and C,Ct,etc.
+					// matrices must be allocated accordingly, otherwise are null.
+		DestroyLink();
+		BuildLink();
+	}
+}
+
+void ChLinkMasked::SetMarker2 (ChMarker* mark2)
+{
+	ChLinkMarkers::SetMarker2 (mark2);
+
+	if(this->Body1 && this->Body2)
+	{
+		((ChLinkMaskLF*)this->mask)->SetTwoBodiesVariables(&Body1->Variables(), &Body2->Variables());
+					// This is needed because only if all constraints in mask are now active, and C,Ct,etc.
+					// matrices must be allocated accordingly, otherwise are null.
+		DestroyLink();
+		BuildLink();
+	}
+}
+
+
+ 
+////////////////////////////////////
+///
+///    LCP SYSTEM FUNCTIONS
+
+
+void ChLinkMasked::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	if (!this->IsActive())
+		return;
+
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+			mdescriptor.InsertConstraint(&mask->Constr_N(i));
+	}
+}
+
+void ChLinkMasked::ConstraintsBiReset()
+{
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		mask->Constr_N(i).Set_b_i(0.);
+	}
+}
+ 
+void ChLinkMasked::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			if (do_clamp)
+			{
+				if (mask->Constr_N(i).IsUnilateral())
+					mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + ChMax (factor * C->ElementN(cnt), -recovery_clamp)  );
+				else 
+					mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + ChMin(ChMax (factor * C->ElementN(cnt), -recovery_clamp), recovery_clamp)  );
+			}
+			else
+				mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + factor * C->ElementN(cnt)  );
+
+			cnt++;
+		}
+	}
+}
+
+void ChLinkMasked::ConstraintsBiLoad_Ct(double factor)
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + factor * Ct->ElementN(cnt)  );
+			cnt++;
+		}
+	} 
+}
+
+void ChLinkMasked::ConstraintsBiLoad_Qc(double factor)
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + factor * Qc->ElementN(cnt)  );
+			cnt++;
+		}
+	}
+}
+
+
+
+
+void ChLinkMasked::ConstraintsLoadJacobians()
+{
+	if (!this->ndoc)
+		return;
+
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			mask->Constr_N(i).Get_Cq_a()->PasteClippedMatrix(this->Cqw1, cnt, 0, 1, this->Cqw1->GetColumns(), 0,0);
+			mask->Constr_N(i).Get_Cq_b()->PasteClippedMatrix(this->Cqw2, cnt, 0, 1, this->Cqw2->GetColumns(), 0,0);
+			cnt++;
+
+			// sets also the CFM term
+			//mask->Constr_N(i).Set_cfm_i(this->attractor);
+		}
+	}
+}
+ 
+
+void ChLinkMasked::ConstraintsFetch_react(double factor)
+{
+	react_force = VNULL;		// Do not update 'intuitive' react force and torque here: just set as 0. 
+    react_torque = VNULL;		// Child classes implementations should compute them. 
+	
+	// From constraints to react vector:
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			react->ElementN(cnt) = mask->Constr_N(i).Get_l_i() * factor;
+			cnt++;
+		}
+	}
+}
+
+void  ChLinkMasked::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			mask->Constr_N(i).Set_l_i( cache_li_speed->ElementN(cnt) );
+			cnt++;
+		}
+	}
+}
+
+void  ChLinkMasked::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			mask->Constr_N(i).Set_l_i( cache_li_pos->ElementN(cnt) ) ;
+			cnt++;
+		}
+	}
+}
+
+void  ChLinkMasked::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			cache_li_speed->ElementN(cnt) = mask->Constr_N(i).Get_l_i();
+			cnt++;
+		}
+	}
+}
+
+void  ChLinkMasked::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			cache_li_pos->ElementN(cnt) = mask->Constr_N(i).Get_l_i();
+			cnt++;
+		}
+	}
+}
+
+
+
+
+
+////////////////////////////////////
+///
+///    UPDATING PROCEDURES
+
+
+
+
+
+/////////   4.5- UPDATE Cqw1 and Cqw2
+/////////
+void ChLinkMasked::Transform_Cq_to_Cqw(ChMatrix<>* mCq, ChMatrix<>* mCqw, ChBody* mbody)
+{
+    if (!mCq) return;
+
+    // traslational part - not changed
+    mCqw->PasteClippedMatrix(mCq,0,0,mCq->GetRows(),3,0,0);
+
+    // rotational part [Cq_w] = [Cq_q]*[Gl]'*1/4
+    register int col, row, colres;
+    double sum;
+
+	ChMatrixNM<double,3,4> mGl;
+	ChFrame<>::SetMatrix_Gl(mGl, mbody->GetCoord().rot);
+
+    for (colres=0; colres < 3; colres++)    {
+        for (row=0; row < (mCq->GetRows()); row++)      {
+            sum = 0;
+            for (col=0; col < 4; col++)         {
+                sum+= ((mCq->GetElement (row,col+3))*(mGl.GetElement (colres,col)));
+            }
+            mCqw->SetElement (row, colres+3, sum * 0.25);
+        }
+    }
+}
+
+void ChLinkMasked::UpdateCqw()
+{
+    if (!Cq1 || !Cq2) return;
+
+    ChLinkMasked::Transform_Cq_to_Cqw(Cq1, Cqw1, Body1);
+	ChLinkMasked::Transform_Cq_to_Cqw(Cq2, Cqw2, Body2);
+}
+
+/////////   5-   UPDATE FORCES
+/////////
+
+void ChLinkMasked::UpdateForces(double mytime)
+{
+	ChLinkMarkers::UpdateForces(mytime);
+
+    // ** Child class can inherit this method. The parent implementation must
+    //    be called _before_ adding further custom forces.
+
+    Vector m_force = VNULL;         // initialize to zero the m1-m2 force/torque
+    Vector m_torque = VNULL;        // 'intuitive' vectors (can be transformed&added later into Qf)
+
+
+    // COMPUTE THE FORCES IN THE LINK, FOR EXAMPLE
+    // CAUSED BY SPRINGS
+    // NOTE!!!!!   C_force and C_torque   are considered in the reference coordsystem
+    // of marker2  (the MAIN marker), and their application point is considered the
+    // origin of marker1 (the SLAVE marker)
+
+    // 1)========== the generic spring-damper
+
+    if (force_D) {
+    if (force_D->Get_active())
+    {
+        double dfor;
+        dfor = force_D->Get_Force((dist - d_restlenght), dist_dt, ChTime);
+        m_force = Vmul (Vnorm(relM.pos), dfor);
+
+        C_force = Vadd(C_force, m_force);
+    } }
+
+
+    // 2)========== the generic torsional spring / torsional damper
+
+    if (force_R) {
+    if (force_R->Get_active())
+    {
+        double tor;
+            // 1) the tors. spring
+        tor = force_R->Get_Force(relAngle, 0, ChTime);
+        m_torque = Vmul (relAxis, tor);
+        C_torque = Vadd(C_torque, m_torque);
+            // 2) the tors. damper
+        double angle_dt = Vlenght (relWvel);
+        tor = force_R->Get_Force(0, angle_dt, ChTime);
+        m_torque = Vmul (Vnorm(relWvel), tor);
+        C_torque = Vadd(C_torque, m_torque);
+    } }
+
+
+    // 3)========== the XYZ forces
+
+    m_force = VNULL;
+
+    if (force_X) {
+    if (force_X->Get_active())
+    {
+        m_force.x = force_X->Get_Force(relM.pos.x, relM_dt.pos.x, ChTime);
+    } }
+
+    if (force_Y) {
+    if (force_Y->Get_active())
+    {
+        m_force.y = force_Y->Get_Force(relM.pos.y, relM_dt.pos.y, ChTime);
+    } }
+
+    if (force_Z) {
+    if (force_Z->Get_active())
+    {
+        m_force.z = force_Z->Get_Force(relM.pos.z, relM_dt.pos.z, ChTime);
+    } }
+
+    C_force = Vadd(C_force, m_force);
+
+
+    // 4)========== the RxRyRz forces (torques)
+
+    m_torque = VNULL;
+
+    if (force_Rx) {
+    if (force_Rx->Get_active())
+    {
+        m_torque.x = force_Rx->Get_Force(relRotaxis.x, relWvel.x, ChTime);
+    } }
+
+    if (force_Ry) {
+    if (force_Ry->Get_active())
+    {
+        m_torque.y = force_Ry->Get_Force(relRotaxis.y, relWvel.y, ChTime);
+    } }
+
+    if (force_Rz) {
+    if (force_Rz->Get_active())
+    {
+        m_torque.z = force_Rz->Get_Force(relRotaxis.z, relWvel.z, ChTime);
+    } }
+
+    C_torque = Vadd(C_torque, m_torque);
+
+}
+
+
+
+
+
+/////////
+/////////   COMPLETE UPDATE
+/////////
+/////////
+
+void ChLinkMasked::Update (double time)
+{
+    // 1 -
+    UpdateTime(time);
+
+    // 2 -
+    UpdateRelMarkerCoords();
+
+    // 3 -
+    UpdateState();
+
+    // 3b-
+    UpdateCqw();
+
+    // 4 -
+    UpdateForces(time);
+
+}
+
+
+
+/////////
+///////// FILE I/O
+/////////
+
+
+// Define some  link-specific flags for backward compatibility
+
+#define LF_INACTIVE		(1L << 0)
+#define LF_BROKEN		(1L << 2)
+#define LF_DISABLED	    (1L << 4)
+
+
+
+void ChLinkMasked::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(10);
+		// serialize parent class too
+	ChLinkMarkers::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream.AbstractWrite(mask);
+    mstream << d_restlenght;
+    mstream << *force_D;
+    mstream << *force_R;
+    mstream << *force_X;
+    mstream << *force_Y;
+    mstream << *force_Z;
+    mstream << *force_Rx;
+    mstream << *force_Ry;
+    mstream << *force_Rz;
+}
+
+void ChLinkMasked::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkMarkers::StreamIN(mstream);
+
+		// stream in all member data
+	if (mask) delete (mask); mask=NULL;
+	mstream.AbstractReadCreate(&mask);
+    mstream >> d_restlenght;
+    mstream >> *force_D;
+    mstream >> *force_R;
+    mstream >> *force_X;
+    mstream >> *force_Y;
+    mstream >> *force_Z;
+    mstream >> *force_Rx;
+    mstream >> *force_Ry;
+    mstream >> *force_Rz;
+	
+}
+
+
+
+
+ 
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkMasked.h b/SRC/ChronoEngine/physics/ChLinkMasked.h
new file mode 100644
index 0000000..33a32d6
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMasked.h
@@ -0,0 +1,322 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKMASKED_H
+#define CHLINKMASKED_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMasked.h
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkMarkers.h"
+#include "physics/ChLinkMask.h"
+#include "physics/ChLinkforce.h"
+
+
+namespace chrono
+{
+
+// Forward references
+class ChSystem;
+
+
+///
+/// Base class for all link joints which use a 'six degrees of freedom' mask
+/// and auxiliary matrices to store jacobians. The management of jacobian matrices,
+/// as well as other auxiliary matrices, is automatic as soon as the mask is 
+/// changed. 
+/// Also, links inherited from this class inherit six ChLinkForce objects, to
+/// set inner spring-damper features for each degree of freedom. 
+///
+
+class ChApi ChLinkMasked : public ChLinkMarkers {
+
+	CH_RTTI(ChLinkMasked,ChLinkMarkers);
+
+protected:
+
+				//
+	  			// DATA
+				//
+						// THE SCALAR CONSTRAINTS
+						// The mask of the locked coords, with the status of the
+						// scalar constraints. This encapsulated object also
+						// contains the jacobians and residuals for the LCP solver.
+	ChLinkMask* mask;
+
+							 // the following counters are cached here for optimization purposes
+	int ndoc;			// number of DOC, degrees of costraint
+	int ndoc_c;			// number of DOC, degrees of costraint (only bilaterals)
+	int ndoc_d;			// number of DOC, degrees of costraint (only unilaterals)
+
+		// internal forces
+	ChLinkForce* force_D;	// the force acting on the straight line m1-m2 (distance)
+	ChLinkForce* force_R;	// the torque acting about rotation axis
+	ChLinkForce* force_X;	// the force acting along X dof
+	ChLinkForce* force_Y;	// the force acting along Y dof
+	ChLinkForce* force_Z;	// the force acting along Z dof
+	ChLinkForce* force_Rx;  // the torque acting about Rx dof
+	ChLinkForce* force_Ry;  // the torque acting about Ry dof
+	ChLinkForce* force_Rz;  // the torque acting about Rz dof
+	double d_restlenght;    // the rest lenght of the "d_spring" spring
+
+	ChMatrix<>* C;			// {C(q,q_dt,t)}, <<<<!!!   that is
+	ChMatrix<>* C_dt;		// the violation= relC = C(q,qdt,t)
+	ChMatrix<>* C_dtdt;		// also speed violations. and acc violations
+
+	ChMatrix<>* Cq1;		// [Cq1], the jacobian of the constraint, for coords1, [ndoc,7]
+	ChMatrix<>* Cq2;		// [Cq2], the jacobian of the constraint, for coords2. [ndoc,7]
+
+	ChMatrix<>* Cqw1;		// [Cqw1], the jacobian [ndoc,6] for 3 Wl rot.coordinates instead of quaternions
+	ChMatrix<>* Cqw2;		// [Cqw2], the jacobian [ndoc,6] for 3 Wl rot.coordinates instead of quaternions
+
+	ChMatrix<>* Qc;			// {Qc} , the known part,
+						//        {Qc}=-{C_dtdt}-([Cq]{q_dt})q-2[Cq_dt]{q_dt}
+
+	ChMatrix<>* Ct;			// The time derivative of link equation, i.e. (dC/dt)
+
+	ChMatrix<>* react;		// {l}	, the lagrangians forces in the constraints
+
+	ChMatrix<>* cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	ChMatrix<>* cache_li_pos;	// used to cache the last computed value of multiplier (solver warm starting)
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+	ChLinkMasked ();
+	virtual ~ChLinkMasked ();
+	virtual void Copy(ChLinkMasked* source);
+	virtual ChLink* new_Duplicate ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+protected:
+					// [mostly internal], allocates matrices and, in general, initializes all stuff
+					// which is mask-dependant.  Sets n. DOF and n .DOC.
+					// Copies the mask from new_mask.
+	void BuildLink (ChLinkMask* new_mask);
+					// [mostly internal]. as before, but uses the current (just changed) mask
+	void BuildLink ();
+					// [mostly internal], frees matrices allocated by BuildLink
+	void DestroyLink ();
+
+
+public:
+					/// Must be called after whatever change the mask of the link,
+					/// in order to update auxiliary matrices sizes...
+	void ChangeLinkMask (ChLinkMask* new_mask);
+
+					/// Must be called after whatever change the mask of the link,
+					/// in order to update auxiliary matrices sizes...
+	void ChangedLinkMask ();
+
+					/// If some constraint is redundant, return to normal state
+	int  RestoreRedundant();		   ///< \return number of changed states
+
+
+					/// Set the status of link validity
+	virtual void SetValid(bool mon) {valid = mon;}
+
+					/// User can use this to enable/disable all the constraint of
+					/// the link as desired.
+	virtual void SetDisabled(bool mdis);
+
+					/// Ex:3rd party software can set the 'broken' status via this method
+	virtual void SetBroken(bool mon);
+
+
+					/// Get the pointer to the link mask, ie. a ChLinkMask (sort of
+					/// array containing a set of ChLcpConstraint items).
+	ChLinkMask* GetMask () {return mask;}
+
+	virtual int GetDOC  () {return ndoc;}
+	virtual int GetDOC_c  () {return ndoc_c;}
+	virtual int GetDOC_d  () {return ndoc_d;}
+
+	virtual void SetMarker1 (ChMarker* mark1);
+	virtual void SetMarker2 (ChMarker* mark2);
+
+
+
+			//
+			// LCP INTERFACE  ( functions to assembly/manage data for system solver)
+			//
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsBiLoad_Qc(double factor=1.);
+	//virtual void ConstraintsFbLoadForces(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsFetch_react(double factor=1.);
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+
+
+			//
+			// UPDATING FUNCTIONS
+			//
+
+					/// This is expected to update the values in C, C_dt, C_dtdt, in 
+					/// jacobians Cq1 and Cq2, in Qc and in Ct. 
+					/// By default, this does NOTHING, so it is up to the inherited 
+					/// classes to fill these vectors/matrices depending on how they 
+					/// describe the constraint equations.
+	virtual void UpdateState () {};
+
+					/// Updates Cqw1 and Cqw2  given updated  Cq1 and Cq2, i.e. computes the
+					/// jacobians with 'Wl' rotational coordinates knowing the jacobians
+					/// for body rotations in quaternion coordinates.
+	virtual void UpdateCqw ();
+
+					/// Inherits, and updates the C_force and C_torque 'intuitive' forces,  
+					/// adding the effects of the contained ChLinkForce objects. 
+					/// (Default: inherits parent UpdateForces(), then C_force and C_torque are 
+					/// incremented with the Link::ChLinkForces objects)
+	virtual void UpdateForces (double mytime);
+
+
+
+					// -----------COMPLETE UPDATE.
+					// sequence:
+					//			UpdateTime;
+					//          UpdateRelMarkerCoords;
+					//			UpdateState;
+					//          UpdateCqw
+					//			UpdateForces;
+
+					/// This following "complete" update functions actually fill all the
+					/// matrices of the link, and does all calculus, by
+					/// calling all the previous Update functions in sequence.
+	virtual void Update (double mytime);
+
+
+
+
+				// LINK VIOLATIONS
+				//
+				// to get the constraint violations,
+				// i.e. the residual of the constraint equations and their time derivatives
+
+					/// Link violation (residuals of the link constraint equations)
+	ChMatrix<>* GetC () {return C;}
+					/// Time derivatives of link violations
+	ChMatrix<>* GetC_dt () {return C_dt;}
+					/// Double time derivatives of link violations
+	ChMatrix<>* GetC_dtdt () {return C_dtdt;}
+
+
+				// LINK STATE MATRICES
+				//
+				// Here follow the functions used by simulation engines to
+				// fetch the system state matrices (the jacobians, the Q vector, etc.)
+				// for building the state system matrices
+				// Note that these function does not compute/update such matrices,
+				// because all the updating/computing must be implemented in the Update...
+				// functions above.
+
+					/// The jacobian (body n.1 part, i.e. columns= 7 ,  rows= ndoc)
+	ChMatrix<>* GetCq1 () {return Cq1;}
+					/// The jacobian (body n.2 part, i.e. columns= 7 ,  rows= ndoc)
+	ChMatrix<>* GetCq2 () {return Cq2;}
+
+					/// The jacobian for Wl (col 6, rows= ndoc), as [Cqw1_rot]=[Cq_rot]*[Gl_1]'
+	ChMatrix<>* GetCqw1 () {return Cqw1;}
+					/// The jacobian for Wl (col 6, rows= ndoc)	as [Cqw2_rot]=[Cq_rot]*[Gl_2]'
+	ChMatrix<>* GetCqw2 () {return Cqw2;}
+
+					/// The gamma vector used in dynamics,  [Cq]x''=Qc
+	ChMatrix<>* GetQc  () {return Qc;}
+
+					/// The Ct vector used in kinematics,  [Cq]x'=Ct
+	ChMatrix<>* GetCt  () {return Ct;}
+
+
+					/// Access the reaction vector, after dynamics computations
+	ChMatrix<>* GetReact () {return react;}
+
+
+
+			//
+			// OTHER DATA
+			//
+
+
+			// for the internal forces
+	ChLinkForce* GetForce_D() {return force_D;}
+	ChLinkForce* GetForce_R() {return force_R;}
+	ChLinkForce* GetForce_X() {return force_X;}
+	ChLinkForce* GetForce_Y() {return force_Y;}
+	ChLinkForce* GetForce_Z() {return force_Z;}
+	ChLinkForce* GetForce_Rx() {return force_Rx;}
+	ChLinkForce* GetForce_Ry() {return force_Ry;}
+	ChLinkForce* GetForce_Rz() {return force_Rz;}
+	void SetForce_D		(ChLinkForce* m_for) {if (force_D) delete force_D; force_D = m_for;};
+	void SetForce_R		(ChLinkForce* m_for) {if (force_R) delete force_R; force_R = m_for;};
+	void SetForce_X		(ChLinkForce* m_for) {if (force_X) delete force_X; force_X = m_for;};
+	void SetForce_Y		(ChLinkForce* m_for) {if (force_Y) delete force_Y; force_Y = m_for;};
+	void SetForce_Z		(ChLinkForce* m_for) {if (force_Z) delete force_Z; force_Z = m_for;};
+	void SetForce_Rx	(ChLinkForce* m_for) {if (force_Rx) delete force_Rx; force_Rx = m_for;};
+	void SetForce_Ry	(ChLinkForce* m_for) {if (force_Ry) delete force_Ry; force_Ry = m_for;};
+	void SetForce_Rz	(ChLinkForce* m_for) {if (force_Rz) delete force_Rz; force_Rz = m_for;};
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii&) {};
+
+
+protected:
+					// Internal use only - transforms a Nx7 jacobian matrix for a 
+					// body with rotations expressed as quaternions, into
+					// a Nx6 jacobian matrix for a body with 'w' rotations.
+	static void Transform_Cq_to_Cqw(ChMatrix<>* mCq, ChMatrix<>* mCqw, ChBody* mbody);
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkMate.cpp b/SRC/ChronoEngine/physics/ChLinkMate.cpp
new file mode 100644
index 0000000..8772568
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMate.cpp
@@ -0,0 +1,1078 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMate.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChLinkMate.h"
+#include "physics/ChSystem.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMate> a_registration_ChLinkMate;
+
+ChLink* ChLinkMate::new_Duplicate ()
+{
+    ChLinkMate* m_l = new ChLinkMate;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+void ChLinkMate::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLink::StreamOUT(mstream);
+
+		// stream out all member data
+}
+
+
+void ChLinkMate::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+
+		// deserialize parent class too
+	ChLink::StreamIN(mstream);
+
+		// stream in all member data
+}
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMateGeneric> a_registration_ChLinkMateGeneric;
+
+
+
+ChLinkMateGeneric::ChLinkMateGeneric (bool mc_x, bool mc_y, bool mc_z, bool mc_rx, bool mc_ry, bool mc_rz)
+{ 
+	c_x = mc_x;
+	c_y = mc_y;
+	c_z = mc_z;
+	c_rx = mc_rx;
+	c_ry = mc_ry;
+	c_rz = mc_rz;
+
+	C =0;
+	cache_li_pos = 0;
+	cache_li_speed = 0;
+
+	mask = new ChLinkMask();
+
+	SetupLinkMask();
+}
+
+ChLinkMateGeneric::~ChLinkMateGeneric ()
+{
+	if (C)
+		delete C;
+	C=0;
+
+	if (cache_li_pos)
+		delete cache_li_pos;
+	cache_li_pos=0;
+
+	if (cache_li_speed)
+		delete cache_li_speed;
+	cache_li_speed=0;
+
+	if (mask)
+		delete mask; 
+	mask=0;
+}
+
+
+void ChLinkMateGeneric::Copy(ChLinkMateGeneric* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMate::Copy(source);
+	
+	c_x = source->c_x;
+	c_y = source->c_y;
+	c_z = source->c_z;
+	c_rx = source->c_rx;
+	c_ry = source->c_ry;
+	c_rz = source->c_rz;
+
+	SetupLinkMask();
+}
+
+ChLink* ChLinkMateGeneric::new_Duplicate ()
+{
+    ChLinkMateGeneric * m_l = new ChLinkMateGeneric;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+void ChLinkMateGeneric::SetConstrainedCoords(bool mc_x, bool mc_y, bool mc_z, bool mc_rx, bool mc_ry, bool mc_rz)
+{
+	c_x = mc_x;
+	c_y = mc_y;
+	c_z = mc_z;
+	c_rx = mc_rx;
+	c_ry = mc_ry;
+	c_rz = mc_rz;
+
+	SetupLinkMask();
+}
+
+
+void ChLinkMateGeneric::SetupLinkMask()
+{
+	int nc = 0;
+	if (c_x) nc++;
+	if (c_y) nc++;
+	if (c_z) nc++;
+	if (c_rx) nc++;
+	if (c_ry) nc++;
+	if (c_rz) nc++;
+
+	mask->ResetNconstr(nc);
+
+	if (C)
+		delete C;
+	C   = new ChMatrixDynamic<>(nc,1);
+
+	if (cache_li_pos)
+		delete cache_li_pos;
+	cache_li_pos   = new ChMatrixDynamic<>(nc,1);
+
+	if (cache_li_speed)
+		delete cache_li_speed;
+	cache_li_speed = new ChMatrixDynamic<>(nc,1);
+
+	ChangedLinkMask();
+}
+
+void ChLinkMateGeneric::ChangedLinkMask()
+{
+	ndoc   = mask->GetMaskDoc();
+	ndoc_c = mask->GetMaskDoc_c();
+	ndoc_d = mask->GetMaskDoc_d();
+}
+
+
+void ChLinkMateGeneric::SetDisabled(bool mdis)
+{
+	ChLinkMate::SetDisabled(mdis);
+
+    if (mask->SetAllDisabled(mdis) >0)
+        ChangedLinkMask ();
+}
+
+void ChLinkMateGeneric::SetBroken(bool mbro)
+{
+	ChLinkMate::SetBroken(mbro);
+
+    if (mask->SetAllBroken(mbro) >0)
+        ChangedLinkMask ();
+}
+
+
+int ChLinkMateGeneric::RestoreRedundant()
+{
+    int mchanges = mask->RestoreRedundant();
+    if (mchanges)
+        ChangedLinkMask ();
+    return mchanges;
+}
+
+
+void ChLinkMateGeneric::Update (double mytime)
+{
+    // Inherit time changes of parent class (ChLink), basically doing nothing :)
+    ChLink::UpdateTime(mytime);
+
+	if(this->Body1 && this->Body2)
+	{
+		this->mask->SetTwoBodiesVariables(&Body1->Variables(), &Body2->Variables());
+	
+		ChFrame<> aframe = this->frame1 >> (*this->Body1);
+		ChVector<> p1_abs = aframe.GetPos();
+		ChFrame<> aframe2 = this->frame2 >> (*this->Body2);
+		ChVector<> p2_abs = aframe2.GetPos();
+		ChFrame<> bframe;  
+		static_cast<ChFrame<>*>(this->Body2)->TrasformParentToLocal(aframe, bframe);
+		this->frame2.TrasformParentToLocal(bframe, aframe);
+		// Now 'aframe' contains the position/rotation of frame 1 respect to frame 2, in frame 2 coords.
+
+		ChMatrix33<> Jx1, Jx2, Jr1, Jr2, Jw1, Jw2;
+		ChMatrix33<> mtempM, mtempQ;
+
+		ChMatrix33<> abs_plane;
+		abs_plane.MatrMultiply(*this->Body2->GetA(), *this->frame2.GetA());
+
+		Jx1.CopyFromMatrixT(abs_plane);
+		Jx2.CopyFromMatrixT(abs_plane);
+		Jx2.MatrNeg();
+
+		Jw1.MatrTMultiply(abs_plane, *this->Body1->GetA() );
+		Jw2.MatrTMultiply(abs_plane, *this->Body2->GetA() );
+
+		mtempM.Set_X_matrix(this->frame1.GetPos());
+		Jr1.MatrMultiply(Jw1, mtempM);
+		Jr1.MatrNeg();
+
+		mtempM.Set_X_matrix(this->frame2.GetPos());
+		Jr2.MatrMultiply(Jw2, mtempM);
+
+		ChVector<> p2p1_base2 = (*this->Body2->GetA()).MatrT_x_Vect( Vsub(p1_abs,p2_abs) );
+		mtempM.Set_X_matrix(p2p1_base2);
+		mtempQ.MatrTMultiply(*this->frame2.GetA() ,mtempM);
+		Jr2.MatrInc(mtempQ); 
+
+		Jw2.MatrNeg();
+
+		// Premultiply by Jw1 and Jw2 by  0.5*[Fp(q_resid)]' to get residual as imaginary part of a quaternion.
+		// For small misalignment this effect is almost insignificant cause [Fp(q_resid)]=[I],
+		// but otherwise it is needed (if you want to use the stabilization term - if not, you can live without). 
+		mtempM.Set_X_matrix((aframe.GetRot().GetVector())*0.5);
+		mtempM(0,0) = aframe.GetRot().e0;
+		mtempM(1,1) = aframe.GetRot().e0;
+		mtempM(2,2) = aframe.GetRot().e0;
+		mtempQ.MatrTMultiply(mtempM, Jw1);
+		Jw1 = mtempQ;
+		mtempQ.MatrTMultiply(mtempM, Jw2);
+		Jw2 = mtempQ;
+
+		int nc = 0;
+
+		if (c_x) 
+		{
+			this->C->ElementN(nc) = aframe.GetPos().x;
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jx1, 0,0, 1,3, 0,0);
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jr1, 0,0, 1,3, 0,3);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jx2, 0,0, 1,3, 0,0);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jr2, 0,0, 1,3, 0,3);
+			nc++;
+		}
+		if (c_y) 
+		{
+			this->C->ElementN(nc) = aframe.GetPos().y;
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jx1, 1,0, 1,3, 0,0);
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jr1, 1,0, 1,3, 0,3);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jx2, 1,0, 1,3, 0,0);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jr2, 1,0, 1,3, 0,3);
+			nc++;
+		}
+		if (c_z) 
+		{
+			this->C->ElementN(nc) = aframe.GetPos().z;
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jx1, 2,0, 1,3, 0,0);
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jr1, 2,0, 1,3, 0,3);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jx2, 2,0, 1,3, 0,0);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jr2, 2,0, 1,3, 0,3);
+			nc++;
+		}
+		if (c_rx) 
+		{
+			this->C->ElementN(nc) = aframe.GetRot().e1; 
+			this->mask->Constr_N(nc).Get_Cq_a()->FillElem(0);
+			this->mask->Constr_N(nc).Get_Cq_b()->FillElem(0);
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jw1, 0,0, 1,3, 0,3);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jw2, 0,0, 1,3, 0,3);
+			nc++;
+		}
+		if (c_ry) 
+		{
+			this->C->ElementN(nc) = aframe.GetRot().e2; 
+			this->mask->Constr_N(nc).Get_Cq_a()->FillElem(0);
+			this->mask->Constr_N(nc).Get_Cq_b()->FillElem(0);
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jw1, 1,0, 1,3, 0,3);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jw2, 1,0, 1,3, 0,3);
+			nc++;
+		}
+		if (c_rz) 
+		{
+			this->C->ElementN(nc) = aframe.GetRot().e3; 
+			this->mask->Constr_N(nc).Get_Cq_a()->FillElem(0);
+			this->mask->Constr_N(nc).Get_Cq_b()->FillElem(0);
+			this->mask->Constr_N(nc).Get_Cq_a()->PasteClippedMatrix(&Jw1, 2,0, 1,3, 0,3);
+			this->mask->Constr_N(nc).Get_Cq_b()->PasteClippedMatrix(&Jw2, 2,0, 1,3, 0,3);
+			nc++;
+		}
+/*
+		if (this->c_x)
+			GetLog()<< "err.x ="<< aframe.GetPos().x << "\n";
+		if (this->c_y)
+			GetLog()<< "err.y ="<< aframe.GetPos().y << "\n";
+		if (this->c_z)
+			GetLog()<< "err.z ="<< aframe.GetPos().z << "\n";
+		if (this->c_x || this->c_y || this->c_z)
+				GetLog()<< *this->C << "\n";
+*/
+	}
+
+}
+
+
+
+int ChLinkMateGeneric::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChFrame<> mpos1,			///< mate frame (slave), for 1st body (rel. or abs., see flag above)
+						   ChFrame<> mpos2  		///< mate frame (master), for 2nd body (rel. or abs., see flag above) 
+						   )
+{
+	assert(mbody1.get_ptr() != mbody2.get_ptr());
+	assert(mbody1->GetSystem() == mbody2->GetSystem());
+
+	this->Body1 = mbody1.get_ptr();
+	this->Body2 = mbody2.get_ptr();
+	this->SetSystem(mbody1->GetSystem());
+
+	this->mask->SetTwoBodiesVariables(&Body1->Variables(), &Body2->Variables());
+	
+	if (pos_are_relative)
+	{
+		this->frame1 = mpos1;
+		this->frame2 = mpos2;
+	}
+	else
+	{
+		// from abs to body-rel
+		static_cast<ChFrame<>*>(this->Body1)->TrasformParentToLocal(mpos1, this->frame1);
+		static_cast<ChFrame<>*>(this->Body2)->TrasformParentToLocal(mpos2, this->frame2);
+	}
+	return true;
+}
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChLinkMateGeneric::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	if (!this->IsActive())
+		return;
+
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+			mdescriptor.InsertConstraint(&mask->Constr_N(i));
+	}
+}
+
+void ChLinkMateGeneric::ConstraintsBiReset()
+{
+	if (!this->IsActive())
+		return;
+
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		mask->Constr_N(i).Set_b_i(0.);
+	}
+}
+ 
+void ChLinkMateGeneric::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	if (!this->IsActive())
+		return;
+
+//***TEST***
+/*
+	GetLog()<< "cload: " ;
+	if (this->c_x) GetLog()<< " x";
+	if (this->c_y) GetLog()<< " y";
+	if (this->c_z) GetLog()<< " z";
+	if (this->c_rx) GetLog()<< " Rx";
+	if (this->c_ry) GetLog()<< " Ry";
+	if (this->c_rz) GetLog()<< " Rz";
+	GetLog()<< *this->C << "\n";
+*/
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			if (do_clamp)
+			{
+				if (mask->Constr_N(i).IsUnilateral())
+					mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + ChMax (factor * C->ElementN(cnt), -recovery_clamp)  );
+				else 
+					mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + ChMin(ChMax (factor * C->ElementN(cnt), -recovery_clamp), recovery_clamp)  );
+			}
+			else
+				mask->Constr_N(i).Set_b_i( mask->Constr_N(i).Get_b_i() + factor * C->ElementN(cnt)  );
+
+			cnt++;
+		}
+	}
+}
+
+void ChLinkMateGeneric::ConstraintsBiLoad_Ct(double)
+{
+	if (!this->IsActive())
+		return;
+
+	// NOT NEEDED BECAUSE NO RHEONOMIC TERM
+	
+}
+
+
+
+void ChLinkMateGeneric::ConstraintsLoadJacobians()
+{
+	// already loaded when doing Update (which used the matrices of the scalar constraint objects)
+
+	
+}
+ 
+
+void ChLinkMateGeneric::ConstraintsFetch_react(double factor)
+{
+	react_force  = VNULL;
+	react_torque = VNULL;
+
+	if (!this->IsActive())
+		return;
+
+	int nc = 0;
+	if (c_x) 
+	{
+		if (mask->Constr_N(nc).IsActive())
+			react_force.x = - mask->Constr_N(nc).Get_l_i() * factor;
+		nc++;
+	}
+	if (c_y) 
+	{
+		if (mask->Constr_N(nc).IsActive())
+			react_force.y = - mask->Constr_N(nc).Get_l_i() * factor;
+		nc++;
+	}
+	if (c_z) 
+	{
+		if (mask->Constr_N(nc).IsActive())
+			react_force.z = - mask->Constr_N(nc).Get_l_i() * factor;
+		nc++;
+	}
+	if (c_rx) 
+	{
+		if (mask->Constr_N(nc).IsActive())
+			react_torque.x = - 0.5*mask->Constr_N(nc).Get_l_i() * factor;
+		nc++;
+	}
+	if (c_ry) 
+	{
+		if (mask->Constr_N(nc).IsActive())
+			react_torque.y = - 0.5*mask->Constr_N(nc).Get_l_i() * factor;
+		nc++;
+	}
+	if (c_rz) 
+	{
+		if (mask->Constr_N(nc).IsActive())
+			react_torque.z = - 0.5*mask->Constr_N(nc).Get_l_i() * factor;
+		nc++;
+	}
+
+	
+}
+
+
+int ChLinkMateGeneric::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			
+						   ChVector<> mpt2,  		
+						   ChVector<> mnorm1,		
+						   ChVector<> mnorm2  
+						   )
+{
+	assert(mbody1.get_ptr() != mbody2.get_ptr());
+	assert(mbody1->GetSystem() == mbody2->GetSystem());
+
+	this->Body1 = mbody1.get_ptr();
+	this->Body2 = mbody2.get_ptr();
+	this->SetSystem(mbody1->GetSystem());
+
+	this->mask->SetTwoBodiesVariables(&Body1->Variables(), &Body2->Variables());
+	
+	ChVector<> mx, my, mz, mN;
+	ChMatrix33<> mrot;
+
+	ChFrame<> mfr1;
+	ChFrame<> mfr2;
+
+	if (pos_are_relative)
+	{
+		mN = mnorm1;
+		mN.DirToDxDyDz(&mx, &my, &mz);
+		mrot.Set_A_axis(mx,my,mz);
+		mfr1.SetRot(mrot);
+		mfr1.SetPos(mpt1);
+
+		mN = mnorm2;
+		mN.DirToDxDyDz(&mx, &my, &mz);
+		mrot.Set_A_axis(mx,my,mz);
+		mfr2.SetRot(mrot);
+		mfr2.SetPos(mpt2);
+	}
+	else
+	{
+
+		ChVector<> temp=VECT_Z;
+		// from abs to body-rel
+		mN = this->Body1->Dir_World2Body(&mnorm1);
+		mN.DirToDxDyDz(&mx, &my, &mz, &temp);
+		mrot.Set_A_axis(mx,my,mz);
+		mfr1.SetRot(mrot);
+		mfr1.SetPos(this->Body1->Point_World2Body(&mpt1));
+
+		mN = this->Body2->Dir_World2Body(&mnorm2);
+		mN.DirToDxDyDz(&mx, &my, &mz, &temp);
+		mrot.Set_A_axis(mx,my,mz);
+		mfr2.SetRot(mrot);
+		mfr2.SetPos(this->Body2->Point_World2Body(&mpt2));
+	}
+
+	this->frame1 = mfr1;
+	this->frame2 = mfr2;
+
+	return true;
+}
+
+
+
+// 
+// Following functions are for exploiting persistence
+//
+
+void  ChLinkMateGeneric::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			mask->Constr_N(i).Set_l_i( cache_li_speed->ElementN(cnt) );
+			cnt++;
+		}
+	}
+}
+
+void  ChLinkMateGeneric::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			mask->Constr_N(i).Set_l_i( cache_li_pos->ElementN(cnt) ) ;
+			cnt++;
+		}
+	}
+}
+
+void  ChLinkMateGeneric::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			cache_li_speed->ElementN(cnt) = mask->Constr_N(i).Get_l_i();
+			cnt++;
+		}
+	}
+}
+
+void  ChLinkMateGeneric::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	int cnt=0;
+	for (int i=0; i< mask->nconstr; i++)
+	{
+		if (mask->Constr_N(i).IsActive())
+		{
+			cache_li_pos->ElementN(cnt) = mask->Constr_N(i).Get_l_i();
+			cnt++;
+		}
+	}
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMatePlane> a_registration_ChLinkMatePlane;
+
+
+void ChLinkMatePlane::Copy(ChLinkMatePlane* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMateGeneric::Copy(source);
+	
+	this->flipped = source->flipped;
+	this->separation = source->separation;
+}
+
+ChLink* ChLinkMatePlane::new_Duplicate ()
+{
+    ChLinkMatePlane * m_l = new ChLinkMatePlane;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+void ChLinkMatePlane::SetFlipped(bool doflip)
+{
+	if (doflip != this->flipped)
+	{
+		// swaps direction of X axis by flippping 180� the frame A (slave)
+
+		ChFrame<> frameRotator(VNULL, Q_from_AngAxis(CH_C_PI, VECT_Y));
+		this->frame1.ConcatenatePostTransformation(frameRotator);
+
+		this->flipped = doflip;
+	}
+}
+
+
+int ChLinkMatePlane::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< point on slave plane, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2,  		///< point on master plane, for 2nd body (rel. or abs., see flag above)
+						   ChVector<> mnorm1,		///< normal of slave plane, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mnorm2  		///< normal of master plane, for 2nd body (rel. or abs., see flag above)
+						   )
+{
+	// set the two frames so that they have the X axis aligned when the
+	// two normals are opposed (default behavior, otherwise is considered 'flipped')
+
+	ChVector<> mnorm1_reversed;
+	if (!this->flipped)
+		mnorm1_reversed = -mnorm1;
+	else
+		mnorm1_reversed = mnorm1;
+
+	return ChLinkMateGeneric::Initialize(mbody1, mbody2, 
+								pos_are_relative, 
+								mpt1, mpt2, 
+								mnorm1_reversed, mnorm2);
+
+}
+
+
+/// Override _all_ time, jacobian etc. updating.
+void ChLinkMatePlane::Update (double mtime)
+{
+	// Parent class inherit
+	ChLinkMateGeneric::Update(mtime);
+
+	// .. then add the effect of imposed distance on C residual vector
+	this->C->Element(0,0) -= this->separation; // for this mate, C = {Cx, Cry, Crz}
+
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMateCoaxial> a_registration_ChLinkMateCoaxial;
+
+
+void ChLinkMateCoaxial::Copy(ChLinkMateCoaxial* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMateGeneric::Copy(source);
+	
+	this->flipped = source->flipped;
+}
+
+ChLink* ChLinkMateCoaxial::new_Duplicate ()
+{
+    ChLinkMateCoaxial * m_l = new ChLinkMateCoaxial;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+void ChLinkMateCoaxial::SetFlipped(bool doflip)
+{
+	if (doflip != this->flipped)
+	{
+		// swaps direction of X axis by flippping 180� the frame A (slave)
+
+		ChFrame<> frameRotator(VNULL, Q_from_AngAxis(CH_C_PI, VECT_Y));
+		this->frame1.ConcatenatePostTransformation(frameRotator);
+
+		this->flipped = doflip;
+	}
+}
+
+
+int ChLinkMateCoaxial::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			
+						   ChVector<> mpt2,  		
+						   ChVector<> mnorm1,		
+						   ChVector<> mnorm2  		
+						   )
+{
+	// set the two frames so that they have the X axis aligned when the
+	// two normals are opposed (default behavior, otherwise is considered 'flipped')
+
+	ChVector<> mnorm1_reversed;
+	if (!this->flipped)
+		mnorm1_reversed = mnorm1;
+	else
+		mnorm1_reversed = -mnorm1;
+
+	return ChLinkMateGeneric::Initialize(mbody1, mbody2, 
+								pos_are_relative, 
+								mpt1, mpt2, 
+								mnorm1_reversed, mnorm2);
+}
+
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMateSpherical> a_registration_ChLinkMateSpherical;
+
+
+void ChLinkMateSpherical::Copy(ChLinkMateSpherical* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMateGeneric::Copy(source);
+	
+}
+
+ChLink* ChLinkMateSpherical::new_Duplicate ()
+{
+    ChLinkMateSpherical * m_l = new ChLinkMateSpherical;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+int ChLinkMateSpherical::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			
+						   ChVector<> mpt2 		
+						   )
+{
+	return ChLinkMateGeneric::Initialize(mbody1, mbody2, 
+								pos_are_relative, 
+								mpt1, mpt2, 
+								VECT_X, VECT_X);
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMateXdistance> a_registration_ChLinkMateXdistance;
+
+
+void ChLinkMateXdistance::Copy(ChLinkMateXdistance* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMateGeneric::Copy(source);
+
+	// ...then copy class data
+	this->distance = source->distance;
+}
+
+ChLink* ChLinkMateXdistance::new_Duplicate ()
+{
+    ChLinkMateXdistance * m_l = new ChLinkMateXdistance;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+int ChLinkMateXdistance::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			
+						   ChVector<> mpt2,
+						   ChVector<> mdir2
+						   )
+{
+	return ChLinkMateGeneric::Initialize(mbody1, mbody2, 
+								pos_are_relative, 
+								mpt1, mpt2, 
+								mdir2, mdir2);
+}
+
+
+void ChLinkMateXdistance::Update (double mtime)
+{
+	// Parent class inherit
+	ChLinkMateGeneric::Update(mtime);
+
+	// .. then add the effect of imposed distance on C residual vector
+	this->C->Element(0,0) -= this->distance; // for this mate, C = {Cx}
+
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMateParallel> a_registration_ChLinkMateParallel;
+
+
+void ChLinkMateParallel::Copy(ChLinkMateParallel* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMateGeneric::Copy(source);
+}
+
+ChLink* ChLinkMateParallel::new_Duplicate ()
+{
+    ChLinkMateParallel * m_l = new ChLinkMateParallel;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+void ChLinkMateParallel::SetFlipped(bool doflip)
+{
+	if (doflip != this->flipped)
+	{
+		// swaps direction of X axis by flippping 180� the frame A (slave)
+
+		ChFrame<> frameRotator(VNULL, Q_from_AngAxis(CH_C_PI, VECT_Y));
+		this->frame1.ConcatenatePostTransformation(frameRotator);
+
+		this->flipped = doflip;
+	}
+}
+
+int ChLinkMateParallel::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			
+						   ChVector<> mpt2,  		
+						   ChVector<> mnorm1,		
+						   ChVector<> mnorm2  		
+						   )
+{
+	// set the two frames so that they have the X axis aligned when the
+	// two axes are aligned (default behavior, otherwise is considered 'flipped')
+
+	ChVector<> mnorm1_reversed;
+	if (!this->flipped)
+		mnorm1_reversed = mnorm1;
+	else
+		mnorm1_reversed = -mnorm1;
+
+	return ChLinkMateGeneric::Initialize(mbody1, mbody2, 
+								pos_are_relative, 
+								mpt1, mpt2, 
+								mnorm1_reversed, mnorm2);
+}
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkMateOrthogonal> a_registration_ChLinkMateOrthogonal;
+
+
+void ChLinkMateOrthogonal::Copy(ChLinkMateOrthogonal* source)
+{
+    // first copy the parent class data...
+    ChLinkMateGeneric::Copy(source);
+
+	// ..then class data
+	this->reldir1 = source->reldir1;
+	this->reldir2 = source->reldir2;
+}
+
+ChLink* ChLinkMateOrthogonal::new_Duplicate ()
+{
+    ChLinkMateOrthogonal * m_l = new ChLinkMateOrthogonal;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+int ChLinkMateOrthogonal::Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> ,			
+						   ChVector<> ,  		
+						   ChVector<> mnorm1,		
+						   ChVector<> mnorm2  		
+						   )
+{
+	// set the two frames so that they have the X axis aligned 
+
+	ChVector<> mabsnorm1, mabsnorm2;
+	if (pos_are_relative)
+	{
+		this->reldir1 = mnorm1;
+		this->reldir2 = mnorm2;
+	}
+	else
+	{
+		this->reldir1 = mbody1->Dir_World2Body(&mnorm1);
+		this->reldir2 = mbody2->Dir_World2Body(&mnorm2);
+	}
+
+	// do this asap otherwise the following Update() won't work..
+	this->Body1 = mbody1.get_ptr();
+	this->Body2 = mbody2.get_ptr();
+
+	// Force the alignment of frames so that the X axis is cross product of two dirs, etc.
+	// by calling the custom update function of ChLinkMateOrthogonal.
+	this->Update(this->ChTime);
+
+	// Perform initialization (set pointers to variables, etc.)
+	return ChLinkMateGeneric::Initialize(mbody1, mbody2, 
+								true, // recycle already-updated frames 
+								this->frame1, this->frame2);
+}
+
+
+/// Override _all_ time, jacobian etc. updating.
+void ChLinkMateOrthogonal::Update (double mtime)
+{
+	// Prepare the alignment of the two frames so that the X axis is orthogonal 
+	// to the two directions
+
+	ChVector<> mabsD1, mabsD2;
+
+	if (this->Body1 && this->Body2)
+	{
+		mabsD1 = this->Body1->Dir_Body2World(&this->reldir1);
+		mabsD2 = this->Body2->Dir_Body2World(&this->reldir2);
+
+		ChVector<> mX = Vcross(mabsD2,mabsD1);
+		double xlen = mX.Length();
+
+		// Ops.. parallel directions? -> fallback to singularity handling
+		if (fabs(xlen) < 1e-20)
+		{
+			ChVector<> ortho_gen;
+			if (fabs(mabsD1.z) < 0.9)	
+				ortho_gen = VECT_Z;
+			if (fabs(mabsD1.y) < 0.9)
+				ortho_gen = VECT_Y;
+			if (fabs(mabsD1.x) < 0.9)
+				ortho_gen = VECT_X;
+			mX = Vcross(mabsD1, ortho_gen);
+			xlen = Vlenght(mX);
+		}
+		mX.Scale(1.0/xlen);
+
+		ChVector<> mY1, mZ1;
+		mZ1 = mabsD1;
+		mY1 = Vcross(mZ1, mX);
+		
+		ChMatrix33<> mA1; 
+		mA1.Set_A_axis(mX,mY1,mZ1);
+
+		ChVector<> mY2, mZ2;
+		mY2 = mabsD2;
+		mZ2 = Vcross(mX, mY2);
+
+		ChMatrix33<> mA2; 
+		mA2.Set_A_axis(mX,mY2,mZ2);
+
+		ChFrame<> absframe1(VNULL,mA1);	// position not needed for orth. constr. computation
+		ChFrame<> absframe2(VNULL,mA2);	// position not needed for orth. constr. computation
+
+		// from abs to body-rel
+		static_cast<ChFrame<>*>(this->Body1)->TrasformParentToLocal(absframe1, this->frame1);
+		static_cast<ChFrame<>*>(this->Body2)->TrasformParentToLocal(absframe2, this->frame2);
+	}
+
+	// Parent class inherit
+	ChLinkMateGeneric::Update(mtime);
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkMate.h b/SRC/ChronoEngine/physics/ChLinkMate.h
new file mode 100644
index 0000000..4015890
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkMate.h
@@ -0,0 +1,638 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKMATE_H
+#define CHLINKMATE_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkMate.h
+//
+//   Classes for enforcing constraints of simple
+//   types (geometric mating)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+//***WORK IN PROGRESS***
+
+#include "physics/ChLink.h"
+#include "physics/ChLinkMask.h"
+
+
+namespace chrono
+{
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATE	41
+
+///
+/// Base class for all 'simple' constraints between 
+/// two frames attached to two bodies. These constraints 
+/// can correspond to the typical 'mating' conditions that
+/// are created in assemblies of 3D CAD tools (parallel
+/// axis, or face-to-face, etc.).
+/// Note that most of the ChLinkMate constraints can be
+/// done also with the contraints inherited from ChLinkLock...
+/// but in case of links of the ChLinkLock class they 
+/// reference two ChMarker objects, tht can also move, but
+/// this is could be an unnecessary complication in most cases.
+///
+
+class ChApi ChLinkMate : public ChLink {
+
+	CH_RTTI(ChLinkMate,ChLink);
+
+protected:
+				//
+	  			// DATA
+				//
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMate () {};
+	virtual ~ChLinkMate () {};
+	virtual void Copy(ChLinkMate*) {};
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATE;}
+
+				//
+				// STREAMING
+				//
+
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+	virtual void StreamOUT(ChStreamOutAscii&) {};
+};
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATEGENERIC	42
+
+///
+/// Generic mate constraint, where one can select which 
+/// DOF must be constrained between two frames attached to 
+/// the two bodies.
+///
+
+
+class ChApi ChLinkMateGeneric : public ChLinkMate {
+
+	CH_RTTI(ChLinkMateGeneric,ChLinkMate);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	ChFrame<> frame1;
+	ChFrame<> frame2;
+
+	bool c_x;
+	bool c_y;
+	bool c_z;
+	bool c_rx;
+	bool c_ry;
+	bool c_rz;
+
+	int ndoc;			// number of DOC, degrees of costraint
+	int ndoc_c;			// number of DOC, degrees of costraint (only bilaterals)
+	int ndoc_d;			// number of DOC, degrees of costraint (only unilaterals)
+
+	ChLinkMask* mask;
+	
+	ChMatrix<>* C; // residuals
+
+	ChMatrix<>* cache_li_pos;
+	ChMatrix<>* cache_li_speed;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMateGeneric (bool mc_x=true, bool mc_y=true, bool mc_z=true, bool mc_rx=true, bool mc_ry=true, bool mc_rz=true);
+	virtual ~ChLinkMateGeneric ();
+	virtual void Copy(ChLinkMateGeneric* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATEGENERIC;}
+
+					/// Get the link coordinate system, expressed relative to Body2 (the 'master'
+					/// body). This represents the 'main' reference of the link: reaction forces 
+					/// are expressed in this coordinate system.
+					/// (It is the coordinate system of the contact plane relative to Body2)
+	virtual ChCoordsys<> GetLinkRelativeCoords() {return frame2.GetCoord();};
+
+					/// Get the master coordinate system for the assets (this will return the 
+					/// absolute coordinate system of the 'master' marker2)
+	virtual ChFrame<> GetAssetsFrame(unsigned int=0) { return (frame2 >> *this->GetBody2() );}
+
+					/// Access the coordinate system considered attached to body1.
+					/// Its position is expressed in the coordinate system of body1.
+	ChFrame<>& GetFrame1() {return frame1;};
+
+					/// Access the coordinate system considered attached to body1.
+					/// Its position is expressed in the coordinate system of body1.
+	ChFrame<>& GetFrame2() {return frame2;};
+
+	bool IsConstrainedX() {return c_x;}
+	bool IsConstrainedY() {return c_y;}
+	bool IsConstrainedZ() {return c_z;}
+	bool IsConstrainedRx() {return c_rx;}
+	bool IsConstrainedRy() {return c_ry;}
+	bool IsConstrainedRz() {return c_rz;}
+
+					/// Sets which movements (of frame 1 respect to frame 2) are constrained
+	virtual void SetConstrainedCoords(bool mc_x, bool mc_y, bool mc_z, bool mc_rx, bool mc_ry, bool mc_rz);
+
+					/// Specialized initialization for generic mate, given the two bodies to be connected, the
+					/// positions of the two frames to connect on the bodies (each expressed
+					/// in body or abs. coordinates).
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+			       ChSharedPtr<ChBody>& mbody2, ///< second body to link
+			       bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+			       ChFrame<> mframe1,		///< mate frame (slave), for 1st body (rel. or abs., see flag above)
+			       ChFrame<> mframe2  		///< mate frame (master), for 2nd body (rel. or abs., see flag above) 
+			       );
+
+
+					/// Initialization based on passing two vectors (point + dir) on the 
+					/// two bodies, they will represent the X axes of the two frames (Y and Z will
+					/// be built from the X vector via Gramm Schmidt orthonomralization). 
+					/// Use the other ChLinkMateGeneric::Initialize() if you want to set the two frames directly.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< origin of slave frame 1, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2,  		///< origin of master frame 2, for 2nd body (rel. or abs., see flag above)
+						   ChVector<> mnorm1,		///< X axis of slave plane, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mnorm2  		///< X axis of master plane, for 2nd body (rel. or abs., see flag above)
+						   );
+
+
+
+				//
+				// UPDATING FUNCTIONS
+				//
+
+					/// Override _all_ time, jacobian etc. updating.
+	virtual void Update (double mtime);
+
+						/// If some constraint is redundant, return to normal state
+	virtual int  RestoreRedundant();		   ///< \return number of changed states
+
+					/// Set the status of link validity
+	virtual void SetValid(bool mon) {valid = mon;}
+
+					/// User can use this to enable/disable all the constraint of
+					/// the link as desired.
+	virtual void SetDisabled(bool mdis);
+
+					/// Ex:3rd party software can set the 'broken' status via this method
+	virtual void SetBroken(bool mon);
+
+	virtual int GetDOC  () {return ndoc;}
+	virtual int GetDOC_c  () {return ndoc_c;}
+	virtual int GetDOC_d  () {return ndoc_d;}
+
+				//
+				// LCP INTERFACE
+				//
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+protected:
+	void SetupLinkMask();
+	void ChangedLinkMask();
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATEPLANE	43
+
+///
+/// Mate constraint of plane-to-plane type. This correspond to the
+/// typical planar face vs planar face mating used in 3D CAD assemblies.
+/// The planes are defined by the Y and Z axes of the two frames.
+///
+
+class ChApi ChLinkMatePlane : public ChLinkMateGeneric {
+
+	CH_RTTI(ChLinkMatePlane,ChLinkMateGeneric);
+
+protected:
+
+	bool	flipped;
+	double	separation;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMatePlane () : ChLinkMateGeneric(true, false, false, false, true,true) {flipped = false; separation=0;};
+	virtual ~ChLinkMatePlane () {};
+	virtual void Copy(ChLinkMatePlane* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATEPLANE;}
+
+					/// Tell if the two normals must be opposed (flipped=false) or must have the same verse (flipped=true)
+	void SetFlipped(bool doflip);
+	bool IsFlipped() {return flipped;}
+
+					/// Set the distance between the two planes, in normal direction
+	void SetSeparation(double msep) {separation = msep;}
+					/// Get the requested distance between the two planes, in normal direction
+	double GetSeparation() {return separation;}
+
+
+					/// Specialized initialization for plane-plane mate, given the two bodies to be connected,
+					/// two points on the two faces, two normals on the faces (each expressed
+					/// in body or abs. coordinates). 
+					/// Use ChLinkMateGeneric::Initialize() if you want to set the two frames directly.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< point on slave plane, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2,  		///< point on master plane, for 2nd body (rel. or abs., see flag above)
+						   ChVector<> mnorm1,		///< normal of slave plane, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mnorm2  		///< normal of master plane, for 2nd body (rel. or abs., see flag above)
+						   );
+
+					/// Override _all_ time, jacobian etc. updating, inheriting parent but also adding the effect of separation
+	virtual void Update (double mtime);
+
+};
+
+
+
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATECOAXIAL	44
+
+///
+/// Mate constraint of coaxial type. This correspond to the
+/// typical cylinder-vs-cylinder mating used in 3D CAD assemblies.
+/// The two coaxial axes are the X axes of the two frames.
+///
+
+class ChApi ChLinkMateCoaxial : public ChLinkMateGeneric {
+
+	CH_RTTI(ChLinkMateCoaxial,ChLinkMateGeneric);
+
+protected:
+
+	bool	flipped;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMateCoaxial () : ChLinkMateGeneric(false, true, true, false, true,true) {flipped = false;};
+	virtual ~ChLinkMateCoaxial () {};
+	virtual void Copy(ChLinkMateCoaxial* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATECOAXIAL;}
+
+					/// Tell if the two axes must be opposed (flipped=false) or must have the same verse (flipped=true)
+	void SetFlipped(bool doflip);
+	bool IsFlipped() {return flipped;}
+
+					/// Specialized initialization for coaxial mate, given the two bodies to be connected,
+					/// two points, two directions (each expressed in body or abs. coordinates). 
+					/// Use ChLinkMateGeneric::Initialize() if you want to set the two frames directly.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< point on slave axis, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2, 		///< point on master axis, for 2nd body (rel. or abs., see flag above)
+						   ChVector<> mdir1,		///< direction of slave axis, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mdir2  		///< direction of master axis, for 2nd body (rel. or abs., see flag above)
+						   );
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATESPHERICAL	45
+
+///
+/// Mate constraint of spherical type. This correspond to the
+/// typical point-on-point or spherical joint mating used in 3D CAD assemblies.
+///
+
+class ChApi ChLinkMateSpherical : public ChLinkMateGeneric {
+
+	CH_RTTI(ChLinkMateSpherical,ChLinkMateGeneric);
+
+protected:
+
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMateSpherical () : ChLinkMateGeneric(true, true, true, false, false, false) {} ;
+	virtual ~ChLinkMateSpherical () {};
+	virtual void Copy(ChLinkMateSpherical* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATESPHERICAL;}
+
+
+					/// Specialized initialization for coincident mate, given the two bodies to be connected,
+					/// and two points (each expressed in body or abs. coordinates). 
+					/// Use ChLinkMateGeneric::Initialize() if you want to set the two frames directly.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< point, slave, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2  		///< point, master, for 2nd body (rel. or abs., see flag above)
+						   );
+
+};
+
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATEXDISTANCE	48
+
+///
+/// Mate constraining distance of origin of frame B respect to X axis of
+/// frame A.
+///
+
+class ChApi ChLinkMateXdistance : public ChLinkMateGeneric {
+
+	CH_RTTI(ChLinkMateXdistance,ChLinkMateGeneric);
+
+protected:
+
+	double distance;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMateXdistance () : ChLinkMateGeneric(true, false, false, false, false, false) { distance =0;} ;
+	virtual ~ChLinkMateXdistance () {};
+	virtual void Copy(ChLinkMateXdistance* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATEXDISTANCE;}
+
+					/// Set the distance on X of frame 2
+	void SetDistance(double msep) {distance = msep;}
+					/// Get the requested distance on X of frame 2
+	double GetDistance() {return distance;}
+
+					/// Specialized initialization for X distance mate, given the two bodies to be connected,
+					/// and two points (each expressed in body or abs. coordinates). 
+					/// Use ChLinkMateGeneric::Initialize() if you want to set the two frames directly.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< point, slave, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2,  		///< point, master, for 2nd body (rel. or abs., see flag above)
+						   ChVector<> mdir2  		///< direction of master axis, for 2nd body (rel. or abs., see flag above)
+						   );
+
+						/// Override _all_ time, jacobian etc. updating, inheriting parent but also adding the effect of separation
+	virtual void Update (double mtime);
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATEPARALLEL	46
+
+///
+/// Mate constraint of parallel type. This correspond to the
+/// typical axis-is-parallel-to-axis (or edge to edge, etc.) mating 
+/// used in 3D CAD assemblies. The axes to be kept parallel are
+/// the two X axes of the two frames.
+///
+
+class ChApi ChLinkMateParallel : public ChLinkMateGeneric {
+
+	CH_RTTI(ChLinkMateParallel,ChLinkMateGeneric);
+
+protected:
+
+	bool flipped;
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMateParallel () : ChLinkMateGeneric(false, false, false, false, true, true) { flipped = false;} ;
+	virtual ~ChLinkMateParallel () {};
+	virtual void Copy(ChLinkMateParallel* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATEPARALLEL;}
+
+					/// Tell if the two axes must be opposed (flipped=false) or must have the same verse (flipped=true)
+	void SetFlipped(bool doflip);
+	bool IsFlipped() {return flipped;}
+
+					/// Specialized initialization for parallel mate, given the two bodies to be connected,
+					/// two points and two directions (each expressed in body or abs. coordinates). 
+					/// Use ChLinkMateGeneric::Initialize() if you want to set the two frames directly.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< point on slave axis, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2,  		///< point on master axis, for 2nd body (rel. or abs., see flag above)
+						   ChVector<> mdir1,		///< direction of slave axis, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mdir2  		///< direction of master axis, for 2nd body (rel. or abs., see flag above
+						   );
+
+};
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+
+
+
+// Unique link identifier, for detecting type faster than with rtti. (Obsolete)
+#define LNK_MATEORTHOGONAL	47
+
+///
+/// Mate constraint of orthogonal type. This correspond to the
+/// typical axis-is-orthogonal-to-axis (or edge to edge, etc.) mating 
+/// used in 3D CAD assemblies. The the two X axes of the two frames
+/// are aligned to the cross product of the two directions.
+///
+
+class ChApi ChLinkMateOrthogonal : public ChLinkMateGeneric {
+
+	CH_RTTI(ChLinkMateOrthogonal,ChLinkMateGeneric);
+
+protected:
+	ChVector<> reldir1;
+	ChVector<> reldir2;
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChLinkMateOrthogonal () : ChLinkMateGeneric(false, false, false, true, false, false) {reldir1=VECT_X; reldir2=VECT_Y;} ;
+	virtual ~ChLinkMateOrthogonal () {};
+	virtual void Copy(ChLinkMateOrthogonal* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+				//
+	  			// FUNCTIONS
+				//
+
+	virtual int GetType	() {return LNK_MATEORTHOGONAL;}
+
+
+					/// Specialized initialization for orthogonal mate, given the two bodies to be connected,
+					/// two points and two directions (each expressed in body or abs. coordinates). 
+					/// Use ChLinkMateGeneric::Initialize() if you want to set the two frames directly.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpt1,			///< point on slave axis, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpt2,  		///< point on master axis, for 2nd body (rel. or abs., see flag above)
+						   ChVector<> mdir1,		///< direction of slave axis, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mdir2  		///< direction of master axis, for 2nd body (rel. or abs., see flag above
+						   );
+
+					/// Override _all_ time, jacobian etc. updating, inheriting parent but also adding the effect of separation
+	virtual void Update (double mtime);
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkNumdiff.cpp b/SRC/ChronoEngine/physics/ChLinkNumdiff.cpp
new file mode 100644
index 0000000..dfff57c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkNumdiff.cpp
@@ -0,0 +1,294 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkNumdiff.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkNumdiff.h"
+
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkNumdiff> a_registration_ChLinkNumdiff;
+
+
+            // BUILD
+ChLinkNumdiff::ChLinkNumdiff ()
+{
+}
+
+            // DESTROY
+ChLinkNumdiff::~ChLinkNumdiff ()
+{
+}
+
+
+void ChLinkNumdiff::Copy(ChLinkNumdiff* source)
+{
+    // first copy the parent class data...
+    ChLinkMasked::Copy(source);
+
+}
+
+
+ChLink* ChLinkNumdiff::new_Duplicate ()   // inherited classes:  Link* MyInheritedLink::new_Duplicate()
+{
+    ChLinkNumdiff* m_l;
+    m_l = new ChLinkNumdiff;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+////////////////////////////////////
+///
+///    UPDATING PROCEDURES
+
+
+
+
+
+ 
+/////////       COMPUTE C    -updates the value of C residuals, given current coordinates & time
+/////////                     C = C(q,t)
+
+void ChLinkNumdiff::ComputeC ()
+{
+    // ** Child classes must implement this constraint evaluation, in order
+    //    to allow this base class to perform backward differentiation to get
+    //    all state matrices.
+    //    This function can be called many times by UpdateState() for the numerical
+    //    differentiation.
+    //
+    //    Example: C = my_constraint_functionXXX(distance_between_markers,time), etc.
+    //
+    //    Default: do nothing (residual always zero)
+
+    C->Reset();     // default: always no violation. C = 0;
+}
+
+
+/////////     COMPUTE Ct
+/////////
+
+
+void ChLinkNumdiff::ComputeCt ()
+{
+    ChMatrixDynamic<> m_q(GetNumCoords(), 1);       // coordinates
+    FetchCoords(&m_q);          // current state coordinates = position of bodies 1&2
+
+    double m_tdt = ChTime + BDF_STEP_VERYLOW;
+
+    ChMatrixDynamic<> C_qt(ndoc,1);            //  C(q,t)      // assuming C is already updated (computed)!!
+    C_qt.CopyFromMatrix(*this->C);
+
+    ChMatrixDynamic<> C_qdt(ndoc,1);           //  C(q,t+dt)
+    ImposeCoords(&m_q, m_tdt);
+    ComputeC();
+    C_qdt.CopyFromMatrix(*this->C);
+
+    Ct->MatrSub(C_qdt, C_qt);         // Ct
+    Ct->MatrScale(1.0/BDF_STEP_VERYLOW);
+}
+
+
+/////////    COMPUTE Cq
+/////////
+
+void ChLinkNumdiff::ComputeCq ()
+{
+    double orig;
+
+    ChMatrixDynamic<> m_q(GetNumCoords(), 1);       // current coordinates
+    FetchCoords(&m_q);              // current state coordinates = position of bodies 1&2
+
+    ChMatrixDynamic<> C_dqt(ndoc,1);
+    ChMatrixDynamic<> Cq_column(ndoc, 1);
+    ChMatrixDynamic<> C_qt(ndoc,1);            //  C(q,t)      // assuming C is already updated (computed)!!
+    C_qt.CopyFromMatrix(*this->C);
+
+    for (int i= 0; i< GetNumCoords(); i++)
+    {
+        orig = m_q(i,0);
+        m_q(i,0) = orig + BDF_STEP_VERYLOW;
+        ImposeCoords(&m_q, ChTime);
+        ComputeC();
+        C_dqt.CopyFromMatrix(*this->C);      // C(dqi,t)
+
+        Cq_column.MatrSub(C_dqt, C_qt);
+        Cq_column.MatrScale(1.0/BDF_STEP_VERYLOW);
+
+        if (i<BODY_QDOF)
+            this->Cq1->PasteMatrix(&Cq_column,0,i);             // jacobians [Cq], 1&2
+        else
+            this->Cq2->PasteMatrix(&Cq_column,0,(i-BODY_QDOF));
+        m_q(i,0) = orig;
+    }
+}
+
+
+/////////     UPDATE STATE
+/////////
+
+
+void ChLinkNumdiff::UpdateState ()
+{
+    double m_t = ChTime;
+    double m_tdt = ChTime + BDF_STEP_VERYLOW;
+
+    ChMatrixDynamic<> m_q(GetNumCoords(), 1);   // The coordinates q
+    FetchCoords(&m_q);      // current state coordinates = position of bodies 1&2
+
+    ChMatrixDynamic<> m_qdt(GetNumCoords(), 1); // The coordinates q
+    FetchCoords_dt(&m_qdt);     // current state coordinates = position of bodies 1&2
+
+    ChMatrixDynamic<> C_qt(ndoc,1);
+    ComputeC();              //  C(q,t)  (assuming system is now at (q,t) )
+    C_qt.CopyFromMatrix(*this->C);
+
+    ComputeCt();             //  Ct
+
+    ComputeCq();             //  Cq1 and Cq2
+
+
+    ChMatrixDynamic<> m_qdt1(BODY_QDOF,1);
+    ChMatrixDynamic<> m_qdt2(BODY_QDOF,1);
+    m_qdt1.PasteClippedMatrix(&m_qdt, 0,0, BODY_QDOF,1, 0,0);
+    m_qdt2.PasteClippedMatrix(&m_qdt, BODY_QDOF,0, BODY_QDOF,1, 0,0);
+
+    ChMatrixDynamic<> m_temp(ndoc,1);
+
+    m_temp.MatrMultiply(*Cq1, m_qdt1);
+    C_dt->CopyFromMatrix(m_temp);
+    m_temp.MatrMultiply(*Cq2, m_qdt2);
+    C_dt->MatrInc(m_temp);
+    C_dt->MatrInc(*Ct);      // C_dt  = Ct + [Cq](dq/dt);
+
+        // now compute vector gamma for dynamics:  ???
+    //***TO DO***....
+}
+
+
+
+
+
+
+
+
+/////////    -   SET COORDINATES of the two connected bodies
+/////////
+
+void ChLinkNumdiff::ImposeCoords(ChMatrix<>* mc, double t)
+{
+    static Coordsys mcsys;
+
+    mcsys = mc->ClipCoordsys(0,0);
+    Body1->Update(mcsys, Body1->GetCoord_dt(), t);
+
+    mcsys = mc->ClipCoordsys(7,0);
+    Body2->Update(mcsys, Body2->GetCoord_dt(), t);
+
+    // - update the time dependant stuff
+    UpdateTime(t);
+    // - update the relative marker position
+    UpdateRelMarkerCoords();
+}
+
+void ChLinkNumdiff::FetchCoords(ChMatrix<>* mc)
+{
+    static Coordsys mcsys;
+
+    mcsys = Body1->GetCoord();
+    mc->PasteCoordsys(mcsys,0,0);
+
+    mcsys = Body2->GetCoord();
+    mc->PasteCoordsys(mcsys,7,0);
+}
+
+void ChLinkNumdiff::FetchCoords_dt(ChMatrix<>* mc)
+{
+    static Coordsys mcsys;
+
+    mcsys = Body1->GetCoord_dt();
+    mc->PasteCoordsys(mcsys,0,0);
+
+    mcsys = Body2->GetCoord_dt();
+    mc->PasteCoordsys(mcsys,7,0);
+}
+
+
+
+/////////
+///////// FILE I/O
+/////////
+
+
+
+
+void ChLinkNumdiff::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(10);
+		// serialize parent class too
+	ChLinkMasked::StreamOUT(mstream);
+
+		// stream out all member data
+
+}
+
+void ChLinkNumdiff::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkMasked::StreamIN(mstream);
+
+		// stream in all member data
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkNumdiff.h b/SRC/ChronoEngine/physics/ChLinkNumdiff.h
new file mode 100644
index 0000000..5f66ad3
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkNumdiff.h
@@ -0,0 +1,161 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKNUMDIFF_H
+#define CHLINKNUMDIFF_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkNumdiff.h
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkMasked.h"
+
+
+
+namespace chrono
+{
+
+
+
+///
+/// Link for constraints where the jacobians and other 
+/// complex terms are automatically computed by numerical 
+	/// differentiation. ***EXPERIMENTAL*** (UNDER DEVELOPEMENT)
+///
+/// The user can inherit custom constraint classes from this
+/// class, and the only 'big' function to implement is the
+/// ComputeC() function, which must return the residual of the 
+/// constraint, given the state of the bodies and the time. that's all.
+///
+/// Note that numerical differentiation for computing jacobians
+/// might be an easy way to write constraints, but in general it
+/// is slower (and less precise) than with custom analytical approaches
+/// (that's why the ChLinkLock family is not inherited from this 
+/// class and prefer to use a custom analytical expression for 
+/// jacobians).
+///
+
+class ChApi ChLinkNumdiff : public ChLinkMasked {
+
+	CH_RTTI(ChLinkNumdiff,ChLinkMasked);
+
+protected:
+
+				//
+	  			// DATA
+				//
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+	ChLinkNumdiff ();
+	virtual ~ChLinkNumdiff ();
+	virtual void Copy(ChLinkNumdiff* source);
+	virtual ChLink* new_Duplicate ();
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+					///  Forces the system (basically: two connected bodies) into
+					/// the specified states/times. Used internally by numerical
+					/// differentiation, when computing numerially the jacobian,
+					/// by the UpdateState() function. Used by UpdateState() and ComputeK().
+					///  Default: the mc matrix is a vector with "Link::GetNumCoords" rows,
+					/// with the position states (vect1,quat1,vect1,quat2) of Body1 and Body2.
+					/// Note!! It automatically calls, at the end, the
+					/// UpdateTime(time)  and 	UpdateRelMarkerCoords()  functions!!!
+					///  Most often, no need to give specific implementations if the
+					/// q coordinate vector of your constraint equation(s) C(q,t)
+					/// represents the position of the two bodies Body1 and Body2, and it's enough.
+					/// But you must override it, if your inherited link' "numcoords" aren't 14,
+					/// for example if linking 3 bodies, etc -really seldom..-, or body pos & speeds, etc
+	virtual void ImposeCoords(ChMatrix<>* mc, double t);
+
+					/// The opposite: returns the current state into the vector mc,
+					/// which has number of rows = "GetNumCoords()" (def. 14)
+	virtual void FetchCoords(ChMatrix<>* mc);
+
+					/// Same, but returns the _time_derivative_ of current state (the speeds)
+	virtual void FetchCoords_dt(ChMatrix<>* mc);
+
+ 
+					/// >>>> IMPORTANT FUNCTION<<<< 
+					/// Given current time and coordinate state, computes
+					/// the residual vect. of the constraint equations C.
+					///      C = C(q,t)
+					///  NOTE!! If your class inherits from this class, often
+					/// this is the ONLY function you _must_ provide, together with GetDOC(),
+					/// because the base UpdateState() will automatically compute
+					/// the jacobians matrix etc. via numerical differentiation
+					/// (Default: C = 0, no particular constraint)
+	virtual void ComputeC();
+
+					/// Used mostly internally by UpdateState(), to compute Ct term and
+					/// and Cq1, Cq2 jacobian matrices at current (q,t), by numerical differentiation. 
+					/// However, you may override one of these if you know some fast custom 
+					/// analytical expression - otherwise leave these as they are, and 
+					/// the numerical differentiation will do the rest.
+	virtual void ComputeCt();
+	virtual void ComputeCq();
+
+
+			//
+			// UPDATING
+			//
+
+					// Override the parent ChLinkMasked UpdateState(), which does nothing,
+					// because this version will call ComputeCt, ComputeCq to get the 
+					// values of Cq1, Cq2, Qc, Ct. This will happen automatically if one
+					// has provided a proper ComputeC() function in his inherited class.
+	virtual void UpdateState ();
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii& mstream) {};
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkPneumaticActuator.cpp b/SRC/ChronoEngine/physics/ChLinkPneumaticActuator.cpp
new file mode 100644
index 0000000..8acdf60
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkPneumaticActuator.cpp
@@ -0,0 +1,297 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkPneumaticActuator.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+ 
+#include "physics/ChLinkPneumaticActuator.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkPneumaticActuator> a_registration_ChLinkPneumaticActuator;
+
+
+ChLinkPneumaticActuator::ChLinkPneumaticActuator ()
+{
+    type = LNK_PNEUMATIC;       // initializes type
+
+    pneuma = new AssePneumatico();
+    offset = pneuma->Get_L() + 0.1;
+
+    pA = pB = pneuma->Get_Ps(); // default state (initial chamber pressure = ambient pressure)
+    pA_dt = pB_dt = 0;
+    pneu_F = 0;
+    last_force_time = 0;
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to free. It was a LinkMaskLF because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(false, false, false,
+                       false, false, false, false,
+                       false, false);
+
+            // set upper lower limits, active
+    limit_X->Set_active(TRUE);
+    limit_X->Set_min( offset);// 0.0);
+    limit_X->Set_max(pneuma->Get_L()+offset);
+    limit_X->Set_maxElastic(0.0);
+    limit_X->Set_minElastic(0.0);
+
+    ChangedLinkMask();
+}
+
+ChLinkPneumaticActuator::~ChLinkPneumaticActuator ()
+{
+    if (pneuma) delete pneuma;
+    pneuma = NULL;
+}
+
+void ChLinkPneumaticActuator::Copy(ChLinkPneumaticActuator* source)
+{
+    // first copy the parent class data...
+    //
+
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    pneuma->Set_Ci( source->pneuma->Get_Ci() );
+    pneuma->Set_Co( source->pneuma->Get_Co() );
+    pneuma->Set_Bi( source->pneuma->Get_Bi() );
+    pneuma->Set_Bo( source->pneuma->Get_Bo() );
+    pneuma->Set_Ps( source->pneuma->Get_Ps() );
+    pneuma->Set_Pma( source->pneuma->Get_Pma() );
+    pneuma->Set_Pmb( source->pneuma->Get_Pmb() );
+    pneuma->Set_L( source->pneuma->Get_L() );
+    pneuma->Set_Wa( source->pneuma->Get_Wa() );
+    pneuma->Set_Wb( source->pneuma->Get_Wb() );
+    pneuma->Set_A( source->pneuma->Get_A() );
+    pneuma->Set_Alfa( source->pneuma->Get_Alfa() );
+    pneuma->Set_Gamma( source->pneuma->Get_Gamma() );
+    pneuma->Set_ValvA_min( source->pneuma->Get_ValvA_min() );
+    pneuma->Set_ValvA_max( source->pneuma->Get_ValvA_max() );
+    pneuma->Set_ValvA_close( source->pneuma->Get_ValvA_close() );
+    pneuma->Set_ValvB_min( source->pneuma->Get_ValvB_min() );
+    pneuma->Set_ValvB_max( source->pneuma->Get_ValvB_max() );
+    pneuma->Set_ValvB_close( source->pneuma->Get_ValvB_close() );
+    pneuma->SetupAssePneumatico(); // setup into sub objects
+    this->offset = source->offset;
+    this->pA = source->pA;
+    this->pB = source->pB;
+    this->pA_dt = source->pA_dt;
+    this->pB_dt = source->pB_dt;
+    pneuma->Set_P(source->pA, source->pB); // this also copies state into internal structures
+    pneuma->Set_Pos(source->Get_pneu_pos(), source->Get_pneu_pos_dt() );
+    this->pneu_F = source->pneu_F;
+    this->last_force_time = source->last_force_time;
+}
+
+
+void ChLinkPneumaticActuator::Set_lin_offset(double mset)
+{
+    offset = mset;
+    limit_X->Set_min(offset);
+    limit_X->Set_max(pneuma->Get_L()+offset);
+}
+
+void ChLinkPneumaticActuator::Set_pneu_L(double mset)
+{
+    pneuma->Set_L(mset);
+    limit_X->Set_max(pneuma->Get_L()+offset);
+}
+
+
+ChLink* ChLinkPneumaticActuator::new_Duplicate ()
+{
+    ChLinkPneumaticActuator* m_l;
+    m_l = new ChLinkPneumaticActuator;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+void ChLinkPneumaticActuator::UpdateTime (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateTime(mytime);
+
+        // Move (well, rotate...) marker 2 to align it in actuator direction
+
+        // ! Require that the BDF routine of marker won't handle speed and acc.calculus of the moved marker 2!
+    marker2->SetMotionType(ChMarker::M_MOTION_EXTERNAL);
+
+    ChMatrix33<> ma;
+    ma.Set_A_quaternion(marker2->GetAbsCoord().rot);
+
+    Vector absdist = Vsub(marker1->GetAbsCoord().pos,
+                          marker2->GetAbsCoord().pos);
+
+    Vector mx = Vnorm (absdist);
+
+    Vector my = ma.Get_A_Yaxis();
+    if (Vequal(&mx, &my))
+        if  (mx.x == 1.0)   my = VECT_Y;
+        else                my = VECT_X;
+    Vector mz = Vnorm (Vcross(mx, my));
+    my = Vnorm (Vcross(mz, mx));
+
+    ma.Set_A_axis(mx,my,mz);
+
+    Coordsys newmarkpos;
+    newmarkpos.pos = marker2->GetAbsCoord().pos;
+    newmarkpos.rot = ma.Get_A_quaternion();
+    marker2->Impose_Abs_Coord(newmarkpos);        //rotate "main" marker2 into tangent position
+
+}
+
+void ChLinkPneumaticActuator::UpdateForces (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateForces(mytime);
+
+    // DEFAULTS set null forces
+    this->pneu_F = 0;
+
+    // COMPUTE PNEUMATIC FORCE!!
+
+        // 1a - set current state (pressure A and B)
+    this->pneuma->Set_P(this->pA, this->pB);
+        // 1b - set current state (position, speed)
+    this->pneuma->Set_Pos(this->Get_pneu_pos(), this->Get_pneu_pos_dt() );
+
+        // 2- compute new force for this state
+    this->pneuma->Update(); // needed, so that F is computed in pneuma*
+    this->pneu_F = this->pneuma->Get_F();
+
+    // Security clamping on plausible limit, to avoid divergence
+    //if (this->pneu_F > 100000) this->pneu_F = 100000;
+
+
+        // 3- compute new pressures by 'local' integration, from previous
+        //    values of pressures.
+    this->pneuma->Get_P_dt(&this->pA_dt, &this->pB_dt);
+
+    double mforce_timestep = mytime - this->last_force_time;
+    if ( (mforce_timestep < 0.1) &&
+         (mforce_timestep >0) )
+    {
+        this->pA = this->pA + mforce_timestep * this->pA_dt;
+        this->pB = this->pB + mforce_timestep * this->pB_dt;
+
+        if (this->pA < 0) this->pA = 0;
+        if (this->pB < 0) this->pB = 0;
+
+        this->pneuma->Set_P(this->pA, this->pB);
+    }
+
+    this->last_force_time = mytime;
+
+
+    // +++ADD PNEUMATIC FORCE TO LINK INTERNAL FORCE VECTOR (on x axis only)
+
+    C_force.x = C_force.x + this->pneu_F;
+}
+
+
+
+void ChLinkPneumaticActuator::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << pneuma->Get_Ci();
+    mstream << pneuma->Get_Co();
+    mstream << pneuma->Get_Bi();
+    mstream << pneuma->Get_Bo();
+    mstream << pneuma->Get_Ps();
+    mstream << pneuma->Get_Pma();
+    mstream << pneuma->Get_Pmb();
+    mstream << pneuma->Get_L();
+    mstream << pneuma->Get_Wa();
+    mstream << pneuma->Get_Wb();
+    mstream << pneuma->Get_A();
+    mstream << pneuma->Get_Alfa();
+    mstream << pneuma->Get_Gamma();
+    mstream << pneuma->Get_ValvA_min();
+    mstream << pneuma->Get_ValvA_max();
+    mstream << pneuma->Get_ValvA_close();
+    mstream << pneuma->Get_ValvB_min();
+    mstream << pneuma->Get_ValvB_max();
+    mstream << pneuma->Get_ValvB_close();
+    mstream << pA;
+    mstream << pB;
+    mstream << pA_dt;
+    mstream << pB_dt;
+    mstream << pneu_F;
+    mstream << offset;
+}
+
+void ChLinkPneumaticActuator::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	double dfoo;
+	mstream >> dfoo;	pneuma->Set_Ci(dfoo);
+    mstream >> dfoo;	pneuma->Set_Co(dfoo);
+    mstream >> dfoo;	pneuma->Set_Bi(dfoo);
+    mstream >> dfoo;	pneuma->Set_Bo(dfoo);
+    mstream >> dfoo;	pneuma->Set_Ps(dfoo);
+    mstream >> dfoo;	pneuma->Set_Pma(dfoo);
+    mstream >> dfoo;	pneuma->Set_Pmb(dfoo);
+    mstream >> dfoo;	pneuma->Set_L(dfoo);
+    mstream >> dfoo;	pneuma->Set_Wa(dfoo);
+    mstream >> dfoo;	pneuma->Set_Wb(dfoo);
+    mstream >> dfoo;	pneuma->Set_A(dfoo);
+    mstream >> dfoo;	pneuma->Set_Alfa(dfoo);
+    mstream >> dfoo;	pneuma->Set_Gamma(dfoo);
+    mstream >> dfoo;	pneuma->Set_ValvA_min(dfoo);
+    mstream >> dfoo;	pneuma->Set_ValvA_max(dfoo);
+    mstream >> dfoo;	pneuma->Set_ValvA_close(dfoo);
+    mstream >> dfoo;	pneuma->Set_ValvB_min(dfoo);
+    mstream >> dfoo;	pneuma->Set_ValvB_max(dfoo);
+    mstream >> dfoo;	pneuma->Set_ValvB_close(dfoo);
+    mstream >> pA;
+    mstream >> pB;
+    mstream >> pA_dt;
+    mstream >> pB_dt;
+    mstream >> pneu_F;
+    mstream >> dfoo;	Set_lin_offset(dfoo);
+}
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkPneumaticActuator.h b/SRC/ChronoEngine/physics/ChLinkPneumaticActuator.h
new file mode 100644
index 0000000..87f3734
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkPneumaticActuator.h
@@ -0,0 +1,137 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKPNEUMATICACTUATOR_H
+#define CHLINKPNEUMATICACTUATOR_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkPneumaticActuator.h
+//
+//
+//   Classes for pneumatic actuators between two
+//   bodies.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkLock.h"
+#include "pneumatica/assepneumatico.h"
+
+
+
+namespace chrono
+{
+
+using namespace chrono::pneumatics;
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_PNEUMATIC	33
+
+
+///
+/// Class for pneumatic linear actuators between two markers,
+/// as the piston were joined with two spherical
+/// bearing at the origin of the two markers.
+///
+
+class ChApi ChLinkPneumaticActuator : public ChLinkLock {
+
+	CH_RTTI(ChLinkPneumaticActuator,ChLinkLock);
+
+protected:
+							// pointer to internal structure with all pneumatic variables
+	AssePneumatico* pneuma;
+							// marker distance for zero stroke
+	double offset;
+							// read-only vars  (updated in UpdateXyz() functions!!)
+	double pA;		// pressure chamber A
+	double pB;		// pressure chamber B
+	double pA_dt;	// d/dt pressure chamber A
+	double pB_dt;	// d/dt pressure chamber B
+	double pneu_F;	// applied force
+
+	double last_force_time;	// internal
+
+public:
+						// builders and destroyers
+	ChLinkPneumaticActuator ();
+	virtual ~ChLinkPneumaticActuator ();
+	virtual void Copy(ChLinkPneumaticActuator* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+							// UPDATING FUNCTIONS - "lin. pneumatic actuator" custom implementations
+
+							// Updates motion laws, marker positions, etc.
+	virtual void UpdateTime (double mytime);
+							// Updates forces etc.
+	virtual void UpdateForces (double mytime);
+
+							// DATA GET/ SET
+										// for straight access to all internal pneumatic data
+	AssePneumatico* Get_pneuma() {return this->pneuma;};
+										// after setting internal pneumatic datas in 'pneuma'
+	void SetupActuator()			{pneuma->SetupAssePneumatico();};
+
+										// joints offset for zero length stroke
+	double  Get_lin_offset() {return offset;};
+	void    Set_lin_offset(double mset);
+										// cylinder stroke
+	double  Get_pneu_L() {return pneuma->Get_L();};
+	void    Set_pneu_L(double mset);
+
+
+										// state
+	double Get_pA() {return pA;}
+	double Get_pB() {return pB;}
+	double Get_pA_dt() {return pA_dt;}
+	double Get_pB_dt() {return pB_dt;}
+										// actual force
+	double Get_pneu_F() {return pneu_F;}
+										// actual position & speed
+	double Get_pneu_pos()	 {return relM.pos.x - this->offset;};
+	double Get_pneu_pos_dt() {return relM_dt.pos.x;};
+
+										// shortcuts for valve commands
+	void Set_ComA(double ma)	{pneuma->Set_ComA(ma);};
+	double Get_ComA()			{return pneuma->Get_ComA();};
+	void Set_ComB(double ma)	{pneuma->Set_ComB(ma);};
+	double Get_ComB()			{return pneuma->Get_ComB();};
+
+	double Get_pneu_R() {return sqrt(pneuma->Get_A() / CH_C_PI);}
+	void Set_pneu_R(double mr) { pneuma->Set_A(mr*mr*CH_C_PI); pneuma->SetupAssePneumatico();}
+
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkPointSpline.cpp b/SRC/ChronoEngine/physics/ChLinkPointSpline.cpp
new file mode 100644
index 0000000..a29bac1
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkPointSpline.cpp
@@ -0,0 +1,217 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkPointSpline.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+  
+
+#include "physics/ChLinkPointSpline.h"
+#include "physics/ChSystem.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+ 
+
+using namespace geometry;
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkPointSpline> a_registration_ChLinkPointSpline;
+
+
+                // BUILDERS
+ChLinkPointSpline::ChLinkPointSpline ()
+{
+    type = LNK_POINTSPLINE;       // initializes type
+
+	trajectory_line = 0;
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to X  only. It was a LinkMaskLF because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(false, true, true,
+                       false, false, false, false,
+                       false, false);
+
+    ChangedLinkMask();
+}
+
+
+            // DESTROYER
+ChLinkPointSpline::~ChLinkPointSpline ()
+{
+	if (trajectory_line) 
+		delete trajectory_line;
+	trajectory_line=0;
+}
+
+void ChLinkPointSpline::Copy(ChLinkPointSpline* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+	// copy own data
+
+	if (trajectory_line) 
+		delete trajectory_line;
+    trajectory_line = (ChLine*) (source->trajectory_line->Duplicate());
+}
+
+
+ChLink* ChLinkPointSpline::new_Duplicate ()   
+{
+    ChLinkPointSpline* m_l;
+    m_l = new ChLinkPointSpline;  
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+//////////
+
+
+void ChLinkPointSpline::Set_trajectory_line (ChLine* mline)
+{
+	if (trajectory_line) 
+		delete trajectory_line;
+    trajectory_line = mline;
+}
+
+
+
+/////////    UPDATE TIME
+/////////
+
+void ChLinkPointSpline::UpdateTime (double time)
+{
+    ChTime = time;
+
+	double tol=10e-9;
+	if (GetSystem())
+		tol = ((ChSystem*)GetSystem())->GetTol();
+
+	//R3OBJ* markerobj = ((ChExternalObjectR3D*)marker2->GetExternalObject())->Get_r3d_object();
+    //R3OBJ* lineobj = Ch_GetLinkedParamObject(markerobj, 0);
+    if (trajectory_line)
+    {
+        Vector param, ptang, ptang2, vdir, vdir2, vnorm, vrad, vpoint;
+        double mu, ds, dh, mrad;
+
+        // constant update line geometry after each step... it may be rotated by chrono simulation
+        //Ch_ForceUpdateOfR3Dcoords(lineobj); ***TO DO*** move to R3D code!
+
+        // find nearest point
+        vpoint = marker1->GetAbsCoord().pos;
+		trajectory_line->FindNearestLinePoint(vpoint, mu, 0,  ((ChSystem*)GetSystem())->GetTol() );
+		//FindNearestLinePoint (lineobj, (void*)(&vpoint), mu, 0, ((ChSystem*)GetSystem())->GetTol() );
+
+        param.y= 0; param.z= 0;
+        param.x= mu;
+		trajectory_line->Evaluate(ptang, param.x);
+        //R3SendMsgA3(lineobj, R3PRIMM_EVALUATE, (void *)R3SPACE_ABSOLUTE, &param, &ptang);
+        if (param.x < 0) param.x=0;
+		trajectory_line->Derive(vdir, param.x);
+        //R3SendMsgA3(lineobj, R3PRIMM_DERIVE, (void *)R3SPACE_ABSOLUTE, &param, &vdir);
+
+        param.x= mu+ BDF_STEP_HIGH;
+        if (param.x > 1) param.x=1;
+		trajectory_line->Evaluate(ptang2, param.x);
+        //R3SendMsgA3(lineobj, R3PRIMM_EVALUATE, (void *)R3SPACE_ABSOLUTE, &param, &ptang2);
+		trajectory_line->Derive(vdir2, param.x);
+        //R3SendMsgA3(lineobj, R3PRIMM_DERIVE, (void *)R3SPACE_ABSOLUTE, &param, &vdir2);
+
+        vdir = Vnorm(vdir);
+        vdir2 = Vnorm (vdir2);
+        vnorm = Vnorm(Vcross(vdir2, vdir));
+        vrad = Vnorm(Vcross(vdir, vnorm));
+        ChMatrix33<> ma;
+        ma.Set_A_axis(vdir, vnorm, vrad);
+        Quaternion qabsdir = ma.Get_A_quaternion();
+
+        Coordsys newmarkpos;
+        newmarkpos.pos = ptang;
+        newmarkpos.rot = qabsdir;
+        marker2->Impose_Abs_Coord(newmarkpos);       // move "main" marker2 into tangent position
+        marker2->SetMotionType(ChMarker::M_MOTION_EXTERNAL);   // the BDF routine won't handle speed and acc.calculus of the moved marker!
+
+        ds = Vlenght(Vsub(ptang,ptang2));
+        dh = Vdot( Vsub(ptang2, ptang), vrad);
+        mrad = ((ds*ds)/(2*dh)); // radius of curvature on spline
+
+        ChMatrix33<> mw;
+        mw.Set_A_quaternion(marker2->GetAbsCoord().rot);
+
+        deltaC.pos = VNULL;
+        deltaC_dt.pos = VNULL;
+        deltaC_dtdt.pos.x = 0;              // csys X axis aligned to vdir: just
+        deltaC_dtdt.pos.y = 0;              // impose centripetal acceleration
+        //deltaC_dtdt.pos.z =   pow(Vdot(this->GetRelM_dt().pos, vdir), 2) / mrad;
+        deltaC_dtdt.pos.z = pow(GetRelM_dt().pos.x, 2) / mrad;
+
+        deltaC.rot = QUNIT;
+        deltaC_dt.rot = QNULL;
+        deltaC_dtdt.rot = QNULL;
+
+	}
+
+}
+
+
+
+void ChLinkPointSpline::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream.AbstractWrite(trajectory_line);
+}
+
+
+void ChLinkPointSpline::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	ChLine* mline=0;
+	mstream.AbstractReadCreate(&mline);		Set_trajectory_line(mline);
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkPointSpline.h b/SRC/ChronoEngine/physics/ChLinkPointSpline.h
new file mode 100644
index 0000000..837cea1
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkPointSpline.h
@@ -0,0 +1,97 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKPOINTSPLINE_H
+#define CHLINKPOINTSPLINE_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkPointSpline.h
+//
+//
+//   Class for point-on-spline constraint
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkLock.h"
+#include "geometry/ChCLine.h"
+
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_POINTSPLINE 20
+
+
+///
+/// ChLinkPointSpline class.
+/// This class implements the 'point on a spline curve' 
+/// constraint. It can be used also to simulate
+/// curvilinear glyphs, etc.
+///
+
+class ChApi ChLinkPointSpline : public ChLinkLock {
+
+	CH_RTTI(ChLinkPointSpline,ChLinkLock);
+
+protected:
+
+						/// The line for the trajectory.
+	geometry::ChLine*		trajectory_line;
+
+public:
+						// builders and destroyers
+	ChLinkPointSpline ();
+	virtual ~ChLinkPointSpline ();
+	virtual void Copy(ChLinkPointSpline* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+						/// Get the address of the trajectory line
+	geometry::ChLine* Get_trajectory_line() {return trajectory_line;}
+						
+						/// Sets the trajectory line (take ownership - does not copy line)
+	void Set_trajectory_line (geometry::ChLine* mline);
+
+
+
+							// UPDATING FUNCTIONS - "lock formulation" custom implementations
+
+							// Overrides the parent class function. Here it moves the 
+							// constraint mmain marker tangent to the line.
+	virtual void UpdateTime (double mytime);
+
+
+							// STREAMING
+
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkPulley.cpp b/SRC/ChronoEngine/physics/ChLinkPulley.cpp
new file mode 100644
index 0000000..6f67855
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkPulley.cpp
@@ -0,0 +1,320 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkPulley.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+ 
+#include "physics/ChLinkPulley.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+ 
+namespace chrono
+{
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR PULLEYS
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkPulley> a_registration_ChLinkPulley;
+
+
+ChLinkPulley::ChLinkPulley ()
+{
+    type = LNK_PULLEY;    // initializes type
+
+    a1 = 0;
+    a2 = 0;
+    r1 = 1;
+    r2 = 1;
+    tau = 1;
+    phase = 0;
+    checkphase = FALSE;
+	shaft_dist = 0;
+
+	local_shaft1.SetIdentity();
+	local_shaft2.SetIdentity();
+
+    belt_up1= VNULL;
+	belt_up2= VNULL;
+	belt_low1= VNULL;
+	belt_low2= VNULL;
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to X  only. It was a LinkMaskLF because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(true, false, false,
+                       false, false, false, false,
+                       false, false);
+    ChangedLinkMask();
+}
+
+ChLinkPulley::~ChLinkPulley ()
+{ }
+
+void ChLinkPulley::Copy(ChLinkPulley* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    tau = source->tau;
+    phase = source->phase;
+    a1 = source->a1;
+    a2 = source->a2;
+    checkphase = source->checkphase;
+    r1 = source->r1;
+    r2 = source->r2;
+	belt_up1 = source->belt_up1;
+	belt_up2 = source->belt_up2;
+	belt_low1 = source->belt_low1;
+	belt_low2 = source->belt_low2;
+	local_shaft1 = source->local_shaft1;
+	local_shaft2 = source->local_shaft2;
+    shaft_dist = source->shaft_dist;
+}
+
+ChLink* ChLinkPulley::new_Duplicate ()
+{
+    ChLinkPulley* m_l;
+    m_l = new ChLinkPulley;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+Vector  ChLinkPulley::Get_shaft_dir1()
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body1)->TrasformLocalToParent(local_shaft1, absframe);
+		return absframe.GetA()->Get_A_Zaxis();
+	} else return VECT_Z;
+}
+
+Vector  ChLinkPulley::Get_shaft_dir2() 
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body2)->TrasformLocalToParent(local_shaft2, absframe);
+		return absframe.GetA()->Get_A_Zaxis();
+	} else return VECT_Z;
+}
+
+Vector  ChLinkPulley::Get_shaft_pos1() 
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body1)->TrasformLocalToParent(local_shaft1, absframe);
+		return absframe.GetPos();
+	} else return VNULL;
+}
+
+Vector  ChLinkPulley::Get_shaft_pos2() 
+{
+	if (this->Body1)
+	{
+		ChFrame<double> absframe;
+		((ChFrame<double>*)Body2)->TrasformLocalToParent(local_shaft2, absframe);
+		return absframe.GetPos();
+	} else return VNULL;
+}
+
+
+
+
+void ChLinkPulley::UpdateTime (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateTime(mytime);
+
+	ChFrame<double> abs_shaft1;
+	ChFrame<double> abs_shaft2;
+
+	((ChFrame<double>*)Body1)->TrasformLocalToParent(local_shaft1, abs_shaft1);
+	((ChFrame<double>*)Body2)->TrasformLocalToParent(local_shaft2, abs_shaft2);
+
+	ChVector<> dcc_w = Vsub(Get_shaft_pos2(),
+                            Get_shaft_pos1());
+
+		// compute actual rotation of the two wheels (relative to truss).
+    Vector md1 = abs_shaft1.GetA()->MatrT_x_Vect(dcc_w);
+    md1.z = 0;  md1 = Vnorm (md1);
+    Vector md2 = abs_shaft2.GetA()->MatrT_x_Vect(dcc_w);
+    md2.z = 0;  md2 = Vnorm (md2);
+
+	double periodic_a1 = ChAtan2(md1.x, md1.y);
+	double periodic_a2 = ChAtan2(md2.x, md2.y);
+	double old_a1 = a1; 
+	double old_a2 = a2;
+	double turns_a1 = floor (old_a1 / CH_C_2PI);
+	double turns_a2 = floor (old_a2 / CH_C_2PI);
+	double a1U = turns_a1 * CH_C_2PI + periodic_a1 + CH_C_2PI;
+	double a1M = turns_a1 * CH_C_2PI + periodic_a1;
+	double a1L = turns_a1 * CH_C_2PI + periodic_a1 - CH_C_2PI;
+	a1 = a1M;
+	if (fabs(a1U - old_a1) < fabs(a1M - old_a1))
+		a1 = a1U;
+	if (fabs(a1L - a1) < fabs(a1M - a1))
+		a1 = a1L;
+	double a2U = turns_a2 * CH_C_2PI + periodic_a2 + CH_C_2PI;
+	double a2M = turns_a2 * CH_C_2PI + periodic_a2;
+	double a2L = turns_a2 * CH_C_2PI + periodic_a2 - CH_C_2PI;
+	a2 = a2M;
+	if (fabs(a2U - old_a2) < fabs(a2M - old_a2))
+		a2 = a2U;
+	if (fabs(a2L - a2) < fabs(a2M - a2))
+		a2 = a2L;
+
+	     // correct marker positions if phasing is not correct
+	double m_delta =0;
+    if (this->checkphase)
+    {
+		double realtau = tau; 
+		//if (this->epicyclic) 
+		//	realtau = -tau;
+        
+        m_delta = a1 - phase - (a2/realtau);
+
+        if (m_delta> CH_C_PI) m_delta -= (CH_C_2PI);		 // range -180..+180 is better than 0...360
+        if (m_delta> (CH_C_PI/4.0)) m_delta = (CH_C_PI/4.0); // phase correction only in +/- 45�
+        if (m_delta<-(CH_C_PI/4.0)) m_delta =-(CH_C_PI/4.0);
+		//***TODO***
+    }
+
+
+    // Move markers 1 and 2 to align them as pulley ends
+
+	ChVector<> d21_w = dcc_w - Get_shaft_dir1()* Vdot (Get_shaft_dir1(), dcc_w);
+	ChVector<> D21_w = Vnorm(d21_w);
+
+	this->shaft_dist = d21_w.Length();
+	
+	ChVector<> U1_w = Vcross(Get_shaft_dir1(), D21_w);
+
+	double gamma1 = acos( (r1-r2) / shaft_dist);
+
+	ChVector<> Ru_w =  D21_w*cos(gamma1) + U1_w*sin(gamma1);
+	ChVector<> Rl_w =  D21_w*cos(gamma1) - U1_w*sin(gamma1);
+
+	this->belt_up1  = Get_shaft_pos1()+ Ru_w*r1;
+	this->belt_low1 = Get_shaft_pos1()+ Rl_w*r1;
+	this->belt_up2  = Get_shaft_pos1()+ d21_w + Ru_w*r2;
+	this->belt_low2 = Get_shaft_pos1()+ d21_w + Rl_w*r2;
+
+		// marker alignment
+	ChMatrix33<> maU;
+	ChMatrix33<> maL;
+
+	ChVector<> Dxu = Vnorm(belt_up2 - belt_up1);
+	ChVector<> Dyu = Ru_w;
+	ChVector<> Dzu = Vnorm (Vcross(Dxu, Dyu));
+	Dyu = Vnorm (Vcross(Dzu, Dxu));
+	maU.Set_A_axis(Dxu,Dyu,Dzu);
+
+            // ! Require that the BDF routine of marker won't handle speed and acc.calculus of the moved marker 2!
+    marker2->SetMotionType(ChMarker::M_MOTION_EXTERNAL);
+    marker1->SetMotionType(ChMarker::M_MOTION_EXTERNAL);
+
+	ChCoordsys<> newmarkpos;
+
+        // move marker1 in proper positions
+    newmarkpos.pos = this->belt_up1;
+    newmarkpos.rot = maU.Get_A_quaternion();
+    marker1->Impose_Abs_Coord(newmarkpos);        //move marker1 into teeth position
+        // move marker2 in proper positions
+    newmarkpos.pos = this->belt_up2;
+    newmarkpos.rot = maU.Get_A_quaternion();
+    marker2->Impose_Abs_Coord(newmarkpos);        //move marker2 into teeth position
+
+	double phase_correction_up = m_delta*r1;
+	double phase_correction_low = - phase_correction_up;
+	double hU = Vlenght(belt_up2- belt_up1)  + phase_correction_up;
+	double hL = Vlenght(belt_low2- belt_low1) + phase_correction_low;
+
+        // imposed relative positions/speeds
+    deltaC.pos = ChVector<>(-hU, 0, 0);
+    deltaC_dt.pos = VNULL;
+    deltaC_dtdt.pos = VNULL;
+
+    deltaC.rot = QUNIT;             // no relative rotations imposed!
+    deltaC_dt.rot = QNULL;
+    deltaC_dtdt.rot = QNULL;
+}
+
+
+
+void ChLinkPulley::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << tau;
+    mstream << phase;
+    mstream << checkphase;
+    mstream << a1;
+    mstream << a2;
+    mstream << r1;
+    mstream << r2;
+	mstream << local_shaft1;
+	mstream << local_shaft2;
+}
+
+void ChLinkPulley::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> tau;
+    mstream >> phase;
+    mstream >> checkphase;
+    mstream >> a1;
+    mstream >> a2;
+    mstream >> r1;
+    mstream >> r2;
+	mstream >> local_shaft1;
+	mstream >> local_shaft2;
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkPulley.h b/SRC/ChronoEngine/physics/ChLinkPulley.h
new file mode 100644
index 0000000..061ae6c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkPulley.h
@@ -0,0 +1,189 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKPULLEY_H
+#define CHLINKPULLEY_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkPulley.h
+//
+//
+//   Classes for pulleys and synchro belts
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkLock.h"
+
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_PULLEY		38
+
+
+///
+/// Class to create pulleys on two rigid bodies, connected by a belt. 
+/// The two bodies must be already connected to a truss by other 
+/// links, for example two revolute joints (ChLinkLockRevolute), because
+/// this link constraints only the rotation.
+///
+
+class ChApi ChLinkPulley : public ChLinkLock {
+
+	CH_RTTI(ChLinkPulley,ChLinkLock);
+
+protected:
+	double tau;			// transmission coeff.
+	double r1;			// radius of pulley in body1
+	double r2;			// radius of pulley in body2
+	double phase;		// mounting phase angle
+	int	   checkphase;	// keep pulleys always on phase
+
+	double a1;			// auxiliary
+	double a2;
+
+	double shaft_dist;
+
+	ChVector<> belt_up1;	// upper segment of belt - end on body1.
+	ChVector<> belt_up2;	// upper segment of belt - end on body2.
+	ChVector<> belt_low1;	// lower segment of belt - end on body1.
+	ChVector<> belt_low2;	// lower segment of belt - end on body2.
+
+	ChFrame<double> local_shaft1; // shaft1 pos & dir (as Z axis), relative to body1
+	ChFrame<double> local_shaft2; // shaft2 pos & dir (as Z axis), relative to body2
+
+public:
+						// builders and destroyers
+	ChLinkPulley ();
+	virtual ~ChLinkPulley ();
+	virtual void Copy(ChLinkPulley* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+	virtual int GetType	() {return LNK_PULLEY;}
+
+							// UPDATING FUNCTIONS - "pulley" custom implementations
+
+							// Updates motion laws, marker positions, etc.
+	virtual void UpdateTime (double mytime);
+
+			// data get/set
+
+						/// Set radius of 1st pulley.
+	void  Set_r1(double mr) {r1=mr; tau = r1/r2;};
+						/// Set radius of 2nd pulley. 
+	void  Set_r2(double mr) {r2=mr; tau = r1/r2;};
+
+						/// Get radius of 1st pulley.
+	double  Get_r1() {return r1;};
+						/// Get radius of 2nd pulley.
+	double  Get_r2() {return r2;};
+
+						/// Get the transmission ratio. Its value is assumed always positive.
+	double  Get_tau() {return tau;};
+		
+						/// Get the initial phase of rotation of pulley A.
+	double  Get_phase() {return phase;};
+						/// Set the initial phase of rotation of pulley A.
+	void	Set_phase(double mset) {phase = mset;}
+
+						/// If true, enforce check on exact phase between pulleys 
+						/// (otherwise after many simulation steps the phasing
+						/// may be affected by numerical error accumulation). 
+						///  By default, it is turned off, but for the simulation of
+						/// synchro belts, this should be better turned on.
+						///  Note that, to ensure the correct phasing during the many
+						/// rotations, an algorithm will use the a1 and a2 total rotation
+						/// values, which might be affected by loss of numerical precision
+						/// after few thousands of revolutions, so this is NOT suited to
+						/// real-time simulators which must run for many hours.
+	void	Set_checkphase(int mset) {checkphase = mset;}
+	int		Get_checkphase() {return checkphase;};
+
+
+						/// Get total rotation of 1st pulley, respect to interaxis, in radians 
+	double  Get_a1() {return a1;};
+						/// Get total rotation of 1st pulley, respect to interaxis, in radians 
+	double  Get_a2() {return a2;};
+						/// Reset the total rotations of a1 and a2. 
+	void    Reset_a1a2() {a1=a2=0;};
+
+
+
+						/// Get shaft position and direction, for 1st pulley, in body1-relative reference. 
+						/// The shaft direction is the Z axis of that frame.
+	ChFrame<double> Get_local_shaft1() {return local_shaft1;}
+						/// Set shaft position and direction, for 1st pulley, in body1-relative reference. 
+						/// The shaft direction is the Z axis of that frame.  It should be parallel to shaft 2.
+						/// Note that the origin of shaft position will be automatically shifted along
+						/// shaft direction in order to have both pulleys on same plane.
+	void            Set_local_shaft1(ChFrame<double> mf) {local_shaft1 = mf;}
+
+						/// Get shaft position and direction, for 2nd pulley, in body2-relative reference. 
+						/// The shaft direction is the Z axis of that frame.
+	ChFrame<double> Get_local_shaft2() {return local_shaft2;}
+						/// Set shaft position and direction, for 2nd pulley, in body2-relative reference. 
+						/// The shaft direction is the Z axis of that frame.  It should be parallel to shaft 1.
+	void            Set_local_shaft2(ChFrame<double> mf) {local_shaft2 = mf;}
+
+
+						/// Get shaft direction, for 1st pulley, in absolute reference
+	ChVector<>  Get_shaft_dir1();
+						/// Get shaft direction, for 2nd pulley, in absolute reference
+	ChVector<>  Get_shaft_dir2();
+
+						/// Get shaft position, for 1st pulley, in absolute reference
+	ChVector<>  Get_shaft_pos1();
+						/// Get shaft position, for 2nd pulley, in absolute reference
+	ChVector<>  Get_shaft_pos2();
+
+						/// Get the endpoint of belt, on pulley of body1, for the 'upper' segment, 
+						/// in absolute coordinates.
+	ChVector<>	Get_belt_up1() {return belt_up1;}
+						/// Get the endpoint of belt, on pulley of body2, for the 'upper' segment, 
+						/// in absolute coordinates.
+	ChVector<>	Get_belt_up2() {return belt_up2;}
+						/// Get the endpoint of belt, on pulley of body1, for the 'lower' segment, 
+						/// in absolute coordinates.
+	ChVector<>	Get_belt_low1() {return belt_low1;}
+						/// Get the endpoint of belt, on pulley of body1, for the 'lower' segment, 
+						/// in absolute coordinates.
+	ChVector<>	Get_belt_low2() {return belt_low2;}
+
+						/// Return distance between the two axes.
+	double	GetShaftsDistance() {return shaft_dist;}
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkRackpinion.cpp b/SRC/ChronoEngine/physics/ChLinkRackpinion.cpp
new file mode 100644
index 0000000..f88e879
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkRackpinion.cpp
@@ -0,0 +1,163 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#include "physics/ChLinkRackpinion.h"
+
+namespace chrono {
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkRackpinion> a_registration_ChLinkRackpinion;
+
+ChLinkRackpinion::ChLinkRackpinion() : ChLinkMateGeneric(true, false, false, false, false, false) {
+    R = 0.1;
+    alpha = 0;
+    beta = 0;
+    phase = 0;
+    checkphase = false;
+    a1 = 0;
+
+    local_pinion.SetIdentity();
+    local_rack.SetIdentity();
+
+    contact_pt = VNULL;
+}
+
+ChLinkRackpinion::~ChLinkRackpinion() {
+}
+
+void ChLinkRackpinion::Copy(ChLinkRackpinion* source) {
+    // first copy the parent class data...
+    //
+    ChLinkMateGeneric::Copy(source);
+
+    // copy custom data:
+    R = source->R;
+    alpha = source->alpha;
+    beta = source->beta;
+    phase = source->phase;
+    a1 = source->a1;
+    checkphase = source->checkphase;
+
+    contact_pt = source->contact_pt;
+    local_pinion = source->local_pinion;
+    local_rack = source->local_rack;
+}
+
+ChLink* ChLinkRackpinion::new_Duplicate() {
+    ChLinkRackpinion* m_l = new ChLinkRackpinion;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+ChVector<> ChLinkRackpinion::GetAbsPinionDir() {
+    if (this->Body1) {
+        ChFrame<double> absframe;
+        ((ChFrame<double>*)Body1)->TransformLocalToParent(local_pinion, absframe);
+        return absframe.GetA()->Get_A_Zaxis();
+    } else
+        return VECT_Z;
+}
+
+ChVector<> ChLinkRackpinion::GetAbsPinionPos() {
+    if (this->Body1) {
+        ChFrame<double> absframe;
+        ((ChFrame<double>*)Body1)->TransformLocalToParent(local_pinion, absframe);
+        return absframe.GetPos();
+    } else
+        return VNULL;
+}
+
+ChVector<> ChLinkRackpinion::GetAbsRackDir() {
+    if (this->Body2) {
+        ChFrame<double> absframe;
+        ((ChFrame<double>*)Body2)->TransformLocalToParent(local_rack, absframe);
+        return absframe.GetA()->Get_A_Zaxis();
+    } else
+        return VECT_Z;
+}
+
+ChVector<> ChLinkRackpinion::GetAbsRackPos() {
+    if (this->Body2) {
+        ChFrame<double> absframe;
+        ((ChFrame<double>*)Body2)->TransformLocalToParent(local_rack, absframe);
+        return absframe.GetPos();
+    } else
+        return VNULL;
+}
+
+void ChLinkRackpinion::Update(double mytime) {
+    // First, inherit to parent class
+    ChLinkMateGeneric::Update(mytime);
+
+    ChFrame<double> abs_pinion;
+    ChFrame<double> abs_rack;
+
+    ((ChFrame<double>*)Body1)->TransformLocalToParent(local_pinion, abs_pinion);
+    ((ChFrame<double>*)Body2)->TransformLocalToParent(local_rack, abs_rack);
+
+    ChVector<> abs_distpr = abs_pinion.GetPos() - abs_rack.GetPos();
+    ChVector<> abs_Dpin = abs_pinion.GetA()->Get_A_Zaxis();
+    ChVector<> abs_RackX = abs_rack.GetA()->Get_A_Xaxis();
+    ChVector<> abs_Dx;
+    ChVector<> abs_Dy;
+    ChVector<> abs_Dz;
+    abs_Dpin.DirToDxDyDz(&abs_Dz, &abs_Dx, &abs_Dy, &abs_RackX);  // with z as pinion shaft and x as suggested rack X dir
+
+    
+    // GetLog() << "abs_distpr " << abs_distpr << "\n";
+    // GetLog() << "abs_rack Xaxis()" << abs_rack.GetA()->Get_A_Xaxis() << "\n";
+    // GetLog() << "abs_Dpin " << abs_Dpin << "\n";
+    // GetLog() << "abs_Dx " << abs_Dx << "\n";
+    
+
+    ChVector<> abs_Ro = abs_Dy * Vdot(abs_Dy, abs_distpr);
+
+    if (Vdot(abs_Ro, abs_distpr) > 0)
+        abs_Ro = -abs_Ro;
+
+    ChVector<> abs_Dr = abs_Ro.GetNormalized();
+    ChVector<> abs_R = abs_Dr * this->GetPinionRadius();
+    this->contact_pt = abs_pinion.GetPos() + abs_R;
+
+    double runX = Vdot(abs_distpr, abs_Dx);
+
+    // ChVector<> abs_runX    = Vdot( abs_distpr, abs_Dx );
+
+    // Absolute frame of link reference
+    ChMatrix33<> ma1;
+    ma1.Set_A_axis(abs_Dx, abs_Dy, abs_Dz);
+    ChFrame<> abs_contact(this->contact_pt, ma1);
+
+    ChMatrix33<> mrot;
+
+    // rotate link frame on its Y because of beta
+    mrot.Set_A_Rxyz(ChVector<>(0, this->beta, 0));
+    ChFrame<> mrotframe(VNULL, mrot);
+    abs_contact.ConcatenatePostTransformation(mrotframe);  // or: abs_contact *= mrotframe;
+
+    // rotate link frame on its Z because of alpha
+    if (this->react_force.x < 0)
+        mrot.Set_A_Rxyz(ChVector<>(0, 0, this->alpha));
+    else
+        mrot.Set_A_Rxyz(ChVector<>(0, 0, -this->alpha));
+    mrotframe.SetRot(mrot);
+    abs_contact.ConcatenatePostTransformation(mrotframe);  // or: abs_contact *= mrotframe;
+
+    // Set the link frame 'abs_contact' to relative frames to the two connected ChBodyFrame
+    ((ChFrame<double>*)Body1)->TransformParentToLocal(abs_contact, this->frame1);
+    ((ChFrame<double>*)Body2)->TransformParentToLocal(abs_contact, this->frame2);
+}
+
+
+///////////////////////////////////////////////////////////////
+
+}  // END_OF_NAMESPACE____
diff --git a/SRC/ChronoEngine/physics/ChLinkRackpinion.h b/SRC/ChronoEngine/physics/ChLinkRackpinion.h
new file mode 100644
index 0000000..7425f87
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkRackpinion.h
@@ -0,0 +1,125 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+// File Author: A. Tasora
+
+#ifndef CHLINKRACKPINION_H
+#define CHLINKRACKPINION_H
+
+#include "physics/ChLinkMate.h"
+
+namespace chrono {
+
+///
+/// Rack-pinion link between two body frames.
+/// It correctly handles the direction of transmitted force
+/// given the teeth pressure angle.
+///
+
+class ChApi ChLinkRackpinion : public ChLinkMateGeneric {
+    CH_RTTI(ChLinkRackpinion, ChLinkMateGeneric);
+
+  protected:
+    double R;        // primitive radius of the pinion
+    double alpha;    // inclination of action line
+    double beta;     // helix angle
+    double phase;    // mounting phase angle
+    int checkphase;  // keep gear always on phase
+
+    double a1;  // auxiliary
+
+    ChVector<> contact_pt;
+
+    ChFrame<double> local_pinion;  // pinion shaft pos & dir (frame Z axis), relative to body1
+    ChFrame<double> local_rack;    // rack direction (frame X axis), relative to body2
+
+  public:
+    // builders and destroyers
+    ChLinkRackpinion();
+    virtual ~ChLinkRackpinion();
+    virtual void Copy(ChLinkRackpinion* source);
+    virtual ChLink* new_Duplicate();  // always return base link class pointer
+
+    // UPDATING FUNCTIONS - "gear" custom implementations
+
+    // Updates aux frames positions
+    virtual void Update(double mytime);
+
+    // data get/set
+
+    /// Get the primitive radius of the pinion.
+    double GetPinionRadius() { return R; };
+    /// Set the primitive radius of the pinion.
+    void SetPinionRadius(double mR) { R = mR; };
+
+    /// Get the pressure angle (usually 20� for typical gears)
+    double GetAlpha() { return alpha; };
+    /// Set the pressure angle (usually 20� for typical gears)
+    void SetAlpha(double mset) { alpha = mset; }
+
+    /// Get the angle of teeth in bevel gears (0� for spur gears)
+    double GetBeta() { return beta; };
+    /// Set the angle of teeth in bevel gears (0� for spur gears)
+    void SetBeta(double mset) { beta = mset; }
+
+    /// Get the initial phase of rotation of pinion respect to rack
+    double GetPhase() { return phase; };
+    /// Set the initial phase of rotation of pinion respect to rack
+    void SetPhase(double mset) { phase = mset; }
+
+    /// If true, enforce check on exact phase between gears
+    /// (otherwise after many simulation steps the phasing
+    /// may be affected by numerical error accumulation).
+    /// By default, it is turned off.
+    /// Note that, to ensure the correct phasing during the many
+    /// rotations, an algorithm will update an accumulator with total rotation
+    /// values, which might be affected by loss of numerical precision
+    /// after few thousands of revolutions; keep in mind this if you do
+    /// real-time simulations which must run for many hours.
+    void SetCheckphase(int mset) { checkphase = mset; }
+    int GetCheckphase() { return checkphase; };
+
+    /// Get total rotation of 1st gear, respect to interaxis, in radians
+    double Get_a1() { return a1; };
+    /// Reset the total rotations of a1 and a2.
+    void Reset_a1() { a1 = 0; };
+
+    /// Set pinion shaft position and direction, in body1-relative reference.
+    /// The shaft direction is the Z axis of that frame.
+    void SetPinionFrame(ChFrame<double> mf) { local_pinion = mf; }
+    /// Get pinion shaft position and direction, in body1-relative reference.
+    /// The shaft direction is the Z axis of that frame.
+    ChFrame<double> GetPinionFrame() { return local_pinion; }
+
+    /// Set rack position and direction, in body2-relative reference.
+    /// The rack direction is the X axis of that frame.
+    void SetRackFrame(ChFrame<double> mf) { local_rack = mf; }
+    /// Get rack position and direction, in body2-relative reference.
+    /// The rack direction is the X axis of that frame.
+    ChFrame<double> GetRackFrame() { return local_rack; }
+
+    /// Get pinion shaft direction in absolute reference
+    ChVector<> GetAbsPinionDir();
+    /// Get pinion position in absolute reference
+    ChVector<> GetAbsPinionPos();
+
+    /// Get rack direction in absolute reference
+    ChVector<> GetAbsRackDir();
+    /// Get rack position in absolute reference
+    ChVector<> GetAbsRackPos();
+
+};
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+}  // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkScrew.cpp b/SRC/ChronoEngine/physics/ChLinkScrew.cpp
new file mode 100644
index 0000000..82ee4f8
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkScrew.cpp
@@ -0,0 +1,201 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkScrew.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+  
+#include "physics/ChLinkScrew.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+ 
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR SCREW
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkScrew> a_registration_ChLinkScrew;
+
+
+ChLinkScrew::ChLinkScrew ()
+{
+    type = LNK_SCREW;       // initializes type
+
+    //tau = 0.01;
+    Set_thread(0.05);
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to X,Y,Z,Rx Ry, (note: the Z lock is'nt a standard LinkLock z-lock and will
+            // be handled as a custom screw constraint z = tau *alpha, later in updating functions).
+    ((ChLinkMaskLF*)mask)->SetLockMask(true, true, true,
+                       false, true, true, false,
+                       false, false);
+    ChangedLinkMask();
+}
+
+ChLinkScrew::~ChLinkScrew ()
+{ }
+
+void ChLinkScrew::Copy(ChLinkScrew* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+    tau = source->tau;
+}
+
+ChLink* ChLinkScrew::new_Duplicate ()
+{
+    ChLinkScrew* m_l;
+    m_l = new ChLinkScrew;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+void ChLinkScrew::UpdateState()
+{
+    // First, compute everything as it were a normal "revolute" joint, on z axis...
+    ChLinkLock::UpdateState();
+
+    // Then, MODIFY the Z part of equations, such that the Z = 0  becomes Z = tau * alpha
+    double scr_C, scr_C_dt, scr_C_dtdt;
+    double scr_Ct, scr_Qc;
+    double coeffa, coeffb, zangle, msign;
+    ChMatrixNM<double,1,7> scr_Cq1;
+    ChMatrixNM<double,1,7> scr_Cq2;
+    double Crz;
+
+    if (fabs (relC.rot.e0) <0.707)
+    {
+        Crz = relC.rot.e0;  // cos(alpha/2)
+        msign = +1;
+        zangle = acos (Crz);
+        if (relC.rot.e3 < 0)
+        {
+            zangle = - zangle; // a/2 = -acos(Crz);
+            msign = -1;
+        }
+        double mrelz = relC.pos.z;
+
+        scr_C = mrelz - tau * 2.0 * zangle;
+                                                // modulus correction..
+        scr_C = scr_C - Get_thread()*floor(scr_C / Get_thread());
+        double shiftedC = scr_C - Get_thread()*ceil(scr_C / Get_thread());
+        if (fabs(scr_C)>fabs(shiftedC)) scr_C = shiftedC;
+
+        coeffa = + 2.0 * tau * msign * 1/(sqrt(1 - pow (Crz,2.0) ) );
+        coeffb = + 2.0 * tau * msign * Crz/(pow  ((1 - pow (Crz,2)), 3.0/2.0 ) );
+
+        scr_C_dt = relC_dt.pos.z + relC_dt.rot.e0 * coeffa;
+        scr_C_dtdt = relC_dtdt.pos.z + relC_dt.rot.e0 * coeffb + relC_dtdt.rot.e0 * coeffa;
+        scr_Ct = Ct_temp.pos.z + coeffa * Ct_temp.rot.e0;
+        scr_Qc = Qc_temp->GetElement(2,0) + coeffa * Qc_temp->GetElement(3,0) - relC_dt.rot.e0 * coeffb;
+        scr_Cq1.Reset();
+        scr_Cq2.Reset();
+        scr_Cq1.PasteClippedMatrix(Cq1_temp, 3,3, 1,4, 0,3);
+        scr_Cq2.PasteClippedMatrix(Cq2_temp, 3,3, 1,4, 0,3);
+        scr_Cq1.MatrScale(coeffa);
+        scr_Cq2.MatrScale(coeffa);
+    }
+    else
+    {
+        Crz = relC.rot.e3;  // Zz*sin(alpha/2)
+        msign = +1;
+        zangle = asin (Crz);
+        if (relC.rot.e0 < 0)
+        {
+            zangle  = CH_C_PI - zangle;
+            msign = -1;
+        }
+        double mrelz = relC.pos.z;//fmod (relC.pos.z , (tau * 2 * CH_C_PI));
+
+        scr_C = mrelz - tau * 2.0 * zangle;
+                                                        // modulus correction..
+        scr_C = scr_C - Get_thread()*floor(scr_C / Get_thread());
+        double shiftedC = scr_C - Get_thread()*ceil(scr_C / Get_thread());
+        if (fabs(scr_C)>fabs(shiftedC)) scr_C = shiftedC;
+
+        coeffa = - 2.0 * tau * msign * 1 /(sqrt(1 - pow (Crz,2.0) ) );
+        coeffb = - 2.0 * tau * msign * Crz /(pow  ((1 - pow (Crz,2)), 3.0/2.0 ) );
+
+        scr_C_dt = relC_dt.pos.z + relC_dt.rot.e3 * coeffa;
+        scr_C_dtdt = relC_dtdt.pos.z + relC_dt.rot.e3 * coeffb + relC_dtdt.rot.e3 * coeffa;
+        scr_Ct = Ct_temp.pos.z + coeffa * Ct_temp.rot.e3;
+        scr_Qc = Qc_temp->GetElement(2,0) + coeffa * Qc_temp->GetElement(6,0) - relC_dt.rot.e3 * coeffb;
+        scr_Cq1.Reset();
+        scr_Cq2.Reset();
+        scr_Cq1.PasteClippedMatrix(Cq1_temp, 6,3, 1,4, 0,3);
+        scr_Cq2.PasteClippedMatrix(Cq2_temp, 6,3, 1,4, 0,3);
+        scr_Cq1.MatrScale(coeffa);
+        scr_Cq2.MatrScale(coeffa);
+    }
+
+    Cq1->PasteClippedMatrix(Cq1_temp, 2,0,  1,7,  2,0);
+    Cq2->PasteClippedMatrix(Cq2_temp, 2,0,  1,7,  2,0);
+    Cq1->PasteSumMatrix(&scr_Cq1, 2,0);
+    Cq2->PasteSumMatrix(&scr_Cq2, 2,0);
+    Qc->SetElement(2,0,scr_Qc);
+    C->SetElement(2,0, scr_C);
+    C_dt->SetElement(2,0, scr_C_dt);
+    C_dtdt->SetElement(2,0, scr_C_dtdt);
+    Ct->SetElement(2,0, scr_Ct);
+}
+
+void ChLinkScrew::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << tau;
+}
+
+void ChLinkScrew::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> tau;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkScrew.h b/SRC/ChronoEngine/physics/ChLinkScrew.h
new file mode 100644
index 0000000..a2012ec
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkScrew.h
@@ -0,0 +1,89 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKSCREW_H
+#define CHLINKSCREW_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkScrew.h
+//
+//
+//   Classes for screw joint
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkLock.h"
+
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_SCREW		12
+
+
+///
+/// Screw joint between two rigid bodies. This 
+/// link type is able to couple translation and rotation.
+///
+
+class ChApi ChLinkScrew : public ChLinkLock {
+
+	CH_RTTI(ChLinkScrew,ChLinkLock);
+
+protected:
+	double tau;			// transmission coeff.
+
+public:
+						// builders and destroyers
+	ChLinkScrew ();
+	virtual ~ChLinkScrew ();
+	virtual void Copy(ChLinkScrew* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+							// UPDATING FUNCTIONS - "screw" custom implementations
+
+							// Inherit the link-lock computations like it were a
+							// normal "revolute" joint, but then modifies the Z-lock parts of C,
+							// Cdt, Cdtdt, [Cq] etc., in order to have z = tau * alpha.
+	virtual void UpdateState ();
+
+			// data get/set
+	double  Get_tau() {return tau;};
+	void  Set_tau(double mset) {tau = mset;}
+	double  Get_thread() {return tau*(2*CH_C_PI);};
+	void  Set_thread(double mset) {tau = mset/(2*CH_C_PI);}
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkSpring.cpp b/SRC/ChronoEngine/physics/ChLinkSpring.cpp
new file mode 100644
index 0000000..b2de7ee
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkSpring.cpp
@@ -0,0 +1,252 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkSpring.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+  
+ 
+#include "physics/ChLinkSpring.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). 
+
+
+namespace chrono
+{
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR SPRING LINKS
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkSpring> a_registration_ChLinkSpring;
+
+
+                // BUILDERS
+ChLinkSpring::ChLinkSpring ()
+{
+    spr_restlenght = 0;     // custom variables
+    spr_k = 100;
+    spr_r = 5;
+    spr_f = 0;
+
+    mod_f_time =   new ChFunction_Const (1);
+    mod_k_d =   new ChFunction_Const (1);
+    mod_k_speed =   new ChFunction_Const (1);
+    mod_r_d =   new ChFunction_Const (1);
+    mod_r_speed =   new ChFunction_Const (1);
+
+    spr_react = 0.0;
+}
+
+
+            // DESTROYER
+ChLinkSpring::~ChLinkSpring ()
+{
+    // delete custom instanced data...
+    if (mod_f_time) delete mod_f_time;
+    if (mod_k_d) delete mod_k_d;
+    if (mod_k_speed) delete mod_k_speed;
+    if (mod_r_d) delete mod_r_d;
+    if (mod_r_speed) delete mod_r_speed;
+}
+
+
+void ChLinkSpring::Copy(ChLinkSpring* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkMarkers::Copy(source);
+
+    // copy custom data:
+    spr_restlenght = source->spr_restlenght;
+    spr_f = source->spr_f;
+    spr_k = source->spr_k;
+    spr_r = source->spr_r;
+    spr_react = source->spr_react;
+    if (mod_f_time) delete mod_f_time;
+         mod_f_time =   source->mod_f_time->new_Duplicate();
+    if (mod_k_d) delete mod_k_d;
+         mod_k_d =   source->mod_k_d->new_Duplicate();
+    if (mod_k_speed) delete mod_k_speed;
+         mod_k_speed =   source->mod_k_speed->new_Duplicate();
+    if (mod_r_d) delete mod_r_d;
+         mod_r_d =   source->mod_r_d->new_Duplicate();
+    if (mod_r_speed) delete mod_r_speed;
+         mod_r_speed =   source->mod_r_speed->new_Duplicate();
+}
+
+
+ChLink* ChLinkSpring::new_Duplicate ()
+{
+    ChLinkSpring* m_l;
+    m_l = new ChLinkSpring;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+
+int ChLinkSpring::Initialize(ChSharedPtr<ChBody>& mbody1,   ///< first body to link
+						   ChSharedPtr<ChBody>& mbody2,		 ///< second body to link
+						   bool pos_are_relative,///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpos1,	 ///< position of distance endpoint, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpos2,	 ///< position of distance endpoint, for 2nd body (rel. or abs., see flag above) 
+						   bool auto_rest_length,///< if true, initializes the imposed distance as the distance between mpos1 and mpos2
+						   double mrest_length   ///< imposed distance (no need to define, if auto_distance=true.)
+						   )
+{
+	// first, initialize as all constraint with markers. In this case, create the two markers also!.
+	ChLinkMarkers::Initialize(mbody1,mbody2, CSYSNORM);
+
+	if (pos_are_relative)
+	{
+		this->marker1->Impose_Rel_Coord(ChCoordsys<>(mpos1,QUNIT));
+		this->marker2->Impose_Rel_Coord(ChCoordsys<>(mpos2,QUNIT));
+	}
+	else
+	{
+		this->marker1->Impose_Abs_Coord(ChCoordsys<>(mpos1,QUNIT));
+		this->marker2->Impose_Abs_Coord(ChCoordsys<>(mpos2,QUNIT));
+	}
+	 
+	ChVector<> AbsDist = this->marker1->GetAbsCoord().pos - this->marker2->GetAbsCoord().pos;
+	this->dist = AbsDist.Length();
+
+	if (auto_rest_length)
+	{
+		this->spr_restlenght = this->dist;
+	}
+	else
+	{
+		this->spr_restlenght = mrest_length; 
+	}
+
+	return true;
+}
+
+
+
+
+
+
+void ChLinkSpring::Set_mod_f_time (ChFunction* m_funct)
+{
+    if (mod_f_time) delete mod_f_time;
+    mod_f_time = m_funct;
+}
+void ChLinkSpring::Set_mod_k_d    (ChFunction* m_funct)
+{
+    if (mod_k_d) delete mod_k_d;
+    mod_k_d = m_funct;
+}
+void ChLinkSpring::Set_mod_r_d    (ChFunction* m_funct)
+{
+    if (mod_r_d) delete mod_r_d;
+    mod_r_d = m_funct;
+}
+void ChLinkSpring::Set_mod_k_speed(ChFunction* m_funct)
+{
+    if (mod_k_speed) delete mod_k_speed;
+    mod_k_speed = m_funct;
+}
+void ChLinkSpring::Set_mod_r_speed(ChFunction* m_funct)
+{
+    if (mod_r_speed) delete mod_r_speed;
+    mod_r_speed = m_funct;
+}
+
+
+void ChLinkSpring::UpdateForces (double mytime)
+{
+    // Inherit force computation:
+    // also base class can add its own forces.
+    ChLinkMarkers::UpdateForces(mytime);
+
+    spr_react = 0.0;
+    Vector m_force;
+    double deform = Get_SpringDeform();
+
+    spr_react  =  spr_f * mod_f_time->Get_y(ChTime);
+    spr_react -= (spr_k * mod_k_d->Get_y(deform) * mod_k_speed->Get_y(dist_dt)) * (deform);
+    spr_react -= (spr_r * mod_r_d->Get_y(deform) * mod_r_speed->Get_y(dist_dt)) * (dist_dt);
+
+    m_force = Vmul (Vnorm(relM.pos), spr_react);
+
+    C_force = Vadd(C_force, m_force);  
+}
+
+
+
+void ChLinkSpring::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkMarkers::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << spr_restlenght;
+    mstream << spr_f;
+    mstream << spr_k;
+    mstream << spr_r;
+	mstream.AbstractWrite(mod_f_time);
+	mstream.AbstractWrite(mod_k_d);
+    mstream.AbstractWrite(mod_k_speed);
+    mstream.AbstractWrite(mod_r_d);
+    mstream.AbstractWrite(mod_r_speed);
+}
+
+void ChLinkSpring::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChLinkMarkers::StreamIN(mstream);
+
+		// stream in all member data
+	ChFunction* ffoo;
+	mstream >> spr_restlenght;
+    mstream >> spr_f;
+    mstream >> spr_k;
+    mstream >> spr_r;
+	mstream.AbstractReadCreate(&ffoo);		Set_mod_f_time(ffoo);
+	mstream.AbstractReadCreate(&ffoo);		Set_mod_k_d(ffoo);
+    mstream.AbstractReadCreate(&ffoo);		Set_mod_k_speed(ffoo);
+    mstream.AbstractReadCreate(&ffoo);		Set_mod_r_d(ffoo);
+    mstream.AbstractReadCreate(&ffoo);		Set_mod_r_speed(ffoo);
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkSpring.h b/SRC/ChronoEngine/physics/ChLinkSpring.h
new file mode 100644
index 0000000..34d5ccf
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkSpring.h
@@ -0,0 +1,163 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKSPRING_H
+#define CHLINKSPRING_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkSpring.h
+//
+//
+//   Classes for spring-dampers joints.
+//
+//   This class is inherited from the base ChLink()
+//   class, used by all joints in 3D.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkMarkers.h"
+
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_SPRING		25
+
+
+///
+/// Class for spring-damper systems, acting along the polar
+/// distance of two markers
+///
+
+class ChApi ChLinkSpring : public ChLinkMarkers {
+
+	CH_RTTI(ChLinkSpring,ChLinkMarkers);
+
+protected:
+	double spr_restlenght;
+	double spr_k;
+	double spr_r;
+	double spr_f;
+	ChFunction* mod_f_time;		// f(t)
+	ChFunction* mod_k_d;		// k(d)
+	ChFunction* mod_r_d;		// r(d)
+	ChFunction* mod_r_speed;	// k(speed)
+	ChFunction* mod_k_speed;	// r(speed)
+	double spr_react;		// resulting force in dist. coord / readonly
+public:
+
+				//
+	  			// FUNCTIONS
+				//
+						// builders and destroyers
+	ChLinkSpring ();
+	virtual ~ChLinkSpring ();
+	virtual void Copy(ChLinkSpring* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer, Link*
+
+	virtual int GetType	() {return LNK_SPRING;}
+
+						// data fetch/store
+	double Get_SpringRestLenght() {return spr_restlenght;};
+	void   Set_SpringRestLenght(double m_r) {spr_restlenght = m_r;};
+	double Get_SpringDeform() {return (dist - spr_restlenght);};
+	double Get_SpringK() {return spr_k;};
+	void   Set_SpringK(double m_r) {spr_k = m_r;};
+	double Get_SpringR() {return spr_r;};
+	void   Set_SpringR(double m_r) {spr_r = m_r;};
+	double Get_SpringF() {return spr_f;};
+	void   Set_SpringF(double m_r) {spr_f = m_r;};
+	double Get_SpringReact() {return spr_react;};
+
+	ChFunction* Get_mod_f_time() {return mod_f_time;};
+	ChFunction* Get_mod_k_d() {return mod_k_d;};
+	ChFunction* Get_mod_r_d() {return mod_r_d;};
+	ChFunction* Get_mod_k_speed() {return mod_k_speed;};
+	ChFunction* Get_mod_r_speed() {return mod_r_speed;};
+	void Set_mod_f_time	(ChFunction* m_funct);
+	void Set_mod_k_d	(ChFunction* m_funct);
+	void Set_mod_r_d	(ChFunction* m_funct);
+	void Set_mod_k_speed(ChFunction* m_funct);
+	void Set_mod_r_speed(ChFunction* m_funct);
+
+					/// Specialized initialization for springs, given the two bodies to be connected, the
+					/// positions of the two anchor endpoints of the spring (each expressed
+					/// in body or abs. coordinates) and the imposed rest length of the spring.
+					/// NOTE! As in ChLinkMarkers::Initialize(), the two markers are automatically 
+					/// created and placed inside the two connected bodies.
+	virtual int Initialize(ChSharedPtr<ChBody>& mbody1,	///< first body to link
+						   ChSharedPtr<ChBody>& mbody2, ///< second body to link
+						   bool pos_are_relative,	///< true: following posit. are considered relative to bodies. false: pos.are absolute
+						   ChVector<> mpos1,		///< position of spring endpoint, for 1st body (rel. or abs., see flag above)
+						   ChVector<> mpos2,		///< position of spring endpoint, for 2nd body (rel. or abs., see flag above) 
+						   bool auto_rest_length =true,///< if true, initializes the rest-length as the distance between mpos1 and mpos2
+						   double mrest_length =0   ///< imposed rest_length (no need to define, if auto_rest_length=true.)
+						   );
+
+					/// Get the 1st spring endpoint (expressed in Body1 coordinate system)
+	ChVector<> GetEndPoint1Rel() {return marker1->GetPos();}
+					/// Set the 1st spring endpoint (expressed in Body1 coordinate system)
+	void       SetEndPoint1Rel(const ChVector<>& mset) { marker1->Impose_Rel_Coord(ChCoordsys<>(mset,QUNIT));}
+					/// Get the 1st spring endpoint (expressed in absolute coordinate system)
+	ChVector<> GetEndPoint1Abs() {return marker1->GetAbsCoord().pos;}
+					/// Set the 1st spring endpoint (expressed in absolute coordinate system)
+	void       SetEndPoint1Abs(ChVector<>& mset) { marker1->Impose_Abs_Coord(ChCoordsys<>(mset,QUNIT));}
+
+					/// Get the 2nd spring endpoint (expressed in Body2 coordinate system)
+	ChVector<> GetEndPoint2Rel() {return marker2->GetPos();};
+					/// Set the 2nd spring endpoint (expressed in Body2 coordinate system)
+	void       SetEndPoint2Rel(const ChVector<>& mset) { marker2->Impose_Rel_Coord(ChCoordsys<>(mset,QUNIT));}
+					/// Get the 1st spring endpoint (expressed in absolute coordinate system)
+	ChVector<> GetEndPoint2Abs() {return marker2->GetAbsCoord().pos;}
+					/// Set the 1st spring endpoint (expressed in absolute coordinate system)
+	void       SetEndPoint2Abs(ChVector<>& mset) { marker2->Impose_Abs_Coord(ChCoordsys<>(mset,QUNIT));}
+
+			//
+			// UPDATING FUNCTIONS
+			//
+
+						/// Inherits, then also adds the spring custom forces to
+						/// the C_force and C_torque. 
+	virtual void UpdateForces (double mytime);
+
+
+			//
+			// STREAMING
+			//
+
+
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkTrajectory.cpp b/SRC/ChronoEngine/physics/ChLinkTrajectory.cpp
new file mode 100644
index 0000000..ed713f6
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkTrajectory.cpp
@@ -0,0 +1,205 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkTrajectory.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+
+#include "physics/ChLinkTrajectory.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). 
+ 
+
+namespace chrono
+{
+
+ 
+
+using namespace geometry;
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkTrajectory> a_registration_ChLinkTrajectory;
+
+
+                // BUILDERS
+ChLinkTrajectory::ChLinkTrajectory ()
+{
+    type = LNK_TRAJECTORY;       // initializes type
+
+	space_fx = new ChFunction_Ramp(0, 1.);
+
+	trajectory_line = 0;
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+            // to X  only. It was a LinkMaskLF because this class inherited from LinkLock.
+    ((ChLinkMaskLF*)mask)->SetLockMask(true, true, true,
+                       false, false, false, false,
+                       false, false);
+
+    ChangedLinkMask();
+}
+
+
+            // DESTROYER
+ChLinkTrajectory::~ChLinkTrajectory ()
+{
+	if (space_fx) 
+		delete space_fx;
+	space_fx=0;
+
+	if (trajectory_line) 
+		delete trajectory_line;
+	trajectory_line=0;
+
+    // nothing..
+}
+
+void ChLinkTrajectory::Copy(ChLinkTrajectory* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+	// copy own data
+
+	if (space_fx) 
+		delete space_fx;
+    space_fx =   source->space_fx->new_Duplicate();
+
+	if (trajectory_line) 
+		delete trajectory_line;
+    trajectory_line = static_cast<ChLine*> (source->trajectory_line->Duplicate());
+}
+
+
+ChLink* ChLinkTrajectory::new_Duplicate ()   
+{
+    ChLinkTrajectory* m_l;
+    m_l = new ChLinkTrajectory;  
+    m_l->Copy(this);
+    return (m_l);
+}
+
+
+
+void ChLinkTrajectory::Set_space_fx (ChFunction* m_funct)
+{
+    if (space_fx) 
+		delete space_fx;
+    space_fx = m_funct;
+}
+
+void ChLinkTrajectory::Set_trajectory_line (ChLine* mline)
+{
+	if (trajectory_line) 
+		delete trajectory_line;
+    trajectory_line = mline;
+}
+
+
+
+/////////    UPDATE TIME
+/////////
+
+void ChLinkTrajectory::UpdateTime (double time)
+{
+    ChTime = time;
+
+	double tr_time = space_fx->Get_y(time);
+
+	//R3OBJ* markerobj = ((ChExternalObjectR3D*)marker2->GetExternalObject())->Get_r3d_object();
+    //R3OBJ* lineobj = R3SendMsgA(markerobj, R3LEVM_GETSUBBYORDNUM, (void *)0);
+    if (trajectory_line)
+    {
+        Vector param, result, resultB, resultA;
+        double tstep = BDF_STEP_HIGH;
+        double timeB = tr_time + tstep;
+        double timeA = tr_time - tstep;
+        param.y= 0; param.z= 0;
+        param.x= fmod(tr_time, 1);
+		trajectory_line->Evaluate(result, param.x);
+        param.x= fmod(timeB, 1);
+		trajectory_line->Evaluate(resultB, param.x);
+        param.x= fmod(timeA, 1);
+		trajectory_line->Evaluate(resultA, param.x);
+
+        ChMatrix33<> mw;
+        mw.Set_A_quaternion(marker2->GetAbsCoord().rot);
+
+        deltaC.pos = mw.MatrT_x_Vect(
+                            Vsub (result, marker2->GetAbsCoord().pos));  // ***  CORRECT?
+        deltaC_dt.pos =  mw.MatrT_x_Vect(
+                            Vmul( Vsub(resultB, resultA), 1/(timeB-timeA)) );
+        deltaC_dtdt.pos =  mw.MatrT_x_Vect (
+                            Vmul   ( Vadd (Vadd (resultA, resultB),
+                                   Vmul (result,-2)), 4/pow(timeB-timeA, 2) ) );
+        deltaC.rot = QUNIT;
+        deltaC_dt.rot = QNULL;
+        deltaC_dtdt.rot = QNULL;
+    }
+	else
+	{
+		GetLog() << "NO TRAJECTORY \n";
+	}
+
+
+}
+
+
+
+void ChLinkTrajectory::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream.AbstractWrite(space_fx);
+	mstream.AbstractWrite(trajectory_line);
+}
+
+
+void ChLinkTrajectory::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+		// stream in all member data
+	ChFunction* ffoo=0;
+	mstream.AbstractReadCreate(&ffoo);		Set_space_fx(ffoo);
+	ChLine* mline=0;
+	mstream.AbstractReadCreate(&mline);		Set_trajectory_line(mline);
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkTrajectory.h b/SRC/ChronoEngine/physics/ChLinkTrajectory.h
new file mode 100644
index 0000000..a21d215
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkTrajectory.h
@@ -0,0 +1,109 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKTRAJECTORY_H
+#define CHLINKTRAJECTORY_H
+
+///////////////////////////////////////////////////
+//
+//   ChLinkTrajectory.h
+//
+//
+//   Class for point-on-imposed-trajectory constraint
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChLinkLock.h"
+#include "geometry/ChCLine.h"
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_TRAJECTORY  22
+
+
+///
+/// ChLinkTrajectory class.
+/// This class implements the 'point on an imposed 
+/// trajectory' constraint. 
+/// It can be used also to simulate the imposed motion
+/// of objects in space (for motion capture, for example).
+///
+
+class ChApi ChLinkTrajectory : public ChLinkLock {
+
+	CH_RTTI(ChLinkTrajectory,ChLinkLock);
+
+protected:
+
+						/// Function s=s(t) telling how the curvilinear
+						/// parameter of the trajectory is visited in time.
+	ChFunction* space_fx;
+			
+						/// The line for the trajectory.
+	geometry::ChLine*		trajectory_line;
+
+public:
+						// builders and destroyers
+	ChLinkTrajectory ();
+	virtual ~ChLinkTrajectory ();
+	virtual void Copy(ChLinkTrajectory* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+						/// Gets the address of the function s=s(t) telling 
+						/// how the curvilinear parameter of the trajectory changes in time.
+	ChFunction* Get_space_fx() {return space_fx;};
+						
+						/// Sets the function s=s(t) telling how the curvilinear parameter 
+						/// of the trajectory changes in time. 
+	void Set_space_fx	(ChFunction* m_funct);
+
+
+						/// Get the address of the trajectory line
+	geometry::ChLine* Get_trajectory_line() {return trajectory_line;}
+						
+						/// Sets the trajectory line (take ownership - does not copy line)
+	void Set_trajectory_line (geometry::ChLine* mline);
+
+
+							// UPDATING FUNCTIONS - "lock formulation" custom implementations
+
+							// Overrides the parent class function. Here it moves the 
+							// constraint mmain marker tangent to the line.
+	virtual void UpdateTime (double mytime);
+
+
+							// STREAMING
+
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkWheel.cpp b/SRC/ChronoEngine/physics/ChLinkWheel.cpp
new file mode 100644
index 0000000..e0c907c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkWheel.cpp
@@ -0,0 +1,724 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkWheel.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+ 
+ 
+#ifdef CH_V_PLUGIN
+ extern "C"
+ {
+    #include <r3error.h>
+	#include <r3quater.h>
+    #include <r3oops.h>
+    #include <r3link.h>
+    #include <r3freng.h>
+    #include "ChRlink.h"
+    #include "ChRmarker.h"
+    #include "ChRbody.h"
+    #include "ChRsystem.h"
+    #include "ChRutils.h"
+ }
+ #include "ChMathR3D.h"
+ #include "ChGlobalR3D.h"
+ #include "ChExternalObjectR3D.h"
+
+#endif
+
+#include "physics/ChLinkWheel.h"
+#include "physics/ChSystem.h"
+//#include "physics/ChCollide.h"
+//#include "lcp/ChLcpConstraintTwoFrictionOrtho.h"
+//#include "lcp/ChLcpConstraintTwoFrictionApprox.h"
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+//
+//   CLASS FOR WHEEL LINKS
+//
+//
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChLinkWheel> a_registration_ChLinkWheel;
+
+
+ChLinkWheel::ChLinkWheel ()
+{
+    type = LNK_WHEEL;       // initializes type
+
+    wheel_rotation = new ChFunction_Const (0);
+    wcollision = 0;
+    speed_handled = 0;
+    radius = 0.1;
+    thickness = 0.0;
+    friction = 0.7;
+    fri_spe =  new ChFunction_Const (1);
+    fri_norm = new ChFunction_Const (1);
+    allow_sticking = FALSE;
+    slip_treshold = 0.01;
+    static_friction = 1;
+    unilateral = TRUE;
+    pneus_krp = FALSE;
+    rad_k =   1000;
+    rad_r =  0.001;
+    rad_p = 100000; // about 1 atm..
+    rad_k_def = new ChFunction_Const (1);
+    pneus_h = 0.2;
+
+    angle = angle_dt = angle_dtdt = slipping = f_slip =
+        l_slip = derive_angle = tforce = f_tforce = l_tforce = curr_friction = 0;
+    loc_iters = 0;
+    mv = mu =  malpha = 0.0;
+
+    this->limit_Z->Set_active(TRUE);
+    this->limit_Z->Set_max(100000000.0);
+    this->limit_Z->Set_min(0.0);
+
+            // Mask: initialize our LinkMaskLF (lock formulation mask)
+    ((ChLinkMaskLF*)mask)->SetLockMask(false,false, true,
+                        false,false,false,false,
+                        false, false);
+	((ChLinkMaskLF*)mask)->Constr_Z().SetMode(CONSTRAINT_UNILATERAL);
+
+    ChangedLinkMask();
+}
+
+ChLinkWheel::~ChLinkWheel ()
+{
+    delete wheel_rotation;
+    delete fri_spe;
+    delete fri_norm;
+}
+
+void ChLinkWheel::Copy(ChLinkWheel* source)
+{
+    // first copy the parent class data...
+    //
+    ChLinkLock::Copy(source);
+
+    // copy custom data:
+
+    wcollision = source->wcollision;
+    speed_handled = source->speed_handled;
+    radius = source->radius;
+    thickness = source->thickness;
+    friction = source->friction;
+    allow_sticking = source->allow_sticking;
+    slip_treshold = source->slip_treshold;
+    static_friction = source->static_friction;
+    unilateral = source->unilateral;
+    pneus_krp = source->pneus_krp;
+    rad_k = source->rad_k;
+    rad_r = source->rad_r;
+    rad_p = source->rad_p;  // about 2 atm..
+    pneus_h = source->pneus_h;
+
+    if (wheel_rotation) delete wheel_rotation;
+        wheel_rotation =   source->wheel_rotation->new_Duplicate();
+    if (fri_spe) delete fri_spe;
+        fri_spe =   source->fri_spe->new_Duplicate();
+    if (fri_norm) delete fri_norm;
+        fri_norm =   source->fri_norm->new_Duplicate();
+    if (rad_k_def) delete rad_k_def;
+        rad_k_def =   source->rad_k_def->new_Duplicate();
+
+    angle = angle_dt = angle_dtdt = slipping = f_slip =
+        l_slip = derive_angle = tforce = f_tforce = l_tforce = curr_friction = 0;
+    loc_iters = 0;
+    mv = mu =  malpha = 0.0;
+}
+
+ChLink* ChLinkWheel::new_Duplicate ()
+{
+    ChLinkWheel* m_l;
+    m_l = new ChLinkWheel;  // inherited classes should write here: m_l = new MyInheritedLink;
+    m_l->Copy(this);
+    return (m_l);
+}
+
+void ChLinkWheel::Set_unilateral(int mset)
+{
+    this->unilateral = mset;
+    if (this->unilateral)
+    {
+        this->limit_Z->Set_active(TRUE);
+		((ChLinkMaskLF*)mask)->Constr_Z().SetMode(CONSTRAINT_FREE);
+    }
+    else
+    {
+        this->limit_Z->Set_active(FALSE);
+        ((ChLinkMaskLF*)mask)->Constr_Z().SetMode(CONSTRAINT_LOCK);
+    }
+    ChangedLinkMask();
+}
+
+void ChLinkWheel::UpdateTime (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateTime(mytime);
+
+    Vector m2_pos, m1_pos, vx, vy, vz, m1_relacc, m1_relvel;
+    Quaternion m2_rot, m1_rot;
+
+
+    //defaults: if no spindle obj. is provided, marker 1 is used instead
+        //spindle_csys.Set_A_quaternion(marker1->GetAbsCoord().rot);
+        //spindle_pos = marker1->GetAbsCoord().pos;
+    spindle_csys.Set_A_quaternion(Body1->GetCoord().rot);
+    spindle_pos = Body1->GetCoord().pos;
+
+
+    #ifdef CH_V_PLUGIN
+
+    // Fetch spindle obj.  (1st subobject link in marker 1)
+
+
+	R3OBJ* anobj = ((ChExternalObjectR3D*)marker1->GetExternalObject())->Get_r3d_object();
+
+    R3OBJ* spindleobj = Ch_GetLinkedParamObject(anobj, 0);
+    if (spindleobj)
+    {
+         // constant update surface geometry after each step... it may be rotated by chrono simulation
+        Ch_ForceUpdateOfR3Dcoords(spindleobj);
+
+        R3MATRIX m1;
+        R3SendMsgA(spindleobj, R3PRIMM_GETTOABSSPACEMATRIX, &m1);
+        R3Matrix_To_Chrono(m1, &spindle_csys, &spindle_pos);
+    }
+
+
+    // Fetch surface of contact (1st subobj link in marker 2)
+
+
+	R3OBJ* anobjb = ((ChExternalObjectR3D*)marker2->GetExternalObject())->Get_r3d_object();
+
+    R3OBJ* groundobj = Ch_GetLinkedParamObject(anobjb, 0);
+    if (groundobj)
+    {
+        // constant update surface geometry after each step... it may be rotated by chrono simulation
+        //Ch_ForceUpdateOfR3Dcoords(groundobj);
+        //***NOT NEEDED since an hypothesis for the use of this constraint is that
+        //   steady (not moving) grounds must be used!
+    }
+
+    #endif
+
+
+    ///////  CONTACT MODE:          (also used to set defaults, and default mode)
+    ///////  -- X-Z PLANE ---
+    ///////
+
+    // Default normal
+    Vector surf_normal = VECT_Y;
+    // Radius vector from spindle to ground (default)
+    Vector vgroundrad = Vmul( Vcross (spindle_csys.Get_A_Zaxis(), Vnorm (Vcross (spindle_csys.Get_A_Zaxis() , surf_normal) )), Get_RigidRadius());
+
+    // Defaults for marker positions and rotations
+    m1_pos = Vadd(spindle_pos, vgroundrad);
+
+     Vector vm1z = Vmul(Vnorm(vgroundrad), -1.0);
+     Vector vm1x = Vnorm(Vcross( spindle_csys.Get_A_Zaxis(), vm1z ));
+     ChMatrix33<> a_m1;
+     a_m1.Set_A_axis(vm1x, spindle_csys.Get_A_Zaxis(), vm1z );
+    m1_rot = Qnorm(a_m1.Get_A_quaternion());
+
+
+    m2_pos= m1_pos;
+    m2_pos.y = 0.0;
+
+     ChMatrix33<> a_m2;
+     vz = surf_normal;
+     vy = spindle_csys.Get_A_Zaxis();
+     vx = Vnorm(Vcross(vy, vz));
+     vy = Vnorm(Vcross(vz, vx));
+     a_m2.Set_A_axis(vx, vy, vz);
+    m2_rot = a_m2.Get_A_quaternion();
+
+    // Compute relative speed of reference M1
+    // (hypothesis: ground is flat and steady: contact must move with same vel. as wheel spindle)
+    Vector vabsradius = Vsub(m1_pos, spindle_pos);
+    m1_relvel = Body1->GetA()->MatrT_x_Vect(
+        Vcross(vabsradius, Body1->GetWvel_par()) );
+    // Compute relative acceleration of reference M1
+    // (hypothesis: ground is flat and steady: contact must move with same acc. as wheel spindle)
+    m1_relacc = Body1->GetA()->MatrT_x_Vect(
+        Vcross(Body1->GetWvel_par() , Vcross(vabsradius, Body1->GetWvel_par()) ) ); // cut centrip
+    m1_relacc = Vadd( m1_relacc,
+        Vmul (Vcross(Body1->GetWvel_loc(), m1_relvel) , -2.0 ) );   // cut coriolis
+    m1_relacc = Vadd( m1_relacc,
+        Body1->GetA()->MatrT_x_Vect(Vcross(vabsradius, Body1->GetWacc_par() ) ) ); // cut tang acc
+
+
+    ///////  CONTACT MODE:
+    ///////  -- Y-COLLISION ---
+    ///////
+
+   #ifdef CH_V_PLUGIN
+    if (this->wcollision == WCOLLISION_YCOLLIDE)
+    {
+        R3OBJ* target;
+        if (groundobj)
+            target = groundobj;
+        else
+            target = ((ChExternalObjectR3D*)GetBody2()->GetExternalObject())->Get_r3d_object();
+
+        R3OBJ* renderer = NULL;
+        if (!renderer)
+            if(!(renderer = R3ObjectCreate(R3CLID_FRENGINE, R3TAG_END))) return;
+        // describe scene to rendering engine
+        if(!(int)R3SendMsgA(renderer, R3FRM_BEGINWORLD, NULL)) return;
+        R3SendMsg(target, R3PRIMM_RENDER,
+            R3PRIMA_RenderEngine, renderer,
+            R3PRIMA_RenderAlways, TRUE,
+            R3TAG_END);
+        if(!(int)R3SendMsgA(renderer, R3FRM_ENDWORLD, NULL)) return;
+        // optimize octree??
+        //R3SendMsgA(renderer, R3FRM_OPTIMIZEHIT, NULL);
+
+        Vector direction, origin, hitpoint, m_uv;
+        direction = Vnorm(Vmul(vgroundrad, -1.0));
+        origin = Vadd(spindle_pos, Vmul(vgroundrad, 1.001) );  // start ray from circumference toward center (speed optimization)
+        int hit_ok;
+
+        // launch intersection ray!
+        hit_ok =(int) R3SendMsgA3(renderer, R3FRM_FINDHIT, &origin, &direction, &hitpoint);
+
+        if(hit_ok &&
+            (Vdot(Vsub(hitpoint,origin), direction)>= ((-0.00001)*this->Get_RigidRadius() )) )
+        {
+            // something has hit...
+            R3SendMsgA2(renderer, R3FRM_EVALHITGEOMETRY, &m_uv, &surf_normal);
+            // useful vars
+            surf_normal = Vnorm (surf_normal);
+            Vector real_radius;
+            real_radius = Vsub(hitpoint,spindle_pos);
+            double hit_lenght = Vlenght(real_radius);
+             // compute position of m2
+            m2_pos = hitpoint;
+             // compute rotation of m2 (ground marker)
+            vz = surf_normal;
+            vy = spindle_csys.Get_A_Zaxis();
+            vx = Vnorm(Vcross(vy, vz));
+            vy = Vnorm(Vcross(vz, vx));
+            a_m2.Set_A_axis(vx, vy, vz);
+            m2_rot = a_m2.Get_A_quaternion();
+             // compute position and rotation of m1 (wheel marker) (not needed?)
+            //m1_rot = m2_rot; // NOT!
+            //m1_pos = Vadd(spindle_pos, vgroundrad ); // NOT!
+
+            this->limit_Z->Set_active(TRUE);
+        }
+        else
+        {
+            // no hit found!!
+            m2_pos = m1_pos;
+            m2_rot = m1_rot;
+
+            this->limit_Z->Set_active(FALSE);
+
+            // force link opening!!!
+            if (((ChLinkMaskLF*)mask)->Constr_Z().IsActive())
+            {
+                ((ChLinkMaskLF*)mask)->Constr_Z().SetMode(CONSTRAINT_FREE);
+                ChangedLinkMask();
+                if (system)
+                    ((ChSystem*)system)->Setup(); // ndoc has changed!
+            }
+        }
+        // suppose flat surface
+
+		if(renderer) R3ObjectDelete(renderer);
+
+    }
+   #endif
+
+    // MOVE "MAIN" MARKER 2 INTO UPDATED POSITION
+    //
+    Coordsys newmarkpos2;
+    newmarkpos2.pos = m2_pos;
+    newmarkpos2.rot = m2_rot;
+    marker2->Impose_Abs_Coord(newmarkpos2);   // move "main" marker2 into tangent position
+    marker2->SetMotionType(ChMarker::M_MOTION_EXTERNAL); //M_MOTION_KEYFRAMED );  // the BDF routine won't handle speed and acc.calculus of the point
+    marker2->UpdateState();
+
+    // MOVE "SLAVE" MARKER 1 INTO UPDATED POSITION
+    //
+    Coordsys newmarkpos1;
+    Coordsys relmotioncsys = CSYSNULL;
+    newmarkpos1.pos = m1_pos;
+    newmarkpos1.rot = m1_rot;
+    marker1->Impose_Abs_Coord(newmarkpos1);   // impose position to slave marker
+    relmotioncsys.pos = m1_relvel;
+    marker1->SetCoord_dt(relmotioncsys);   // impose rel.speed
+    relmotioncsys.pos = m1_relacc;
+    marker1->SetCoord_dtdt(relmotioncsys); // impose rel.accel.
+    marker1->SetMotionType(ChMarker::M_MOTION_EXTERNAL);  //M_MOTION_KEYFRAMED ); // the BDF routine won't handle speed and acc.calculus of the point
+    marker1->UpdateState();
+
+    // THE RELATIVE MARKER POSITION:
+    //
+    deltaC.pos = VNULL;
+    deltaC_dt.pos = VNULL;
+    deltaC_dtdt.pos = VNULL;
+
+    deltaC.rot = QUNIT;
+    deltaC_dt.rot = QNULL;
+    deltaC_dtdt.rot = QNULL;
+}
+
+
+
+void ChLinkWheel::UpdateForces (double mytime)
+{
+    // First, inherit to parent class
+    ChLinkLock::UpdateForces(mytime);
+
+   #ifdef CH_V_PLUGIN
+
+            // fetch tyre surface of wheel (the 2nd subobject link of marker 1)
+
+
+	R3OBJ* anobj1 = ((ChExternalObjectR3D*)marker1->GetExternalObject())->Get_r3d_object();
+
+	R3OBJ* anobj2 = ((ChExternalObjectR3D*)marker2->GetExternalObject())->Get_r3d_object();
+
+    R3OBJ* tyreobj = Ch_GetLinkedParamObject(anobj1, 1);
+            // fetch surface of contact (1st subobject link of marker 2)
+    R3OBJ* surfobj  = Ch_GetLinkedParamObject(anobj2, 0);
+
+
+    // Now, if ground and wheel surfaces are here, we can do the "soft wheel" model
+    if (surfobj && tyreobj && (this->thickness>0.0))
+    {
+
+        R3OBJ* renderer;
+        if(!(renderer = R3ObjectCreate(R3CLID_FRENGINE, R3TAG_END))) return;
+        // describe scene to rendering engine
+        if(!(int)R3SendMsgA(renderer, R3FRM_BEGINWORLD, NULL)) return;
+        R3SendMsg(surfobj, R3PRIMM_RENDER,
+            R3PRIMA_RenderEngine, renderer,
+            R3PRIMA_RenderAlways, TRUE,
+            R3TAG_END);
+        if(!(int)R3SendMsgA(renderer, R3FRM_ENDWORLD, NULL)) return;
+        // optimize octree
+        R3SendMsgA(renderer, R3FRM_OPTIMIZEHIT, NULL);
+
+        #define U_WHEEL 36
+        #define V_WHEEL 4
+        Vector m_normals[U_WHEEL][V_WHEEL];
+        Vector m_pos[U_WHEEL][V_WHEEL];
+        double m_areas[U_WHEEL][V_WHEEL];
+        double m_disp[U_WHEEL][V_WHEEL];
+        Vector forces_sum = VNULL;
+        Vector torques_sum = VNULL;
+        Vector polo_sum = this->marker1->GetAbsCoord().pos;
+
+        for (int iu = 0; iu < U_WHEEL; iu++)
+        {
+            for (int iv = 0; iv < V_WHEEL; iv++)
+            {
+                double mu = (iu / ((double)U_WHEEL));
+                double mv = (iv / ((double)V_WHEEL));
+                Vector param, duparam, dvparam;
+                param.x = mu + 0.5* 1.0/((double)U_WHEEL);
+                param.y = mv + 0.5* 1.0/((double)V_WHEEL);
+                param.z = 0;
+                duparam = param; duparam.x += 0.0001;
+                dvparam = param; dvparam.y += 0.0001;
+                Vector ppos, dupos, dvpos, mnorm, vdu, vdv;
+                Vector direction, origin, hitpoint, m_uv, surf_normal;
+                R3SendMsgA3(tyreobj, R3PRIMM_EVALUATE, (void *)R3SPACE_ABSOLUTE, &param, &ppos);
+                R3SendMsgA3(tyreobj, R3PRIMM_EVALUATE, (void *)R3SPACE_ABSOLUTE, &duparam, &dupos);
+                R3SendMsgA3(tyreobj, R3PRIMM_EVALUATE, (void *)R3SPACE_ABSOLUTE, &dvparam, &dvpos);
+                vdu = Vsub(dupos, ppos);
+                vdv = Vsub(dvpos, ppos);
+                mnorm = Vnorm(Vcross(vdu, vdv));
+                direction = Vmul(mnorm, -1.0);
+                origin = Vadd(ppos, Vmul(mnorm, this->thickness));
+                m_pos[iu][iv] = ppos;
+                m_normals[iu][iv] = mnorm;
+                m_areas[iu][iv] = (1.0/0.0001) * (1.0/0.0001) * Vlenght(Vcross(vdu, vdv));
+                m_disp[iu][iv] = 0.0;
+                // findhit
+                if(Vdot(direction,VECT_Y) < -0.5)  // optimization: check only toward xz plane
+                 if(R3SendMsgA3(renderer, R3FRM_FINDHIT, &origin, &direction, &hitpoint))
+                {
+                    R3SendMsgA2(renderer, R3FRM_EVALHITGEOMETRY, &m_uv, &surf_normal);
+                    surf_normal = Vnorm (surf_normal);
+                    if (Vdot(mnorm,surf_normal)<0.0)
+                        surf_normal = Vmul(surf_normal, -1.0);
+                    if (Vdot(mnorm,surf_normal)<0.0)
+                        surf_normal = Vmul(surf_normal, -1.0);
+                    m_normals[iu][iv] = surf_normal;
+
+                    m_disp[iu][iv] = this->thickness - Vlenght(Vsub(origin, hitpoint));
+                    if (m_disp[iu][iv] < 0.0)
+                           m_disp[iu][iv] = 0.0;
+//-
+                    if (m_disp[iu][iv] > 0.0)
+                    {
+
+                        Vector vrad_force, vtan_force, vtotal_force;
+                        Vector vrel_speed, vtan_speed, vrad_speed;
+                        double m_rad_force, m_rad_speed;
+                        // radial compression force
+                        m_rad_force = (m_areas[iu][iv] * m_disp[iu][iv] *
+                                         this->rad_k * this->rad_k_def->Get_y(m_disp[iu][iv]) );
+                        // radial damping force , proportional to orthogonal speed of compression
+                        vrel_speed = Vsub( Body2->RelPoint_AbsSpeed(&(Body2->Point_World2Body(&m_pos[iu][iv]))),
+                                           Body1->RelPoint_AbsSpeed(&(Body1->Point_World2Body(&m_pos[iu][iv])))  ) ;
+                        m_rad_speed = Vdot(m_normals[iu][iv], vrel_speed);
+                        vrad_speed = Vmul(m_normals[iu][iv], m_rad_speed);
+                        vtan_speed = Vsub(vrel_speed, vrad_speed);
+                        m_rad_force +=  m_areas[iu][iv] * this->rad_r * m_rad_speed;
+
+                        if (m_rad_force <= 0) m_rad_force = 0; // no radial traction force, only compression.
+
+                        vrad_force = Vmul (m_normals[iu][iv], m_rad_force);
+                        vtan_force = Vmul (Vnorm(vtan_speed), m_rad_force * this->friction);
+                        vtotal_force = Vadd(vrad_force, vtan_force);
+
+                        forces_sum = Vadd(forces_sum, vtotal_force);
+                        torques_sum = Vadd(torques_sum, Vcross(vtotal_force, Vsub(m_pos[iu][iv], polo_sum)));
+
+                        this->Body1->Add_as_lagrangian_force(
+                            vtotal_force,               // Force in abs space! (as seen from Body1)
+                            m_pos[iu][iv],          // application point
+                            FALSE,                  // reference: absolute
+                            Qf1);                   // store += the resulting lagrangian torque;
+
+                        this->Body2->Add_as_lagrangian_force(
+                            Vmul(vtotal_force, -1.0),   // Force in abs space! (as seen from Body2, F2=-F1)
+                            m_pos[iu][iv],          // application point
+                            FALSE,                  // reference: absolute
+                            Qf2);                   // store += the resulting lagrangian torque;
+
+                    }
+
+                }
+                else
+                    m_disp[iu][iv] = 0.0;
+            }
+        }
+
+        if(renderer) R3ObjectDelete(renderer);
+
+    } // end soft wheel model
+
+   #endif
+
+    // COMPUTE SLIP FORCES
+
+    Vector mvradius = Vsub(marker2->GetAbsCoord().pos, this->spindle_pos);
+
+    // point of contact on Body1: absolute speed
+    Vector vp1 = Vadd (Body1->GetCoord_dt().pos,
+                       Body1->GetA_dt().Matr_x_Vect(marker1->GetCoord().pos) );
+
+    // point of contact on Body2: absolute speed
+    Vector vp2 = Vadd (Body2->GetCoord_dt().pos,
+                       Body2->GetA_dt().Matr_x_Vect(marker2->GetCoord().pos) );
+
+    Vector mabs_slip = Vsub(vp1, vp2);
+
+    ChMatrix33<> mtra1;
+    mtra1.Set_A_quaternion(marker1->GetAbsCoord().rot);
+    ChMatrix33<> mtra2;
+    mtra2.Set_A_quaternion(marker2->GetAbsCoord().rot);
+
+
+
+    // skip further computations if wheel do not touch ground
+    //
+    if (Vlenght(mvradius) > this->radius*1.01)
+    {
+        slipping = f_slip = l_slip = derive_angle = tforce = f_tforce = l_tforce = curr_friction = 0;
+        return;     // <<<<<
+    }
+
+    // effect of imposed rotation:
+    //
+    if (speed_handled == 1)    // set artificial speed
+    {   angle  = wheel_rotation->Get_y(ChTime);
+        angle_dt = wheel_rotation->Get_y_dx(ChTime);
+        angle_dtdt =  wheel_rotation->Get_y_dxdx(ChTime);
+    }
+    if (speed_handled == 2)    // set artificial speed (function already represents dy/dx mode)
+    {   angle  = 0; // ***TO DO*** wheel_rotation->Get_y_Ix(ChTime, initial_rot);
+        angle_dt = wheel_rotation->Get_y(ChTime);
+        angle_dtdt =  wheel_rotation->Get_y_dx(ChTime);
+    }
+    if (speed_handled)
+        mabs_slip = Vadd( mabs_slip,        // s = s + w x R
+                        Vcross( Vmul(this->spindle_csys.Get_A_Zaxis(), angle_dt),   // w
+                        mvradius)   // R
+                        );
+ 
+    Vector mrel_slip2 = mtra2.MatrT_x_Vect(mabs_slip);
+    //Vector mrel_slip1 = mtra1.MatrT_x_Vect(mabs_slip);
+
+    this->slipping = Vlenght(mabs_slip);
+
+    this->l_slip = mrel_slip2.y;
+    this->f_slip = mrel_slip2.x;
+
+    double norm_force = 0.0;
+    if (this->react)
+        norm_force += this->GetReact()->GetElement(0,0);  // N = constraint reaction
+//if (norm_force >0.01)
+//  R3Error("pos force %g", norm_force);
+
+    this->curr_friction = this->friction *
+                   this->fri_spe->Get_y(slipping) *
+                   this->fri_norm->Get_y(norm_force);
+
+    this->tforce = this->curr_friction * norm_force;  // Ft = u() *Fn
+    tforce = fabs(tforce);
+
+    Vector m_force2 = Vmul( Vnorm(mrel_slip2), (tforce * -1.0) );
+    m_force2.z= 0; // Ft_z should be already near zero, in m2 csys, but imposed for safety.
+
+    Vector mabs_slipforce = mtra2.Matr_x_Vect(m_force2);
+    //Vector mabs_slipforce = Vmul( Vnorm(mabs_slip), (tforce * -1.0) );
+
+    this->l_tforce = m_force2.y;
+    this->f_tforce = m_force2.x;
+
+/* ***should use only C_force and C_torque*** .... Qf1 and Qf2 are deprecated ... TO DO
+    this->Body1->Add_as_lagrangian_force(
+        mabs_slipforce,         // Force in abs space! (as seen from Body1)
+        marker2->GetAbsCoord().pos,  // application point: marker 2 (the ground contact point)
+        FALSE,                  // reference: absolute
+        Qf1);                   // store += the resulting lagrangian force/torque;
+
+    this->Body2->Add_as_lagrangian_force(
+        Vmul(mabs_slipforce, -1.0), // Force in abs space! (as seen from Body2, F2=-F1)
+        marker2->GetAbsCoord().pos,  // application point: marker 2 (the ground contact point)
+        FALSE,                  // reference: absolute
+        Qf2);                   // store += the resulting lagrangian force/torque;
+*/
+}
+
+void ChLinkWheel::Set_wheel_rotation(ChFunction* m_funct)
+{
+    if (wheel_rotation) delete wheel_rotation;  wheel_rotation = m_funct;
+}
+void ChLinkWheel::Set_fri_spe(ChFunction* m_funct)
+{
+    if (fri_spe) delete fri_spe;    fri_spe = m_funct;
+}
+void ChLinkWheel::Set_fri_norm(ChFunction* m_funct)
+{
+    if (fri_norm) delete fri_norm;  fri_norm = m_funct;
+}
+void ChLinkWheel::Set_rad_k_def(ChFunction* m_funct)
+{
+    if (rad_k_def) delete rad_k_def; rad_k_def = m_funct;
+}
+
+
+
+// FILE I/O
+//
+
+void ChLinkWheel::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChLinkLock::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << speed_handled;
+    mstream << radius;
+    mstream << thickness;
+    mstream << friction;
+    mstream << allow_sticking;
+    mstream << slip_treshold;
+    mstream << static_friction;
+    mstream << unilateral;
+    mstream << pneus_krp;
+    mstream << rad_k;
+    mstream << rad_r;
+    mstream << rad_p;
+    mstream << pneus_h;
+	mstream.AbstractWrite(wheel_rotation);
+	mstream.AbstractWrite(fri_spe);
+    mstream.AbstractWrite(fri_norm);
+	mstream.AbstractWrite(rad_k_def);
+    mstream << wcollision;
+}
+
+void ChLinkWheel::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChLinkLock::StreamIN(mstream);
+
+	    // To restore mask array when loading finishes, (maybe following data loading changes mask..)
+    ChLinkMask* moriginalmask = this->mask->NewDuplicate();
+
+		// stream in all member data
+	ChFunction* ffoo;
+	mstream >> speed_handled;
+    mstream >> radius;
+    mstream >> thickness;
+    mstream >> friction;
+    mstream >> allow_sticking;
+    mstream >> slip_treshold;
+    mstream >> static_friction;
+    mstream >> unilateral;
+    mstream >> pneus_krp;
+    mstream >> rad_k;
+    mstream >> rad_r;
+    mstream >> rad_p;
+    mstream >> pneus_h;
+	mstream.AbstractReadCreate(&ffoo);	Set_wheel_rotation(ffoo);
+	mstream.AbstractReadCreate(&ffoo);	Set_fri_spe(ffoo);
+    mstream.AbstractReadCreate(&ffoo);	Set_fri_norm(ffoo);
+	mstream.AbstractReadCreate(&ffoo);	Set_rad_k_def(ffoo);
+    mstream >> wcollision;
+
+	this->mask->Copy(moriginalmask);
+    this->ChangedLinkMask();
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChLinkWheel.h b/SRC/ChronoEngine/physics/ChLinkWheel.h
new file mode 100644
index 0000000..5efcd4a
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkWheel.h
@@ -0,0 +1,194 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKWHEEL_H
+#define CHLINKWHEEL_H
+
+///////////////////////////////////////////////////
+//
+//   ChLink.h
+//
+//
+//   Classes for fast simulation of rigid wheels
+//   with zero mass.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChLinkLock.h"
+
+
+
+namespace chrono
+{
+
+// Unique link identifier, for detecting type faster than with rtti.
+#define LNK_WHEEL		26
+
+
+#define WCOLLISION_PLANE	0
+#define WCOLLISION_YCOLLIDE 1
+
+///
+/// Class representing a wheel constraint (for fast simulation
+/// of cars, etc.)
+///
+
+class ChApi ChLinkWheel : public ChLinkLock {
+
+	CH_RTTI(ChLinkWheel,ChLinkLock);
+
+protected:
+	ChFunction* wheel_rotation;		// rotation(time) or rotation_speed(time)
+	int	speed_handled;		// if TRUE, wheel_rotation means angular speed, not angle.
+	double radius;			//  wheel radius
+	double thickness;		//  wheel thickness
+
+								// FRICTION MODEL
+	double friction;		// friction coefficient;
+	ChFunction* fri_spe;	// friction(slipping_speed)	 modulation (def=1)
+	ChFunction* fri_norm;	// friction(normal_contact_force)  modulation (def=1)
+
+								// STICKING
+	int allow_sticking;		// if true, tangential contraint will be added when
+							// sticking happens (for  slip_speed < slip_treshold)
+	double slip_treshold;	// def. 0.01 m/s ??
+	double static_friction;	// statical friction coefficient (to guess when breaking tangential sticking contraint);
+
+								// VERTICAL CONSTRAINT
+	int wcollision;			// collision detection mode
+	int	unilateral;			// if TRUE, unilateral constraint, FALSE= bilateral;
+	int pneus_krp;			// if TRUE, uses the nonlinear functions of k and r to simulate pneus radial deformability
+	 double rad_k;			// radial stiffness;
+	 double rad_r;			// radial damping;
+	 double rad_p;			// radial pressure; (const.radial force f, per square surf.unit)
+	 double pneus_h;		// radial height of pneus (percentual of radius, 0..1)
+	 ChFunction* rad_k_def;	// modulation of k stiffness as a function of deformation
+
+								// INFO DATA   -also as auxiliary temp.data for intermediate calculus-
+	double angle;			// current wheel rotation angle (artificial, for simplified model)
+	double angle_dt;		// "" speed
+	double angle_dtdt;		// "" acceleration
+	double slipping;		// absolute slipping speed;
+	double f_slip;			// the frontal part of slipping (in direction of the wheel)
+	double l_slip;			// the lateral part of slipping (perp. to direction of wheel)
+	double derive_angle;	// derive angle
+	double tforce;			// tangential contact force (modulus) on wheel
+	double f_tforce;		// the frontal part of contact force (in direction of the wheel)
+	double l_tforce;		// the lateral part of contact force (perp. to direction of wheel)
+	double curr_friction;	// the current value of friction coeff as f=f(slip, norm.pressure, etc)
+
+								// Auxiliary, internal
+	ChMatrix33<> spindle_csys;	// direction of spindle (Z axis used)
+	Vector spindle_pos;		// position of spindle
+	int loc_iters;
+	double mu;
+	double mv;
+	double malpha;
+
+public:
+						// builders and destroyers
+	ChLinkWheel ();
+	virtual ~ChLinkWheel ();
+	virtual void Copy(ChLinkWheel* source);
+	virtual ChLink* new_Duplicate ();	// always return base link class pointer
+
+
+							// UPDATING FUNCTIONS - "wheel link" custom implementations
+
+							// Updates the position of marker m2, moving it -tangentially- on the
+							// surf/wheel contact point (m1 representing the center of wheel)
+							// Updates motion laws depending on surface & wheel curvatures.
+	virtual void UpdateTime (double mytime);
+
+							// Apply tangential force/torque to terrain and wheel, depending on
+							// relative slipping.  Also, all the INFO DATA datas are computed.
+	virtual void UpdateForces (double mytime);
+
+
+			// data get/set
+	ChFunction* Get_wheel_rotation() {return wheel_rotation;};
+	void Set_wheel_rotation(ChFunction* m_funct);
+	int   Get_speed_handled() {return speed_handled;};
+	void  Set_speed_handled(int mset) {speed_handled = mset;}
+	int   Get_wcollision() {return wcollision;};
+	void  Set_wcollision(int mset) {wcollision = mset;}
+	double  Get_radius() {return radius;};
+	void  Set_radius(double mset) {radius = mset; this->limit_Z->Set_min(radius-thickness);}
+	double  Get_thickness() {return thickness;};
+	void  Set_thickness(double mset) {thickness = mset; this->limit_Z->Set_min(radius-thickness);}
+	double  Get_friction() {return friction;};
+	void  Set_friction(double mset) {friction = mset;}
+	ChFunction* Get_fri_spe() {return fri_spe;};
+	void Set_fri_spe(ChFunction* m_funct);
+	ChFunction* Get_fri_norm() {return fri_norm;};
+	void Set_fri_norm(ChFunction* m_funct);
+	int   Get_allow_sticking() {return allow_sticking;};
+	void  Set_allow_sticking(int mset) {allow_sticking = mset;}
+	double  Get_slip_treshold() {return slip_treshold;};
+	void  Set_slip_treshold(double mset) {slip_treshold = mset;}
+	double  Get_static_friction() {return static_friction;};
+	void  Set_static_friction(double mset) {static_friction = mset;}
+	int   Get_unilateral() {return unilateral;};
+	void  Set_unilateral(int mset); // see cpp,
+	int   Get_pneus_krp() {return pneus_krp;};
+	void  Set_pneus_krp(int mset) {pneus_krp = mset;}
+	double Get_rad_k() {return rad_k;};
+	void  Set_rad_k(double mset) {rad_k = mset;}
+	double Get_rad_r() {return rad_r;};
+	void  Set_rad_r(double mset) {rad_r = mset;}
+	double Get_rad_p() {return rad_p;};
+	void  Set_rad_p(double mset) {rad_p = mset;}
+	double Get_pneus_h() {return pneus_h;};
+	void  Set_pneus_h(double mset) {pneus_h = mset; if (pneus_h >1) pneus_h = 1;}
+	void Set_rad_k_def(ChFunction* m_funct);
+	ChFunction* Get_rad_k_def() {return rad_k_def;};
+	double Get_RigidRadius() {return (radius - thickness);};
+	ChMatrix33<>* Get_wheel_spindle_csys() {return &spindle_csys;};
+	Vector  Get_wheel_spindle_pos() {return spindle_pos;};
+
+	double Get_angle() {return angle;};
+	double Get_angle_dt() {return angle_dt;};
+	double Get_angle_dtdt() {return angle_dtdt;};
+	double Get_slipping() {return slipping;};
+	double Get_f_slip() {return f_slip;};
+	double Get_l_slip() {return l_slip;};
+	double Get_derive_angle() {return derive_angle;};
+	double Get_tforce() {return tforce;};
+	double Get_f_tforce() {return f_tforce;};
+	double Get_l_tforce() {return l_tforce;};
+	double Get_curr_friction() {return curr_friction;};
+
+
+							// STREAMING
+	virtual void StreamIN(ChStreamInBinary& mstream);
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChLinkforce.cpp b/SRC/ChronoEngine/physics/ChLinkforce.cpp
new file mode 100644
index 0000000..db64be0
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkforce.cpp
@@ -0,0 +1,213 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChLinkforce.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChLinkforce.h"
+ 
+ 
+namespace chrono
+{
+ 
+
+ChLinkForce::ChLinkForce()
+{
+	active = 0;		// default: inactive limit
+
+	iforce = 0;
+	modul_iforce= new ChFunction_Const (1);  // default: const.modulation of iforce
+
+	K = 0;
+	modul_K =	new ChFunction_Const (1);  // default: const.modulation of K
+
+	R = 0;
+	modul_R =   new ChFunction_Const (1);  // default: const.modulation of R
+}
+
+
+ChLinkForce::~ChLinkForce ()
+{
+	if (modul_iforce) delete modul_iforce;
+	if (modul_K) delete modul_K;
+	if (modul_R) delete modul_R;
+}
+
+void ChLinkForce::Copy (ChLinkForce* source)
+{
+	active = source->active;
+
+	iforce = source->iforce;
+	K = source->K;
+	R = source->R;
+
+		// replace functions:
+	if (modul_iforce) delete modul_iforce;
+	if (modul_K) delete modul_K;
+	if (modul_R) delete modul_R;
+
+	modul_iforce = source->modul_iforce->new_Duplicate();
+	modul_K =   source->modul_K->new_Duplicate();
+	modul_R =   source->modul_R->new_Duplicate();
+}
+
+ChLinkForce* ChLinkForce::new_Duplicate ()
+{
+	ChLinkForce* m_lim;
+	m_lim = new ChLinkForce;
+	m_lim->Copy(this);
+	return (m_lim);
+}
+
+
+
+void ChLinkForce::Set_modul_iforce	(ChFunction* m_funct)
+{
+	if (modul_iforce) delete modul_iforce;
+	modul_iforce = m_funct;
+}
+void ChLinkForce::Set_modul_K	(ChFunction* m_funct)
+{
+	if (modul_K) delete modul_K;
+	modul_K = m_funct;
+}
+void ChLinkForce::Set_modul_R	(ChFunction* m_funct)
+{
+	if (modul_R) delete modul_R;
+	modul_R = m_funct;
+}
+
+
+
+// file parsing / dumping
+
+void ChLinkForce::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// stream out all member data
+	mstream << Get_active();
+	mstream << Get_iforce();
+	mstream.AbstractWrite(Get_modul_iforce());
+	mstream << Get_K();
+	mstream.AbstractWrite(Get_modul_K());
+	mstream << Get_R();
+	mstream.AbstractWrite(Get_modul_R());
+}
+
+void ChLinkForce::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in all member data
+	double dfoo;
+	int ifoo;
+	ChFunction* ffoo;
+	mstream >> ifoo;			Set_active(ifoo);
+	mstream >> dfoo;			Set_iforce(dfoo);
+	mstream.AbstractReadCreate(&ffoo);		Set_modul_iforce(ffoo);
+	mstream >> dfoo;			Set_K(dfoo);
+	mstream.AbstractReadCreate(&ffoo);		Set_modul_K(ffoo);
+	mstream >> dfoo;			Set_R(dfoo);
+	mstream.AbstractReadCreate(&ffoo);		Set_modul_R(ffoo);
+}
+
+void ChLinkForce::StreamOUT(ChStreamOutAscii& mstream)
+{
+	//***TO DO***
+}
+
+
+
+
+double ChLinkForce::Get_Kcurrent (double x, double x_dt, double t)
+{
+	double mK = 0;
+	if (active)
+	{
+		double modulator;
+
+		if (modul_K) { modulator = modul_K->Get_y(x);}
+		else { modulator = 1;}
+		mK = K * modulator;
+	}
+	return mK;
+}
+
+double ChLinkForce::Get_Rcurrent (double x, double x_dt, double t)
+{
+	double mR = 0;
+	if (active)
+	{
+		double modulator;
+
+		if (modul_R) { modulator = modul_R->Get_y(x);}
+		else { modulator = 1;}
+		mR = R * modulator;
+	}
+	return mR;
+}
+
+double ChLinkForce::Get_iFcurrent (double x, double x_dt, double t)
+{
+	double mforce = 0;
+	if (active)
+	{
+		double modulator;
+
+				// the internal force contribute = iforce
+		if (modul_iforce) { modulator = modul_iforce->Get_y(t);}
+		else { modulator = 1;}
+		mforce=  iforce * modulator;
+	}
+	return mforce;
+}
+
+///////////////////
+
+double ChLinkForce::Get_Force (double x, double x_dt, double t)
+{
+	double mforce = 0;
+	if (active)
+	{
+		double modulator;
+
+				// the internal force contribute = iforce
+		if (modul_iforce) { modulator = modul_iforce->Get_y(t);}
+		else { modulator = 1;}
+		mforce=  iforce * modulator;
+
+				// the stiffness contribute =  - K x
+		if (modul_K) { modulator = modul_K->Get_y(x);}
+		else { modulator = 1;}
+		mforce -= (K * modulator) * x;
+
+				// the damping contribute =  - R x_dt
+		if (modul_R) { modulator = modul_R->Get_y(x);}
+		else { modulator = 1;}
+		mforce -= (R * modulator) * x_dt;
+	}
+
+	return  mforce;
+}
+
+} // END_OF_NAMESPACE____
+
+
+///////////////////
diff --git a/SRC/ChronoEngine/physics/ChLinkforce.h b/SRC/ChronoEngine/physics/ChLinkforce.h
new file mode 100644
index 0000000..216af08
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinkforce.h
@@ -0,0 +1,113 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKFORCE_H
+#define CHLINKFORCE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChLinkForce.h
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+#include <float.h>
+
+#include "core/ChMath.h"
+#include "physics/ChFunction.h"
+
+
+namespace chrono 
+{
+
+
+///
+/// Class for forces in link joints of type ChLink().
+///
+
+class ChApi ChLinkForce
+{
+private:
+	int active;		// true/false
+
+	double iforce;		// impressed force
+	ChFunction* modul_iforce;	// time-modulation of imp. force
+
+	double K;			// stiffness of the dof
+	ChFunction* modul_K;  // modulation of K along the dof coord
+
+	double R;			// damping of the dof
+	ChFunction* modul_R;  // modulation of R along the dof coord
+
+
+public:
+	ChLinkForce();
+	~ChLinkForce();
+	void Copy(ChLinkForce* source);
+	ChLinkForce* new_Duplicate();
+
+	int Get_active () {return active;}
+	void Set_active (int m_a) {active = m_a;}
+
+	double Get_iforce () {return iforce;}
+	void Set_iforce (double m_f) {iforce = m_f;}
+
+	double Get_K () {return K;}
+	void Set_K (double m_K) {K = m_K;}
+
+	double Get_R () {return R;}
+	void Set_R (double m_R) {R = m_R;}
+
+	ChFunction* Get_modul_iforce() {return modul_iforce;};
+	ChFunction* Get_modul_K() {return modul_K;};
+	ChFunction* Get_modul_R() {return modul_R;};
+
+	void Set_modul_iforce(ChFunction* m_funct);
+	void Set_modul_K		(ChFunction* m_funct);
+	void Set_modul_R		(ChFunction* m_funct);
+
+	double Get_Kcurrent (double x, double x_dt, double t);
+	double Get_Rcurrent (double x, double x_dt, double t);
+	double Get_iFcurrent (double x, double x_dt, double t);	
+
+	// this is the most important function: it is called to evaluate
+	// the internal force at instant t, position x and speed x_dt
+	double Get_Force (double x, double x_dt, double t);	
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream);
+
+
+};
+
+
+} // END_OF_NAMESPACE____
+
+#endif
+
diff --git a/SRC/ChronoEngine/physics/ChLinksAll.h b/SRC/ChronoEngine/physics/ChLinksAll.h
new file mode 100644
index 0000000..66212f5
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChLinksAll.h
@@ -0,0 +1,52 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHLINKSALL_H
+#define CHLINKSALL_H
+
+//////////////////////////////////////////////////
+//  
+//   ChLinksAll.h
+//
+//   Shortcut to include most headers related to
+//   links (joints in 3d space) with a single include..
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+// This header is just a trick to include quickly the 
+// following headers, all at once with a single #include "physics/ChLinksAll.h" statement
+
+#include "physics/ChLink.h"
+#include "physics/ChLinkLock.h"
+#include "physics/ChLinkSpring.h"
+#include "physics/ChLinkLinActuator.h"
+#include "physics/ChLinkPneumaticActuator.h"
+#include "physics/ChLinkEngine.h"
+#include "physics/ChLinkScrew.h"
+#include "physics/ChLinkGear.h"
+#include "physics/ChLinkPulley.h"
+#include "physics/ChLinkDistance.h"
+#include "physics/ChLinkBrake.h"
+#include "physics/ChLinkWheel.h"
+#include "physics/ChLinkClearance.h"
+#include "physics/ChLinkPointSpline.h"
+//#include "physics/ChLinkPointSurf.h"
+#include "physics/ChLinkTrajectory.h"
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChMarker.cpp b/SRC/ChronoEngine/physics/ChMarker.cpp
new file mode 100644
index 0000000..473fc0d
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChMarker.cpp
@@ -0,0 +1,485 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChMarker.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+ 
+
+#include "core/ChTrasform.h"
+#include "physics/ChMarker.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChBody.h"
+#include "physics/ChExternalObject.h"
+ 
+
+
+namespace chrono
+{
+
+#define MARKER_BDF_STEP 0.0001
+
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+// CLASS FOR MARKERS
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChMarker> a_registration_ChMarker;
+
+
+ChMarker::ChMarker()
+{
+	Body = NULL;
+
+	motion_X =   new ChFunction_Const (0);  // default: no motion
+	motion_Y =   new ChFunction_Const (0);
+	motion_Z =   new ChFunction_Const (0);
+	motion_ang = new ChFunction_Const (0);
+	motion_axis = VECT_Z;
+
+	rest_coord=	CSYSNORM;
+
+	motion_type = M_MOTION_FUNCTIONS;
+
+	last_rel_coord     = CSYSNORM;
+	last_rel_coord_dt  = CSYSNULL;
+	last_time = 0;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	UpdateState();
+}
+
+ChMarker::ChMarker (char myname[], ChBody* myBody, Coordsys myrel_pos, Coordsys myrel_pos_dt, Coordsys myrel_pos_dtdt)
+{
+	SetName (myname);
+	Body = myBody;
+
+	motion_X =   new ChFunction_Const (0);  // default: no motion
+	motion_Y =   new ChFunction_Const (0);
+	motion_Z =   new ChFunction_Const (0);
+	motion_ang = new ChFunction_Const (0);
+	motion_axis = VECT_Z;
+
+	rest_coord=	CSYSNORM;
+
+	motion_type = M_MOTION_FUNCTIONS;
+
+	SetCoord (myrel_pos);
+	SetCoord_dt (myrel_pos_dt);
+	SetCoord_dtdt (myrel_pos_dtdt);
+
+	last_rel_coord     = CSYSNORM;
+	last_rel_coord_dt  = CSYSNULL;
+	last_time = 0;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	UpdateState();
+};
+
+ChMarker::~ChMarker ()
+{
+	if (motion_X) delete motion_X;
+	if (motion_Y) delete motion_Y;
+	if (motion_Z) delete motion_Z;
+	if (motion_ang) delete motion_ang;
+}
+
+void ChMarker::Copy(ChMarker* source)
+{
+	// first copy the parent class data...
+	ChObj::Copy(source);
+
+	// first copy the parent class data...
+	ChFrameMoving<double>::operator=(*source);
+
+
+	Body = NULL;
+
+		// Replace the default functions.
+	if (motion_X) delete motion_X;
+	if (motion_Y) delete motion_Y;
+	if (motion_Z) delete motion_Z;
+	if (motion_ang) delete motion_ang;
+	motion_X =   source->motion_X->new_Duplicate();
+	motion_Y =   source->motion_Y->new_Duplicate();
+	motion_Z =   source->motion_Z->new_Duplicate();
+	motion_ang = source->motion_ang->new_Duplicate();
+	motion_axis= source->motion_axis;
+
+	rest_coord =		source->rest_coord;
+
+	motion_type =	source->motion_type;
+
+	abs_frame =		source->abs_frame;
+
+	last_rel_coord    = source->last_rel_coord;
+	last_rel_coord_dt = source->last_rel_coord_dt;
+	last_time		= source->last_time;
+}
+
+
+// setup the functions when user changes them.
+
+void ChMarker::SetMotion_X	(ChFunction* m_funct)
+{
+	if (motion_X) delete motion_X;
+	motion_X = m_funct;
+}
+
+void ChMarker::SetMotion_Y	(ChFunction* m_funct)
+{
+	if (motion_Y) delete motion_Y;
+	motion_Y = m_funct;
+}
+
+void ChMarker::SetMotion_Z	(ChFunction* m_funct)
+{
+	if (motion_Z) delete motion_Z;
+	motion_Z = m_funct;
+}
+
+void ChMarker::SetMotion_ang	(ChFunction* m_funct)
+{
+	if (motion_ang) delete motion_ang;
+	motion_ang = m_funct;
+}
+
+void ChMarker::SetMotion_axis (Vector m_axis)
+{
+	motion_axis = m_axis;
+}
+
+
+
+
+// Coordinate setting, for user access
+
+void ChMarker::Impose_Rel_Coord (Coordsys m_coord)
+{
+	Quaternion qtemp;
+				// set the actual coordinates
+	SetCoord(m_coord);
+				// set the resting position coordinates
+	rest_coord.pos.x = m_coord.pos.x - motion_X->Get_y(ChTime);
+	rest_coord.pos.y = m_coord.pos.y - motion_Y->Get_y(ChTime);
+	rest_coord.pos.z = m_coord.pos.z - motion_Z->Get_y(ChTime);
+	qtemp = Q_from_AngAxis (-(motion_ang->Get_y(ChTime)), motion_axis);
+	rest_coord.rot = Qcross (m_coord.rot, qtemp);  // ***%%% check
+				// set also the absolute positions, and other.
+	UpdateState () ;
+}
+
+void ChMarker::Impose_Abs_Coord (Coordsys m_coord)
+{
+	ChBody* my_body;
+	my_body = GetBody();
+
+	Coordsys csys;
+			// trasform coordsys to local coordsys...
+	csys.pos= ChTrasform<>::TrasformParentToLocal (m_coord.pos, my_body->GetCoord().pos, *my_body->GetA());
+	csys.rot= Qcross (Qconjugate (my_body->GetCoord().rot), m_coord.rot);
+			// apply the imposition on local  coordinate and resting coordinate:
+	Impose_Rel_Coord (csys);
+}
+
+
+
+
+//// Utilities for coordinate transformations
+///
+
+Vector ChMarker::Point_World2Ref (Vector* mpoint)
+{
+	return abs_frame / *mpoint;
+}
+
+Vector ChMarker::Point_Ref2World (Vector* mpoint)
+{
+	return *(ChFrame<double>*)&abs_frame * *mpoint;
+}
+
+Vector ChMarker::Dir_World2Ref (Vector* mpoint)
+{
+	return abs_frame.GetA()->MatrT_x_Vect (*mpoint);
+}
+
+Vector ChMarker::Dir_Ref2World (Vector* mpoint)
+{
+	return abs_frame.GetA()->Matr_x_Vect (*mpoint);
+}
+
+
+
+
+// This handles the time-varying functions for the relative
+// coordinates
+
+void ChMarker::UpdateTime (double mytime)
+{
+	static Coordsys csys, csys_dt, csys_dtdt;
+	static Quaternion qtemp;
+	double ang, ang_dt, ang_dtdt;
+
+	ChTime = mytime;
+
+	// if a imposed motion (keyframed movement) affects the marker postion (example,from R3D animation system),
+	// compute the speed and acceleration values by BDF (example,see the UpdatedExternalTime() function, later)
+	// so the updating via motion laws can be skipped!
+	if (this->motion_type == M_MOTION_KEYFRAMED) return;
+
+	// skip realtive-position-functions evaluation also if
+	// someone is already handling this from outside..
+  	if (this->motion_type == M_MOTION_EXTERNAL) return;  // >>>>
+
+
+	// positions:
+		// update positions:    rel_pos
+	csys.pos.x= motion_X->Get_y(mytime);
+	csys.pos.y= motion_Y->Get_y(mytime);
+	csys.pos.z= motion_Z->Get_y(mytime);
+	if (motion_X->Get_Type() != FUNCT_MOCAP)
+		csys.pos = Vadd(csys.pos, rest_coord.pos);
+
+		// update speeds:		rel_pos_dt
+	csys_dt.pos.x= motion_X->Get_y_dx(mytime);
+	csys_dt.pos.y= motion_Y->Get_y_dx(mytime);
+	csys_dt.pos.z= motion_Z->Get_y_dx(mytime);
+
+		// update accelerations
+	csys_dtdt.pos.x= motion_X->Get_y_dxdx(mytime);
+	csys_dtdt.pos.y= motion_Y->Get_y_dxdx(mytime);
+	csys_dtdt.pos.z= motion_Z->Get_y_dxdx(mytime);
+
+
+	// rotations:
+
+	ang		= motion_ang->Get_y(mytime);
+	ang_dt	= motion_ang->Get_y_dx(mytime);
+	ang_dtdt= motion_ang->Get_y_dxdx(mytime);
+
+	if ((ang !=0)||(ang_dt !=0)||(ang_dtdt !=0))
+	{
+		// update q
+		Vector motion_axis_versor = Vnorm(motion_axis);
+		qtemp = Q_from_AngAxis (ang, motion_axis_versor);
+		csys.rot = Qcross (qtemp, rest_coord.rot);
+		// update q_dt
+		csys_dt.rot = chrono::Qdt_from_AngAxis (csys.rot, ang_dt, motion_axis_versor);
+		// update q_dtdt
+		csys_dtdt.rot = chrono::Qdtdt_from_AngAxis (ang_dtdt, motion_axis_versor, csys.rot, csys_dt.rot);
+	}
+	else
+	{
+		csys.rot = this->coord.rot; //rel_pos.rot;
+		csys_dt.rot = QNULL;
+		csys_dtdt.rot = QNULL;
+	}
+
+
+	// Set the position, speed and acceleration in relative space,
+	// automatically getting also the absolute values,
+	if (!(csys==this->coord))
+			SetCoord (csys);
+
+	if (!(csys_dt==this->coord_dt) || !(csys_dt.rot==QNULL))
+			SetCoord_dt (csys_dt);
+
+	if (!(csys_dtdt==this->coord_dtdt) || !(csys_dtdt.rot==QNULL))
+			SetCoord_dtdt (csys_dtdt);
+};
+
+
+
+void ChMarker::UpdateState ()
+{
+	if (!GetBody()) return;
+
+	GetBody()->TrasformLocalToParent(*this, abs_frame);
+};
+
+
+void ChMarker::Update (double mytime)
+{
+	UpdateTime (mytime);
+	UpdateState ();
+}
+
+
+
+
+void ChMarker::UpdateExternalGeometry ()
+{
+	// tell the R3 object to move itself where needed
+	if (GetExternalObject())
+		GetExternalObject()->onChronoChanged();
+}
+
+void ChMarker::UpdatedExternalTime (double prevtime, double mtime)
+{
+	double mstep = mtime-prevtime;
+
+	Coordsys m_rel_pos_dt;
+	Coordsys m_rel_pos_dtdt;
+
+	// do not try to switch on the M_MOTION_KEYFRAMED mode if
+	// we are already in the M_MOTION_EXTERNAL mode, maybe because
+	// a link point-surface is already moving the marker and
+	// it will handle the accelerations by itself
+	if (this->motion_type == M_MOTION_EXTERNAL) return; // >>>>
+
+
+	// otherwise see if a BDF is needed, cause an external 3rd party is moving the marker
+	this->motion_type = M_MOTION_FUNCTIONS;
+
+	if (  (!(Vequal(&coord.pos, &last_rel_coord.pos))||
+		   !(Qequal(&coord.rot, &last_rel_coord.rot)) )
+	     && (fabs(mstep) < 0.1)
+	     && (mstep != 0)
+	   ) // if POSITION or ROTATION ("rel_pos") has been changed in acceptable time step,.
+	{
+		if ((motion_X->Get_y(mtime)==0)
+		 && (motion_Y->Get_y(mtime)==0)
+		 && (motion_Z->Get_y(mtime)==0)
+		 && (motion_ang->Get_y(mtime)==0)
+		 && (motion_X->Get_Type() == FUNCT_CONST)
+		 && (motion_Y->Get_Type() == FUNCT_CONST)
+		 && (motion_Z->Get_Type() == FUNCT_CONST)
+		 && (motion_ang->Get_Type() == FUNCT_CONST)
+		 )	// .. and if motion wasn't caused by motion laws, then it was a keyframed movement!
+		{
+			// compute the relative speed by BDF !
+			m_rel_pos_dt.pos = Vmul   ( Vsub (coord.pos, last_rel_coord.pos), 1/mstep);
+			m_rel_pos_dt.rot = Qscale ( Qsub (coord.rot, last_rel_coord.rot), 1/mstep);
+
+			// compute the relative acceleration by BDF !
+			m_rel_pos_dtdt.pos = Vmul   ( Vsub (m_rel_pos_dt.pos, last_rel_coord_dt.pos), 1/mstep);
+			m_rel_pos_dtdt.rot = Qscale ( Qsub (m_rel_pos_dt.rot, last_rel_coord_dt.rot), 1/mstep);
+
+			// Set the position, speed and acceleration in relative space,
+			// automatically getting also the absolute values,
+			SetCoord_dt (m_rel_pos_dt);
+			SetCoord_dtdt (m_rel_pos_dtdt);
+
+			// update the remaining state variables
+			this->UpdateState();
+
+			// remember that the movement of this guy won't need further update
+			// of speed and acc. via motion laws!
+			this->motion_type = M_MOTION_KEYFRAMED;
+		}
+	}
+
+	// restore state buffers and that's all.
+	last_time		  = ChTime;
+	last_rel_coord    = coord;
+	last_rel_coord_dt = coord_dt;
+}
+
+
+
+
+
+////////////////  FILE I/O
+
+
+
+void ChMarker::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(2);
+
+		// serialize parent class too
+	ChObj::StreamOUT(mstream);
+
+		// deserialize parent class too
+	ChFrameMoving<double>::StreamOUT(mstream);
+
+		// stream out all member data
+
+	mstream << abs_frame;
+    mstream << rest_coord;
+	mstream << (int)motion_type;
+	mstream.AbstractWrite(GetMotion_X());
+	mstream.AbstractWrite(GetMotion_Y());
+	mstream.AbstractWrite(GetMotion_Z());
+	mstream.AbstractWrite(GetMotion_ang());
+	mstream << motion_axis;
+}
+
+void ChMarker::StreamIN(ChStreamInBinary& mstream)
+{
+	Coordsys cfoo;
+	ChFunction* ffoo;
+	Vector vfoo;
+	int menum;
+
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChObj::StreamIN(mstream);
+
+		// stream in all member data
+	if(version==1)
+	{
+		mstream >> cfoo;		SetCoord(cfoo);
+		mstream >> cfoo;		SetCoord_dt(cfoo);
+		mstream >> cfoo;		SetCoord_dtdt(cfoo);
+		mstream >> cfoo;		SetAbsCoord(cfoo);
+		mstream >> cfoo;		SetAbsCoord_dt(cfoo);
+		mstream >> cfoo;		SetAbsCoord_dtdt(cfoo);
+		mstream >> cfoo;		//SetRestCoord(cfoo); not needed?
+	}
+	if(version >1)
+	{
+			// deserialize parent class too
+		ChFrameMoving<double>::StreamIN(mstream);
+
+		mstream >> abs_frame;
+		mstream >> rest_coord;
+		mstream >> menum;		SetMotionType((eChMarkerMotion)menum);
+	}
+
+	mstream.AbstractReadCreate(&ffoo);	SetMotion_X(ffoo);
+	mstream.AbstractReadCreate(&ffoo);	SetMotion_Y(ffoo);
+	mstream.AbstractReadCreate(&ffoo);	SetMotion_Z(ffoo);
+	mstream.AbstractReadCreate(&ffoo);	SetMotion_ang(ffoo);
+	mstream >> motion_axis;
+}
+
+void ChMarker::StreamOUT(ChStreamOutAscii& mstream)
+{
+	//***TO DO***
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+////////// end
diff --git a/SRC/ChronoEngine/physics/ChMarker.h b/SRC/ChronoEngine/physics/ChMarker.h
new file mode 100644
index 0000000..b8c109f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChMarker.h
@@ -0,0 +1,323 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHMARKER_H
+#define CHMARKER_H
+
+//////////////////////////////////////////////////
+//
+//   ChMarker.h
+//
+//   "Marker" definition (an auxiliary frame, to be
+//   attached to rigid bodies).
+//   Each body needs markers to define links
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include <iostream>
+
+#include "core/ChLog.h"
+#include "core/ChMath.h"
+#include "core/ChFrameMoving.h"
+
+#include "physics/ChFunction.h"
+#include "physics/ChObject.h"
+
+
+
+
+namespace chrono
+{
+
+
+// Forward reference
+class ChBody;
+
+
+#define CHCLASS_MARKER 5
+
+///
+/// Class for 'markers'.
+///
+///  Markers are auxiliary reference frames which belong to
+/// rigid bodies ChBody() , and move together with them.
+/// Most often, markers are used as references to build
+/// ChLink() constraints between two rigid bodies.
+///  The ChMarker objects allow also to user-define a
+/// motion law of marker respect to parent ChBody, if
+/// needed to represent imposed trajectories etc.
+
+class ChApi ChMarker : public ChObj, public ChFrameMoving<double>  {
+
+							// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChMarker,ChObj);
+
+
+				//
+	  			// DATA
+				//
+
+
+public:
+	enum eChMarkerMotion {
+							/// Uses it's own  x,y,z,angle ch functions (default)
+		M_MOTION_FUNCTIONS =0,
+							/// The marker is moved via external functions, for examples
+							/// Real3d keyframing, so backward dirrerentiation will be used
+							/// to guess derivatives.
+		M_MOTION_KEYFRAMED =1,
+							/// Someone (i.e. a constraint object) is moving the marker and
+							/// will also provide the correct derivatives.
+		M_MOTION_EXTERNAL  =2,
+	};
+
+private:
+							/// The way the motion of this marker (if any) is handled.
+ 	eChMarkerMotion motion_type;
+
+	ChFunction* motion_X;	// user imposed motion for X coord, body relative
+	ChFunction* motion_Y;	// user imposed motion for Y coord, body relative
+	ChFunction* motion_Z;	// user imposed motion for Z coord, body relative
+	ChFunction* motion_ang;	// user imposed angle rotation about axis
+	Vector		motion_axis;// this is the axis for the user imposed rotation
+
+
+	ChBody* Body;			// points to parent body
+
+	Coordsys rest_coord;	// relative resting position for the
+							// coordsys, for function=0.
+
+	Coordsys last_rel_coord;	// These values are set for each marker update, and are
+	Coordsys last_rel_coord_dt;	// used internally to guess if there's some external routine
+	double last_time;			// which moves the marker, so marker motion is guessed by BDF.
+
+
+						// Auxiliary variables, computed after Updating functions..
+
+							/// Absolute position of frame (frame translation and rotation
+							/// expressed in absolute coordinate system).
+							/// This is computed at each Update() call. Useful for high
+							/// performance reasons.
+	ChFrameMoving<double> abs_frame;
+
+
+public:
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChMarker ();
+
+	ChMarker (char myname[], ChBody* myBody, Coordsys myrel_pos, Coordsys myrel_pos_dt, Coordsys myrel_pos_dtdt);
+
+	~ChMarker ();
+
+	void Copy(ChMarker* source);
+
+
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Gets the address of the parent rigid body.
+	ChBody* GetBody () { return Body;}
+				/// Sets the parent rigid body.
+	void SetBody (ChBody* newRB) {Body= newRB;}
+
+
+
+				/// Set body-relative coord. and update auxiliary variables
+				/// Also, current position becomes the 'resting position' coordinates
+				/// for the current time.
+	void Impose_Rel_Coord (Coordsys m_coord);
+
+				/// Set absolute coordinates  and update auxiliary variables
+				/// Also, current position becomes the 'resting position' coordinates
+				/// for the current time.
+	void Impose_Abs_Coord (Coordsys m_coord);
+
+
+				/// Get the 'resting position' (that is, the position which the
+				/// marker should have when the x,y,z motion laws are at time=0).
+	Coordsys GetRest_Coord() {return rest_coord;}
+
+
+			//
+			// Body-relative coordinates
+			//
+
+				// No functions here...
+				//  In order to get/set  body-relative coordinates,
+				// you can use the methods of the ChFrameMoving parent
+				// class: for example use  my_marker->SetCoord(newpos) to
+				// impose a new position&rotation, etc.
+				//  NOTE!! after each modification of the frame position,
+				// speed, acceleration etc., you should remember to call UpdateState()
+				// if you want to kee updated also the absolute coordinates , ie. the
+				// auxiliary structure to get with GetAbsFrame().
+
+
+
+			//
+			// Absolute coordinates (auxiliary data)
+			//
+
+				/// Get reference to the inner 'absolute frame' auxiliary
+				/// coordinates. This object (coordinates/speeds/accel. of marker
+				/// expressed in absolute coordinates) is useful for performace
+				/// reasons. Note! it is updated only after each Update() function.
+	ChFrameMoving<double>& GetAbsFrame () { return abs_frame; }
+
+				/// Get the translation and rotation (as a ChCoordsys) of the marker
+				/// respect to the absolute coordinates.
+	Coordsys GetAbsCoord () { return abs_frame.GetCoord(); }
+				/// Get the speed of translation and rotation (as a derived ChCoordsys)
+				/// of the marker respect to the absolute coordinates.
+	Coordsys GetAbsCoord_dt () { return abs_frame.GetCoord_dt(); }
+				/// Get the acceleration of translation and rotation (as a derived ChCoordsys)
+				/// of the marker respect to the absolute coordinates.
+	Coordsys GetAbsCoord_dtdt () { return abs_frame.GetCoord_dtdt(); }
+
+				/// Set the translation and rotation (as a ChCoordsys) of the marker
+				/// respect to the absolute coordinates.
+				/// NOTE! inner use only, for the moment. Use  Impose_Abs_Coord() if needed.
+	void SetAbsCoord (Coordsys newpos) {abs_frame.SetCoord(newpos);}
+				/// Set the speed of translation and rotation (as a ChCoordsys) of the marker
+				/// respect to the absolute coordinates.
+				/// NOTE! inner use only, for the moment.
+	void SetAbsCoord_dt (Coordsys newpos_dt) {abs_frame.SetCoord(newpos_dt);}
+				/// Set the speed of translation and rotation (as a ChCoordsys) of the marker
+				/// respect to the absolute coordinates.
+				/// NOTE! inner use only, for the moment.
+	void SetAbsCoord_dtdt (Coordsys newpos_dtdt) {abs_frame.SetCoord(newpos_dtdt);}
+
+				/// Get the angular speed respect to absolute coordinates,
+				/// expressed in  absolute coordinates.
+	Vector  GetAbsWvel () {return abs_frame.GetWvel_par();}
+
+				/// Get the angular acceleration respect to absolute coordinates,
+				/// expressed in  absolute coordinates.
+	Vector  GetAbsWacc () {return abs_frame.GetWacc_par();}
+
+
+
+			//
+			// Imposed motion
+			//
+
+				/// Set the imposed motion law, for translation on X body axis
+	void SetMotion_X	(ChFunction* m_funct);
+				/// Set the imposed motion law, for translation on Y body axis
+	void SetMotion_Y	(ChFunction* m_funct);
+				/// Set the imposed motion law, for translation on Z body axis
+	void SetMotion_Z	(ChFunction* m_funct);
+				/// Set the imposed motion law, for rotation about an axis
+	void SetMotion_ang	(ChFunction* m_funct);
+				/// Set the axis of rotation, if rotation motion law is used.
+	void SetMotion_axis (Vector m_axis);
+
+				/// The imposed motion law, for translation on X body axis
+	ChFunction* GetMotion_X() {return motion_X;};
+				/// The imposed motion law, for translation on Y body axis
+	ChFunction* GetMotion_Y() {return motion_Y;};
+				/// The imposed motion law, for translation on Z body axis
+	ChFunction* GetMotion_Z() {return motion_Z;};
+				/// The imposed motion law, for rotation about an axis
+	ChFunction* GetMotion_ang() {return motion_ang;};
+				/// Get the axis of rotation, if rotation motion law is used.
+	Vector GetMotion_axis() {return motion_axis;};
+
+
+				/// Sets the way the motion of this marker (if any) is handled (see
+				/// the eChMarkerMotion enum options).
+	void SetMotionType (eChMarkerMotion m_motion) {motion_type = m_motion;};
+
+				/// Gets the way the motion of this marker (if any) is handled (see
+				/// the eChMarkerMotion enum options).
+	eChMarkerMotion GetMotionType () {return motion_type;}
+
+
+
+
+			//
+			// UPDATING
+			//
+
+				/// Updates the time.dependant variables (ex: ChFunction objects
+				/// which impose the body-relative motion, etc.)
+	void UpdateTime (double mytime);
+
+				/// Given current state, updates auxiliary variables (for example
+				/// the abs_frame data, containing the absolute pos/speed/acc of
+				/// the marker.
+	void UpdateState ();
+
+				/// Both UpdateTime() and UpdateState() at once.
+	void Update (double mytime);
+
+
+					/// Tells to the associated external object ChExternalObject() ,if any,
+					/// that its 3D shape must be updated in order to syncronize to marker
+					/// coordinates
+	void UpdateExternalGeometry ();
+
+					/// Someone (ex. an ChExternalObject() ) may send this message to
+					/// the marker to tell that time has changed (even if simulation is
+					/// not running! - so it is different from the usual UpdateTime() -)
+	void UpdatedExternalTime (double prevtime, double mtime);
+
+			//
+			// UTILITIES
+			//
+
+	Vector Point_World2Ref (Vector* mpoint);
+	Vector Point_Ref2World (Vector* mpoint);
+	Vector Dir_World2Ref (Vector* mpoint);
+	Vector Dir_Ref2World (Vector* mpoint);
+
+
+			//
+			// STREAMING
+			//
+
+				/// Method to allow serialization of transient data in ascii,
+				/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream);
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChMaterialCouple.h b/SRC/ChronoEngine/physics/ChMaterialCouple.h
new file mode 100644
index 0000000..b8b1777
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChMaterialCouple.h
@@ -0,0 +1,70 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHMATERIALCOUPLE_H
+#define CHMATERIALCOUPLE_H
+
+///////////////////////////////////////////////////
+//
+//   ChMaterialCouple.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+namespace chrono
+{
+
+/// Class to pass data about material properties of a contact pair.
+/// Used by ChAddContactCallback for generating cutom combinations
+/// of material properties (by default, friction & c. are average
+/// of values of the two parts in contact)
+
+class ChApi ChMaterialCouple
+{
+public:
+	float  static_friction;	
+	float  sliding_friction;	
+	float  rolling_friction;	
+	float  spinning_friction;			
+	float  restitution;	
+	float  cohesion;
+	float  dampingf;
+	float  compliance;
+	float  complianceT;
+	float  complianceRoll;
+	float  complianceSpin;
+
+	ChMaterialCouple() :static_friction(0),
+						sliding_friction(0),
+						rolling_friction(0),
+						spinning_friction(0),
+						restitution(0),
+						cohesion(0),
+						dampingf(0),
+						compliance(0),
+						complianceT(0),
+						complianceRoll(0),
+						complianceSpin(0)
+						{};
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChMaterialSurface.h b/SRC/ChronoEngine/physics/ChMaterialSurface.h
new file mode 100644
index 0000000..25ddf35
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChMaterialSurface.h
@@ -0,0 +1,242 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2011-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHMATERIALSURFACE_H
+#define CHMATERIALSURFACE_H
+
+///////////////////////////////////////////////////
+//
+//   ChMaterialSurface.h
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "core/ChShared.h"
+
+
+namespace chrono
+{
+
+/// Material data for a surface: friction, compliance, etc.
+/// This data is used to define surface properties owned by 
+/// ChBody rigid bodies and similar things; it carries information
+/// that is used to make contacts.
+
+class ChApi ChMaterialSurface : public ChShared
+{
+public:
+
+			//
+			// DATA
+			//
+
+	float  static_friction;	
+	float  sliding_friction;	
+	float  rolling_friction;	
+	float  spinning_friction;			
+	float  restitution;	
+	float  cohesion;
+	float  dampingf;
+	float  compliance;
+	float  complianceT;
+	float  complianceRoll;
+	float  complianceSpin;
+
+
+			//
+			// CONSTRUCTORS
+			//
+
+	ChMaterialSurface() :static_friction(0.6f),
+						sliding_friction(0.6f),
+						rolling_friction(0),
+						spinning_friction(0),
+						restitution(0),
+						cohesion(0),
+						dampingf(0),
+						compliance(0),
+						complianceT(0),
+						complianceRoll(0),
+						complianceSpin(0)
+					{
+					};
+
+	~ChMaterialSurface() 
+					{
+					};
+
+						// Copy constructor 
+	ChMaterialSurface(const ChMaterialSurface& other) 
+					{ 
+						static_friction=other.static_friction;
+						sliding_friction=other.sliding_friction;
+						rolling_friction=other.rolling_friction;
+						spinning_friction=other.spinning_friction;
+						restitution=other.restitution;
+						cohesion=other.cohesion;
+						dampingf=other.dampingf;
+						compliance=other.compliance;
+						complianceT=other.complianceT;
+						complianceRoll=other.complianceRoll;
+						complianceSpin=other.complianceSpin;
+					}
+
+			//
+			// FUNCTIONS
+			//
+
+				/// The static friction coefficient. 
+				/// Usually in 0..1 range, rarely above.
+				/// Default 0.6
+	float  GetSfriction() {return static_friction;}
+	void   SetSfriction(float mval) {static_friction = mval;}
+
+				/// The sliding ('kinetic')friction coefficient. Default 0.6
+				/// Usually in 0..1 range, rarely above. 
+				/// Note: currently the static friction will be used instead, anyway, because of an issue in the solver.
+	float  GetKfriction() {return sliding_friction;}
+	void   SetKfriction(float mval) {sliding_friction = mval;}
+
+				/// Set both static friction and kinetic friction at once, with same value.
+	void   SetFriction(float mval) {SetSfriction(mval); SetKfriction(mval);}
+
+				/// The rolling friction (rolling parameter, it has the dimension of a length). 
+				/// Rolling resistant torque is Tr <= (normal force) * (this parameter)
+				/// Usually a very low value. Measuring unit: m
+				/// Default =0.
+				/// Note! a non-zero value will make the simulation 2x slower! Also, the
+				/// GPU solver currently does not support rolling friction. Default: 0.
+	float  GetRollingFriction() {return rolling_friction;}
+	void   SetRollingFriction(float mval) {rolling_friction = mval;}
+
+				/// The spinning friction (it has the dimension of a length). 
+				/// Spinning resistant torque is Ts <= (normal force) * (this parameter)
+				/// Usually a very low value.  Measuring unit: m
+				/// Default =0.
+				/// Note! a non-zero value will make the simulation 2x slower! Also, the
+				/// GPU solver currently does not support spinning friction. Default: 0.
+	float  GetSpinningFriction() {return spinning_friction;}
+	void   SetSpinningFriction(float mval) {spinning_friction = mval;}
+
+				/// The normal restitution coefficient, for collisions.
+				/// Should be in 0..1 range. Default =0.
+	float  GetRestitution() {return restitution;}
+	void   SetRestitution(float mval) {restitution = mval;}
+
+				/// The cohesion max. force for normal pulling traction in 
+				/// contacts. Measuring unit: N
+				/// Default =0.
+	float  GetCohesion() {return cohesion;}
+	void   SetCohesion(float mval) {cohesion = mval;}
+
+				/// The damping in contact, as a factor 'f': damping is a 
+				/// multiple of stiffness [K], that is: [R]=f*[K] 
+				/// Measuring unit: time, s. Default =0.
+	float  GetDampingF() {return dampingf;}
+	void   SetDampingF(float mval) {dampingf = mval;}
+
+				/// Compliance of the contact, in normal direction.
+				/// It is the inverse of the stiffness [K] , so for zero
+				/// value one has a perfectly rigid contact.
+				/// Measuring unit: m/N  
+				/// Default =0.
+	float  GetCompliance() {return compliance;}
+	void   SetCompliance(float mval) {compliance = mval;}
+
+				/// Compliance of the contact, in tangential direction.
+				/// Measuring unit: m/N
+				/// Default =0.
+	float  GetComplianceT() {return complianceT;}
+	void   SetComplianceT(float mval) {complianceT = mval;}
+
+				/// Rolling compliance of the contact, if using a nonzero rolling friction.
+				/// (If there is no rolling friction, this has no effect.)
+				/// Measuring unit: rad/Nm
+				/// Default =0.
+	float  GetComplianceRolling() {return complianceRoll;}
+	void   SetComplianceRolling(float mval) {complianceRoll = mval;}
+				
+				/// Spinning compliance of the contact, if using a nonzero rolling friction.
+				/// (If there is no spinning friction, this has no effect.)
+				/// Measuring unit: rad/Nm
+				/// Default =0.
+	float  GetComplianceSpinning() {return complianceSpin;}
+	void   SetComplianceSpinning(float mval) {complianceSpin = mval;}
+
+
+			//
+			// STREAMING
+			//
+					/// Method to allow serializing transient data into in ascii
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii& mstream)
+						{
+							mstream << "Material \n";
+						}
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream)
+						{
+							// class version number
+							mstream.VersionWrite(1);
+
+							// deserialize parent class too
+							//ChShared::StreamOUT(mstream); // nothing 
+
+							// stream out all member data
+							mstream <<   static_friction;	
+							mstream <<   sliding_friction;	
+							mstream <<   rolling_friction;	
+							mstream <<   spinning_friction;			
+							mstream <<   restitution;	
+							mstream <<   cohesion;
+							mstream <<   dampingf;
+							mstream <<   compliance;
+							mstream <<   complianceT;
+							mstream <<   complianceRoll;
+							mstream <<   complianceSpin;
+						}
+
+					/// Operator to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream)
+						{
+
+							// deserialize parent class too
+							//ChShared::StreamIN(mstream); // nothing 
+
+							// stream in all member data
+							mstream >>   static_friction;	
+							mstream >>   sliding_friction;	
+							mstream >>   rolling_friction;	
+							mstream >>   spinning_friction;			
+							mstream >>   restitution;	
+							mstream >>   cohesion;
+							mstream >>   dampingf;
+							mstream >>   compliance;
+							mstream >>   complianceT;
+							mstream >>   complianceRoll;
+							mstream >>   complianceSpin;
+						}
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChMatterSPH.cpp b/SRC/ChronoEngine/physics/ChMatterSPH.cpp
new file mode 100644
index 0000000..86a42c9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChMatterSPH.cpp
@@ -0,0 +1,617 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChMatterSPH.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "physics/ChMatterSPH.h"
+#include "physics/ChSystem.h"
+
+#include "physics/ChExternalObject.h"
+#include "physics/ChProximityContainerSPH.h"
+#include "collision/ChCModelBulletNode.h"
+#include "core/ChLinearAlgebra.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChMatterSPH> a_registration_ChMatterSPH;
+
+	
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR A SPH NODE
+
+
+ChNodeSPH::ChNodeSPH()
+{
+	this->collision_model = new ChModelBulletNode;
+	
+	this->UserForce = VNULL;
+	this->h_rad = 0.1;
+	this->coll_rad = 0.001;
+	this->SetMass(0.01);
+	this->volume = 0.01;
+	this->density = this->GetMass()/this->volume;
+	this->pressure = 0;
+}
+
+ChNodeSPH::~ChNodeSPH()
+{
+	delete collision_model; 
+}
+
+ChNodeSPH::ChNodeSPH (const ChNodeSPH& other) :
+					ChNodeXYZ(other) 
+{
+	this->collision_model = new ChModelBulletNode;
+	this->collision_model->AddSphere(other.coll_rad); 
+	((ChModelBulletNode*)collision_model)->SetNode(
+		((ChModelBulletNode*)other.collision_model)->GetNodes(),
+		((ChModelBulletNode*)other.collision_model)->GetNodeId());
+
+	this->UserForce = other.UserForce;
+	this->SetKernelRadius(other.h_rad);
+	this->SetCollisionRadius(other.coll_rad);
+	this->SetMass(other.GetMass());
+	this->volume = other.volume;
+	this->density = other.density;
+	this->pressure = other.pressure;
+
+	this->variables = other.variables;
+}
+
+ChNodeSPH& ChNodeSPH::operator= (const ChNodeSPH& other)
+{
+	if (&other == this) 
+		return *this;
+
+	ChNodeXYZ::operator=(other);
+
+	this->collision_model->ClearModel();
+	this->collision_model->AddSphere(other.coll_rad ); 
+	((ChModelBulletNode*)collision_model)->SetNode(
+		((ChModelBulletNode*)other.collision_model)->GetNodes(),
+		((ChModelBulletNode*)other.collision_model)->GetNodeId());
+	
+	this->UserForce = other.UserForce;
+	this->SetKernelRadius(other.h_rad);
+	this->SetCollisionRadius(other.coll_rad);
+	this->SetMass(other.GetMass());
+	this->volume = other.volume;
+	this->density = other.density;
+
+	this->variables = other.variables;
+	
+	return *this;
+}
+
+void ChNodeSPH::SetKernelRadius(double mr)
+{
+	h_rad = mr;
+	double aabb_rad = h_rad/2; // to avoid too many pairs: bounding boxes hemisizes will sum..  __.__--*--
+	((ChModelBulletNode*)this->collision_model)->SetSphereRadius(coll_rad, ChMax(0.0, aabb_rad-coll_rad) );
+}
+	
+void ChNodeSPH::SetCollisionRadius(double mr)
+{
+	coll_rad = mr;
+	double aabb_rad = h_rad/2; // to avoid too many pairs: bounding boxes hemisizes will sum..  __.__--*--
+	((ChModelBulletNode*)this->collision_model)->SetSphereRadius(coll_rad, ChMax(0.0, aabb_rad-coll_rad) );
+}
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SPH MATERIAL
+
+void ChContinuumSPH::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// stream out parent class
+	ChContinuumMaterial::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->viscosity;
+	mstream << this->surface_tension;
+	mstream << this->pressure_stiffness;
+}
+
+void ChContinuumSPH::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// stream in parent class
+	ChContinuumMaterial::StreamIN(mstream);
+
+		// stream in all member data
+	mstream >> this->viscosity;
+	mstream >> this->surface_tension;
+	mstream >> this->pressure_stiffness;
+}
+
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SPH NODE CLUSTER
+
+
+ChMatterSPH::ChMatterSPH ()
+{
+	this->do_collide = false;
+
+	this->nodes.clear();
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+}
+
+
+ChMatterSPH::~ChMatterSPH ()
+{
+	// delete nodes
+	this->ResizeNnodes(0);
+}
+
+
+
+void ChMatterSPH::Copy(ChMatterSPH* source)
+{
+		// copy the parent class data...
+	ChIndexedNodes::Copy(source);
+
+	do_collide = source->do_collide;
+
+	this->material = source->material;
+	
+	ResizeNnodes(source->GetNnodes());
+}
+
+
+
+
+void ChMatterSPH::ResizeNnodes(int newsize)
+{
+	bool oldcoll = this->GetCollide();
+	this->SetCollide(false); // this will remove old particle coll.models from coll.engine, if previously added
+
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		delete (this->nodes[j]);
+		this->nodes[j] = 0;
+	}
+
+	this->nodes.resize(newsize);
+
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->nodes[j] = new ChNodeSPH;
+
+		this->nodes[j]->variables.SetUserData((void*)this); // UserData unuseful in future cuda solver?
+		((ChModelBulletNode*)this->nodes[j]->collision_model)->SetNode(this,j);
+		this->nodes[j]->collision_model->AddSphere(0.001); //***TEST***
+		this->nodes[j]->collision_model->BuildModel();
+	}
+
+	this->SetCollide(oldcoll); // this will also add particle coll.models to coll.engine, if already in a ChSystem
+
+}
+
+
+void ChMatterSPH::AddNode(ChVector<double> initial_state)
+{
+	ChNodeSPH* newp = new ChNodeSPH;
+
+	newp->SetPos(initial_state);
+
+	this->nodes.push_back(newp);
+
+	newp->variables.SetUserData((void*)this);  // UserData unuseful in future cuda solver?
+	((ChModelBulletNode*)newp->collision_model)->SetNode(this,nodes.size()-1);
+	newp->collision_model->AddSphere(0.1); //***TEST***
+	newp->collision_model->BuildModel(); // will also add to system, if collision is on.
+}
+
+
+
+void ChMatterSPH::FillBox (const ChVector<> size,	
+				  const double spacing,		
+				  const double initial_density, 
+				  const ChCoordsys<> boxcoords, 
+				  const bool do_centeredcube,	
+				  const double kernel_sfactor,  
+				  const double randomness
+				  )
+{
+	int samples_x = (int)(size.x/spacing);
+	int samples_y = (int)(size.y/spacing);
+	int samples_z = (int)(size.z/spacing);
+	int totsamples = 0;
+
+	double mrandomness= randomness;
+	if (do_centeredcube)
+		mrandomness = randomness*0.5;
+
+	for (int ix = 0; ix < samples_x; ix++)
+		for (int iy = 0; iy < samples_y; iy++)  
+			for (int iz = 0; iz < samples_z; iz++) 
+			{
+				ChVector<> pos (	ix*spacing  -0.5*size.x, 
+									iy*spacing  -0.5*size.y,	
+									iz*spacing  -0.5*size.z);
+				pos += ChVector<>(mrandomness*ChRandom()*spacing, mrandomness*ChRandom()*spacing, mrandomness*ChRandom()*spacing);
+				this->AddNode(boxcoords.TrasformLocalToParent(pos));
+				totsamples++;
+
+				if (do_centeredcube)
+				{
+					ChVector<> pos2 = pos + 0.5*ChVector<>(spacing,spacing,spacing);
+					pos2 += ChVector<>(mrandomness*ChRandom()*spacing, mrandomness*ChRandom()*spacing, mrandomness*ChRandom()*spacing);
+					this->AddNode(boxcoords.TrasformLocalToParent(pos2));
+					totsamples++;
+				}
+			}
+
+	double mtotvol  = size.x * size.y * size.z;
+	double mtotmass = mtotvol * initial_density;
+	double nodemass = mtotmass/(double)totsamples;
+	double kernelrad = kernel_sfactor*spacing;
+
+	for (unsigned int ip = 0; ip < this->GetNnodes(); ip++)
+	{
+		ChNodeSPH* mnode = (ChNodeSPH*)(this->GetNode(ip));
+		mnode->SetKernelRadius(kernelrad);
+		mnode->SetCollisionRadius(spacing*0.1); 
+		mnode->SetMass(nodemass);
+	}
+
+	this->GetMaterial().Set_density(initial_density);
+}
+
+
+
+//// 
+void ChMatterSPH::InjectVariables(ChLcpSystemDescriptor& mdescriptor)
+{	
+	//this->variables.SetDisabled(!this->IsActive());
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		mdescriptor.InsertVariables(&(this->nodes[j]->variables));
+	}
+}
+
+
+void ChMatterSPH::VariablesFbReset()
+{
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->nodes[j]->variables.Get_fb().FillElem(0.0);
+	}
+}
+
+void ChMatterSPH::VariablesFbLoadForces(double factor)
+{
+
+	// COMPUTE THE SPH FORCES HERE
+
+	// First, find if any ChProximityContainerSPH object is present
+	// in the system,
+
+	ChProximityContainerSPH* edges =0;
+	std::list<ChPhysicsItem*>::iterator iterotherphysics = this->GetSystem()->Get_otherphysicslist()->begin();
+	while (iterotherphysics != this->GetSystem()->Get_otherphysicslist()->end())
+	{
+		if (edges=dynamic_cast<ChProximityContainerSPH*>(*iterotherphysics))
+			break;
+		iterotherphysics++;
+	}
+	assert(edges); // If using a ChMatterSPH, you must add also a ChProximityContainerSPH.
+	
+
+	// 1- Per-node initialization
+
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->nodes[j]->UserForce = VNULL;
+		this->nodes[j]->density = 0;
+	}
+
+	// 2- Per-edge initialization and accumulation of particles's density
+
+	edges->AccumulateStep1();
+
+	// 3- Per-node volume and pressure computation
+
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		ChNodeSPH* mnode = this->nodes[j];
+
+		// node volume is v=mass/density
+		if (mnode->density)
+			mnode->volume = mnode->GetMass()/mnode->density;
+		else 
+			mnode->volume = 0; 
+
+		// node pressure = k(dens - dens_0);
+		mnode->pressure = this->material.Get_pressure_stiffness() * ( mnode->density - this->material.Get_density() );
+	}
+
+	// 4- Per-edge forces computation and accumulation
+
+	edges->AccumulateStep2();
+
+
+	// 5- Per-node load forces in LCP
+
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		// particle gyroscopic force:
+		// none.
+
+		// add gravity 
+		ChVector<> Gforce = GetSystem()->Get_G_acc() * this->nodes[j]->GetMass();
+		ChVector<> TotForce = this->nodes[j]->UserForce + Gforce; 
+
+		ChNodeSPH* mnode = this->nodes[j];
+
+		mnode->variables.Get_fb().PasteSumVector(TotForce * factor ,0,0);
+	}
+
+}
+
+void ChMatterSPH::VariablesQbLoadSpeed()
+{
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		// set current speed in 'qb', it can be used by the LCP solver when working in incremental mode
+		this->nodes[j]->variables.Get_qb().PasteVector(this->nodes[j]->GetPos_dt(),0,0);
+	}
+}
+
+void ChMatterSPH::VariablesFbIncrementMq()
+{
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->nodes[j]->variables.Compute_inc_Mb_v(this->nodes[j]->variables.Get_fb(), this->nodes[j]->variables.Get_qb());
+	}
+}
+
+void ChMatterSPH::VariablesQbSetSpeed(double step)
+{
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		ChVector<> old_pos_dt = this->nodes[j]->GetPos_dt();
+
+		// from 'qb' vector, sets body speed, and updates auxiliary data
+		this->nodes[j]->SetPos_dt(   this->nodes[j]->variables.Get_qb().ClipVector(0,0) );
+
+		// Compute accel. by BDF (approximate by differentiation);
+		if (step)
+		{
+			this->nodes[j]->SetPos_dtdt( (this->nodes[j]->GetPos_dt() - old_pos_dt)  / step);
+		}
+	}
+}
+
+void ChMatterSPH::VariablesQbIncrementPosition(double dt_step)
+{
+	//if (!this->IsActive()) 
+	//	return;
+
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		// Updates position with incremental action of speed contained in the
+		// 'qb' vector:  pos' = pos + dt * speed   , like in an Eulero step.
+
+		ChVector<> newspeed = this->nodes[j]->variables.Get_qb().ClipVector(0,0);
+
+		// ADVANCE POSITION: pos' = pos + dt * vel
+		this->nodes[j]->SetPos( this->nodes[j]->GetPos() + newspeed * dt_step);
+	}
+
+
+}
+
+
+
+//////////////
+
+
+void ChMatterSPH::SetNoSpeedNoAcceleration()
+{
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->nodes[j]->SetPos_dt(VNULL);
+		this->nodes[j]->SetPos_dtdt(VNULL);
+	}
+}
+
+
+
+
+
+//////
+
+
+
+
+
+
+void ChMatterSPH::Update()
+{
+	ChMatterSPH::Update(this->GetChTime());
+}
+
+						
+void ChMatterSPH::Update (double mytime)
+{	
+		// Inherit time changes of parent class
+	ChPhysicsItem::Update(mytime);
+
+	//TrySleeping();		// See if the body can fall asleep; if so, put it to sleeping 
+	//ClampSpeed();			// Apply limits (if in speed clamping mode) to speeds.
+	
+}
+
+
+
+void ChMatterSPH::UpdateExternalGeometry ()
+{
+	if (this->GetExternalObject())
+		this->GetExternalObject()->onChronoChanged();
+}
+
+ 
+// collision stuff
+void ChMatterSPH::SetCollide (bool mcoll)
+{
+
+	if (mcoll == this->do_collide) 
+		return;
+
+	if (mcoll)
+	{
+		this->do_collide = true;
+		if (GetSystem())
+		{
+			for (unsigned int j = 0; j < nodes.size(); j++)
+			{
+				GetSystem()->GetCollisionSystem()->Add(this->nodes[j]->collision_model);
+			}
+		}
+	}
+	else 
+	{
+		this->do_collide = false;
+		if (GetSystem())
+		{
+			for (unsigned int j = 0; j < nodes.size(); j++)
+			{
+				GetSystem()->GetCollisionSystem()->Remove(this->nodes[j]->collision_model);
+			}
+		}
+	}
+}
+
+void ChMatterSPH::SyncCollisionModels()
+{
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->nodes[j]->collision_model->SyncPosition();
+	}
+}
+
+void ChMatterSPH::AddCollisionModelsToSystem() 
+{
+	assert(this->GetSystem());
+	SyncCollisionModels();
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->GetSystem()->GetCollisionSystem()->Add(this->nodes[j]->collision_model);
+	}
+}
+
+void ChMatterSPH::RemoveCollisionModelsFromSystem() 
+{
+	assert(this->GetSystem());
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->GetSystem()->GetCollisionSystem()->Remove(this->nodes[j]->collision_model);
+	}
+}
+
+
+////
+
+void ChMatterSPH::UpdateParticleCollisionModels()
+{
+	for (unsigned int j = 0; j < nodes.size(); j++)
+	{
+		this->nodes[j]->collision_model->ClearModel();
+		//***TO DO*** UPDATE RADIUS OF SPHERE? this->nodes[j]->collision_model->AddCopyOfAnotherModel(this->particle_collision_model);
+		this->nodes[j]->collision_model->BuildModel();
+	}
+}
+
+
+
+
+//////// FILE I/O
+
+void ChMatterSPH::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChIndexedNodes::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->material;
+
+	//***TO DO*** stream nodes
+
+}
+
+void ChMatterSPH::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChIndexedNodes::StreamIN(mstream);
+
+
+		// stream in all member data
+
+	mstream >> this->material;
+
+	//***TO DO*** unstream nodes
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChMatterSPH.h b/SRC/ChronoEngine/physics/ChMatterSPH.h
new file mode 100644
index 0000000..7a9b1c9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChMatterSPH.h
@@ -0,0 +1,353 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHMATTERSPH_H
+#define CHMATTERSPH_H
+
+//////////////////////////////////////////////////
+//
+//   ChMatterSPH.h
+//
+//   Class for clusters of points that can 
+//   simulate a fluid or an elastic / plastic
+//   solid with the SPH Smooth Particle Hydrodynamics
+//   approach, that is with a 'meshless' FEM approach.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "physics/ChIndexedNodes.h"
+#include "physics/ChContinuumMaterial.h"
+#include "collision/ChCCollisionModel.h"
+#include "lcp/ChLcpVariablesNode.h"
+
+
+namespace chrono
+{
+
+using namespace collision;
+
+
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+/// Class for a single node in the SPH cluster
+/// (it does not define mass, inertia and shape becuase those
+/// data are shared between them)
+
+class ChApi ChNodeSPH : public ChNodeXYZ  
+{
+public:
+	ChNodeSPH();
+	~ChNodeSPH();
+
+	ChNodeSPH (const ChNodeSPH& other); // Copy constructor
+	ChNodeSPH& operator= (const ChNodeSPH& other); //Assignment operator
+
+					//
+					// FUNCTIONS
+					//
+
+
+			// Get the kernel radius (max. radius while checking surrounding particles)
+	double GetKernelRadius() {return h_rad;}
+	void SetKernelRadius(double mr);
+
+			// Set collision radius (for colliding with bodies, boundaries, etc.)
+	double GetCollisionRadius() {return coll_rad;}
+	void SetCollisionRadius(double mr);
+
+			// Set the mass of the node
+	void SetMass(double mmass) {this->variables.SetNodeMass(mmass);}
+			// Get the mass of the node
+	double GetMass() const {return variables.GetNodeMass();}
+
+			// Access the 'LCP variables' of the node
+	ChLcpVariables& Variables() {return variables;}
+
+					//
+					// DATA
+					// 
+	
+	ChLcpVariablesNode	variables;
+
+	ChCollisionModel*	collision_model;
+
+	ChVector<> UserForce;		
+
+	double volume; 
+	double density;
+	double h_rad;
+	double coll_rad;
+	double pressure;
+};
+
+
+
+/// Class for SPH fluid material, with basic property 
+/// of uncompressible fluid. 
+
+class ChApi ChContinuumSPH : public fem::ChContinuumMaterial
+{
+private:
+
+	double viscosity;
+	double surface_tension;
+	double pressure_stiffness;
+
+public:
+
+			/// Create a continuum isothropic elastoplastic material,
+			/// where you can define also plastic and elastic max. stress (yeld limits
+			/// for transition elastic->blastic and plastic->fracture).
+	ChContinuumSPH(double m_refdensity = 1000, double mviscosity = 0.1, double mtension= 0) 
+				: viscosity(mviscosity), surface_tension(mtension), pressure_stiffness(100), ChContinuumMaterial(m_refdensity) {};
+
+	virtual ~ChContinuumSPH() {};
+	
+
+			/// Set the viscosity, in [Pa s] units. 
+	void   Set_viscosity (double mvisc) {viscosity = mvisc;}
+			/// Get the viscosity.
+	double Get_viscosity () {return viscosity;}
+
+			/// Set the surface tension coefficient. 
+	void   Set_surface_tension (double mten) {surface_tension = mten;}
+			/// Get the surface tension coefficient.
+	double Get_surface_tension() {return surface_tension;}
+
+			/// Set the pressure stiffness (should be infinite for water
+			/// or other almost-incompressible fluids, but too large 
+			/// values can cause numerical troubles).
+	void   Set_pressure_stiffness (double mst) {pressure_stiffness = mst;}
+			/// Set the pressure stiffness.
+	double Get_pressure_stiffness() {return pressure_stiffness;}
+
+
+				/// Method to allow deserializing 
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing 
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+
+/// Class for clusters of point nodes that can 
+/// simulate a fluid or an elastic / plastic
+/// solid with the SPH Smooth Particle Hydrodynamics
+/// approach, that is with a 'meshless' FEM approach.
+
+class ChApi ChMatterSPH : public ChIndexedNodes
+{
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChMatterSPH,ChIndexedNodes);
+
+private:
+			//
+	  		// DATA
+			//
+	
+						// The nodes: 
+	std::vector<ChNodeSPH*> nodes;				
+
+	ChContinuumSPH material;
+
+	bool do_collide;
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a cluster of nodes for SPH and meshless FEM.
+				/// By default the cluster will contain 0 particles.
+	ChMatterSPH ();
+
+				/// Destructor
+	~ChMatterSPH ();
+
+				/// Copy from another ChMatterSPH. 
+	void Copy(ChMatterSPH* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+
+				/// Enable/disable the collision for this cluster of particles.
+				/// After setting ON, remember RecomputeCollisionModel()
+				/// before anim starts (it is not automatically
+				/// recomputed here because of performance issues.)
+	void  SetCollide (bool mcoll);
+	bool  GetCollide() {return do_collide;}
+
+
+			//
+	  		// FUNCTIONS
+			//
+
+			 	/// Get the number of nodes
+	unsigned int GetNnodes() {return nodes.size();}
+
+				/// Access the N-th node 
+	ChNodeBase* GetNode(unsigned int n) { assert(n<nodes.size()); return nodes[n];}
+				
+				/// Resize the node cluster. Also clear the state of 
+				/// previously created particles, if any.
+	void ResizeNnodes(int newsize);
+
+				/// Add a new node to the particle cluster, passing a 
+				/// vector as initial position.
+	void AddNode(ChVector<double> initial_state);
+
+
+
+		//
+		// LCP INTERFACE
+		//
+
+			 // Override/implement LCP system functions of ChPhysicsItem
+			 // (to assembly/manage data for LCP system solver)
+
+				/// Sets the 'fb' part of the encapsulated ChLcpVariablesBody to zero.
+	void VariablesFbReset();
+
+				/// Adds the current forces applied to body (including gyroscopic torque) in
+				/// encapsulated ChLcpVariablesBody, in the 'fb' part: qf+=forces*factor
+	void VariablesFbLoadForces(double factor=1.);
+
+				/// Initialize the 'qb' part of the ChLcpVariablesBody with the 
+				/// current value of body speeds. Note: since 'qb' is the unknown of the LCP, this
+				/// function seems unuseful, unless used before VariablesFbIncrementMq()
+	void VariablesQbLoadSpeed();
+
+				/// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
+				/// with v_old using VariablesQbLoadSpeed, this method can be used in 
+				/// timestepping schemes that do: M*v_new = M*v_old + forces*dt
+	void VariablesFbIncrementMq();
+
+				/// Fetches the body speed (both linear and angular) from the
+				/// 'qb' part of the ChLcpVariablesBody (does not updates the full body&markers state)
+				/// and sets it as the current body speed.
+				/// If 'step' is not 0, also computes the approximate acceleration of
+				/// the body using backward differences, that is  accel=(new_speed-old_speed)/step.
+				/// Mostly used after the LCP provided the solution in ChLcpVariablesBody .
+	void VariablesQbSetSpeed(double step=0.);
+
+				/// Increment body position by the 'qb' part of the ChLcpVariablesBody,
+				/// multiplied by a 'step' factor.
+				///     pos+=qb*step
+				/// If qb is a speed, this behaves like a single step of 1-st order
+				/// numerical integration (Eulero integration).
+				/// Does not automatically update markers & forces.
+	void VariablesQbIncrementPosition(double step);
+
+
+				/// Tell to a system descriptor that there are variables of type
+				/// ChLcpVariables in this object (for further passing it to a LCP solver)
+				/// Basically does nothing, but maybe that inherited classes may specialize this.
+	virtual void InjectVariables(ChLcpSystemDescriptor& mdescriptor);
+
+
+
+ 
+
+
+			   // Other functions
+
+				/// Set no speed and no accelerations (but does not change the position)
+	void SetNoSpeedNoAcceleration();
+
+			
+				/// Synchronize coll.models coordinates and bounding boxes to the positions of the particles.
+	virtual void SyncCollisionModels();
+	virtual void AddCollisionModelsToSystem();
+	virtual void RemoveCollisionModelsFromSystem();
+
+	void UpdateParticleCollisionModels();
+
+
+				/// Access the material
+	ChContinuumSPH&  GetMaterial() {return material;}
+	
+				/// Initialize the fluid as a prismatic region filled with nodes,
+				/// initially well ordered as a lattice. This is a helper function
+				/// so that you avoid to create all nodes one by one with many calls
+				/// to AddNode() .
+	void FillBox (const ChVector<> size,	///< x,y,z sizes of the box to fill (better if integer multiples of spacing)
+				  const double spacing,		///< the spacing between two near nodes
+				  const double initial_density, ///< density of the material inside the box, for initialization of node's masses
+				  const ChCoordsys<> cords = CSYSNORM, ///< position and rotation of the box
+				  const bool do_centeredcube =true,	///< if false, array is simply cubic, if true is centered cubes (highest regularity)
+				  const double kernel_sfactor =2.2,  ///< the radius of kernel of the particle is 'spacing' multiplied this value
+				  const double randomness = 0.0	///< randomness of the initial distribution lattice, 0...1
+				  );
+
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the particles 
+	virtual void Update (double mytime);
+				/// Update all auxiliary data of the particles
+	virtual void Update ();
+
+				/// Tells to the associated external object ChExternalObject() ,if any,
+				/// that its 3D shape must be updated in order to syncronize to ChBody
+				/// coordinates
+	void UpdateExternalGeometry ();
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+typedef ChSharedPtr<ChMatterSPH> ChSharedMatterSPHPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChNlsolver.cpp b/SRC/ChronoEngine/physics/ChNlsolver.cpp
new file mode 100644
index 0000000..0118d85
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChNlsolver.cpp
@@ -0,0 +1,121 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//  
+//   ChNlsolver.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "physics/ChNlsolver.h"
+#include "core/ChLinearAlgebra.h"
+ 
+namespace chrono
+{
+
+
+
+void ChNonlinearSolver::JacobianCompute(void (*m_func) (ChMatrix<>* mx, ChMatrix<>* res, void* my_data),
+			  ChMatrix<>* mx,
+			  ChMatrix<>* res,
+			  void* my_data,
+			  ChMatrix<>* mJ,
+			  double diff_step)
+{
+	if (diff_step <= 0) diff_step = BDF_STEP_LOW;
+	int jrows = res->GetRows();
+	int jcols = mx->GetRows();
+
+	ChMatrixDynamic<> dres;
+	ChMatrixDynamic<> dx;
+
+	dres.Reset(jrows,1);		
+	dx.Reset(jcols,1);			
+	
+	dres.CopyFromMatrix(*res);
+	dx.CopyFromMatrix(*mx);					
+
+	for (int i = 0; i < jcols; i++)
+	{
+		dx.SetElement(i,0, mx->GetElement(i,0) + diff_step);
+		(*m_func)(&dx, &dres, my_data);
+		for (int j = 0; j < jrows; j++)
+		{
+			mJ->SetElement(j,i, (dres.GetElement(j,0)-res->GetElement(j,0))/diff_step );
+		}
+		dx.SetElement(i,0, mx->GetElement(i,0));
+	}
+}
+
+
+double ChNonlinearSolver::NewtonRaphson (void (*m_func)(ChMatrix<>* mx, ChMatrix<>* res, void* my_data), 
+					  void (*m_jacob)(ChMatrix<>* mx, ChMatrix<>* mJ, void* my_data),
+					  ChMatrix<>* mx,
+					  void* my_data,
+					  int maxiters,
+					  double tolerance)
+{
+	ChMatrixDynamic<> res;
+	ChMatrixDynamic<> jac;
+	ChMatrixDynamic<> delta;
+
+	double residual = 0;
+	int vars = mx->GetRows();
+
+	res.Reset(vars,1);
+	delta.Reset(vars,1);
+	jac.Reset(vars, vars);
+
+	int iters = 0;
+
+	while (TRUE)
+	{
+		if (iters >= maxiters) break; 
+
+		// compute residuals
+
+		(*m_func)(mx, &res, my_data);
+		residual = res.NormInf();
+		if (residual <= tolerance) break;
+		
+		// compute jacobian
+		if (m_jacob)
+			(*m_jacob)(mx, &jac, my_data);
+		else 
+		{
+			ChNonlinearSolver::JacobianCompute(m_func, mx, &res, my_data, &jac, BDF_STEP_LOW);
+		}
+		// solve LU for delta 
+		ChLinearAlgebra::Solve_LinSys(jac, &res, &delta);
+		delta.MatrNeg();
+		mx->MatrInc(delta);
+		
+		iters ++;
+	}
+	return residual;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+
+
+//////// 
+
diff --git a/SRC/ChronoEngine/physics/ChNlsolver.h b/SRC/ChronoEngine/physics/ChNlsolver.h
new file mode 100644
index 0000000..0f4f697
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChNlsolver.h
@@ -0,0 +1,101 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHNLSOLVER_H
+#define CHNLSOLVER_H
+
+//////////////////////////////////////////////////
+//
+//   ChNlsolver.h
+//
+//   Math functions for :
+//      - SOLVER FOR NON-LINEAR EQUATIONS (Newton-Raphson)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "core/ChApiCE.h"
+#include "core/ChMatrix.h"
+
+
+
+namespace chrono
+{
+
+
+
+///
+/// Solver for systems of nonlinear equations.
+///
+///  The solver is provided as a static function, so it can be called
+/// without the need of creating a class instance. That is, you just need to
+/// type: ChNonlinearSolver::NewtonRaphson(etc...)
+///
+///
+
+class ChApi ChNonlinearSolver
+{
+public:
+
+		/// Function which computes the jacobian matrix of a nonlinear vectorial
+		/// function (i.e. set of N scalar functions) respect to M variables.
+		/// It is used internally by NewtonRaphson, but it can also be used by the user.
+		/// If you want to use JacobianCompute, remember that matrices mJ, mx and res
+		/// must be already allocated with the correct sizes (i.e. mJ(N,M), mx(M,1), res(N,1) )
+		/// Also, res must be already computed, for current mx, and mx must be the
+		/// current state in which the jacobian is desired.
+		/// \test
+
+	static void JacobianCompute(void (*m_func) (ChMatrix<>* mx, ChMatrix<>* res, void* my_data),
+				  ChMatrix<>* mx,
+				  ChMatrix<>* res,
+				  void* my_data,
+				  ChMatrix<>* mJ,
+				  double diff_step);
+
+		/// Static function which solves numerically a set of N nonlinear equations in N unknowns.
+		/// You must pass the address of the function m_func() which computes the
+		/// residuals values of the nonlinear equations (being zero when satisfied).
+		/// Your m_func must return the N residuals in the column matrix 'res', given
+		/// the values of the variables in column 'mx', each time it is called -no need
+		/// to create res and mx inside your m_func!!!  Also, the generic pointer my_data
+		/// is passed to my_func just for your convenience, for auxiliary data.
+		/// You can pass the m_jacob() function address if you have a _fast_ custom routine to
+		/// compute the jacobian mJ at mx, otherwise set it to NULL and a generic numerical
+		/// method will be used by default.
+		/// \return  Return value is norm of residual vector (should be near zero after root finding).
+		/// \test
+
+	static double NewtonRaphson (void (*m_func)(ChMatrix<>* mx, ChMatrix<>* res, void* my_data),
+						  void (*m_jacob)(ChMatrix<>* mx, ChMatrix<>* mJ, void* my_data),
+						  ChMatrix<>* mx,
+						  void* my_data,
+						  int maxiters,
+						  double tolerance);
+
+};
+
+
+} // END_OF_NAMESPACE____
+
+
+
+#endif  // END of ChNlsolver.h
+
+
diff --git a/SRC/ChronoEngine/physics/ChNodeBody.cpp b/SRC/ChronoEngine/physics/ChNodeBody.cpp
new file mode 100644
index 0000000..1a98e6a
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChNodeBody.cpp
@@ -0,0 +1,275 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChNodeBody.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChNodeBody.h"
+#include "physics/ChSystem.h"
+#include "physics/ChIndexedNodes.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChNodeBody> a_registration_ChNodeBody;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+
+
+ChNodeBody::ChNodeBody ()
+{
+	this->react= VNULL;
+	this->cache_li_speed = VNULL;
+	this->cache_li_pos = VNULL;
+
+	this->nodes = 0;
+	this->node_index = 0;
+	this->body = 0;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+}
+
+
+ChNodeBody::~ChNodeBody ()
+{
+	
+}
+
+void ChNodeBody::Copy(ChNodeBody* source)
+{
+		// copy the parent class data...
+	ChPhysicsItem::Copy(source);
+
+		// copy class data
+
+	react = source->react;
+	cache_li_speed = source->cache_li_speed;
+	cache_li_pos = source->cache_li_pos;
+
+	this->nodes = 0;
+	this->node_index = 0;
+	this->body = 0;
+}
+
+
+int ChNodeBody::Initialize(ChSharedPtr<ChIndexedNodes> mnodes, ///< nodes container
+						   unsigned int mnode_index, ///< index of the node to join
+						   ChSharedPtr<ChBody>&  mbody,   ///< body to join 
+						   ChVector<>* mattach 	
+						   )
+{
+	ChIndexedNodes* mm1 = mnodes.get_ptr();
+	ChBody* mm2 = mbody.get_ptr();
+	assert(mm1 && mm2);
+	assert(mm1->GetSystem() == mm2->GetSystem());
+
+	this->nodes = mm1;
+	this->node_index = mnode_index;
+	this->body = mm2;
+
+	this->constraint1.SetVariables(&(mm1->GetNode(node_index)->Variables()), &mm2->Variables());
+	this->constraint2.SetVariables(&(mm1->GetNode(node_index)->Variables()), &mm2->Variables());
+	this->constraint3.SetVariables(&(mm1->GetNode(node_index)->Variables()), &mm2->Variables());
+
+	this->SetSystem(this->body->GetSystem());
+
+	if (mattach)
+	{
+		this->attach_position = body->Point_World2Body(mattach);
+	}
+	else
+	{
+		ChVector<> temp= ((ChNodeXYZ*)(this->nodes->GetNode(this->node_index)))->GetPos(); // warning, downcast to ChNodeXYZ* 
+		this->attach_position = body->Point_World2Body(&temp);
+	}
+
+	return true;
+}
+
+
+void ChNodeBody::Update (double mytime)
+{
+		// Inherit time changes of parent class
+	ChPhysicsItem::Update(mytime);
+	
+		// update class data
+	// ...
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChNodeBody::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	mdescriptor.InsertConstraint(&constraint1);
+	mdescriptor.InsertConstraint(&constraint2);
+	mdescriptor.InsertConstraint(&constraint3);
+}
+
+void ChNodeBody::ConstraintsBiReset()
+{
+	constraint1.Set_b_i(0.);
+	constraint2.Set_b_i(0.);
+	constraint3.Set_b_i(0.);
+}
+ 
+void ChNodeBody::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	ChVector<> res = ((ChNodeXYZ*)(this->nodes->GetNode(this->node_index)))->GetPos() - this->body->Point_Body2World(&this->attach_position) ; 
+
+	this->constraint1.Set_b_i(constraint1.Get_b_i() +  factor * res.x);
+	this->constraint2.Set_b_i(constraint2.Get_b_i() +  factor * res.y);
+	this->constraint3.Set_b_i(constraint3.Get_b_i() +  factor * res.z);
+}
+
+void ChNodeBody::ConstraintsBiLoad_Ct(double factor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	// nothing
+}
+
+
+void ChNodeBody::ConstraintsLoadJacobians()
+{
+		// compute jacobians
+	ChMatrix33<> Jxn;
+	Jxn.Set33Identity();
+
+	ChMatrix33<> Jxb;
+	Jxb.Set33Identity();
+	Jxb.MatrNeg();
+
+	ChMatrix33<> atilde;
+	atilde.Set_X_matrix(-this->attach_position);
+	ChMatrix33<> Jrb;
+	Jrb.MatrMultiply(*this->body->GetA(), atilde);
+
+	this->constraint1.Get_Cq_a()->PasteClippedMatrix(&Jxn, 0,0, 1,3, 0,0);
+	this->constraint2.Get_Cq_a()->PasteClippedMatrix(&Jxn, 1,0, 1,3, 0,0);
+	this->constraint3.Get_Cq_a()->PasteClippedMatrix(&Jxn, 2,0, 1,3, 0,0);
+
+	this->constraint1.Get_Cq_b()->PasteClippedMatrix(&Jxb, 0,0, 1,3, 0,0);
+	this->constraint2.Get_Cq_b()->PasteClippedMatrix(&Jxb, 1,0, 1,3, 0,0);
+	this->constraint3.Get_Cq_b()->PasteClippedMatrix(&Jxb, 2,0, 1,3, 0,0);
+	this->constraint1.Get_Cq_b()->PasteClippedMatrix(&Jrb, 0,0, 1,3, 0,3);
+	this->constraint2.Get_Cq_b()->PasteClippedMatrix(&Jrb, 1,0, 1,3, 0,3);
+	this->constraint3.Get_Cq_b()->PasteClippedMatrix(&Jrb, 2,0, 1,3, 0,3);
+
+}
+ 
+
+void ChNodeBody::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	this->react.x = constraint1.Get_l_i() * factor; 
+	this->react.y = constraint2.Get_l_i() * factor; 
+	this->react.z = constraint3.Get_l_i() * factor; 
+}
+
+// Following functions are for exploiting the contact persistence
+
+void  ChNodeBody::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	constraint1.Set_l_i(this->cache_li_speed.x);
+	constraint2.Set_l_i(this->cache_li_speed.y);
+	constraint3.Set_l_i(this->cache_li_speed.z);
+}
+
+void  ChNodeBody::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	constraint1.Set_l_i(this->cache_li_pos.x);
+	constraint2.Set_l_i(this->cache_li_pos.y);
+	constraint3.Set_l_i(this->cache_li_pos.z);
+}
+
+void  ChNodeBody::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	this->cache_li_speed.x = (float)constraint1.Get_l_i();
+	this->cache_li_speed.y = (float)constraint2.Get_l_i();
+	this->cache_li_speed.z = (float)constraint3.Get_l_i();
+}
+
+void  ChNodeBody::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	this->cache_li_pos.x =  (float)constraint1.Get_l_i();
+	this->cache_li_pos.y =  (float)constraint2.Get_l_i();
+	this->cache_li_pos.z =  (float)constraint3.Get_l_i();
+}
+
+
+
+//////// FILE I/O
+
+void ChNodeBody::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->node_index;
+	mstream << this->attach_position;
+	mstream << this->react;
+}
+
+void ChNodeBody::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(mstream);
+
+		// deserialize class
+	mstream >> this->node_index;
+	mstream >> this->attach_position;
+	mstream >> this->react;
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChNodeBody.h b/SRC/ChronoEngine/physics/ChNodeBody.h
new file mode 100644
index 0000000..26a181f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChNodeBody.h
@@ -0,0 +1,182 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSBODY_H
+#define CHSHAFTSBODY_H
+
+//////////////////////////////////////////////////
+//
+//   ChNodeBody.h
+//
+//   Class for creating a constraint between a node point
+//   and a ChBody object (that is, it fixes a 3-DOF point
+//   to a 6-DOF body). 
+//   Nodes are 3-DOF points that are used in point-based 
+//   primitives, such as ChMatterSPH or finite elements.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChBody.h"
+#include "lcp/ChLcpConstraintTwoGeneric.h"
+
+
+
+namespace chrono
+{
+
+// Forward references (for parent hierarchy pointer)
+
+class ChIndexedNodes;
+class ChBody;
+
+/// Class for creating a constraint between a node point
+/// and a ChBody object (that is, it fixes a 3-DOF point
+/// to a 6-DOF body). 
+/// Nodes are 3-DOF points that are used in point-based 
+/// primitives, such as ChMatterSPH or finite elements.
+
+class ChApi ChNodeBody : public ChPhysicsItem {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChNodeBody,ChPhysicsItem);
+
+private:
+			//
+	  		// DATA
+			//
+
+	ChVector<> react;					
+	
+						// used as an interface to the LCP solver.
+	ChLcpConstraintTwoGeneric constraint1;
+	ChLcpConstraintTwoGeneric constraint2;
+	ChLcpConstraintTwoGeneric constraint3;
+
+	ChVector<> cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	ChVector<> cache_li_pos;	// used to cache the last computed value of multiplier (solver warm starting)	
+
+	unsigned int node_index;
+	ChIndexedNodes* nodes;
+	ChBody*  body;
+
+	ChVector<> attach_position; 
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a shaft.
+	ChNodeBody ();
+				/// Destructor
+	~ChNodeBody ();
+
+				/// Copy from another ChNodeBody. 
+	void Copy(ChNodeBody* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of scalar costraints 
+	virtual int GetDOC_c  () {return 3;}
+
+
+			// Override/implement LCP system functions of ChPhysicsItem
+			// (to assembly/manage data for LCP system solver
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+			   // Other functions
+
+				/// Use this function after object creation, to initialize it, given  
+				/// the 1D shaft and 3D body to join. 
+				/// The attachment position is the actual position of the node (unless
+				/// otherwise defines, using the optional 'mattach' parameter).
+				/// Note, mnodes and mbody must belong to the same ChSystem. 
+	virtual int Initialize(ChSharedPtr<ChIndexedNodes> mnodes, ///< nodes container
+						   unsigned int mnode_index, ///< index of the node to join
+						   ChSharedPtr<ChBody>&  mbody,  ///< body to join 
+						   ChVector<>* mattach=0		 ///< optional: if not null, sets the attachment position in absolute coordinates 
+						   );
+
+					/// Get the attachment position, in the reference coordinates of the body.
+	ChVector<> GetAttachPosition() {return attach_position;}
+					/// Set the attachment position, in the reference coordinates of the body
+	void SetAttachPositionInBodyCoords(ChVector<> mattach) {attach_position = mattach;}
+					/// Set the attachment position, in the absolute coordinates
+	void SetAttachPositionInAbsoluteCoords(ChVector<> mattach) {attach_position = body->Point_World2Body(&mattach);}
+
+
+				/// Get the reaction torque considered as applied to ChShaft.
+	ChVector<> GetReactionOnNode() {return -(react);}
+
+				/// Get the reaction torque considered as applied to ChBody.
+	ChVector<> GetReactionOnBody() {return react;}
+
+	
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the gear transmission at given time
+	virtual void Update (double mytime);
+	
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChNodeBody> ChSharedNodeBodyPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChObject.cpp b/SRC/ChronoEngine/physics/ChObject.cpp
new file mode 100644
index 0000000..a8ccf4a
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChObject.cpp
@@ -0,0 +1,180 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChObject.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <stdlib.h>
+#include <iostream>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+#include "physics/ChObject.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChExternalObject.h"
+
+
+namespace chrono
+{
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+// BASE CLASS FOR HANDLING ITEMS
+// with linked-list handling functions
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChObj> a_registration_ChObj;
+
+
+ChObj::ChObj ()						// builder
+{
+	name.clear();
+	//next= 0;
+	//prev= 0;
+
+	ChTime = 0;
+	identifier = 0;
+
+	external_obj = 0;
+}
+
+ChObj::~ChObj()
+{
+	if (external_obj)
+		delete external_obj;
+}
+
+
+void ChObj::Copy(ChObj* source)
+{
+	identifier = source->identifier;
+
+	name = source->name;
+	ChTime = source->ChTime;
+
+	if (source->GetExternalObject())
+		SetExternalObject(source->GetExternalObject());
+	else
+		SetNoExternalObject();
+}
+
+
+
+void ChObj::SetExternalObject(ChExternalObject* m_obj)
+{
+	if (external_obj)
+		delete external_obj;
+	external_obj = m_obj->new_Duplicate();
+}
+
+void ChObj::SetNoExternalObject()
+{
+	if (external_obj)
+		delete external_obj;
+	external_obj = NULL;
+}
+
+
+
+//
+// OTHER FUNCTIONS
+//
+
+char* ChObj::GetName ()
+{
+	if (this->external_obj)
+		return external_obj->GetName();
+	else
+		return (char*)this->name.c_str();
+}
+
+void ChObj::SetName (char myname[])
+{
+	name = myname;
+}
+
+
+std::string ChObj::GetNameString ()
+{
+	if (this->external_obj)
+		return std::string(external_obj->GetName());
+	else
+		return this->name;
+}
+
+void ChObj::SetNameString (std::string& myname)
+{
+	name = myname;
+}
+
+
+
+
+//
+// FILE BINARY I/O
+//
+
+
+
+
+void ChObj::StreamOUT(ChStreamOutBinary& mstream)
+{
+		// class version number
+	mstream.VersionWrite(2);
+		// stream out all member data
+	mstream << identifier;
+	mstream << GetName();
+}
+
+
+void ChObj::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// stream in all member data
+	if (version <= 1)
+	{
+		int mfoo;
+		mstream >> mfoo;
+	}
+	mstream >> identifier;
+	char mbuffer[250];
+	mstream >> mbuffer;
+	SetName(mbuffer);
+}
+
+void ChObj::StreamOUT(ChStreamOutAscii& mstream)
+{
+	mstream <<"object type:" << this->GetRTTI()->GetName() << "\n";
+	mstream << GetName() << "\n";
+	mstream << GetIdentifier() << "\n";
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChObject.h b/SRC/ChronoEngine/physics/ChObject.h
new file mode 100644
index 0000000..4ef190c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChObject.h
@@ -0,0 +1,229 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHOBJECT_H
+#define CHOBJECT_H
+
+//////////////////////////////////////////////////
+//  
+//   ChObject.h
+//
+// Base class for objects which can be renamed, 
+// copied, etc. Provides interface to link objects to
+// item in hosting applications, like geometric objects 
+// in the editor of a 3d modeler.
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include <iostream>
+#include <string>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+
+#include "core/ChLog.h"
+#include "core/ChMath.h"
+#include "core/ChLists.h"
+#include "core/ChShared.h"
+
+#include <vector>
+
+
+
+namespace chrono 
+{
+
+
+// Forward references
+
+class ChVar;
+class ChTag;
+class ChExternalObject;
+
+
+
+#define CHOBJ_NAMELENGTH 20
+
+
+///
+/// Base class for items which can be named, deleted,
+/// copied. etc. as in the editor of a 3d modeler.
+///
+/// This class also embeds a simple linked-list mechanism
+/// for fast management of linked lists of items, instead
+/// of using STL lists or ChList. ***OBSOLETE***
+///
+/// This class inherits the features of the reference-countable
+/// ChShared class, so that  ChObj  instances can be managed
+/// easily with the 'intrusive smart pointers' ChSharedPtr
+/// (with minimal overhead in performance, yet providing the
+/// safe and comfortable automatic deallocation mechanism of
+/// shared/smart pointers).
+///
+/// Each ChObject also has a pointer to user data (for example,
+/// the user data can be the encapsulating object in case of
+/// implementation as a plugin for 3D modeling software.
+///
+/// Also, each ChObj object has a 32 bit identifier, in case
+/// unique identifiers are used (hash algorithms, etc.)
+///
+
+class ChApi ChObj : public ChShared {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChObj, ChShared);
+
+private:
+			// 
+			// DATA
+			//
+
+				// name of object
+	std::string name;
+
+				// ID for referencing
+	int identifier;				
+
+
+				// Reference to an external object associated to this item,
+				// useful if encapsulating into other 3d engines or apps.
+	ChExternalObject* external_obj;
+
+
+protected: 
+				// the time of simulation for the object
+	double ChTime;		
+
+
+public:
+			//
+			//	CONSTRUCTORS/DELETION
+			// 
+
+	ChObj();							
+	virtual ~ChObj();
+
+	void Copy(ChObj* source);
+
+			//
+			// FUNCTIONS
+			//
+
+				/// Gets the numerical identifier of the object. 
+	int  GetIdentifier () { return identifier; }	
+				/// Sets the numerical identifier of the object.
+	void SetIdentifier (int id) { identifier = id; }
+
+				/// Given a fast list of ChObj, returns the address of the first matching the ID.
+	ChObj* GetAddrFromID (ChObj** ChList, int myID);
+
+				/// Gets the simulation time of this object
+	double GetChTime () { return ChTime; }	
+				/// Sets the simulation time of this object.
+	void   SetChTime (double m_time) { ChTime = m_time; }
+
+
+				/// Gets the name of the object as C Ascii null-terminated string -for reading only!
+	char* GetName ();
+				/// Sets the name of this object, as ascii string
+	void SetName (char myname[]);
+
+				/// Gets the name of the object as C Ascii null-terminated string.
+	std::string GetNameString ();
+				/// Sets the name of this object, as std::string 
+	void SetNameString (std::string& myname);
+
+
+	
+
+				/// Returns a reference to the ChExternalObject object associated
+				/// to this item. The external object can be used to handle 
+				/// external objects when encapsulating other 3d engines or apps.
+				/// Return value may be null.
+	ChExternalObject* GetExternalObject() {return external_obj;}
+
+				/// Sets the ChExternalObject of this object (the m_obj will be cloned)
+	void   SetExternalObject(ChExternalObject* m_obj);
+				/// Sets no external object.
+	void   SetNoExternalObject();
+
+
+		// Set-get generic LONG flags, passed as reference
+
+	void MFlagsSetAllOFF (int& mflag) {mflag = 0;}
+	void MFlagsSetAllON (int& mflag) {mflag = 0; mflag = ~ mflag;}
+	void MFlagSetON  (int& mflag, int mask) {mflag |= mask ;}
+	void MFlagSetOFF (int& mflag, int mask) {mflag &= ~ mask;}
+	int  MFlagGet    (int& mflag, int mask) {	return (mflag & mask);};
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	virtual void StreamOUT(ChStreamOutAscii& mstream);
+
+
+};
+
+
+
+// Functions to manipulate STL containers of ChObj objects
+
+template <class T, class Iterator>
+T* ChContainerSearchFromName(char* m_name, Iterator from, Iterator to)
+{
+	Iterator iter = from;
+	while (iter != to)
+	{
+		if (!strcmp(m_name, (*iter)->GetName())) 
+			return (*iter);
+		iter++;
+	}
+	return 0; 
+}
+
+template <class T, class Iterator>
+T* ChContainerSearchFromID(int myID, Iterator from, Iterator to)
+{
+	Iterator iter = from;
+	while (iter != to)
+	{
+		if (myID == (*iter)->GetIdentifier()) 
+			return (*iter);
+		iter++;
+	}
+	return 0;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChParticlesClones.cpp b/SRC/ChronoEngine/physics/ChParticlesClones.cpp
new file mode 100644
index 0000000..57a00d2
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChParticlesClones.cpp
@@ -0,0 +1,576 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChParticlesClones.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+    
+#include <stdlib.h>
+#include <algorithm>
+
+#include "core/ChTrasform.h"
+#include "physics/ChParticlesClones.h"
+#include "physics/ChSystem.h"
+#include "physics/ChGlobal.h"
+
+#include "physics/ChExternalObject.h"
+#include "collision/ChCModelBulletParticle.h"
+#include "core/ChLinearAlgebra.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+using namespace collision;
+using namespace geometry;
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChParticlesClones> a_registration_ChParticlesClones;
+
+	
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR A PARTICLE
+
+
+ChAparticle::ChAparticle()
+{
+	this->collision_model = new ChModelBulletParticle;
+	this->UserForce = VNULL;
+	this->UserTorque = VNULL;
+}
+
+ChAparticle::~ChAparticle()
+{
+	delete collision_model; 
+}
+
+ChAparticle::ChAparticle (const ChAparticle& other) :
+					ChParticleBase(other)
+{
+	this->collision_model = new ChModelBulletParticle;
+	this->collision_model->AddCopyOfAnotherModel(other.collision_model);
+	((ChModelBulletParticle*)collision_model)->SetParticle(
+		((ChModelBulletParticle*)other.collision_model)->GetParticles(),
+		((ChModelBulletParticle*)other.collision_model)->GetParticleId());
+	this->UserForce = other.UserForce;
+	this->UserTorque = other.UserTorque;
+	this->variables = other.variables;
+}
+
+ChAparticle& ChAparticle::operator= (const ChAparticle& other)
+{
+	if (&other == this) 
+		return *this;
+
+	// parent class copy
+	ChParticleBase::operator=(other);
+
+	this->collision_model->ClearModel();
+	this->collision_model->AddCopyOfAnotherModel(other.collision_model);
+		((ChModelBulletParticle*)collision_model)->SetParticle(
+		((ChModelBulletParticle*)other.collision_model)->GetParticles(),
+		((ChModelBulletParticle*)other.collision_model)->GetParticleId());
+	this->UserForce = other.UserForce;
+	this->UserTorque = other.UserTorque;
+	this->variables = other.variables;
+	
+	return *this;
+}
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR PARTICLE CLUSTER
+
+
+ChParticlesClones::ChParticlesClones ()
+{
+	do_collide = false;
+	do_limit_speed = false;
+	do_sleep = false;
+
+	this->SetMass(1.0);
+	this->SetInertiaXX(ChVector<double>(1.0,1.0,1.0));
+	this->SetInertiaXY(ChVector<double>(0,0,0));
+
+	particle_collision_model = new ChModelBulletParticle();
+	((ChModelBulletParticle*)particle_collision_model)->SetParticle(this,9999999);
+
+	this->particles.clear();
+	//this->ResizeNparticles(num_particles); // caused memory corruption.. why?
+
+	matsurface = ChSharedPtr<ChMaterialSurface>(new ChMaterialSurface);
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	max_speed = 0.5f;
+	max_wvel  = 2.0f*float(CH_C_PI);
+
+	sleep_time = 0.6f;
+	sleep_starttime = 0;
+	sleep_minspeed = 0.1f;
+	sleep_minwvel = 0.04f; 
+}
+
+
+ChParticlesClones::~ChParticlesClones ()
+{
+	this->ResizeNparticles(0);
+
+	if (particle_collision_model) 
+		delete particle_collision_model;
+	particle_collision_model = 0;
+	
+}
+
+void ChParticlesClones::Copy(ChParticlesClones* source)
+{
+		// copy the parent class data...
+	ChIndexedParticles::Copy(source);
+
+	do_collide = source->do_collide;
+	do_sleep = source->do_sleep;
+	do_limit_speed = source->do_limit_speed;
+
+	this->SetMass(source->GetMass());
+	this->SetInertiaXX(source->GetInertiaXX());
+	this->SetInertiaXY(source->GetInertiaXY());
+
+	particle_collision_model->ClearModel();
+	
+	this->matsurface = source->matsurface;  // also copy-duplicate the material? Let the user handle this..
+
+	ResizeNparticles(source->GetNparticles());
+
+	max_speed = source->max_speed;
+	max_wvel  = source->max_wvel;
+
+	sleep_time = source->sleep_time;
+	sleep_starttime = source->sleep_starttime;
+	sleep_minspeed = source->sleep_minspeed;
+	sleep_minwvel = source->sleep_minwvel;
+}
+
+
+
+
+void ChParticlesClones::ResizeNparticles(int newsize)
+{
+	bool oldcoll = this->GetCollide();
+	this->SetCollide(false); // this will remove old particle coll.models from coll.engine, if previously added
+
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		delete (this->particles[j]);
+		this->particles[j] = 0;
+	}
+
+	this->particles.resize(newsize);
+
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->particles[j] = new ChAparticle;
+
+		this->particles[j]->variables.SetSharedMass(&this->particle_mass);
+		this->particles[j]->variables.SetUserData((void*)this); // UserData unuseful in future cuda solver?
+		((ChModelBulletParticle*)this->particles[j]->collision_model)->SetParticle(this,j);
+		// this->particles[j]->collision_model->ClearModel();
+		this->particles[j]->collision_model->AddCopyOfAnotherModel(this->particle_collision_model);
+		this->particles[j]->collision_model->BuildModel();
+	}
+
+	this->SetCollide(oldcoll); // this will also add particle coll.models to coll.engine, if already in a ChSystem
+
+}
+
+
+void ChParticlesClones::AddParticle(ChCoordsys<double> initial_state)
+{
+	ChAparticle* newp = new ChAparticle;
+	newp->SetCoord(initial_state);
+
+	this->particles.push_back(newp);
+
+	newp->variables.SetSharedMass(&this->particle_mass);
+	newp->variables.SetUserData((void*)this);  // UserData unuseful in future cuda solver?
+	((ChModelBulletParticle*)newp->collision_model)->SetParticle(this,particles.size()-1);
+	// newp->collision_model->ClearModel(); // wasn't already added to system, no need to remove
+	newp->collision_model->AddCopyOfAnotherModel(this->particle_collision_model); 
+	newp->collision_model->BuildModel(); // will also add to system, if collision is on.
+
+}
+
+
+
+
+
+
+
+//// 
+void ChParticlesClones::InjectVariables(ChLcpSystemDescriptor& mdescriptor)
+{	
+	//this->variables.SetDisabled(!this->IsActive());
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		mdescriptor.InsertVariables(&(this->particles[j]->variables));
+	}
+}
+
+
+void ChParticlesClones::VariablesFbReset()
+{
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->particles[j]->variables.Get_fb().FillElem(0.0);
+	}
+}
+
+void ChParticlesClones::VariablesFbLoadForces(double factor)
+{
+	ChVector<> Gforce; 
+	if (GetSystem())
+		Gforce = GetSystem()->Get_G_acc() * this->particle_mass.GetBodyMass();
+
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		// particle gyroscopic force:
+		ChVector<> Wvel = this->particles[j]->GetWvel_loc();
+		ChVector<> gyro = Vcross (Wvel, (this->particle_mass.GetBodyInertia().Matr_x_Vect (Wvel)));
+
+		// add applied forces and torques (and also the gyroscopic torque and gravity!) to 'fb' vector
+		this->particles[j]->variables.Get_fb().PasteSumVector((this->particles[j]->UserForce + Gforce) * factor ,0,0);
+		this->particles[j]->variables.Get_fb().PasteSumVector((this->particles[j]->UserTorque- gyro)  * factor ,3,0);
+	}
+}
+
+
+void ChParticlesClones::VariablesQbLoadSpeed()
+{
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		// set current speed in 'qb', it can be used by the LCP solver when working in incremental mode
+		this->particles[j]->variables.Get_qb().PasteVector(this->particles[j]->GetCoord_dt().pos,0,0);
+		this->particles[j]->variables.Get_qb().PasteVector(this->particles[j]->GetWvel_loc()    ,3,0);
+	}
+}
+
+void ChParticlesClones::VariablesFbIncrementMq()
+{
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->particles[j]->variables.Compute_inc_Mb_v(this->particles[j]->variables.Get_fb(), this->particles[j]->variables.Get_qb());
+	}
+}
+
+void ChParticlesClones::VariablesQbSetSpeed(double step)
+{
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		ChCoordsys<> old_coord_dt = this->particles[j]->GetCoord_dt();
+
+		// from 'qb' vector, sets body speed, and updates auxiliary data
+		this->particles[j]->SetPos_dt(   this->particles[j]->variables.Get_qb().ClipVector(0,0) );
+		this->particles[j]->SetWvel_loc( this->particles[j]->variables.Get_qb().ClipVector(3,0) );
+
+		// apply limits (if in speed clamping mode) to speeds.
+		//ClampSpeed(); NO - do only per-particle, here.. (but.. really needed here?)
+
+		// Compute accel. by BDF (approximate by differentiation);
+		if (step)
+		{
+			this->particles[j]->SetPos_dtdt( (this->particles[j]->GetCoord_dt().pos - old_coord_dt.pos)  / step);
+			this->particles[j]->SetRot_dtdt( (this->particles[j]->GetCoord_dt().rot - old_coord_dt.rot)  / step);
+		}
+	}
+}
+
+void ChParticlesClones::VariablesQbIncrementPosition(double dt_step)
+{
+	//if (!this->IsActive()) 
+	//	return;
+
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		// Updates position with incremental action of speed contained in the
+		// 'qb' vector:  pos' = pos + dt * speed   , like in an Eulero step.
+
+		ChVector<> newspeed = this->particles[j]->variables.Get_qb().ClipVector(0,0);
+		ChVector<> newwel   = this->particles[j]->variables.Get_qb().ClipVector(3,0);
+
+		// ADVANCE POSITION: pos' = pos + dt * vel
+		this->particles[j]->SetPos( this->particles[j]->GetPos() + newspeed * dt_step);
+
+		// ADVANCE ROTATION: rot' = [dt*wwel]%rot  (use quaternion for delta rotation)
+		ChQuaternion<> mdeltarot;
+		ChQuaternion<> moldrot = this->particles[j]->GetRot();
+		ChVector<> newwel_abs = (*(this->particles[j]->GetA())) * newwel;
+		double mangle = newwel_abs.Length() * dt_step;
+		newwel_abs.Normalize();
+		mdeltarot.Q_from_AngAxis(mangle, newwel_abs);
+		ChQuaternion<> mnewrot = mdeltarot % moldrot;
+		this->particles[j]->SetRot( mnewrot );
+	}
+}
+
+
+
+//////////////
+
+
+void ChParticlesClones::SetNoSpeedNoAcceleration()
+{
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->particles[j]->SetPos_dt(VNULL);
+		this->particles[j]->SetWvel_loc(VNULL);
+		this->particles[j]->SetPos_dtdt(VNULL);
+		this->particles[j]->SetRot_dtdt(QNULL);
+	}
+}
+
+
+////
+void ChParticlesClones::ClampSpeed()
+{
+	if (this->GetLimitSpeed())
+	{
+		for (unsigned int j = 0; j < particles.size(); j++)
+		{
+			double w = 2.0*this->particles[j]->GetRot_dt().Length();
+			if (w > max_wvel)
+				this->particles[j]->SetRot_dt(this->particles[j]->GetRot_dt() * max_wvel/w);
+		
+			double v = this->particles[j]->GetPos_dt().Length();
+			if (v > max_speed)
+				this->particles[j]->SetPos_dt(this->particles[j]->GetPos_dt() * max_speed/v);
+		}
+	}
+}
+
+
+
+
+////
+// The inertia tensor functions
+
+void ChParticlesClones::SetInertia (ChMatrix33<>* newXInertia)
+{
+	this->particle_mass.SetBodyInertia(newXInertia);
+}
+
+void ChParticlesClones::SetInertiaXX (Vector iner)
+{
+	this->particle_mass.GetBodyInertia().SetElement(0,0,iner.x);
+	this->particle_mass.GetBodyInertia().SetElement(1,1,iner.y);
+	this->particle_mass.GetBodyInertia().SetElement(2,2,iner.z);
+	this->particle_mass.GetBodyInertia().FastInvert(&this->particle_mass.GetBodyInvInertia());
+}
+void ChParticlesClones::SetInertiaXY (Vector iner)
+{
+	this->particle_mass.GetBodyInertia().SetElement(0,1,iner.x);
+	this->particle_mass.GetBodyInertia().SetElement(0,2,iner.y);
+	this->particle_mass.GetBodyInertia().SetElement(1,2,iner.z);
+	this->particle_mass.GetBodyInertia().SetElement(1,0,iner.x);
+	this->particle_mass.GetBodyInertia().SetElement(2,0,iner.y);
+	this->particle_mass.GetBodyInertia().SetElement(2,1,iner.z);
+	this->particle_mass.GetBodyInertia().FastInvert(&this->particle_mass.GetBodyInvInertia());
+}
+
+Vector ChParticlesClones::GetInertiaXX()
+{
+	ChVector<> iner;
+	iner.x= this->particle_mass.GetBodyInertia().GetElement(0,0);
+	iner.y= this->particle_mass.GetBodyInertia().GetElement(1,1);
+	iner.z= this->particle_mass.GetBodyInertia().GetElement(2,2);
+	return iner;
+}
+
+Vector ChParticlesClones::GetInertiaXY()
+{
+	ChVector<> iner;
+	iner.x= this->particle_mass.GetBodyInertia().GetElement(0,1);
+	iner.y= this->particle_mass.GetBodyInertia().GetElement(0,2);
+	iner.z= this->particle_mass.GetBodyInertia().GetElement(1,2);
+	return iner;
+}
+
+
+
+//////
+
+
+
+
+
+
+void ChParticlesClones::Update()
+{
+	ChParticlesClones::Update(this->GetChTime());
+}
+
+						
+void ChParticlesClones::Update (double mytime)
+{	
+	ChTime = mytime;
+
+	//TrySleeping();			// See if the body can fall asleep; if so, put it to sleeping 
+	ClampSpeed();			// Apply limits (if in speed clamping mode) to speeds.
+	
+}
+
+
+
+void ChParticlesClones::UpdateExternalGeometry ()
+{
+	if (this->GetExternalObject())
+		this->GetExternalObject()->onChronoChanged();
+}
+
+ 
+// collision stuff
+void ChParticlesClones::SetCollide (bool mcoll)
+{
+
+	if (mcoll == this->do_collide) 
+		return;
+
+	if (mcoll)
+	{
+		this->do_collide = true;
+		if (GetSystem())
+		{
+			for (unsigned int j = 0; j < particles.size(); j++)
+			{
+				GetSystem()->GetCollisionSystem()->Add(this->particles[j]->collision_model);
+			}
+		}
+	}
+	else 
+	{
+		this->do_collide = false;
+		if (GetSystem())
+		{
+			for (unsigned int j = 0; j < particles.size(); j++)
+			{
+				GetSystem()->GetCollisionSystem()->Remove(this->particles[j]->collision_model);
+			}
+		}
+	}
+}
+
+void ChParticlesClones::SyncCollisionModels()
+{
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->particles[j]->collision_model->SyncPosition();
+	}
+}
+
+void ChParticlesClones::AddCollisionModelsToSystem() 
+{
+	assert(this->GetSystem());
+	SyncCollisionModels();
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->GetSystem()->GetCollisionSystem()->Add(this->particles[j]->collision_model);
+	}
+}
+
+void ChParticlesClones::RemoveCollisionModelsFromSystem() 
+{
+	assert(this->GetSystem());
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->GetSystem()->GetCollisionSystem()->Remove(this->particles[j]->collision_model);
+	}
+}
+
+
+////
+
+void ChParticlesClones::UpdateParticleCollisionModels()
+{
+	for (unsigned int j = 0; j < particles.size(); j++)
+	{
+		this->particles[j]->collision_model->ClearModel();
+		this->particles[j]->collision_model->AddCopyOfAnotherModel(this->particle_collision_model);
+		this->particles[j]->collision_model->BuildModel();
+	}
+}
+
+
+
+
+//////// FILE I/O
+
+void ChParticlesClones::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChIndexedParticles::StreamOUT(mstream);
+
+		// stream out all member data
+
+	//...
+	//dfoo=(double)rolling_friction;mstream << dfoo;
+	//dfoo=(double)spinning_friction;mstream << dfoo;
+
+	//***TO DO*** stream data & clones
+
+}
+
+void ChParticlesClones::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChIndexedParticles::StreamIN(mstream);
+
+
+		// stream in all member data
+
+	particle_collision_model->ClearModel();
+	
+	//...
+	//double dfoo;
+	//mstream >> dfoo;		rolling_friction= (float)dfoo;
+	//mstream >> dfoo;		spinning_friction= (float)dfoo;
+
+	//***TO DO*** unstream data & nodes
+
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChParticlesClones.h b/SRC/ChronoEngine/physics/ChParticlesClones.h
new file mode 100644
index 0000000..22adfe9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChParticlesClones.h
@@ -0,0 +1,384 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHPARTICLESCLONES_H
+#define CHPARTICLESCLONES_H
+
+//////////////////////////////////////////////////
+//
+//   ChParticlesClones.h
+//
+//   Class for clusters of particle 'clones', that is many
+//   rigid objects that share the same shape and mass.
+//   This can be used to make granular flows. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "physics/ChIndexedParticles.h"
+#include "collision/ChCCollisionModel.h"
+#include "lcp/ChLcpVariablesBodySharedMass.h"
+#include "physics/ChMaterialSurface.h"
+
+namespace chrono
+{
+
+using namespace collision;
+
+
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+/// Class for a single particle clone in the ChParticlesClones cluster
+/// (it does not define mass, inertia and shape becuase those
+/// data are _shared_ between them)
+
+class ChApi ChAparticle : public ChParticleBase  
+{
+public:
+	ChAparticle();
+	~ChAparticle();
+
+	ChAparticle (const ChAparticle& other); // Copy constructor
+	ChAparticle& operator= (const ChAparticle& other); //Assignment operator
+	
+		// Access the 'LCP variables' of the node
+	virtual ChLcpVariables& Variables() {return variables;}
+
+
+	ChLcpVariablesBodySharedMass	variables;
+	ChCollisionModel*				collision_model;
+	ChVector<> UserForce;		
+	ChVector<> UserTorque;		
+};
+
+
+/// Class for clusters of 'clone' particles, that is many
+/// rigid objects with the same shape and mass.
+/// This can be used to make granular flows, where
+/// you have thousands of objects with the same shape.
+/// In fact, a single ChParticlesClones object can
+/// be more memory-efficient than many ChBody objects,
+/// because they share many features, such as mass and
+/// collision shape.
+/// If you have N different families of shapes in your 
+/// granular simulations (ex. 50% of particles are large
+/// spheres, 25% are small spheres and 25% are polihedrons)
+/// you can simply add three ChParticlesClones objects to the 
+/// ChSystem. This would be more efficient anyway than
+/// creating all shapes as ChBody.
+
+class ChApi ChParticlesClones : public ChIndexedParticles 
+{
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChParticlesClones,ChIndexedParticles);
+
+private:
+			//
+	  		// DATA
+			//
+	
+						// The particles: 
+	std::vector<ChAparticle*> particles;				
+	
+						// Shared mass of particles
+	ChSharedMassBody		 particle_mass;
+
+						// Sample collision model
+	ChCollisionModel*		 particle_collision_model;
+
+
+	bool do_collide;
+	bool do_limit_speed;
+	bool do_sleep;
+
+						// data for surface contact and impact (can be shared):
+	ChSharedPtr<ChMaterialSurface> matsurface;
+	
+	float max_speed;	// limit on linear speed (useful for VR & videagames)
+	float max_wvel;		// limit on angular vel. (useful for VR & videagames)
+
+	float  sleep_time;
+	float  sleep_minspeed;
+	float  sleep_minwvel;
+	float  sleep_starttime;
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a cluster of particles.
+				/// By default the cluster will contain 0 particles.
+	ChParticlesClones ();
+
+				/// Destructor
+	~ChParticlesClones ();
+
+				/// Copy from another ChParticlesClones. 
+	void Copy(ChParticlesClones* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+
+				/// Enable/disable the collision for this cluster of particles.
+				/// After setting ON, remember RecomputeCollisionModel()
+				/// before anim starts (it is not automatically
+				/// recomputed here because of performance issues.)
+	void  SetCollide (bool mcoll);
+	bool  GetCollide() {return do_collide;}
+
+				/// Trick. Set the maximum linear speed (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations, because it reduces the risk of bad collision detection.
+				/// The realism is limited, but the simulation is more stable.
+	void SetLimitSpeed    (bool mlimit) { do_limit_speed = mlimit;};
+	bool GetLimitSpeed()  {return do_limit_speed;};
+
+
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Get the number of particles
+	unsigned int GetNparticles() {return particles.size();}
+
+				/// Access the N-th particle 
+	ChParticleBase& GetParticle(unsigned int n) { assert(n<particles.size()); return *particles[n];}
+				
+				/// Resize the particle cluster. Also clear the state of 
+				/// previously created particles, if any.
+				/// NOTE! Define the sample collision shape using GetCollisionModel()->...
+				/// before adding particles!
+	void ResizeNparticles(int newsize);
+
+				/// Add a new particle to the particle cluster, passing a 
+				/// coordinate system as initial state.
+				/// NOTE! Define the sample collision shape using GetCollisionModel()->...
+				/// before adding particles!
+	void AddParticle(ChCoordsys<double> initial_state = CSYSNORM);
+
+
+
+			 // Override/implement LCP system functions of ChPhysicsItem
+			 // (to assembly/manage data for LCP system solver)
+
+				/// Sets the 'fb' part of the encapsulated ChLcpVariablesBody to zero.
+	void VariablesFbReset();
+
+				/// Adds the current forces applied to body (including gyroscopic torque) in
+				/// encapsulated ChLcpVariablesBody, in the 'fb' part: qf+=forces*factor
+	void VariablesFbLoadForces(double factor=1.);
+
+				/// Initialize the 'qb' part of the ChLcpVariablesBody with the 
+				/// current value of body speeds. Note: since 'qb' is the unknown of the LCP, this
+				/// function seems unuseful, unless used before VariablesFbIncrementMq()
+	void VariablesQbLoadSpeed();
+
+				/// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
+				/// with v_old using VariablesQbLoadSpeed, this method can be used in 
+				/// timestepping schemes that do: M*v_new = M*v_old + forces*dt
+	void VariablesFbIncrementMq();
+
+				/// Fetches the body speed (both linear and angular) from the
+				/// 'qb' part of the ChLcpVariablesBody (does not updates the full body&markers state)
+				/// and sets it as the current body speed.
+				/// If 'step' is not 0, also computes the approximate acceleration of
+				/// the body using backward differences, that is  accel=(new_speed-old_speed)/step.
+				/// Mostly used after the LCP provided the solution in ChLcpVariablesBody .
+	void VariablesQbSetSpeed(double step=0.);
+
+				/// Increment body position by the 'qb' part of the ChLcpVariablesBody,
+				/// multiplied by a 'step' factor.
+				///     pos+=qb*step
+				/// If qb is a speed, this behaves like a single step of 1-st order
+				/// numerical integration (Eulero integration).
+				/// Does not automatically update markers & forces.
+	void VariablesQbIncrementPosition(double step);
+
+
+				/// Tell to a system descriptor that there are variables of type
+				/// ChLcpVariables in this object (for further passing it to a LCP solver)
+				/// Basically does nothing, but maybe that inherited classes may specialize this.
+	virtual void InjectVariables(ChLcpSystemDescriptor& mdescriptor);
+
+
+
+ 
+
+
+			   // Other functions
+
+				/// Set no speed and no accelerations (but does not change the position)
+	void SetNoSpeedNoAcceleration();
+
+				/// Acess the collision model for the collision engine: this is the 'sample'
+				/// collision model that is used by all particles.
+				/// To get a non-null pointer, remember to SetCollide(true), before.
+	ChCollisionModel* GetCollisionModel() {return particle_collision_model;}
+			
+				/// Synchronize coll.models coordinates and bounding boxes to the positions of the particles.
+	virtual void SyncCollisionModels();
+	virtual void AddCollisionModelsToSystem();
+	virtual void RemoveCollisionModelsFromSystem();
+
+				/// After you added collision shapes to the sample coll.model (the one
+				/// that you access with GetCollisionModel() ) you need to call this
+				/// function so that all collision models of particles will reference the sample coll.model.
+	void UpdateParticleCollisionModels();
+
+
+				/// Access the material surface properties, referenced by this 
+				/// particle cluster. The material surface contains properties such as friction, etc. 
+				/// The ChMaterialSurface can be a shared object! (by default, each cluster creates its
+				/// own as soon as instanced, but later the material object can be replaced).
+	ChSharedPtr<ChMaterialSurface>& GetMaterialSurface() {return this->matsurface;}
+				/// Set the material surface properties by passing a ChMaterialSurface object.
+				/// Thank to smart pointers, the one that was previously used is replaced and,
+				/// if needed, it is automatically dereferenced and deleted.
+				/// The ChMaterialSurface can be a shared object! (by default, each cluster creates its
+				/// own as soon as instanced, but later the material object can be replaced).
+	void SetMaterialSurface(ChSharedPtr<ChMaterialSurface>& mnewsurf) {this->matsurface = mnewsurf;}
+
+
+				/// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+	float  GetImpactC() {return this->matsurface->GetRestitution();}
+	void   SetImpactC(float mval) {this->matsurface->SetRestitution(mval);}
+				/// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+	float  GetImpactCt() {return 0;}
+	void   SetImpactCt(float mval) {}
+				/// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+	float  GetKfriction() {return this->matsurface->GetKfriction();}
+	void   SetKfriction(float mval) {this->matsurface->SetKfriction(mval);}
+				/// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+	float  GetSfriction() {return this->matsurface->GetSfriction();}
+	void   SetSfriction(float mval) {this->matsurface->SetSfriction(mval);}
+				/// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+	void   SetFriction(float mval) {this->matsurface->SetFriction(mval);}
+				/// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+	float  GetRollingFriction() {return this->matsurface->GetRollingFriction();}
+	void   SetRollingFriction(float mval) {this->matsurface->SetRollingFriction(mval);}
+				/// FOR BACKWARD COMPATIBILITY ONLY. Better use: GetMaterialSurface()->Get...  etc.etc.
+	float  GetSpinningFriction() {return this->matsurface->GetSpinningFriction();}
+	void   SetSpinningFriction(float mval) {this->matsurface->SetSpinningFriction(mval);}
+
+
+				/// Mass of each particle. Must be positive.
+	void   SetMass (double newmass) { if (newmass>0.) this->particle_mass.SetBodyMass(newmass);}
+	double GetMass() {return this->particle_mass.GetBodyMass();}
+
+				/// Set the inertia tensor of each particle
+	void SetInertia (ChMatrix33<>* newXInertia);
+				/// Set the diagonal part of the inertia tensor of each particle
+	void SetInertiaXX (Vector iner);
+				/// Get the diagonal part of the inertia tensor of each particle
+	Vector GetInertiaXX();
+				/// Set the extradiagonal part of the inertia tensor of each particle
+				/// (xy, yz, zx values, the rest is symmetric)
+	void SetInertiaXY (Vector iner);
+				/// Get the extradiagonal part of the inertia tensor of each particle
+				/// (xy, yz, zx values, the rest is symmetric)
+	Vector GetInertiaXY();
+
+
+				/// Trick. Set the maximum linear speed (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations, because it reduces the risk of bad collision detection.
+				/// This speed limit is active only if you set  SetLimitSpeed(true);
+	void   SetMaxSpeed(float m_max_speed) {max_speed = m_max_speed;}
+	float  GetMaxSpeed () {return max_speed;}
+
+				/// Trick. Set the maximum angualar speed (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations, because it reduces the risk of bad collision detection.
+				/// This speed limit is active only if you set  SetLimitSpeed(true);
+	void   SetMaxWvel(float m_max_wvel) {max_wvel = m_max_wvel;}
+	float  GetMaxWvel () {return max_wvel;}
+
+				/// When this function is called, the speed of particles is clamped
+				/// into limits posed by max_speed and max_wvel  - but remember to
+				/// put the body in the SetLimitSpeed(true) mode.
+	void ClampSpeed();
+
+				/// Set the amount of time which must pass before going automatically in
+				/// sleep mode when the body has very small movements.
+	void   SetSleepTime(float m_t) {sleep_time = m_t;}
+	float GetSleepTime () {return sleep_time;}
+
+				/// Set the max linear speed to be kept for 'sleep_time' before freezing.
+	void   SetSleepMinSpeed(float m_t) {sleep_minspeed = m_t;}
+	float GetSleepMinSpeed () {return sleep_minspeed;}
+
+				/// Set the max linear speed to be kept for 'sleep_time' before freezing.
+	void   SetSleepMinWvel(float m_t) {sleep_minwvel = m_t;}
+	float GetSleepMinWvel () {return sleep_minwvel;}
+
+
+
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the particles 
+	virtual void Update (double mytime);
+				/// Update all auxiliary data of the particles
+	virtual void Update ();
+
+				/// Tells to the associated external object ChExternalObject() ,if any,
+				/// that its 3D shape must be updated in order to syncronize to ChBody
+				/// coordinates
+	void UpdateExternalGeometry ();
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+typedef ChSharedPtr<ChParticlesClones> ChSharedParticlesClonesPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChPhysicsItem.cpp b/SRC/ChronoEngine/physics/ChPhysicsItem.cpp
new file mode 100644
index 0000000..80a7538
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChPhysicsItem.cpp
@@ -0,0 +1,108 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChPhysicsItem.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChPhysicsItem.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChPhysicsItem> a_registration_ChPhysicsItem;
+
+
+
+void ChPhysicsItem::Copy(ChPhysicsItem* source)
+{
+    // first copy the parent class data...
+    ChObj::Copy(source);
+
+	// copy other class data
+	system=0; // do not copy - must be initialized with insertion in system.
+
+}
+
+
+
+
+void ChPhysicsItem::GetTotalAABB(ChVector<>& bbmin, ChVector<>& bbmax)
+{
+	bbmin.Set(-1e200, -1e200, -1e200);
+	bbmax.Set( 1e200,  1e200,  1e200);
+}
+				
+void ChPhysicsItem::GetCenter(ChVector<>& mcenter)
+{
+	ChVector<> mmin, mmax;
+	this->GetTotalAABB(mmin, mmax);
+	mcenter = (mmin+mmax)*0.5;
+}
+
+
+/////////
+///////// FILE I/O
+/////////
+
+
+
+void ChPhysicsItem::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+		// serialize parent class too
+	ChObj::StreamOUT(mstream);
+
+		// stream out all member data
+	
+}
+
+void ChPhysicsItem::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+		// deserialize parent class too
+	ChObj::StreamIN(mstream);
+
+		// stream in all member data
+
+}
+
+
+
+
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChPhysicsItem.h b/SRC/ChronoEngine/physics/ChPhysicsItem.h
new file mode 100644
index 0000000..f15ccb6
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChPhysicsItem.h
@@ -0,0 +1,306 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHPHYSICSITEM_H
+#define CHPHYSICSITEM_H
+
+///////////////////////////////////////////////////
+//
+//   ChPhysicsItem.h
+//
+//
+//   Base class for items that can contain objects
+//   of ChLcpVariables or ChLcpConstraints, such as 
+//   rigid bodies, mechanical joints, etc.
+//
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChFrame.h"
+#include "physics/ChObject.h"
+#include "lcp/ChLcpSystemDescriptor.h"
+
+
+namespace chrono
+{
+
+// Forward references
+class ChSystem;
+
+
+/// Base class for items that can contain objects
+/// of ChLcpVariables or ChLcpConstraints, such as 
+/// rigid bodies, mechanical joints, etc.
+
+
+class ChApi ChPhysicsItem :  public ChObj {
+
+	CH_RTTI(ChPhysicsItem,ChObj);
+
+protected:
+
+				//
+	  			// DATA
+				//
+
+	ChSystem *system;	  // parent system
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+	ChPhysicsItem () { system = 0;};
+	virtual ~ChPhysicsItem () {}; 
+	virtual void Copy(ChPhysicsItem* source);
+
+public:
+		//
+	  	// FUNCTIONS
+		//
+
+
+
+				/// Get the pointer to the parent ChSystem()
+	ChSystem* GetSystem () { return system;}
+
+				/// Set the pointer to the parent ChSystem()
+	virtual void SetSystem (ChSystem* m_system) {system= m_system;}
+
+
+
+
+		// --- INTERFACES --- 
+		// inherited classes might/should implement 
+		// some of the following functions.
+
+
+			// Collisions - override these in child classes if needed
+			// 
+
+				/// Tell if the object is subject to collision.
+				/// Only for interface; child classes may override this, using internal flags.
+	virtual bool GetCollide() {return false;};
+
+				/// If this physical item contains one or more collision models,	
+				/// sinchronize their coordinates and bounding boxes to the state of the item.
+	virtual void SyncCollisionModels() {};
+
+				/// If this physical item contains one or more collision models,	
+				/// add them to the system's collision engine.
+	virtual void AddCollisionModelsToSystem() {};
+
+				/// If this physical item contains one or more collision models,	
+				/// remove them from the system's collision engine.
+	virtual void RemoveCollisionModelsFromSystem() {};
+
+			// Functions used by domain decomposition
+
+				/// Get the entire AABB axis-aligned bounding box of the object.
+				/// The AABB must enclose the collision models, if any.
+				/// By default is infinite AABB.
+				/// Should be overridden by child classes.
+	virtual void GetTotalAABB(ChVector<>& bbmin, ChVector<>& bbmax);
+
+				/// Get a symbolic 'center' of the object. By default this 
+				/// function returns the center of the AABB.
+				/// It could be overridden by child classes, anyway it must 
+				/// always get a point that must be inside AABB.
+	virtual void GetCenter(ChVector<>& mcenter);
+
+				/// Method to deserialize only the state (position, speed)
+				/// Must be implemented by child classes. 
+	virtual void StreamINstate(ChStreamInBinary&) {};
+				/// Method to serialize only the state (position, speed)
+				/// Must be implemented by child classes. 
+	virtual void StreamOUTstate(ChStreamOutBinary&) {};				
+
+
+			// UPDATING  - child classes may implement these functions
+			//
+
+				/// This is an important function, which is called by the 
+				/// owner ChSystem at least once per integration step.
+				/// It may update all auxiliary data of the item, such as
+				/// matrices if any, etc., depending on the current coordinates.
+				/// The inherited classes, for example the ChLinkMask, often
+				/// implement specialized versions of this Update(time) function,
+				/// because they might need to update inner states, forces, springs, etc.
+				/// This base version, by default, simply updates the item's time.
+	virtual void Update (double mytime) { this->ChTime = mytime; };
+
+				/// As above, but does not require updating of time-dependent 
+				/// data. By default, calls Update(mytime) using item's current time. 
+	virtual void Update() {Update(this->ChTime);}
+
+
+				/// Set zero speed (and zero accelerations) in state, without changing the position.
+				/// Child classes should impement this function if GetDOF() > 0.
+				/// It is used by owner ChSystem for some static analysis.
+	void SetNoSpeedNoAcceleration() {};
+
+
+			// STATISTICS  - override these in child classes if needed
+			// 
+
+				/// Get the number of scalar coordinates (variables), if any, in this item 
+	virtual int GetDOF  ()   {return 0;}
+				/// Get the number of scalar constraints, if any, in this item 
+	virtual int GetDOC  ()   {return GetDOC_c()+GetDOC_d();}
+				/// Get the number of scalar constraints, if any, in this item (only bilateral constr.)
+	virtual int GetDOC_c  () {return 0;}
+				/// Get the number of scalar constraints, if any, in this item (only unilateral constr.)
+	virtual int GetDOC_d  () {return 0;}
+
+
+			// LCP SYSTEM FUNCTIONS   
+			//
+			// These are the functions that are used to manage ChLcpConstraint and/or ChLcpVariable 
+			// objects that are sent to the system solver.
+			// The children classes, inherited from ChPhysicsItem, can implement them (by default,
+			// the base ChPhysicsItem does not introduce any variable nor any constraint).
+
+				/// Sets the 'fb' part (the known term) of the encapsulated ChLcpVariables to zero.
+	virtual void VariablesFbReset() {};
+
+				/// Adds the current forces (applied to item) into the
+				/// encapsulated ChLcpVariables, in the 'fb' part: qf+=forces*factor
+	virtual void VariablesFbLoadForces(double=1.) {};
+
+				/// Initialize the 'qb' part of the ChLcpVariables with the 
+				/// current value of speeds. Note: since 'qb' is the unknown of the LCP, this
+				/// function seems unuseful, unless used before VariablesFbIncrementMq()
+	virtual void VariablesQbLoadSpeed() {};
+
+				/// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
+				/// with v_old using VariablesQbLoadSpeed, this method can be used in 
+				/// timestepping schemes that do: M*v_new = M*v_old + forces*dt
+	virtual void VariablesFbIncrementMq() {};
+
+				/// Fetches the item speed (ex. linear and angular vel.in rigid bodies) from the
+				/// 'qb' part of the ChLcpVariables and sets it as the current item speed.
+				/// If 'step' is not 0, also should compute the approximate acceleration of
+				/// the item using backward differences, that is  accel=(new_speed-old_speed)/step.
+				/// Mostly used after the LCP provided the solution in ChLcpVariables.
+	virtual void VariablesQbSetSpeed(double=0.) {};
+
+				/// Increment item positions by the 'qb' part of the ChLcpVariables,
+				/// multiplied by a 'step' factor.
+				///     pos+=qb*step
+				/// If qb is a speed, this behaves like a single step of 1-st order
+				/// numerical integration (Eulero integration).
+	virtual void VariablesQbIncrementPosition(double) {};
+
+				/// Tell to a system descriptor that there are variables of type
+				/// ChLcpVariables in this object (for further passing it to a LCP solver)
+				/// Basically does nothing, but maybe that inherited classes may specialize this.
+	virtual void InjectVariables(ChLcpSystemDescriptor&) {};
+
+
+
+				/// Tell to a system descriptor that there are contraints of type
+				/// ChLcpConstraint in this object (for further passing it to a LCP solver)
+				/// Basically does nothing, but maybe that inherited classes may specialize this.
+	virtual void InjectConstraints(ChLcpSystemDescriptor&) {};
+
+				/// Sets to zero the known term (b_i) of encapsulated ChLcpConstraints
+	virtual void ConstraintsBiReset() {};
+
+				/// Adds the current C (constraint violation) to the known term (b_i) of
+				/// encapsulated ChLcpConstraints
+	virtual void ConstraintsBiLoad_C(double=1., double=0.1, bool=false) {};
+
+				/// Adds the current Ct (partial t-derivative, as in C_dt=0-> [Cq]*q_dt=-Ct)
+				/// to the known term (b_i) of encapsulated ChLcpConstraints
+	virtual void ConstraintsBiLoad_Ct(double=1.) {};
+
+				/// Adds the current Qc (the vector of C_dtdt=0 -> [Cq]*q_dtdt=Qc )
+				/// to the known term (b_i) of encapsulated ChLcpConstraints
+	virtual void ConstraintsBiLoad_Qc(double=1.) {};
+
+				/// Adds the current link-forces, if any, (caused by springs, etc.) to the 'fb' vectors
+				/// of the ChLcpVariables referenced by encapsulated ChLcpConstraints
+	virtual void ConstraintsFbLoadForces(double=1.) {};
+
+				/// Adds the current jacobians in encapsulated ChLcpConstraints
+	virtual void ConstraintsLoadJacobians() {};
+
+				/// Fills the solution of the constraint (the lagrangian multiplier l_i)
+				/// with an initial guess, if any. This can be used for warm-starting the 
+				/// LCP solver before starting the solution of the SPEED problem, if some 
+				/// approximate solution of constraint impulese l_i already exist (ex. cached
+				/// from a previous LCP execution)
+				/// When implementing this in sub classes, if no guess is available, set l_i as 0.
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution() {};
+
+				/// As ConstraintsLiLoadSuggestedSpeedSolution(), but for the POSITION problem.
+	virtual void ConstraintsLiLoadSuggestedPositionSolution() {};
+
+				/// After the LCP solver has found the l_i lagangian multipliers for the
+				/// SPEED problem, this function will be called to store the solutions in a
+				/// cache (to be implemented in ChLink sub classes) so that it can be later retrieved with
+				/// ConstraintsLiLoadSuggestedSpeedSolution(). If you do not plan to implement a l_i cache,
+				/// just do not override this function in child classes and do nothing.
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution() {};
+
+				/// As ConstraintsLiFetchSuggestedSpeedSolution(), but for the POSITION problem.
+	virtual void ConstraintsLiFetchSuggestedPositionSolution() {};
+
+				/// Fetches the reactions from the lagrangian multiplier (l_i)
+				/// of encapsulated ChLcpConstraints. 
+				/// Mostly used after the LCP provided the solution in ChLcpConstraints.
+				/// Also, should convert the reactions obtained from dynamical simulation,
+				/// from link space to intuitive react_force and react_torque.
+	virtual void ConstraintsFetch_react(double=1.) {};
+
+
+				/// Tell to a system descriptor that there are items of type
+				/// ChLcpKstiffness in this object (for further passing it to a LCP solver)
+				/// Basically does nothing, but maybe that inherited classes may specialize this.
+	virtual void InjectKRMmatrices(ChLcpSystemDescriptor&) {};
+
+				/// Adds the current stiffness K and damping R and mass M matrices in encapsulated
+				/// ChLcpKstiffness item(s), if any. The K, R, M matrices are added with scaling 
+				/// values Kfactor, Rfactor, Mfactor.  
+	virtual void KRMmatricesLoad(double, double, double) {};
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	virtual void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	virtual void StreamOUT(ChStreamOutBinary& mstream);
+
+
+};
+
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChProbe.cpp b/SRC/ChronoEngine/physics/ChProbe.cpp
new file mode 100644
index 0000000..684d5f6
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChProbe.cpp
@@ -0,0 +1,78 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChProbe.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <math.h>
+
+#include "physics/ChProbe.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChExternalObject.h"
+
+namespace chrono 
+{
+
+
+
+/////////////////////////////////////////////////////////
+/// 
+///   CLASS
+///
+///
+
+
+
+
+ChProbe::ChProbe()
+{
+	this->SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+}
+
+ChProbe::~ChProbe()
+{
+}
+
+void ChProbe::Copy(ChProbe* source)
+{
+	// first copy the parent class data...
+	ChObj::Copy(source);
+	
+	// copy other data..
+
+}
+
+void ChProbe::Record(double mtime)
+{
+	if (GetExternalObject())
+		GetExternalObject()->onChronoProbeRecord(mtime);
+
+}
+
+void ChProbe::Reset()
+{
+	if (GetExternalObject())
+		GetExternalObject()->onChronoProbeReset();
+
+}
+
+
+} // END_OF_NAMESPACE____
+
+////// end
diff --git a/SRC/ChronoEngine/physics/ChProbe.h b/SRC/ChronoEngine/physics/ChProbe.h
new file mode 100644
index 0000000..520aa3e
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChProbe.h
@@ -0,0 +1,73 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHPROBE_H
+#define CHPROBE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChProbe.h
+//
+//   Class for probes
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "physics/ChObject.h"
+
+
+namespace chrono 
+{
+
+///
+/// Class for probe objects, used to record data during
+/// simulations.  
+///
+/// The ChProbe::Record() method will be automatically called
+/// once per time step, during simulation.
+///
+
+class ChApi ChProbe : public ChObj {
+
+public:
+	ChProbe();
+	~ChProbe();
+	
+	void Copy(ChProbe* source);
+
+	//
+	// FUNCTIONS
+	//
+			// Record the value.
+			// Note that X and Y variables must be already set, using the
+			// probe data. 
+			// Usually mtime is used for X var (default), while a
+			// script is used to specify the Y  variable.
+			// The Record() is called for each integration step, by the 
+			// system object which contains all probes.
+	void Record(double mtime);	
+
+			// if some data is recorded, delete.
+	void Reset();
+};
+		
+
+} // END_OF_NAMESPACE____
+
+#endif  // END of header
diff --git a/SRC/ChronoEngine/physics/ChProplist.h b/SRC/ChronoEngine/physics/ChProplist.h
new file mode 100644
index 0000000..0d90132
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChProplist.h
@@ -0,0 +1,58 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHPROPLIST_H
+#define CHPROPLIST_H
+
+//////////////////////////////////////////////////
+//  
+//   ChProplist.h
+//
+//   Property list
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChLists.h"
+
+
+namespace chrono 
+{
+
+
+//  To build a tree list of properties for objects
+
+class chjs_propdata {
+public:
+	char propname[100];
+	char label[100];
+	ChList<chjs_propdata> children;
+	int haschildren;
+};
+
+class chjs_fullnamevar {
+public:
+	char propname[200];
+	char label[100];
+	int active;
+	void* script;		// for example, points to already-compiled Javascript to fetch var
+};
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChProximityContainerBase.cpp b/SRC/ChronoEngine/physics/ChProximityContainerBase.cpp
new file mode 100644
index 0000000..3ef0e70
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChProximityContainerBase.cpp
@@ -0,0 +1,40 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChProximityContainerBase.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChProximityContainerBase.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegisterABSTRACT<ChProximityContainerBase> a_registration_ChProximityContainerBase;
+ 
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChProximityContainerBase.h b/SRC/ChronoEngine/physics/ChProximityContainerBase.h
new file mode 100644
index 0000000..8315b0b
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChProximityContainerBase.h
@@ -0,0 +1,168 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHPROXIMITYCONTAINERBASE_H
+#define CHPROXIMITYCONTAINERBASE_H
+
+///////////////////////////////////////////////////
+//
+//   ChProximityContainerBase.h
+//
+//   Class for container of many contacts
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChContact.h"
+#include "physics/ChMaterialCouple.h"
+#include "collision/ChCCollisionInfo.h"
+
+namespace chrono
+{
+
+/// Class to be used as a callback interface for some user defined
+/// action to be taken each time a proximity info is added to the container.
+
+class ChApi ChAddProximityCallback
+{
+public:
+			/// Callback, used to report proximity pairs being added to the container.
+			/// This must be implemented by a child class of ChAddProximityCallback
+	virtual void ProximityCallback (const  collision::ChCollisionModel& modA, ///< get contact model 1
+									const  collision::ChCollisionModel& modB  ///< get contact model 2
+								) = 0;			
+};
+
+
+/// Class to be used as a callback interface for some user defined
+/// action to be taken for each proximity pair (already added to the container).
+/// The user should implement an inherited class and
+/// implement a custom ReportProximityCallback() function.
+
+class ChApi ChReportProximityCallback
+{
+public:
+			/// Callback, used to report contact points already added to the container.
+			/// This must be implemented by a child class of ChReportContactCallback.
+			/// If returns false, the contact scanning will be stopped.
+	virtual bool ReportProximityCallback (
+					collision::ChCollisionModel* modA,	///< get model A (note: some containers may not support it and could be zero!)
+					collision::ChCollisionModel* modB	///< get model B (note: some containers may not support it and could be zero!)
+										) = 0;			
+};
+
+
+
+
+
+///
+/// Class representing the interface for containers of proximity pairs,
+/// that is pairs of collision models that have been obtained from the
+/// broadphase collision.
+/// There might be implementations of this interface
+/// in form of plain CPU linked lists of objects (ex. springs or similar
+/// forcefields for cloth simulation etc.) or highly optimized GPU buffers, 
+/// etc. etc. 
+/// This is only the basic interface with the features that are in common.
+///
+
+class ChApi ChProximityContainerBase : public ChPhysicsItem {
+
+	CH_RTTI(ChProximityContainerBase, ChPhysicsItem);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	ChAddProximityCallback* add_proximity_callback;	
+	ChReportProximityCallback* report_proximity_callback; 
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChProximityContainerBase () 
+				{ 
+					add_proximity_callback =0;
+					report_proximity_callback =0;
+				};
+
+	virtual ~ChProximityContainerBase () {};
+
+				//
+	  			// FUNCTIONS 
+				//
+
+					/// Tell the number of added proximity pairs. To be implemented by child classes.
+	virtual int  GetNproximities  () = 0;
+
+					/// Remove (delete) all contained proximity pairs. To be implemented by child classes.
+	virtual void RemoveAllProximities() = 0;
+
+					/// The collision system will call BeginAddProximity() before adding
+					/// all proximity pairs (for example with AddProximity() or similar). By default
+					/// it deletes all previous contacts. Custom more efficient implementations
+					/// might reuse contacts if possible.
+	virtual void BeginAddProximities() { RemoveAllProximities(); }
+
+					/// Add a proximity pair between two collision models, storing it into this container.
+					/// To be implemented by child classes.
+					/// Some specialized child classes (ex. one that uses GPU buffers)
+					/// could implement also other more efficient functions to add many proximity pairs
+					/// in a batch (so that, for example, a special GPU collision system can exploit it);
+					/// yet most collision system might still fall back to this function if no other 
+					/// specialized add-functions are found.
+	virtual void AddProximity(collision::ChCollisionModel* modA, ///< get contact model 1
+							  collision::ChCollisionModel* modB  ///< get contact model 2
+							  ) = 0;
+
+					/// The collision system will call this after adding
+					/// all pairs (for example with AddProximity() or similar). By default
+					/// it does nothing.
+	virtual void EndAddProximities() {};
+
+
+
+
+					/// Sets a callback to be used each time a proximity pair is 
+					/// added to the container. Note that not all child classes can
+					/// support this function in all circumstances (example, the GPU container
+					/// won't launch the callback for all its points because of performance optimization)
+	void SetAddProximityCallback(ChAddProximityCallback* mcallback) {add_proximity_callback = mcallback;}
+
+					/// Scans all the contacts and for each proximity pair executes the ReportProximityCallback()
+					/// function of the user object inherited from ChReportContactCallback.
+					/// Child classes of ChContactContainerBase should try to implement this (although
+					/// in some highly-optimized cases as in ChContactContainerGPU it could be impossible to
+					/// report all contacts).
+	virtual void ReportAllProximities(ChReportProximityCallback* mcallback) =0;
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChProximityContainerSPH.cpp b/SRC/ChronoEngine/physics/ChProximityContainerSPH.cpp
new file mode 100644
index 0000000..08b1de3
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChProximityContainerSPH.cpp
@@ -0,0 +1,288 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChProximityContainerMeshless.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+ 
+  
+#include "physics/ChProximityContainerSPH.h"
+#include "physics/ChMatterSPH.h"
+#include "physics/ChSystem.h"
+#include "physics/ChBody.h"
+#include "collision/ChCModelBulletNode.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+using namespace collision;
+using namespace geometry;
+
+
+
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChProximityContainerSPH> a_registration_ChProximityContainerSPH;
+ 
+
+ChProximityContainerSPH::ChProximityContainerSPH ()
+{ 
+	proximitylist.clear();
+	n_added = 0;
+}
+
+
+ChProximityContainerSPH::~ChProximityContainerSPH ()
+{
+	std::list<ChProximitySPH*>::iterator iterproximity = proximitylist.begin();
+	while(iterproximity != proximitylist.end())
+	{
+		delete (*iterproximity);
+		(*iterproximity) = 0;
+		++iterproximity;
+		//proximitylist.erase(iterproximity); //no! do later with clear(), all together
+	}
+	proximitylist.clear();
+
+	lastproximity = proximitylist.begin();
+	n_added = 0;
+}
+
+
+
+void ChProximityContainerSPH::RemoveAllProximities()
+{
+	std::list<ChProximitySPH*>::iterator iterproximity = proximitylist.begin();
+	while(iterproximity != proximitylist.end())
+	{
+		delete (*iterproximity);
+		(*iterproximity) = 0;
+		++iterproximity;
+		//proximitylist.erase(iterproximity); //no! do later with clear(), all together
+	}
+	proximitylist.clear();
+
+	lastproximity = proximitylist.begin();
+	n_added = 0;
+}
+
+
+void ChProximityContainerSPH::BeginAddProximities()
+{
+	lastproximity = proximitylist.begin();
+	n_added = 0;
+}
+
+void ChProximityContainerSPH::EndAddProximities()
+{
+	// remove proximities that are beyond last proximity
+	while (lastproximity != proximitylist.end())
+	{
+		delete (*lastproximity);
+		lastproximity = proximitylist.erase(lastproximity);
+	}
+}
+
+
+void ChProximityContainerSPH::AddProximity(
+							  collision::ChCollisionModel* modA, 
+							  collision::ChCollisionModel* modB  
+							  )
+{
+	// Fetch the frames of that proximity and other infos
+
+	bool fixedA = false;
+	bool fixedB = false;
+
+	ChModelBulletNode* mmpaA = dynamic_cast<ChModelBulletNode*>(modA);
+	
+	ChModelBulletNode* mmpaB = dynamic_cast<ChModelBulletNode*>(modB);
+
+	if (!(mmpaA && mmpaB))
+		return;
+
+	if ((fixedA && fixedB))
+		return;
+
+	// Launch the proximity callback, if implemented by the user
+
+	if (this->add_proximity_callback)
+	{
+		this->add_proximity_callback->ProximityCallback(*modA, *modB);
+	}
+
+	// %%%%%%% Create and add a ChProximitySPH object 
+
+	if (lastproximity != proximitylist.end())
+	{
+		// reuse old proximity pairs
+		(*lastproximity)->Reset(mmpaA, mmpaB);
+						
+		lastproximity++;
+	}
+	else
+	{
+		// add new proximity
+		ChProximitySPH* mp = new ChProximitySPH( mmpaA, mmpaB);
+		
+		proximitylist.push_back(mp);
+		lastproximity = proximitylist.end();
+	}
+	n_added++;
+
+	
+}
+
+
+
+void ChProximityContainerSPH::ReportAllProximities(ChReportProximityCallback* mcallback)
+{
+	std::list<ChProximitySPH*>::iterator iterproximity = proximitylist.begin();
+	while(iterproximity != proximitylist.end())
+	{
+		bool proceed = mcallback->ReportProximityCallback(
+					(*iterproximity)->GetModelA(), 
+					(*iterproximity)->GetModelB()  
+					);
+		if (!proceed) 
+			break;
+		++iterproximity;
+	}
+}
+
+
+////////// LCP INTERFACES ////
+
+static double W_poly6(double r, double h)
+{
+	if (r < h)
+	{
+		return (315.0 / (64.0 * CH_C_PI * pow(h,9)) ) * pow((h*h - r*r) ,3);
+	}
+	else return 0;
+}
+
+
+static double W_sq_visco(double r, double h)
+{
+	if (r < h)
+	{
+		return (45.0 / (CH_C_PI * pow(h,6)) ) * (h - r);
+	}
+	else return 0;
+}
+
+static void W_gr_press(ChVector<>& Wresult, const ChVector<>& r, const double r_length, const double h)
+{
+	if (r_length < h)
+	{
+		Wresult = r;
+		Wresult *= -(45.0 / (CH_C_PI * pow(h,6)) ) * pow((h - r_length),2.0) ;
+	}
+	else Wresult = VNULL;
+}
+
+
+void ChProximityContainerSPH::AccumulateStep1()
+{
+	// Per-edge data computation
+	std::list<ChProximitySPH*>::iterator iterproximity = proximitylist.begin();
+	while(iterproximity != proximitylist.end())
+	{
+		ChMatterSPH* mmatA = (ChMatterSPH*)(*iterproximity)->GetModelA()->GetPhysicsItem();
+		ChMatterSPH* mmatB = (ChMatterSPH*)(*iterproximity)->GetModelB()->GetPhysicsItem();
+		ChNodeSPH* mnodeA =(ChNodeSPH*) mmatA->GetNode ( ((ChModelBulletNode*)(*iterproximity)->GetModelA())->GetNodeId()  );
+		ChNodeSPH* mnodeB =(ChNodeSPH*) mmatB->GetNode ( ((ChModelBulletNode*)(*iterproximity)->GetModelB())->GetNodeId()  );
+	
+		ChVector<> x_A  = mnodeA->GetPos();
+		ChVector<> x_B  = mnodeB->GetPos();
+
+		ChVector<> r_BA = x_B  - x_A ;
+		double dist_BA = r_BA.Length();
+
+		double W_k_poly6 =  W_poly6( dist_BA, mnodeA->GetKernelRadius() );
+
+		// increment data of connected nodes
+
+		mnodeA->density += mnodeB->GetMass() * W_k_poly6;
+		mnodeB->density += mnodeA->GetMass() * W_k_poly6;
+
+		++iterproximity;
+	}
+
+}
+
+void ChProximityContainerSPH::AccumulateStep2()
+{
+	// Per-edge data computation (transfer stress to forces)
+	std::list<ChProximitySPH*>::iterator iterproximity = proximitylist.begin();
+	while(iterproximity != proximitylist.end())
+	{
+		ChMatterSPH* mmatA = (ChMatterSPH*)(*iterproximity)->GetModelA()->GetPhysicsItem();
+		ChMatterSPH* mmatB = (ChMatterSPH*)(*iterproximity)->GetModelB()->GetPhysicsItem();
+		ChNodeSPH* mnodeA =(ChNodeSPH*) mmatA->GetNode ( ((ChModelBulletNode*)(*iterproximity)->GetModelA())->GetNodeId()  );
+		ChNodeSPH* mnodeB =(ChNodeSPH*) mmatB->GetNode ( ((ChModelBulletNode*)(*iterproximity)->GetModelB())->GetNodeId()  );
+	
+		ChVector<> x_A  = mnodeA->GetPos();
+		ChVector<> x_B  = mnodeB->GetPos();
+
+		ChVector<> r_BA = x_B - x_A;
+		double dist_BA = r_BA.Length();
+
+		// increment pressure forces
+
+		ChVector<> W_k_press;
+		W_gr_press( W_k_press, r_BA, dist_BA, mnodeA->GetKernelRadius() );
+
+		double avg_press = 0.5*(mnodeA->pressure + mnodeB->pressure);
+	
+		ChVector<> pressureForceA  =   W_k_press * mnodeA->volume * avg_press * mnodeB->volume;
+		mnodeA->UserForce += pressureForceA;
+
+		//ChVector<> pressureForceB  = - W_k_press * mnodeB->volume * avg_dens * mnodeA->volume;
+		mnodeB->UserForce -= pressureForceA;
+
+
+		// increment viscous forces..
+
+		double W_k_visc =  W_sq_visco( dist_BA, mnodeA->GetKernelRadius() );
+		ChVector<> velBA =  mnodeB->GetPos_dt() - mnodeA->GetPos_dt();
+
+		double avg_viscosity =  0.5*(mmatA->GetMaterial().Get_viscosity() + mmatB->GetMaterial().Get_viscosity());
+
+		ChVector<> viscforceBA =  velBA * ( mnodeA->volume * avg_viscosity * mnodeB->volume * W_k_visc );
+		mnodeA->UserForce += viscforceBA;
+		mnodeB->UserForce -= viscforceBA;
+
+
+		++iterproximity;
+	}
+
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/physics/ChProximityContainerSPH.h b/SRC/ChronoEngine/physics/ChProximityContainerSPH.h
new file mode 100644
index 0000000..36c8650
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChProximityContainerSPH.h
@@ -0,0 +1,176 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHPROXIMITYCONTAINERSPH_H
+#define CHPROXIMITYCONTAINERSPH_H
+
+///////////////////////////////////////////////////
+//
+//   ChProximityContainerSPH.h
+//
+//   Class for container of many proximity pairs for SPH (Smooth 
+//   Particle Hydrodinamics and similar meshless force computations), 
+//   as CPU typical linked list of ChProximitySPH objects
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChProximityContainerBase.h"
+#include "collision/ChCModelBulletNode.h"
+#include <list>
+
+namespace chrono
+{
+
+
+
+///
+/// Class for a proximity pair information in a SPH cluster 
+/// of particles - that is, an 'edge' topological connectivity in
+/// in a meshless FEM approach, like the Smoothed Particle Hydrodynamics.
+/// 
+
+class ChApi ChProximitySPH
+{
+public:
+	ChProximitySPH(collision::ChModelBulletNode* mmodA,	///< model A
+				   collision::ChModelBulletNode* mmodB)	///< model B
+	{
+		Reset(mmodA, mmodB);
+	}
+
+	virtual ~ChProximitySPH () {};
+
+				//
+	  			// FUNCTIONS
+				//
+
+					/// Initialize again this constraint.
+	virtual void Reset(	collision::ChModelBulletNode* mmodA,	///< model A
+						collision::ChModelBulletNode* mmodB) ///< model B
+	{
+		assert (mmodA);
+		assert (mmodB);
+
+		this->modA = mmodA;
+		this->modB = mmodB;
+	}
+
+					/// Get the collision model A, with point P1
+	virtual collision::ChCollisionModel* GetModelA() {return this->modA;}
+					/// Get the collision model B, with point P2
+	virtual collision::ChCollisionModel* GetModelB() {return this->modB;}
+
+private:
+				//
+	  			// DATA
+				//
+	collision::ChCollisionModel* modA;	///< model A
+	collision::ChCollisionModel* modB;  ///< model B
+};
+
+
+
+///
+/// Class for container of many proximity pairs for SPH (Smooth 
+/// Particle Hydrodinamics and similar meshless force computations), 
+/// as CPU typical linked list of ChProximitySPH objects.
+///
+
+class ChApi ChProximityContainerSPH : public ChProximityContainerBase {
+
+	CH_RTTI(ChProximityContainerSPH,ChProximityContainerBase);
+
+protected:
+				//
+	  			// DATA
+				//
+
+	std::list<ChProximitySPH*>   proximitylist; 
+
+	int n_added;
+
+	std::list<ChProximitySPH*>::iterator lastproximity;
+
+
+public:
+				//
+	  			// CONSTRUCTORS
+				//
+
+	ChProximityContainerSPH ();
+
+	virtual ~ChProximityContainerSPH ();
+
+
+
+				//
+	  			// FUNCTIONS
+				//
+
+
+					/// Tell the number of added contacts
+	virtual int GetNproximities  () {return n_added;}
+
+					/// Remove (delete) all contained contact data.
+	virtual void RemoveAllProximities();
+
+					/// The collision system will call BeginAddProximities() before adding
+					/// all pairs (for example with AddProximity() or similar). Instead of
+					/// simply deleting all list of the previous pairs, this optimized implementation
+					/// rewinds the link iterator to begin and tries to reuse previous pairs objects
+					/// until possible, to avoid too much allocation/deallocation.
+	virtual void BeginAddProximities();
+
+					/// Add a proximity SPH data between two collision models, if possible.
+	virtual void AddProximity(collision::ChCollisionModel* modA, ///< get contact model 1
+							  collision::ChCollisionModel* modB  ///< get contact model 2
+							  );
+
+					/// The collision system will call BeginAddContact() after adding
+					/// all contacts (for example with AddContact() or similar). This optimized version
+					/// purges the end of the list of contacts that were not reused (if any).
+	virtual void EndAddProximities();
+
+					/// Scans all the proximity pairs of SPH type and for each pair executes the ReportProximityCallback()
+					/// function of the user object inherited from ChReportProximityCallback.
+	virtual void ReportAllProximities(ChReportProximityCallback* mcallback);
+
+
+					// Perform some SPH per-edge initializations and accumulations of values 
+					// into the connected pairs of particles (summation into partcle's  J, Amoment, m_v, UserForce -viscous only- )
+					// Will be called by the ChMatterSPH item.
+	virtual void AccumulateStep1();
+
+					// Perform some SPH per-edge transfer of forces, given stress tensors in A B nodes
+					// Will be called by the ChMatterSPH item.
+	virtual void AccumulateStep2();
+	
+
+};
+
+
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChRef.cpp b/SRC/ChronoEngine/physics/ChRef.cpp
new file mode 100644
index 0000000..c080c5c
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChRef.cpp
@@ -0,0 +1,157 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChRef.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+#include "physics/ChRef.h"
+
+
+namespace chrono
+{
+
+
+////////////////////////////////////
+//
+// CLASS  ChRef
+//
+////////////////////////////////////
+
+
+
+
+
+////////////////////////////////////
+//
+// CLASS  ChRefFunctionSegment
+//
+////////////////////////////////////
+
+
+ChRefFunctionSegment::ChRefFunctionSegment(ChFunction* mrootf, char* myIDs)
+{
+	this->function= mrootf;
+	this->SetTreeIDs(myIDs);
+	this->RestoreReference(this->function);
+}
+
+bool ChRefFunctionSegment::RestoreReference(ChFunction* mrootf)
+{
+	// inherit parent behavoiur
+	ChRefFunction::RestoreReference(mrootf);
+
+				// default segment is root function, also for ID=""
+	this->function_segment = GetRootFunction();
+	if (!function_segment)
+		return (valid=false);
+
+
+	static char buffer[100];
+	int mpos =0;
+	int mbupos =0;
+	int mid =0;
+	while (treeIDs[mpos] !=0)
+	{
+		mbupos = 0;
+		while ((treeIDs[mpos] != *":")||(treeIDs[mpos] !=0))
+		{
+			buffer[mbupos]=treeIDs[mpos];
+			mpos++;
+			mbupos++;
+		}
+		buffer[mbupos]=0;
+		int mIDi = atoi(buffer);
+
+		if (this->function_segment->Get_Type()!=FUNCT_SEQUENCE)
+			return (valid=false);
+
+		this->function_segment =((ChFunction_Sequence*)function_segment)->GetNthFunction(mIDi);
+
+		mid++;
+	}
+	return (valid=true);
+}
+
+
+int ChRefFunctionSegment::SetTreeIDs(char* myIDs)
+{
+	if (strlen(myIDs)<CHREF_TREE_IDS_MAXLENGTH)
+	{
+		strcpy(this->treeIDs, myIDs);
+		this->RestoreReference(this->function);
+		return TRUE;
+	}
+	else return FALSE;
+}
+
+
+
+
+////////////////////////////////////
+//
+// CLASS  ChRefFunctionHandle
+//
+////////////////////////////////////
+
+
+ChRefFunctionHandle::ChRefFunctionHandle(ChFunction* mrootf,int m_hid)
+{
+	this->function= mrootf;
+	this->SetHandleId(m_hid);
+	this->RestoreReference(this->function);
+}
+
+bool ChRefFunctionHandle::RestoreReference(ChFunction* mrootf)
+{
+	// inherit parent behavoiur
+	ChRefFunction::RestoreReference(mrootf);
+
+	// implement
+	// ***TO DO***???
+	return (valid=true);
+}
+
+int ChRefFunctionHandle::AccessHandle(double& mx, double& my, bool set_mode)
+{
+	if (valid)
+	{
+		if (set_mode)
+		{
+		}
+		else
+		{
+		}
+		return true;
+	} else return false;
+}
+
+int ChRefFunctionHandle::SetHandleId(int m_hid)
+{
+	handle_id = m_hid;
+	this->RestoreReference(this->function);
+
+	return TRUE;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+////// end
diff --git a/SRC/ChronoEngine/physics/ChRef.h b/SRC/ChronoEngine/physics/ChRef.h
new file mode 100644
index 0000000..40a2045
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChRef.h
@@ -0,0 +1,164 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHREF_H
+#define CHREF_H
+
+//////////////////////////////////////////////////
+//  
+//   ChRef.h
+//
+//   Class for referencing objects (a bit OBSOLETE?)
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <math.h>
+
+#include "core/ChLists.h"
+#include "physics/ChFunction.h"
+
+
+
+namespace chrono 
+{
+
+
+
+
+// CLASS FOR BASIC REFERENCE (a bit OBSOLETE?)
+//
+/// This is the base data for all types of references. 
+/// The base implemetation is basically _useless_ unless it has some 
+/// inherited implementation (see other classes below)
+
+
+class ChApi ChRef {
+
+ protected:
+	bool valid;
+
+ public:
+	ChRef() {valid = false;};
+
+		/// Tells if the reference is currently valid.
+		/// Instead of implementing it, child classes may simply
+		/// set valif=false (or true) depending on the result of their
+	    /// implementations of RestoreReference();
+	virtual bool IsValid() {return valid;}
+		
+		/// This may be overloaded by child classes. Argument should be
+		/// the 'database' where the reference restoring takes place.
+		/// Should return false if referencing was not possible.
+		/// Should set valid=true/false depending on referencing success.
+	virtual bool RestoreReference() {return false;};
+
+};
+		
+
+// CLASSES FOR REFERENCING CH-FUNCTIONS
+//
+/// Reference to a generic functions of class ChFunction.
+/// This also may be the database for
+/// referencing variables in ChFunction objects....
+
+
+class ChApi ChRefFunction : public ChRef {
+
+ protected:
+	ChFunction* function;
+
+ public:
+	ChRefFunction()				  {function= NULL; valid = false;}
+	ChRefFunction(ChFunction* mf) {function= mf;   valid = true;}
+
+	virtual bool RestoreReference(ChFunction* mrootf) 
+						{function=mrootf; valid=true; return true;};
+	
+		/// Returns the referenced function
+		/// ==========>>>>>>
+	virtual ChFunction* GetFunction() {if (valid) return function; else return NULL;};
+
+};
+		
+
+
+/// Reference to a segment of a ChFunction (of type ChFunctSequence), identified
+/// with a sequence of IDs for navigating the segments tree.. 
+
+#define CHREF_TREE_IDS_MAXLENGTH 20
+
+class ChApi ChRefFunctionSegment : public ChRefFunction {
+
+ protected:
+		// identifier of child segment
+	char treeIDs[CHREF_TREE_IDS_MAXLENGTH];
+		// optim.:storage place for last fetched function segment
+	ChFunction* function_segment;
+
+ public:
+	ChRefFunctionSegment()		{function= NULL; valid = false; strcpy (treeIDs,"");}
+	ChRefFunctionSegment(ChFunction* mrootf, char* myIDs);
+
+	virtual bool RestoreReference(ChFunction* mrootf);
+	
+		/// Returns the referenced segment function 
+		/// ==========>>>>>>
+	virtual ChFunction* GetFunction() {if (valid) return function_segment; else return NULL;};
+
+		/// Returns the root function (i.e. father sequence containing this segment)
+	ChFunction* GetRootFunction() {return ChRefFunction::GetFunction();}
+
+		/// Change the IDs for ravigating the tree
+	int SetTreeIDs(char* myIDs);
+};	
+
+
+
+
+
+/// A reference to an handle of a ChFunction, that is one of the points
+/// which can be also dragged with the mouse
+
+class ChApi ChRefFunctionHandle : public ChRefFunction {
+
+ protected:
+		// identifier of handle
+	int handle_id;
+
+ public:
+	ChRefFunctionHandle()		{function= NULL; valid = false; handle_id=0;}
+	ChRefFunctionHandle(ChFunction* mrootf, int m_hid);
+
+	virtual bool RestoreReference(ChFunction* mrootf);
+	
+		/// Access the referenced handle
+		/// ==========>>>>>>
+	int AccessHandle(double& mx, double& my, bool set_mode);
+
+
+		/// Change the handle ID
+	int SetHandleId(int m_hid);
+	int GetHandleId() {return handle_id;};
+};	
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif  // END of ChRef.h 
diff --git a/SRC/ChronoEngine/physics/ChScriptEngine.h b/SRC/ChronoEngine/physics/ChScriptEngine.h
new file mode 100644
index 0000000..500e5a0
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChScriptEngine.h
@@ -0,0 +1,84 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSCRIPTENGINE_H
+#define CHSCRIPTENGINE_H
+
+//////////////////////////////////////////////////
+//  
+//   ChScriptEngine.h
+//
+//   The generic interface for script engines
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+namespace chrono 
+{
+
+	
+///
+/// Generic compiled script for script engines
+///
+
+class ChScript
+{
+public:
+	ChScript() {};
+	virtual ~ChScript() {};
+};
+
+
+
+///
+/// Generic interface for script engines
+///
+
+class ChScriptEngine
+{
+public:
+	ChScriptEngine() {};
+	virtual ~ChScriptEngine() {};
+
+						// Set the reporter mode, 0=no report
+	virtual void SetReporterMode(int mmode) = 0;
+
+					// Simplified evaluation of a string, result goes in double*. 
+					// Returns TRUE if success. 
+	virtual int Eval(char*, double*) = 0; 
+					// Evaluation of a string, the result is converted in string anyway 
+					// (return string must be already allocated!).
+	virtual int Eval(char*, char*) = 0;  
+					// Set a variable to a double value, if any. Otherwise creates it. 
+	virtual int SetVar(char*, double) =0; 	
+					// If shell is open, prints something.
+	virtual int Print(char*) =0;
+					// Create a script object
+	virtual ChScript* CreateScript() =0;
+					// Loads a file and precompile it into a script 
+	virtual int FileToScript(ChScript& script, char* file) =0;
+					// Execute a precompiled script 
+	virtual int ExecuteScript(ChScript& script) =0;
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaft.cpp b/SRC/ChronoEngine/physics/ChShaft.cpp
new file mode 100644
index 0000000..be4bd5b
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaft.cpp
@@ -0,0 +1,307 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChShaft.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChShaft.h"
+#include "physics/ChSystem.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChShaft> a_registration_ChShaft;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SHAFTS
+
+
+ChShaft::ChShaft ()
+{
+	this->torque = 0;
+	this->system = 0;
+	this->pos = 0;
+	this->pos_dt = 0;
+	this->pos_dtdt = 0;
+	this->inertia = 1;
+	this->fixed = false;
+	this->limitspeed = false;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	max_speed = 10.f;
+
+	sleep_time = 0.6f;
+	sleep_starttime = 0;
+	sleep_minspeed = 0.1f;
+	sleep_minwvel = 0.04f;
+	this->sleeping = false;
+	SetUseSleeping(true); 
+
+	//variables.SetUserData((void*)this);
+}
+
+
+
+ChShaft::~ChShaft ()
+{
+	
+}
+
+void ChShaft::Copy(ChShaft* source)
+{
+		// copy the parent class data...
+	ChPhysicsItem::Copy(source);
+
+	this->torque = source->torque;
+	this->system = source->system;
+	this->pos = source->pos;
+	this->pos_dt = source->pos_dt;
+	this->pos_dtdt = source->pos_dtdt;
+	this->inertia = source->inertia;
+	this->fixed = source->fixed;
+	this->sleeping = source->sleeping;
+	this->limitspeed = source->limitspeed;
+
+	this->system = source->system;
+
+	variables = source->variables;
+
+	max_speed = source->max_speed;
+
+	sleep_time = source->sleep_time;
+	sleep_starttime = source->sleep_starttime;
+	sleep_minspeed = source->sleep_minspeed;
+	sleep_minwvel = source->sleep_minwvel;
+}
+
+
+
+void ChShaft::SetInertia (double newJ) 
+{ 
+	assert(newJ >0.);
+	if (newJ<=0.) 
+		return;
+	this->inertia = newJ; 
+	this->variables.GetMass().SetElementN(0, newJ); 
+	this->variables.GetInvMass().SetElementN(0, (1.0/newJ)); 
+}
+
+
+
+//// 
+void ChShaft::InjectVariables(ChLcpSystemDescriptor& mdescriptor)
+{	
+	this->variables.SetDisabled(!this->IsActive());
+
+	mdescriptor.InsertVariables(&this->variables);
+}
+
+
+void ChShaft::VariablesFbReset()
+{
+	this->variables.Get_fb().FillElem(0.0);
+}
+
+void ChShaft::VariablesFbLoadForces(double factor)
+{
+	// add applied torques to 'fb' vector
+	this->variables.Get_fb().ElementN(0) += this->torque * factor;
+}
+
+void ChShaft::VariablesFbIncrementMq()
+{
+	this->variables.Compute_inc_Mb_v(this->variables.Get_fb(), this->variables.Get_qb());
+}
+
+void ChShaft::VariablesQbLoadSpeed()
+{
+	// set current speed in 'qb', it can be used by the LCP solver when working in incremental mode
+	this->variables.Get_qb().SetElement(0,0, pos_dt);
+}
+
+
+void ChShaft::VariablesQbSetSpeed(double step)
+{
+	double old_dt = this->pos_dt;
+
+	// from 'qb' vector, sets body speed, and updates auxiliary data
+	this->pos_dt =  this->variables.Get_qb().GetElement(0,0);
+
+	// apply limits (if in speed clamping mode) to speeds.
+	ClampSpeed(); 
+
+	// Compute accel. by BDF (approximate by differentiation);
+	if (step)
+	{
+		pos_dtdt = ( (this->pos_dt - old_dt)  / step);
+	}
+}
+
+void ChShaft::VariablesQbIncrementPosition(double dt_step)
+{
+	if (!this->IsActive()) 
+		return;
+
+	// Updates position with incremental action of speed contained in the
+	// 'qb' vector:  pos' = pos + dt * speed   , like in an Eulero step.
+
+	double newspeed = variables.Get_qb().GetElement(0,0);
+
+	// ADVANCE POSITION: pos' = pos + dt * vel
+	this->pos =  this->pos + newspeed * dt_step;
+}
+
+
+
+void ChShaft::SetNoSpeedNoAcceleration()
+{
+	this->pos_dt = 0;
+	this->pos_dtdt = 0;
+}
+
+
+////
+void ChShaft::ClampSpeed()
+{
+	if (this->GetLimitSpeed())
+	{
+		if (this->pos_dt > max_speed)
+			this->pos_dt = max_speed;
+		if (this->pos_dt < -max_speed)
+			this->pos_dt = -max_speed;
+	}
+}
+
+
+
+
+bool ChShaft::TrySleeping()
+{
+	if (this->GetUseSleeping())
+	{	
+		if (this->GetSleeping()) 
+			return true;
+
+		if ( fabs(this->pos_dt) < this->sleep_minspeed )
+		{
+				if ((this->GetChTime() - this->sleep_starttime) > this->sleep_time)
+				{
+					SetSleeping(true);
+					return true;
+				}
+		}
+		else
+		{
+			this->sleep_starttime = float(this->GetChTime());
+		}
+	}
+	return false;
+}
+
+
+
+void ChShaft::Update (double mytime)
+{
+		// Update parent class too
+	ChPhysicsItem::Update(mytime);
+
+		// Class update
+
+	//TrySleeping();			// See if the body can fall asleep; if so, put it to sleeping 
+	ClampSpeed();			// Apply limits (if in speed clamping mode) to speeds.
+}
+
+
+//////// FILE I/O
+
+void ChShaft::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+	double dfoo;
+	mstream << this->torque;
+	mstream << this->pos;
+	mstream << this->pos_dt;
+	mstream << this->pos_dtdt;
+	mstream << this->inertia;
+	mstream << this->GetShaftFixed();
+
+	mstream << max_speed;
+	mstream << sleep_time;
+	dfoo=(double)sleep_starttime;	mstream << dfoo;
+	mstream << sleep_minspeed;
+	mstream << sleep_minwvel;
+
+	mstream << fixed;
+	mstream << limitspeed;
+	mstream << sleeping;
+	mstream << use_sleeping;
+}
+
+void ChShaft::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(mstream);
+
+	double dfoo;
+	bool   bfoo;
+	mstream >> this->torque;
+	mstream >> this->pos;
+	mstream >> this->pos_dt;
+	mstream >> this->pos_dtdt;
+	mstream >> this->inertia;
+	mstream >> bfoo; this->SetShaftFixed(bfoo);
+
+	mstream >> max_speed;
+	mstream >> sleep_time;
+	mstream >> dfoo;		sleep_starttime= (float)dfoo;
+	mstream >> sleep_minspeed;
+	mstream >> sleep_minwvel;
+	
+	mstream >> fixed;
+	mstream >> limitspeed;
+	mstream >> sleeping;
+	mstream >> use_sleeping;
+}
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChShaft.h b/SRC/ChronoEngine/physics/ChShaft.h
new file mode 100644
index 0000000..49b643f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaft.h
@@ -0,0 +1,279 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFT_H
+#define CHSHAFT_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaft.h
+//
+//   Class for one-degree-of-freedom part, that is
+//   shafts that can be used to build 1D models
+//   of power trains. This is more efficient than 
+//   simulating power trains modeled full 3D ChBody
+//   objects. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+//#include "core/ChShared.h"
+#include "physics/ChPhysicsItem.h"
+#include "lcp/ChLcpVariablesGeneric.h"
+
+
+
+namespace chrono
+{
+
+// Forward references (for parent hierarchy pointer)
+
+class ChSystem;
+
+
+///
+///  Class for one-degree-of-freedom mechanical parts with associated
+///  inertia (mass, or J moment of intertial for rotating parts). 
+///  In most cases these represent shafts that can be used to build 1D models
+///  of power trains. This is more efficient than simulating power trains 
+///  modeled with full 3D ChBody objects. 
+///
+
+class ChApi ChShaft : public ChPhysicsItem {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaft,ChPhysicsItem);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double torque;		// The torque acting on shaft (force, if used as linear DOF)
+
+	double pos;			// angle 
+	double pos_dt;		// angular velocity
+	double pos_dtdt;	// angular acceleration
+
+	double inertia;		// the J moment of inertia (or mass, if used as linear DOF)
+
+						// used as an interface to the LCP solver.
+	ChLcpVariablesGeneric variables;
+
+	float max_speed;	// limit on linear speed (useful for VR & videagames)
+
+	float  sleep_time;
+	float  sleep_minspeed;
+	float  sleep_minwvel;
+	float  sleep_starttime;
+
+	bool fixed;
+	bool limitspeed;
+	bool sleeping;
+	bool use_sleeping;
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a shaft.
+	ChShaft ();
+				/// Destructor
+	~ChShaft ();
+
+				/// Copy from another ChShaft. 
+	void Copy(ChShaft* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+
+				/// Sets the 'fixed' state of the shaft. If true, it does not rotate
+				/// despite constraints, forces, etc.
+	void SetShaftFixed (bool mev) {this->fixed = mev; variables.SetDisabled(mev);}
+	bool GetShaftFixed() {return this->fixed;}
+				/// Trick. Set the maximum shaft velocity (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations.
+				/// The realism is limited, but the simulation is more stable.
+	void SetLimitSpeed    (bool mlimit) { this->limitspeed = mlimit;}
+	bool GetLimitSpeed()  {return this->limitspeed;};
+
+				/// Trick. If use sleeping= true, shafts which do not rotate
+				/// for too long time will be deactivated, for optimization.
+				/// The realism is limited, but the simulation is faster.
+	void SetUseSleeping    (bool ms) { this->use_sleeping = ms;}
+	bool GetUseSleeping()  {return this->use_sleeping;}
+
+				/// Force the shaft in sleeping mode or not (usually this state change is not
+				/// handled by users, anyway, because it is mostly automatic).
+	void SetSleeping    (bool ms) { this->sleeping = ms;}
+				/// Tell if the shaft is actually in sleeping state.
+	bool GetSleeping()  {return this->sleeping;}
+
+				/// Put the shaft in sleeping state if requirements are satisfied.
+	bool TrySleeping();
+
+				/// Tell if the body is active, i.e. it is neither fixed to ground nor
+				/// it is in sleep mode.
+	bool IsActive() {return !(sleeping || fixed);}
+
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of coordinates of the shaft
+	virtual int GetDOF  ()   {return 1;}
+
+				/// Returns reference to the encapsulated ChLcpVariables,
+	ChLcpVariablesGeneric& Variables() {return variables;}
+
+			 // Override/implement LCP system functions of ChPhysicsItem
+			 // (to assembly/manage data for LCP system solver)
+
+				/// Sets the 'fb' part of the encapsulated ChLcpVariables to zero.
+	void VariablesFbReset();
+
+				/// Adds the current torques in the 'fb' part: qf+=torques*factor
+	void VariablesFbLoadForces(double factor=1.);
+
+				/// Initialize the 'qb' part of the ChLcpVariables with the 
+				/// current value of shaft speed. Note: since 'qb' is the unknown of the LCP, this
+				/// function seems unuseful, unless used before VariablesFbIncrementMq()
+	void VariablesQbLoadSpeed();
+
+				/// Adds M*q (masses multiplied current 'qb') to Fb, ex. if qb is initialized
+				/// with v_old using VariablesQbLoadSpeed, this method can be used in 
+				/// timestepping schemes that do: M*v_new = M*v_old + forces*dt
+	void VariablesFbIncrementMq();
+
+				/// Fetches the shaft speed from the 'qb' part of the ChLcpVariables (does not 
+				/// updates the full shaft state) and sets it as the current shaft speed.
+				/// If 'step' is not 0, also computes the approximate acceleration of
+				/// the shaft using backward differences, that is  accel=(new_speed-old_speed)/step.
+	void VariablesQbSetSpeed(double step=0.);
+
+				/// Increment shaft position by the 'qb' part of the ChLcpVariables,
+				/// multiplied by a 'step' factor.
+				///     pos+=qb*step
+	void VariablesQbIncrementPosition(double step);
+
+
+				/// Tell to a system descriptor that there are variables of type
+				/// ChLcpVariables in this object (for further passing it to a LCP solver)
+	virtual void InjectVariables(ChLcpSystemDescriptor& mdescriptor);
+
+
+
+
+			   // Other functions
+
+				/// Set no speed and no accelerations (but does not change the position)
+	void SetNoSpeedNoAcceleration();
+
+				/// Set the torque applied to the shaft 
+	void   SetAppliedTorque(double mtorque) { this->torque = mtorque;}
+				/// Get the torque applied to the shaft 
+	double GetAppliedTorque() {return torque;}
+
+				/// Set the angular position 
+	void   SetPos(double mp) { this->pos = mp;}
+				/// Get the angular position 
+	double GetPos() {return this->pos;}
+	
+				/// Set the angular velocity 
+	void   SetPos_dt(double mp) { this->pos_dt = mp;}
+		 		/// Get the angular velocity 
+	double GetPos_dt() {return this->pos_dt;}
+
+				/// Set the angular acceleration 
+	void   SetPos_dtdt(double mp) { this->pos_dtdt = mp;}
+				/// Get the angular acceleration
+	double GetPos_dtdt() {return this->pos_dtdt;}
+
+				/// Inertia of the shaft. Must be positive.
+				/// Try not to mix bodies with too high/too low values of mass, for numerical stability.
+	void   SetInertia (double newJ);
+	double GetInertia() {return this->inertia;}
+
+
+
+				/// Trick. Set the maximum velocity (beyond this limit it will
+				/// be clamped). This is useful in virtual reality and real-time
+				/// simulations, to increase robustness at the cost of realism.
+				/// This limit is active only if you set  SetLimitSpeed(true);
+	void   SetMaxSpeed(float m_max_speed) {max_speed = m_max_speed;}
+	float  GetMaxSpeed () {return max_speed;}
+
+				/// When this function is called, the speed of the shaft is clamped
+				/// into limits posed by max_speed and max_wvel  - but remember to
+				/// put the shaft in the SetLimitSpeed(true) mode.
+	void   ClampSpeed();
+
+				/// Set the amount of time which must pass before going automatically in
+				/// sleep mode when the shaft has very small movements.
+	void   SetSleepTime(float m_t) {sleep_time = m_t;}
+	float  GetSleepTime () {return sleep_time;}
+
+				/// Set the max linear speed to be kept for 'sleep_time' before freezing.
+	void   SetSleepMinSpeed(float m_t) {sleep_minspeed = m_t;}
+	float  GetSleepMinSpeed () {return sleep_minspeed;}
+
+				/// Set the max linear speed to be kept for 'sleep_time' before freezing.
+	void   SetSleepMinWvel(float m_t) {sleep_minwvel = m_t;}
+	float  GetSleepMinWvel () {return sleep_minwvel;}
+
+	
+
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the shaft at given time
+	virtual void Update (double mytime);
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChShaft> ChSharedShaftPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaftsBody.cpp b/SRC/ChronoEngine/physics/ChShaftsBody.cpp
new file mode 100644
index 0000000..41f3af9
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsBody.cpp
@@ -0,0 +1,226 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChShaftsBody.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChShaftsBody.h"
+#include "physics/ChGlobal.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChShaftsBody> a_registration_ChShaftsBody;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+
+
+ChShaftsBody::ChShaftsBody ()
+{
+
+	this->torque_react= 0;
+	this->cache_li_speed =0.f;
+	this->cache_li_pos = 0.f;
+
+	this->shaft = 0;
+	this->body = 0;
+	this->shaft_dir = VECT_Z;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+}
+
+
+ChShaftsBody::~ChShaftsBody ()
+{
+	
+}
+
+void ChShaftsBody::Copy(ChShaftsBody* source)
+{
+		// copy the parent class data...
+	ChPhysicsItem::Copy(source);
+
+		// copy class data
+
+	torque_react = source->torque_react;
+	cache_li_speed = source->cache_li_speed;
+	cache_li_pos = source->cache_li_pos;
+	this->shaft_dir = source->shaft_dir;
+	this->shaft = 0;
+	this->body = 0;
+}
+
+
+int ChShaftsBody::Initialize(ChSharedPtr<ChShaft>& mshaft, ChSharedPtr<ChBody>& mbody, ChVector<>& mdir)
+{
+	ChShaft* mm1 = mshaft.get_ptr();
+	ChBody* mm2 = mbody.get_ptr();
+	assert(mm1 && mm2);
+	assert(mm1->GetSystem() == mm2->GetSystem());
+
+	this->shaft = mm1;
+	this->body = mm2;
+	this->shaft_dir = Vnorm(mdir);
+
+	this->constraint.SetVariables(&mm1->Variables(), &mm2->Variables());
+
+	this->SetSystem(this->shaft->GetSystem());
+	return true;
+}
+
+
+void ChShaftsBody::Update (double mytime)
+{
+		// Inherit time changes of parent class
+	ChPhysicsItem::Update(mytime);
+	
+		// update class data
+	// ...
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChShaftsBody::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	mdescriptor.InsertConstraint(&constraint);
+}
+
+void ChShaftsBody::ConstraintsBiReset()
+{
+	constraint.Set_b_i(0.);
+}
+ 
+void ChShaftsBody::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	double res = 0; // no residual
+
+	constraint.Set_b_i(constraint.Get_b_i() +  factor * res);
+}
+
+void ChShaftsBody::ConstraintsBiLoad_Ct(double factor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	// nothing
+}
+
+
+void ChShaftsBody::ConstraintsLoadJacobians()
+{
+		// compute jacobians
+	ChVector<> jacw = this->body->Dir_World2Body(&shaft_dir);
+
+	this->constraint.Get_Cq_a()->ElementN(0)=-1;
+
+	this->constraint.Get_Cq_b()->ElementN(0)=0;
+	this->constraint.Get_Cq_b()->ElementN(1)=0;
+	this->constraint.Get_Cq_b()->ElementN(2)=0;
+	this->constraint.Get_Cq_b()->ElementN(3)=(float)jacw.x;
+	this->constraint.Get_Cq_b()->ElementN(4)=(float)jacw.y;
+	this->constraint.Get_Cq_b()->ElementN(5)=(float)jacw.z;
+}
+ 
+
+void ChShaftsBody::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	this->torque_react = constraint.Get_l_i() * factor;  
+}
+
+// Following functions are for exploiting the contact persistence
+
+void  ChShaftsBody::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	constraint.Set_l_i(this->cache_li_speed);
+}
+
+void  ChShaftsBody::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	constraint.Set_l_i(this->cache_li_pos);
+}
+
+void  ChShaftsBody::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	this->cache_li_speed = (float)constraint.Get_l_i();
+}
+
+void  ChShaftsBody::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	this->cache_li_pos =  (float)constraint.Get_l_i();
+}
+
+
+
+//////// FILE I/O
+
+void ChShaftsBody::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->shaft_dir;
+	
+}
+
+void ChShaftsBody::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(mstream);
+
+		// deserialize class
+	mstream >> this->shaft_dir;
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChShaftsBody.h b/SRC/ChronoEngine/physics/ChShaftsBody.h
new file mode 100644
index 0000000..de51902
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsBody.h
@@ -0,0 +1,191 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSBODY_H
+#define CHSHAFTSBODY_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaftsBody.h
+//
+//   Class for creating a constraint between a 3D
+//   ChBody object and a 1D ChShaft object. A rotation
+//   axis must be specified (to tell along which direction
+//   she shaft inertia and rotation affects the body).
+//   This constraint is useful, for example, when you have modeled a
+//   3D car using ChBody items and a 1D powertrain (gears,
+//   differential, etc.) using ChShaft objects: you can connect
+//   the former (at least, the wheels) to the latter using
+//   this constraint.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChBody.h"
+#include "physics/ChShaft.h"
+#include "lcp/ChLcpConstraintTwoGeneric.h"
+
+
+
+namespace chrono
+{
+
+// Forward references (for parent hierarchy pointer)
+
+class ChShaft;
+class ChBody;
+
+/// Class for creating a constraint between a 3D
+/// ChBody object and a 1D ChShaft object. A rotation
+/// axis must be specified (to tell along which direction
+/// she shaft inertia and rotation affects the body).
+/// This constraint is useful, for example, when you have modeled a
+/// 3D car using ChBody items and a 1D powertrain (gears,
+/// differential, etc.) using ChShaft objects: you can connect
+/// the former (at least, the wheels) to the latter using
+/// this constraint.
+
+class ChApi ChShaftsBody : public ChPhysicsItem {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaftsBody,ChPhysicsItem);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double torque_react;					
+	
+						// used as an interface to the LCP solver.
+	ChLcpConstraintTwoGeneric constraint;
+
+	float cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	float cache_li_pos;		// used to cache the last computed value of multiplier (solver warm starting)	
+
+	ChShaft* shaft;
+	ChBody*  body;
+
+	ChVector<> shaft_dir;
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a shaft.
+	ChShaftsBody ();
+				/// Destructor
+	~ChShaftsBody ();
+
+				/// Copy from another ChShaftsPlanetary. 
+	void Copy(ChShaftsBody* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of scalar costraints 
+	virtual int GetDOC_c  () {return 1;}
+
+
+			// Override/implement LCP system functions of ChPhysicsItem
+			// (to assembly/manage data for LCP system solver
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+			   // Other functions
+
+				/// Use this function after object creation, to initialize it, given  
+				/// the 1D shaft and 3D body to join. 
+				/// Each item must belong to the same ChSystem. 
+	virtual int Initialize(ChSharedPtr<ChShaft>& mshaft, ///< shaft to join 
+						   ChSharedPtr<ChBody>&  mbody,  ///< body to join 
+						   ChVector<>& mdir			 ///< the direction of the shaft on 3D body (applied on COG: pure torque)
+						   );
+
+				/// Get the shaft
+	ChShaft* GetShaft() {return shaft;}
+				/// Get the body
+	ChBody*  GetBody() {return body;}
+
+				/// Set the direction of the shaft respect to 3D body, as a 
+				/// normalized vector expressed in the coordinates of the body.
+				/// The shaft applies only torque, about this axis.
+	void  SetShaftDirection(ChVector<> md) {shaft_dir = Vnorm(md);}
+
+				/// Get the direction of the shaft respect to 3D body, as a 
+				/// normalized vector expressed in the coordinates of the body. 
+	ChVector<>  GetShaftDirection() {return shaft_dir;}
+
+
+				/// Get the reaction torque considered as applied to ChShaft.
+	double GetTorqueReactionOnShaft() {return -(torque_react);}
+
+				/// Get the reaction torque considered as applied to ChBody.
+	ChVector<> GetTorqueReactionOnBody() {return (shaft_dir*torque_react);}
+
+	
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the gear transmission at given time
+	virtual void Update (double mytime);
+	
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChShaftsBody> ChSharedShaftsBodyPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaftsClutch.cpp b/SRC/ChronoEngine/physics/ChShaftsClutch.cpp
new file mode 100644
index 0000000..f8f0a7f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsClutch.cpp
@@ -0,0 +1,238 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChShaftsClutch.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChShaftsClutch.h"
+#include "physics/ChSystem.h"
+#include "physics/ChShaft.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChShaftsClutch> a_registration_ChShaftClutch;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR CLUTCH
+
+
+ChShaftsClutch::ChShaftsClutch ()
+{
+	this->maxT =  1.;
+	this->minT = -1.;
+	this->modulation = 1.0;
+
+	this->torque_react= 0;
+	this->cache_li_speed =0.f;
+	this->cache_li_pos = 0.f;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	//variables.SetUserData((void*)this);
+}
+
+
+ChShaftsClutch::~ChShaftsClutch ()
+{
+	
+}
+
+void ChShaftsClutch::Copy(ChShaftsClutch* source)
+{
+		// copy the parent class data...
+	ChShaftsCouple::Copy(source);
+
+		// copy class data
+	maxT = source->maxT;
+	minT = source->minT;
+	modulation = source->modulation;
+
+	torque_react = source->torque_react;
+	cache_li_speed = source->cache_li_speed;
+	cache_li_pos = source->cache_li_pos;
+}
+
+
+int ChShaftsClutch::Initialize(ChSharedPtr<ChShaft>& mshaft1, ChSharedShaftPtr& mshaft2)
+{
+	// parent class initialization
+	if (!ChShaftsCouple::Initialize(mshaft1, mshaft2)) return false;
+
+	ChShaft* mm1 = mshaft1.get_ptr();
+	ChShaft* mm2 = mshaft2.get_ptr();
+
+	this->constraint.SetVariables(&mm1->Variables(), &mm2->Variables());
+
+	this->SetSystem(this->shaft1->GetSystem());
+	return true;
+}
+
+
+void ChShaftsClutch::Update (double mytime)
+{
+		// Inherit time changes of parent class
+	ChShaftsCouple::Update(mytime);
+	
+		// update class data
+	// ...
+}
+
+
+void  ChShaftsClutch::SetTorqueLimit(double ml, double mu)
+{
+	this->minT = ml;
+	this->maxT = mu;
+}
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChShaftsClutch::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	mdescriptor.InsertConstraint(&constraint);
+}
+
+void ChShaftsClutch::ConstraintsBiReset()
+{
+	constraint.Set_b_i(0.);
+}
+ 
+void ChShaftsClutch::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	double res = 0; // no residual
+
+	constraint.Set_b_i(constraint.Get_b_i() +  factor * res);
+}
+
+void ChShaftsClutch::ConstraintsBiLoad_Ct(double factor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	// nothing
+}
+
+
+void ChShaftsClutch::ConstraintsFbLoadForces(double factor)
+{
+	// no forces
+
+		// compute jacobians
+	double m_dt = factor;
+
+	this->constraint.SetBoxedMinMax(m_dt*this->minT*this->modulation, 
+									m_dt*this->maxT*this->modulation);
+}
+
+
+void ChShaftsClutch::ConstraintsLoadJacobians()
+{
+	constraint.Get_Cq_a()->SetElement(0,0,  1.0);
+	constraint.Get_Cq_b()->SetElement(0,0, -1.0); 
+}
+ 
+
+void ChShaftsClutch::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	this->torque_react = constraint.Get_l_i() * factor;  
+}
+
+// Following functions are for exploiting the contact persistence
+
+void  ChShaftsClutch::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	constraint.Set_l_i(this->cache_li_speed);
+}
+
+void  ChShaftsClutch::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	constraint.Set_l_i(this->cache_li_pos);
+}
+
+void  ChShaftsClutch::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	this->cache_li_speed = (float)constraint.Get_l_i();
+}
+
+void  ChShaftsClutch::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	this->cache_li_pos =  (float)constraint.Get_l_i();
+}
+
+
+
+//////// FILE I/O
+
+void ChShaftsClutch::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChShaftsCouple::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->maxT;
+	mstream << this->minT;
+	mstream << this->modulation;
+	
+}
+
+void ChShaftsClutch::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChShaftsCouple::StreamIN(mstream);
+
+		// deserialize class
+	mstream >> this->maxT;
+	mstream >> this->minT;
+	mstream >> this->modulation;
+	
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChShaftsClutch.h b/SRC/ChronoEngine/physics/ChShaftsClutch.h
new file mode 100644
index 0000000..ffce7d0
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsClutch.h
@@ -0,0 +1,201 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSCLUTCH_H
+#define CHSHAFTSCLUTCH_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaftsClutch.h
+//
+//   Class for defining a clutch (or brake) between
+//   two one-degree-of-freedom parts, that is,
+//   shafts that can be used to build 1D models
+//   of power trains. This is more efficient than 
+//   simulating power trains modeled full 3D ChBody
+//   objects. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChShaftsCouple.h"
+#include "lcp/ChLcpConstraintTwoGenericBoxed.h"
+
+
+
+namespace chrono
+{
+
+///  Class for defining a clutch or a brake (1D model) 
+///  between two one-degree-of-freedom parts, that is,
+///  shafts that can be used to build 1D models
+///  of power trains. This is more efficient than 
+///  simulating power trains modeled with full 3D ChBody
+///  objects. 
+
+class ChApi ChShaftsClutch : public ChShaftsCouple {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaftsClutch,ChShaftsCouple);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double maxT;		// clutch max transmissible torque (for forward direction
+	double minT;		// clutch min transmissible torque (for backward direction)
+	double modulation;	// 0...1  (default 1).
+
+
+	double torque_react;					
+	
+						// used as an interface to the LCP solver.
+	ChLcpConstraintTwoGenericBoxed constraint;
+
+	float cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	float cache_li_pos;		// used to cache the last computed value of multiplier (solver warm starting)	
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Constructor.
+	ChShaftsClutch ();
+				/// Destructor
+	~ChShaftsClutch ();
+
+				/// Copy from another ChShaftsClutch. 
+	void Copy(ChShaftsClutch* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of scalar constraints, for statistical reasons 
+	virtual int GetDOC_d  () {return 1;}
+
+
+			// Override/implement LCP system functions of ChShaftsCouple
+			// (to assembly/manage data for LCP system solver
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsFbLoadForces(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+			   // Other functions
+
+
+				/// Use this function after gear creation, to initialize it, given  
+				/// two shafts to join. 
+				/// Each shaft must belong to the same ChSystem. 
+	virtual int Initialize(ChSharedPtr<ChShaft>& mshaft1, ///< first  shaft to join
+						   ChSharedPtr<ChShaft>& mshaft2  ///< second shaft to join
+						   );
+
+
+				/// Set the transmissible torque limit (the maximum torque that
+				/// the clutch can transmit between the two shafts).
+				/// You can specify two values for backward/forward directions: usually
+				/// these are equal (ex. -100,100) in most commercial clutches, but
+				/// if you define (0,100), for instance, you can create a so called 
+				/// freewheel or overrunning clutch that works only in one direction.
+	void   SetTorqueLimit(double ml, double mu);
+				/// Set the transmissible torque limit (the maximum torque that
+				/// the clutch can transmit between the two shafts), for both 
+				/// forward and backward direction.
+	void   SetTorqueLimit(double ml) {SetTorqueLimit(-fabs(ml),fabs(ml));}
+
+				/// Get the torque limit for forward rotation
+	double GetTorqueLimitF() {return this->maxT;}
+				/// Get the torque limit for backward rotation
+	double GetTorqueLimitB() {return this->minT;}
+				/// Get the torque limit (when this is a clutch with symmetric forw/backw limits)
+	double GetTorqueLimit() {return this->maxT;}
+
+				/// Set the user modulation of the torque (or brake, if you use it between
+				/// a fixed shaft and a free shaft). The modulation must range from
+				/// 0 (switched off) to 1 (max torque). Default is 1, when clutch is created.
+				/// You can update this during integration loop to simulate the pedal pushing by the driver.
+	void   SetModulation(double mm) { this->modulation = ChMax(ChMin(mm,1.0), 0.0);}
+				/// Get the the user modulation.
+	double GetModulation() {return this->modulation;}
+
+				/// Get the actual angle slippage of the clutch, in terms of phase of shaft 1 respect to 2.
+	double GetSlippage() {return GetRelativeRotation();}
+				/// Get the actual slippage speed of the clutch, in terms of speed of shaft 1 respect to 2.
+	double GetSlippage_dt() {return  GetRelativeRotation_dt();}
+				/// Get the actual slippage acceleration of the clutch, in terms of accel. of shaft 1 respect to 2.
+	double GetSlippage_dtdt() {return GetRelativeRotation_dtdt();}
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 1st axis.
+	virtual double GetTorqueReactionOn1() {return  (this->torque_react); }
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 2nd axis.
+	virtual double GetTorqueReactionOn2() {return -(this->torque_react); }
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the gear transmission at given time
+	virtual void Update (double mytime);
+	
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChShaftsClutch> ChSharedShaftsClutchPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaftsCouple.h b/SRC/ChronoEngine/physics/ChShaftsCouple.h
new file mode 100644
index 0000000..6084046
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsCouple.h
@@ -0,0 +1,171 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSCOUPLE_H
+#define CHSHAFTSCOUPLE_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaftsCouple.h
+//
+//   Base class for defining constraints between a couple
+//   of two one-degree-of-freedom parts, that is,
+//   shafts that can be used to build 1D models
+//   of power trains. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChShaft.h"
+
+namespace chrono
+{
+
+/// Base class for defining constraints between a couple
+/// of two one-degree-of-freedom parts, that is,
+/// shafts that can be used to build 1D models
+/// of power trains. 
+
+class ChApi ChShaftsCouple : public ChPhysicsItem {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaftsCouple,ChPhysicsItem);
+
+protected:
+			//
+	  		// DATA
+			//
+
+	ChShaft* shaft1;
+	ChShaft* shaft2;
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a shaft.
+	ChShaftsCouple ()
+						{
+							this->shaft1 = 0;
+							this->shaft2 = 0;
+						}
+
+				/// Destructor
+	~ChShaftsCouple () {};
+
+				/// Copy from another ChShaftsClutch. 
+	void Copy(ChShaftsCouple* source)
+						{
+							this->shaft1 = 0;
+							this->shaft2 = 0;
+						}
+
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Use this function after gear creation, to initialize it, given  
+				/// two shafts to join. 
+				/// Each shaft must belong to the same ChSystem. 
+				/// Children classes might overload this (here, basically it only sets the two
+				/// pointers)
+	virtual int Initialize(ChSharedPtr<ChShaft>& mshaft1, ///< first  shaft to join
+						   ChSharedPtr<ChShaft>& mshaft2  ///< second shaft to join
+						   )
+					{
+						ChShaft* mm1 = mshaft1.get_ptr();
+						ChShaft* mm2 = mshaft2.get_ptr();
+						assert(mm1 && mm2);
+						assert(mm1 != mm2);
+						assert(mm1->GetSystem() == mm2->GetSystem());
+						this->shaft1 = mm1;
+						this->shaft2 = mm2;
+						this->SetSystem(this->shaft1->GetSystem());
+						return true;
+					};
+
+				/// Get the first (input) shaft
+	ChShaft* GetShaft1() {return shaft1;}
+				/// Get the second (output) shaft
+	ChShaft* GetShaft2() {return shaft2;}
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 1st axis.
+				/// Children classes might overload this.
+	virtual double GetTorqueReactionOn1() {return 0; }
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 2nd axis.
+				/// Children classes might overload this.
+	virtual double GetTorqueReactionOn2() {return 0; }
+
+				/// Get the actual reative angle in terms of phase of shaft 1 respect to 2.
+	double GetRelativeRotation() {return (this->shaft1->GetPos() - this->shaft2->GetPos());}
+				/// Get the actual relative speed in terms of speed of shaft 1 respect to 2.
+	double GetRelativeRotation_dt() {return (this->shaft1->GetPos_dt() - this->shaft2->GetPos_dt());}
+				/// Get the actual relative acceleration in terms of speed of shaft 1 respect to 2.
+	double GetRelativeRotation_dtdt() {return (this->shaft1->GetPos_dtdt() - this->shaft2->GetPos_dtdt());}
+
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream)
+					{
+							// class version number
+						int version = mstream.VersionRead();
+
+							// deserialize parent class too
+						ChPhysicsItem::StreamIN(mstream);
+
+							// deserialize class
+						// nothing - pointers must be rebound
+					}
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream)
+					{
+								// class version number
+						mstream.VersionWrite(1);
+
+							// serialize parent class too
+						ChPhysicsItem::StreamOUT(mstream);
+
+							// stream out all member data
+						// nothing - pointers must be rebound
+					}
+					
+};
+
+
+
+typedef ChSharedPtr<ChShaftsCouple> ChSharedShaftsCouplePtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaftsGear.cpp b/SRC/ChronoEngine/physics/ChShaftsGear.cpp
new file mode 100644
index 0000000..3a32872
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsGear.cpp
@@ -0,0 +1,218 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChShaftsGear.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChShaftsGear.h"
+#include "physics/ChSystem.h"
+#include "physics/ChShaft.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChShaftsGear> a_registration_ChShaftsGear;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SHAFTS
+
+
+ChShaftsGear::ChShaftsGear ()
+{
+	this->ratio = 1;
+	this->torque_react= 0;
+	this->cache_li_speed =0.f;
+	this->cache_li_pos = 0.f;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	//variables.SetUserData((void*)this);
+}
+
+
+ChShaftsGear::~ChShaftsGear ()
+{
+	
+}
+
+void ChShaftsGear::Copy(ChShaftsGear* source)
+{
+		// copy the parent class data...
+	ChShaftsCouple::Copy(source);
+
+		// copy class data
+	ratio = source->ratio;
+	torque_react = source->torque_react;
+	cache_li_speed = source->cache_li_speed;
+	cache_li_pos = source->cache_li_pos;
+}
+
+
+int ChShaftsGear::Initialize(ChSharedPtr<ChShaft>& mshaft1, ChSharedPtr<ChShaft>& mshaft2)
+{
+	// Parent initialization
+	if (!ChShaftsCouple::Initialize(mshaft1, mshaft2)) return false;
+
+	ChShaft* mm1 = mshaft1.get_ptr();
+	ChShaft* mm2 = mshaft2.get_ptr();
+
+	this->constraint.SetVariables(&mm1->Variables(), &mm2->Variables());
+
+	this->SetSystem(this->shaft1->GetSystem());
+	return true;
+}
+
+
+void ChShaftsGear::Update (double mytime)
+{
+		// Inherit time changes of parent class
+	ChShaftsCouple::Update(mytime);
+	
+		// update class data
+	// ...
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChShaftsGear::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	mdescriptor.InsertConstraint(&constraint);
+}
+
+void ChShaftsGear::ConstraintsBiReset()
+{
+	constraint.Set_b_i(0.);
+}
+ 
+void ChShaftsGear::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	double res = 0; // no residual
+
+	constraint.Set_b_i(constraint.Get_b_i() +  factor * res);
+}
+
+void ChShaftsGear::ConstraintsBiLoad_Ct(double factor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	// nothing
+}
+
+/*
+void ChShaftsGear::ConstraintsFbLoadForces(double factor)
+{
+	// no forces
+}
+*/
+
+void ChShaftsGear::ConstraintsLoadJacobians()
+{
+		// compute jacobians
+	constraint.Get_Cq_a()->SetElement(0,0, (float)this->ratio);
+	constraint.Get_Cq_b()->SetElement(0,0, -1);  
+}
+ 
+
+void ChShaftsGear::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	this->torque_react = constraint.Get_l_i() * factor;  
+}
+
+// Following functions are for exploiting the contact persistence
+
+void  ChShaftsGear::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	constraint.Set_l_i(this->cache_li_speed);
+}
+
+void  ChShaftsGear::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	constraint.Set_l_i(this->cache_li_pos);
+}
+
+void  ChShaftsGear::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	this->cache_li_speed = (float)constraint.Get_l_i();
+}
+
+void  ChShaftsGear::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	this->cache_li_pos =  (float)constraint.Get_l_i();
+}
+
+
+
+//////// FILE I/O
+
+void ChShaftsGear::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChShaftsCouple::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->ratio;
+	
+}
+
+void ChShaftsGear::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChShaftsCouple::StreamIN(mstream);
+
+		// deserialize class
+	mstream >> this->ratio;
+	
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChShaftsGear.h b/SRC/ChronoEngine/physics/ChShaftsGear.h
new file mode 100644
index 0000000..3addb1f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsGear.h
@@ -0,0 +1,174 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSGEAR_H
+#define CHSHAFTSGEAR_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaftsGear.h
+//
+//   Class for defining a transmission ratio between
+//   two one-degree-of-freedom parts, that is,
+//   shafts that can be used to build 1D models
+//   of power trains. This is more efficient than 
+//   simulating power trains modeled full 3D ChBody
+//   objects. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChShaftsCouple.h"
+#include "lcp/ChLcpConstraintTwoGeneric.h"
+
+
+
+namespace chrono
+{
+
+///  Class for defining a 'transmission ratio' (a 1D gear) 
+///  between two one-degree-of-freedom parts, that is,
+///  shafts that can be used to build 1D models
+///  of power trains. This is more efficient than 
+///  simulating power trains modeled with full 3D ChBody
+///  objects. 
+
+class ChApi ChShaftsGear : public ChShaftsCouple {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaftsGear,ChShaftsCouple);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double ratio;		// transmission ratio t, as in w2=t*w1, or t=w2/w1
+
+	double torque_react;					
+	
+						// used as an interface to the LCP solver.
+	ChLcpConstraintTwoGeneric constraint;
+
+	float cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	float cache_li_pos;		// used to cache the last computed value of multiplier (solver warm starting)	
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Build a shaft.
+	ChShaftsGear ();
+				/// Destructor
+	~ChShaftsGear ();
+
+				/// Copy from another ChShaftsGear. 
+	void Copy(ChShaftsGear* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of scalar constraints 
+	virtual int GetDOC_c  () {return 1;}
+
+
+			// Override/implement LCP system functions of ChShaftsCouple
+			// (to assembly/manage data for LCP system solver
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	//virtual void ConstraintsFbLoadForces(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+			   // Other functions
+
+				/// Use this function after gear creation, to initialize it, given  
+				/// two shafts to join. 
+				/// Each shaft must belong to the same ChSystem. 
+	virtual int Initialize(ChSharedPtr<ChShaft>& mshaft1, ///< first  shaft to join
+						   ChSharedPtr<ChShaft>& mshaft2  ///< second shaft to join 
+						   );
+
+
+				/// Set the transmission ratio t, as in w2=t*w1, or t=w2/w1 , or  t*w1 - w2 = 0.
+				/// For example, t=1 for a rigid joint; t=-0.5 for representing
+				/// a couple of spur gears with teeths z1=20 & z2=40; t=0.1 for
+				/// a gear with inner teeths (or epicycloidal reducer), etc.
+	void   SetTransmissionRatio(double mt) { this->ratio = mt;}
+				/// Get the transmission ratio t, as in w2=t*w1, or t=w2/w1
+	double GetTransmissionRatio() {return this->ratio;}
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 1st axis.
+	double GetTorqueReactionOn1() {return (this->ratio*this->torque_react);}
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 2nd axis.
+	double GetTorqueReactionOn2() {return -(this->torque_react);}
+
+
+
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the gear transmission at given time
+	virtual void Update (double mytime);
+	
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChShaftsGear> ChSharedShaftsGearPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaftsMotor.cpp b/SRC/ChronoEngine/physics/ChShaftsMotor.cpp
new file mode 100644
index 0000000..2b4da84
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsMotor.cpp
@@ -0,0 +1,249 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChShaftsMotor.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChShaftsMotor.h"
+#include "physics/ChSystem.h"
+#include "physics/ChShaft.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChShaftsMotor> a_registration_ChShaftsMotor;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+
+
+ChShaftsMotor::ChShaftsMotor ()
+{
+	this->motor_torque= 0;
+	this->motor_mode = MOT_MODE_TORQUE;
+	this->motor_set_rot = 0;
+	this->motor_set_rot_dt = 0;
+
+	this->cache_li_speed =0.f;
+	this->cache_li_pos = 0.f;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+}
+
+
+ChShaftsMotor::~ChShaftsMotor ()
+{
+	
+}
+
+void ChShaftsMotor::Copy(ChShaftsMotor* source)
+{
+		// copy the parent class data...
+	ChShaftsCouple::Copy(source);
+
+		// copy class data
+	motor_torque = source->motor_torque;
+	motor_mode = source->motor_mode;
+	motor_set_rot = source->motor_set_rot;
+	motor_set_rot_dt = source->motor_set_rot_dt;
+
+	cache_li_speed = source->cache_li_speed;
+	cache_li_pos = source->cache_li_pos;
+}
+
+
+int ChShaftsMotor::Initialize(ChSharedPtr<ChShaft>& mshaft1, ChSharedPtr<ChShaft>& mshaft2)
+{
+	// Parent class initialize
+	if (!ChShaftsCouple::Initialize(mshaft1, mshaft2)) return false;
+
+	ChShaft* mm1 = mshaft1.get_ptr();
+	ChShaft* mm2 = mshaft2.get_ptr();
+
+	this->constraint.SetVariables(&mm1->Variables(), &mm2->Variables());
+
+	this->SetSystem(this->shaft1->GetSystem());
+	return true;
+}
+
+
+void ChShaftsMotor::Update (double mytime)
+{
+		// Inherit time changes of parent class
+	ChShaftsCouple::Update(mytime);
+	
+		// update class data
+	// ...
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChShaftsMotor::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	//if (!this->IsActive())
+	//	return;
+	if (motor_mode != MOT_MODE_TORQUE)
+		mdescriptor.InsertConstraint(&constraint);
+}
+
+void ChShaftsMotor::ConstraintsBiReset()
+{
+	if (motor_mode != MOT_MODE_TORQUE)
+		constraint.Set_b_i(0.);
+}
+ 
+void ChShaftsMotor::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	if (motor_mode != MOT_MODE_TORQUE)
+	{
+		double res;
+
+		if (motor_mode == MOT_MODE_SPEED)
+			res = 0; // no need to stabilize positions
+
+		if (motor_mode == MOT_MODE_ROTATION)
+			res = this->GetMotorRot() - this->motor_set_rot; 
+
+		constraint.Set_b_i(constraint.Get_b_i() +  factor * res);
+	}
+}
+
+void ChShaftsMotor::ConstraintsBiLoad_Ct(double factor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	if (motor_mode == MOT_MODE_SPEED)
+	{
+		double ct = this->motor_set_rot_dt;
+		constraint.Set_b_i(constraint.Get_b_i() +  factor * ct);
+	}
+}
+
+void ChShaftsMotor::ConstraintsFbLoadForces(double factor)
+{
+	if (motor_mode == MOT_MODE_TORQUE)
+	{
+		shaft1->Variables().Get_fb().ElementN(0) +=  motor_torque*factor;
+		shaft2->Variables().Get_fb().ElementN(0) += -motor_torque*factor;
+	}
+}
+
+void ChShaftsMotor::ConstraintsLoadJacobians()
+{
+	if (motor_mode != MOT_MODE_TORQUE)
+	{
+		constraint.Get_Cq_a()->SetElement(0,0, 1);
+		constraint.Get_Cq_b()->SetElement(0,0, -1);  
+	}
+}
+ 
+
+void ChShaftsMotor::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	if (motor_mode != MOT_MODE_TORQUE)
+		this->motor_torque = constraint.Get_l_i() * factor;  
+}
+
+// Following functions are for exploiting the contact persistence
+
+void  ChShaftsMotor::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	if (motor_mode != MOT_MODE_TORQUE)
+		constraint.Set_l_i(this->cache_li_speed);
+}
+
+void  ChShaftsMotor::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	if (motor_mode != MOT_MODE_TORQUE)
+		constraint.Set_l_i(this->cache_li_pos);
+}
+
+void  ChShaftsMotor::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	if (motor_mode != MOT_MODE_TORQUE)
+		this->cache_li_speed = (float)constraint.Get_l_i();
+}
+
+void  ChShaftsMotor::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	if (motor_mode != MOT_MODE_TORQUE)
+		this->cache_li_pos =  (float)constraint.Get_l_i();
+}
+
+
+
+//////// FILE I/O
+
+void ChShaftsMotor::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChShaftsCouple::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->motor_torque;
+	mstream << (int)this->motor_mode;
+	mstream << this->motor_set_rot;
+	mstream << this->motor_set_rot_dt;
+	
+}
+
+void ChShaftsMotor::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChShaftsCouple::StreamIN(mstream);
+
+		// deserialize class
+	int ifoo;
+	mstream >> this->motor_torque;
+	mstream >> ifoo; this->motor_mode = (ChShaftsMotor::eCh_shaftsmotor_mode)ifoo;
+	mstream >> this->motor_set_rot;
+	mstream >> this->motor_set_rot_dt;
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChShaftsMotor.h b/SRC/ChronoEngine/physics/ChShaftsMotor.h
new file mode 100644
index 0000000..9e42bc7
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsMotor.h
@@ -0,0 +1,207 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSMOTOR_H
+#define CHSHAFTSMOTOR_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaftsMotor.h
+//
+//   Class for defining a motor (a torque) between
+//   two one-degree-of-freedom parts, that is,
+//   shafts that can be used to build 1D models
+//   of power trains. This is more efficient than 
+//   simulating power trains modeled full 3D ChBody
+//   objects. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChShaftsCouple.h"
+#include "lcp/ChLcpConstraintTwoGeneric.h"
+
+
+
+namespace chrono
+{
+
+///  Class for defining a 'transmission ratio' (a 1D gear) 
+///  between two one-degree-of-freedom parts, that is,
+///  shafts that can be used to build 1D models
+///  of power trains. This is more efficient than 
+///  simulating power trains modeled with full 3D ChBody
+///  objects. 
+
+class ChApi ChShaftsMotor : public ChShaftsCouple {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaftsMotor,ChShaftsCouple);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double motor_torque;	
+
+	double motor_set_rot;
+	double motor_set_rot_dt;
+
+	double torque_react1;					
+	double torque_react2;
+
+						// used as an interface to the LCP solver.
+	ChLcpConstraintTwoGeneric constraint;
+	float cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	float cache_li_pos;		// used to cache the last computed value of multiplier (solver warm starting)	
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Constructor.
+	ChShaftsMotor ();
+				/// Destructor
+	~ChShaftsMotor ();
+
+				/// Copy from another ChShaftsMotor. 
+	void Copy(ChShaftsMotor* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of scalar constraints 
+	virtual int GetDOC_c  () {return 0;}
+
+
+			// Override/implement LCP system functions of ChShaftsCouple
+			// (to assembly/manage data for LCP system solver
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	virtual void ConstraintsFbLoadForces(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+			   // Other functions
+
+				/// Use this function after gear creation, to initialize it, given  
+				/// two shafts to join. 
+				/// Each shaft must belong to the same ChSystem. 
+	virtual int Initialize(ChSharedPtr<ChShaft>& mshaft1, ///< first  shaft to join
+						   ChSharedPtr<ChShaft>& mshaft2  ///< second shaft to join 
+						   );
+
+
+	enum eCh_shaftsmotor_mode {
+		MOT_MODE_ROTATION = 0,
+		MOT_MODE_SPEED,
+		MOT_MODE_TORQUE
+		} motor_mode;
+
+				/// Se the motor mode. The options are that you impose
+				/// the relative torque between the two shafts, 
+				/// or their relative rotation phase, or
+				/// their relative speed, but one mode excludes the others. 
+	void SetMotorMode(eCh_shaftsmotor_mode mmode) {motor_mode = mmode;}
+
+				/// Set the motor torque applied between shaft2 and shaft1. 
+				/// So, if fixed, shaft1 can be considered the reference, or the 'truss'.
+				/// (The torque is applied with opposite sign to shaft 1).
+				/// Note: use this only when in MOT_MODE_TORQUE !!
+	void   SetMotorTorque(double mt) { assert(motor_mode == MOT_MODE_TORQUE); this->motor_torque = mt;}
+
+				/// Get the motor torque applied between shaft2 and shaft1. 
+	double GetMotorTorque() { return this->motor_torque;}
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 1st axis.
+	double GetTorqueReactionOn1() {return  (GetMotorTorque());}
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 2nd axis.
+	double GetTorqueReactionOn2() {return -(GetMotorTorque());}
+
+				/// Set the motor rotation phase between shaft2 and shaft1. 
+				/// If the rotation is not constant, you also must use SetMotorRot_dt()
+				/// Note: use this only when in MOT_MODE_ROTATION !
+	void   SetMotorRot(double mt) 
+					{   assert(motor_mode == MOT_MODE_ROTATION); 
+						this->motor_set_rot = mt; }
+
+				/// Set the motor rotation speed between shaft2 and shaft1.
+				/// Note: use this only when in MOT_MODE_ROTATION or MOT_MODE_SPEED !
+	void   SetMotorRot_dt(double mt) 
+					{   assert((motor_mode == MOT_MODE_ROTATION)||(motor_mode == MOT_MODE_SPEED));
+						this->motor_set_rot_dt = mt; }
+
+				/// Get the actual angle rotation of the motor, in terms of phase of shaft 1 respect to 2.
+	double GetMotorRot() {return (this->shaft1->GetPos() - this->shaft2->GetPos());}
+				/// Get the actual speed of the motor, in terms of speed of shaft 1 respect to 2.
+	double GetMotorRot_dt() {return (this->shaft1->GetPos_dt() - this->shaft2->GetPos_dt());}
+				/// Get the actual acceleration of the motor, in terms of accel. of shaft 1 respect to 2.
+	double GetMotorRot_dtdt() {return (this->shaft1->GetPos_dtdt() - this->shaft2->GetPos_dtdt());}
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the gear transmission at given time
+	virtual void Update (double mytime);
+	
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChShaftsMotor> ChSharedShaftsMotorPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaftsPlanetary.cpp b/SRC/ChronoEngine/physics/ChShaftsPlanetary.cpp
new file mode 100644
index 0000000..8dde1f2
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsPlanetary.cpp
@@ -0,0 +1,243 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChShaftsPlanetary.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChShaftsPlanetary.h"
+#include "physics/ChSystem.h"
+#include "physics/ChShaft.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChShaftsPlanetary> a_registration_ChShaftsPlanetary;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+/// CLASS FOR SHAFTS
+
+
+ChShaftsPlanetary::ChShaftsPlanetary ()
+{
+	this->r1 = 1;
+	this->r2 = 1;
+	this->r3 = 1;
+
+	this->torque_react= 0;
+	this->cache_li_speed =0.f;
+	this->cache_li_pos = 0.f;
+
+	this->shaft1 = 0;
+	this->shaft2 = 0;
+	this->shaft3 = 0;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+
+	//variables.SetUserData((void*)this);
+}
+
+
+ChShaftsPlanetary::~ChShaftsPlanetary ()
+{
+	
+}
+
+void ChShaftsPlanetary::Copy(ChShaftsPlanetary* source)
+{
+		// copy the parent class data...
+	ChPhysicsItem::Copy(source);
+
+		// copy class data
+	r1 = source->r1;
+	r2 = source->r2;
+	r3 = source->r3;
+
+	torque_react = source->torque_react;
+	cache_li_speed = source->cache_li_speed;
+	cache_li_pos = source->cache_li_pos;
+	this->shaft1 = 0;
+	this->shaft2 = 0;
+	this->shaft3 = 0;
+}
+
+
+int ChShaftsPlanetary::Initialize(ChSharedPtr<ChShaft>& mshaft1, ChSharedPtr<ChShaft>& mshaft2, ChSharedPtr<ChShaft>& mshaft3)
+{
+	ChShaft* mm1 = mshaft1.get_ptr();
+	ChShaft* mm2 = mshaft2.get_ptr();
+	ChShaft* mm3 = mshaft3.get_ptr();
+	assert(mm1 && mm2 && mm3);
+	assert(mm1 != mm2);
+	assert(mm1 != mm3);
+	assert(mm3 != mm2);
+	assert((mm1->GetSystem() == mm2->GetSystem()) &&( mm1->GetSystem() == mm3->GetSystem()) );
+
+	this->shaft1 = mm1;
+	this->shaft2 = mm2;
+	this->shaft3 = mm3;
+
+	this->constraint.SetVariables(&mm1->Variables(), &mm2->Variables(), &mm3->Variables());
+
+	this->SetSystem(this->shaft1->GetSystem());
+	return true;
+}
+
+
+void ChShaftsPlanetary::Update (double mytime)
+{
+		// Inherit time changes of parent class
+	ChPhysicsItem::Update(mytime);
+	
+		// update class data
+	// ...
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChShaftsPlanetary::InjectConstraints(ChLcpSystemDescriptor& mdescriptor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	mdescriptor.InsertConstraint(&constraint);
+}
+
+void ChShaftsPlanetary::ConstraintsBiReset()
+{
+	constraint.Set_b_i(0.);
+}
+ 
+void ChShaftsPlanetary::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	double res = 0; // no residual
+
+	constraint.Set_b_i(constraint.Get_b_i() +  factor * res);
+}
+
+void ChShaftsPlanetary::ConstraintsBiLoad_Ct(double factor)
+{
+	//if (!this->IsActive())
+	//	return;
+
+	// nothing
+}
+
+/*
+void ChShaftsPlanetary::ConstraintsFbLoadForces(double factor)
+{
+	// no forces
+}
+*/
+
+void ChShaftsPlanetary::ConstraintsLoadJacobians()
+{
+		// compute jacobians
+	constraint.Get_Cq_a()->SetElement(0,0, (float)this->r1);
+	constraint.Get_Cq_b()->SetElement(0,0, (float)this->r2);
+	constraint.Get_Cq_c()->SetElement(0,0, (float)this->r3);
+}
+ 
+
+void ChShaftsPlanetary::ConstraintsFetch_react(double factor)
+{
+	// From constraints to react vector:
+	this->torque_react = constraint.Get_l_i() * factor;  
+}
+
+// Following functions are for exploiting the contact persistence
+
+void  ChShaftsPlanetary::ConstraintsLiLoadSuggestedSpeedSolution()
+{
+	constraint.Set_l_i(this->cache_li_speed);
+}
+
+void  ChShaftsPlanetary::ConstraintsLiLoadSuggestedPositionSolution()
+{
+	constraint.Set_l_i(this->cache_li_pos);
+}
+
+void  ChShaftsPlanetary::ConstraintsLiFetchSuggestedSpeedSolution()
+{
+	this->cache_li_speed = (float)constraint.Get_l_i();
+}
+
+void  ChShaftsPlanetary::ConstraintsLiFetchSuggestedPositionSolution()
+{
+	this->cache_li_pos =  (float)constraint.Get_l_i();
+}
+
+
+
+//////// FILE I/O
+
+void ChShaftsPlanetary::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChPhysicsItem::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->r1;
+	mstream << this->r2;
+	mstream << this->r3;
+	
+}
+
+void ChShaftsPlanetary::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChPhysicsItem::StreamIN(mstream);
+
+		// deserialize class
+	mstream >> this->r1;
+	mstream >> this->r2;
+	mstream >> this->r3;
+	
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChShaftsPlanetary.h b/SRC/ChronoEngine/physics/ChShaftsPlanetary.h
new file mode 100644
index 0000000..d6667c7
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsPlanetary.h
@@ -0,0 +1,226 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSPLANETARY_H
+#define CHSHAFTSPLANETARY_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaftsPlanetary.h
+//
+//   Class for defining a transmission ratio between
+//   three one-degree-of-freedom parts (that is,
+//   shafts that can be used to build 1D models
+//   of power trains), as in a planetary gear.
+//   This is more efficient than 
+//   simulating power trains modeled full 3D ChBody
+//   objects. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChPhysicsItem.h"
+#include "physics/ChShaft.h"
+#include "lcp/ChLcpConstraintThreeGeneric.h"
+
+
+
+namespace chrono
+{
+
+// Forward references (for parent hierarchy pointer)
+
+class ChShaft;
+
+///  Class for defining a planetary gear
+///  between three one-degree-of-freedom parts (that is,
+///  shafts that can be used to build 1D models
+///  of power trains - this is more efficient than 
+///  simulating power trains modeled full 3D ChBody
+///  objects). 
+///  Planetary gears can be used to make, for instance,
+///  the differentials of cars. 
+///  While traditional gear reducers have one input and one
+///  output, the planetary gear have two inputs and one 
+///  output (or, if you prefer, one input and two outputs).
+
+class ChApi ChShaftsPlanetary : public ChPhysicsItem {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaftsPlanetary,ChPhysicsItem);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double r1;		// transmission ratios  as in   r1*w1 + r2*w2 + r3*w3 = 0
+	double r2;
+	double r3;
+
+	double torque_react;					
+	
+						// used as an interface to the LCP solver.
+	ChLcpConstraintThreeGeneric constraint;
+
+	float cache_li_speed;	// used to cache the last computed value of multiplier (solver warm starting)
+	float cache_li_pos;		// used to cache the last computed value of multiplier (solver warm starting)	
+
+	ChShaft* shaft1;
+	ChShaft* shaft2;
+	ChShaft* shaft3;
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Constructor.
+	ChShaftsPlanetary ();
+				/// Destructor
+	~ChShaftsPlanetary ();
+
+				/// Copy from another ChShaftsPlanetary. 
+	void Copy(ChShaftsPlanetary* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of scalar costraints 
+	virtual int GetDOC_c  () {return 1;}
+
+
+			// Override/implement LCP system functions of ChPhysicsItem
+			// (to assembly/manage data for LCP system solver
+
+	virtual void InjectConstraints(ChLcpSystemDescriptor& mdescriptor);
+	virtual void ConstraintsBiReset();
+	virtual void ConstraintsBiLoad_C(double factor=1., double recovery_clamp=0.1, bool do_clamp=false);
+	virtual void ConstraintsBiLoad_Ct(double factor=1.);
+	//virtual void ConstraintsFbLoadForces(double factor=1.);
+	virtual void ConstraintsLoadJacobians();
+	virtual void ConstraintsLiLoadSuggestedSpeedSolution();
+	virtual void ConstraintsLiLoadSuggestedPositionSolution();
+	virtual void ConstraintsLiFetchSuggestedSpeedSolution();
+	virtual void ConstraintsLiFetchSuggestedPositionSolution();
+	virtual void ConstraintsFetch_react(double factor=1.);
+
+
+			   // Other functions
+
+				/// Use this function after planetary gear creation, to initialize it, given  
+				/// three shafts to join. 
+				/// Although there's no special requirement, you may think of the three
+				/// typical moving parts of an apycycloidal reducer: the carrier, the
+				/// input gear, and the gear with inner teeth that usually is kept fixed (but the
+				/// ChShaftsPlanetary does not require that one shaft is fixed - it's up to you) 
+				/// Each shaft must belong to the same ChSystem. 
+	virtual int Initialize(ChSharedPtr<ChShaft>& mshaft1, ///< first  shaft to join (carrier wheel -usually the output)
+						   ChSharedPtr<ChShaft>& mshaft2, ///< second shaft to join (wheel -usually the input)
+						   ChSharedPtr<ChShaft>& mshaft3  ///< third  shaft to join (wheel -other input, or fixed)
+						   );
+
+				/// Get the first shaft
+	ChShaft* GetShaft1() {return shaft1;}
+				/// Get the second shaft
+	ChShaft* GetShaft2() {return shaft2;}
+				/// Get the third shaft
+	ChShaft* GetShaft3() {return shaft3;}
+
+
+				/// Set the transmission ratios r1 r2 r3 as in  
+				///     r1*w1 + r2*w2 + r3*w3 = 0
+				/// For example, for the car differential, if you assume that shaft 1 is
+				/// the carrier and shafts 2 and 3 go to the wheel hubs, you must use 
+				/// r1=-2, r2=1, r3=1 to satisfy the kinematics -2*w1+w2+w3=0 of the differential;
+				/// equivalently, you may use r1=1, r2=-0.5, r3=-0.5 (the equation would hold the same).
+	void   SetTransmissionRatios(double mr1, double mr2, double mr3) { r1=mr1; r2=mr2; r3=mr3;}
+
+				/// Setting the transmission ratios r1 r2 r3 for  r1*w1 + r2*w2 + r3*w3 = 0
+				/// may be cumbersome, but when you deal with typical planetary devices, this
+				/// function provides a shortcut to setting them for you, given a single 
+				/// parameter 't0', that is the speed ratio t'=w3'/w2' of the inverted planetary.
+				/// That ratio is simple to get: to invert the planetary, imagine to hold fixed 
+				/// the wheel of shaft 1 (that is w1' =0), move the shaft 2 and see which is 
+				/// the speed of shaft 3, to get the ratio t'=w3'/w2'. Generally, shaft 1 is
+				/// called the 'carrier'. For example, in normal operation of an epicycloidal 
+				/// reducer, the carrier (shaft 1) is used as output, shaft 2 is the input, and
+				/// shaft 3 is hold fixed to get one degree of freedom only; but in 'inverted' operation
+				/// imagine the carrier is fixed, so t' can be easily got as t'=-z2/z3, with z=n.of teeth.
+				/// In a car differential, again with shaft 1 as carrier, one can see that t'=w3'/w2'
+				/// so t'=-1.     See the Willis theory for more details on these formulas.
+				/// Note that t' must be different from 1 (singularity)
+				/// Once you get t', simply use this function and it will set r1 r2 r3 automatically.
+	void   SetTransmissionRatios(double t0) { r1=(1.-t0); r2=t0; r3=-1.0;}
+
+				/// Get the transmission ratio r1, as in  r1*w1+r2*w2+r3*w3 = 0
+	double GetTransmissionR1() {return this->r1;}
+				/// Get the transmission ratio r1, as in  r1*w1+r2*w2+r3*w3 = 0
+	double GetTransmissionR2() {return this->r2;}
+				/// Get the transmission ratio r1, as in  r1*w1+r2*w2+r3*w3 = 0
+	double GetTransmissionR3() {return this->r3;}
+
+				/// Get the reaction torque considered as applied to the 1st axis.
+	double GetTorqueReactionOn1() {return (this->r1*torque_react);}
+
+				/// Get the reaction torque considered as applied to the 2nd axis.
+	double GetTorqueReactionOn2() {return (this->r2*torque_react);}
+
+				/// Get the reaction torque considered as applied to the 3rd axis.
+	double GetTorqueReactionOn3() {return (this->r3*torque_react);}
+
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the gear transmission at given time
+	virtual void Update (double mytime);
+	
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChShaftsPlanetary> ChSharedPlanetaryPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChShaftsTorsionSpring.cpp b/SRC/ChronoEngine/physics/ChShaftsTorsionSpring.cpp
new file mode 100644
index 0000000..d3d50e4
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsTorsionSpring.cpp
@@ -0,0 +1,131 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChShaftsTorsionSpring.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "physics/ChShaftsTorsionSpring.h"
+#include "physics/ChSystem.h"
+#include "physics/ChShaft.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+namespace chrono
+{
+
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChShaftsTorsionSpring> a_registration_ChShaftsTorsionSpring;
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+
+
+
+ChShaftsTorsionSpring::ChShaftsTorsionSpring ()
+{
+	this->torque_kr= 0;
+	this->stiffness = 0;
+	this->damping = 0;
+
+	SetIdentifier(CHGLOBALS().GetUniqueIntID()); // mark with unique ID
+}
+
+
+ChShaftsTorsionSpring::~ChShaftsTorsionSpring ()
+{
+	
+}
+
+void ChShaftsTorsionSpring::Copy(ChShaftsTorsionSpring* source)
+{
+		// copy the parent class data...
+	ChShaftsCouple::Copy(source);
+
+		// copy class data
+	torque_kr = source->torque_kr;
+	stiffness = source->stiffness;
+	damping   = source->damping;
+}
+
+
+
+void ChShaftsTorsionSpring::Update (double mytime)
+{
+		// Inherit time changes of parent class
+	ChShaftsCouple::Update(mytime);
+	
+		// update class data
+	torque_kr = - (this->GetRelativeRotation() * this->stiffness + this->GetRelativeRotation_dt() * this->damping);
+}
+
+
+
+
+////////// LCP INTERFACES ////
+
+
+void ChShaftsTorsionSpring::VariablesFbLoadForces(double factor)
+{
+	// add applied torques to 'fb' vector
+	this->shaft1->Variables().Get_fb().ElementN(0) +=  this->torque_kr * factor;
+	this->shaft2->Variables().Get_fb().ElementN(0) += -this->torque_kr * factor;
+}
+
+
+
+//////// FILE I/O
+
+void ChShaftsTorsionSpring::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(1);
+
+		// serialize parent class too
+	ChShaftsCouple::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << this->stiffness;
+	mstream << this->damping;
+}
+
+void ChShaftsTorsionSpring::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChShaftsCouple::StreamIN(mstream);
+
+		// deserialize class
+	mstream >> this->stiffness;
+	mstream >> this->damping;
+}
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+
+
+/////////////////////
diff --git a/SRC/ChronoEngine/physics/ChShaftsTorsionSpring.h b/SRC/ChronoEngine/physics/ChShaftsTorsionSpring.h
new file mode 100644
index 0000000..45c9330
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChShaftsTorsionSpring.h
@@ -0,0 +1,153 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSHAFTSTORSIONSPRING_H
+#define CHSHAFTSTORSIONSPRING_H
+
+//////////////////////////////////////////////////
+//
+//   ChShaftsTorsionSpring.h
+//
+//   Class for defining a torsional spring-damper between
+//   two one-degree-of-freedom parts, that is,
+//   shafts that can be used to build 1D models
+//   of power trains. This is more efficient than 
+//   simulating power trains modeled full 3D ChBody
+//   objects. 
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChShaftsCouple.h"
+#include "lcp/ChLcpConstraintTwoGeneric.h"
+
+
+
+namespace chrono
+{
+
+
+///  Class for defining a torsional spring-damper between
+///  between two one-degree-of-freedom parts, that is,
+///  shafts that can be used to build 1D models
+///  of power trains. This is more efficient than 
+///  simulating power trains modeled with full 3D ChBody
+///  objects. 
+
+class ChApi ChShaftsTorsionSpring : public ChShaftsCouple {
+
+						// Chrono simulation of RTTI, needed for serialization
+	CH_RTTI(ChShaftsTorsionSpring,ChShaftsCouple);
+
+private:
+			//
+	  		// DATA
+			//
+
+	double stiffness;	
+	double damping;
+
+	double torque_kr;					
+
+
+public:
+
+			//
+	  		// CONSTRUCTORS
+			//
+
+				/// Constructor.
+	ChShaftsTorsionSpring ();
+				/// Destructor
+	~ChShaftsTorsionSpring ();
+
+				/// Copy from another ChShaftsTorsionSpring. 
+	void Copy(ChShaftsTorsionSpring* source);
+
+
+			//
+	  		// FLAGS
+			//
+
+			//
+	  		// FUNCTIONS
+			//
+
+				/// Number of scalar constraints 
+	virtual int GetDOC_c  () {return 0;}
+
+
+			// Override/implement LCP system functions of ChShaftsCouple
+			// (to assembly/manage data for LCP system solver
+
+				// Adds the torsional torques in the 'fb' part: qf+=torques*factor 
+				// of both shafts 
+	void VariablesFbLoadForces(double factor=1.);
+
+
+				/// Set the torsional stiffness between the two shafts 
+	void   SetTorsionalStiffness(double mt) { this->stiffness = mt;}
+				/// Get the torsional stiffness between the two shafts 
+	double GetTorsionalStiffness() { return this->stiffness;}
+
+				/// Set the torsional damping between the two shafts 
+	void   SetTorsionalDamping(double mt) { this->damping = mt;}
+				/// Get the torsional damping between the two shafts 
+	double GetTorsionalDamping() { return this->damping;}
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 1st axis.
+	virtual double GetTorqueReactionOn1() {return  (this->torque_kr); }
+
+				/// Get the reaction torque exchanged between the two shafts,
+				/// considered as applied to the 2nd axis.
+	virtual double GetTorqueReactionOn2() {return -(this->torque_kr); }
+
+
+			//
+			// UPDATE FUNCTIONS
+			//
+
+				/// Update all auxiliary data of the gear transmission at given time
+	virtual void Update (double mytime);
+	
+
+
+			//
+			// STREAMING
+			//
+
+
+				/// Method to allow deserializing a persistent binary archive (ex: a file)
+				/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+				/// Method to allow serializing transient data into a persistent
+				/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+};
+
+
+
+typedef ChSharedPtr<ChShaftsTorsionSpring> ChSharedShaftsTorsionSpringPtr;
+
+
+
+} // END_OF_NAMESPACE____
+
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChSolver.h b/SRC/ChronoEngine/physics/ChSolver.h
new file mode 100644
index 0000000..d63ab49
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChSolver.h
@@ -0,0 +1,198 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2011 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSOLVER_H
+#define CHSOLVER_H
+
+//////////////////////////////////////////////////
+//  
+//   ChSolver.h
+//
+//   Math functions  for :
+//      - NEWTON NONLINEAR SOLUTION
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include "physics/ChOptvar.h"
+
+
+namespace chrono 
+{
+
+
+////////////////////////////////////////////////
+// LINEAR SYSTEM ITERATIVE SOLVER 
+
+
+
+// ***TO DO***
+
+
+////////////////////////////////////////////////
+// NON LINEAR SOLVER
+
+
+// ***TO DO***
+
+
+class ChApi ChSolver : public ChObj {
+
+protected: 
+
+	//ChOptVar* functionlist;	// list of functions to be solved, as JAVASCRIPT expressions	
+
+	ChOptVar* varlist;		// list of variables to be solved, as JAVASCRIPT expressions;
+
+
+	int C_vars;				// If NULL, the number of optimized variables is automatically
+							// computed from list of ASCII variables (see "optvarlist" above),
+							// otherwise must be set >0 to use the following C evaluation of formulas..
+	//***TO DO*** 
+	// use the more generic ChFx classes instead of function pointers to c-style *funct and *Jfunct
+	// ..
+							// The user can provide the evaluation fxs also in form of
+							// a generic C function of N parameters (passed as a vector double[] p),
+							// returning N residuals (stored into vector double[] r),
+							// which will be used if C_vars >0 and by providing the function "*funct",
+							// otherwise NULL for parsing of the ASCII formulas "function".
+	double (*func)(ChMatrix<>* x, ChMatrix<>* r, void* my_data);		
+							// Optional: a function which returns directly the jacobian
+							// matrix J of the equations, at position q. If this function is NULL, the jacobian
+							// will be computed numerically (but it will be slower).
+	double (*Jfunc)(ChMatrix<>* x, ChMatrix<>* J, void* my_data);		
+	
+
+							// Optional data to be passed to the *func and *Jfunc 
+	void* my_data;			
+
+
+	ChMatrix<>* xv;	    // Vector of variables, for C function above, also 1st approximation.
+	ChMatrix<>* rv;	    // Vector of variables, for C function above
+
+
+	// internal 
+
+	//JSScript* fx_script;	// JavaScript script coming from compilation of function[]   {internal}
+
+
+public: 
+
+	// ------ DATA
+					
+ 	double grad_step;			// def = 1.e-12; step size for evaluation of gradient 
+
+	char err_message[200];		// the ok/warning/error messages are written here
+	int error_code;
+
+	long fx_evaluations;		// number of function evaluations
+	long jacobian_evaluations;	// number of jacobian evaluations
+
+
+	int (*break_funct)();	// if not null, this function is called each 'break_cycles' evaluations
+	int break_cycles;		// how many fx evaluations per check
+	int user_break;			// if break_funct() reported TRUE, this flag is ON, and optimizers should exit all cycles
+	int break_cyclecounter; // internal
+
+
+	// ------ FUCTIONS
+
+	ChSolver();
+	virtual ~ChSolver();
+	virtual void Copy(ChSolver* source);
+
+
+
+				// Sets the optimization variables
+	virtual void AddOptVar (ChOptVar* newvar);
+	virtual void RemoveOptVar (ChOptVar* newvar);
+	virtual ChOptVar* GetVarList() {return optvarlist;};
+	virtual void SetVarList(ChOptVar* mv) {optvarlist = mv;};
+	virtual int  CompileOptVar();	// to speed up code..
+
+				// returns the number of optimization variables set.
+	virtual int  GetNumOfVars();
+
+
+				// Set the number of solution variables.
+				// note: if you use the ChOptVar "ascii" variables, 
+				// this is not needed -the count is automatic- but you 
+				// MUST set it > 0 if you want to use the "C" evaluation of *funct()!!!
+	virtual void  SetNumOfVars(int mv) {C_vars = mv;};
+				
+				// set the C function which will be used for fx evaluation
+				// instead of parsing of "ascii" objective formula.
+	virtual void  SetObjective (double (*m_func)(double p[], double r[], void* my_data)) {func = m_func;};
+
+				// gets the vector of variables, if C function is used
+	double* GetXv() {return xv;};
+
+	void SetXv(double* mx) {xv = mx;};
+
+
+				// function aoptional argument: the "my_data" generic pointer..
+	void* GetMyData() {return my_data;};
+	void SetMyData(void* mmy_data) {my_data= mmy_data;};
+
+
+		// the multibody system "database" gets the current state of variables. Ret. null if can't set values
+	int Vars_to_System(double  x[]);
+	int Vars_to_System(ChMatrix<>* x);
+		// the variables gets their corresponding values in multibody system. Ret. null if can't get values
+	int System_to_Vars(double  x[]);
+	int System_to_Vars(ChMatrix<>* x);
+
+
+		// Returns the value of the residuals in r vector, for given state of variables 
+		// and with the given "database" multibody system. Here evaluates the string "function". 
+		// Return null if some function cannot be evaluated.
+	int Eval_fx(double x[], ChMatrix<>* r);
+	int Eval_fx(ChMatrix<>* x, ChMatrix<>* r);
+
+		// Computes the gradient of objective function, for given state of variables.
+		// The gradient is stored into gr vector. 
+	void   Eval_jacobian(double x[], double gr[][]);
+	void   Eval_jacobian(ChMatrix<>* x, ChMatrix<>* gr);
+
+
+		// Performs the solution
+		// using the current parameters. Returns false if some error occured.
+	virtual int PreSolve();	// <- this just makes some tests, allocations, and compilations..
+	virtual int DoSolve();	// <- THIS IS THE STEP WHICH COMPUTES THE OPTIMAL xv[] AND MUST BE IMPLEMENTED BY CHILDREN CLASSES!	
+	virtual int PostSolve();// <- this just makes deallocations and sets the system as xv[]
+		
+
+		// Does the three steps in sequence PreOptimize, DoOptimize, PostOptimize.
+		// The derived classes shouldn't need the definition of this method, because
+		// they just have to implement the DoOptimize. 
+	virtual int Solve();  
+
+		// each break_cycles number of times this fx is called, the function break_funct() is 
+		// evaluated (if any) and if positive, the variable user_break becomes true.
+	void DoBreakCheck(); 
+
+	
+};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
\ No newline at end of file
diff --git a/SRC/ChronoEngine/physics/ChSolvmin.cpp b/SRC/ChronoEngine/physics/ChSolvmin.cpp
new file mode 100644
index 0000000..1aa50c4
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChSolvmin.cpp
@@ -0,0 +1,2198 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010, 2012 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+//////////////////////////////////////////////////
+//
+//   ChSolvmin.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+
+#include <stdlib.h>
+#include <math.h>
+#include <stdio.h>
+
+#if !defined(__APPLE__)
+#include <malloc.h>
+#endif
+#include "core/ChLog.h"
+#include "physics/ChSolvmin.h"
+
+
+
+namespace chrono
+{
+
+
+
+
+
+void null_entry_solv_opt(double x[],double g[]){}
+
+///////////////////////////////////////////////////////////
+///
+/// Ch_optimizer
+///           Base optimization engine member functions
+///
+
+// build
+ChOptimizer::ChOptimizer()
+{
+	strcpy (err_message, "");
+	C_vars = 0;
+	afunction = 0;
+	afunctionGrad = 0;
+
+	xv = NULL;
+	xv_sup = NULL;
+	xv_inf = NULL;
+
+	minimize = FALSE;
+	opt_fx= 0;
+	error_code = 0;
+	fx_evaluations = 0;
+	grad_evaluations = 0;
+	grad_step = 1.e-12;
+
+	break_funct = NULL;
+	break_cycles = 10;
+	break_cyclecounter = 0;
+	user_break = 0;
+}
+
+
+// destroy
+ChOptimizer::~ChOptimizer()
+{
+
+}
+
+
+// copy
+void ChOptimizer::Copy(ChOptimizer* source)
+{
+	// first copy the parent class data...
+	ChObj::Copy(source);
+
+	// copy error message
+	strcpy (err_message, source->err_message);
+
+	minimize = source->minimize;
+	error_code = source->error_code;
+	fx_evaluations = source->fx_evaluations;
+	grad_evaluations = source->grad_evaluations;
+	grad_step = source->grad_step;
+	C_vars = source->C_vars;
+
+	xv = source->xv;
+	xv_sup = source->xv_sup;
+	xv_inf = source->xv_inf;
+
+	break_funct = source->break_funct;
+	break_cycles = source->break_cycles;
+	break_cyclecounter = source->break_cyclecounter;
+	user_break = source->user_break;
+
+}
+
+
+// Evaluates the function ("function" string) in database, with given state
+// of variables.
+
+double ChOptimizer::Eval_fx(double x[])
+{
+	ChMatrixDynamic<> Vin	(this->C_vars,1);
+	ChMatrixDynamic<> Vout	(1,1);
+
+	for(int i=0; i<Vin.GetRows(); i++) Vin(i,0)=x[i];
+	this->afunction->Eval(Vout, Vin);
+
+	this->fx_evaluations++;
+
+	return Vout(0,0);
+}
+
+
+
+// Evaluates the function ("function" string) in database, with given state
+// of variables.
+
+
+void ChOptimizer::Eval_grad(double x[], double gr[])
+{
+	if (this->afunctionGrad)
+	{
+		ChMatrixDynamic<> Vin	(this->C_vars,1);
+		ChMatrixDynamic<> Vout	(this->C_vars,1);
+
+		for(int i=0; i<Vin.GetRows(); i++) Vin(i,0)=x[i];
+		this->afunctionGrad->Eval(Vout, Vin);
+		for(int i=0; i<Vin.GetRows(); i++) gr[i]=Vout(i,0);
+	}
+	else
+	{
+		// ------ otherwise use BDF  ---------------------
+		int mtotvars = GetNumOfVars();
+		double oldval;
+		double mf, mfd;
+
+		// %%%%%%%%%%%%%  Evaluate central value of function
+		mf = Eval_fx(x);
+
+		for (int mvar = 0; mvar < mtotvars; mvar++)
+		{
+			oldval = x[mvar];
+			// increment one variable
+			x[mvar]=oldval + this->grad_step;
+			mfd = Eval_fx(x);
+			// %%%%%%%%%%%%% compute gradient by BDF
+			gr[mvar]= ((mfd-mf)/(this->grad_step));
+			// back to original value
+			x[mvar]=oldval;
+		}
+	}
+	this->grad_evaluations++;		// increment the counter of total number of gradient evaluations
+}
+
+
+double ChOptimizer::Eval_fx(const ChMatrix<>* x)
+{
+	ChMatrixDynamic<> out(1,1);
+	this->afunction->Eval(out, *x);
+	this->fx_evaluations++;
+	return out(0,0);
+}
+
+void   ChOptimizer::Eval_grad(const ChMatrix<>* x, ChMatrix<>* gr)
+{
+	//Eval_grad(x->GetAddress(), gr->GetAddress());
+	if (this->afunctionGrad)
+	{
+		this->afunctionGrad->Eval(*gr, *x);
+	}
+	else
+	{
+		// ------ otherwise use BDF  ---------------------
+		int mtotvars = GetNumOfVars();
+		double oldval;
+		double mf, mfd;
+
+		// Evaluate central value of function
+		mf = Eval_fx(x);
+		ChMatrixDynamic<> mdx(*x);
+
+		for (int mvar = 0; mvar < mtotvars; mvar++)
+		{
+			oldval = (*x)(mvar);
+			// increment one variable
+			mdx(mvar)=oldval + this->grad_step;
+			mfd = Eval_fx(x);
+			// compute gradient by BDF
+			(*gr)(mvar)= ((mfd-mf)/(this->grad_step));
+			// back to original value
+			mdx(mvar)=oldval;
+		}
+	}
+}
+
+
+
+//// breaking
+
+void  ChOptimizer::DoBreakCheck()
+{
+	break_cyclecounter++;
+	if (break_cyclecounter > break_cycles)
+		if (this->break_funct)
+		{
+			break_cyclecounter = 0;
+			user_break = break_funct();
+		}
+}
+
+
+
+//// OPTIMIZE FUNCTION
+
+int ChOptimizer::PreOptimize()
+{
+	// reset the counter of number of evaluations.
+	fx_evaluations = 0;
+	grad_evaluations = 0;
+
+	// reset breakers
+	user_break = 0;
+	break_cyclecounter = 0;
+
+	// reset error message
+	strcpy (err_message, "");
+
+	// check count vars
+	int nv = GetNumOfVars();
+	if (nv<1) { error_code = OPT_ERR_NOVARS;
+				strcpy (err_message, "Error: no variables defined");
+				return FALSE;}
+
+	return TRUE;
+}
+
+int ChOptimizer::DoOptimize()
+{
+	//////
+	//////  Must be implemented by child class!!!
+	//////  ..............................
+	return TRUE;
+}
+
+int ChOptimizer::PostOptimize()
+{
+	// *** TO DO ***//
+	return TRUE;
+}
+
+
+// DO all the tree steps in sequence
+//
+
+int ChOptimizer::Optimize()
+{
+	if (!this->PreOptimize())  return FALSE;	// 1-
+	if (!this->DoOptimize())   return FALSE;	// 2-
+	if (!this->PostOptimize()) return FALSE;	// 3-
+	return TRUE;
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+///
+/// Ch_local_optimizer
+///           Local optimization engine member functions
+///
+
+
+//// $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+/////
+////  EVALUATION OF OBJECTIVE FUNCTION ( C function called by solvopt() function )
+
+
+double CalcFO (double x[],void *  idData)
+{
+
+	ChOptimizerLocal* moptimizer = (ChOptimizerLocal*) idData;
+
+		// evaluate function and change sign, because local optimizer
+		// uses the solvopt() function which by default minimizes (we
+		// maximize by default
+	return -(moptimizer->Eval_fx(x));
+}
+
+void showVarFun() { };
+
+//// $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
+
+
+// build
+ChOptimizerLocal::ChOptimizerLocal()
+{
+	// first, build parent class
+	ChOptimizer::ChOptimizer();
+
+	initial_step = 1.0;
+	arg_tol = 1.e-6;
+	fun_tol = 1.e-7;
+	maxiters = 50;
+	maxevaluations = 200;
+	gamma = 2.001e0;
+	dilation = 2.5;
+	gradstep = 1.e-100;
+
+	iters_done = 0;
+}
+
+
+// destroy
+ChOptimizerLocal::~ChOptimizerLocal()
+{
+	// first, delete parent class
+	// Ch_optimizer::~Ch_optimizer();
+}
+
+
+// copy
+void ChOptimizerLocal::Copy(ChOptimizerLocal* source)
+{
+	// first, copy  parent class
+	ChOptimizer::Copy(source);
+
+	initial_step = source->initial_step;
+	arg_tol = source->arg_tol;
+	fun_tol = source->fun_tol;
+	maxiters = source->maxiters;
+	maxevaluations = source->maxevaluations;
+	gamma = source->gamma;
+	dilation = source->dilation;
+	gradstep = source->gradstep;
+
+	iters_done = source->iters_done;
+}
+
+
+
+
+
+
+//// OPTIMIZE FUNCTION  , locally with pseudo-NR method
+
+
+int ChOptimizerLocal::DoOptimize()
+{
+ 	double solvopt_options[12];
+	double nstep;
+	int err_code = 0;
+
+	// count vars
+	int nv = GetNumOfVars();
+	if (nv<1) { error_code = OPT_ERR_NOVARS; return FALSE;}
+
+	//nstep = fabs(initial_step);
+	//if (minimize) nstep = nstep * (-1);
+
+	nstep = - fabs(initial_step); // nstep always negative,
+								  // always minimize otherwise solvopt() is buggy.
+
+	error_code = OPT_ERR_OK;
+
+		// set vector of options
+	solvopt_options[0] = nstep;
+	solvopt_options[1] = arg_tol;
+	solvopt_options[2] = fun_tol;
+	solvopt_options[3] = maxiters;
+	solvopt_options[4] = 0;
+	solvopt_options[5] = gamma;
+	solvopt_options[6] = dilation;
+	solvopt_options[7] = gradstep;
+	solvopt_options[8] = 0;
+	solvopt_options[9] = 0;
+	solvopt_options[10] = 0;
+	solvopt_options[11] = maxevaluations;
+
+	int everyTotStep = 1;
+	int breakCicle = 0;
+
+	if (!this->C_vars)
+	{
+			// allocate variables vector
+		if (xv)
+			delete [] xv;
+		xv = new double[nv+3];  // or...[nv] :-)
+
+			// populate vector with starting approximation
+			// system->vector
+	    //	System_to_Vars(xv);
+	}
+
+	double inires = this->Eval_fx(xv);
+
+		// call solver !!!!
+
+	opt_fx = solvopt(nv, //numero di dimensioni
+                  xv, //punto iniziale
+                  CalcFO, //funzione che calcola la funzione obiettivo di intersect
+                  null_entry_solv_opt, //nessuna gradiente
+                  solvopt_options,
+                  (void *)this,
+                  showVarFun,
+                  everyTotStep,
+                  &breakCicle,
+				  err_code);
+
+		// return auxiliary results and infos
+	fx_evaluations = (long)solvopt_options[9];
+	grad_evaluations = (long)solvopt_options[10];
+	iters_done = (long)solvopt_options[8];
+
+
+		// parse the error message
+	/*
+	switch (err_code)
+	{
+	case 0: sprintf (err_message, "OK: objective function optimized in %d steps", iters_done); break;
+	case 2: strcpy  (err_message, "Error: insufficient memory for NR optimization"); break;
+	case 3: strcpy  (err_message, "Error: objective function equals infinity"); break;
+	case 4: strcpy  (err_message, "Error: zero gradient in local optimization"); break;
+	case 7: strcpy  (err_message, "Warning: number of iterations exceeded the limit"); break;
+	case 8: strcpy  (err_message, "Warning: user imposed stop"); break;
+	}
+	*/
+
+		// delete variables vector
+	if (!this->C_vars)
+	{
+		// Vars_to_System(xv);
+		if (xv)
+			delete [] xv;
+		xv = NULL;
+	}
+
+	return TRUE;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+///
+/// Ch_genetic_optimizer
+///           global optimization engine - member functions
+///
+
+// build/destroy genotypes objects (the individuals)
+
+ChGenotype::ChGenotype(int number_of_genes)
+{
+	genes = new ChMatrixDynamic<>(number_of_genes, 1);	// instance matrix of genes
+	fitness = 0;
+	rel_fitness = 0;
+	cum_fitness = 0;
+	need_eval  = TRUE;
+}
+
+ChGenotype::~ChGenotype()
+{
+	delete (genes); genes = NULL;
+}
+
+void ChGenotype::Copy(ChGenotype* source)
+{
+	genes->CopyFromMatrix(*source->genes);
+	fitness = source->fitness;
+	rel_fitness = source->rel_fitness;
+	cum_fitness = source->cum_fitness;
+	need_eval = source->need_eval;
+}
+
+
+// build/destroy the optimizer engine
+
+ChOptimizerGenetic::ChOptimizerGenetic()
+{
+	// first, build parent class
+	//Ch_optimizer::Ch_optimizer();
+
+	// initialize
+	popsize = 50;
+	population = NULL;
+	best_indiv = new ChGenotype(1);
+	max_generations = 100;
+	selection = SELEC_ROULETTEBEST;
+	crossover = CROSSOVER_BLEND;
+	mutation = MUTATION_UNIFORM;
+	elite = ELITE_FALSE;
+	crossv_change = CRO_CHANGE_NULL;
+	crossv_changeto = CROSSOVER_BLEND;
+	crossv_changewhen = 40;
+	average = 0;
+	stdeviation = 0;
+	min_fitness = 0;
+	max_fitness = 0;
+	generations_done = 0;
+	mutation_prob = 0.006;
+	crossover_prob = 0.3;
+	speciation_mating = FALSE;
+	incest_taboo = TRUE;
+	replacement = REPLA_PARENTS;
+	eugenetics = 0.0;
+
+	stop_by_stdeviation = FALSE;
+	stop_stdeviation = 0.0001;
+	stop_by_fitness = FALSE;
+	stop_fitness = 0;
+
+	his_average = NULL;
+	his_stdeviation = NULL;
+	his_maxfitness = NULL;
+	his_minfitness = NULL;
+}
+
+// destroy
+ChOptimizerGenetic::~ChOptimizerGenetic()
+{
+	// first, delete parent class
+	// Ch_optimizer::~Ch_optimizer();
+
+	// delete the instance of best individual
+	delete best_indiv;
+}
+
+
+// copy
+void ChOptimizerGenetic::Copy(ChOptimizerGenetic* source)
+{
+	// first, copy  parent class
+	ChOptimizer::Copy(source);
+
+	population = NULL;
+	best_indiv->Copy(source->best_indiv);
+
+	popsize = source->popsize;
+	max_generations = source->max_generations;
+	selection = source->selection;
+	crossover = source->crossover;
+	mutation = source->mutation;
+	mutation_prob = source->mutation_prob;
+	crossover_prob = source->crossover_prob;
+	elite = source->elite;
+	crossv_change =  source->crossv_change ;
+	crossv_changeto =  source->crossv_changeto ;
+	crossv_changewhen =  source->crossv_changewhen ;
+	speciation_mating = source->speciation_mating;
+	incest_taboo = source->incest_taboo;
+	replacement = source->replacement;
+	eugenetics = source->eugenetics;
+
+	stop_by_stdeviation = source->stop_by_stdeviation;
+	stop_stdeviation = source->stop_stdeviation;
+	stop_by_fitness = source->stop_by_fitness;
+	stop_fitness = source->stop_fitness;
+
+	average = 0;
+	stdeviation = 0;
+	min_fitness = 0;
+	max_fitness = 0;
+	generations_done = 0;
+
+	his_average = NULL;
+	his_stdeviation = NULL;
+	his_maxfitness = NULL;
+	his_minfitness = NULL;
+}
+
+
+
+
+
+// Genetic operations
+
+int ChOptimizerGenetic::CreatePopulation(ChGenotype**& my_population, int my_popsize)
+{
+	// create the array of pointers;
+	my_population = (ChGenotype**)  calloc (my_popsize, sizeof(ChGenotype*));
+
+	// create the individuals (the genotypes are set to default)
+	ChGenotype* mygen;
+	int nvars = GetNumOfVars();
+	for (int i = 0; i < my_popsize; i++ )
+	{
+		mygen = new ChGenotype(nvars);
+		my_population[i] = mygen;
+	}
+	return TRUE;
+}
+
+int ChOptimizerGenetic::DeletePopulation(ChGenotype**& my_population, int my_popsize)
+{
+	if (my_population == NULL) return FALSE;
+
+	// delete all the individuals (the genotypes)
+	ChGenotype* mygen;
+	for (int i = 0; i<my_popsize; i++)
+	{
+		mygen = my_population[i];
+		delete (mygen);
+	}
+
+	// delete the array of pointers
+	free(my_population);
+	my_population = NULL;
+
+	return TRUE;
+}
+
+int ChOptimizerGenetic::InitializePopulation()
+{
+	int nv= GetNumOfVars();
+	int mind;
+	int varindex;
+	double mvalue, a1, a2;
+
+	if (population == NULL) return FALSE;
+	if (population[0]->genes->GetRows() != nv) return FALSE;
+
+	for (mind = 0; mind < popsize; mind++)
+	{
+		varindex = 0;
+		population[mind]->need_eval = TRUE;
+		for (varindex = 0; varindex <nv ;varindex ++)
+		{
+			a1 = this->xv_inf[varindex];		// the random value of each variable
+			a2 = this->xv_sup[varindex];		// must lie within the max/min limits
+			mvalue = a1 + (ChRandom() * (a2-a1));
+			population[mind]->genes->SetElement(varindex,0, mvalue);
+			varindex++;
+		}
+	}
+
+	return TRUE;
+}
+
+double ChOptimizerGenetic::ComputeFitness(ChGenotype* mygen)
+{
+	int nv= GetNumOfVars();
+	int mvar;
+	double mfitness= 0;
+	// create temporary array of variables for function-parameter-passing purposes.
+	double* myvars = (double*) calloc (nv, sizeof(double));
+
+	// fill the vector of variables as double* array
+	for (mvar = 0; mvar <nv; mvar++)
+		{ myvars[mvar] = mygen->genes->GetElement(mvar,0); }
+
+			// impose these variables to the system,
+			//  Vars_to_System(myvars);
+	// evaluate functional,
+	mfitness = this->Eval_fx(myvars);	// ++++++ HERE THE FITNESS IS EVALUATED
+
+	mygen->fitness = mfitness;
+	// set flag for speed reasons..
+	mygen->need_eval = FALSE;
+
+	free (myvars); // delete the array of variables
+
+	return mfitness;
+}
+
+int ChOptimizerGenetic::ComputeAllFitness()
+{
+	int nv= GetNumOfVars();
+	int mvar, mind;
+	// create temporary array of variables for function-parameter-passing purposes.
+	double* myvars = (double*) calloc (nv, sizeof(double));
+
+	for (mind = 0; mind < popsize; mind++)
+	{
+		if (population[mind]->need_eval)
+		{
+			// fill the vector of variables as double* array
+			for (mvar = 0; mvar <nv; mvar++)
+				{ myvars[mvar] = population[mind]->genes->GetElement(mvar,0); }
+				 // impose these variables to the system,
+				 // Vars_to_System(myvars);
+			// evaluate functional,
+			population[mind]->fitness = this->Eval_fx(myvars);	// ++++++ HERE THE FITNESS IS EVALUATED
+			// set flag for speed reasons..
+			population[mind]->need_eval = FALSE;
+			// user break?
+			if (this->user_break) break;
+		}
+	}
+	free (myvars); // delete the array of variables
+
+	return TRUE;
+}
+
+
+ChGenotype* ChOptimizerGenetic::Select_best(ChGenotype** my_population)
+{
+	ChGenotype* mselected = my_population[0];
+	double mbestfitness =  my_population[0]->fitness;
+
+	for (int i = 0; i < popsize; i++)
+	{
+		if (fabs(my_population[i]->fitness) != OPT_IMPOSSIBLE)
+			if (my_population[i]->fitness > mbestfitness)
+			{
+				mselected  = my_population[i];
+				mbestfitness = my_population[i]->fitness;
+			}
+	}
+	// default .
+	return mselected;
+}
+
+ChGenotype* ChOptimizerGenetic::Select_worst(ChGenotype** my_population)
+{
+	ChGenotype* mselected = my_population[0];
+	double mworstfitness = my_population[0]->fitness;
+
+	for (int i = 0; i < popsize; i++)
+	{
+		if (fabs(my_population[i]->fitness) != OPT_IMPOSSIBLE)
+			if (my_population[i]->fitness < mworstfitness)
+			{
+				mselected  = my_population[i];
+				mworstfitness = my_population[i]->fitness;
+			}
+	}
+	// default .
+	return mselected;
+}
+
+double ChOptimizerGenetic::Get_fitness_interval(ChGenotype** my_population)
+{
+	return (Select_best(my_population)->fitness - Select_worst(my_population)->fitness);
+}
+
+
+int ChOptimizerGenetic::PopulationStats(double& average, double& max, double& min, double& stdeviation)
+{
+	average = 0;
+	max = -999999999;
+	min = +999999999;
+	stdeviation = 0;
+	double variance = 0;
+	int i;
+	int sumind = 0;
+
+	for (i = 0; i < popsize; i++)
+	{
+		if (fabs(population[i]->fitness) != OPT_IMPOSSIBLE)
+		{
+			sumind ++;
+			average += population[i]->fitness;
+			if (population[i]->fitness > max) max = population[i]->fitness;
+			if (population[i]->fitness < min) min = population[i]->fitness;
+		}
+	}
+	average = average / (double)sumind;
+
+	for (i = 0; i < popsize; i++)
+	{
+		if (fabs(population[i]->fitness) != OPT_IMPOSSIBLE)
+		{
+			variance += pow((population[i]->fitness - average), 2);
+		}
+	}
+	variance = variance / (double)(sumind-1);
+	stdeviation = sqrt(variance);
+
+	return TRUE;
+}
+
+
+ChGenotype* ChOptimizerGenetic::Select_roulette(ChGenotype** my_population)
+{
+	ChGenotype* mselected = my_population[0];
+
+	// compute sum of all fitness, relative to worst.
+	double msum = 0;
+	double norm_fitness;
+	double minf_fit = Select_worst(my_population)->fitness;
+	double msup_fit = Select_best(my_population)->fitness;
+	double clamp_fit = minf_fit + this->eugenetics*(msup_fit - minf_fit);
+
+    int i;
+	for (i = 0; i < popsize; i++)
+	{
+		if (fabs(my_population[i]->fitness) != OPT_IMPOSSIBLE)
+		{
+			norm_fitness = my_population[i]->fitness - clamp_fit;
+			if (norm_fitness < 0) norm_fitness = 0;
+			msum = msum + norm_fitness;
+		}
+	}
+
+	double number = ChRandom() * msum;	// the sorted-out number!
+	double partialsum = 0;
+	for (i = 0; i < popsize; i++)
+	{
+		if (fabs(my_population[i]->fitness) != OPT_IMPOSSIBLE)
+		{
+			norm_fitness = my_population[i]->fitness - clamp_fit;
+			if (norm_fitness < 0) norm_fitness = 0;
+			partialsum = partialsum + norm_fitness;
+			if (partialsum >= number)
+				return my_population[i]; // the number was ok.
+		}
+	}
+	// default .
+	return mselected;
+}
+
+
+int ChOptimizerGenetic::Selection()
+{
+	// create the selected population:
+	ChGenotype** selected_population;
+	CreatePopulation(selected_population, popsize);
+	int i;
+
+	// move the good elements into the new temp array of selected elements
+	switch (this->selection)
+	{
+	case SELEC_ROULETTE:
+		for (i = 0; i < popsize; i++)
+			selected_population[i]->Copy(Select_roulette(population));
+		break;
+	case SELEC_ROULETTEBEST:
+		for (i = 0; i < popsize; i++)
+			selected_population[i]->Copy(Select_roulette(population));
+		Select_worst(selected_population)->Copy(Select_best(population));
+		break;
+	default:
+		for (i = 0; i < popsize; i++)
+			selected_population[i]->Copy(Select_roulette(population));
+	}
+
+	// set the tmp_population as new population, deleting the old.
+	DeletePopulation(population, popsize);
+	population = selected_population;
+
+	return TRUE;
+}
+
+
+int ChOptimizerGenetic::ApplyCrossover (ChGenotype* par1, ChGenotype* par2, ChGenotype& child1, ChGenotype& child2)
+{
+	int nvars = par1->genes->GetRows();
+	int mv;
+	double fen1, fen2, newfen1, newfen2, w1, w2;
+	ChMatrixDynamic<> mtemp (nvars,1);
+
+	switch (this->crossover)
+	{
+	case CROSSOVER_DISABLED:
+		// do not perform crossover, return same as parent without need of evaluation
+		child1.Copy(par1);
+		child2.Copy(par2);
+		child1.need_eval = FALSE;
+		child2.need_eval = FALSE;
+		return TRUE; // %%%%
+
+	case CROSSOVER_ARITMETIC:
+		// 'Aritmetic' crossover:
+		// average of fenotypes with random wheight
+		for (mv = 0; mv < nvars; mv++)
+		{
+			w1 = ChRandom();
+			w2 = ChRandom();
+			fen1 = par1->genes->GetElement(mv, 0);
+			fen2 = par2->genes->GetElement(mv, 0);
+			newfen1 = fen1 * w1 + fen2 * (1-w1);
+			newfen2 = fen1 * w2 + fen2 * (1-w2);
+			child1.genes->SetElement(mv,0, newfen1);
+			child2.genes->SetElement(mv,0, newfen2);
+		}
+		break;
+
+	case CROSSOVER_BLEND:
+		// 'Blend' crossover:
+		// linear average of two fenotypes with constant weights 0.3 and 0.7 (children are linear
+		// interpolation of parents 0...0.3...0.7...1)
+		w1 = 0.3;
+		w2 = 0.7;
+		for (mv = 0; mv < nvars; mv++)
+		{
+			fen1 = par1->genes->GetElement(mv, 0);
+			fen2 = par2->genes->GetElement(mv, 0);
+			newfen1 = fen1 * w1 + fen2 * (1-w1);
+			newfen2 = fen1 * w2 + fen2 * (1-w2);
+			child1.genes->SetElement(mv,0, newfen1);
+			child2.genes->SetElement(mv,0, newfen2);
+		}
+		break;
+	case CROSSOVER_BLEND_RANDOM:
+		// 'Blend random' crossover:
+		// linear average of two fenotypes with random weights 0.3 and 0.7 (children are linear
+		// interpolation of parents 0...rnd...rnd...1)
+		w1 = ChRandom();
+		w2 = ChRandom();
+		for (mv = 0; mv < nvars; mv++)
+		{
+			fen1 = par1->genes->GetElement(mv, 0);
+			fen2 = par2->genes->GetElement(mv, 0);
+			newfen1 = fen1 * w1 + fen2 * (1-w1);
+			newfen2 = fen1 * w2 + fen2 * (1-w2);
+			child1.genes->SetElement(mv,0, newfen1);
+			child2.genes->SetElement(mv,0, newfen2);
+		}
+		break;
+	case CROSSOVER_HEURISTIC:
+		// 'heuristic crossover' extrapolates the child in the direction of
+		// the parent with best fitness
+		ChGenotype* lead_par;
+		ChGenotype* slave_par;
+		if (par1->fitness >= par2->fitness)
+			{lead_par = par1; slave_par = par2;}
+		else
+			{lead_par = par2; slave_par = par1;}
+
+		for (mv = 0; mv < nvars; mv++)
+		{
+			fen1 = lead_par->genes->GetElement(mv, 0);
+			fen2 = slave_par->genes->GetElement(mv, 0);
+
+			w1 = ChRandom();
+			newfen1 = fen1 + w1*(fen1-fen2);
+			if (newfen1 > this->xv_sup[mv]) newfen1 = this->xv_sup[mv];
+			if (newfen1 < this->xv_inf[mv]) newfen1 = this->xv_inf[mv];
+			child1.genes->SetElement(mv,0, newfen1);
+
+			w2 = ChRandom();
+			newfen2 = fen1 + w2*(fen1-fen2);
+			if (newfen2 > this->xv_sup[mv]) newfen2 = this->xv_sup[mv];
+			if (newfen2 < this->xv_inf[mv]) newfen2 = this->xv_inf[mv];
+			child2.genes->SetElement(mv,0, newfen2);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	// set flags: the chromosomes has been changed,
+	// and fitness should be computed!
+	child1.need_eval = TRUE;
+	child2.need_eval = TRUE;
+
+	return TRUE;
+}
+
+int ChOptimizerGenetic::Crossover()
+{
+	int nv= GetNumOfVars();
+	ChGenotype* par1;
+	ChGenotype* par2;
+	ChGenotype child1(nv);
+	ChGenotype child2(nv);
+	ChGenotype bestparent(nv);
+	int selnum1 = 0;
+	int selnum2 = 0;
+
+
+	par1= NULL;
+	par2= NULL;
+/*
+	int marriage;
+	int ind1, ind2;
+	int maxmarriages = (int)(((double)popsize)*crossover_prob);
+	for (marriage = 0; marriage < maxmarriages; marriage++)
+	{
+		ind1 = (int)(floor(ChRandom()*(double)popsize));
+		ind2 = (int)(floor(ChRandom()*(double)popsize));
+		par1 = population[ind1];
+		par2 = population[ind2];
+		// perform the crossover to find child1, child2
+		ApplyCrossover (par1, par2, child1, child2);
+		// replace parents with children data
+		par1->Copy(&child1);
+		par2->Copy(&child2);
+	}
+*/
+
+	for (int i = 0; i < popsize; i++)
+	{
+		if (ChRandom() <= this->crossover_prob)
+		{
+			if ((par1 == NULL)&&(par2 == NULL))
+				par1 = population[i];
+			else
+				if ((par1 != NULL)&&(par2 == NULL))
+					par2 = population[i];
+		}
+
+		if ((par1 != NULL)&&(par2 != NULL))
+		{
+///if (par1->genes->Equals(par2->genes))
+////cout << "\n                    --incest";
+			// perform the crossover to find child1, child2
+			ApplyCrossover (par1, par2, child1, child2);
+
+			// replacement of children data  ##########
+			switch (replacement) {
+			case REPLA_PARENTS:
+				par1->Copy(&child1);
+				par2->Copy(&child2);
+				break;
+			case REPLA_WORST:
+				Select_worst(this->population)->Copy(&child1);
+				Select_worst(this->population)->Copy(&child2);
+				break;
+			default:
+				break;
+			}
+
+			// restore pointer for next marriage in for loop...
+			par1 = NULL;
+			par2 = NULL;
+		}
+	}
+
+	return TRUE;
+}
+
+
+int ChOptimizerGenetic::Mutation()
+{
+	int nv= GetNumOfVars();
+	double a1, a2, mutval;
+	int had_mutation;
+
+ 	for (int i = 0; i < popsize; i++)
+	{
+		had_mutation = FALSE;
+		for (int mvar = 0; mvar < nv; mvar++)
+		{
+			if (ChRandom() <= this->mutation_prob)
+			{
+				// MUTATION of the fenotype variable...
+				// Find the variable structure in variable linked list, with limits
+				a1 = this->xv_inf[mvar];	// the random value of each variable
+				a2 = this->xv_sup[mvar];	// must lie within the max/min
+				// Perform mutation:
+				switch (this->mutation)
+				{
+				case MUTATION_UNIFORM:
+					mutval = a1 + ChRandom() * (a2- a1);
+					break;
+				case MUTATION_BOUNDARY:
+					if (ChRandom() < 0.5) mutval = a1;
+					else                  mutval = a2;
+					break;
+				}
+
+				// store the mutated allele:
+				population[i]->genes->SetElement(mvar,0,mutval);
+
+				// the chromosomes have been changed, remember that
+				// new fitness will be computed:
+				population[i]->need_eval = TRUE;
+
+				had_mutation = TRUE;
+			}
+		}
+		if (had_mutation) this->mutants++;
+	}
+
+
+	return TRUE;
+}
+
+
+int ChOptimizerGenetic::LogOut(int filelog)
+{
+	if (his_average)
+		if (his_average->GetRows()>=generations_done)
+			his_average->SetElement(generations_done-1,0,average);
+	if (his_stdeviation)
+		if (his_stdeviation->GetRows()>=generations_done)
+			his_stdeviation->SetElement(generations_done-1,0,stdeviation);
+	if (his_maxfitness)
+		if (his_maxfitness->GetRows()>=generations_done)
+			his_maxfitness->SetElement(generations_done-1,0,max_fitness);
+	if (his_minfitness)
+		if (his_minfitness->GetRows()>=generations_done)
+			his_minfitness->SetElement(generations_done-1,0,min_fitness);
+
+	if (filelog)
+	{
+		ChLog::eChLogLevel oldfilemode = GetLog().GetCurrentLevel();
+		GetLog().SetCurrentLevel(ChLog::CHMESSAGE);
+
+		GetLog() << "\n\nGENERATION ------- n. ";
+		GetLog() << (int)generations_done;
+		GetLog() << "\n  STATISTICS:";
+		GetLog() << "\n     max:   ";		GetLog() << max_fitness;
+		GetLog() << "\n     min:   ";		GetLog() << min_fitness;
+		GetLog() << "\n     media: ";		GetLog() << average;
+		GetLog() << "\n     stdev: ";		GetLog() << stdeviation;
+		GetLog() << "\n  Fitness of best individual ever born: ";
+		GetLog() << best_indiv->fitness;
+		GetLog() << "\n";
+
+		GetLog().SetCurrentLevel(oldfilemode);
+	}
+	return TRUE;
+}
+
+
+int ChOptimizerGenetic::DoOptimize()
+{
+	GetLog() << "\n\n\nGENETIC OPTIMIZATION STARTED.............\n\n";
+
+	int nv= GetNumOfVars();
+
+	// allocate -if needed- the upper-lower boundaries arrays
+/*
+	if (!this->C_vars)
+	{
+		this->xv_sup = (double*) calloc (nv, sizeof(double));
+		this->xv_inf = (double*) calloc (nv, sizeof(double));
+		int mvar = 0;
+
+		for (ChOptVar* Vovar = optvarlist; Vovar != NULL; Vovar = (ChOptVar*) Vovar->GetNext())
+		{
+			this->xv_sup[mvar] = Vovar->GetLimSup();
+			this->xv_inf[mvar] = Vovar->GetLimInf();
+			mvar++;
+		}
+	}
+*/
+
+	this->CreatePopulation(population, popsize);
+	this->InitializePopulation();
+
+	this->mutants = 0;
+
+		// avoid complete streaming of log during optimization;
+	ChLog::eChLogLevel oldfilemode = GetLog().GetCurrentLevel();
+	GetLog().SetCurrentLevel(ChLog::CHQUIET);
+
+
+	// -- COMPUTE FITNESS  (for all individuals of brand-new population, 1st time)
+	this->ComputeAllFitness();
+
+	//
+	// THE CYCLE OF OPTIMIZATION,
+	// GENERATION BY GENERATION
+	//
+	for (generations_done = 1; generations_done <= max_generations; generations_done++)
+	{
+		if (crossv_change == CRO_CHANGE_DATE)
+			if(generations_done > crossv_changewhen) crossover = crossv_changeto;
+
+		// -- store the best individual of old population
+		best_indiv->Copy(Select_best(population));
+
+		// -- set the value of best found value of FX
+		opt_fx = best_indiv->fitness;
+
+		// -- statistics...
+		PopulationStats(average, max_fitness, min_fitness, stdeviation);
+
+		// -- log
+		LogOut(TRUE);
+
+
+		// -- break cycle conditions
+		if (stop_by_stdeviation)
+			if (stdeviation <= stop_stdeviation)
+			{
+				sprintf (err_message, "OK, imposed standard deviation reached in %d generations", generations_done);
+				break;
+			}
+		if (stop_by_fitness)
+			if (max_fitness >= stop_fitness)
+			{
+				sprintf (err_message, "OK, imposed max fitness reached in %d generations", generations_done);
+				break;
+			}
+
+		// -- user break?
+		if (this->user_break)
+		{
+			if (*err_message == 0)
+				sprintf (err_message, "OK, user break");
+			break;
+		}
+
+
+		// -- CROSSOVER
+		this->Crossover();
+
+		// -- MUTATION
+		this->Mutation();
+
+		// -- COMPUTE FITNESS
+		this->ComputeAllFitness();
+
+		// -- SELECTION
+		this->Selection();
+
+		if (elite == ELITE_TRUE)
+		{
+			if (Select_best(population)->fitness < best_indiv->fitness)
+			{
+				Select_worst(population)->Copy(best_indiv);
+			}
+		}
+
+	}
+
+	GetLog().SetCurrentLevel(oldfilemode);
+
+
+	if (generations_done >= max_generations)
+		sprintf (err_message, "OK, all %d generations done", max_generations);
+
+	// on termination, reset the system at the value of the fenotypes of the best indiv.
+
+	GetLog() << "\n\nGENETIC OPTIMIZATION TERMINATED.";
+
+	GetLog() << "\nResetting the system to the best genotype-variables found:";
+
+	// resetting system  (or xv[] vector) to best individual
+	int mvar;
+	double* myvars = (double*) calloc (nv, sizeof(double));
+	for (mvar = 0; mvar <nv; mvar++)
+		{
+			myvars[mvar] = best_indiv->genes->GetElement(mvar,0);
+			GetLog() << "\n   "; 
+			GetLog() << myvars[mvar];
+		}
+	
+	memcpy (this->xv, myvars, (sizeof(double) * nv));
+	//	Vars_to_System(myvars);
+
+	free (myvars); // delete the array of variables
+
+	GetLog() << "\n with fitness (objective fx obtained) equal to = ";
+	GetLog() << best_indiv->fitness;
+	GetLog() << "\n\n\n";
+
+	// delete the population, useful anymore...
+	this->DeletePopulation(population, popsize);
+
+	if (!this->C_vars)
+	{
+		free (this->xv_sup);
+		free (this->xv_inf);
+	}
+
+	return TRUE;
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+///
+/// Ch_gradb_optimizer
+///           Local optimization engine member functions
+///
+
+
+// build
+ChOptimizerGradient::ChOptimizerGradient()
+{
+	// first, build parent class
+	ChOptimizer::ChOptimizer();
+
+	initial_step	=1;
+	arg_tol		= 1.e-6;
+	fun_tol		= 1.e-7;
+	maxevaluations	= 800;
+	maxgradients	= 50;
+	maxdilationsteps	= 8;
+	maxbisections	= 10;
+	dilation	= 2.1;
+	do_conjugate = FALSE;
+}
+
+
+// destroy
+ChOptimizerGradient::~ChOptimizerGradient()
+{
+}
+
+
+// copy
+void ChOptimizerGradient::Copy(ChOptimizerGradient* source)
+{
+	// first, copy  parent class
+	ChOptimizer::Copy(source);
+
+	initial_step = source->initial_step;
+	arg_tol = source->arg_tol;
+	fun_tol = source->fun_tol;
+	maxevaluations = source->maxevaluations;
+	maxgradients = source->maxgradients;
+	maxdilationsteps = source->maxdilationsteps;
+	maxbisections = source->maxbisections;
+	dilation = source->dilation;
+	do_conjugate = source->do_conjugate;
+}
+
+
+
+
+
+
+
+
+
+//// OPTIMIZE FUNCTION  , locally with pseudo-NR method
+
+
+int ChOptimizerGradient::DoOptimize()
+{
+	double nstep = initial_step;
+	int dilationstep;
+	int bisections;
+	double fx, fxguess, fxmid, fx1, fx2, lastgood, normGold, normGnew;
+	int update_grad;
+
+	// count vars
+	int nv = GetNumOfVars();
+
+	nstep = initial_step;
+
+	// allocate variables vector
+	ChMatrixDynamic<> mX(nv,1);		// the variables
+	ChMatrixDynamic<> mXguess(nv,1);// the guessed variables
+	ChMatrixDynamic<> mG(nv,1);		// the gradient
+	ChMatrixDynamic<> mGcn(nv,1);	// the conjugategradient
+	ChMatrixDynamic<> mGcnold(nv,1);// the old conjugate gradient
+	ChMatrixDynamic<> mDx(nv,1);	// the increment
+	ChMatrixDynamic<> mXmid(nv,1);	// the bisection center
+	ChMatrixDynamic<> mX1(nv,1);	// the bisection left
+	ChMatrixDynamic<> mX2(nv,1);	// the bisection right
+
+	// populate vector with starting approximation
+	// system->vector
+
+	for (int i = 0; i < nv; i++) { mX(i,0) = this->xv[i]; };
+	//System_to_Vars(&mX);
+
+	fx = Eval_fx(&mX);
+
+	update_grad = TRUE;
+
+	// perform iterative optimization..
+
+	while(TRUE)
+	{
+		// #### compute gradient here;
+		Eval_grad(&mX, &mG);
+
+		// correction for conjugate gradient method?
+		if (this->do_conjugate)
+		{
+			normGnew = mG.NormTwo();
+			mGcn.CopyFromMatrix(mG);
+			if (grad_evaluations > 1)
+			{
+				mGcnold.MatrScale((normGnew/normGold));
+				mGcn.MatrInc(mGcnold);	// update conj.gradient direction
+			}
+			mGcnold.CopyFromMatrix(mGcn);
+			normGold = normGnew;
+			mG.CopyFromMatrix(mGcn);	// use the conjugate gradient!
+		}
+
+		// Forward dilation search;
+		dilationstep = 0;
+		lastgood = fx;
+		while(TRUE)
+		{
+			if (dilationstep > maxdilationsteps) break;
+			dilationstep++;
+
+			// compute new fx position;
+			mDx.CopyFromMatrix(mG);
+			mDx.MatrScale(nstep);
+			mXguess.MatrAdd(mX, mDx);
+
+			fxguess = Eval_fx(&mXguess);
+
+			if (fxguess <= lastgood)
+			{
+				break;
+			}
+
+			nstep *= dilation;
+			lastgood = fxguess;
+		}
+
+		// Backward bisection search;
+		bisections = 0;
+		int gone;
+
+		mDx.CopyFromMatrix(mG);// initialize mid
+		mDx.MatrScale(nstep*0.5);
+		mXmid.MatrAdd(mX, mDx);
+
+		fxmid = Eval_fx(&mXmid);
+
+		while(TRUE)
+		{
+			if (bisections > maxbisections) break;
+			bisections++;
+			if (fx_evaluations > maxevaluations) 	break;
+
+			mDx.CopyFromMatrix(mG);// initialize left
+			mDx.MatrScale(nstep*0.25);
+			mX1.MatrAdd(mX, mDx);
+
+			fx1 = Eval_fx(&mX1);
+
+			mDx.CopyFromMatrix(mG);// initialize right
+			mDx.MatrScale(nstep*0.75);
+			mX2.MatrAdd(mX, mDx);
+
+			fx2 = Eval_fx(&mX2);
+
+			gone = FALSE;
+			if ((fx1 <= fxmid)&&(fxmid <= fx2)&&(gone==FALSE))
+			{
+				mX.CopyFromMatrix(mXmid);		fx = fxmid;
+				mXmid.CopyFromMatrix(mX2);		fxmid = fx2;
+				gone = TRUE;
+			}
+			if ((fx1 >= fxmid)&&(fxmid >= fx2)&&(gone==FALSE))
+			{
+				mXguess.CopyFromMatrix(mXmid);	fxguess = fxmid;
+				mXmid.CopyFromMatrix(mX1);		fxmid = fx1;
+				gone = TRUE;
+			}
+			if ((fx1 <= fxmid)&&(fxmid >= fx2)&&(gone==FALSE))
+			{
+				mX.CopyFromMatrix(mX1);		fx = fx1;
+				mXguess.CopyFromMatrix(mX2);	fxguess = fx2;
+				gone = TRUE;
+			}
+			if (gone==FALSE)
+			{
+				nstep *= 0.25;
+				break;
+			}
+
+			if (fabs(fxmid-fx)<= fun_tol)
+			{
+//cout << "\n              ---- ";
+				sprintf (err_message, "OK,function tolerance reached.");
+				goto end_opt;
+			}
+			// ***TO DO*** stop after "arg_tol" passed
+
+			// half step, then repeat
+			nstep *= 0.5;
+		}
+
+		if ((fx1 >= fx)&&(fx1 >= fxmid)&&(fx1 >= fx2)&&(fx1 >= fxguess))
+			mX.CopyFromMatrix(mX1);
+		if ((fx2 >= fx)&&(fx2 >= fxmid)&&(fx2 >= fx1)&&(fx2 >= fxguess))
+			mX.CopyFromMatrix(mX2);
+		if ((fxmid >= fx)&&(fxmid >= fx1)&&(fxmid >= fx2)&&(fxmid >= fxguess))
+			mX.CopyFromMatrix(mXmid);
+		if ((fxguess >= fx)&&(fxguess >= fx1)&&(fxguess >= fx2)&&(fxguess >= fxmid))
+			mX.CopyFromMatrix(mXguess);
+
+		fx = Eval_fx(mX.GetAddress());
+
+		if (this->fx_evaluations > maxevaluations)
+		{
+//cout << "\n          limit on fx evals----= ";
+			sprintf (err_message, "OK, limit on max number of fx evaluations reached in %d steps", this->grad_evaluations);
+			break;
+		}
+		if (this->grad_evaluations > maxgradients)
+		{
+//cout << "\n          limit on max gradients ---- ";
+			sprintf (err_message, "OK, limit on max number of %d gradient evaluations reached.", this->grad_evaluations);
+			break;
+		}
+	}
+
+	goto end_opt;
+
+end_opt:
+	// ***TO DO*** set the system at best variables among fx, fxguess, fx1, fx2;
+	this->opt_fx = fx;
+
+	if (this->C_vars)
+	{
+		for (int i = 0; i < nv; i++) { this->xv[i] = mX(i,0);};
+	}  // copy result into vector xv
+
+	return TRUE;
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+///
+/// Ch_hybrid_optimizer
+///           Hybrid (genetic+local) optimization engine
+///
+
+
+// build
+ChOptimizerHybrid::ChOptimizerHybrid()
+{
+	// first, build parent class
+	ChOptimizer::ChOptimizer();
+
+	genetic_opt = new ChOptimizerGenetic();
+	local_opt = new ChOptimizerLocal();
+
+	current_phase = 0;
+	use_genetic = TRUE;
+	use_local = TRUE;
+}
+
+
+// destroy
+ChOptimizerHybrid::~ChOptimizerHybrid()
+{
+	// delete the two incapsulated optimizers;
+	delete genetic_opt;
+	delete local_opt;
+}
+
+
+// copy
+void ChOptimizerHybrid::Copy(ChOptimizerHybrid* source)
+{
+	// first, copy  parent class
+	ChOptimizer::Copy(source);
+
+	current_phase = source->current_phase;
+	use_genetic = source->use_genetic;
+	use_local = source->use_local;
+
+	// copy everything also in the two optmimizers
+	genetic_opt->Copy(source->genetic_opt);
+	local_opt->Copy(source->local_opt);
+}
+
+
+
+
+
+
+//// OPTIMIZE FUNCTION  ,
+
+int ChOptimizerHybrid::DoOptimize()
+{
+
+	// set common optimization settings
+	genetic_opt->minimize = this->minimize;
+	local_opt->minimize = this->minimize;
+	genetic_opt->SetNumOfVars(this->C_vars);
+	local_opt->SetNumOfVars(this->C_vars);
+	genetic_opt->SetXv(this->xv);
+	genetic_opt->SetXv_sup(this->xv_sup);
+	genetic_opt->SetXv_inf(this->xv_inf);
+	local_opt->SetXv(this->xv);
+	local_opt->SetXv_sup(this->xv_sup);
+	local_opt->SetXv_inf(this->xv_inf);
+
+	genetic_opt->break_funct = this->break_funct;
+	local_opt->break_funct = this->break_funct;
+	genetic_opt->break_cycles = this->break_cycles;
+	local_opt->break_cycles = this->break_cycles;
+
+
+	// 1)  optimization with genetic method
+
+	if (this->use_genetic)
+	{
+		this->current_phase = 1;
+
+		if (!genetic_opt->Optimize())
+		{
+			strcpy (this->err_message, genetic_opt->err_message);
+			return FALSE;
+		}
+
+		this->fx_evaluations = genetic_opt->fx_evaluations;
+		this->grad_evaluations = genetic_opt->grad_evaluations;
+		this->opt_fx = genetic_opt->opt_fx;
+	}
+
+	// 2)  optimization with gradient method
+
+	if (this->use_local)
+	{
+		this->current_phase = 2;
+
+		if (!local_opt->Optimize())
+		{
+			strcpy (this->err_message, local_opt->err_message);
+			return FALSE;
+		}
+
+		this->fx_evaluations = genetic_opt->fx_evaluations + local_opt->fx_evaluations;
+		this->grad_evaluations = genetic_opt->grad_evaluations + local_opt->grad_evaluations;
+		this->opt_fx = local_opt->opt_fx;
+	}
+
+	this->current_phase = 0;
+
+	// set class values after optimization
+	strcpy (this->err_message, "Ok, hybrid optimization has been terminated");
+
+
+	// on termination, reset the system at the value of the fenotypes of the best indiv.
+	GetLog() << "\n\nHYBRID OPTIMIZATION TERMINATED.";
+	GetLog() << "\nCurrent system variables after optimization:";
+	int nv = this->GetNumOfVars();
+	double* myvars = (double*) calloc (nv, sizeof(double));
+	//this->System_to_Vars(myvars);
+	for (int mvar = 0; mvar <nv; mvar++)
+		{
+			GetLog() << "\n   "; 
+			GetLog() << myvars[mvar];
+		}
+	free (myvars); // delete the array of variables
+
+	GetLog() << "\n with objective fx obtained equal to = ";
+	GetLog() << this->opt_fx;
+	GetLog() << "\n\n\n";
+
+	return TRUE;
+}
+
+
+void  ChOptimizerHybrid::SetObjective (ChFx* mformula)
+{
+	ChOptimizer::SetObjective(mformula);
+	genetic_opt->SetObjective(mformula);
+	local_opt->SetObjective(mformula);
+}
+void  ChOptimizerHybrid::SetObjectiveGrad (ChFx* mformula)
+{
+	ChOptimizer::SetObjectiveGrad(mformula);
+	genetic_opt->SetObjectiveGrad(mformula);
+	local_opt->SetObjectiveGrad(mformula);
+}
+
+void ChOptimizerHybrid::SetNumOfVars(int mv)
+{
+	C_vars = mv;
+	genetic_opt->SetNumOfVars(mv);
+	local_opt->SetNumOfVars(mv);
+};
+
+
+
+
+//###################################################################
+/////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////
+///  NR OPTIMIZER FUNCTION
+
+
+#define slv_err1 "\nSolvOpt error: x has to be a vector of dimension >=2\n"
+#define slv_err2 "\nSolvOpt error: insufficient memory available\n"
+#define slv_err3 "\nSolvopt error: objective function equals infinity\n"
+#define slv_wrn1 "\nSolvOpt warning: ZERO GRADIENT is returned"
+#define slv_wrn2 "\nSolvOpt Warning: Resetting"
+#define slv_wrn3 "\nSolvOpt Warning: trying random point"
+#define slv_wrn4 "\nSolvOpt warning: Number of iterations exceeded the limit\n"
+#define slv_wrn5 "\nSolvOpt warning: user imposed stop \n"
+#define slv_wrn6 "\nSolvOpt warning: Number of function evaluations exceeded the limit\n"
+
+
+
+double solvopt(unsigned int n,
+               double x[],
+               double  fun(double x[],void * idData),
+               void  grad(double x[],double g[]),
+               double options[],
+               void *  idData,
+               void (*showDisplay)(),
+               int showEvery,
+               int *breakCicle,
+			   int& err_code)
+{
+/*
+  solvopt  returns the optimum function value.
+
+  Arguments to the function:
+  x       is the n-vector, the coordinates of the starting point
+          at a call to the subroutine and the optimizer at regular return,
+  fun     is the entry name of an external function which computes the value
+          of the function 'fun' at a point x.
+          synopsis: double fun(double x[])
+  grad    is the entry name of an external function which computes the gradient
+          vector of the function 'fun' at a point x.
+          synopsis: void grad(double x[],double g[])
+  options is a vector of optional parameters (see the description in SOLVOPT.H).
+        Returned optional values:
+        options[8], the number of iterations, options[8]<0 means
+                    an error occured
+        options[9], the number of objective function evaluations, and
+        options[10],the number of gradient evaluations.
+  idData rappresenta un dato a 32 bit per contenere particolari informazioni
+  showVarFun puntatore a funzione void (*)() per il display delle variabili
+         chiamata in ogni ciclo
+  showEvery ogni quanti cilci chiamare la funzione di show
+    breakCicle puntatore ad intero, se diventa alto il ciclo viene interrotto
+
+
+
+____________________________________________________________________________*/
+
+      double default_options[12]=
+             {-1.e0,1.e-6,1.e-7,5.e3,0.e0,2.001e0,2.5e0,1.e-100,0.e0,0.e0,0.e0, 1000.0};
+      //void null_entry();
+      unsigned short gammadj, app, reset, termin;
+      double f,fi,f1,fopt,d,d1,dd,gamma,alpha,w,h1,h,hp,y,evstep;
+      double dx,e2g,e2gt,e2z,e2g1,gnp=5.1e0,xrb,xlb;
+      const double zero=0.e0, one=1.e0, eps=1.e-15, maxf=1.e100;
+      double  *B;               /* space transformation matrix (allocatable)      */
+      double *g,*g0,*g1,*gt,*z,*x1; /* allocatable working arrays                     */
+      //unsigned short k=0,           /* iteration counter                              */
+      unsigned int   k=0,           /* iteration counter                              */
+                     kcheck=0,      /* reset check counter                            */
+                     ld,            /* iteraion number to print intermediate results  */
+                     i,j,           /* loop counters                                  */
+                     k1=0,k2=0,     /* 1-D search step counters                       */
+                     kstop=0,       /* termination counter                            */
+                     nstop=0,       /* zero-gradient events counter                   */
+                     kg=0,kstore=3,nzero=0,
+                     nsteps[3]={0,0,0}; /* counters used for step size change         */
+      int countShowFun=0;
+
+	  err_code = 0;		// alex
+
+/* Check the dimension: */
+
+      //if (n<2)
+      if (n<1) //paolo, 28/11/98
+      { //printf (slv_err1);
+        options[8]=-one;
+        return(0.);
+      }
+
+/* Allocate the memory for working arrays: */
+
+      B=(double *)calloc(n*n+10,sizeof(double));
+      g=(double *)calloc(n+10,sizeof(double));
+     g0=(double *)calloc(n+10,sizeof(double));
+     g1=(double *)calloc(n+10,sizeof(double));
+     gt=(double *)calloc(n+10,sizeof(double));
+      z=(double *)calloc(n+10,sizeof(double));
+     x1=(double *)calloc(n+10,sizeof(double));
+
+      if (B==NULL||g==NULL||g0==NULL||g1==NULL||gt==NULL||z==NULL||x1==NULL)
+      {
+         //printf (slv_err2);
+         options[8]=-2.e0;
+         return(0.);
+      }
+
+/* ANALIZE THE ARGUMENTS PASSED
+   User-supplied gradients: */
+      if (grad==null_entry_solv_opt) app=1; else app=0;
+
+/* Norm of vector x:*/
+      dx=zero; for (i=0;i<n;i++) dx+=x[i]*x[i]; dx=sqrt(dx);
+
+/* Default values for options */
+      for (i=0;i<=7;i++) if (options[i]==zero) options[i]=default_options[i];
+
+      if (fabs(options[0])<=eps*dx)
+      {
+		  if (options[0]<zero) options[0]=-1.e-6*dx; else options[0]=1.e-6*dx;
+      }
+          if (options[1]<=eps) options[1]=default_options[1];
+          if (options[2]<=eps) options[2]=default_options[2];
+          if (options[5]==default_options[5]) gammadj=1;
+          else
+          {  gammadj=0;
+             if (options[5]<1.2e0) options[5]=1.2e0;
+             else {if (options[5]>3.e0) options[5]=3.e0;}
+          }
+          if (options[6]<1.5e0) options[6]=1.5e0;
+       options[8]=default_options[8];
+       options[9]=default_options[9];
+       options[10]=default_options[10];
+
+/* Minimize resp. maximize the objective function:*/
+      if(options[0]<zero)h1=-one; else h1=one;
+/* Multiplier for the matrix for the inverse of the space dilation: */
+      w=one/options[6]-one;
+/* Set other control parameters: */
+      gamma=options[5];
+      if (options[4]<zero && options[4]!=-one) options[4]=zero;
+      ld=(unsigned int)floor(options[4]+0.1);
+
+	  if (options[11]<=0.0) { options[11]=default_options[11];};
+
+/*--------------------------------------------------------------------
+RESETTING CYCLE */
+
+   while (1)
+   {
+
+/* COMPUTE THE OBJECTIVE FUNCTION: */
+
+      f=fun(x,idData);  options[9]+=one;	// +++++++++
+      if (fabs(f)>maxf)
+      {  //if (options[4]!=-one)
+         //  ; //printf (slv_err3);
+         options[8]=k;
+		 err_code = 3;
+		 goto endrun;
+      }
+
+/* COMPUTE THE GRADIENT: */
+      if (app)
+      {     dd=ChMax(1.e-7/pow((k+1),1.5),options[7]);
+            for (i=0;i<n;i++)
+            {  d=dd*ChMax(fabs(x[i]),1.e-4);
+               y=x[i]; x[i]=x[i]+d;
+			   fi=fun(x,idData);			// ++++++++
+			   g[i]=(fi-f)/d; x[i]=y;
+            }
+            options[9]=options[9]+n;
+			if (options[9]>=options[11]) {err_code = 11; goto endrun;}
+      }
+      else  { grad(x,g); options[10]=options[10]+one; }
+/* Store the gradient in a new array: */
+      for (i=0;i<n;i++) g1[i]=g[i];
+/* Compute the norm of the gradient: */
+      e2g=zero; for (i=0;i<n;i++) e2g+=g[i]*g[i]; e2g=sqrt(e2g);
+/* Check the norm of the gradient:   */
+      if (e2g<eps)
+      {  // if (options[4]!=-one)
+		 //  ; //printf (slv_wrn1);
+		 err_code = 4;
+         options[8]=k;
+		 goto endrun;
+      }
+/*-----------------------------------------------------------------
+  INITIAL TRIAL STEP SIZE and RE-INITIALIZATION of B:  */
+
+      if (k==0) { h=options[0]/(log10(e2g+one)/log10(2.e0));  dx=fabs(h)*3.e0;}
+      for (i=0;i<n;i++) { for (j=0;j<n;j++) B[i*n+j]=zero; B[i*n+i]=one; }
+
+
+
+/*-----------------------------------------------------------------
+  ITERATION CYCLE   */
+
+   while (1)
+   {
+	  k+=1; kcheck+=1;
+
+/* Gradient in the transformed space (gt) and the difference (z): */
+      e2gt=zero; e2z=zero;
+      for (i=0;i<n;i++)
+      {  d=zero; for (j=0;j<n;j++) d+=B[j+i*n]*g[j];
+         gt[i]=d;       e2gt+=d*d;
+         z[i]=d-g1[i];  e2z+=z[i]*z[i];
+      }
+      e2gt=sqrt(e2gt); e2z=sqrt(e2z);
+
+/* Adjust gamma  */
+
+      if (gammadj) gamma=pow(1.2e0,ChMax(one,log10(e2g+one)));
+
+/* Calculate alpha: */
+
+      alpha=options[6];
+      d=zero; for (i=0;i>n;i++) d+=g[i]*gt[i];  d/=e2g*e2gt;
+      if (d<-0.999e0) alpha*=1.2e0;
+      if (gamma>2.5e0 && gammadj) alpha+=(gamma-2.5e0)/2.e0;
+      w=one/alpha-one;
+
+/* Check the norm of the difference: */
+
+      if (e2z>1.e-31) for (i=0;i<n;i++) z[i]/=e2z;
+      else for (i=0;i<n;i++) z[i]=zero;
+
+/* Make a space transformation:
+   g1=gt+w*(z*gt')*z: */
+        d=zero; for (i=0;i<n;i++) d+=z[i]*gt[i];
+        e2g1=zero; d*=w;
+        for (i=0;i<n;i++)
+        { g1[i]=gt[i]+d*z[i];
+          e2g1+=g1[i]*g1[i];
+        } e2g1=sqrt(e2g1);
+
+/*-----------------------------------------------------------------
+  CHECK FOR THE NEED OF RESETTING   */
+
+      reset=1;
+      for (i=0;i<n;i++)
+         {if (fabs(g[i])>eps) if (fabs(gt[i])/fabs(g[i])>=eps) reset=0;}
+      if (e2z==zero && kcheck>2) reset=1;
+      if (reset)
+      {   // if (options[4]!=-one)
+		  //	printf (slv_wrn2);
+		  kcheck=0; h=h1*dx/6.e0; k=k-1; kg=0; for (i=0;i<3;i++) nsteps[i]=0;
+          kstop=0;  exit(0);
+      }
+
+      for (i=0;i<n;i++) gt[i]=g1[i]/e2g1;
+
+/* New inverse matrix: B = B ( I + (1/alpha -1)zz' ) */
+
+      for (i=0;i<n;i++)
+      {    d=zero;   for (j=0;j<n;j++) d+=B[j*n+i]*z[j];
+           d*=w;     for (j=0;j<n;j++) B[j*n+i]+=d*z[j];
+      }
+
+/* Gradient in the non-transformed space: g0 = B' * gt   */
+      for (i=0;i<n;i++)
+      {    d=zero;   for (j=0;j<n;j++) d+=B[j*n+i]*gt[j];
+           g0[i]=d;
+      }
+
+/* STORE THE CURRENT VALUES AND SET THE COUNTERS FOR 1-D SEARCH  */
+
+      for (i=0;i<n;i++) z[i]=x[i]; hp=h; fopt=f; k1=0; k2=0;
+
+/* 1-D SEARCH   */
+
+      while (1)
+      {  for (i=0;i<n;i++) x1[i]=x[i]; f1=f;
+
+/* Next point:   */
+         for (i=0;i<n;i++) x[i]+=hp*g0[i];
+
+/* COMPUTE THE FUNCTION VALUE AT A POINT:  */
+
+         f=fun(x,idData);  options[9]+=one;		// ++++++++
+		 if (options[9]>=options[11]) {err_code = 11; goto endrun;}
+         if (fabs(f)>maxf)
+         {  // if (options[4]!=-one)
+            //		printf (slv_err3);
+			err_code = 3;
+            options[8]=k;
+			goto endrun;
+         }
+
+/* CHECK FOR THE NEED TO USE A SMALLER STEP   */
+
+         if (fabs(f)<eps) { d=f/eps; d1=f1/eps; } else { d=f; d1=f1;}
+         if (d1<zero) dd=-one; else {if (d1>zero) dd=one; else dd=zero; }
+         if ( h1*d  <  h1*pow(gamma,dd)*d1 )
+            {if (e2g>zero) { k2+=1; for (i=0;i<n;i++) x[i]=x1[i]; hp/=gnp; f=f1; k1=0; }}
+         else
+         {
+/* Has the 1-D optimizer been passed?   */
+            if (h1*d<=h1*d1) break;
+/* Adjust a trial step size   */
+            if (k2==0)  k1+=1;
+            if (k1>=20) hp*=2.e0;
+            else
+            {   if (k1>=10) hp*=1.25e0;
+                else
+                {  if (k1>=5)  hp*=1.1e0;
+                   else if (k1>=2)   hp*=1.05e0;
+         }  }   }
+      }
+/* ------------------------  End of 1-D search  ------------------  */
+
+/* Store the number of steps made and calculate the average number  */
+
+      if (kg<kstore) kg+=1;
+      if (kg>=2) for (i=kg-1;i>0;i--) nsteps[i]=nsteps[i-1];
+      nsteps[0]=k1;
+      j=0; for (i=0;i<kg;i++) j+=nsteps[i]; evstep=j/kg;
+
+/* Adjust the trial step size  */
+
+      if (evstep<1.75e0)       h/=pow(1.7e0,2.e0-evstep);
+      else if (evstep>2.25e0)  h*=pow(1.1e0,evstep-one);
+      dx=zero; for (i=0;i<n;i++) dx+=(z[i]-x[i])*(z[i]-x[i]); dx=sqrt(dx);
+
+/* COMPUTE THE GRADIENT */
+
+      if (app) {
+            dd=ChMax(1.e-7/pow((k+1),1.5),options[7]);
+            for (i=0;i<n;i++) {
+               d=dd*ChMax(fabs(x[i]),1.e-4);
+               y=x[i]; x[i]=x[i]+d;
+			   fi=fun(x,idData);			// +++++++++
+			   g[i]=(fi-f)/d;   x[i]=y;
+            }
+            options[9]=options[9]+n;
+			if (options[9]>=options[11]) {err_code = 11; goto endrun;}
+      }
+      else  { grad(x,g); options[10]=options[10]+one; }
+
+/* Compute the norm of the gradient:   */
+
+      e2g=zero; for (i=0;i<n;i++) e2g+=g[i]*g[i]; e2g=sqrt(e2g);
+
+/* Check the norm of the gradient: */
+
+    if (e2g<eps)
+    {   // if (options[4]!=-one)
+        //    printf (slv_wrn1);
+        nzero+=1;
+
+      if (nzero<=10)
+      {
+         //g=g0; //prima era cosi' Se voleno fare una copia la facciamo con un for
+         for(i=0;i<n;i++)  //paolo, 29/11/98
+           g[i]=g0[i];
+
+         e2g=zero; for (i=0;i<n;i++) e2g+=g[i]*g[i]; e2g=sqrt(e2g);
+         dx=fabs(h);
+         if (k>nzero+1) h*=2.e0;    /*Enlarge step size to pass through*/
+         else
+         {    h/=2.e0;              /*Reduce step size to find better X*/
+              for (i=0;i<n;i++) x[i]=x1[i];
+              for (i=0;i<n;i++) z[i]=x1[i]+h;
+         }
+      }
+      else
+      {  /* Use a random point: */
+          // if (options[4]!=-one)
+          //       printf(slv_wrn3);
+          if (k>nzero+1) for (i=0;i<n;i++) x[i]=-x[i];
+          else for (i=0;i<n;i++) x[i]*=.9e0;
+          nzero = 0;
+
+          /* COMPUTE THE OBJECTIVE FUNCTION: */
+          f=fun(x,idData);  options[9]+=one;		// ++++++++
+		  if (options[9]>=options[11]) {err_code = 11; goto endrun;}
+          if (fabs(f)>maxf)
+          {  //if (options[4]!=-one)
+             //   printf (slv_err3);
+			 err_code = 3;
+             options[8]=k;
+			 goto endrun;
+          }
+
+          /* COMPUTE THE GRADIENT: */
+          if (app) {
+                dd=ChMax(1.e-7/pow((k+1),1.5),options[7]);
+                for (i=0;i<n;i++) {
+                   d=dd*ChMax(fabs(x[i]),1.e-4);
+                   y=x[i]; x[i]=x[i]+d;
+				   fi=fun(x,idData);			// ++++++++
+				   g[i]=(fi-f)/d; x[i]=y;
+                }
+                 options[9]=options[9]+n;
+				 if (options[9]>=options[11]) {err_code = 11; goto endrun;}
+          }
+          else  { grad(x,g); options[10]=options[10]+one; }
+          /* Compute the norm of the gradient:   */
+          e2g=zero; for (i=0;i<n;i++) e2g+=g[i]*g[i]; e2g=sqrt(e2g);
+          /* Check the norm of the gradient: */
+          if (e2g<eps)
+          { // if (options[4]!=-one)
+            //     printf (slv_wrn1);
+			err_code = 4;
+            options[8]=k;
+			goto endrun;
+          }
+       }  /* nzero check   */
+     }  /* zero gradient  */
+/*-----------------------------------------------------------------
+  DISPLAY THE CURRENT VALUES: */
+       if (k==ld)
+       {  /*printf ("\nIteration # ..... Function Value ..... "
+                  "Step Value ..... Gradient Norm"
+                  "\n     %5i     %13.5g      %13.5g       %13.5g",k,f,dx,e2g);
+          */
+         ld=(unsigned int)(k+floor(options[4]+.1));
+       }
+/*-----------------------------------------------------------------
+  CHECK THE STOPPING CRITERIA: */
+       xrb=zero; for (i=0;i<n;i++) if (xrb<fabs(x[i])) xrb=fabs(x[i]);
+       if (xrb>1.e-8) xlb=ChMax(1.e-8,1.e-8/xrb);
+       else xlb=1.e-8;
+       /* CRITERION FOR THE ARGUMENT :*/
+       termin=1;
+       for (i=0;i<n;i++)
+       {
+		   if (fabs(x[i])>xlb)
+           {
+			 //if (fabs(z[i]-x[i])/fabs(x[i])>=options[1])	// modified by alex in the absolute err form...
+			 if (fabs(z[i]-x[i]) >= options[1])
+             {
+				termin=0;
+				break;
+             }
+           }
+       }
+       if (termin)
+		   kstop+=1;
+       /* CRITERION FOR THE FUNCTION:  */
+       if (termin && ( (app && kstop>=1) || app==0  ) )
+       {
+		  if (fabs(f)>options[2]*options[2])
+          {
+			 // if (fabs((f-fopt)/f)<options[2] )	// modified by alex in the absolute err form...
+			 if (fabs(f-fopt)<options[2] )
+             {
+				 options[8]=k;
+				 goto endrun;
+             }
+          }
+          else
+          {
+			  options[8]=k;
+			  goto endrun;
+          }
+       }
+/*-------------------------------------------------------------------
+  LIMIT ON ITERATIONS  */
+
+       if (k>(options[3]-0.1))
+       {  options[8]=k;
+          //printf (slv_wrn4);
+		  err_code = 7;
+          goto endrun;
+       }
+
+         //paolo 10/01/99
+         if( showDisplay != NULL && showEvery > 0) {
+           if( ++countShowFun > showEvery ) {
+             (*showDisplay)();
+             countShowFun = 0;
+           }
+         }
+
+         if( breakCicle != NULL )
+           if( *breakCicle ) {
+             options[8]=-3;
+			 err_code = 8;
+			 goto endrun;
+           }
+
+		 // Ale 2002
+		 ChOptimizer* moptim = (ChOptimizer*) idData;
+		 if( moptim->user_break) {
+			 options[8]=-3;
+			 err_code = 8;
+			 goto endrun;
+		 }
+
+
+     } /* enddo for the iteration cycle */
+   }  /*  enddo for the resetting cycle */
+
+  endrun:
+
+  /* deallocate working arrays: */
+     free(x1);
+     free(z);
+     free(gt);
+     free(g1);
+     free(g0);
+     free(g);
+     free(B);
+
+  return(f);
+}
+
+
+
+} // END_OF_NAMESPACE____
+
+// eof
+
diff --git a/SRC/ChronoEngine/physics/ChSolvmin.h b/SRC/ChronoEngine/physics/ChSolvmin.h
new file mode 100644
index 0000000..22610a6
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChSolvmin.h
@@ -0,0 +1,510 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSOLVMIN_H
+#define CHSOLVMIN_H
+
+//////////////////////////////////////////////////
+//
+//   ChSolvmin.h
+//
+//   Math functions and 'optimization engine object' for :
+//      - LOCAL NONLINEAR OPTIMIZATION
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+//****
+//**** WARNING! This has been recently refactored, and we still must
+//****          test is the heavy changes have broken some functionality!!!
+//****
+
+#include "physics/ChFx.h"
+#include "physics/ChObject.h"
+
+
+// forward reference
+struct JSScript;
+
+namespace chrono
+{
+
+
+
+
+#define OPT_ERR_OK				0
+#define OPT_ERR_NOVARS			1
+#define OPT_ERR_NOMEMORY		2
+#define OPT_ERR_INFINITY		3
+#define OPT_ERR_CANNOTEVALFX	4
+#define OPT_ERR_CANNOTEVALVAR	5
+#define OPT_ERR_INVALIDSYS		6
+
+#define OPT_IMPOSSIBLE		+999999
+#define OPT_PENALTY_POS 	+999998
+#define OPT_PENALTY_NEG 	-999998
+
+
+
+
+///
+/// Base class for multi-variable optimization.
+///
+
+class ChApi ChOptimizer : public ChObj {
+
+protected:
+	ChFx* afunction;		// the function to be maximized
+	ChFx* afunctionGrad;	// the gradient of the function to be maximized, or null for default BDF.
+
+	int C_vars;			// number of input variables
+
+	double* xv;			// Vector of variables, also 1st approximation.
+	double* xv_sup;		// These are the hi/lo limits for the variables,
+	double* xv_inf;		// these are not used by all optimizer, and can be NULL for gradient, for example, but needed for genetic.
+
+public:
+
+	// ------ DATA
+
+	bool minimize;				///< default = false; just maximize
+ 	double grad_step;			///< default = 1.e-12; step size for evaluation of gradient
+
+	double opt_fx;				///< best resulting value of objective function
+
+	char err_message[200];		///< the ok/warning/error messages are written here
+	int error_code;
+	long fx_evaluations;		///< number of function evaluations
+	long grad_evaluations;		///< number of gradient evaluations
+
+
+	int (*break_funct)();	///< if not null, this function is called each 'break_cycles' evaluations
+	int break_cycles;		///< how many fx evaluations per check
+	int user_break;			///< if break_funct() reported TRUE, this flag is ON, and optimizers should exit all cycles
+	int break_cyclecounter; ///< internal
+
+
+	// ------ FUCTIONS
+
+	ChOptimizer();
+	virtual ~ChOptimizer();
+	virtual void Copy(ChOptimizer* source);
+
+				/// Sets the objective function to maximize
+	virtual void  SetObjective (ChFx* mformula)  {this->afunction=mformula;};
+	virtual ChFx* GetObjective () {return this->afunction;};
+
+				/// Sets the objective function gradient (not mandatory,
+				/// because if not set, the default bacward differentiation is used).
+	virtual void  SetObjectiveGrad (ChFx* mformula)  {this->afunctionGrad=mformula;};
+	virtual ChFx* GetObjectiveGrad () {return this->afunctionGrad;};
+
+				/// Set the number of optimization variables.
+				/// Note: this must be set properly as the number of variables used in the objective function!
+	virtual void  SetNumOfVars(int mv) {C_vars = mv;};
+				/// Returns the number of optimization variables.
+	virtual int  GetNumOfVars() {return C_vars;};
+
+
+				// Gets the vector of variables
+	double* GetXv() {return xv;};
+	double* GetXv_sup() {return xv_sup;};
+	double* GetXv_inf() {return xv_inf;};
+	void SetXv(double* mx) {xv = mx;};
+	void SetXv_sup(double* mx) {xv_sup = mx;};
+	void SetXv_inf(double* mx) {xv_inf = mx;};
+
+
+				/// Returns the value of the functional, for given state of variables
+				/// and with the given "database" multibody system. Here evaluates the string "function".
+	double Eval_fx(double x[]);
+	double Eval_fx(const ChMatrix<>* x);
+
+				/// Computes the gradient of objective function, for given state of variables.
+				/// The gradient is stored into gr vector.
+	void   Eval_grad(double x[], double gr[]);
+	void   Eval_grad(const ChMatrix<>* x, ChMatrix<>* gr);
+
+
+				/// Performs the optimization of the ChSystem pointed by "database"
+				/// (or whatever object which can evaluate the string "function" and the "optvarlist")
+				/// using the current parameters. Returns false if some error occured.
+	virtual int PreOptimize();	// <- this just makes some tests, allocations, and compilations..
+	virtual int DoOptimize();	// <- THIS IS THE STEP WHICH COMPUTES THE OPTIMAL xv[] AND MUST BE IMPLEMENTED BY CHILDREN CLASSES!
+	virtual int PostOptimize();	// <- this just makes deallocations and sets the system as xv[]
+
+				/// Does the three steps in sequence PreOptimize, DoOptimize, PostOptimize.
+				/// The derived classes shouldn't need the definition of this method, because
+				/// they just have to implement the DoOptimize.
+	virtual int Optimize();
+
+				/// Each break_cycles number of times this fx is called, the function break_funct() is
+				/// evaluated (if any) and if positive, the variable user_break becomes true.
+	void DoBreakCheck();
+
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+
+///
+/// Inherited class for local optimization
+/// with the method of pseudo-Newton
+///
+
+class ChApi ChOptimizerLocal : public ChOptimizer
+{
+public:
+
+	// ------ DATA
+
+	// the parameters for optimization
+	double initial_step;		// def = 1; initial trial step size
+	double arg_tol;				// argument rel.error, def 1.e-6
+	double fun_tol;				// function rel error, def 1.e-7
+	int    maxiters;			// max number of iterations, def 50;
+	int    maxevaluations;		// max number of fx evaluations, def 200;
+	double gamma;				// gamma for line search, def 2.001;
+	double dilation;			// space dilation coeff, def. 2.5
+	double gradstep;			// gradient evaluation step, def 1.e-100
+
+	// results and messages
+	long iters_done;			// number of iterations performed (<0 = err)
+
+
+	// ------ FUNCTIONS
+
+	ChOptimizerLocal();
+	virtual ~ChOptimizerLocal();
+	virtual void Copy(ChOptimizerLocal* source);
+
+		// Performs the optimization of the PSystem pointed by "database"
+		// (or whatever object which can evaluate the string "function" and the "optvarlist")
+		// using the current parameters. Returns false if some error occured.
+	virtual int DoOptimize();
+
+
+};
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+
+/// Class for individuals of the population;
+/// for the ChOptimizerGenetic optimization engine.
+
+class ChApi ChGenotype {
+public:
+	ChMatrix<>* genes;		// genetic information (variables defining the individual)
+	double fitness;		// fitness value
+	double rel_fitness;	// relative fitness
+	double cum_fitness;	// cumulative fitness
+	int	   need_eval;	// genes changed, need recomputation of fitness;
+
+	ChGenotype(int number_of_genes);
+	~ChGenotype();
+	void Copy(ChGenotype* source);
+};
+
+
+///
+/// Inherited class for global optimization
+/// with the genetic method (evolutive simulation).
+///
+
+class ChApi ChOptimizerGenetic : public ChOptimizer
+{
+public:
+
+	// ------ DATA
+
+	// the parameters for optimization
+	int	popsize;				// def = 100; initial population size in array "population"
+	ChGenotype** population;	// Array of pointers to population genotypes (NOTE! created and
+								// deleted just within the function Optimize(); null if outside.
+	ChGenotype* best_indiv;		// The copy of the individual with best fitness found in latest
+								// optimization. It always exist, even after termination of optimization.
+	int	max_generations;		// max number of generations to perform
+	int selection;				// reproduction (selection) type (see codes)
+	int	crossover;				// crossover type (see codes)
+	int mutation;				// mutation type;
+	int elite;					// if true, best parent is always kept after crossover
+	int crossv_change;			// see codes above, if NULL the crossover type is always the same
+	int crossv_changeto;		// the type of new crossover if using crossv_change
+	long crossv_changewhen;		// generation number, when the "change of crossover type" takes place
+	double mutation_prob;		// probability of mutation, 0..1, default = 0.001
+	double crossover_prob;		// crossover probability, default = 0.3;
+	int speciation_mating;		// if TRUE, marriage happens between similar individuals;
+	int incest_taboo;			// if TRUE, avoids marriage between individuals too similar
+	int replacement;			// see codes
+	double eugenetics;			// range (0..1); if 0, no eugenetics, otherwise is the clamping for fitness (normalized in 0..1)
+
+	int stop_by_stdeviation;	// if true...		(def: false)
+	double stop_stdeviation;	// stop search if stdeviation becomes lower than this value (def.0)
+	int stop_by_fitness;		// if true...		(def. false)
+	double stop_fitness;		// stop search if fitness of best individual exceed this value (def.0)
+
+	// results and messages
+	double average;				// the average fitness of individuals
+	double stdeviation;			// the unbiased standard deviation (=sqrt(variance)) of fitness
+	double min_fitness;
+	double max_fitness;
+	long generations_done;		// number of generations performed
+	long mutants;				// mutated individuals since start of optimizations
+
+
+	// History of statistic values.  (pointers to external values, not automatically creates/deleted)
+	// If set = NULL (as by default) nothing is recorded.
+	// If they point to external vectors (matrix with one column), they will
+	// be filled generation by generation.
+	ChMatrix<>* his_average;
+	ChMatrix<>* his_stdeviation;
+	ChMatrix<>* his_maxfitness;
+	ChMatrix<>* his_minfitness;
+
+
+	// ------ FUCTIONS
+
+	ChOptimizerGenetic();
+	virtual ~ChOptimizerGenetic();
+	virtual void Copy(ChOptimizerGenetic* source);
+
+		// The optimization procedure.
+		// Performs the optimization of the PSystem pointed by "database"
+		// using the current parameters. Returns false if some error occured.
+	virtual int DoOptimize();
+
+		// Handling of populations
+	int CreatePopulation(ChGenotype**& my_population, int my_popsize);
+	int DeletePopulation(ChGenotype**& my_population, int my_popsize);
+		// Genetic operations on population, used internally by "optimize".
+	ChGenotype* Select_roulette(ChGenotype** my_population);	// returns an individual from my_population, using roulette method
+	ChGenotype* Select_best(ChGenotype** my_population);		// returns an individual from my_population, using roulette method
+	ChGenotype* Select_worst(ChGenotype** my_population);		// returns an individual from population, using roulette method
+	double Get_fitness_interval(ChGenotype** my_population);	// returns fitness max - fitness min
+	double ComputeFitness(ChGenotype*);		// compute fitness for given genotype
+	int ApplyCrossover (ChGenotype* par1, ChGenotype* par2, ChGenotype& child1, ChGenotype& child2);  // apply crossover to two parents, results in childrens
+	int InitializePopulation();	// all population genotypes are initialized with random values of variables
+ 	int ComputeAllFitness();	// all individuals get their fitness values.
+	int Selection();			// the population is selected, according to "selection" parameter.
+	int Crossover();			// new alleles are obtained by crossover of individuals.
+	int Mutation();				// some mutations are performed on the population.
+	int PopulationStats(double& average, double& max, double& min, double& stdeviation);
+	int LogOut(int filelog);		// outputs generation stats to stramLOG file (if filelog TRUE) and to console
+
+};
+
+enum eChGeneticSelection{
+	SELEC_ROULETTE = 0,
+	SELEC_ROULETTEBEST,
+	SELEC_NORMGEOMETRIC,
+	SELEC_TOURNAMENT,
+};
+enum eChGeneticCrossover{
+	CROSSOVER_ARITMETIC = 0,
+	CROSSOVER_BLEND,
+	CROSSOVER_BLEND_RANDOM,
+	CROSSOVER_HEURISTIC,
+	CROSSOVER_DISABLED,
+};
+enum eChGeneticChange{				
+	CRO_CHANGE_NULL = 0,
+	CRO_CHANGE_DATE,
+	CRO_CHANGE_SLOWLY,
+};
+enum eChGeneticMutation{
+	MUTATION_UNIFORM = 0,
+	MUTATION_BOUNDARY,
+};
+enum eChGeneticEliteMode{
+	ELITE_FALSE = 0,
+	ELITE_TRUE,
+};
+enum eChGeneticReplaceMode{				
+	REPLA_PARENTS = 0,
+	REPLA_WORST,
+};
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+///
+/// Inherited class for local optimization
+/// with the cheap method of gradient and bisection
+///
+
+class ChApi ChOptimizerGradient : public ChOptimizer
+{
+public:
+
+	// ------ DATA
+
+	// the parameters for optimization
+	double initial_step;		// def = 1; initial trial step size
+	double arg_tol;				// argument rel.error, def 1.e-6
+	double fun_tol;				// function rel error, def 1.e-7
+	int    maxevaluations;		// max number of fx evaluations, def 800;
+	int    maxgradients;		// max number of gradient evaluations, def 50;
+	int	   maxdilationsteps;	// max number of 'exploring' steps in forward gradient direction (def 8);
+	int    maxbisections;			// number of bisections in climbing interval, before recomputing gradient (def 10);
+	double dilation;			// space dilation coeff, def. 2
+	int	   do_conjugate;		// if true, corrects the gradient by conjugate method (default= off)
+
+
+	// ------ FUNCTIONS
+
+	ChOptimizerGradient();
+	virtual ~ChOptimizerGradient();
+	virtual void Copy(ChOptimizerGradient* source);
+
+		// Performs the optimization of the PSystem pointed by "database"
+		// (or whatever object which can evaluate the string "function" and the "optvarlist")
+		// using the current parameters. Returns false if some error occured.
+	virtual int DoOptimize();
+
+};
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+
+/// Inherited class for genetic optimization followed by
+/// a refinement with the method of gradient, one after the other.
+///  Parameters must be set for the two incapsulated optimizers
+/// genetic_opt and  gradient_opt,  that is  for example:
+/// my_hybrid->genetic_opt->maxgenerations = 200; etc...
+///  However, the optimization variables, the system and the objective function
+/// must be added to the hybrid optimizer itself, which in turn will
+/// automatically set them for the genetic_opt and gradient_opt.
+
+
+class ChApi ChOptimizerHybrid : public ChOptimizer
+{
+public:
+	// ------ DATA
+
+			// The gradient optimizer. Created/deallocated automatically.
+	ChOptimizerGenetic*	genetic_opt;
+			// The gradient optimizer. Created/deallocated automatically.
+	ChOptimizerLocal*		local_opt;
+
+	int current_phase;	// 0 = null, 1 = genetic running, 2 = local running
+	bool use_genetic;	// def. true;
+	bool use_local;		// def. true;
+
+	// ------ FUNCTIONS
+
+	ChOptimizerHybrid();
+	virtual ~ChOptimizerHybrid();
+	virtual void Copy(ChOptimizerHybrid* source);
+
+	virtual void  SetObjective (ChFx* mformula);
+	virtual void  SetObjectiveGrad (ChFx* mformula);
+
+	void SetNumOfVars(int mv);
+
+
+		// Performs the optimization of the PSystem pointed by "database"
+		// (or whatever object which can evaluate the string "function" and the "optvarlist")
+		// using the current parameters. Returns false if some error occured.
+	virtual int DoOptimize();
+
+
+};
+
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////
+
+
+
+////////////////////////////////////////////////////////////
+// A 3rd party function which performs local optimization
+//
+
+ChApi 
+void null_entry_solv_opt(double x[],double g[]);
+
+ChApi 
+double solvopt(unsigned int n,
+               double x[],
+               double  fun(double x[],void * idData),
+               void  grad(double x[],double g[]),
+               double options[],
+               void *  idData,
+               void (*showDisplay)(),
+               int showEvery,
+               int *breakCicle,
+			   int& err_code);
+
+     /*
+              solvopt_options[0]= H, where sign(H)=-1 resp. sign(H)=+1 means minimize
+                          resp. maximize FUN and H itself is a factor for the
+                          initial trial step size (options[0]=-1 by default),
+              solvopt_options[1]= relative error for the argument
+                          in terms of the max-norm (1.e-6 by default),
+              solvopt_options[2]= relative error for the function value (1.e-7 by default),
+              solvopt_options[3]= limit for the number of iterations (5000 by default),
+              solvopt_options[4]= control of the display of intermediate results and
+                          error resp. warning messages (default value is 0,
+                          i.e., no intermediate output but error and warning
+                          messages),
+             @solvopt_options[5]= constant gamma used by the line search procedure
+                          (options[5]=2.001 by default),
+             @solvopt_options[6]= the coefficient of space dilation (2.5 by default),
+             @solvopt_options[7]= lower bound for the stepsize used for the difference
+                          approximation of gradients (1.e-100 by default).
+						   (@ ... changes should be done with care)
+
+              options[8], return the number of iterations, options[8]<0 means
+                            an error occured
+              options[9], return the number of objective function evaluations, and
+              options[10],return the number of gradient evaluations.
+			  options[11],limit on the maximum number of fx evaluations. No default.
+      */
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif
diff --git a/SRC/ChronoEngine/physics/ChStack.h b/SRC/ChronoEngine/physics/ChStack.h
new file mode 100644
index 0000000..839dc00
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChStack.h
@@ -0,0 +1,145 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010 Alessandro Tasora
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSTACK_H
+#define CHSTACK_H
+
+//////////////////////////////////////////////////
+//  
+//   ChStack.h
+//
+//   Class for stack of pointers to items (items
+//   are automatically deleted on stack deletion
+//   or item popping).
+//   If you need a traditional stack, just use the 
+//   stack of STL template library.
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include "core/ChLists.h"
+
+
+namespace chrono 
+{
+
+
+// CLASS FOR STACKS 
+//
+/// Class for generic stack of pointers to items. 
+/// Stacks are used for formula evaluations, for example.
+/// Note that, on stack deletion, also the objects pointed by
+/// the stack items are deleted (this is different from STL stacks).
+/// Also, popping an element, will also delete it, etc.
+/// If you need a 'classical' stack, use the STL template stack instead.
+
+template<class dt>
+class ChStack {
+private: 
+	long maxsize; 
+	long used;
+	ChList<dt>* slist;
+public: 
+	ChStack(long mmaxsize); 
+	~ChStack();
+	void Clear();
+
+	void Set_maxsize(long mm) {maxsize = mm;};
+	int Get_maxsize() {return maxsize;};
+	int Get_used() {return used;};
+
+	ChList<dt>* GetList() {return slist;};
+	dt* GetTop() {return slist->GetHeadData();};
+	dt* GetTail() {return slist->GetHeadData();};
+
+		// Basic stack operations; return NULL if overflow
+	int Push(dt* mp); // loads a data into stack top (no copy of pointed data)
+	int Pop();
+	int Dup();
+	int Swap();	
+};
+
+template<class dt>
+ChStack<dt>::ChStack(long nmaxsize)
+{
+	slist = new ChList<dt>;
+	maxsize = nmaxsize;
+	used = 0;
+}
+template<class dt>
+ChStack<dt>::~ChStack()
+{
+	slist->KillAll(); // remove all pushed nodes and delete also the pointed data!  
+	delete slist;
+}
+template<class dt>
+void ChStack<dt>::Clear()
+{
+	slist->KillAll();
+	delete slist;
+	slist = new ChList<dt>;
+	used = 0;
+}
+template<class dt>
+int ChStack<dt>::Push(dt* mp)
+{
+	if (used >= maxsize) return FALSE;
+	slist->AddHead(mp);
+	used++;
+	return TRUE;
+}
+template<class dt>
+int ChStack<dt>::Pop()
+{
+	if (used <= 0) return FALSE;
+	delete GetTop();	// delete data pointed by top
+	slist->RemHead();
+	used--;
+	return TRUE;
+}
+template<class dt>
+int ChStack<dt>::Dup()
+{
+	dt* newtop = new dt;
+	newtop->Copy(GetTop());
+	return Push(newtop);
+}
+template<class dt>
+int ChStack<dt>::Swap()
+{
+	dt* mpnt0;
+	dt* mpnt1;
+	ChNode<dt>* mn0;
+	ChNode<dt>* mn1;
+	mn0 = slist->GetNum(1);
+	mn1 = slist->GetNum(2);
+	if (mn0 && mn1)
+	{
+		mpnt0 = mn0->data; 
+		mpnt1 = mn1->data;
+		mn0->data = mpnt1; 
+		mn1->data = mpnt0;
+	}
+	else return NULL;
+}
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif  // END of ChFormule.h 
diff --git a/SRC/ChronoEngine/physics/ChSystem.cpp b/SRC/ChronoEngine/physics/ChSystem.cpp
new file mode 100644
index 0000000..1d6ee51
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChSystem.cpp
@@ -0,0 +1,3560 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChSystem.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+ 
+   
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+#include <algorithm>
+ 
+#include "physics/ChSystem.h"
+#include "physics/ChGlobal.h"
+#include "physics/ChBodyAuxRef.h"
+#include "physics/ChContactContainer.h"
+#include "physics/ChProximityContainerBase.h"
+
+#include "lcp/ChLcpSystemDescriptor.h"
+#include "lcp/ChLcpSimplexSolver.h"
+#include "lcp/ChLcpIterativeSOR.h"
+#include "lcp/ChLcpIterativeSymmSOR.h"
+#include "lcp/ChLcpIterativeSORmultithread.h"
+#include "lcp/ChLcpIterativeJacobi.h"
+//#include "lcp/ChLcpIterativeMINRES.h"
+#include "lcp/ChLcpIterativePMINRES.h"
+#include "lcp/ChLcpIterativeBB.h"
+#include "lcp/ChLcpIterativePCG.h"
+#include "lcp/ChLcpIterativeAPGD.h"
+#include "lcp/ChLcpSolverDEM.h"
+#include "parallel/ChOpenMP.h"
+
+#include "core/ChTimer.h"
+#include "collision/ChCCollisionSystemBullet.h"
+#include "collision/ChCModelBulletBody.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+
+
+using namespace chrono::collision;
+
+namespace chrono
+{
+
+
+
+// Hierarchy-handling functions
+
+#define Bpointer		    (*ibody)
+#define HIER_BODY_INIT      std::vector<ChBody*>::iterator ibody = bodylist.begin();
+#define HIER_BODY_NOSTOP    (ibody != bodylist.end())
+#define HIER_BODY_NEXT	    ibody++;
+
+#define Lpointer		    (*iterlink)
+#define HIER_LINK_INIT      std::list<ChLink*>::iterator iterlink = linklist.begin();
+#define HIER_LINK_NOSTOP    (iterlink != linklist.end())
+#define HIER_LINK_NEXT	    iterlink++;
+
+#define PHpointer		    (*iterotherphysics)
+#define HIER_OTHERPHYSICS_INIT    std::list<ChPhysicsItem*>::iterator iterotherphysics = otherphysicslist.begin();
+#define HIER_OTHERPHYSICS_NOSTOP  (iterotherphysics != otherphysicslist.end())
+#define HIER_OTHERPHYSICS_NEXT	  iterotherphysics++;
+
+#define Ppointer		    (*iterprobe)
+#define HIER_PROBE_INIT      std::vector<ChProbe*>::iterator iterprobe = probelist.begin();
+#define HIER_PROBE_NOSTOP    (iterprobe != probelist.end())
+#define HIER_PROBE_NEXT	    iterprobe++;
+
+#define Cpointer		    (*itercontrol)
+#define HIER_CONTROLS_INIT      std::vector<ChControls*>::iterator itercontrol = controlslist.begin();
+#define HIER_CONTROLS_NOSTOP    (itercontrol != controlslist.end())
+#define HIER_CONTROLS_NEXT	    itercontrol++;
+
+
+
+/// Class for iterating through all items of ChPhysicalItem that exist in
+/// a ChSystem. 
+/// It will iterate through: 
+/// - all ChBody          objects
+/// - all ChLink          objects
+/// - all ChPhysicalItems objects that were added, that were not ChBody or ChLink
+/// - the ChContactContainer object that manages all the contacts.
+/// Note that this iterator suffers a small overhead if compared to the use of
+/// three iterator cycles in succession (one over ChBody list, one over ChLink list, etc.)
+/// but it makes the code much more readable. Use it as follows:
+///    IteratorAllPhysics my_iter(this);
+///    while(my_iter.HasItem())
+///    {
+///        my_iter->....
+///        ++my_iter;
+///    }
+
+class IteratorAllPhysics
+{
+public:
+  IteratorAllPhysics(ChSystem* msys) : msystem(msys) 
+  {
+	  RewindToBegin();
+  }
+  ~IteratorAllPhysics() {}
+
+  void RewindToBegin()
+  {
+	  list_bodies = msystem->Get_bodylist();
+	  node_body   = list_bodies->begin();
+	  list_links  = msystem->Get_linklist();
+	  node_link	  = list_links->begin();
+	  list_otherphysics  = msystem->Get_otherphysicslist();
+	  node_otherphysics	 = list_otherphysics->begin();
+	  stage = 0;
+	  mptr = 0;
+	  this->operator++(); // initialize with 1st available item
+  }
+  
+  bool ReachedEnd()
+  {
+	  if (stage == 9999)
+		  return true;
+	  return false;
+  }
+  bool HasItem()
+  {
+	  if (mptr)
+		  return true;
+	  return false;
+  }
+
+  IteratorAllPhysics& operator=(const IteratorAllPhysics& other)
+  {
+	  msystem = other.msystem;
+     //...***TO DO***
+     return(*this);
+  }
+
+  bool operator==(const IteratorAllPhysics& other)
+  {
+     return(msystem == other.msystem); //...***TO COMPLETE***
+  }
+
+  bool operator!=(const IteratorAllPhysics& other)
+  {
+     return!(msystem == other.msystem); 
+  }
+
+  IteratorAllPhysics& operator++()
+  {
+	  switch (stage)
+	  {
+		case 1:
+		{
+			node_body++; // try next body
+			if (node_body != list_bodies->end())
+			{
+				mptr = (*node_body); 
+				return (*this);
+			} 
+			break;
+		}
+		case 2:
+		{
+			node_link++; // try next link
+			if (node_link != list_links->end())
+			{
+				mptr = (*node_link); 
+				return (*this);
+			}
+			break;
+		}
+		case 3:
+		{
+			node_otherphysics++; // try next otherphysics
+			if (node_otherphysics != list_otherphysics->end())
+			{
+				mptr = (*node_otherphysics); 
+				return (*this);
+			}
+			break;
+		}
+		default:
+			break;
+	  }
+	  // Something went wrong, some list was at the end, so jump to beginning of next list
+	  do
+	  {
+		  switch(stage)
+		  {
+		  case 0:
+			  {
+					  stage = 1;
+					  if (node_body != list_bodies->end())
+					  {
+						  mptr = (*node_body); 
+						  return (*this);
+					  } 
+					  break;
+			  }
+		  case 1:
+			  {
+					  stage = 2;
+					  if (node_link != list_links->end())
+					  {
+						  mptr = (*node_link); 
+						  return (*this);
+					  } 
+					  break;
+			  }
+		  case 2:
+			  {
+					  stage = 3;
+					  if (node_otherphysics != list_otherphysics->end())
+					  {
+						  mptr = (*node_otherphysics); 
+						  return (*this);
+					  } 
+					  break;
+			  }
+		  case 3:
+			  {
+					  stage = 4;
+					  mptr = msystem->GetContactContainer(); 
+					  return (*this);
+			  }
+		  case 4:
+			  {
+					  stage = 9999;
+					  mptr = 0; 
+					  return (*this);
+			  }
+		  } // end cases
+	  } while (true);
+
+     return(*this);
+  }
+
+  ChPhysicsItem* operator->()
+  {
+	  return (mptr);
+  }
+  ChPhysicsItem* operator*()
+  {
+	  return (mptr);
+  }
+
+private:
+   std::vector<ChBody*>::iterator node_body;
+   std::vector<ChBody*>* list_bodies;
+   std::list<ChLink*>::iterator node_link;
+   std::list<ChLink*>* list_links;
+   std::list<ChPhysicsItem*>::iterator node_otherphysics;
+   std::list<ChPhysicsItem*>* list_otherphysics;
+   ChPhysicsItem* mptr;
+   int stage;
+   ChSystem* msystem;
+};
+
+
+
+
+//////////////////////////////////////
+//////////////////////////////////////
+// CLASS FOR PHYSICAL SYSTEM
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChSystem> a_registration_ChSystem;
+
+
+ChSystem::ChSystem(unsigned int max_objects, double scene_size, bool init_sys)
+{
+	linklist.clear(); 
+	bodylist.clear();
+	otherphysicslist.clear();
+	probelist.clear();
+	controlslist.clear();
+	
+	
+	nbodies=0;
+	nlinks=0;
+	nphysicsitems=0;
+	ndof=0;
+	ndoc=0;
+	ndoc_w=0;
+	ndoc_w_C=0;
+	ndoc_w_D=0;
+	nsysvars_w = 0;
+	ncoords=0;
+	ncoords_w=0;
+	nsysvars = 0;
+	ncoords_w=0;
+	ncontacts = 0;
+	nbodies_sleep=0;
+	nbodies_fixed=0;
+
+				// ------ PREFERENCES INITIALIZATION :
+	ChTime = 0;
+
+	end_time = 1;
+	step = 0.04;
+	step_min = 0.002;
+	step_max = 0.04;
+	tol = 0.0002;
+	tol_speeds = 1e-6;
+	normtype = NORM_INF;
+	maxiter = 6;
+	order = 1;
+	SetMultisteps(1);
+	dynaclose = 1;
+	ns_close_pos = 1;
+	ns_close_speed = 3;
+	predict = FALSE;
+	SetPredorder(2);
+	dynatol = 10;
+	stifftol = 3.2;
+	monolat_tol = 2.5;
+	integr_tol = 1.0;
+	adaption  = STEP_FIXED;
+	SetIntegrationType (INT_ANITESCU);
+	modeXY = FALSE;
+	auto_assembly = FALSE;
+	contact_container = 0;
+
+	msteps_collide = 6;
+	min_bounce_speed = 0.15;
+	max_penetration_recovery_speed = 0.6;
+
+	parallel_thread_number = CHOMPfunctions::GetNumProcs(); // default n.threads as n.cores
+
+	this->contact_container=0;
+	// default contact container
+	if(init_sys){
+		this->contact_container = new ChContactContainer();
+	}
+	collision_system=0;
+	// default GPU collision engine
+	if(init_sys){
+		collision_system = new ChCollisionSystemBullet(max_objects, scene_size);
+	}
+	
+
+	LCP_descriptor = 0;
+	LCP_solver_speed = 0;
+	LCP_solver_stab = 0;
+
+	iterLCPmaxIters = 30;
+	iterLCPmaxItersStab = 10;
+	simplexLCPmaxSteps = 100;
+	if(init_sys){
+		SetLcpSolverType(LCP_ITERATIVE_SYMMSOR);
+	}
+	
+	use_GPU = false;
+	use_sleeping = false;
+
+	collision_callback = 0;
+	collisionpoint_callback = 0;
+
+	err_integr = 0.0;
+	err_constr = 0.0;
+
+	Set_G_acc (ChVector<>(0, -9.8, 0));
+ 
+	stepcount = 0;
+
+	last_err = 0;
+	strcpy (err_message, "");
+ 
+	scriptEngine = 0;
+	scriptForStart = NULL;
+	scriptForUpdate = NULL;
+	scriptForStep = NULL;
+	scriptFor3DStep = NULL;
+	strcpy (scriptForStartFile, "");
+	strcpy (scriptForUpdateFile, "");
+	strcpy (scriptForStepFile, "");
+	strcpy (scriptFor3DStepFile, "");
+
+	events = new ChEvents(250);
+
+	timer_step = 0;
+	timer_lcp = 0;
+	timer_collision_broad = 0;
+	timer_collision_narrow = 0;
+	timer_update = 0;
+}
+
+
+ChSystem::~ChSystem()
+{
+
+	RemoveAllBodies(); 
+	RemoveAllLinks();
+	RemoveAllOtherPhysicsItems();
+	RemoveAllProbes();
+	RemoveAllControls();
+
+	if (LCP_solver_speed) delete LCP_solver_speed; LCP_solver_speed=0;
+	if (LCP_solver_stab)  delete LCP_solver_stab;  LCP_solver_stab=0;
+	if (LCP_descriptor) delete LCP_descriptor; LCP_descriptor=0;
+	
+	if (collision_system) delete collision_system; collision_system = 0;
+	if (contact_container) delete contact_container; contact_container = 0;
+
+	if (events) delete events; events = 0;
+
+	if (scriptForStart)	 delete scriptForStart;
+	if (scriptForUpdate) delete scriptForUpdate;
+	if (scriptForStep)   delete scriptForStep;
+	if (scriptFor3DStep) delete scriptFor3DStep;
+}
+
+void ChSystem::Copy(ChSystem* source)
+{
+	// first copy the parent class data...
+	ChObj::Copy(source);
+
+	G_acc = source->Get_G_acc();
+	end_time = source->GetEndTime();
+	step = source->GetStep();
+	step_min = source->GetStepMin();
+	step_max = source->GetStepMax();
+	SetIntegrationType (source->GetIntegrationType());
+	order = source->GetOrder();
+	multisteps = source->GetMultisteps();
+	tol = source->GetTol();
+	tol_speeds = source->tol_speeds;
+	normtype = source->GetNormType();
+	maxiter = source->GetMaxiter();
+	adaption = source->GetAdaption();
+	nbodies = source->GetNbodies();
+	nlinks = source->GetNlinks();
+	nphysicsitems = source->GetNphysicsItems();
+	ncoords = source->GetNcoords();
+	ncoords_w = source->GetNcoords_w();
+	ndoc = source->GetNdoc();
+	ndoc_w = source->GetNdoc_w();
+	ndoc_w_C = source->GetNdoc_w_C();
+	ndoc_w_D = source->GetNdoc_w_D();
+	ndof = source->GetNdof();
+	nsysvars = source->GetNsysvars();
+	nsysvars_w = source->GetNsysvars_w();
+	ncontacts = source->GetNcontacts();
+	nbodies_sleep = source->GetNbodiesSleeping();
+	nbodies_fixed = source->GetNbodiesFixed();
+	dynaclose = source->GetDynaclose();
+	ns_close_pos = source->GetNsClosePos();
+	ns_close_speed = source->GetNsCloseSpeed();
+	dynatol = source->GetDynatol();
+	monolat_tol = source->GetMonolattol();
+	integr_tol = source->GetIntegrtol();
+	predict = source->GetPredict();
+	predorder = source->GetPredorder();
+	stifftol = source->GetStifftol();
+	modeXY = source->modeXY;
+	err_integr = err_constr = 0.0;
+	msteps_collide = source->msteps_collide;
+	min_bounce_speed = source->min_bounce_speed;
+	max_penetration_recovery_speed = source->max_penetration_recovery_speed;
+	iterLCPmaxIters = source->iterLCPmaxIters;
+	iterLCPmaxItersStab = source->iterLCPmaxItersStab;
+	simplexLCPmaxSteps = source->simplexLCPmaxSteps;
+	SetLcpSolverType(GetLcpSolverType());
+	parallel_thread_number = source->parallel_thread_number;
+	use_GPU = source->use_GPU;
+	use_sleeping = source->use_sleeping;
+	timer_step = source->timer_step;
+	timer_lcp = source->timer_lcp;
+	timer_collision_broad = source->timer_collision_broad;
+	timer_collision_narrow = source->timer_collision_narrow;
+	timer_update = source->timer_update;
+
+	collision_callback = source->collision_callback;
+	collisionpoint_callback = source->collisionpoint_callback;
+
+	last_err = source->last_err;
+	memcpy (err_message, source->err_message, (sizeof(char)*CHSYS_ERRLEN));
+
+	RemoveAllLinks(); 
+	RemoveAllBodies(); 
+	RemoveAllProbes();
+	RemoveAllControls();
+
+	events->ResetAllEvents(); // don't copy events.
+
+
+	SetScriptForStartFile(source->scriptForStartFile);
+	SetScriptForUpdateFile(source->scriptForUpdateFile);
+	SetScriptForStepFile(source->scriptForStepFile);
+	SetScriptFor3DStepFile(source->scriptFor3DStepFile);
+
+	ChTime = source->ChTime;
+}
+
+void ChSystem::Clear()
+{
+
+	nbodies=0;
+	nlinks=0;
+	nphysicsitems=0;
+	ndof=0;
+	ndoc=0;
+	ndoc_w=0;
+	ndoc_w_C=0;
+	ndoc_w_D=0;
+	nsysvars_w=0;
+	ncoords=0;
+	ncoords_w=0;
+	nsysvars = 0;
+	ncoords_w=0;
+	ncontacts = 0;
+	nbodies_sleep = 0;
+	nbodies_fixed = 0;
+
+	events->ResetAllEvents();
+
+	//contact_container->RemoveAllContacts();
+
+	RemoveAllLinks();
+	RemoveAllBodies();
+	RemoveAllOtherPhysicsItems();
+	RemoveAllProbes();
+	RemoveAllControls();
+
+	//ResetTimers();
+}
+
+//
+// Set/Get routines
+//
+
+void ChSystem::SetLcpSolverType(eCh_lcpSolver mval)
+{
+	lcp_solver_type = mval;
+
+	use_GPU = false;
+
+	if (LCP_solver_speed) delete LCP_solver_speed; LCP_solver_speed=0;
+	if (LCP_solver_stab)  delete LCP_solver_stab;  LCP_solver_stab=0;
+	if (LCP_descriptor) delete LCP_descriptor; LCP_descriptor=0;
+	if (contact_container) delete contact_container; contact_container=0;
+
+	LCP_descriptor = new ChLcpSystemDescriptor;
+	LCP_descriptor->SetNumThreads(parallel_thread_number);
+
+	contact_container = new ChContactContainer;
+	
+
+	switch (mval)
+	{
+	case LCP_ITERATIVE_SOR:  
+		LCP_solver_speed = new ChLcpIterativeSOR(); 
+		LCP_solver_stab  = new ChLcpIterativeSOR();
+		break;
+	case LCP_ITERATIVE_SYMMSOR:
+		LCP_solver_speed = new ChLcpIterativeSymmSOR();
+		LCP_solver_stab  = new ChLcpIterativeSymmSOR();
+		break; 
+	case LCP_SIMPLEX:
+		LCP_solver_speed = new ChLcpSimplexSolver();
+		LCP_solver_stab  = new ChLcpSimplexSolver();
+		break;
+	case LCP_ITERATIVE_JACOBI:
+		LCP_solver_speed = new ChLcpIterativeJacobi();
+		LCP_solver_stab  = new ChLcpIterativeJacobi();
+		break;
+	case LCP_ITERATIVE_SOR_MULTITHREAD:
+		LCP_solver_speed = new ChLcpIterativeSORmultithread((char*)"speedLCP",parallel_thread_number);
+		LCP_solver_stab = new ChLcpIterativeSORmultithread((char*)"posLCP",parallel_thread_number);
+		break;
+	case LCP_ITERATIVE_PMINRES: 
+		LCP_solver_speed = new ChLcpIterativePMINRES();
+		LCP_solver_stab = new ChLcpIterativePMINRES();
+		break;
+	case LCP_ITERATIVE_BARZILAIBORWEIN:
+		LCP_solver_speed = new ChLcpIterativeBB();
+		LCP_solver_stab = new ChLcpIterativeBB();
+		break;
+	case LCP_ITERATIVE_PCG:
+		LCP_solver_speed = new ChLcpIterativePCG();
+		LCP_solver_stab = new ChLcpIterativePCG();
+		break;
+	case LCP_ITERATIVE_APGD:
+		LCP_solver_speed = new ChLcpIterativeAPGD();
+		LCP_solver_stab = new ChLcpIterativeAPGD();
+		break;
+	case LCP_DEM:
+		LCP_solver_speed = new ChLcpSolverDEM();
+		LCP_solver_stab = new ChLcpSolverDEM();
+		break;
+	default:
+		LCP_solver_speed = new ChLcpIterativeSymmSOR();
+		LCP_solver_stab  = new ChLcpIterativeSymmSOR();
+		break;
+	} 
+}  
+
+
+ChLcpSolver* ChSystem::GetLcpSolverSpeed()
+{
+	// in case the solver is iterative, pre-configure it with max.iter.number
+	switch(lcp_solver_type)
+	{
+	case LCP_DEM:
+		break;
+	case LCP_SIMPLEX:
+		((ChLcpSimplexSolver*)LCP_solver_speed)->SetTruncationStep(GetSimplexLCPmaxSteps());
+		break;
+	default:
+		ChLcpIterativeSolver* iter_solver = (ChLcpIterativeSolver*)LCP_solver_speed;
+		iter_solver->SetMaxIterations(GetIterLCPmaxItersSpeed());
+		iter_solver->SetTolerance(this->tol_speeds); 
+		break;
+	}
+	/*
+	if (lcp_solver_type != LCP_SIMPLEX)
+	{
+		ChLcpIterativeSolver* iter_solver = (ChLcpIterativeSolver*)LCP_solver_speed;
+		iter_solver->SetMaxIterations(GetIterLCPmaxItersSpeed());
+		iter_solver->SetTolerance(this->tol_speeds); 
+	}
+	else 
+	{ 
+		ChLcpSimplexSolver* simplex_solver = (ChLcpSimplexSolver*)LCP_solver_speed;
+		simplex_solver->SetTruncationStep(GetSimplexLCPmaxSteps());
+	}
+	*/
+	return LCP_solver_speed;
+}
+
+ChLcpSolver* ChSystem::GetLcpSolverStab()
+{
+	// in case the solver is iterative, pre-configure it with max.iter.number
+	if (lcp_solver_type != LCP_SIMPLEX)
+	{
+		ChLcpIterativeSolver* iter_solver = (ChLcpIterativeSolver*)LCP_solver_stab;
+		iter_solver->SetMaxIterations(GetIterLCPmaxItersStab());
+		iter_solver->SetTolerance(this->tol);
+	}
+	else
+	{
+		ChLcpSimplexSolver* simplex_solver = (ChLcpSimplexSolver*)LCP_solver_stab;
+		simplex_solver->SetTruncationStep(GetSimplexLCPmaxSteps());
+	}
+	return LCP_solver_stab;
+}
+
+void ChSystem::SetIterLCPwarmStarting(bool usewarm)
+{
+	if (ChLcpIterativeSolver* iter_solver_speed = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_speed))
+	{
+		iter_solver_speed->SetWarmStart(usewarm);
+	}
+	if (ChLcpIterativeSolver* iter_solver_stab = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_stab))
+	{
+		iter_solver_stab->SetWarmStart(usewarm);
+	}
+}
+
+bool ChSystem::GetIterLCPwarmStarting()
+{
+	if (ChLcpIterativeSolver* iter_solver_speed = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_speed))
+	{
+		return iter_solver_speed->GetWarmStart();
+	}
+	return false;
+}
+
+void ChSystem::SetIterLCPomega(double momega)
+{
+	if (ChLcpIterativeSolver* iter_solver_speed = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_speed))
+	{
+		iter_solver_speed->SetOmega(momega);
+	}
+	if (ChLcpIterativeSolver* iter_solver_stab = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_stab))
+	{
+		iter_solver_stab->SetOmega(momega);
+	}
+}
+
+double ChSystem::GetIterLCPomega()
+{
+	if (ChLcpIterativeSolver* iter_solver_speed = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_speed))
+	{
+		return iter_solver_speed->GetOmega();
+	}
+	return 1.0;
+}
+
+void ChSystem::SetIterLCPsharpnessLambda(double momega)
+{
+	if (ChLcpIterativeSolver* iter_solver_speed = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_speed))
+	{
+		iter_solver_speed->SetSharpnessLambda(momega);
+	}
+	if (ChLcpIterativeSolver* iter_solver_stab = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_stab))
+	{
+		iter_solver_stab->SetSharpnessLambda(momega);
+	}
+}
+
+double ChSystem::GetIterLCPsharpnessLambda()
+{
+	if (ChLcpIterativeSolver* iter_solver_speed = dynamic_cast<ChLcpIterativeSolver*>(LCP_solver_speed))
+	{
+		return iter_solver_speed->GetSharpnessLambda();
+	}
+	return 1.0;
+}
+
+
+void ChSystem::SetParallelThreadNumber(int mthreads)
+{
+	if (mthreads<1) 
+		mthreads =1;
+
+	parallel_thread_number = mthreads;
+	
+	LCP_descriptor->SetNumThreads(mthreads);
+
+	if (lcp_solver_type == LCP_ITERATIVE_SOR_MULTITHREAD)
+	{
+		((ChLcpIterativeSORmultithread*)LCP_solver_speed)->ChangeNumberOfThreads(mthreads);
+		((ChLcpIterativeSORmultithread*)LCP_solver_stab)->ChangeNumberOfThreads(mthreads);
+	}
+}
+
+
+
+
+// Plug-in components configuration
+
+
+void ChSystem::ChangeLcpSystemDescriptor(ChLcpSystemDescriptor* newdescriptor)
+{
+	assert (newdescriptor);
+	if (this->LCP_descriptor) 
+		delete (this->LCP_descriptor);
+	this->LCP_descriptor = newdescriptor;
+}
+void ChSystem::ChangeLcpSolverSpeed(ChLcpSolver* newsolver)
+{
+	assert (newsolver);
+	if (this->LCP_solver_speed) 
+		delete (this->LCP_solver_speed);
+	this->LCP_solver_speed = newsolver;
+}
+
+void ChSystem::ChangeLcpSolverStab(ChLcpSolver* newsolver)
+{
+	assert (newsolver);
+	if (this->LCP_solver_stab) 
+		delete (this->LCP_solver_stab);
+	this->LCP_solver_stab = newsolver;
+} 
+
+void ChSystem::ChangeContactContainer(ChContactContainerBase* newcontainer)
+{
+	assert (newcontainer);
+	if (this->contact_container) 
+		delete (this->contact_container);
+	this->contact_container = newcontainer;
+}
+
+void ChSystem::ChangeCollisionSystem(ChCollisionSystem* newcollsystem)
+{
+	assert (this->GetNbodies()==0);
+	assert (newcollsystem);
+	if (this->collision_system) 
+		delete (this->collision_system);
+	this->collision_system = newcollsystem;
+}
+
+// JS commands
+
+
+int ChSystem::SetScriptForStartFile(char* mfile)
+{
+	if (!this->scriptEngine) return 0;
+	strcpy (this->scriptForStartFile, mfile);
+	this->scriptForStart = this->scriptEngine->CreateScript();
+	return this->scriptEngine->FileToScript(*this->scriptForStart, mfile);
+}
+int ChSystem::SetScriptForUpdateFile(char* mfile)
+{
+	if (!this->scriptEngine) return 0;
+	strcpy (this->scriptForUpdateFile, mfile);
+	this->scriptForUpdate = this->scriptEngine->CreateScript();
+	return this->scriptEngine->FileToScript(*this->scriptForUpdate, mfile);
+}
+int ChSystem::SetScriptForStepFile(char* mfile)
+{
+	if (!this->scriptEngine) return 0;
+	strcpy (this->scriptForStepFile, mfile);
+	this->scriptForStep = this->scriptEngine->CreateScript();
+	return this->scriptEngine->FileToScript(*this->scriptForStep, mfile);
+}
+int ChSystem::SetScriptFor3DStepFile(char* mfile)
+{
+	if (!this->scriptEngine) return 0;
+	strcpy (this->scriptFor3DStepFile, mfile);
+	this->scriptFor3DStep = this->scriptEngine->CreateScript();
+	return this->scriptEngine->FileToScript(*this->scriptFor3DStep, mfile);
+}
+
+int ChSystem::ExecuteScriptForStart()
+{
+	if (!this->scriptEngine) return 0;
+	return this->scriptEngine->ExecuteScript(*this->scriptForStart);
+}
+int ChSystem::ExecuteScriptForUpdate()
+{
+	if (!this->scriptEngine) return 0;
+	return this->scriptEngine->ExecuteScript(*this->scriptForUpdate);
+}
+int ChSystem::ExecuteScriptForStep()
+{
+	if (!this->scriptEngine) return 0;
+	return this->scriptEngine->ExecuteScript(*this->scriptForStep);
+}
+int ChSystem::ExecuteScriptFor3DStep()
+{
+	if (!this->scriptEngine) return 0;
+	return this->scriptEngine->ExecuteScript(*this->scriptFor3DStep);
+}
+
+
+// PROBE STUFF
+
+int ChSystem::RecordAllProbes()
+{
+	int pcount = 0;
+
+	HIER_PROBE_INIT
+	while HIER_PROBE_NOSTOP
+	{
+		Ppointer->Record(this->GetChTime());
+
+		HIER_PROBE_NEXT
+	}
+
+	return pcount;
+}
+
+int ChSystem::ResetAllProbes()
+{
+	int pcount = 0;
+
+	HIER_PROBE_INIT
+	while HIER_PROBE_NOSTOP
+	{
+		Ppointer->Reset();
+
+		HIER_PROBE_NEXT
+	}
+
+	return pcount;
+}
+
+// CONTROLS STUFF
+
+
+int ChSystem::ExecuteControlsForStart()
+{
+	HIER_CONTROLS_INIT
+	while HIER_CONTROLS_NOSTOP
+	{
+		Cpointer->ExecuteForStart();
+		HIER_CONTROLS_NEXT
+	}
+	return TRUE;
+}
+
+int ChSystem::ExecuteControlsForUpdate()
+{
+	HIER_CONTROLS_INIT
+	while HIER_CONTROLS_NOSTOP
+	{
+		Cpointer->ExecuteForUpdate();
+		HIER_CONTROLS_NEXT
+	}
+	return TRUE;
+}
+
+int ChSystem::ExecuteControlsForStep()
+{
+	HIER_CONTROLS_INIT
+	while HIER_CONTROLS_NOSTOP
+	{
+		Cpointer->ExecuteForStep();
+		HIER_CONTROLS_NEXT
+	}
+	return TRUE;
+}
+
+int ChSystem::ExecuteControlsFor3DStep()
+{
+	HIER_CONTROLS_INIT
+	while HIER_CONTROLS_NOSTOP
+	{
+		Cpointer->ExecuteFor3DStep();
+		HIER_CONTROLS_NEXT
+	}
+	return TRUE;
+}
+
+
+
+
+// 
+// HIERARCHY HANDLERS
+//
+
+
+
+void ChSystem::AddBody (ChSharedPtr<ChBody> newbody)
+{
+	assert(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), newbody.get_ptr())==bodylist.end());
+	assert(newbody->GetSystem()==0); // should remove from other system before adding here
+
+	newbody->AddRef();
+	newbody->SetSystem (this);
+	bodylist.push_back((newbody).get_ptr());
+
+	// add to collision system too
+	if (newbody->GetCollide())
+		newbody->AddCollisionModelsToSystem(); 
+}
+
+void ChSystem::RemoveBody (ChSharedPtr<ChBody> mbody)
+{
+	assert(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), mbody.get_ptr() )!=bodylist.end());
+
+	// remove from collision system
+	if (mbody->GetCollide())
+		mbody->RemoveCollisionModelsFromSystem(); 
+ 
+	// warning! linear time search, to erase pointer from container.
+	bodylist.erase(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), mbody.get_ptr() ) );
+	
+	// nullify backward link to system
+	mbody->SetSystem(0);
+	// this may delete the body, if none else's still referencing it..
+	mbody->RemoveRef();
+}
+   
+void ChSystem::AddLink (ChLink* newlink)
+{ 
+	assert(std::find<std::list<ChLink*>::iterator>(linklist.begin(), linklist.end(), newlink)==linklist.end());
+
+	newlink->AddRef();
+	newlink->SetSystem (this);
+	linklist.push_back(newlink);
+}
+
+void ChSystem::AddLink (ChSharedPtr<ChLink> newlink)
+{
+	AddLink(newlink.get_ptr());
+}
+
+// Faster than RemoveLink because it does not require the linear time search
+std::list<ChLink*>::iterator ChSystem::RemoveLinkIter(std::list<ChLink*>::iterator& mlinkiter)
+{
+	// nullify backward link to system
+	(*mlinkiter)->SetSystem(0);
+	// this may delete the link, if none else's still referencing it..
+	(*mlinkiter)->RemoveRef();
+
+	return linklist.erase(mlinkiter);
+}
+
+void ChSystem::RemoveLink (ChSharedPtr<ChLink> mlink)
+{
+	assert(std::find<std::list<ChLink*>::iterator>(linklist.begin(), linklist.end(), mlink.get_ptr() )!=linklist.end());
+
+	// warning! linear time search, to erase pointer from container.
+	linklist.remove(mlink.get_ptr());//erase(std::find<std::vector<ChBody*>::iterator>(bodylist.begin(), bodylist.end(), mbody.get_ptr() ) );
+	
+	// nullify backward link to system
+	mlink->SetSystem(0);
+	// this may delete the body, if none else's still referencing it..
+	mlink->RemoveRef();
+}
+
+
+void ChSystem::AddOtherPhysicsItem (ChSharedPtr<ChPhysicsItem> newitem)
+{
+	assert(std::find<std::list<ChPhysicsItem*>::iterator>(otherphysicslist.begin(), otherphysicslist.end(), newitem.get_ptr())==otherphysicslist.end());
+	//assert(newitem->GetSystem()==0); // should remove from other system before adding here
+
+	newitem->AddRef();
+	newitem->SetSystem (this);
+	otherphysicslist.push_back((newitem).get_ptr());
+
+	// add to collision system too
+	if (newitem->GetCollide())
+		newitem->AddCollisionModelsToSystem(); 
+}
+
+void ChSystem::RemoveOtherPhysicsItem (ChSharedPtr<ChPhysicsItem> mitem)
+{
+	assert(std::find<std::list<ChPhysicsItem*>::iterator>(otherphysicslist.begin(), otherphysicslist.end(), mitem.get_ptr())!=otherphysicslist.end());
+
+	// remove from collision system
+	if (mitem->GetCollide())
+		mitem->RemoveCollisionModelsFromSystem();
+ 
+	// warning! linear time search, to erase pointer from container.
+	otherphysicslist.erase(std::find<std::list<ChPhysicsItem*>::iterator>(otherphysicslist.begin(), otherphysicslist.end(), mitem.get_ptr() ) );
+	
+	// nullify backward link to system
+	mitem->SetSystem(0);
+	// this may delete the body, if none else's still referencing it..
+	mitem->RemoveRef();
+}
+
+void ChSystem::Add (ChSharedPtr<ChPhysicsItem> newitem)
+{
+	if (typeid(*newitem.get_ptr())==typeid(ChBody))
+	{
+		AddBody((ChSharedPtr<ChBody>)newitem);
+	}else
+		if (dynamic_cast<ChLink*>(newitem.get_ptr()))
+		{
+			AddLink((ChSharedPtr<ChLink>)newitem);
+		}else
+			  AddOtherPhysicsItem(newitem);
+}
+
+void ChSystem::Remove (ChSharedPtr<ChPhysicsItem> newitem)
+{
+	if (typeid(*newitem.get_ptr())==typeid(ChBody))
+	{
+		RemoveBody((ChSharedPtr<ChBody>)newitem);
+	}else
+		if (dynamic_cast<ChLink*>(newitem.get_ptr()))
+		{
+			RemoveLink((ChSharedPtr<ChLink>)newitem);
+		}else
+			  RemoveOtherPhysicsItem(newitem);
+}
+
+
+
+void ChSystem::AddProbe (ChSharedPtr<ChProbe>& newprobe)
+{
+	assert(std::find<std::vector<ChProbe*>::iterator>(probelist.begin(), probelist.end(), newprobe.get_ptr())==probelist.end());
+
+	newprobe->AddRef();
+	//newprobe->SetSystem (this);
+	probelist.push_back(newprobe.get_ptr());
+}
+
+void ChSystem::AddControls (ChSharedPtr<ChControls>& newcontrols)
+{
+	assert(std::find<std::vector<ChControls*>::iterator>(controlslist.begin(), controlslist.end(), newcontrols.get_ptr())==controlslist.end());
+
+	newcontrols->AddRef();
+	//newcontrols->SetSystem (this);
+	controlslist.push_back(newcontrols.get_ptr());
+}
+
+
+   
+void ChSystem::RemoveAllBodies() 
+{ 
+	HIER_BODY_INIT
+	while (HIER_BODY_NOSTOP)
+	{
+		// remove from collision system
+		if (Bpointer->GetCollide())
+			Bpointer->RemoveCollisionModelsFromSystem(); 
+		// nullify backward link to system
+		Bpointer->SetSystem(0);	
+		// this may delete the body, if none else's still referencing it..
+		Bpointer->RemoveRef();
+		HIER_BODY_NEXT
+	}	
+	bodylist.clear(); 
+}; 
+
+
+void ChSystem::RemoveAllLinks() 
+{ 
+
+	HIER_LINK_INIT
+	while (HIER_LINK_NOSTOP)
+	{
+		// nullify backward link to system
+		Lpointer->SetSystem(0);	
+		// this may delete the link, if none else's still referencing it..
+		Lpointer->RemoveRef();
+		HIER_LINK_NEXT
+	}	
+	linklist.clear(); 
+};
+
+void ChSystem::RemoveAllOtherPhysicsItems() 
+{ 
+	HIER_OTHERPHYSICS_INIT
+	while (HIER_OTHERPHYSICS_NOSTOP)
+	{
+		// remove from collision system
+		if (PHpointer->GetCollide())
+			PHpointer->RemoveCollisionModelsFromSystem();  
+		// nullify backward link to system
+		PHpointer->SetSystem(0);	
+		// this may delete the item, if none else's still referencing it..
+		PHpointer->RemoveRef();
+		HIER_OTHERPHYSICS_NEXT
+	}	
+	otherphysicslist.clear(); 
+}; 
+
+void ChSystem::RemoveAllProbes() 
+{ 
+	HIER_PROBE_INIT
+	while (HIER_PROBE_NOSTOP)
+	{
+		//Ppointer->SetSystem(0);	
+		Ppointer->RemoveRef();
+		HIER_PROBE_NEXT
+	}	
+	probelist.clear();
+};
+
+void ChSystem::RemoveAllControls() 
+{ 
+	HIER_CONTROLS_INIT
+	while (HIER_CONTROLS_NOSTOP)
+	{
+		//Cpointer->SetSystem(0);	
+		Cpointer->RemoveRef();
+		HIER_CONTROLS_NEXT
+	}	
+	controlslist.clear();
+};
+ 
+
+ 
+
+ChSharedPtr<ChBody> ChSystem::SearchBody (char* m_name)
+{
+	ChBody* mbody = ChContainerSearchFromName<ChBody, std::vector<ChBody*>::iterator>
+				(m_name, 
+				bodylist.begin(), 
+				bodylist.end());
+	if (mbody)
+	{
+		mbody->AddRef(); // in that container pointers were not stored as ChSharedPtr, so this is needed..
+		return (ChSharedPtr<ChBody>(mbody));  // ..here I am not getting a new() data, but a reference to something created elsewhere
+	}
+	return (ChSharedPtr<ChBody>()); // not found? return a void shared ptr.
+}
+
+ChSharedPtr<ChLink> ChSystem::SearchLink (char* m_name)
+{
+	ChLink* mlink = ChContainerSearchFromName<ChLink, std::list<ChLink*>::iterator>
+				(m_name, 
+				linklist.begin(), 
+				linklist.end());
+	if (mlink)
+	{
+		mlink->AddRef(); // in that container pointers were not stored as ChSharedPtr, so this is needed..
+		return (ChSharedPtr<ChLink>(mlink));  // ..here I am not getting a new() data, but a reference to something created elsewhere
+	}
+	return (ChSharedPtr<ChLink>()); // not found? return a void shared ptr.
+}
+
+ChSharedPtr<ChPhysicsItem> ChSystem::SearchOtherPhysicsItem (char* m_name)
+{
+	ChPhysicsItem* mitem = ChContainerSearchFromName<ChPhysicsItem, std::list<ChPhysicsItem*>::iterator>
+				(m_name, 
+				otherphysicslist.begin(), 
+				otherphysicslist.end());
+	if (mitem)
+	{
+		mitem->AddRef(); // in that container pointers were not stored as ChSharedPtr, so this is needed..
+		return (ChSharedPtr<ChPhysicsItem>(mitem));  // ..here I am not getting a new() data, but a reference to something created elsewhere
+	}
+	return (ChSharedPtr<ChPhysicsItem>()); // not found? return a void shared ptr.
+}
+
+ChSharedPtr<ChPhysicsItem> ChSystem::Search (char* m_name)
+{
+	ChSharedPtr<ChBody> mbo = SearchBody(m_name);
+	if (!mbo.IsNull())
+		return mbo;
+	ChSharedPtr<ChLink> mli = SearchLink(m_name);
+	if (!mli.IsNull())
+		return mli;
+	ChSharedPtr<ChPhysicsItem> mph = SearchOtherPhysicsItem(m_name);
+	if (!mph.IsNull())
+		return mph;
+	return (ChSharedPtr<ChPhysicsItem>()); // not found? return a void shared ptr.
+}
+
+
+ChSharedPtr<ChMarker> ChSystem::SearchMarker (char* m_name)
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		ChSharedPtr<ChMarker> mmark = Bpointer->SearchMarker(m_name);
+		if (!mmark.IsNull())
+			return mmark;
+		HIER_BODY_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		if (ChBodyAuxRef* mbodyauxref = dynamic_cast<ChBodyAuxRef*>(PHpointer))
+		{
+			ChSharedPtr<ChMarker> mmark = mbodyauxref->SearchMarker(m_name);
+			if (!mmark.IsNull())
+				return mmark;
+		}
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	return (ChSharedPtr<ChMarker>()); // not found? return a void shared ptr.
+}
+
+ChSharedPtr<ChMarker> ChSystem::SearchMarker (int markID)
+{
+	ChMarker* candidate = NULL;
+	ChMarker* res = NULL;
+
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		res = ChContainerSearchFromID<ChMarker, std::vector<ChMarker*>::iterator>
+				(markID, 
+				Bpointer->GetMarkerList()->begin(), 
+				Bpointer->GetMarkerList()->end());
+		if (res != NULL) 
+		{
+			res->AddRef(); // in that container pointers were not stored as ChSharedPtr, so this is needed..
+			return (ChSharedPtr<ChMarker>(res));  // ..here I am not getting a new() data, but a reference to something created elsewhere		
+		}
+
+		HIER_BODY_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		if (ChBodyAuxRef* mbodyauxref = dynamic_cast<ChBodyAuxRef*>(PHpointer))
+		{
+			res = ChContainerSearchFromID<ChMarker, std::vector<ChMarker*>::iterator>
+				(markID, 
+				mbodyauxref->GetMarkerList()->begin(), 
+				mbodyauxref->GetMarkerList()->end());
+			if (res != NULL) 
+			{
+				res->AddRef(); // in that container pointers were not stored as ChSharedPtr, so this is needed..
+				return (ChSharedPtr<ChMarker>(res));  // ..here I am not getting a new() data, but a reference to something created elsewhere		
+			}
+		}
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	return (ChSharedPtr<ChMarker>()); // not found? return a void shared ptr.
+}
+
+
+
+
+
+
+
+void ChSystem::Reference_LM_byID()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		if (ChLinkMarkers* malink = ChDynamicCast(ChLinkMarkers,Lpointer))
+		{
+			ChSharedPtr<ChMarker> shm1 = SearchMarker(malink->GetMarkID1());
+			ChSharedPtr<ChMarker> shm2 = SearchMarker(malink->GetMarkID2());
+			ChMarker* mm1 = shm1.get_ptr();
+			ChMarker* mm2 = shm1.get_ptr();
+			malink->SetMarker1(mm1);
+			malink->SetMarker2(mm2);
+			if (mm1 && mm2)
+			{
+				Lpointer->SetValid(true);
+				HIER_LINK_NEXT
+			}
+			else
+			{
+				Lpointer->SetValid(false);
+				malink->SetMarkers(0,0); // however marker IDs will survive!!
+				iterlink = RemoveLinkIter(iterlink); // may delete it...
+			}
+		}
+		else
+		{
+			HIER_LINK_NEXT
+		}
+	}
+}
+
+//////
+////// PREFERENCES
+
+
+void ChSystem::SetIntegrationType (eCh_integrationType m_integration)
+{									
+	// set integration scheme:
+	integration_type = m_integration;				
+	
+	// set stability region
+	switch (integration_type)
+	{
+		case INT_ANITESCU:
+			SetMultisteps (1);
+			SetOrder (1);
+		case INT_TASORA:
+			SetMultisteps (1);
+			SetOrder (1);
+		default:
+			SetMultisteps (1);
+	}
+	// ......... //
+}
+
+
+
+
+
+void ChSystem::WakeUpSleepingBodies()
+{
+	// Make this class for iterating through contacts (if supported by
+	// contact container)
+
+	class _wakeup_reporter_class : public ChReportContactCallback 
+	{
+	public:
+				/// Callback, used to report contact points already added to the container.
+				/// This must be implemented by a child class of ChReportContactCallback.
+				/// If returns false, the contact scanning will be stopped.
+		virtual bool ReportContactCallback (
+						const ChVector<>& pA,				///< get contact pA
+						const ChVector<>& pB,				///< get contact pB
+						const ChMatrix33<>& plane_coord,	///< get contact plane coordsystem (A column 'X' is contact normal)
+						const double& distance,				///< get contact distance
+						const float& mfriction,			  	///< get friction info
+						const ChVector<>& react_forces,		///< get react.forces (if already computed). In coordsystem 'plane_coord'
+						const ChVector<>& react_torques,	///< get react.torques, if rolling friction (if already computed)
+						collision::ChCollisionModel* modA,	///< get model A (note: some containers may not support it and could be zero!)
+						collision::ChCollisionModel* modB	///< get model B (note: some containers may not support it and could be zero!)
+											) 
+		{
+			if (!(modA && modB)) 
+				return true;
+			ChBody* b1=0;
+			ChBody* b2=0;
+			if (ChModelBulletBody* mmboA = dynamic_cast<ChModelBulletBody*>(modA))
+				b1 = mmboA->GetBody();
+			if (ChModelBulletBody* mmboB = dynamic_cast<ChModelBulletBody*>(modB))
+				b2 = mmboB->GetBody();
+			if (!(b1 && b2)) 
+				return true;
+			bool sleep1 = b1->GetSleeping();
+			bool sleep2 = b2->GetSleeping();
+			bool ground1 = b1->GetBodyFixed();
+			bool ground2 = b2->GetBodyFixed();
+			if (sleep1 && !sleep2 && !ground2)
+			{
+				b1->SetSleeping(false);
+			}
+			if (sleep2 && !sleep1 && !ground1)
+			{
+				b2->SetSleeping(false);
+			}
+			this->someone_sleeps = sleep1 | sleep2 | this->someone_sleeps;
+
+			return true; // to continue scanning contacts
+		}
+
+		// Data 
+		bool someone_sleeps;
+	};
+
+	_wakeup_reporter_class my_waker;
+
+	if (this->GetUseSleeping())
+	{
+		for (int i=0; i<1; i++)  //***TO DO*** reconfigurable number of wakeup cycles
+		{
+			my_waker.someone_sleeps = false;
+
+			// scan all links and wake connected bodies
+			HIER_LINK_INIT
+			while HIER_LINK_NOSTOP
+			{
+				if (Lpointer->IsRequiringWaking())
+				{
+					Lpointer->GetBody1()->SetSleeping(false);
+					Lpointer->GetBody2()->SetSleeping(false);
+				}
+				HIER_LINK_NEXT
+			}
+			
+			// scan all contacts and wake neighbouring bodies
+			this->contact_container->ReportAllContacts(&my_waker);
+			
+			// bailout wakeup cycle prematurely, if all bodies are not sleeping
+			if (!my_waker.someone_sleeps) 
+				break; 
+		}
+	}
+}
+
+
+
+
+////////////////////////////////
+//////
+////// UPDATING ROUTINES
+//////
+//////
+
+
+		// COUNT ALL BODIES AND LINKS, ETC, COMPUTE &SET DOF FOR STATISTICS,
+		// ALLOCATES OR REALLOCATE BOOKKEEPING DATA/VECTORS, IF ANY
+
+int ChSystem::Setup()
+{
+	events->Record(CHEVENT_SETUP);
+
+	int need_update = FALSE;
+	int old_ncoords  = ncoords ;
+	int old_ndoc = ndoc;
+	int old_ndoc_w_D = ndoc_w_D;
+	
+	nbodies = 0;
+	nbodies_sleep = 0;
+	nbodies_fixed = 0;
+	ncoords=0;
+	ncoords_w=0;
+	ndoc =0;
+	ndoc_w =0;
+	ndoc_w_C = 0;
+	ndoc_w_D = 0;
+	nlinks = 0;
+	nphysicsitems = 0;
+
+							
+	HIER_BODY_INIT					
+	while HIER_BODY_NOSTOP		
+	{
+		if (!Bpointer->GetBodyFixed())
+		{
+			if (!Bpointer->GetSleeping())
+			{
+				nbodies ++;	// Count bodies and indicize them.
+			}
+			else
+			{
+				nbodies_sleep ++;
+			}
+		}
+		else
+		{
+			nbodies_fixed ++;
+		}
+ 
+		HIER_BODY_NEXT
+	}
+
+	ncoords_w += nbodies * 6;
+	ncoords   += nbodies * 7; // with quaternion coords
+	ndoc	  += nbodies; // There is a quaternion constr. for each active body.
+
+
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		nphysicsitems ++;	
+
+		ncoords_w += PHpointer->GetDOF();
+		ndoc_w	  += PHpointer->GetDOC();
+		ndoc_w_C  += PHpointer->GetDOC_c();
+		ndoc_w_D  += PHpointer->GetDOC_d();
+
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		nlinks ++;
+
+		ndoc_w   += Lpointer->GetDOC();
+		ndoc_w_C += Lpointer->GetDOC_c();
+		ndoc_w_D += Lpointer->GetDOC_d();
+
+		HIER_LINK_NEXT
+	}
+
+	ndoc_w_D += contact_container->GetDOC_d();
+
+
+	ndoc = ndoc_w + nbodies;		// sets number of constraints including quaternion constraints.
+	nsysvars   = ncoords   + ndoc;  // sets number of total variables (=coordinates + lagrangian multipliers)
+	nsysvars_w = ncoords_w + ndoc_w;// sets number of total variables (with 6 dof per body)
+
+	ndof= ncoords - ndoc;			// sets number of left degrees of freedom (approximate - does not consider constr. redundancy, etc)
+
+	return need_update;
+}
+
+
+
+		// - ALL PHYSICAL ITEMS (BODIES, LINKS,ETC.) ARE UPDATED,
+		//   ALSO UPDATING THEIR AUXILIARY VARIABLES (ROT.MATRICES, ETC.).
+		// - UPDATES ALL FORCES  (AUTOMATIC, AS CHILDREN OF BODIES)
+		// - UPDATES ALL MARKERS (AUTOMATIC, AS CHILDREN OF BODIES).
+
+void ChSystem::Update() 
+{
+
+	ChTimer<double>mtimer; mtimer.start(); // Timer for profiling
+
+
+	events->Record(CHEVENT_UPDATE); // Record an update event
+
+									// Executes the "forUpdate" script, if any
+	ExecuteScriptForUpdate();
+									// Executes the "forUpdate" script
+									// in all controls of controlslist
+	ExecuteControlsForUpdate();
+
+									// --------------------------------------
+									// Spread state vector Y to bodies
+									//    Y --> Bodies
+	HIER_BODY_INIT					//    Y_accel --> Bodies
+	while HIER_BODY_NOSTOP			// Updates recursively all other aux.vars
+	{								// --------------------------------------
+		Bpointer->Update(ChTime);  
+
+		if (this->GetUseSleeping())
+			Bpointer->TrySleeping();
+
+		HIER_BODY_NEXT
+	}
+									// -----------------------------
+									// Updates other physical items
+									// -----------------------------
+	HIER_OTHERPHYSICS_INIT					
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->Update(ChTime);
+
+		HIER_OTHERPHYSICS_NEXT
+	}
+									// -----------------------------
+									// Updates all links
+									// -----------------------------
+	HIER_LINK_INIT					
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->Update(ChTime);
+
+		HIER_LINK_NEXT
+	}
+
+	this->contact_container->Update(); // Update all contacts, if any
+
+	mtimer.stop();
+	timer_update += mtimer();
+}
+
+
+
+
+void ChSystem::UpdateExternalGeometry ()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->UpdateExternalGeometry ();
+
+		HIER_BODY_NEXT
+	}
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->UpdateExternalGeometry ();
+
+		HIER_LINK_NEXT
+	}
+}
+
+
+
+
+///////////////////////////////
+/////////
+/////////   SPARSE LCP BOOKKEEPING
+/////////
+
+
+void ChSystem::LCPprepare_reset()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsBiReset();
+		HIER_LINK_NEXT
+	}
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesFbReset();
+		HIER_BODY_NEXT
+	}	
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->VariablesFbReset();
+		PHpointer->ConstraintsBiReset();
+		HIER_OTHERPHYSICS_NEXT
+	}
+	this->contact_container->ConstraintsBiReset();
+}
+
+
+void ChSystem::LCPprepare_load(bool load_jacobians,
+							   bool load_Mv,
+							   double F_factor,
+							   double K_factor,		
+							   double R_factor,
+							   double M_factor,
+							   double Ct_factor,
+							   double C_factor,
+							   double recovery_clamp,
+							   bool do_clamp
+							    )
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		if (C_factor)
+			Lpointer->ConstraintsBiLoad_C(C_factor, recovery_clamp, do_clamp);
+		if (Ct_factor)
+			Lpointer->ConstraintsBiLoad_Ct(Ct_factor);			// Ct
+		if (F_factor)
+			Lpointer->ConstraintsFbLoadForces(F_factor);		// f*dt
+		if (load_Mv)
+		{
+			Lpointer->VariablesQbLoadSpeed();					//   v_old 
+			Lpointer->VariablesFbIncrementMq();					// M*v_old
+		}
+		if (load_jacobians)
+			Lpointer->ConstraintsLoadJacobians();
+		HIER_LINK_NEXT
+	}
+
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		if (F_factor)
+			Bpointer->VariablesFbLoadForces(F_factor);			// f*dt
+		if (load_Mv)
+		{
+			Bpointer->VariablesQbLoadSpeed();					//   v_old 
+			Bpointer->VariablesFbIncrementMq();					// M*v_old
+		} 
+		HIER_BODY_NEXT
+	}
+
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		if (F_factor)
+			PHpointer->VariablesFbLoadForces(F_factor);			// f*dt
+		if (load_Mv)
+		{
+			PHpointer->VariablesQbLoadSpeed();					//   v_old 
+			PHpointer->VariablesFbIncrementMq();				// M*v_old
+		}
+		if (C_factor)
+			PHpointer->ConstraintsBiLoad_C(C_factor, recovery_clamp, do_clamp);
+		if (Ct_factor)
+			PHpointer->ConstraintsBiLoad_Ct(Ct_factor);			// Ct
+		if (load_jacobians)
+			PHpointer->ConstraintsLoadJacobians();
+		if (K_factor || R_factor || M_factor)
+			PHpointer->KRMmatricesLoad(K_factor, R_factor, M_factor);
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	if (C_factor)
+		contact_container->ConstraintsBiLoad_C(C_factor, recovery_clamp, do_clamp);
+	if (F_factor)
+		contact_container->ConstraintsFbLoadForces(F_factor);		// f*dt
+	if (load_jacobians)
+		contact_container->ConstraintsLoadJacobians();
+
+} 
+
+void ChSystem::LCPprepare_inject(ChLcpSystemDescriptor& mdescriptor)
+{
+	mdescriptor.BeginInsertion(); // This resets the vectors of constr. and var. pointers.
+
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->InjectConstraints(mdescriptor);
+		HIER_LINK_NEXT
+	}
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->InjectVariables(mdescriptor);
+		HIER_BODY_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->InjectVariables(mdescriptor);
+		PHpointer->InjectConstraints(mdescriptor);
+		PHpointer->InjectKRMmatrices(mdescriptor);
+		HIER_OTHERPHYSICS_NEXT
+	}
+	this->contact_container->InjectConstraints(mdescriptor);
+
+	mdescriptor.EndInsertion(); 
+}
+
+
+void ChSystem::LCPprepare_Li_from_speed_cache()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiLoadSuggestedSpeedSolution();
+		HIER_LINK_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->ConstraintsLiLoadSuggestedSpeedSolution();
+		HIER_OTHERPHYSICS_NEXT
+	}
+	this->contact_container->ConstraintsLiLoadSuggestedSpeedSolution();
+}
+
+void ChSystem::LCPprepare_Li_from_position_cache()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiLoadSuggestedPositionSolution();
+		HIER_LINK_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->ConstraintsLiLoadSuggestedPositionSolution();
+		HIER_OTHERPHYSICS_NEXT
+	}
+	this->contact_container->ConstraintsLiLoadSuggestedPositionSolution();
+}
+
+void ChSystem::LCPresult_Li_into_speed_cache()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiFetchSuggestedSpeedSolution();
+		HIER_LINK_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->ConstraintsLiFetchSuggestedSpeedSolution();
+		HIER_OTHERPHYSICS_NEXT
+	}
+	this->contact_container->ConstraintsLiFetchSuggestedSpeedSolution();
+}
+
+void ChSystem::LCPresult_Li_into_position_cache()
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsLiFetchSuggestedPositionSolution();
+		HIER_LINK_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->ConstraintsLiFetchSuggestedPositionSolution();
+		HIER_OTHERPHYSICS_NEXT
+	}
+	this->contact_container->ConstraintsLiFetchSuggestedPositionSolution();
+}
+
+void ChSystem::LCPresult_Li_into_reactions(double mfactor)
+{
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->ConstraintsFetch_react(mfactor);
+		HIER_LINK_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->ConstraintsFetch_react(mfactor);
+		HIER_OTHERPHYSICS_NEXT
+	}
+	this->contact_container->ConstraintsFetch_react(mfactor);
+}
+
+
+// obsolete?
+void ChSystem::SetXYmode (int m_mode)
+{
+	modeXY = m_mode;
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		Lpointer->Set2Dmode(m_mode);
+		HIER_LINK_NEXT
+	}
+}
+
+
+
+
+
+
+
+//////////////////////////////////
+////////
+////////    COLLISION OPERATIONS
+////////
+
+
+int ChSystem::GetNcontacts()
+{
+	return this->contact_container->GetNcontacts();
+}
+
+
+void ChSystem::SynchronizeLastCollPositions()
+{
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		if (Bpointer->GetCollide())
+			Bpointer->SynchronizeLastCollPos();
+		HIER_BODY_NEXT
+	}
+}
+
+ 
+
+
+class SystemAddCollisionPointCallback : public ChAddContactCallback
+{
+public: 
+	ChSystem* client_system;
+	virtual void ContactCallback (const collision::ChCollisionInfo& mcontactinfo, ///< pass info about contact (cannot change it)
+								  ChMaterialCouple&  material 			  		///< you can modify this!
+								)
+	{
+		if (client_system->collisionpoint_callback)
+			client_system->collisionpoint_callback->ContactCallback(mcontactinfo, material);
+	}	
+};
+
+double ChSystem::ComputeCollisions()
+{
+	double mretC= 0.0; 
+
+	ChTimer<double> mtimer;  
+	mtimer.start();
+
+	// Update all positions of collision models	
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->SyncCollisionModels();
+		HIER_BODY_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->SyncCollisionModels();
+		HIER_OTHERPHYSICS_NEXT
+	}
+ 
+	// Prepare the callback
+
+	// In case there is some user callback for each added point..
+	SystemAddCollisionPointCallback mpointcallback;
+	if (collisionpoint_callback)
+	{
+		mpointcallback.client_system = this;
+		this->contact_container->SetAddContactCallback(&mpointcallback);
+	} else 
+		this->contact_container->SetAddContactCallback(0);
+
+	// !!! Perform the collision detection ( broadphase and narrowphase ) !!!
+	
+	collision_system->Run();
+
+	// Report and store contacts and/or proximities, if there are some 
+	// containers in the physic system. The default contact container
+	// for ChBody and ChParticles is used always.
+
+	collision_system->ReportContacts(this->contact_container);
+
+	{
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		if (ChContactContainerBase* mcontactcontainer = dynamic_cast<ChContactContainerBase*>(PHpointer))
+		{
+			collision_system->ReportContacts(mcontactcontainer);
+		}
+		if (ChProximityContainerBase* mproximitycontainer = dynamic_cast<ChProximityContainerBase*>(PHpointer))
+		{
+			collision_system->ReportProximities(mproximitycontainer);
+		}
+		HIER_OTHERPHYSICS_NEXT
+	}
+	}
+
+	// If some other collision engine could add further ChLinkContact into the list.. 
+	if (collision_callback)
+		collision_callback->PerformCustomCollision(this);
+
+	// Count the contacts of body-body type.
+	this->ncontacts = this->contact_container->GetNcontacts();
+
+	mtimer.stop();
+	this->timer_collision_broad = mtimer();
+
+	return mretC;
+}
+
+
+
+
+
+///////////////////////////////////
+////////
+////////   PHYSICAL OPERATIONS
+////////
+
+
+
+
+
+//  PERFORM AN INTEGRATION STEP.  ----
+//
+//  Advances a single time step.
+//
+//  Note that time step can be modified if some variable-time stepper is used.
+//
+//
+
+
+
+// internal codes for m_repeat: if FALSE (null or 0) the step won't repeat
+//#define TRUE_REFINE 1
+//#define TRUE_FORCED 2
+
+
+int ChSystem::Integrate_Y()
+{
+	switch (integration_type)
+	{
+		case INT_ANITESCU:
+			return Integrate_Y_impulse_Anitescu();
+		case INT_TASORA:
+			return Integrate_Y_impulse_Tasora();
+		default:
+			return Integrate_Y_impulse_Anitescu();
+	}
+
+	return TRUE;
+}
+
+
+
+//
+//  PERFORM ANITESCU INTEGRATION STEP  -IMPULSIVE METHOD-
+//
+//  ...but using the differential inclusion approach, better for 
+//  systems with contacts (use the Anitescu method, with stabilization)
+//
+ 
+
+int ChSystem::Integrate_Y_impulse_Anitescu()
+{
+	int ret_code = TRUE;
+
+	ChTimer<double> mtimer_step;
+	mtimer_step.start();
+
+	events->Record(CHEVENT_TIMESTEP);
+
+								// Executes the "forStep" script, if any
+	ExecuteScriptForStep();
+								// Executes the "forStep" script
+								// in all controls of controlslist
+	ExecuteControlsForStep();
+
+
+	this->stepcount++;
+
+	// Compute contacts and create contact constraints
+
+	ComputeCollisions();
+
+
+	Setup();	// Counts dofs, statistics, etc.
+
+
+	Update();	// Update everything - and put to sleep bodies that need it
+
+				// Re-wake the bodies that cannot sleep because they are in contact with
+				// some body that is not in sleep state.
+	WakeUpSleepingBodies();
+
+
+	ChTimer<double> mtimer_lcp;
+	mtimer_lcp.start();
+
+
+	//
+	// Enforce velocity/impulses constraints ....................
+	//
+
+	// reset known-term vectors
+	LCPprepare_reset();
+
+	// fill LCP known-term vectors with proper terms (forces, etc.):
+	//
+	// | M+dt^2*K+dt*R -Cq'|*|v_new|- | [M]*v_old + f*dt      | = |0| ,  c>=0, l>=0, l*c=0;
+	// | Cq              0 | |l    |  | -C/dt +min(-C/dt,vlim)|   |c|
+	//
+
+	LCPprepare_load(true,		    // Cq,
+					true,			// adds [M]*v_old to the known vector
+					GetStep(),      // f*dt
+					GetStep()*GetStep(), // dt^2*K  (nb only non-Schur based solvers support K matrix blocks)
+					GetStep(),		// dt*R   (nb only non-Schur based solvers support R matrix blocks)
+					1.0,			// M (for FEM with non-lumped masses, add their mass-matrixes)
+					1.0,		    // Ct   (needed, for rheonomic motors)
+					1.0/GetStep(),  // C/dt
+					max_penetration_recovery_speed,	 // vlim, max penetrations recovery speed (positive for exiting)
+					true);			// do above max. clamping on -C/dt
+
+	// if warm start is used, can exploit cached multipliers from last step...
+	LCPprepare_Li_from_speed_cache(); 
+
+	// make vectors of variables and constraints, used by the following LCP solver
+	LCPprepare_inject(*this->LCP_descriptor);
+
+
+	// Solve the LCP problem.
+	// Solution variables are new speeds 'v_new'
+	GetLcpSolverSpeed()->Solve(
+							*this->LCP_descriptor
+							);
+	mtimer_lcp.stop();
+	timer_lcp = mtimer_lcp();
+
+	// stores computed multipliers in constraint caches, maybe useful for warm starting next step 
+	LCPresult_Li_into_speed_cache();
+
+	// updates the reactions of the constraint
+	LCPresult_Li_into_reactions(1.0/this->GetStep()) ; // R = l/dt  , approximately
+ 
+	// perform an Eulero integration step (1st order stepping as pos+=v_new*dt)
+
+
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		// EULERO INTEGRATION: pos+=v_new*dt  (do not do this, if GPU already computed it)
+		if (!use_GPU)
+		{
+			Bpointer->VariablesQbIncrementPosition(this->GetStep());
+			// Set body speed, and approximates the acceleration by differentiation.
+			Bpointer->VariablesQbSetSpeed(this->GetStep());
+		}
+		// Now also updates all markers & forces
+		Bpointer->Update(this->ChTime);
+		HIER_BODY_NEXT
+	}
+ 	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		// EULERO INTEGRATION: pos+=v_new*dt  (do not do this, if GPU already computed it)
+		if (!use_GPU)
+		{
+			PHpointer->VariablesQbIncrementPosition(this->GetStep());
+			// Set body speed, and approximates the acceleration by differentiation.
+			PHpointer->VariablesQbSetSpeed(this->GetStep());
+		}
+		// Now also updates all markers & forces
+		PHpointer->Update(this->ChTime);
+		HIER_OTHERPHYSICS_NEXT
+	}
+ 
+	this->ChTime = ChTime + GetStep();
+
+	// Executes custom processing at the end of step
+	CustomEndOfStep();
+
+	// If there are some probe objects in the probe list,
+	// tell them to record their variables (ususally x-y couples)
+	RecordAllProbes();
+
+	// Time elapsed for step..
+	mtimer_step.stop();
+	timer_step = mtimer_step();
+
+
+	return (ret_code);
+}
+
+
+
+//
+//  PERFORM TASORA INTEGRATION STEP  -IMPULSIVE METHOD-
+//
+//  ...but using the differential inclusion approach, better for 
+//  systems with contacts (use the Tasora method, with separate 
+//  positional stabilization)
+//
+
+
+int ChSystem::Integrate_Y_impulse_Tasora()
+{
+	int ret_code = TRUE;
+
+	ChTimer<double> mtimer_step;
+	mtimer_step.start();
+
+	events->Record(CHEVENT_TIMESTEP);
+
+								// Executes the "forStep" script, if any
+	ExecuteScriptForStep();
+								// Executes the "forStep" script
+								// in all controls of controlslist
+	ExecuteControlsForStep();
+
+
+	this->stepcount++;
+
+
+	// Compute contacts and create contact constraints
+
+	ComputeCollisions();
+
+
+	Setup();	// Counts dofs, statistics, etc.
+
+	Update();	// Update everything - and put to sleep bodies that need it
+
+				// Re-wake the bodies that cannot sleep because they are in contact with
+				// some body that is not in sleep state.
+	WakeUpSleepingBodies();
+
+
+	ChTimer<double> mtimer_lcp;
+	mtimer_lcp.start();
+
+
+	// 1-
+	// Enforce velocity/impulses constraints ....................
+	//
+ 
+	// reset known-term vectors
+	LCPprepare_reset();
+
+	// fill LCP known-term vectors with proper terms (forces, etc.):
+	//
+	// | M -Cq'|*|v_new|- | [M]*v_old + f*dt    | = |0| ,  c>=0, l>=0, l*c=0;
+	// | Cq  0 | |l    |  |  - Ct +min(-C/dt,0) |   |c|
+	//
+
+	LCPprepare_load(true,			// Cq
+					true,			// adds [M]*v_old to the known vector
+					GetStep(),      // f*dt
+					GetStep()*GetStep(), // dt^2*K  (nb only non-Schur based solvers support K matrix blocks)
+					GetStep(),		// dt*R   (nb only non-Schur based solvers support K matrix blocks)
+					1.0,			// M (for FEM with non-lumped masses, add their mass-matrices)
+					1.0,			// Ct      (needed, for rheonomic motors)
+					1.0/GetStep(),  // C/dt
+					0.0,			// max constr.recovery speed (positive for exiting) 
+					true);			// do above max. clamping on -C/dt
+
+	// if warm start is used, can exploit cached multipliers from last step...
+	LCPprepare_Li_from_speed_cache();
+
+	// make vectors of variables and constraints, used by the following LCP solver
+	LCPprepare_inject(*this->LCP_descriptor);
+
+
+	// Solve the LCP problem. 
+	// Solution variables are new speeds 'v_new'
+	
+	GetLcpSolverSpeed()->Solve(
+							*this->LCP_descriptor
+							);  
+		
+	// stores computed multipliers in constraint caches, maybe useful for warm starting next step 
+	LCPresult_Li_into_speed_cache();
+
+	// updates the reactions of the constraint
+	LCPresult_Li_into_reactions(1.0/this->GetStep()); // R = l/dt  , approximately
+
+
+	// perform an Eulero integration step (1st order stepping as pos+=v_new*dt)
+
+
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		// EULERO INTEGRATION: pos+=v_new*dt
+		Bpointer->VariablesQbIncrementPosition(this->GetStep());
+		// Set body speed, and approximates the acceleration by differentiation.
+		Bpointer->VariablesQbSetSpeed(this->GetStep());
+
+		// Now also updates all markers & forces
+		//Bpointer->UpdateALL(this->ChTime); // not needed - will be done later anyway
+		HIER_BODY_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		// EULERO INTEGRATION: pos+=v_new*dt
+		PHpointer->VariablesQbIncrementPosition(this->GetStep());
+		// Set body speed, and approximates the acceleration by differentiation.
+		PHpointer->VariablesQbSetSpeed(this->GetStep());
+
+		// Now also updates all markers & forces
+		//PHpointer->UpdateALL(this->ChTime); // not needed - will be done later anyway
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	this->ChTime = ChTime + GetStep();
+ 
+
+	// 2-
+	// Stabilize constraint positions ....................
+	//
+
+	// reset known-term vectors
+	LCPprepare_reset();
+
+	// Fill known-term vectors with proper terms 0 and -C :
+	//
+	// | M -Cq'|*|Dpos|- |0 |= |0| ,  c>=0, l>=0, l*c=0;
+	// | Cq  0 | |l   |  |-C|  |c|
+	//
+	
+	LCPprepare_load(false,  // Cq are already there.. 
+					false,  // no addition of M*v in known term 
+					0,		// no forces
+					0,		// no K matrix
+					0,		// no R matrix
+					1.0,	// M (for FEM with non-lumped masses, add their mass-matrices)
+					0,		// no Ct term
+					1.0,	// C
+					0.0,	// recovery max speed (not used)
+					false);	// no clamping on -C term
+
+	// if warm start is used, can exploit cached multipliers from last step...
+	LCPprepare_Li_from_position_cache();
+
+	// Solve the LCP problem.
+	// Solution variables are 'Dpos', delta positions.
+
+	GetLcpSolverStab()->Solve(
+							*this->LCP_descriptor
+							);
+
+	// stores computed multipliers in constraint caches, maybe useful for warm starting next step 
+	LCPresult_Li_into_position_cache();
+
+	{
+		HIER_BODY_INIT
+		while HIER_BODY_NOSTOP
+		{
+			Bpointer->VariablesQbIncrementPosition(1.0); // pos+=Dpos
+			// Now also updates all markers & forces
+			Bpointer->Update(this->ChTime);
+			HIER_BODY_NEXT
+		}
+		HIER_OTHERPHYSICS_INIT
+		while HIER_OTHERPHYSICS_NOSTOP
+		{
+			PHpointer->VariablesQbIncrementPosition(1.0); // pos+=Dpos
+			// Now also updates all markers & forces
+			PHpointer->Update(this->ChTime);
+			HIER_OTHERPHYSICS_NEXT
+		} 
+	}
+
+
+	mtimer_lcp.stop();
+	timer_lcp = mtimer_lcp();
+
+	// Executes custom processing at the end of step
+	CustomEndOfStep();
+
+	// If there are some probe objects in the probe list,
+	// tell them to record their variables (ususally x-y couples)
+	RecordAllProbes();
+
+
+	// Time elapsed for step..
+	mtimer_step.stop();
+	timer_step = mtimer_step();
+
+
+	return (ret_code);
+}
+
+
+
+
+// **** SATISFY ALL COSTRAINT EQUATIONS WITH NEWTON
+// **** ITERATION, UNTIL TOLERANCE SATISFIED, THEN UPDATE
+// **** THE "Y" STATE WITH SetY (WHICH AUTOMATICALLY UPDATES
+// **** ALSO AUXILIARY MATRICES).
+
+int ChSystem::DoAssembly(int action, int mflags)
+{
+	Setup();
+	Update();
+
+
+	if (action & ASS_POSITION)		// (1)--------  POSITION
+	{
+
+		for (int m_iter = 0; m_iter < maxiter; m_iter++)
+		{
+
+			if (mflags & ASF_COLLISIONS)
+			{
+				// Compute new contacts and create contact constraints
+				ComputeCollisions();
+
+				Setup();	// Counts dofs, statistics, etc.
+				Update();	// Update everything
+			}
+			
+
+			// reset known-term vectors
+			LCPprepare_reset();
+
+			// Fill known-term vectors with proper terms 0 and -C :
+			//
+			// | M -Cq'|*|Dpos|- |0 |= |0| ,  c>=0, l>=0, l*c=0;
+			// | Cq  0 | |l   |  |-C|  |c|
+			//
+
+			LCPprepare_load(true,  // Cq 
+					false,	// no addition of M*v in known term 
+					0,		// no forces
+					0,		// no K matrix
+					0,		// no R matrix
+					1.0,	// M (for FEM with non-lumped masses, add their mass-matrices)
+					0,		// no Ct term
+					1.0,	// C
+					0.0,	// 
+					false);	// no clamping on -C/dt
+			
+			// make the vectors of pointers to constraint and variables, for LCP solver
+			LCPprepare_inject(*this->LCP_descriptor);
+
+			// exit Newton loop if reached tolerance..
+			double max_res, max_LCPerr;
+			this->LCP_descriptor->ComputeFeasabilityViolation(max_res, max_LCPerr);
+			if (max_res <= this->tol)
+			{
+				//reached_tolerance = TRUE;
+				break;		// stop Newton when reached C tolerance |||||||| :-)
+			}
+
+
+				// Solve the LCP problem.
+				// Solution variables are 'Dpos', delta positions.
+				// Note: use settings of the 'speed' lcp solver (i.e. use max number
+				// of iterations as you would use for the speed probl., if iterative solver)
+			GetLcpSolverSpeed()->Solve(
+									*this->LCP_descriptor
+									);
+
+			// Move bodies to updated position
+			HIER_BODY_INIT
+			while HIER_BODY_NOSTOP
+			{
+				Bpointer->VariablesQbIncrementPosition(1.0); // pos+=Dpos
+				Bpointer->Update(this->ChTime);
+				HIER_BODY_NEXT
+			}
+			HIER_OTHERPHYSICS_INIT
+			while HIER_OTHERPHYSICS_NOSTOP
+			{
+				PHpointer->VariablesQbIncrementPosition(1.0); // pos+=Dpos
+				PHpointer->Update(this->ChTime);
+				HIER_OTHERPHYSICS_NEXT
+			}
+
+			Update(); // Update everything
+
+		} // end loop Newton iterations
+
+	}
+
+	if ((action & ASS_SPEED)||(action & ASS_ACCEL))			// 2) -------- SPEEDS and ACCELERATIONS
+	{
+		double foo_dt = 1e-7;
+
+		// reset known-term vectors
+		LCPprepare_reset();
+
+		// fill LCP known-term vectors with proper terms
+		//
+		// | M -Cq'|*|v_new|- | [M]*v_old +f*dt | = |0| ,  c>=0, l>=0, l*c=0;
+		// | Cq  0 | |l    |  |  - Ct           |   |c|
+		//
+		LCPprepare_load(false,  // Cq are already there.. 
+					true,	    // adds [M]*v_old to the known vector
+					foo_dt,		// f*dt
+					foo_dt*foo_dt,// dt^2*K  (nb only non-Schur based solvers support K matrix blocks)
+					foo_dt,		// dt*R   (nb only non-Schur based solvers support K matrix blocks)
+					1.0,			// M (for FEM with non-lumped masses, add their mass-matrices)
+					1.0,		// Ct term
+					0,			// no C term
+					0.0,		// 
+					false);		// no clamping on -C/dt
+
+		
+		// make the vectors of pointers to constraint and variables, for LCP solver
+		LCPprepare_inject(*this->LCP_descriptor);
+
+		// Solve the LCP problem with iterative Gauss-Seidel solver. Solution
+		// variables are new speeds 'v_new'
+		GetLcpSolverSpeed()->Solve(
+								*this->LCP_descriptor
+								);	
+
+
+		HIER_BODY_INIT
+		while HIER_BODY_NOSTOP
+		{
+			// Set body speed -  and approximates the acceleration by BDF, with step foo_dt
+			Bpointer->VariablesQbSetSpeed(foo_dt);
+			// Now also updates all markers & forces
+			Bpointer->Update(this->ChTime);
+			HIER_BODY_NEXT
+		}
+		HIER_OTHERPHYSICS_INIT
+		while HIER_OTHERPHYSICS_NOSTOP
+		{
+			// Set speed -  and approximates the acceleration by BDF, with step foo_dt
+			PHpointer->VariablesQbSetSpeed(foo_dt);
+			// Now also updates all markers & forces
+			PHpointer->Update(this->ChTime);
+			HIER_OTHERPHYSICS_NEXT
+		}
+
+	}
+
+	return 0;
+}
+
+
+
+
+
+// **** PERFORM THE LINEAR STATIC ANALYSIS
+
+int ChSystem::DoStaticLinear()
+{
+	Setup();
+	Update();
+
+		// reset known-term vectors
+	LCPprepare_reset();
+
+	// Fill known-term vectors with proper terms 0 and -C :
+	//
+	// | K   -Cq'|*|Dpos|- |f |= |0| ,  c>=0, l>=0, l*c=0;
+	// | Cq    0 | |l   |  |C |  |c|
+	//
+
+	LCPprepare_load(true,  // Cq 
+			false,	// no addition of [M]*v_old to the known vector
+			1.0,	// f  forces
+			1.0,	// K  matrix
+			0,		// no R matrix
+			0,		// no M matrix (for FEM with non-lumped masses, do not add their mass-matrices)
+			0,		// no Ct term
+			1.0,	// C constraint gap violation, if any
+			0.0,	// 
+			false);	// no clamping on -C/dt
+	
+	// make the vectors of pointers to constraint and variables, for LCP solver
+	LCPprepare_inject(*this->LCP_descriptor);
+
+//***DEBUG***
+/*
+try
+{
+	chrono::ChSparseMatrix mdMK;
+	chrono::ChSparseMatrix mdCq;
+	chrono::ChSparseMatrix mdE;
+	chrono::ChMatrixDynamic<double> mdf;
+	chrono::ChMatrixDynamic<double> mdb;
+	chrono::ChMatrixDynamic<double> mdfric;
+	this->LCP_descriptor->ConvertToMatrixForm(&mdCq, &mdMK, &mdE, &mdf, &mdb, &mdfric);
+	chrono::ChStreamOutAsciiFile file_MK("dump_MK.dat");
+	mdMK.StreamOUTsparseMatlabFormat(file_MK);
+	chrono::ChStreamOutAsciiFile file_Cq("dump_Cq.dat");
+	mdCq.StreamOUTsparseMatlabFormat(file_Cq);
+	chrono::ChStreamOutAsciiFile file_E("dump_E.dat");
+	mdE.StreamOUTsparseMatlabFormat(file_E);
+	chrono::ChStreamOutAsciiFile file_f("dump_f.dat");
+	mdf.StreamOUTdenseMatlabFormat(file_f);
+	chrono::ChStreamOutAsciiFile file_b("dump_b.dat");
+	mdb.StreamOUTdenseMatlabFormat(file_b);
+} 
+catch(chrono::ChException myexc)
+{
+	chrono::GetLog() << myexc.what();
+}
+*/
+
+
+		// Solve the LCP problem.
+		// Solution variables are 'Dpos', delta positions.
+		// Note: use settings of the 'speed' lcp solver (i.e. use max number
+		// of iterations as you would use for the speed probl., if iterative solver)
+	GetLcpSolverSpeed()->Solve(
+							*this->LCP_descriptor
+							);	
+
+//***DEBUG***
+/*
+// **CHECK*** optional check for correctness in result
+chrono::ChMatrixDynamic<double> md;
+GetLcpSystemDescriptor()->BuildDiVector(md);			// d={f;-b}
+
+chrono::ChMatrixDynamic<double> mx;
+GetLcpSystemDescriptor()->FromUnknownsToVector(mx);		// x ={q,-l}
+chrono::ChStreamOutAsciiFile file_x("dump_x.dat");
+mx.StreamOUTdenseMatlabFormat(file_x);
+
+chrono::ChMatrixDynamic<double> mZx;
+GetLcpSystemDescriptor()->SystemProduct(mZx, &mx);		// Zx = Z*x
+
+GetLog() << "CHECK: norm of solver residual: ||Z*x-d|| -------------------\n";
+GetLog() << (mZx - md).NormInf() << "\n";
+*/
+
+	// Updates the reactions of the constraint, getting them from solver data
+	LCPresult_Li_into_reactions(1.0) ; 
+
+	// Move bodies to updated position
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+		Bpointer->VariablesQbIncrementPosition(1.0); // pos+=Dpos
+		Bpointer->Update(this->ChTime);
+		HIER_BODY_NEXT
+	}
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		PHpointer->VariablesQbIncrementPosition(1.0); // pos+=Dpos
+		PHpointer->Update(this->ChTime);
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	Update(); // Update everything
+
+	return 0;
+}
+
+
+
+
+// **** PERFORM THE STATIC ANALYSIS, FINDING THE STATIC
+// **** EQUILIBRIUM OF THE SYSTEM, WITH ITERATIVE SOLUTION
+
+int ChSystem::DoStaticRelaxing ()
+{
+	int err = 0;
+	int reached_tolerance = FALSE;
+
+	ResetErrors();
+
+	if (ncoords > 0)
+	{
+		if (ndof >= 0)
+		{
+			for (int m_iter = 0; m_iter < STATIC_MAX_STEPS; m_iter++)
+			{
+				HIER_BODY_INIT
+				while HIER_BODY_NOSTOP
+				{
+					// Set no body speed and no body accel.
+					Bpointer->SetNoSpeedNoAcceleration();
+					HIER_BODY_NEXT
+				}
+				HIER_OTHERPHYSICS_INIT
+				while HIER_OTHERPHYSICS_NOSTOP
+				{
+					PHpointer->SetNoSpeedNoAcceleration();
+					HIER_OTHERPHYSICS_NEXT
+				}
+
+				double m_undotime = this->GetChTime();
+				DoFrameDynamics(m_undotime + (this->GetStep()*1.8)*( ((double)STATIC_MAX_STEPS-(double)m_iter))/(double)STATIC_MAX_STEPS );
+				this->SetChTime(m_undotime);
+			}
+
+
+			HIER_BODY_INIT
+			while HIER_BODY_NOSTOP
+			{
+				// Set no body speed and no body accel.
+				Bpointer->SetNoSpeedNoAcceleration();
+				HIER_BODY_NEXT
+			}
+			HIER_OTHERPHYSICS_INIT
+			while HIER_OTHERPHYSICS_NOSTOP
+			{
+				PHpointer->SetNoSpeedNoAcceleration();
+				HIER_OTHERPHYSICS_NEXT
+			}
+		}
+	}
+
+	if (err)
+	{
+		last_err = TRUE;
+		GetLog() << "WARNING: some costraints may be redundant, but couldn't be eliminated \n";
+	}
+	return last_err;
+}
+
+
+// **** ---    THE KINEMATIC SIMULATION  ---
+// **** PERFORM IK (INVERSE KINEMATICS) UNTIL THE END_TIME IS
+// **** REACHED, STARTING FROM THE CURRENT TIME.
+
+
+int ChSystem::DoEntireKinematics()
+{
+	Setup();
+
+	ResetErrors();
+
+	DoAssembly (ASS_POSITION|ASS_SPEED|ASS_ACCEL);
+						// first check if there are redundant links (at least one NR cycle
+						// even if the structure is already assembled)
+
+	while (ChTime < end_time)
+	{
+		DoAssembly (ASS_POSITION|ASS_SPEED|ASS_ACCEL);		// >>> Newton-Raphson iteration, closing constraints
+
+		if (last_err) return FALSE;
+
+		ChTime += step;		// >>> Update the time and repeat.
+	}
+
+	return TRUE;
+}
+
+
+
+
+// **** ---   THE DYNAMICAL SIMULATION   ---
+// **** PERFORM EXPLICIT OR IMPLICIT INTEGRATION TO GET
+// **** THE DYNAMICAL SIMULATION OF THE SYSTEM, UNTIL THE
+// **** END_TIME IS REACHED.
+
+
+int ChSystem::DoEntireDynamics()
+{
+
+	Setup();
+
+	ResetErrors();
+
+			// the system may have wrong layout, or too large
+			// clearances in costraints, so it is better to
+			// check for costraint violation each time the integration starts
+	DoAssembly (ASS_POSITION|ASS_SPEED|ASS_ACCEL);
+
+			// Perform the integration steps until the end
+			// time is reached.
+			// All the updating (of Y, Y_dt and time) is done
+			// automatically by Integrate()
+
+	while (ChTime < end_time)
+	{
+		if (!Integrate_Y ()) break;	// >>> 1- single integration step,
+									//        updating Y, from t to t+dt.
+		if (last_err) return FALSE;
+	}
+
+	if (last_err) return FALSE;
+	return TRUE;
+}
+
+
+int ChSystem::DoStepDynamics (double m_step)
+{
+	this->step=m_step;
+	return Integrate_Y ();
+}
+
+
+
+// Perform the dynamical integration, from current ChTime to
+// the specified m_endtime, and terminating the integration exactly
+// on the m_endtime. Therefore, the step of integration may get a
+// little increment/decrement to have the last step ending in m_endtime.
+// Note that this function can be used in iterations to provide results in
+// a evenly spaced frames of time, even if the steps are changing.
+// Also note that if the time step is higher than the time increment
+// requested to reach m_endtime, the step is lowered.
+
+int ChSystem::DoFrameDynamics (double m_endtime)
+{
+	double frame_step;
+	double old_step;
+	double left_time;
+	int restore_oldstep = FALSE;
+	int counter = 0;
+	double fixed_step_undo;
+
+
+	ResetErrors();
+
+	frame_step = (m_endtime - ChTime);
+	fixed_step_undo = step;
+
+	while (ChTime < m_endtime)
+	{
+		restore_oldstep = FALSE;
+		counter++;
+
+		left_time = m_endtime - ChTime;
+
+		if (left_time < 0.0000000000001) break;		// - no integration if backward or null frame step.
+
+		if (left_time < (1.3* step))			// - step changed if too little frame step
+		{
+			old_step = step;
+			step = left_time;
+			restore_oldstep = TRUE;
+		}
+
+
+		if (!Integrate_Y ()) break;	// ***  Single integration step,
+									// ***  updating Y, from t to t+dt.
+									// ***  This also changes local ChTime, and may change step
+
+		if (this->adaption == STEP_FIXED) // this because collision detection may rewind time a bit, even if step_fixed
+				step = fixed_step_undo;
+
+		if (last_err) break;
+	}
+
+	if (restore_oldstep)
+		step = old_step; // if timestep was changed to meet the end of frametime, restore pre-last (even for time-varying schemes)
+	if (this->adaption == STEP_FIXED)
+		step = fixed_step_undo;	// anyway, restore original step if no adaption
+
+	if (last_err) return FALSE;
+	return TRUE;
+}
+
+
+// Performs the dynamical simulation, but using "frame integration"
+// iteratively. The results are provided only at each frame (evenly
+// spaced by "frame_step") rather than at each "step" (steps can be much
+// more than frames, and they may be automatically changed by integrator).
+// Moreover, the integration results shouldn't be dependent by the
+// "frame_step" value (steps are performed anyway, like in normal "DoEntireDynamics"
+// command).
+
+int ChSystem::DoEntireUniformDynamics(double frame_step)
+{
+
+			// the initial system may have wrong layout, or too large
+			// clearances in costraints.
+	Setup();
+	DoAssembly (ASS_POSITION|ASS_SPEED|ASS_ACCEL);
+
+	while (ChTime < end_time)
+	{
+		double goto_time = (ChTime + frame_step);
+		if (!DoFrameDynamics(goto_time)) return FALSE;		// ###### Perform "frame integration
+	}
+
+	return TRUE;
+}
+
+
+// Like DoFrameDynamics, but performs kinematics instead of dinamics
+
+int ChSystem::DoFrameKinematics (double m_endtime)
+{
+	double frame_step;
+	double old_step;
+	double left_time;
+	int restore_oldstep;
+	int counter = 0;
+
+
+	ResetErrors();
+
+	frame_step = (m_endtime - ChTime);
+
+	double fixed_step_undo = step;
+
+	while (ChTime < m_endtime)
+	{
+		restore_oldstep = FALSE;
+		counter++;
+
+		left_time = m_endtime - ChTime;
+
+		if (left_time < 0.000000001) break;		// - no kinematics for backward
+
+		if (left_time < (1.3* step))			// - step changed if too little frame step
+			{
+				old_step = step;
+				step = left_time;
+				restore_oldstep = TRUE;
+			}
+
+
+		DoAssembly(ASS_POSITION|ASS_SPEED|ASS_ACCEL);		// ***  Newton Raphson kinematic equations solver
+
+		if (last_err) return FALSE;
+
+		ChTime += step;
+
+		if (restore_oldstep) step = old_step; // if timestep was changed to meet the end of frametime
+	}
+
+	if (this->adaption == STEP_FIXED)
+		step = fixed_step_undo;	// anyway, restore original step if no adaption
+
+	return TRUE;
+}
+
+
+
+int ChSystem::DoStepKinematics (double m_step)
+{
+	ResetErrors();
+	
+	ChTime += m_step;
+
+	Update(); 
+
+	DoAssembly(ASS_POSITION|ASS_SPEED|ASS_ACCEL);		// ***  Newton Raphson kinematic equations solver
+
+	if (last_err) return FALSE;
+
+	return TRUE;
+}
+
+
+//
+// Full assembly -computes also forces-
+//
+
+int ChSystem::DoFullAssembly()
+{
+	ResetErrors();
+
+	DoAssembly(ASS_POSITION|ASS_SPEED|ASS_ACCEL);
+
+	return last_err;
+}
+
+
+
+
+
+
+
+
+////////
+////////  STREAMING - FILE HANDLING
+////////
+
+
+void ChSystem::StreamOUT(ChStreamOutBinary& mstream)
+{
+			// class version number
+	mstream.VersionWrite(5);
+
+		// serialize parent class too
+	ChObj::StreamOUT(mstream);
+
+		// stream out all member data
+	mstream << GetEndTime();
+	mstream << GetStep();
+	mstream << GetStepMin();
+	mstream << GetStepMax();
+	mstream << GetTol();
+	mstream << GetNormType();
+	mstream << GetMaxiter();
+	mstream << (int)GetIntegrationType();
+	mstream << GetOrder();
+	mstream << GetMultisteps();
+	mstream << GetAdaption();
+	mstream << 0; //GetBaumgarteStabilize();
+	mstream << GetDynaclose();
+	mstream << GetDynatol();
+	mstream << GetPredict();
+	mstream << GetPredorder();
+	mstream << GetStifftol();
+	mstream << G_acc;
+	mstream << GetXYmode();
+	mstream << GetNsClosePos();
+	mstream << GetNsCloseSpeed();
+	mstream << GetMonolattol();
+	mstream << GetIntegrtol();
+	mstream << GetAutoAssembly();
+	mstream << GetScriptForStartFile();
+	mstream << GetScriptForUpdateFile();
+	mstream << GetScriptForStepFile();
+	mstream << GetScriptFor3DStepFile();
+	mstream << GetMaxStepsCollide();
+	mstream << GetMinBounceSpeed();
+	// v2
+	mstream << iterLCPmaxIters;
+	mstream << iterLCPmaxItersStab;
+	mstream << simplexLCPmaxSteps;
+	mstream << (int)GetLcpSolverType();
+	// v3,v4
+	mstream << (int)0;//GetFrictionProjection();
+	// v5
+	mstream << parallel_thread_number;
+	mstream << max_penetration_recovery_speed;
+	mstream << use_GPU;
+	// v6   
+	mstream << use_sleeping;
+}
+
+void ChSystem::StreamIN(ChStreamInBinary& mstream)
+{
+		// class version number
+	int version = mstream.VersionRead();
+
+		// deserialize parent class too
+	ChObj::StreamIN(mstream);
+
+		// stream in all member data
+	 double mdouble;
+	 int mint;
+	 Vector mvector;
+	 char buffer[250];
+	mstream >> mdouble;		SetEndTime(mdouble);
+	mstream >> mdouble;		SetStep(mdouble);
+	mstream >> mdouble;		SetStepMin(mdouble);
+	mstream >> mdouble;		SetStepMax(mdouble);
+	mstream >> mdouble;		SetTol(mdouble);
+	mstream >> mint;		SetNormType (mint);
+	mstream >> mint;		SetMaxiter(mint);
+	mstream >> mint;		SetIntegrationType ((eCh_integrationType)mint);
+	mstream >> mint;		SetOrder(mint);
+	mstream >> mint;		SetMultisteps(mint);
+	mstream >> mint;		SetAdaption (mint);
+	mstream >> mint;		//SetBaumgarteStabilize(mint);
+	mstream >> mint;		SetDynaclose(mint);
+	mstream >> mdouble;		SetDynatol(mdouble);
+	mstream >> mint;		SetPredict(mint);
+	mstream >> mint;		SetPredorder(mint);
+	mstream >> mdouble;		SetStifftol(mdouble);
+	mstream >> mvector;		Set_G_acc(mvector);
+	mstream >> mint;		SetXYmode(mint);
+	mstream >> mint;		SetNsClosePos(mint);
+	mstream >> mint;		SetNsCloseSpeed(mint);
+	mstream >> mdouble;		SetMonolattol(mdouble);
+	mstream >> mdouble;		SetIntegrtol(mdouble);
+	mstream >> mint;		SetAutoAssembly(mint);
+	mstream >> buffer;		SetScriptForStartFile(buffer);
+	mstream >> buffer;		SetScriptForUpdateFile(buffer);
+	mstream >> buffer;		SetScriptForStepFile(buffer);
+	mstream >> buffer;		SetScriptFor3DStepFile(buffer);
+	mstream >> mint;		SetMaxStepsCollide(mint);
+	mstream >> mdouble;		SetMinBounceSpeed(mdouble);
+
+	if (version>=2)
+	{
+		mstream >> iterLCPmaxIters;
+		mstream >> iterLCPmaxItersStab;
+		mstream >> simplexLCPmaxSteps;
+		mstream >> mint;	SetLcpSolverType((eCh_lcpSolver) mint);
+	}
+	if (version>=3)
+	{
+		mstream >> mint;	//SetFrictionProjection((eCh_frictionProjection) mint);
+		if (version==3) {}; //SetFrictionProjection(FRI_CONEORTHO); // for v3, ortho proj anyway
+	}
+	if (version>=5)
+	{
+		mstream >> parallel_thread_number;
+		mstream >> max_penetration_recovery_speed;
+		mstream >> use_GPU;
+	}
+	if (version>=6)
+	{
+		mstream >> use_sleeping;
+	}
+}
+
+void ChSystem::StreamOUT(ChStreamOutAscii& mstream)
+{
+	//***TO DO***
+}
+
+#define CH_CHUNK_END   1234
+#define CH_CHUNK_START 4321
+
+int ChSystem::StreamINall  (ChStreamInBinary& m_file)
+{
+	int mchunk = 0;
+	ChBody* newbody= NULL;
+	ChLink* newlink= NULL;
+	ChPhysicsItem* newitem= NULL;
+
+	// class version number
+	int version = m_file.VersionRead();
+
+	// 0) reset system to have no sub object child
+	this->Clear();
+
+	// 1) read system class data...
+	m_file >> *this;
+
+	// 2a) read how many bodies
+	int mnbodies = 0;
+	m_file >> mnbodies;
+
+	// 2b) read  bodies
+	for (int i= 0; i<mnbodies; i++)
+	{
+		ChSharedPtr<ChBody> newbody(new ChBody);
+		this->AddBody(newbody);
+
+		if (!newbody->StreamINall(m_file)) 
+			throw ChException("Cannot read body data");
+	}
+
+	// 3a) read how many links
+	int mnlinks = 0;
+	m_file >> mnlinks;
+
+	// 3b) read  links
+	for (int j= 0; j<mnlinks; j++)
+	{
+			// read the link, using a special downcasting function Link_BinRead_Create which creates the
+			// proper inherited object, depending on its class inheritance from base Link*
+
+		m_file.AbstractReadCreate(&newlink);
+		if (!newlink) throw ChException("Cannot read link data");
+
+		ChSharedPtr<ChLink> shlink(newlink);
+		this->AddLink(shlink);
+	}
+
+	// 3c) Rebuild link pointers to markers
+	this->Reference_LM_byID();
+
+
+	// 4a) read how many other physics item
+	int mnitems = 0;
+	m_file >> mnitems;
+
+	// 4b) read physics items
+	for (int j= 0; j<mnitems; j++)
+	{
+			// read the item, using a special downcasting function which creates the
+			// proper inherited object, depending on its class inheritance from base ChPhysicsItem*
+
+		m_file.AbstractReadCreate(&newitem);
+		if (!newitem) throw ChException("Cannot read ChPhysicsItem data.");
+
+		ChSharedPtr<ChPhysicsItem> shitem(newitem);
+		this->AddOtherPhysicsItem(shitem);
+	}
+
+
+	this->Setup();
+
+	return 1;
+}
+
+int ChSystem::StreamOUTall  (ChStreamOutBinary& m_file)
+{
+	// class version number
+	m_file.VersionWrite(2);
+
+	// 1) write system class data...
+	m_file << *this;
+
+	// 2a) write how many bodies
+	m_file << (int)bodylist.size();//this->ListCount((ChObj**)&bodylist); ***SHAREDBODY***
+
+	// 2b) write  bodies
+	HIER_BODY_INIT
+	while HIER_BODY_NOSTOP
+	{
+			// write the body + child markers + forces
+		if (!Bpointer->StreamOUTall(m_file)) return 0;
+		HIER_BODY_NEXT
+	}
+
+	// 3a) write how many links
+	m_file << (int)linklist.size(); 
+
+	// 3b) write links links
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+			// Writethe link, using a special downcasting function Link_BinSave which saves also the
+			// inheritance info, depending on link class inheritance from base Link*
+		m_file.AbstractWrite(Lpointer);
+
+		HIER_LINK_NEXT
+	}
+
+	// 4a) write how many other physics items
+	m_file << (int)otherphysicslist.size(); 
+
+	// 4b) write other physics item links
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+			// Write the item, using a special downcasting function which saves also the
+			// inheritance info, depending on class inheritance from base ChPhysicsItem*
+		m_file.AbstractWrite(PHpointer);
+
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	m_file << (int)CH_CHUNK_END;
+
+	return 1;
+}
+
+void ChSystem::ShowHierarchy(ChStreamOutAscii& m_file)
+{
+	m_file << "\n   List of the " << (int)Get_bodylist()->size() << " added rigid bodies: \n";
+ 
+	std::vector<ChBody*>::iterator ibody = Get_bodylist()->begin();
+	while (ibody != Get_bodylist()->end())
+	{
+		GetLog() << "     BODY:       " << (*ibody)->GetName() << "\n";
+
+		std::vector<ChMarker*>::iterator imarker = (*ibody)->GetMarkerList()->begin();
+		while (imarker != (*ibody)->GetMarkerList()->end())
+		{
+			GetLog() << "        MARKER:   " << (*imarker)->GetName() << "\n";
+			imarker++;
+		}
+
+		std::vector<ChForce*>::iterator iforce = (*ibody)->GetForceList()->begin();
+		while (iforce != (*ibody)->GetForceList()->end())
+		{
+			GetLog() << "        FORCE:   " << (*iforce)->GetName() << "\n";
+			iforce++;
+		}
+
+		ibody++;
+	}
+
+	m_file << "\n   List of the " << (int)Get_linklist()->size() << " added links: \n";
+
+	HIER_LINK_INIT
+	while HIER_LINK_NOSTOP
+	{
+		GetLog() << "     LINK:       " << Lpointer->GetName() << "\n";
+		if (ChLinkMarkers* malink = ChDynamicCast(ChLinkMarkers,Lpointer))
+		{
+			if(malink->GetMarker1())
+			GetLog() << "        marker1:     " << malink->GetMarker1()->GetName() << "\n";
+			if(malink->GetMarker2())
+			GetLog() << "        marker2:     " << malink->GetMarker2()->GetName() << "\n";
+		}
+		HIER_LINK_NEXT
+	}
+
+	
+	m_file << "\n   List of other " << (int)otherphysicslist.size() << " added physic items: \n";
+
+	HIER_OTHERPHYSICS_INIT
+	while HIER_OTHERPHYSICS_NOSTOP
+	{
+		GetLog() << "     PHYSIC ITEM :       " << PHpointer->GetName() << "\n";
+		HIER_OTHERPHYSICS_NEXT
+	}
+
+	m_file << "\n\nFlat ChPhysicalItem list (class name - object name):----- \n\n";
+
+	IteratorAllPhysics mphiter(this);
+	while(mphiter.HasItem())
+	{
+		GetLog() << "  " <<   mphiter->GetRTTI()->GetName() << "  -  " <<   mphiter->GetName() << "\n";
+		++mphiter;
+	}
+	m_file << "\n\n";
+}
+
+int ChSystem::FileProcessChR (ChStreamInBinary& m_file)
+{
+	int mchunk = 0;
+
+	m_file >> mchunk;
+	if (mchunk != CH_CHUNK_START) 
+		throw ChException("Not a ChR data file.");
+
+	this->StreamINall(m_file);
+
+	m_file >> mchunk;
+	if (mchunk != CH_CHUNK_END)
+		throw ChException("The end of ChR data file is badly formatted.");
+
+	return 1;
+}
+
+int ChSystem::FileWriteChR (ChStreamOutBinary& m_file)
+{
+	m_file << (int)CH_CHUNK_START;
+
+	this->StreamOUTall(m_file);
+
+	m_file << (int)CH_CHUNK_END;
+
+	return 1;
+}
+
+	// process a scripting instruction file
+int ChSystem::FileProcessJS (char* m_file)
+{
+	if (!this->scriptEngine) return 0;
+
+	ChScript* mscript = this->scriptEngine->CreateScript();
+	if (!this->scriptEngine->ExecuteScript(*mscript)) return 0;
+	delete mscript;
+	return 1;
+}
+
+
+
+
+
+
+//////////////////////////////////////////////////////////////////
+
+
+ChSystem::IteratorBodies& ChSystem::IteratorBodies::operator=(const IteratorBodies& other)
+{
+	node_ = other.node_; 
+	return(*this);
+}
+bool ChSystem::IteratorBodies::operator==(const IteratorBodies& other)
+{
+	return(node_ == other.node_);
+}
+bool ChSystem::IteratorBodies::operator!=(const IteratorBodies& other)
+{
+	return(node_ != other.node_);
+}
+ChSystem::IteratorBodies& ChSystem::IteratorBodies::operator++()
+{
+	node_++;
+	return(*this);
+}
+ChSharedPtr<ChBody> ChSystem::IteratorBodies::operator*()
+{
+	(*node_)->AddRef(); // needed because ...
+	return (ChSharedPtr<ChBody>((*node_)));  // .. here I am not getting a new() data, but a reference to something created elsewhere
+}
+ChSystem::IteratorBodies ChSystem::IterBeginBodies() {return (IteratorBodies(this->bodylist.begin()));};
+ChSystem::IteratorBodies ChSystem::IterEndBodies() {return (IteratorBodies(this->bodylist.end()));};
+
+
+
+//////////////////////////////////////////////////////////////////
+
+
+ChSystem::IteratorLinks& ChSystem::IteratorLinks::operator=(const IteratorLinks& other)
+{
+	node_ = other.node_;
+	return(*this);
+}
+bool ChSystem::IteratorLinks::operator==(const IteratorLinks& other)
+{
+	return(node_ == other.node_);
+}
+bool ChSystem::IteratorLinks::operator!=(const IteratorLinks& other)
+{
+	return(node_ != other.node_);
+}
+ChSystem::IteratorLinks& ChSystem::IteratorLinks::operator++()
+{
+	node_++;
+	return(*this);
+}
+ChSharedPtr<ChLink> ChSystem::IteratorLinks::operator*()
+{
+	(*node_)->AddRef(); // needed because ...
+	return (ChSharedPtr<ChLink>((*node_)));  // .. here I am not getting a new() data, but a reference to something created elsewhere
+}
+ChSystem::IteratorLinks ChSystem::IterBeginLinks() {return (IteratorLinks(this->linklist.begin()));};
+ChSystem::IteratorLinks ChSystem::IterEndLinks() {return (IteratorLinks(this->linklist.end()));};
+
+
+
+//////////////////////////////////////////////////////////////////
+
+
+ChSystem::IteratorOtherPhysicsItems& ChSystem::IteratorOtherPhysicsItems::operator=(const IteratorOtherPhysicsItems& other)
+{
+	node_ = other.node_;
+	return(*this);
+}
+bool ChSystem::IteratorOtherPhysicsItems::operator==(const IteratorOtherPhysicsItems& other)
+{
+	return(node_ == other.node_);
+}
+bool ChSystem::IteratorOtherPhysicsItems::operator!=(const IteratorOtherPhysicsItems& other)
+{
+	return(node_ != other.node_);
+}
+ChSystem::IteratorOtherPhysicsItems& ChSystem::IteratorOtherPhysicsItems::operator++()
+{
+	node_++; 
+	return(*this);
+}
+ChSharedPtr<ChPhysicsItem> ChSystem::IteratorOtherPhysicsItems::operator*()
+{
+	(*node_)->AddRef(); // needed because ...
+	return (ChSharedPtr<ChPhysicsItem>((*node_)));  // .. here I am not getting a new() data, but a reference to something created elsewhere
+}
+ChSystem::IteratorOtherPhysicsItems ChSystem::IterBeginOtherPhysicsItems() {return (IteratorOtherPhysicsItems(this->otherphysicslist.begin()));};
+ChSystem::IteratorOtherPhysicsItems ChSystem::IterEndOtherPhysicsItems() {return (IteratorOtherPhysicsItems(this->otherphysicslist.end()));};
+
+
+
+//////////////////////////////////////////////////////////////////
+
+
+ChSystem::IteratorPhysicsItems::IteratorPhysicsItems(ChSystem* msys) 
+{
+	this->msystem = msys;
+	//RewindToBegin();
+	node_body   = msystem->Get_bodylist()->begin();
+	node_link	  = msystem->Get_linklist()->begin();
+	node_otherphysics	 = msystem->Get_otherphysicslist()->begin();
+	stage = 0;
+    mptr = 0;
+	this->operator++(); // initialize with 1st available item
+}
+ChSystem::IteratorPhysicsItems::IteratorPhysicsItems()
+{
+	this->msystem = 0;
+	this->mptr    = 0;
+	this->stage   = 9999;  
+}
+
+//~ChSystem::IteratorPhysicsItems::IteratorPhysicsItems() {}
+/*
+void ChSystem::IteratorPhysicsItems::RewindToBegin()
+{
+  node_body   = msystem->Get_bodylist()->begin();
+  node_link	  = msystem->Get_linklist()->begin();
+  node_otherphysics	 = msystem->Get_otherphysicslist()->begin();
+  stage = 0;
+  mptr = 0;
+  this->operator++(); // initialize with 1st available item
+}
+
+bool ChSystem::IteratorPhysicsItems::ReachedEnd()
+{
+  if (stage == 9999)
+	  return true;
+  return false;
+}
+*/
+bool ChSystem::IteratorPhysicsItems::HasItem()
+{
+  if (mptr)
+	  return true;
+  return false;
+}
+
+ChSystem::IteratorPhysicsItems& ChSystem::IteratorPhysicsItems::operator=(const ChSystem::IteratorPhysicsItems& other)
+{
+  msystem			= other.msystem;
+  node_body			= other.node_body;
+  node_link			= other.node_link;
+  node_otherphysics	= other.node_otherphysics;
+  stage				= other.stage;
+  mptr				= other.mptr;
+  return(*this);
+}
+
+bool ChSystem::IteratorPhysicsItems::operator==(const ChSystem::IteratorPhysicsItems& other)
+{
+	return ( (mptr == other.mptr) && 
+		     (stage == other.stage) &&
+			 (msystem == other.msystem) ); //...***TO CHECK***
+}
+
+bool ChSystem::IteratorPhysicsItems::operator!=(const ChSystem::IteratorPhysicsItems& other)
+{
+	return!( this->operator==(other)); //...***TO CHECK***
+}
+
+ChSystem::IteratorPhysicsItems& ChSystem::IteratorPhysicsItems::operator++()
+{
+  switch (stage)
+  {
+	case 1:
+	{
+		node_body++; // try next body
+		if (node_body != msystem->Get_bodylist()->end())
+		{
+			mptr = (*node_body); 
+			return (*this);
+		} 
+		break;
+	}
+	case 2:
+	{
+		node_link++; // try next link
+		if (node_link != msystem->Get_linklist()->end())
+		{
+			mptr = (*node_link); 
+			return (*this);
+		}
+		break;
+	}
+	case 3:
+	{
+		node_otherphysics++; // try next otherphysics
+		if (node_otherphysics != msystem->Get_otherphysicslist()->end())
+		{
+			mptr = (*node_otherphysics); 
+			return (*this);
+		}
+		break;
+	}
+	default:
+		break;
+  }
+  // Something went wrong, some list was at the end, so jump to beginning of next list
+  do
+  {
+	  switch(stage)
+	  {
+	  case 0:
+		  {
+				  stage = 1;
+				  if (node_body != msystem->Get_bodylist()->end())
+				  {
+					  mptr = (*node_body); 
+					  return (*this);
+				  } 
+				  break;
+		  }
+	  case 1:
+		  {
+				  stage = 2;
+				  if (node_link != msystem->Get_linklist()->end())
+				  {
+					  mptr = (*node_link); 
+					  return (*this);
+				  } 
+				  break;
+		  }
+	  case 2:
+		  {
+				  stage = 3;
+				  if (node_otherphysics != msystem->Get_otherphysicslist()->end())
+				  {
+					  mptr = (*node_otherphysics); 
+					  return (*this);
+				  } 
+				  break;
+		  }
+	  case 3:
+		  {
+				  stage = 4;
+				  mptr = msystem->GetContactContainer(); 
+				  return (*this);
+		  }
+	  case 4:
+		  {
+				  stage = 9999;
+				  mptr = 0; 
+				  return (*this);
+		  }
+	  } // end cases
+  } while (true);
+
+ return(*this);
+}
+
+ChSharedPtr<ChPhysicsItem> ChSystem::IteratorPhysicsItems::operator*()
+{
+	mptr->AddRef(); // needed because ...
+	return (ChSharedPtr<ChPhysicsItem>(mptr));  // .. here I am not getting a new() data, but a reference to something created elsewhere
+}
+ChSystem::IteratorPhysicsItems ChSystem::IterBeginPhysicsItems() {return (IteratorPhysicsItems(this));};
+ChSystem::IteratorPhysicsItems ChSystem::IterEndPhysicsItems() {return (IteratorPhysicsItems());};
+
+
+
+
+} // END_OF_NAMESPACE____
+
+/////////////////////////////////////// eof
+
diff --git a/SRC/ChronoEngine/physics/ChSystem.h b/SRC/ChronoEngine/physics/ChSystem.h
new file mode 100644
index 0000000..d8789bf
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChSystem.h
@@ -0,0 +1,1174 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2010-2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSYSTEM_H
+#define CHSYSTEM_H
+
+//////////////////////////////////////////////////
+//
+//   ChSystem.h
+//
+//   The physical system definition.
+//   A phisical system encloses bodies, links, 
+//   probes, etc.
+//   This is the oldest source file of Chrono::Engine
+//   therefore it is poorly written and under major
+//   revisiting... Stay tuned..
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+#include <list>
+
+#include "core/ChLog.h"
+#include "core/ChMath.h"
+#include "core/ChSpmatrix.h"
+#include "physics/ChBody.h"
+#include "physics/ChMarker.h"
+#include "physics/ChForce.h"
+#include "physics/ChLinksAll.h"
+#include "physics/ChHistory.h"
+#include "physics/ChEvents.h"
+#include "physics/ChProbe.h"
+#include "physics/ChControls.h"
+#include "physics/ChMaterialCouple.h"
+#include "physics/ChScriptEngine.h"
+#include "physics/ChGlobal.h"
+#include "collision/ChCCollisionSystem.h"
+
+
+namespace chrono
+{
+
+
+
+// forward references & shortcuts..
+
+typedef ChSharedPtr<ChLink>		ChSharedLinkPtr;
+typedef ChSharedPtr<ChProbe>	ChSharedProbePtr;
+typedef ChSharedPtr<ChControls> ChSharedControlsPtr;
+class ChLcpSolver;
+class ChLcpSystemDescriptor;
+class ChContactContainerBase;
+
+
+
+//////////////////////////////////////
+// CLASS FOR PHYSICAL SYSTEM
+
+#define NORM_INF			0
+#define NORM_TWO			1
+
+#define STEP_FIXED			0
+#define STEP_VARIABLE		1
+#define STEP_NOLIMITS		2
+
+#define STATIC_MAX_STEPS	35
+
+#define CHSYS_ERRLEN		200
+
+
+
+
+
+//////////////////////////////////////
+//  MULTIBODY SYSTEM CLASS
+//
+/// This class is used to represent a multibody physical system,
+/// so it acts also as a database for most items involved in
+/// simulations, most noticeably objects of ChBody and ChLink
+/// classes, which are used to represent mechanisms.
+///
+/// Moreover, it also owns some global settings and features,
+/// like the gravity acceleration, the global time and so on.
+///
+/// This object will be responsible of performing the entire
+/// physical simulation (dynamics, kinematics, statics, etc.),
+/// so you need at least one ChSystem object in your program, in
+/// order to perform simulations (you'll insert rigid bodies and
+/// links into it..)
+///
+
+
+class ChApi ChSystem : public ChObj
+{
+
+	CH_RTTI(ChSystem,ChObj);
+
+public:
+
+			//
+			// BUILDERS
+			//
+
+				/// Create a physical system. 
+				/// Note, in case you will use collision detection, the values of
+				/// 'max_objects' and 'scene_size' can be used to initialize the broadphase
+				/// collision algorithm in an optimal way. Scene size should be approximately 
+				/// the radius of the expected area where colliding objects will move.
+				/// If init_sys is false it does not initialize the collision system or solver
+				/// assumes that the user will do so.
+	ChSystem(unsigned int max_objects = 16000, double scene_size = 500, bool init_sys=true);
+
+				/// Destructor
+	virtual ~ChSystem();
+				/// Copy from another ChSystem.
+				/// Note! All settings are copied, but the hierarchy of children
+				/// bodies, links, probes etc. are NOT copied.
+	void Copy(ChSystem* source);
+
+
+			//
+			// PROPERTIES
+			//
+	
+				/// Sets the time step used for integration (dynamical simulation). 
+				/// The lower this value, the more precise the simulation. Usually, values 
+				/// about 0.01 s are enough for simple simulations. It may be modified automatically
+				/// by integration methods, if they support automatic time adaption.
+	void   SetStep (double m_step) {if (m_step>0.) step = m_step;}
+				/// Gets the current time step used for the integration (dynamical simulation).
+	double GetStep () {return step;}
+
+				/// Sets the end of simulation.
+	void   SetEndTime (double m_end_time) {end_time=m_end_time;}
+				/// Gets the end of the simulation
+	double GetEndTime () {return end_time;}
+
+				/// Sets the lower limit for time step (only needed if using 
+				/// integration methods which support time step adaption).
+	void   SetStepMin (double m_step_min) {if (m_step_min>0.) step_min=m_step_min;}
+				/// Gets the lower limit for time step
+	double GetStepMin () {return step_min;}
+
+				/// Sets the upper limit for time step (only needed if using 
+				/// integration methods which support time step adaption).
+	void   SetStepMax (double m_step_max) {if (m_step_max>step_min)step_max=m_step_max;}
+				/// Gets the upper limit for time step
+	double GetStepMax () {return step_max;}
+
+				/// Available methods for time integration (time steppers). 
+				/// Only fixed-step Anitescu and Tasora types are currently supported.
+					enum eCh_integrationType{ 
+						 INT_ANITESCU = 0,
+						 INT_TASORA =6
+						 //INT_KUTTA_EXP = 1,
+						 //INT_RK_EXP = 2,
+						 //INT_EULEROSTD_EXP = 3,
+						 //INT_EULEROMOD_EXP = 4,	
+						 //INT_HEUN_EXP =5 
+					};
+				/// Sets the method for time integration (time stepper).
+				/// Some steppers are faster but can run into some troubles 
+				/// when dealing with large interpenetrations in contacts/impacts (es: INT_ANITESCU),
+				/// while others are more precise but at an expense of a lower performance (es. INT_TASORA).
+	void SetIntegrationType (eCh_integrationType m_integration_type); 
+				/// Gets the current method for time integration (time stepper).
+	eCh_integrationType GetIntegrationType() {return integration_type;}
+
+				/// Integration order (ONLY if current integration method supports multi-order integration.)
+	void SetOrder (int m_order) {order=m_order;}
+				/// Integration order (ONLY if current integration method supports multi-order integration.)
+	int  GetOrder() {return order;}
+
+				/// Integration substeps (ONLY if current integration method supports multi-step integration.)
+	void SetMultisteps (int m_multisteps) {multisteps=m_multisteps;} 
+				/// Integration substeps (ONLY if current integration method supports multi-step integration.)
+	int  GetMultisteps() {return multisteps;}
+
+				/// Sets iteration limit for assembly constraints. When trying to keep constraints together, 
+				/// the iterative process is stopped if this max.number of iterations (or tolerance) is reached.
+	void SetMaxiter (int m_maxiter) {maxiter = m_maxiter;}
+				/// Gets iteration limit for assembly constraints. 
+	int  GetMaxiter () {return maxiter;}
+
+				/// Sets tolerance (in m) for assembly constraints. When trying to keep constraints together, 
+				/// the iterative process is stopped if this tolerance (or max.number of iterations ) is reached 
+	void   SetTol (double m_tol) {tol = m_tol;}
+				/// Gets current tolerance for assembly constraints. 
+	double GetTol () {return tol;}
+
+				/// Sets tolerance for satisfying speeds in constraints. Speeds in constraints must be made compatible:
+				/// the iterative process is stopped if this tolerance (or max.number of iterations ) is reached.
+	void   SetTolSpeeds (double m_tol) {tol_speeds = m_tol;}
+				/// Gets current tolerance (in m/s) for satisfying constraints at the speed level. 
+	double GetTolSpeeds () {return tol_speeds;}
+
+				/// Sets the method used to compute the norm of constraint violation (NORM_INF, NORM_TWO)
+	void SetNormType (int m_normtype) {normtype = m_normtype;}
+	int  GetNormType () {return normtype;}
+
+				/// Activate timestep adaption (ONLY if supported by integration method)
+	void SetAdaption (int m_adapt) {adaption = m_adapt;}
+	int  GetAdaption	() {return adaption;}
+
+				/// Activates the stabilization in constraints as a LCP on position level,
+				/// for acceleration/force integration methods where this is optional. (Not yet used). 
+	void SetDynaclose (int m_close) {dynaclose = m_close;}
+	int  GetDynaclose () {return dynaclose;}
+
+				/// Stabilization in constraints as a LCP on position level happens each Ns steps.
+				/// For acceleration/force integration methods where this is optional. (Not yet used). 
+	void SetNsClosePos (int mn) {ns_close_pos = mn;}
+	int  GetNsClosePos () {return ns_close_pos;}
+
+				/// Stabilization in constraints as a LCP on speed level happens each Ns steps.
+				/// For acceleration/force integration methods where this is optional. (Not yet used). 
+	void SetNsCloseSpeed (int mn) {ns_close_speed = mn;}
+	int  GetNsCloseSpeed () {return ns_close_speed;}
+
+				/// Obsolete
+	void   SetDynatol (double m_tol) {if (m_tol < 1) m_tol = 1; dynatol = m_tol;}
+	double GetDynatol () {return dynatol;}
+	
+				/// Obsolete
+	void   SetMonolattol (double m_tol) {if (m_tol < 0) m_tol = 0; monolat_tol = m_tol;}
+	double GetMonolattol () {return monolat_tol;}
+	
+				/// Tolerance for integration methods with adaptive time step.
+				/// For example, some Runge Kutta methods will halve the step if the
+				/// local integration precision is below the tolerance.
+	void   SetIntegrtol (double m_tol) {if (m_tol < 0) m_tol = 0; integr_tol = m_tol;}
+	double GetIntegrtol () {return integr_tol;}
+				
+				/// Obsolete
+	void SetPredict (int m_pr) {predict = m_pr;}
+	int  GetPredict () {return predict;}
+	
+				/// Obsolete
+	void SetPredorder (int m_pr) {predorder = m_pr; } 
+	int  GetPredorder () {return predorder;}
+	
+				/// Obsolete
+	void   SetStifftol (double m_tol) {if (m_tol < 0) m_tol = 0; stifftol = m_tol;}
+	double GetStifftol () {return stifftol;}
+
+				/// Impose the 2D mode. Only for very simple systems. Note that,
+				/// given the speed and efficiency of current LCP solvers and integrators,
+				/// there's no need to force the 2D mode - just use the 3D.  
+	void SetXYmode (int m_mode);	// mode = 1 -> switch to 2D; mode = 0 -> switch to 3D (default)
+	int  GetXYmode () {return modeXY;}
+
+	void SetAutoAssembly (int aas) {auto_assembly = aas;}
+	int  GetAutoAssembly () {return auto_assembly;}
+	
+	void SetMaxStepsCollide(int mval) {msteps_collide = mval;}
+	int  GetMaxStepsCollide() {return msteps_collide;}
+	
+				/// For elastic collisions, with objects that have nonzero
+				/// restitution coefficient: objects will rebounce only if their
+				/// relative colliding speed is above this threshold. Default 0.15 m/s.
+				/// If this is too low, aliasing problems can happen with small high frequency
+				/// rebounces, and settling to static stacking might be more difficult. 
+	void SetMinBounceSpeed(double mval) {min_bounce_speed = mval;}
+				/// Objects will rebounce only if their relative colliding speed is above this threshold.
+	double GetMinBounceSpeed() {return min_bounce_speed;}
+
+				/// For the Anitescu stepper, you can limit the speed of exiting from penetration
+				/// situations. Usually set a positive value, about 0.1 .. 2 . (as exiting speed, in m/s)
+	void SetMaxPenetrationRecoverySpeed(double mval) {max_penetration_recovery_speed = mval;}
+				/// Get the limit on the speed for exiting from penetration situations (for Anitescu stepper)
+	double GetMaxPenetrationRecoverySpeed() {return max_penetration_recovery_speed;}
+
+
+	double GetErrIntegration () {return err_integr;}
+	double GetErrConstraints () {return err_constr;}
+	
+	
+				/// Available types of solvers for the LCP problem. Note: compared to iterative methods,
+				/// the simplex solver is so slow that it's mostly for experiments. 
+				/// Also, Jacobi is slower than SOR - hence it's here for benchmarks & tests.
+					enum eCh_lcpSolver{
+						 LCP_ITERATIVE_SOR = 0,
+						 LCP_ITERATIVE_SYMMSOR,
+						 LCP_SIMPLEX,			// OBSOLETE!
+						 LCP_ITERATIVE_JACOBI,
+						 LCP_ITERATIVE_SOR_MULTITHREAD, 
+						 LCP_ITERATIVE_PMINRES,
+						 LCP_ITERATIVE_BARZILAIBORWEIN,
+						 LCP_ITERATIVE_PCG,
+						 LCP_ITERATIVE_APGD,
+						 LCP_DEM};
+
+				/// Choose the LCP solver type, to be used for the simultaneous
+				/// solution of the constraints in dynamical simulations (as well as 
+				/// in kinematics, statics, etc.)
+				/// You can choose between the eCh_lcpSolver types, for 
+				/// example LCP_ITERATIVE_SOR for fast (not 100%precise) approach
+				/// to problems with contacts, or LCP_SIMPLEX (slow,precise), etc.
+				///  NOTE: This is a shortcut,that internally is equivalent to the two 
+				/// calls ChangeLcpSolverStab(..) and ChangeLcpSolverSpeed(...), so in 
+				/// future it is better to use directly those two more powerful functions, 
+				/// and this shourtcut will be deprecated.
+	void SetLcpSolverType(eCh_lcpSolver mval);
+				/// Gets the current LCP solver type.
+	eCh_lcpSolver GetLcpSolverType() {return lcp_solver_type;}
+
+				/// In case you are using an iterative LCP solver (es. LCP_ITERATIVE_SOR)
+				/// you can set the maximum number of iterations. The higher the 
+				/// iteration number, the more precise the simulation (but more CPU time)
+	void SetIterLCPmaxItersSpeed(int mval) {iterLCPmaxIters = mval;}
+				/// Current maximum number of iterations, if using an iterative LCP solver.
+	int  GetIterLCPmaxItersSpeed() {return iterLCPmaxIters;}
+
+				/// In case you are using an iterative LCP solver (es. LCP_ITERATIVE_SOR)
+				/// and an integration method requiring post-stabilization (es. INT_TASORA)
+				/// you can set the maximum number of stabilization iterations. The higher the 
+				/// iteration number, the more precise the simulation (but more CPU time)
+	int  GetIterLCPmaxItersStab() {return iterLCPmaxItersStab;}
+				/// Current maxi. number of iterations, if using an iterative LCP solver for stabilization.
+	void SetIterLCPmaxItersStab(int mval) {iterLCPmaxItersStab = mval;}
+
+				/// If you use the LCP_SIMPLEX lcp solver (usually not suggested),
+				/// here you can set a limit on the number of simplex steps (n. of pivots).
+				/// Note: premature truncation of the simplex solver may cause big errors!.
+				/// Set as 0 for no limits on the number of iterations (but it may run forever!)
+	void SetSimplexLCPmaxSteps(int mval) {simplexLCPmaxSteps = mval;}
+				/// Limit on the number of simplex steps, if using LCP_SIMPLEX as LCP solver.
+	int  GetSimplexLCPmaxSteps() {return simplexLCPmaxSteps;}
+
+				/// If you want to easily turn ON/OFF the warm starting feature of both LCP iterative solvers 
+				/// (the one for speed and the other for pos.stabilization) you can simply use the 
+				/// following instead of accessing them directly with GetLcpSolverSpeed() and GetLcpSolverStab()
+	void SetIterLCPwarmStarting(bool usewarm = true);
+				/// Tell if the warm starting is enabled for the speed solver, (if iterative type).
+	bool GetIterLCPwarmStarting();
+
+				/// If you want to easily adjust the omega overrelaxation parameter of both LCP iterative solvers 
+				/// (the one for speed and the other for pos.stabilization) you can simply use the 
+				/// following instead of accessing them directly with GetLcpSolverSpeed() and GetLcpSolverStab().
+				/// Note, usually a good omega for Jacobi or GPU solver is 0.2; for other iter.solvers can be up to 1.0
+	void   SetIterLCPomega(double momega = 1.0);
+				/// Tell the omega overrelaxation factor for the speed solver, (if iterative type).
+	double GetIterLCPomega();
+
+				/// If you want to easily adjust the 'sharpness lambda' parameter of both LCP iterative solvers 
+				/// (the one for speed and the other for pos.stabilization) you can simply use the 
+				/// following instead of accessing them directly with GetLcpSolverSpeed() and GetLcpSolverStab().
+				/// Note, usually a good sharpness value is in 1..0.8 range (the lower, the more it helps exact
+				/// convergence, but overall convergence gets also much slower so maybe better to tolerate some error) 
+	void   SetIterLCPsharpnessLambda(double momega = 1.0);
+				/// Tell the 'sharpness lambda' factor for the speed solver, (if iterative type).
+	double GetIterLCPsharpnessLambda();
+
+				/// Instead of using SetLcpSolverType(), you can create your own
+				/// custom lcp solver (suffice it is inherited from ChLcpSolver) and plug
+				/// it into the system using this function. The replaced solver is automatically deleted. 
+				/// When the system is deleted, the custom solver that you plugged will be automatically deleted.
+	void ChangeLcpSolverStab(ChLcpSolver* newsolver);
+
+				/// Access directly the LCP solver, configured to be used for the stabilization
+				/// of constraints (solve delta positions). Use mostly for diagnostics.
+	ChLcpSolver* GetLcpSolverStab();
+
+				/// Instead of using SetLcpSolverType(), you can create your own
+				/// custom lcp solver (suffice it is inherited from ChLcpSolver) and plug
+				/// it into the system using this function. The replaced solver is automatically deleted. 
+				/// When the system is deleted, the custom solver that you plugged will be automatically deleted.
+	void ChangeLcpSolverSpeed(ChLcpSolver* newsolver);
+
+				/// Access directly the LCP solver, configured to be used for the main differential
+				/// inclusion problem (LCP on speed-impulses). Use mostly for diagnostics.
+	ChLcpSolver* GetLcpSolverSpeed();
+
+				/// Instead of using the default LCP 'system descriptor', you can create your own
+				/// custom descriptor (suffice it is inherited from ChLcpSystemDescriptor) and plug
+				/// it into the system using this function. The replaced descriptor is automatically deleted. 
+				/// When the system is deleted, the custom descriptor that you plugged will be automatically deleted.
+	void ChangeLcpSystemDescriptor(ChLcpSystemDescriptor* newdescriptor);
+
+				/// Access directly the LCP 'system descriptor'. Use mostly for diagnostics.
+	ChLcpSystemDescriptor* GetLcpSystemDescriptor() {return this->LCP_descriptor;};
+
+
+				/// Changes the number of parallel threads (by default is n.of cores).
+				/// Note that not all solvers use parallel computation.
+				/// If you have a N-core processor, this should be set at least =N for maximum performance.
+	void SetParallelThreadNumber(int mthreads = 2); 
+				/// Get the number of parallel threads. 
+				/// Note that not all solvers use parallel computation.
+	int GetParallelThreadNumber() {return parallel_thread_number;}
+
+
+				/// Returns true if the GPU is used for the LCP problem (ex. because
+				/// the LCP_ITERATIVE_GPU solver is used)
+	bool GetUseGPU() {return use_GPU;}
+	void SetUseGPU(bool gpu) {use_GPU=gpu;}
+
+
+
+
+				/// Sets the G (gravity) acceleration vector, affecting all the bodies in the system. 
+	void  Set_G_acc (ChVector<> m_acc = ChVector<>(0.0, -9.8, 0.0)) {G_acc = m_acc;}
+				/// Gets the G (gravity) acceleration vector affecting all the bodies in the system. 
+	ChVector<> Get_G_acc() {return G_acc;}
+
+
+
+
+			//
+			// DATABASE HANDLING.
+			//
+
+
+			// To attach/remove items (rigid bodies, links, etc.) you must use 
+			// shared pointer, so that you don't need to care about item deletion, 
+			// which will be automatic when needed.
+			// Please don't add the same item multiple times; also, don't remove
+			// items which haven't ever been added! This will most often cause an assert() failure
+			// in debug mode.
+			// NOTE! adding/removing items to the system doesn't call Update() automatically.
+				
+				/// Attach a body to this system. Must be an object of exactly ChBody class.
+	void AddBody (ChSharedPtr<ChBody> newbody);
+				/// Attach a link to this system. Must be an object of ChLink or derived classes.
+	void AddLink (ChSharedPtr<ChLink> newlink);
+	void AddLink (ChLink* newlink);  // _internal use
+				/// Attach a ChPhysicsItem object that is not a body or link
+	void AddOtherPhysicsItem (ChSharedPtr<ChPhysicsItem> newitem);
+				/// Attach a probe to this system. 
+	void AddProbe (ChSharedPtr<ChProbe>& newprobe);
+				/// Attach a control to this system. 
+	void AddControls (ChSharedPtr<ChControls>& newcontrols);
+				/// Attach whatever type of ChPhysicsItem (ex a ChBody, or a 
+				/// ChParticles, or a ChLink, etc.) to the system. It will take care
+				/// of adding it to the proper list: of bodies, of links, or of other generic 
+				/// physic item. (i.e. it calls AddBody(), AddLink() or AddOtherPhysicsItem() ).
+	void Add (ChSharedPtr<ChPhysicsItem> newitem);
+
+				/// Remove a body from this system.
+	void RemoveBody (ChSharedPtr<ChBody> mbody); 
+				/// Remove a link from this system.
+	void RemoveLink (ChSharedPtr<ChLink> mlink); 
+				/// Remove a link from this system (faster version, mostly internal use)
+	std::list<ChLink*>::iterator RemoveLinkIter(std::list<ChLink*>::iterator& mlinkiter); 
+				/// Remove a ChPhysicsItem object that is not a body or a link
+	void RemoveOtherPhysicsItem (ChSharedPtr<ChPhysicsItem> mitem);
+				/// Remove whatever type of ChPhysicsItem that was added to the system. 
+				/// (suggestion: use this instead of old RemoveBody(), RemoveLink, etc.)
+	void Remove (ChSharedPtr<ChPhysicsItem> newitem);
+
+				/// Remove all bodies from this system.
+	void RemoveAllBodies();
+				/// Remove all links from this system.
+	void RemoveAllLinks();
+				/// Remove all physics items that were not added to body or link lists.
+	void RemoveAllOtherPhysicsItems();
+				/// Remove all probes from this system.
+	void RemoveAllProbes();
+				/// Remove all controls from this system.
+	void RemoveAllControls();
+
+				/// Iterator to scan through the list of all added ChBody items 
+				/// using a safe smart pointer.
+	class ChApi IteratorBodies
+	{
+    public:
+      IteratorBodies(std::vector<ChBody*>::iterator p) : node_(p) {}
+      IteratorBodies& operator=(const IteratorBodies& other);
+      bool operator==(const IteratorBodies& other);
+      bool operator!=(const IteratorBodies& other);
+      IteratorBodies& operator++();
+      ChSharedPtr<ChBody> operator*();
+	  IteratorBodies(){};
+	 private:
+	    std::vector<ChBody*>::iterator node_;
+    };
+				/// Get a ChBody iterator, initialized at the beginning of body list
+	IteratorBodies IterBeginBodies();
+	IteratorBodies IterEndBodies();
+
+				/// Iterator to scan through the list of all added ChLink items 
+				/// using a safe smart pointer.
+	class ChApi IteratorLinks
+	{
+    public:
+      IteratorLinks(std::list<ChLink*>::iterator p) : node_(p) {}
+      IteratorLinks& operator=(const IteratorLinks& other);
+      bool operator==(const IteratorLinks& other);
+      bool operator!=(const IteratorLinks& other);
+      IteratorLinks& operator++();
+      ChSharedPtr<ChLink> operator*();
+	  IteratorLinks(){};
+	 private:
+	    std::list<ChLink*>::iterator node_;
+    };
+				/// Get a ChLink iterator, initialized at the beginning of link list
+	IteratorLinks IterBeginLinks();
+	IteratorLinks IterEndLinks();
+
+				/// Iterator to scan through the list of all physics items 
+				/// that were not added to body or link lists, using a safe smart pointer.
+	class ChApi IteratorOtherPhysicsItems
+	{
+    public:
+      IteratorOtherPhysicsItems(std::list<ChPhysicsItem*>::iterator p) : node_(p) {}
+      IteratorOtherPhysicsItems& operator=(const IteratorOtherPhysicsItems& other);
+      bool operator==(const IteratorOtherPhysicsItems& other);
+      bool operator!=(const IteratorOtherPhysicsItems& other);
+      IteratorOtherPhysicsItems& operator++();
+      ChSharedPtr<ChPhysicsItem> operator*();
+	  IteratorOtherPhysicsItems(){};
+	 private:
+	    std::list<ChPhysicsItem*>::iterator node_;
+    };
+				/// Get a ChPhysics iterator, initialized at the beginning of additional ChPhysicsItems
+	IteratorOtherPhysicsItems IterBeginOtherPhysicsItems();
+	IteratorOtherPhysicsItems IterEndOtherPhysicsItems();
+
+				/// Iterator to scan through ALL physics items (bodies,
+				/// links, 'other' physics items, contact container)
+				/// Note, for performance reasons, if you know in advance that you
+				/// are going to scan only ChBody items, the IteratorBodies is faster,
+				/// and the same for IteratorLinks; so use IteratorPhysicsItems for generic cases.
+	class ChApi IteratorPhysicsItems
+	{
+     public:
+      IteratorPhysicsItems(ChSystem* msys);
+	  IteratorPhysicsItems();
+      IteratorPhysicsItems& operator=(const IteratorPhysicsItems& other);
+	  bool operator==(const IteratorPhysicsItems& other); 
+	  bool operator!=(const IteratorPhysicsItems& other); 
+	  IteratorPhysicsItems& operator++();
+	  ChSharedPtr<ChPhysicsItem> operator*();
+	  //void RewindToBegin();
+	  //bool ReachedEnd();
+	  bool HasItem();
+	 private:
+	   std::vector<ChBody*>::iterator node_body;
+	   std::list<ChLink*>::iterator node_link;
+	   std::list<ChPhysicsItem*>::iterator node_otherphysics;
+	   int stage;
+	   ChPhysicsItem* mptr;
+	   ChSystem* msystem;
+    };
+				/// Get a ChPhysics iterator
+	IteratorPhysicsItems IterBeginPhysicsItems();
+	IteratorPhysicsItems IterEndPhysicsItems();
+
+				/// Gets the list of children bodies -low level function-.
+				/// NOTE! use this list only to enumerate etc., but NOT to
+				/// remove or add items (use the appropriate Remove.. and Add.. 
+				/// functions instead!)
+	std::vector<ChBody*>* Get_bodylist() {return &bodylist;}
+				/// Gets the list of children links -low level function-.
+				/// NOTE! use this list only to enumerate etc., but NOT to
+				/// remove or add items (use the appropriate Remove.. and Add.. 
+				/// functions instead!)
+	std::list<ChLink*>* Get_linklist() {return &linklist;}
+				/// Gets the list of children physics items that are not in the body or link lists.
+				/// NOTE! use this list only to enumerate etc., but NOT to
+				/// remove or add items (use the appropriate Remove.. and Add.. 
+				/// functions instead!)
+	std::list<ChPhysicsItem*>* Get_otherphysicslist() {return &otherphysicslist;}
+
+				/// For higher performance (ex. when GPU coprocessors are available) you can create your own
+				/// custom contact container (suffice it is inherited from ChContactContainerBase) and plug
+				/// it into the system using this function. The replaced container is automatically deleted. 
+				/// When the system is deleted, the custom container that you plugged will be automatically deleted.
+	void ChangeContactContainer(ChContactContainerBase* newcontainer);
+
+				/// Get the contact container
+	ChContactContainerBase* GetContactContainer() {return contact_container;}
+
+				/// Searches a body from its ChObject name
+	ChSharedPtr<ChBody> SearchBody  (char* m_name);
+				/// Searches a link from its ChObject name
+	ChSharedPtr<ChLink> SearchLink  (char* m_name);
+				/// Searches from other ChPhysics items (not bodies or links) from name
+	ChSharedPtr<ChPhysicsItem> SearchOtherPhysicsItem  (char* m_name);
+				/// Searches whatever item (body, link or other ChPhysics items) 
+	ChSharedPtr<ChPhysicsItem> Search(char* m_name);
+	
+				/// Searches a marker from its ChObject name -OBSOLETE
+	ChSharedPtr<ChMarker> SearchMarker(char* m_name);
+				/// Searches a marker from its unique ID -OBSOLETE
+	ChSharedPtr<ChMarker> SearchMarker(int markID);
+
+				/// Removes all bodies/marker/forces/links/contacts,
+				/// also resets timers and events.
+	void Clear();
+
+				/// Given inserted markers and links, restores the
+				/// pointers of links to markers given the information
+				/// about the marker IDs.
+	void Reference_LM_byID();
+
+
+
+			//
+			// STATISTICS
+			//
+
+				/// Gets the number of active bodies (so, excluding those that are sleeping or are fixed to ground)
+	int GetNbodies() {return nbodies;}
+				/// Gets the number of bodies that are in sleeping mode (excluding fixed bodies).
+	int GetNbodiesSleeping() {return nbodies_sleep;}
+				/// Gets the number of bodies that are fixed to ground.
+	int GetNbodiesFixed() {return nbodies_fixed;}
+				/// Gets the total number of bodies added to the system, including the grounded and sleeping bodies.
+	int GetNbodiesTotal() {return nbodies + nbodies_fixed + nbodies_sleep;}
+
+				/// Gets the number of links .
+	int GetNlinks() {return nlinks;}
+				/// Gets the number of other physics items (not ChLinks or ChBodies).
+	int GetNphysicsItems() {return nphysicsitems;}
+				/// Gets the number of coordinates (considering 7 coords for rigid bodies because of the 4 dof of quaternions)
+	int GetNcoords() {return ncoords;}
+				/// Gets the number of degrees of freedom of the system.
+	int GetNdof() {return ndof;}
+				/// Gets the number of scalar constraints added to the system, including constraints on quaternion norms
+	int GetNdoc() {return ndoc;}
+				/// Gets the number of system variables (coordinates plus the constraint multipliers, in case of quaternions)
+	int GetNsysvars() {return nsysvars;}
+				/// Gets the number of coordinates (considering 6 coords for rigid bodies, 3 transl.+3rot.)
+	int GetNcoords_w() {return ncoords_w;}
+				/// Gets the number of scalar constraints added to the system		
+	int GetNdoc_w() {return ndoc_w;}
+				/// Gets the number of scalar constraints added to the system (only bilaterals)
+	int GetNdoc_w_C() {return ndoc_w_C;}
+				/// Gets the number of scalar constraints added to the system (only unilaterals)
+	int GetNdoc_w_D() {return ndoc_w_D;}
+				/// Gets the number of system variables (coordinates plus the constraint multipliers)
+	int GetNsysvars_w() {return nsysvars_w;}
+				/// Gets the number of contacts.
+	int GetNcontacts();
+
+
+
+				/// Gets the time (in seconds) spent for computing the time step
+	double GetTimerStep() {return timer_step;}
+				/// Gets the fraction of time (in seconds) for the solution of the LCPs, within the time step
+	double GetTimerLcp() {return timer_lcp;}
+				/// Gets the fraction of time (in seconds) for finding collisions, within the time step
+	double GetTimerCollisionBroad() {return timer_collision_broad;}
+				/// Gets the fraction of time (in seconds) for finding collisions, within the time step
+	double GetTimerCollisionNarrow() {return timer_collision_narrow;}
+				/// Gets the fraction of time (in seconds) for updating auxiliary data, within the time step
+	double GetTimerUpdate() {return timer_update;}
+				/// Resets the timers.
+	void ResetTimers() {timer_step = timer_lcp = timer_collision_broad = timer_collision_narrow = timer_update = 0.;}
+
+				/// Current warning/error (soon this function will be deprecated and obsolete)
+	char* GetErrMessage () {return err_message;}
+				/// Current warning/error code (soon this function will be deprecated and obsolete)
+	int GetLastErr () {return last_err;}
+	void ResetErrors () {last_err = 0; strcpy (err_message, "");}
+
+				/// Gets the cyclic event buffer of this system (it can be used for
+				/// debugging/profiling etc.) 
+	ChEvents* Get_events () {return events;}
+
+
+
+			//
+			// UPDATING/SETUP FUNCTIONS
+			//
+
+				/// Counts the number of bodies and links. 
+	int  Setup();
+
+				/// Updates all the auxiliary data and children of
+				/// bodies, forces, links, given their current state.
+	void Update();
+
+				/// Tells to the associated external object of class ChExternalObject() ,
+				/// if any, that all 3D shapes of the system must be updated in order
+				/// to syncronize to the current system's state.
+	void UpdateExternalGeometry ();
+
+
+
+protected:
+
+			//
+			// LCP SOLVER
+			//
+
+				/// Sets to zero all the known terms bi & fb of the sparse LCP (that is,
+				/// resets all the bi terms in ChConstraints (for example constraints
+				/// defined in ChLinks, and resets all the fb vectors of ChVariables
+				/// contained, for example, in ChBodies)
+	virtual void LCPprepare_reset();
+
+				/// Fills the all the known terms of the sparse LCP (that is,
+				/// fills all the bi terms in ChConstraints (for example constraints
+				/// defined in ChLinks, and fills all the fb vectors of ChVariables
+				/// contained, for example, in ChBodies).
+				/// The parameters of this function specify which data must be loaded
+				/// in the known terms.
+	virtual void LCPprepare_load(      bool load_jacobians, ///< load jacobians into ChConstraints
+							   bool   load_Mv,		///< load M*v in fb: fb+=M*v (for timestepping where fb=F*h+M*v_old). Also, sets q=v_old.
+							   double F_factor, 	///< load F (forces) in fb: fb+=F*F_factor
+							   double K_factor,		///< load K stiff.matrices, if any ChLcpKstiffness blocks, multiplied by K_factor
+							   double R_factor,		///< load R damp.matrices, if any ChLcpKstiffness blocks, multiplied by R_factor
+							   double M_factor,		///< load M mass.matrices, if any ChLcpKstiffness blocks, multiplied by M_factor (ex in non-lumped-mass FEM)
+							   double Ct_factor,	///< load Ct into bi:  bi+= Ct*Ct_factor
+							   double C_factor,		///< load C  into bi:  bi+= C*C_factor, otherwise..
+							   double recovery_clamp,///< if do_clamp=true,  bi+= min(C*C_factor, recovery_clamp); 
+							   bool do_clamp		///< if true, limit the recovery of constraint drifting
+						);
+
+				/// Pushes back all ChConstraints and ChVariables contained in links,bodies,etc. 
+				/// into the LCP descriptor. 
+	virtual void LCPprepare_inject(ChLcpSystemDescriptor& mdescriptor);
+
+				/// The following constraints<->system functions are used before and after the solution of a LCP, because
+				/// iterative LCP solvers may converge faster to the Li lagrangian multiplier solutions if 'guessed' 
+				/// values provided (exploit the fact that ChLink classes implement caches with 'last computed multipliers').
+	virtual void LCPprepare_Li_from_speed_cache();
+	virtual void LCPprepare_Li_from_position_cache();
+	virtual void LCPresult_Li_into_speed_cache();
+	virtual void LCPresult_Li_into_position_cache();
+	virtual void LCPresult_Li_into_reactions(double mfactor);
+
+public:
+
+			//
+			// UTILITY FUNCTIONS
+			//
+
+				/// If ChProbe() objects are added to this system, using this command you force 
+				/// the ChProbe::Record() on all them, at once.
+	int RecordAllProbes(); 
+
+				/// If ChProbe() objects are added to this system, using this command you force 
+				/// the ChProbe::Reset() on all them, at once.				
+	int ResetAllProbes();
+
+				/// Executes custom processing at the end of step. By default it does nothing, 
+				/// but if you inherit a special ChSystem you can implement this.
+	virtual void CustomEndOfStep() {};
+
+				/// Set the script engine (ex. a Javascript engine). 
+				/// The user must take care of creating and deleting the script 
+				/// engine , if any, and deletion must happen after deletion of the ChSystem.
+	void SetScriptEngine(ChScriptEngine* mengine) {this->scriptEngine = mengine;}
+	ChScriptEngine* GetScriptEngine() {return this->scriptEngine;}
+
+	char* GetScriptForStartFile() {return scriptForStartFile;}
+	char* GetScriptForUpdateFile() {return scriptForUpdateFile;}
+	char* GetScriptForStepFile() {return scriptForStepFile;}
+	char* GetScriptFor3DStepFile() {return scriptFor3DStepFile;}
+	int SetScriptForStartFile(char* mfile);
+	int SetScriptForUpdateFile(char* mfile);
+	int SetScriptForStepFile(char* mfile);
+	int SetScriptFor3DStepFile(char* mfile);
+	int ExecuteScriptForStart();
+	int ExecuteScriptForUpdate();
+	int ExecuteScriptForStep();
+	int ExecuteScriptFor3DStep();
+
+				/// If ChControl() objects are added to this system, using the following commands 
+				/// you call the execution of their scripts. You seldom call these functions directly,
+				/// since the ChSystem() methods already call them automatically, at each step, update, etc. 
+	int ExecuteControlsForStart();
+	int ExecuteControlsForUpdate();
+	int ExecuteControlsForStep();
+	int ExecuteControlsFor3DStep();
+
+
+
+				/// All bodies with collision detection data are requested to
+				/// store the current position as "last position collision-checked"
+	void SynchronizeLastCollPositions();
+
+
+				/// Perform the collision detection.
+				/// For each contact, a ChLink object is created and inserted into
+				/// the linklist. Previous contacts, if existing in the linklist,
+				/// are deleted or replaced by the new ones. 
+				/// This is mostly called automatically by time integration.
+	double ComputeCollisions();
+
+
+					/// Class to be inherited by user and to use in SetCustomComputeCollisionCallback()
+			class ChApi ChCustomComputeCollisionCallback
+			{
+				public: virtual void PerformCustomCollision(ChSystem*) {};
+			};
+				/// Use this if you want that some specific callback function is executed at each 
+				/// collision detection step (ex. all the times that ComputeCollisions() is automatically
+				/// called by the integration method). For example some other collision engine could 
+				/// add further contacts using this callback.
+	void	SetCustomComputeCollisionCallback(ChCustomComputeCollisionCallback* mcallb) {collision_callback = mcallb;};
+
+
+
+					/// Class to be inherited by user and to use in SetCustomCollisionPointCallback()
+			class  ChApi ChCustomCollisionPointCallback
+			{
+				public:	virtual void ContactCallback(
+							const collision::ChCollisionInfo& mcontactinfo, ///< get info about contact (cannot change it)				
+							ChMaterialCouple&  material 			  		///< you can modify this!
+													) = 0;
+			};
+				/// Use this if you want that some specific callback function is executed soon after 
+				/// each contact point is created. The callback will be called many times, once for each contact.
+				/// Example: it can be used to modify the friction coefficients for each created 
+				/// contact (otherwise, by default, would be the average of the two frict.coeff.)
+	void	SetCustomCollisionPointCallback(ChCustomCollisionPointCallback* mcallb) {collisionpoint_callback = mcallb;};
+
+
+
+	public:
+
+				/// For higher performance (ex. when GPU coprocessors are available) you can create your own
+				/// custom collision engine (suffice it is inherited from ChCollisionSystem) and plug
+				/// it into the system using this function. The replaced engine is automatically deleted. 
+				/// When the system is deleted, the custom engine that you plugged will be automatically deleted.
+				/// Note: use only _before_ you start adding colliding bodies to the system!
+	void ChangeCollisionSystem(ChCollisionSystem* newcollsystem);
+
+				/// Access the collision system, the engine which 
+				/// computes the contact points (usually you don't need to
+				/// access it, since it is automatically handled by the
+				/// client ChSystem object).
+	ChCollisionSystem* GetCollisionSystem() {return collision_system;}; 
+
+
+
+				/// Turn on this feature to let the system put to sleep the bodies whose
+				/// motion has almost come to a rest. This feature will allow faster simulation
+				/// of large scenarios for real-time purposes, but it will affect the precision!
+				/// This functionality can be turned off selectively for specific ChBodies.
+	void SetUseSleeping(bool ms) {use_sleeping = ms;}
+
+				/// Tell if the system will put to sleep the bodies whose motion has almost come to a rest. 
+	bool GetUseSleeping() {return use_sleeping;}
+
+  private:
+	  			/// If some body has been tentatively and automatically put into sleeping mode,
+				/// but it is touching some objects that are still moving, this function
+				/// will wake up those sleeping bodies. Used internally.
+	void WakeUpSleepingBodies();
+
+
+
+
+			//
+			// ANALYSIS FUNCTIONS
+			//
+
+  private:
+				/// Performs a single dynamical simulation step, according to
+				/// current values of:  Y, time, step  (and other minor settings)
+				/// The time step can be automatically repeated (or shrunken)
+				/// if too much C violation or local integration error.
+				/// Automatic assemblation of C and Cdt holonomic constraint is done too.
+	int Integrate_Y ();
+
+	
+				/// As Integrate_Y(), but uses the differential inclusion approach as in Anitescu,
+				/// Use Anitescu stepper, with position stabilization in speed stage.
+	virtual int Integrate_Y_impulse_Anitescu ();
+
+				/// As Integrate_Y(), but uses the differential inclusion approach as in Anitescu,
+				/// Use Tasora stepper, with separate stage for position stabilization.
+	int Integrate_Y_impulse_Tasora ();
+
+  public:
+
+				// ---- DYNAMICS   
+
+				/// Advances the dynamical simulation for a single step, of 
+				/// length m_step. You can call this function many
+				/// times in order to simulate up to a desired end time.
+				/// This is the most important function for analysis, you
+				/// can use it, for example, once per screen refresh in VR
+				/// and interactive realtime applications, etc.
+	int DoStepDynamics (double m_step);
+
+				/// Performs integration until the m_endtime is exactly
+				/// reached, but current time step may be automatically "retouched" to
+	            /// meet exactly the m_endtime after n steps.
+				/// Useful when you want to advance the simulation in a 
+				/// simulations (3d modeling software etc.) wihch needs updates
+				/// of the screen at a fixed rate (ex.30th of second)  while
+				/// the integration must use more steps. 
+	int DoFrameDynamics (double m_endtime);
+	
+				/// Given the current state, the sw simulates the
+				/// dynamical behaviour of the system, until the end
+				/// time is reached, repeating many steps (maybe the step size
+				/// will be automatically changed if the integrator method supports
+				/// step size adaption).
+	int DoEntireDynamics ();
+
+				/// Like "DoEntireDynamics", but results are provided at uniform
+				/// steps "frame_step", using the DoFrameDynamics() many times.
+	int DoEntireUniformDynamics (double frame_step);
+
+
+
+				// ---- KINEMATICS
+
+				/// Advances the kinematic simulation for a single step, of 
+				/// length m_step. You can call this function many
+				/// times in order to simulate up to a desired end time.
+	int DoStepKinematics (double m_step);
+
+				/// Performs kinematics until the m_endtime is exactly
+				/// reached, but current time step may be automatically "retouched" to
+	            /// meet exactly the m_endtime after n steps.
+	int DoFrameKinematics (double m_endtime);
+
+				/// Given the current state, this kinematic simulation  
+				/// satisfies all the costraints with the "DoStepKinematics"
+				/// procedure for each time step, from the current time
+				/// to the end time.
+	int DoEntireKinematics ();
+
+
+
+				// ---- CONSTRAINT ASSEMBLATION
+
+				/// Given the current time and state, the
+				/// sw tries to satisfy all costraints, with
+				/// the Newton-Raphson iteration. Used iteratively
+				/// in inverse kinematics.
+				/// Different tolerance checking allowable (norm 1/2/inf)
+				///  mode = [action flags, see above], ASS_POSITION , ASS_SPEED , ASS_ACCEL (also together)
+				///  flags = [see above]
+				///  ASF_COLLISION , perform also collision detection
+				/// Returns 0 if no errors, returns TRUE if error happened (impossible assemblation?)
+	int DoAssembly (int action, int mflags=0);
+
+				/// Shortcut for full pos/speed/acc assembly, also computes forces
+	int DoFullAssembly();
+
+
+				// ---- STATICS
+
+				/// Solve the position of static equilibrium (and the
+				/// reactions). This is a one-step only approach that solves
+				/// the _linear_ equilibrium. To be used mostly for FEM 
+				/// problems with small deformations.
+	int DoStaticLinear();
+
+				/// Finds the position of static equilibrium (and the
+				/// reactions) starting from the current position.
+				/// Since a truncated iterative metod is used, you may need
+				/// to call this method multiple times in case of large nonlienarities
+				/// before coming to the precise static solution.
+	int DoStaticRelaxing();
+
+
+
+
+
+			//
+			// STREAMING
+			//
+
+					/// Method to allow deserializing a persistent binary archive (ex: a file)
+					/// into transient data.
+	void StreamIN(ChStreamInBinary& mstream);
+
+					/// Method to allow serializing transient data into a persistent
+					/// binary archive (ex: a file).
+	void StreamOUT(ChStreamOutBinary& mstream);
+
+					/// Method to allow serialization of transient data in ascii,
+					/// as a readable item, for example   "chrono::GetLog() << myobject;"
+	void StreamOUT(ChStreamOutAscii& mstream);
+
+					/// Binary save data, for this object and subobjects (bodies, links, etc.)
+	int StreamOUTall (ChStreamOutBinary& m_file);
+
+					/// Binary read data, for this object and subobjects (bodies, links, etc.),
+					/// also rebuilding hierarchy.
+	int StreamINall (ChStreamInBinary& m_file);
+
+					/// Writes the hierarchy of contained bodies, markers, etc. in ASCII
+					/// readable form, mostly for debugging purposes.
+	void ShowHierarchy(ChStreamOutAscii& m_file);
+
+					/// Process a ".chr" binary file containing the full system object
+					/// hierarchy as exported -for example- by the R3D modeler, with chrono plugin version,
+					/// or by using the FileWriteChR() function.
+	int FileProcessChR (ChStreamInBinary& m_file);
+
+					/// Write a ".chr" binary file containing the full system object
+					/// hierarchy (bodies, forces, links, etc.) (deprecated function - obsolete)
+	int FileWriteChR   (ChStreamOutBinary& m_file);
+
+					/// If you have initialized SetScriptEngine(), here you can process 
+					/// a script file, i.e. a file containing a Chrono scripted
+					/// program (it may build a system and perform simulations, and write to files)
+					/// Example, a ".js"  jvascript file that contain generic javascript commands.
+	int FileProcessJS (char* m_file);
+
+
+		
+	/////////////////////////////////////////////////////////////////////////////////////
+
+protected:
+
+		//
+		// DATA
+		//
+
+						// list of rigid bodies
+	std::vector<ChBody*> bodylist;
+
+						// list of joints (links)
+	std::list<ChLink*>   linklist; 
+
+						// list of other physic objects that are not bodies or links
+	std::list<ChPhysicsItem*> otherphysicslist; 
+
+						// list of 'probes' (variable-recording objects, exp. for
+						// 3rd party apps)
+	std::vector<ChProbe*> probelist;
+
+						// list of 'controls' script objects (objects containing 
+						// scripting programs and GUI panels, exp. for 3rd party apps)
+	std::vector<ChControls*> controlslist;
+
+						// the container of contacts
+	ChContactContainerBase* contact_container;
+
+
+	ChVector<> G_acc;	// gravitational acceleration
+
+	double end_time;	// end of simulation, in seconds
+	double step;		// time step, in seconds
+	double step_min;	// min time step
+	double step_max;	// max time step
+	int order;			// integration order
+	int multisteps;		// multistep number
+	double tol;			// tolerance
+	double tol_speeds;	// tolerance for speeds
+	int normtype;		// type of norm
+	int maxiter;		// max iterations for tolerance convergence
+	double st_region;	// stability interval of expl.integrator
+	int adaption;		// adaption of time step, for variable-step integr.
+	int dynaclose;		// true = close constraint clearances during dynamics, as following:
+	int ns_close_pos;	//  each ns steps close position constraints (def = 1, each step);
+	int ns_close_speed;	//  each ns steps close speed constraints (def = 3, each 3 steps);
+	double dynatol;		// integration step repeated and halfed if |C|> (tol * dynatol);
+	double monolat_tol;	// integration step repeated and halfed if |Cmonolateral| > (tol * monolat_tol);
+	double integr_tol;	// integration step repeated and halfed if |Err_integrator| > (tol * integr_tol);
+	double stifftol;	// integration step repeated and halfed if |Ynew - Ypredicted| > (tol * stifftol);
+	int predict;		// true = use prediction to guess if system is getting stiff
+	int predorder;		// prediction polynomial order
+	int modeXY;			// if =1, computes everything on XY plane, for simple bidimensional case.
+	double err_integr;	// current value of integration error -if err.extimation is supported by int.method-
+	double err_constr;	// current value of constraint violation error
+	int auto_assembly;	// keep system automatically assemblated when GUI modifies position of bodies (used by interface)
+	int msteps_collide; // maximum number of steps for bisection rule which rewinds the intgration at the collision event //***DISABLED
+	bool use_GPU;		// if true, the GPU parallel code is used for the LCP problem
+	bool use_sleeping;  // if true, can put to sleep objects that come to rest, to speed up simulation (but decreasing the precision)
+
+	eCh_integrationType integration_type;// integration scheme
+
+	ChLcpSystemDescriptor* LCP_descriptor; // the LCP system descriptor		
+	ChLcpSolver* LCP_solver_speed;	// the LCP solver for speed problem 
+	ChLcpSolver* LCP_solver_stab;	// the LCP solver for position (stabilization) problem, if any
+	eCh_lcpSolver lcp_solver_type;	// Type of LCP solver (iterative= fastest, but may fail satisfying constraints)
+
+	int iterLCPmaxIters;	// maximum n.of iterations for the iterative LCP solver
+	int iterLCPmaxItersStab;// maximum n.of iterations for the iterative LCP solver when used for stabilizing constraints
+	int simplexLCPmaxSteps;	// maximum number of steps for the simplex solver.
+
+	double min_bounce_speed; // maximum speed for rebounce after impacts. If lower speed at rebounce, it is clamped to zero.
+	double max_penetration_recovery_speed; // For Anitescu stepper, this value limits the speed of penetration recovery (>0, speed of exiting)
+
+	int parallel_thread_number; // used for multithreaded solver etc.
+
+	int stepcount;		// internal counter for steps
+
+	int nbodies;		// number of bodies (currently active)
+	int nlinks;			// number of links
+	int nphysicsitems;	// number of other physics items
+	int ncoords;		// number of scalar coordinates (including 4th dimension of quaternions) for all active bodies
+	int ndoc;			// number of scalar costraints (including constr. on quaternions)
+	int nsysvars;		// number of variables (coords+lagrangian mult.), i.e. = ncoords+ndoc  for all active bodies
+	int ncoords_w;		// number of scalar coordinates when using 3 rot. dof. per body;  for all active bodies
+	int ndoc_w;			// number of scalar costraints  when using 3 rot. dof. per body;  for all active bodies
+	int nsysvars_w;		// number of variables when using 3 rot. dof. per body; i.e. = ncoords_w+ndoc_w
+	int ndof;			// number of degrees of freedom, = ncoords-ndoc =  ncoords_w-ndoc_w ,
+	int ndoc_w_C;		// number of scalar costraints C, when using 3 rot. dof. per body (excluding unilaterals)
+	int ndoc_w_D;		// number of scalar costraints D, when using 3 rot. dof. per body (only unilaterals)
+	int ncontacts;		// number of contacts 
+	int nbodies_sleep;  // number of bodies that are sleeping
+	int nbodies_fixed;  // number of bodies that are fixed
+
+						// The collision engine, to compute and store contact manifolds
+	ChCollisionSystem*		collision_system;
+
+	ChCustomComputeCollisionCallback* collision_callback;
+	public: ChCustomCollisionPointCallback*	  collisionpoint_callback;
+	private:
+
+	char err_message[CHSYS_ERRLEN];	// the last ok/warning/error messages are written here
+	int last_err;			// If null, no error during last kinematic/dynamics/statics etc.
+							// otherwise see CHSYS_ERR_xxxx  code
+
+	ChEvents* events;		// the cyclic buffer which records event IDs
+
+	ChScriptEngine* scriptEngine;	// points to a script engine
+	ChScript* scriptForStart;		// this script is executed when simulation starts.
+	char scriptForStartFile[200];
+	ChScript* scriptForUpdate;		// this script is executed for each Update step.
+	char scriptForUpdateFile[200];
+	ChScript* scriptForStep;		// this script is executed for each integration step
+	char scriptForStepFile[200];
+	ChScript* scriptFor3DStep;		// this script is executed for each 3d interface macro step
+	char scriptFor3DStepFile[200];
+
+							// timers for profiling execution speed
+	protected:
+	double timer_step;
+	double timer_lcp;
+	double timer_collision_broad;
+	double timer_collision_narrow;
+	double timer_update;
+
+};
+
+
+
+
+
+//////////////////////////////////////
+// Define flags for "action" of
+// DoAssembly()  function 
+
+#define ASS_POSITION	(1L << 0)
+#define ASS_SPEED		(1L << 1)
+#define ASS_ACCEL		(1L << 2)
+
+// define other flags for "flags"
+// argument of DoAssembly() function 
+#define ASF_NONE				0
+#define ASF_COLLISIONS			(1L << 6)
+
+
+
+
+} // END_OF_NAMESPACE____
+
+#endif // ond of ChSystem.h
diff --git a/SRC/ChronoEngine/physics/ChSystemOpenMP.cpp b/SRC/ChronoEngine/physics/ChSystemOpenMP.cpp
new file mode 100644
index 0000000..b780d0f
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChSystemOpenMP.cpp
@@ -0,0 +1,346 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+///////////////////////////////////////////////////
+//
+//   ChSystemOpenMP.cpp
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include <stdlib.h>
+#include <iostream>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+#include <memory.h>
+#include <algorithm>
+
+#include "physics/ChSystemOpenMP.h"
+#include "physics/ChGlobal.h"
+//#include "physics/ChCollide.h"
+#include "physics/ChBodyAuxRef.h"
+#include "physics/ChContactContainer.h"
+#include "physics/ChProximityContainerBase.h"
+
+#include "lcp/ChLcpSystemDescriptor.h"
+#include "lcp/ChLcpSimplexSolver.h"
+#include "lcp/ChLcpIterativeSOR.h"
+#include "lcp/ChLcpIterativeSymmSOR.h"
+#include "lcp/ChLcpIterativeSORmultithread.h"
+#include "lcp/ChLcpIterativeJacobi.h"
+//#include "lcp/ChLcpIterativeMINRES.h"
+#include "lcp/ChLcpIterativePMINRES.h"
+#include "lcp/ChLcpIterativeBB.h"
+#include "lcp/ChLcpIterativePCG.h"
+#include "lcp/ChLcpSolverDEM.h"
+
+#include "core/ChTimer.h"
+#include "collision/ChCCollisionSystemBullet.h"
+#include "collision/ChCModelBulletBody.h"
+
+#include "core/ChMemory.h" // must be last include (memory leak debugger). In .cpp only.
+using namespace chrono::collision;
+
+namespace chrono {
+
+// Hierarchy-handling functions
+
+#define Bpointer		    (*ibody)
+#define HIER_BODY_INIT      std::vector<ChBody*>::iterator ibody = bodylist.begin();
+#define HIER_BODY_NOSTOP    (ibody != bodylist.end())
+#define HIER_BODY_NEXT	    ibody++;
+
+#define Lpointer		    (*iterlink)
+#define HIER_LINK_INIT      std::list<ChLink*>::iterator iterlink = linklist.begin();
+#define HIER_LINK_NOSTOP    (iterlink != linklist.end())
+#define HIER_LINK_NEXT	    iterlink++;
+
+#define PHpointer		    (*iterotherphysics)
+#define HIER_OTHERPHYSICS_INIT    std::list<ChPhysicsItem*>::iterator iterotherphysics = otherphysicslist.begin();
+#define HIER_OTHERPHYSICS_NOSTOP  (iterotherphysics != otherphysicslist.end())
+#define HIER_OTHERPHYSICS_NEXT	  iterotherphysics++;
+
+#define Ppointer		    (*iterprobe)
+#define HIER_PROBE_INIT      std::vector<ChProbe*>::iterator iterprobe = probelist.begin();
+#define HIER_PROBE_NOSTOP    (iterprobe != probelist.end())
+#define HIER_PROBE_NEXT	    iterprobe++;
+
+#define Cpointer		    (*itercontrol)
+#define HIER_CONTROLS_INIT      std::vector<ChControls*>::iterator itercontrol = controlslist.begin();
+#define HIER_CONTROLS_NOSTOP    (itercontrol != controlslist.end())
+#define HIER_CONTROLS_NEXT	    itercontrol++;
+
+//////////////////////////////////////
+//////////////////////////////////////
+// CLASS FOR PHYSICAL SYSTEM
+
+// Register into the object factory, to enable run-time
+// dynamic creation and persistence
+ChClassRegister<ChSystemOpenMP> a_registration_ChSystemOpenMP;
+
+ChSystemOpenMP::ChSystemOpenMP(unsigned int max_objects, double scene_size, bool init_sys) :
+        ChSystem() {
+}
+
+ChSystemOpenMP::~ChSystemOpenMP() {
+
+}
+
+void ChSystemOpenMP::Update()
+{
+
+    ChTimer<double>mtimer; mtimer.start(); // Timer for profiling
+
+
+    //events->Record(CHEVENT_UPDATE); // Record an update event
+
+                                    // Executes the "forUpdate" script, if any
+    ExecuteScriptForUpdate();
+                                    // Executes the "forUpdate" script
+                                    // in all controls of controlslist
+    ExecuteControlsForUpdate();
+
+                                    // --------------------------------------
+                                    // Spread state vector Y to bodies
+                                    //    Y --> Bodies
+
+
+
+
+    mtimer.stop();
+    timer_update += mtimer();
+}
+
+
+
+
+void ChSystemOpenMP::LCPprepare(bool load_jacobians,
+                               bool load_v,
+                               double F_factor,
+							   double K_factor,
+							   double R_factor,
+							   double M_factor,
+                               double Ct_factor,
+                               double C_factor,
+                               double recovery_clamp,
+                               bool do_clamp,
+                               ChLcpSystemDescriptor& mdescriptor
+                                )
+{
+    this->contact_container->Update(); // Update all contacts, if any
+    this->contact_container->ConstraintsBiReset();
+    mdescriptor.BeginInsertion(); // This resets the vectors of constr. and var. pointers.
+    HIER_LINK_INIT
+    while HIER_LINK_NOSTOP
+    {
+        Lpointer->Update(ChTime);
+        Lpointer->ConstraintsBiReset();
+        if (C_factor)
+            Lpointer->ConstraintsBiLoad_C(C_factor, recovery_clamp, do_clamp);
+        if (Ct_factor)
+            Lpointer->ConstraintsBiLoad_Ct(Ct_factor);          // Ct
+        if (F_factor)
+            Lpointer->ConstraintsFbLoadForces(F_factor);        // f*dt
+        if (load_jacobians)
+            Lpointer->ConstraintsLoadJacobians();
+        Lpointer->ConstraintsLiLoadSuggestedSpeedSolution();
+        Lpointer->InjectConstraints(mdescriptor);
+        HIER_LINK_NEXT
+    }
+#pragma omp parallel for
+    for(int i=0; i<bodylist.size(); i++){
+        bodylist[i]->Update(ChTime);
+        if (this->GetUseSleeping()){ bodylist[i]->TrySleeping();}
+         bodylist[i]->VariablesFbReset();
+        if (F_factor)
+             bodylist[i]->VariablesFbLoadForces(F_factor);          // f*dt
+        if (load_v)
+             bodylist[i]->VariablesQbLoadSpeed();                   // v_old
+
+         bodylist[i]->InjectVariables(mdescriptor);
+    }
+
+    HIER_OTHERPHYSICS_INIT
+    while HIER_OTHERPHYSICS_NOSTOP
+    {
+        PHpointer->Update(ChTime);
+        PHpointer->VariablesFbReset();
+               PHpointer->ConstraintsBiReset();
+        if (F_factor)
+            PHpointer->VariablesFbLoadForces(F_factor);         // f*dt
+        if (load_v)
+            PHpointer->VariablesQbLoadSpeed();                  // v_old
+        if (C_factor)
+            PHpointer->ConstraintsBiLoad_C(C_factor, recovery_clamp, do_clamp);
+        if (Ct_factor)
+            PHpointer->ConstraintsBiLoad_Ct(Ct_factor);         // Ct
+        if (load_jacobians)
+            PHpointer->ConstraintsLoadJacobians();
+		if (K_factor || R_factor)
+			PHpointer->KRMmatricesLoad(K_factor, R_factor, M_factor);
+        PHpointer->ConstraintsLiLoadSuggestedSpeedSolution();
+        PHpointer->InjectVariables(mdescriptor);
+        PHpointer->InjectConstraints(mdescriptor);
+		PHpointer->InjectKRMmatrices(mdescriptor);
+        HIER_OTHERPHYSICS_NEXT
+    }
+
+    if (C_factor)
+        contact_container->ConstraintsBiLoad_C(C_factor, recovery_clamp, do_clamp);
+    if (F_factor)
+        contact_container->ConstraintsFbLoadForces(F_factor);       // f*dt
+    if (load_jacobians)
+        contact_container->ConstraintsLoadJacobians();
+
+    this->contact_container->ConstraintsLiLoadSuggestedSpeedSolution();
+    this->contact_container->InjectConstraints(mdescriptor);
+    mdescriptor.EndInsertion();
+}
+
+int ChSystemOpenMP::Integrate_Y_impulse_Anitescu() {
+    int ret_code = TRUE;
+
+        ChTimer<double> mtimer_step;
+        mtimer_step.start();
+
+        //events->Record(CHEVENT_TIMESTEP);
+
+                                    // Executes the "forStep" script, if any
+        ExecuteScriptForStep();
+                                    // Executes the "forStep" script
+                                    // in all controls of controlslist
+        ExecuteControlsForStep();
+
+
+        this->stepcount++;
+
+        // Compute contacts and create contact constraints
+
+        ComputeCollisions();
+
+
+        Setup();    // Counts dofs, statistics, etc.
+
+
+        Update();   // Update everything - and put to sleep bodies that need it
+
+                    // Re-wake the bodies that cannot sleep because they are in contact with
+                    // some body that is not in sleep state.
+        //WakeUpSleepingBodies();
+
+
+        ChTimer<double> mtimer_lcp;
+        mtimer_lcp.start();
+
+
+        //
+        // Enforce velocity/impulses constraints ....................
+        //
+
+        // reset known-term vectors
+        //LCPprepare_reset();
+
+        // fill LCP known-term vectors with proper terms (forces, etc.):
+        //
+        // | M+dt^2*K+dt*R  -Cq'|*|v_new|- | [M]*v_old + f*dt      | = |0| ,  c>=0, l>=0, l*c=0;
+        // | Cq              0  | |l    |  | -C/dt +min(-C/dt,vlim)|   |c|
+        //
+
+        LCPprepare(true,           // Cq,
+                        true,           // add [M]*v_old to the known vector
+                        GetStep(),      // f*dt
+						GetStep()*GetStep(), // dt^2*K  (nb only non-Schur based solvers support K matrix blocks)
+						GetStep(),		// dt*R   (nb only non-Schur based solvers support K matrix blocks)
+						1.0,			// M (for FEM with non-lumped masses, add their mass-matrices)
+                        1.0,            // Ct   (needed, for rheonomic motors)
+                        1.0/GetStep(),  // C/dt
+                        max_penetration_recovery_speed,  // vlim, max penetrations recovery speed (positive for exiting)
+                        true, // do above max. clamping on -C/dt
+                        *this->LCP_descriptor);
+
+        // if warm start is used, can exploit cached multipliers from last step...
+        //LCPprepare_Li_from_speed_cache();
+
+        // make vectors of variables and constraints, used by the following LCP solver
+        //LCPprepare_inject(*this->LCP_descriptor);
+
+
+        // Solve the LCP problem.
+        // Solution variables are new speeds 'v_new'
+        GetLcpSolverSpeed()->Solve(
+                                *this->LCP_descriptor
+                                );          
+
+        mtimer_lcp.stop();
+        timer_lcp = mtimer_lcp();
+
+        // stores computed multipliers in constraint caches, maybe useful for warm starting next step
+        LCPresult_Li_into_speed_cache();
+
+        // updates the reactions of the constraint
+        LCPresult_Li_into_reactions(1.0/this->GetStep()) ; // R = l/dt  , approximately
+
+        // perform an Eulero integration step (1st order stepping as pos+=v_new*dt)
+
+
+        HIER_BODY_INIT
+        while HIER_BODY_NOSTOP
+        {
+            // EULERO INTEGRATION: pos+=v_new*dt  (do not do this, if GPU already computed it)
+            if (!use_GPU)
+            {
+                Bpointer->VariablesQbIncrementPosition(this->GetStep());
+                // Set body speed, and approximates the acceleration by differentiation.
+                Bpointer->VariablesQbSetSpeed(this->GetStep());
+            }
+            // Now also updates all markers & forces
+            Bpointer->Update(this->ChTime);
+            HIER_BODY_NEXT
+        }
+        HIER_OTHERPHYSICS_INIT
+        while HIER_OTHERPHYSICS_NOSTOP
+        {
+            // EULERO INTEGRATION: pos+=v_new*dt  (do not do this, if GPU already computed it)
+            if (!use_GPU)
+            {
+                PHpointer->VariablesQbIncrementPosition(this->GetStep());
+                // Set body speed, and approximates the acceleration by differentiation.
+                PHpointer->VariablesQbSetSpeed(this->GetStep());
+            }
+            // Now also updates all markers & forces
+            PHpointer->Update(this->ChTime);
+            HIER_OTHERPHYSICS_NEXT
+        }
+
+        this->ChTime = ChTime + GetStep();
+
+        // Executes custom processing at the end of step
+        CustomEndOfStep();
+
+        // If there are some probe objects in the probe list,
+        // tell them to record their variables (ususally x-y couples)
+        RecordAllProbes();
+
+        // Time elapsed for step..
+        mtimer_step.stop();
+        timer_step = mtimer_step();
+
+
+        return (ret_code);
+}
+} // END_OF_NAMESPACE____
+
+/////////////////////////////////////// eof
+
diff --git a/SRC/ChronoEngine/physics/ChSystemOpenMP.h b/SRC/ChronoEngine/physics/ChSystemOpenMP.h
new file mode 100644
index 0000000..1921989
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChSystemOpenMP.h
@@ -0,0 +1,93 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2012 Alessandro Tasora
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHSYSTEMOPENMP_H
+#define CHSYSTEMOPENMP_H
+
+//////////////////////////////////////////////////
+//
+//   ChSystemOpenMP.h
+//
+//   The physical system definition.
+//   A phisical system encloses bodies, links, 
+//   probes, etc.
+//   This is the oldest source file of Chrono::Engine
+//   therefore it is poorly written and under major
+//   revisiting... Stay tuned..
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+#include "physics/ChSystem.h"
+
+namespace chrono {
+
+//////////////////////////////////////
+//  MULTIBODY SYSTEM CLASS
+//
+/// This class is used to represent a multibody physical system,
+/// so it acts also as a database for most items involved in
+/// simulations, most noticeably objects of ChBody and ChLink
+/// classes, which are used to represent mechanisms.
+///
+/// Moreover, it also owns some global settings and features,
+/// like the gravity acceleration, the global time and so on.
+///
+/// This object will be responsible of performing the entire
+/// physical simulation (dynamics, kinematics, statics, etc.),
+/// so you need at least one ChSystem object in your program, in
+/// order to perform simulations (you'll insert rigid bodies and
+/// links into it..)
+///
+
+class ChApi ChSystemOpenMP: public ChSystem {
+
+    CH_RTTI(ChSystemOpenMP,ChSystem)
+        ;
+
+    public:
+
+        //
+        // BUILDERS
+        //
+
+        /// Create a physical system.
+        /// Note, in case you will use collision detection, the values of
+        /// 'max_objects' and 'scene_size' can be used to initialize the broadphase
+        /// collision algorithm in an optimal way. Scene size should be approximately
+        /// the radius of the expected area where colliding objects will move.
+        /// If init_sys is false it does not initialize the collision system or solver
+        /// assumes that the user will do so.
+        ChSystemOpenMP(unsigned int max_objects = 16000, double scene_size = 500, bool init_sys = true);
+
+        /// Destructor
+        virtual ~ChSystemOpenMP();
+        void Update();
+
+        void LCPprepare(bool load_jacobians, bool load_v, double F_factor, double K_factor, double R_factor, double M_factor, double Ct_factor, double C_factor, double recovery_clamp, bool do_clamp, ChLcpSystemDescriptor& mdescriptor);
+
+        /// Copy from another ChSystem.
+        /// Note! All settings are copied, but the hierarchy of children
+        /// As Integrate_Y(), but uses the differential inclusion approach as in Anitescu,
+        /// Use Anitescu stepper, with position stabilization in speed stage.
+        virtual int Integrate_Y_impulse_Anitescu();
+
+};
+
+} // END_OF_NAMESPACE____
+
+#endif // ond of ChSystem.h
diff --git a/SRC/ChronoEngine/physics/ChTensors.h b/SRC/ChronoEngine/physics/ChTensors.h
new file mode 100644
index 0000000..990dfe0
--- /dev/null
+++ b/SRC/ChronoEngine/physics/ChTensors.h
@@ -0,0 +1,196 @@
+//
+// PROJECT CHRONO - http://projectchrono.org
+//
+// Copyright (c) 2013 Project Chrono
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be 
+// found in the LICENSE file at the top level of the distribution
+// and at http://projectchrono.org/license-chrono.txt.
+//
+
+#ifndef CHTENSORS_H
+#define CHTENSORS_H
+
+//////////////////////////////////////////////////
+//  
+//   ChTensors.h
+//
+//   Class for stress & strain tensors
+//
+//   HEADER file for CHRONO,
+//	 Multibody dynamics engine
+//
+// ------------------------------------------------
+//             www.deltaknowledge.com
+// ------------------------------------------------
+///////////////////////////////////////////////////
+
+
+#include <stdlib.h>
+#include "core/ChApiCE.h"
+#include "core/ChMath.h"
+#include "core/ChShared.h"
+
+namespace chrono 
+{
+namespace fem
+{
+
+
+/// Base class for stress and strain tensors, in compact Voight notation
+/// that is with 6 components in a column. This saves some
+/// memory when compared to traditional 3D tensors with three
+/// rows and three columns, that are symmetric.
+
+template <class Real = double>
+class ChApi ChVoightTensor : public ChMatrixNM<Real,6,1>
+{
+public:
+					/// Constructors (default empty)
+	ChVoightTensor()  {};
+
+					/// Copy constructor, from a typical 3D rank-two stress or strain tensor (as 3x3 matrix)
+	template <class RealB>
+	inline ChVoightTensor (const ChMatrix33<RealB>& msource) 
+					  {
+						 this->ConvertFromMatrix(msource);
+					  };
+
+	inline Real& XX()   { return ChMatrix<Real>::ElementN(0); };
+	inline const Real& XX () const { return ChMatrix<Real>::ElementN(0); };
+
+	inline Real& YY()   { return ChMatrix<Real>::ElementN(1); };
+	inline const Real& YY () const { return ChMatrix<Real>::ElementN(1); };
+
+	inline Real& ZZ()   { return ChMatrix<Real>::ElementN(2); };
+	inline const Real& ZZ () const { return ChMatrix<Real>::ElementN(2); };
+
+	inline Real& XY()   { return ChMatrix<Real>::ElementN(3); };
+	inline const Real& XY () const { return ChMatrix<Real>::ElementN(3); };
+
+	inline Real& XZ()   { return ChMatrix<Real>::ElementN(4); };
+	inline const Real& XZ () const { return ChMatrix<Real>::ElementN(4); };
+
+	inline Real& YZ()   { return ChMatrix<Real>::ElementN(5); };
+	inline const Real& YZ () const { return ChMatrix<Real>::ElementN(5); };
+		
+			/// Convert from a typical 3D rank-two stress or strain tensor (a 3x3 matrix)
+	template <class RealB>
+	void ConvertFromMatrix(const ChMatrix33<RealB>& msource)
+					{
+						 XX()= (Real)msource(0,0);
+						 YY()= (Real)msource(1,1);
+ 						 ZZ()= (Real)msource(2,2);
+						 XY()= (Real)msource(0,1);
+						 XZ()= (Real)msource(0,2);
+						 YZ()= (Real)msource(1,2);
+					};
+
+			/// Convert to a typical 3D rank-two stress or strain tensor (a 3x3 matrix)
+	template <class RealB>
+	void ConvertToMatrix(ChMatrix33<RealB>& mdest)
+					{
+						 mdest(0,0) = (RealB)XX();
+						 mdest(1,1) = (RealB)YY();
+ 						 mdest(2,2) = (RealB)ZZ();
+						 mdest(0,1) = (RealB)XY();
+						 mdest(0,2) = (RealB)XZ();
+						 mdest(1,2) = (RealB)YZ();
+						 mdest(1,0) = (RealB)XY();
+						 mdest(2,0) = (RealB)XZ();
+						 mdest(2,1) = (RealB)YZ();
+					};
+
+			/// Compute the volumetric part of the tensor, that is 
+			/// the trace V =Txx+Tyy+Tzz.
+	Real GetVolumetricPart() const
+					{
+						return XX()+YY()+ZZ();
+					}
+			/// Compute the deviatoric part of the tensor, storing
+			/// it in mdeviatoric
+	void GetDeviatoricPart(ChVoightTensor<Real>& mdeviatoric) const
+					{
+						Real mM = GetVolumetricPart()/3.0;
+						mdeviatoric = *this;
+						mdeviatoric.XX() -= mM;
+						mdeviatoric.YY() -= mM;
+						mdeviatoric.ZZ() -= mM;
+					}
+
+			/// Compute the I1 invariant
+	Real GetInvariant_I1() const
+			{
+				return XX()+YY()+ZZ();
+			}
+
+			/// Compute the I2 invariant
+	Real GetInvariant_I2() const
+			{
+				return XX()*YY() + YY()*ZZ() + XX()*ZZ() 
+					 - XY()*XY() - YZ()*YZ() - XZ()*XZ();
+			}
+
+			/// Compute the I3 invariant
+	Real GetInvariant_I3() const
+			{
+				return XX()*YY()*ZZ() + 2*XY()*YZ()*XZ() 
+					  -XY()*XY()*ZZ() - YZ()*YZ()*XX() - XZ()*XZ()*YY();
+			}
+
+			/// Compute the J1 invariant of the deviatoric part (that is always 0)
+	Real GetInvariant_J1() const { return 0;}
+			 
+			/// Compute the J2 invariant of the deviatoric part
+	Real GetInvariant_J2() const
+	{
+		return ChMax(0.0,  ((pow(this->GetInvariant_I1(),2))/3.0) -this->GetInvariant_I2() );
+	}
+			/// Compute the J3 invariant of the deviatoric part
+	Real GetInvariant_J3() const
+	{
+		return ( pow(this->GetInvariant_I1(),3)*(2./27.)
+			        -this->GetInvariant_I1()*this->GetInvariant_I2()*(1./3.)
+					+this->GetInvariant_I3() );
+	}
+
+		  /// FORMULAS THAT ARE USEFUL FOR YELD CRITERIONS: 
+
+			/// Compute the Von Mises equivalent
+	double GetEquivalentVonMises() const
+			{	
+				return sqrt( 0.5*(pow(this->XX()-this->YY(),2.) + pow(this->YY()-this->ZZ(),2.) + pow(this->ZZ()-this->XX(),2.)) + 3.0*( this->XY()*this->XY() + this->XZ()*this->XZ() + this->YZ()*this->YZ()) );
+			}
+
+};
+
+/// Class for stress tensors, in compact Voight notation
+/// that is with 6 components in a column. 
+
+template <class Real = double>
+class ChApi ChStressTensor : public ChVoightTensor<Real>
+{
+public:
+
+};
+
+
+/// Class for strain tensors, in compact Voight notation
+/// that is with 6 components in a column. 
+
+template <class Real = double>
+class ChApi ChStrainTensor : public ChVoightTensor<Real>
+{
+public:
+
+};
+
+
+
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+#endif 
diff --git a/SRC/ChronoEngine/pneumatica/assepneumatico.cpp b/SRC/ChronoEngine/pneumatica/assepneumatico.cpp
new file mode 100644
index 0000000..8e274df
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/assepneumatico.cpp
@@ -0,0 +1,206 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: assepneumatico.cpp
+//
+// Descrizione		: Questa classe implementa tutte le funzionalit� di un asse
+//					  pneumatico provvisto di due valvole proporzionali in 
+//					  controllo di portata.
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#include "assepneumatico.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+///////////////////////////////////////////////////////////////////////////////
+AssePneumatico::AssePneumatico()
+{
+	myattuatore = new sis_attuatore_3_2_prop();
+	myattuatore->mypistone->SetupValvole();
+
+	com =new double[2]; memset(com,0x0,sizeof(double)*2);
+
+
+	// Attribuisco alle variabili che definiscono il sistema dei valori sensati
+	ci=2.75e-8;	//0.0000000275; // Conduttanza in ingresso
+	co=3.12e-8;	//0.0000000312;	// Conduttanza in uscita
+	bi=0.44157; // Beta in ingresso
+	bo=0.29748;	// Beta in uscita
+	
+	
+	pva=601325;		//101325; //Pressione nella camera a
+	pma=601325;		//601325; // pressione di alimentazione della camera a
+	pvb=681325;		//601325; // pressione nella camera b //** Per non farlo partire
+	pmb=601325;		//601325; // pressione di alimentazione della camera b
+	ps =101325;		// pressione di scarico
+	
+	
+	l=0.5;			// Corsa dello stelo
+	wa =0.0000042;	//4.2e-6; //0.002*0.1	// Volume morto camera a
+	wb =0.000013;	//1.3e-5;				// Volume morto camera b
+	a=0.002;					// Superficie dello stantuffo
+	alfa=0.9;					// Coefficiente di riduzione superficie dello stantuffo
+	gamma=59.6;					// Coefficiente di smorzamento viscoso							
+	mstelo=5.7;					// Massa dello stelo
+	
+	valvA_min = 0;
+	valvA_close = 5;
+	valvA_max = 10;
+	
+	valvB_min = 0;
+	valvB_close = 5;
+	valvB_max = 10;
+
+	
+	// Inizializzo il sistema
+	// Considero le valvole come simmetriche
+	(myattuatore->mypistone->GetValvA())->SetupValvola(ci, co, bi, bo, ci, co, bi, bo, pma, ps, pva);
+	(myattuatore->mypistone->GetValvB())->SetupValvola(ci, co, bi, bo, ci, co, bi, bo, pmb, ps, pvb);
+
+	myattuatore->mypistone->SetupPistone(ps,l,wa,wb,a,alfa,gamma,mstelo);
+	
+	// Inizizializzo lo stato del sitema
+	*(myattuatore->mypistone->GetStatoPistone())=0;		
+	*(myattuatore->mypistone->GetStatoPistone()+1)=0;
+	*(myattuatore->mypistone->GetStatoPistone()+2)=pva;
+	*(myattuatore->mypistone->GetStatoPistone()+3)=pvb;
+	
+	//******************************************************************************
+	// Impongo il range di funzionamento delle valvole
+	(myattuatore->mypistone->GetValvA())->SetComandoMin(valvA_min);
+	(myattuatore->mypistone->GetValvA())->SetComandoChius(valvA_close);
+	(myattuatore->mypistone->GetValvA())->SetComandoMax(valvA_max);
+	
+	
+	(myattuatore->mypistone->GetValvB())->SetComandoMin(valvB_min);
+	(myattuatore->mypistone->GetValvB())->SetComandoChius(valvB_close);
+	(myattuatore->mypistone->GetValvB())->SetComandoMax(valvB_max);
+	
+	// Condizioni iniziali delle valvole
+	myattuatore->mypistone->SetComando(valvA_close ,valvB_close); //0 0
+
+	// Initialize own command array. Alex
+	com[0] = valvA_close;
+	com[1] = valvB_close;
+
+	// Alloca memoria per le varibili di sistema
+	myattuatore->SetSistema();
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+AssePneumatico::~AssePneumatico()
+{
+	if(myattuatore) delete myattuatore;
+		myattuatore = NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void AssePneumatico::SetupAssePneumatico(void)
+{
+	(myattuatore->mypistone->GetValvA())->SetupValvola(ci, co, bi, bo, ci, co, bi, bo, pma, ps, pva);
+	(myattuatore->mypistone->GetValvB())->SetupValvola(ci, co, bi, bo, ci, co, bi, bo, pmb, ps, pvb);
+
+	myattuatore->mypistone->SetupPistone(ps,l,wa,wb,a,alfa,gamma,mstelo);
+	
+	// Inizizializzo lo stato del sitema
+	
+	//***NOT WANTED??? Alex
+	/*
+
+	*(myattuatore->mypistone->GetStatoPistone())=0;		
+	*(myattuatore->mypistone->GetStatoPistone()+1)=0;
+	*(myattuatore->mypistone->GetStatoPistone()+2)=pva;
+	*(myattuatore->mypistone->GetStatoPistone()+3)=pvb;
+
+	*/	
+
+
+	//******************************************************************************
+	// Impongo il range di funzionamento delle valvole
+	(myattuatore->mypistone->GetValvA())->SetComandoMin(valvA_min);
+	(myattuatore->mypistone->GetValvA())->SetComandoChius(valvA_close);
+	(myattuatore->mypistone->GetValvA())->SetComandoMax(valvA_max);
+	
+	
+	(myattuatore->mypistone->GetValvB())->SetComandoMin(valvB_min);
+	(myattuatore->mypistone->GetValvB())->SetComandoChius(valvB_close);
+	(myattuatore->mypistone->GetValvB())->SetComandoMax(valvB_max);
+	
+	// Condizioni iniziali delle valvole
+
+	// ***NOT WANTED???  Alex
+	//myattuatore->mypistone->SetComando(valvA_close ,valvB_close); //0 0
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//void AssePneumatico::Set_P(double p1, double p2)
+//{
+//
+//};
+//
+///////////////////////////////////////////////////////////////////////////////
+void AssePneumatico::Get_P(double *p1, double *p2)
+{
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//void AssePneumatico::Set_Pos(double x, double x_dt)
+//{
+//
+//};
+//
+///////////////////////////////////////////////////////////////////////////////
+void AssePneumatico::Get_Pos(double *x, double *x_dt)
+{
+
+};
+
+///////////////////////////////////////////////////////////////////////////////
+void AssePneumatico::Update(void)
+{
+	// Inizizializzo lo stato del sitema
+	*(myattuatore->GetStato())=pos;			// Spostamento
+	*(myattuatore->GetStato()+1)=vel;		// Velocit�
+	*(myattuatore->GetStato()+2)=pva;		// Pressione camera a
+	*(myattuatore->GetStato()+3)=pvb;		// Pressione camera b
+
+	// Setto lo stato
+	myattuatore->SetStato();
+
+	myattuatore->SetDerivataStato();
+
+	myattuatore->InizializzaSistema();
+
+	(myattuatore->comandi)= com;
+	myattuatore->Comanda(myattuatore->comandi);
+}; 
+
+
+///////////////////////////////////////////////////////////////////////////////
+double AssePneumatico::Get_F(void)
+{	
+	return myattuatore->mypistone->Forza();
+};
+
+///////////////////////////////////////////////////////////////////////////////
+void AssePneumatico::Get_P_dt(double *p1_dt, double *p2_dt)
+{
+	*(p1_dt)=myattuatore->mypistone->PresA1();
+	*(p2_dt)=myattuatore->mypistone->PresB1();
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/pneumatica/assepneumatico.h b/SRC/ChronoEngine/pneumatica/assepneumatico.h
new file mode 100644
index 0000000..4b91a42
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/assepneumatico.h
@@ -0,0 +1,184 @@
+#ifndef _ASSEPNEUMATICO_H			//*****
+#define _ASSEPNEUMATICO_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: assepneumatico.h
+//
+// Descrizione		: Questa classe implementa tutte le funzionalit� di un asse
+//					  pneumatico provvisto di due valvole proporzionali in
+//					  controllo di portata.
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+#include <math.h>
+#include "sis_attuatore_3_2.h"
+#include "sis_attuatore_3_2_prop.h"
+
+
+namespace chrono
+{
+/// Namespace with classes for the simulation of pneumatic devices
+namespace pneumatics
+{
+
+
+/// This class provides the functionality to simulate a single
+/// pneumatic actuator (i.e. a pneumatic cylinder) with two 3-2
+/// valves and two nozzles.
+
+class AssePneumatico {
+
+private:
+	// Puntatore al sistema pneumatico
+	sis_attuatore_3_2_prop *myattuatore;
+	// Variabili che definisco il sistema
+	double ci,co,bi,bo;
+	double ps,pma,pmb;
+	double l,wa,wb,a,alfa,gamma,mstelo;
+	double valvA_min, valvA_close, valvA_max;
+	double valvB_min, valvB_close, valvB_max;
+
+	double pva, pvb;	// Pressioni nelle due camere del cilindro
+	double pos, vel;	// Posizione e velocit� dello stantuffo
+	double *com;		// Puntatore all'array contenente i comandi da dare alle due valvole
+
+public:
+	AssePneumatico();
+	virtual ~AssePneumatico();
+
+
+	// FUNZIONI PER L'INIZZIALIZZAZIONE DEL SISTEMA
+
+	// Conduttanza ingresso
+	void Set_Ci(double myci){ci=myci; };
+	double Get_Ci(void){return ci;};
+
+	// Conduttanza uscita
+	void Set_Co(double myco){co=myco; };
+	double Get_Co(void){return co;};
+
+	// Beta ingresso
+	void Set_Bi(double mybi){bi=mybi; };
+	double Get_Bi(void){return bi;};
+
+	// Beta uscita
+	void Set_Bo(double mybo){bo=mybo; };
+	double Get_Bo(void){return bo;};
+
+	// Pressione allo scarico
+	void Set_Ps(double myps){ps=myps; };
+	double Get_Ps(void){return ps;};
+
+	// Pressione di alimentazione camera a
+	void Set_Pma(double mypma){pma=mypma; };
+	double Get_Pma(void){return pma;};
+
+	// Pressione di alimentazione camera b
+	void Set_Pmb(double mypmb){pmb=mypmb; };
+	double Get_Pmb(void){return pmb;};
+
+	// Lunghezza della corsa
+	void Set_L(double myl){l=myl; };
+	double Get_L(void){return l;};
+
+	// Volume morto camera a
+	void Set_Wa(double mywa){wa=mywa; };
+	double Get_Wa(void){return wa;};
+
+	// Volume morto camera b
+	void Set_Wb(double mywb){wb=mywb; };
+	double Get_Wb(void){return wb;};
+
+	// Superficie dello stantuffo
+	void Set_A(double mya){a=mya; };
+	double Get_A(void){return a;};
+
+	// Coefficiente di riduzione della superficie dello stantuffo
+	void Set_Alfa(double myalfa){alfa=myalfa; };
+	double Get_Alfa(void){return alfa;};
+
+	// Coefficiente di attrito viscoso
+	void Set_Gamma(double mygamma){gamma=mygamma; };
+	double Get_Gamma(void){return gamma;};
+
+	// Massa dello stelo
+	void Set_Mstelo(double mymstelo){mstelo=mymstelo; };
+	double Get_Mstelo(void){return mstelo;};
+
+	// Setto il comando di apertura minima della valvola
+	void Set_ValvA_min(double myvalvA_min){valvA_min=myvalvA_min;};
+	double Get_ValvA_min(void){return valvA_min;};
+
+	// Setto il comando di chiusura della valvola
+	void Set_ValvA_close(double myvalvA_close){valvA_close=myvalvA_close;};
+	double Get_ValvA_close(void){return valvA_close;};
+
+	// Setto il comando di apertura massima della valvola
+	void Set_ValvA_max(double myvalvA_max){valvA_max=myvalvA_max;};
+	double Get_ValvA_max(void){return valvA_max;};
+
+	// Setto il comando di apertura minima della valvola
+	void Set_ValvB_min(double myvalvB_min){valvB_min=myvalvB_min;};
+	double Get_ValvB_min(void){return valvB_min;};
+
+	// Setto il comando di chiusura della valvola
+	void Set_ValvB_close(double myvalvB_close){valvB_close=myvalvB_close;};
+	double Get_ValvB_close(void){return valvB_close;};
+
+	// Setto il comando di apertura massima della valvola
+	void Set_ValvB_max(double myvalvB_max){valvB_max=myvalvB_max;};
+	double Get_ValvB_max(void){return valvB_max;};
+
+	/////////////////////////////////////////////////////////////
+	// FUNZIONI DI SCAMBIO CON **CHRONO** durante integrazione
+	//
+
+		// pressioni					<---
+	void Set_P(double p1, double p2){pva=p1; pvb=p2;};
+	void Get_P(double *p1, double *p2);	   // nothing
+
+		// posizione e velocit� stelo	<---
+	void Set_Pos(double x, double x_dt){pos=x; vel=x_dt;};
+	void Get_Pos(double *x, double *x_dt); // nothing
+
+		// comandi valvole				<---
+	void Set_Com(double com1, double com2){*(com)=com1; *(com+1)=com2;};
+	void Get_Com(double *com1, double *com2){*(com1)=*(com); *(com2)=*(com+1);};
+	void Set_ComA(double com1){*(com+0)=com1;};
+	void Set_ComB(double com2){*(com+1)=com2;};
+	double Get_ComA(){return *(com+0);};
+	double Get_ComB(){return *(com+1);};
+
+		// Da usare per inizializzarare il sistema con valori
+		// differenti da quelli de default (cfr costruttore)
+	void SetupAssePneumatico(void);
+
+		// Calcola F e P_dt
+	void Update(void);
+
+		// Forza F				--->
+	double Get_F(void);
+
+		// Derivata pressioni	--->
+	void Get_P_dt(double *p1_dt, double *p2_dt);
+
+		// TO DO
+	void Integrate(double, double ){};
+
+	//
+	//
+	///////////////////////////////////////////////////////////////
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif								//*****
diff --git a/SRC/ChronoEngine/pneumatica/pistone.cpp b/SRC/ChronoEngine/pneumatica/pistone.cpp
new file mode 100644
index 0000000..ebd9148
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/pistone.cpp
@@ -0,0 +1,183 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: pistone.cpp
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "pistone.h"
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+pistone::pistone()
+			// Costruttore di pistone
+{
+	l=a=alfa=ga=gb=wa=wb=ps=gamma=mstelo=Dx1=fp=fs=fd=0;
+	
+	ca = cb = NULL;
+	
+	//****** Parametri relativi all'atrito
+	Dx1=0.00001;
+	fs=0;//51.85;		// [N]
+	fd=0;//21.34;		// [N]
+	//************************************
+
+	memset(statopistone,0x0,sizeof(statopistone));
+	memset(derivatastatopistone,0x0,sizeof(derivatastatopistone));
+	
+	ca = new volume();
+	cb = new volume();
+
+}
+
+pistone::~pistone()
+			// Distruttore di pistone
+{
+	if(ca) delete ca;
+	ca = NULL;
+	if(cb) delete cb;
+	cb = NULL;
+}
+
+void pistone::SetupPistone(double mps, double ml, double mwa, double mwb, double ma, double malfa, /*double mfa,*/ double mgamma, double mmstelo)
+			// Pressione di scarico mps (� la stessa che metto nel setup_valvola)
+			// Lunghezza corsa ml, Volume morto camera A e camera B = mwa,mwb
+			// Sezione ma, Coeff.di riduzione sezione malfa, Forza attrito mfa;
+			// Coeff.attrito viscoso mgamma, Massa stelo mmstelo;
+{
+	l=ml;	
+	a=ma;
+	alfa=malfa;
+	
+	wa=mwa;
+	wb=mwb;
+
+	ps=mps;
+
+	gamma=mgamma;
+	mstelo=mmstelo;
+}
+
+double pistone::Forza()
+			// Restituisce il valore della forza che il pistone imprime
+{	
+	fp=(statopistone[2]*a) - (statopistone[3]*a*alfa) - (ps*a*(1-alfa));
+	
+	if(statopistone[1]<Dx1 && statopistone[1]>-Dx1)
+	{
+		if((fabs(fp)-fs)<0)
+		{
+			statopistone[1]=derivatastatopistone[0]=0;
+			return 0;
+		}
+	} 
+	//if(statopistone[1]<0) fd=-fd;
+	// ritorno il valore facendo il conto dul segno della forza dinamica 
+	return (fp - gamma*statopistone[1] - (statopistone[1]>0 ? fd :-fd )); 
+}
+
+void pistone::SetStatoPistone()
+			// Setta lo stato del sistema e si preoccupa dei vari controlli sulle variabili
+{
+	if(statopistone[0]>l)
+	{
+		statopistone[0]=l;
+		statopistone[1]=0;
+	}
+
+	if(statopistone[0]<0)
+	{
+		statopistone[0]=0;
+		statopistone[1]=0;
+	}
+	
+	ca->SetP(statopistone[2]);	
+	ca->SetG(ga);				// ATTENZIONE ga deve essere settata dalla valvola
+	ca->SetV(wa+statopistone[0]*a);
+	ca->SetV1(statopistone[1]*a);
+	
+	cb->SetP(statopistone[3]);	
+	cb->SetG(gb);				// ATTENZIONE gb deve essere settata dalla valvola
+	cb->SetV(wb+(l-statopistone[0])*a*alfa);
+	cb->SetV1(-statopistone[1]*a*alfa);
+}
+
+void pistone::SetDerivataStatoPistone()
+			// Setta lo stato derivato
+{
+	derivatastatopistone[0]=statopistone[1];
+	double ap;
+	ap=(Forza()-mstelo*0)/mstelo;		// + Contributo forza peso
+	
+	if(statopistone[0]>=l)
+	{
+		if(ap>=0) 
+		{
+			derivatastatopistone[1]=0;
+		}
+		else 
+		{
+			derivatastatopistone[1]=ap;
+		}
+	}
+	else if(statopistone[0]<=0)
+	{
+		if(ap>0) 
+		{
+			derivatastatopistone[1]=ap;
+		}
+		else 
+		{
+			derivatastatopistone[1]=0;
+		}
+	}
+	else if(statopistone[0]<l) 
+		derivatastatopistone[1]=ap;
+
+	derivatastatopistone[2]=PresA1();
+	derivatastatopistone[3]=PresB1();
+}
+
+
+void pistone::SetStatoDer(double *s, double *ds)
+			// Aggiorna la deriv. dello stato senza fare controlli, usando variabili d'appoggio
+{
+	SetStatoSist(s);
+	
+	*(ds)=*(s+1); //statopistone[1];
+	double ap;
+	ap=Forza()/mstelo;
+	*(ds+1)=ap;
+	*(ds+2)=PresA1();
+	*(ds+3)=PresB1();
+}
+
+void pistone::SetStatoSist(double *s)
+			// Aggiorna lo stato nelle variabili d'appoggio senza fare controlli 
+{
+	ca->SetP((*(s+2)));	
+	ca->SetG(ga);				// ATTENZIONE ga deve essere settata dalla valvola
+	ca->SetV(wa+(*(s))*a);
+	ca->SetV1((*(s+1))*a);
+	
+	cb->SetP((*(s+3)));	
+	cb->SetG(gb);				// ATTENZIONE gb deve essere settata dalla valvola
+	cb->SetV(wb+(l-(*(s)))*a*alfa);
+	cb->SetV1(-(*(s+1))*a*alfa);
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/pneumatica/pistone.h b/SRC/ChronoEngine/pneumatica/pistone.h
new file mode 100644
index 0000000..2759536
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/pistone.h
@@ -0,0 +1,123 @@
+#ifndef _PISTONE_H			//*****
+#define _PISTONE_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: pistone.h
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include "volume.h"
+#include <string.h>
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+/// This class implements the details of a pneumatic piston
+/// with given stroke, chambers,  etc. 
+
+class pistone {
+
+public:	
+	double l, a, alfa;
+			// l = corsa del pistone, a= sezione stantuffo, alfa=coeff.di riduzione area;
+	double wa, wb;
+			// wolumi morti delle due camere;
+	double ga, gb;
+			// ga = portata valvola A, gb = portata valvola B;
+	double  ps;
+			// ps = pressione di scarico;
+	double gamma, mstelo;
+			// coeff.di attrito viscoso, massa dello stelo;
+
+	double statopistone[4];
+			// [0]=spostamento; [1]=velocit�; [2]=pressione A; [3]=pressione B;
+	double derivatastatopistone[4];
+			// [0]=velocit�; [1]=accelerazione; [2]=derivata press A; [3]=derivata press B;
+	
+	double Dx1,fp,fs,fd;
+			// Dx1 =intervallo velocit�, fp = forza dovuta alle pressioni
+			// fs = forza d'attrito statico, fd = forza d'attrito dinamico;
+	
+	volume *ca, *cb;
+			// puntatori che permetteranno di creare la camera A e la B
+
+public:
+	pistone();
+	virtual ~pistone();
+
+	void SetL (double myl) { l = myl;};
+	double GetL () {return l;};
+	void SetA (double mya) { a = mya;};
+	double GetA () {return a;};
+	void SetAlfa (double myalfa) { alfa = myalfa;};
+	double GetAlfa () {return alfa;};
+
+	void SetWa (double mywa) { wa = mywa;};
+	double GetWa () {return wa;};
+	void SetWb (double mywb) { wb = mywb;};
+	double GetWb () {return wb;};
+
+	void SetGa (double myga) { ga = myga;};
+	double GetGa () {return ga;};
+	void SetGb (double mygb) { gb = mygb;};
+	double GetGb () {return gb;};
+	
+	void SetPs (double myps) { ps = myps;};
+	double GetPs () {return ps;};
+	
+	void SetGamma (double mygamma) { gamma = mygamma;};
+	double GetGamma () {return gamma;};
+	void SetMstelo (double mymstelo) { mstelo = mymstelo;};
+	double GetMstelo () {return mstelo;};
+	
+	volume *GetCa() {return ca;};
+	volume *GetCb() {return cb;};
+	
+	
+	virtual void SetupPistone(double mps, double ml, double mwa, double mwb, double ma, double malfa, double mgamma, double mmstelo);
+			// Metodo che inizializza il pistone
+	
+	virtual double *GetStatoPistone() {return statopistone;};
+			// Restituisce un puntatore a statopistone
+	virtual void SetStatoPistone();
+			// Aggiorna lo stato del sistema
+	virtual double *GetDerivataStatoPistone() {return derivatastatopistone;};
+			// Restituisce un puntatore a derivatastatopistone
+	virtual void SetDerivataStatoPistone();
+			// Riempie l'array derivatastatopistone con il nuovo derivatastatopistone
+			
+	virtual void SetStatoDer(double *s, double *ds);
+	virtual void SetStatoSist(double *s);
+			// Questi due metotodi settano lo stato e lo stato derivato senza controlli
+
+	double Forza();
+			// Restituisce la forza dello stantuffo
+	double PresA1() {return (ca -> Pressione1());};
+			// Restituisce la derivata della pressione nella camera a
+	double PresB1() {return (cb -> Pressione1());};
+			// Restituisce la derivata della pressione nella camera b
+	
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif						//*****
diff --git a/SRC/ChronoEngine/pneumatica/pistone_3_2.cpp b/SRC/ChronoEngine/pneumatica/pistone_3_2.cpp
new file mode 100644
index 0000000..c7077ba
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/pistone_3_2.cpp
@@ -0,0 +1,130 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: pistone_3_2.cpp
+//
+// Descrizione		: pistone comandato con 2 valvole 3-2 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "pistone_3_2.h"
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+pistone_3_2::pistone_3_2()
+			// Costruttore di pistone_3_2
+{
+	valva = valvb = NULL;
+	// Ricordarsi di chiamare il metodo SetupValvole() per creare i due oggetti
+}
+
+pistone_3_2::~pistone_3_2()
+			// Distruttore di pistone
+{
+	if(valva) delete valva;
+	valva = NULL;
+	if(valvb) delete valvb;
+	valvb = NULL;
+	
+}
+
+void pistone_3_2::SetupValvole()
+		// Decide a seconda della classe quale valvole usare
+{
+	valva = new valvola_3_2();
+	valva->SetupUgelli();
+	valvb = new valvola_3_2();
+	valvb->SetupUgelli();
+}
+
+
+void pistone_3_2::SetComando(double mycomandoA, double mycomandoB)
+			// scarico = -1, chiusa = 0, alimentazione = 1
+{
+	switch (int(mycomandoA)) {
+	case -1:
+		valva->SetStato(valvola_3_2::scarico);
+		break;
+	case 0:
+		valva->SetStato(valvola_3_2::chiusa);
+		break;
+	case 1:	
+		valva->SetStato(valvola_3_2::alimentazione);
+		break;
+	}
+	
+	switch (int(mycomandoB)) {
+	case -1:
+		valvb->SetStato(valvola_3_2::scarico);
+		break;
+	case 0:
+		valvb->SetStato(valvola_3_2::chiusa);
+		break;
+	case 1:	
+		valvb->SetStato(valvola_3_2::alimentazione);
+		break;
+	}
+}
+
+void pistone_3_2::SetStatoPistone()
+			// Setta lo stato del sistema e si preoccupa dei vari controlli sulle variabili
+{
+	if(statopistone[0]>l)
+	{
+		statopistone[0]=l;
+		statopistone[1]=0;
+	}
+
+	if(statopistone[0]<0)
+	{
+		statopistone[0]=0;
+		statopistone[1]=0;
+	}
+	
+	valva->SetPa(statopistone[2]);
+	valvb->SetPa(statopistone[3]);
+
+	ca->SetP(statopistone[2]);	
+	ca->SetG(valva->Portata());				
+	ca->SetV(wa+statopistone[0]*a);
+	ca->SetV1(statopistone[1]*a);
+	
+	cb->SetP(statopistone[3]);	
+	cb->SetG(valvb->Portata());				
+	cb->SetV(wb+(l-statopistone[0])*a*alfa);
+	cb->SetV1(-statopistone[1]*a*alfa);
+
+}
+
+
+void pistone_3_2::SetStatoSist(double *s)
+
+{
+	valva->SetPa((*(s+2)));
+	valvb->SetPa((*(s+3)));
+
+	ca->SetP((*(s+2)));	
+	ca->SetG(valva->Portata());				
+	ca->SetV(wa+(*(s))*a);
+	ca->SetV1((*(s+1))*a);
+	
+	cb->SetP((*(s+3)));	
+	cb->SetG(valvb->Portata());				
+	cb->SetV(wb+(l-(*(s)))*a*alfa);
+	cb->SetV1(-(*(s+1))*a*alfa);
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/pneumatica/pistone_3_2.h b/SRC/ChronoEngine/pneumatica/pistone_3_2.h
new file mode 100644
index 0000000..c75e69a
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/pistone_3_2.h
@@ -0,0 +1,66 @@
+#ifndef _PISTONE_3_2_H			//*****
+#define _PISTONE_3_2_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: pistone_3_2.h
+//
+// Descrizione		: pistone comandato con 2 valvole 3-2 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include "pistone.h"
+#include "valvola_3_2.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+/// A specialized pneumatic piston actuator, with two 3-2 valves
+
+class pistone_3_2 : public pistone {
+
+public:
+	valvola_3_2 *valva, *valvb;
+	
+
+public:
+	pistone_3_2();
+	virtual ~pistone_3_2();
+	
+	virtual void SetupValvole();
+
+	virtual valvola_3_2 *GetValvA() {return valva;};
+	virtual valvola_3_2 *GetValvB() {return valvb;};
+	
+	virtual void SetStatoPistone();
+	
+	virtual void SetComando(double mycomandoA, double mycomandoB);
+	
+	virtual void SetStatoSist(double *s);
+
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+
+#endif							//*****
+
diff --git a/SRC/ChronoEngine/pneumatica/pistone_3_2_prop.cpp b/SRC/ChronoEngine/pneumatica/pistone_3_2_prop.cpp
new file mode 100644
index 0000000..b38fd2d
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/pistone_3_2_prop.cpp
@@ -0,0 +1,109 @@
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: pistone_3_2_prop.cpp
+//
+// Descrizione		: pistone comandato con 2 valvole 3-2 proporzionali
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "pistone_3_2_prop.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+pistone_3_2_prop::pistone_3_2_prop()
+			// Costruttore di pistone_3_2_prop
+{
+	valva = valvb = NULL;
+	// Ricordarsi di chiamare il metodo SetupValvole() per creare i due oggetti
+}
+
+pistone_3_2_prop::~pistone_3_2_prop()
+			// Distruttore di pistone
+{
+	if(valva) delete valva;
+	valva = NULL;
+	if(valvb) delete valvb;
+	valvb = NULL;
+	
+}
+
+void pistone_3_2_prop::SetupValvole()
+		// Decide a seconda della classe quale valvole usare
+{
+	valva = new valvola_3_2_prop();
+	valva->SetupUgelli();
+	valvb = new valvola_3_2_prop();
+	valvb->SetupUgelli();
+}
+
+void pistone_3_2_prop::SetComando(double mycomandoA, double mycomandoB)
+			// Scrivo il comando nella variabile comando delle valvole, la funzione portata si occupa del resto
+{
+	valva->SetComando(mycomandoA);	// Scrive il comando nella variabile comando e basta
+	valvb->SetComando(mycomandoB);
+}
+
+void pistone_3_2_prop::SetStatoPistone()
+			// Setta lo stato del sistema e si preoccupa dei vari controlli sulle variabili
+{
+	if(statopistone[0]>l)
+	{
+		statopistone[0]=l;
+		statopistone[1]=0;
+	}
+
+	if(statopistone[0]<0)
+	{
+		statopistone[0]=0;
+		statopistone[1]=0;
+	}
+	
+	valva->SetPa(statopistone[2]);
+	valvb->SetPa(statopistone[3]);
+
+	ca->SetP(statopistone[2]);	
+	ca->SetG(valva->Portata());				
+	ca->SetV(wa+statopistone[0]*a);
+	ca->SetV1(statopistone[1]*a);
+	
+	cb->SetP(statopistone[3]);	
+	cb->SetG(valvb->Portata());				
+	cb->SetV(wb+(l-statopistone[0])*a*alfa);
+	cb->SetV1(-statopistone[1]*a*alfa);
+
+}
+
+
+void pistone_3_2_prop::SetStatoSist(double *s)
+
+{
+	valva->SetPa((*(s+2)));
+	valvb->SetPa((*(s+3)));
+
+	ca->SetP((*(s+2)));	
+	ca->SetG(valva->Portata());				
+	ca->SetV(wa+(*(s))*a);
+	ca->SetV1((*(s+1))*a);
+	
+	cb->SetP((*(s+3)));	
+	cb->SetG(valvb->Portata());				
+	cb->SetV(wb+(l-(*(s)))*a*alfa);
+	cb->SetV1(-(*(s+1))*a*alfa);
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/pneumatica/pistone_3_2_prop.h b/SRC/ChronoEngine/pneumatica/pistone_3_2_prop.h
new file mode 100644
index 0000000..b72d6bf
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/pistone_3_2_prop.h
@@ -0,0 +1,61 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: pistone_3_2_prop.h
+//
+// Descrizione		: pistone comandato con 2 valvole 3-2 proporzionali
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _PISTONE_3_2_PROP_H			//*****
+#define _PISTONE_3_2_PROP_H			//*****
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include "pistone.h"
+#include "valvola_3_2_prop.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+/// Specialized pneumatic piston, exploiting two 3-2 proportional
+/// valves.
+
+
+class pistone_3_2_prop : public pistone {
+
+private:
+	valvola_3_2_prop *valva, *valvb;
+	
+
+public:
+	pistone_3_2_prop();
+	virtual ~pistone_3_2_prop();
+	
+	virtual void SetupValvole();
+
+	virtual valvola_3_2_prop *GetValvA() {return valva;};
+	virtual valvola_3_2_prop *GetValvB() {return valvb;};
+	
+	virtual void SetComando(double mycomandoA, double mycomandoB);
+	
+	virtual void SetStatoPistone();
+	
+	virtual void SetStatoSist(double *s);
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif							//*****
+
diff --git a/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.cpp b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.cpp
new file mode 100644
index 0000000..18bf348
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.cpp
@@ -0,0 +1,104 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: sis_attuatore_3_2.cpp
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "sis_attuatore_3_2.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+sis_attuatore_3_2::sis_attuatore_3_2()
+			// Costruttore
+{
+	mypistone = NULL;
+	mypistone = new pistone_3_2();
+
+	//mycontrollore = NULL;
+	//mycontrollore = new controllore();
+}
+
+sis_attuatore_3_2::~sis_attuatore_3_2()
+			// Distruttore
+{
+	if(mypistone) delete mypistone;
+	mypistone = NULL;
+
+	//if(mycontrollore) delete mycontrollore;
+	//mycontrollore = NULL;
+}
+
+
+
+void sis_attuatore_3_2::InizializzaSistema()
+			// Metodi che inizializza il sistema(condizioni iniziali nel sistema)
+{
+	
+	memcpy(stato,mypistone->statopistone,(n*sizeof(double)));
+	memcpy(derivatastato,mypistone->derivatastatopistone,(n*sizeof(double)));
+
+}
+
+
+void sis_attuatore_3_2::SetStato()
+			
+{
+	// scarico = -1, chiusa = 0, alimentazione = 1
+	//SetComando(1,-1);
+//double com;
+//com = mycontrollore->proporzionale(1.4, *(stato+1));
+//mypistone->SetComando(com,-com);
+
+	//memcpy(stato[0],mysistema->GetStato(),(n*sizeof(double)));
+
+	memcpy(mypistone->statopistone,stato,(n*sizeof(double)));
+	//Copio da stato del sistema a stato del pistone (statopistone)
+	/*mypistone->statopistone[0] = *(stato);
+	mypistone->statopistone[1] = *(stato+1);
+	mypistone->statopistone[2] = *(stato+2);
+	mypistone->statopistone[3] = *(stato+3);*/
+	
+	
+	mypistone->SetStatoPistone(); // Qui faccio i controlli funzionali e il controllore?????
+
+}
+
+
+void sis_attuatore_3_2::SetDerivataStato()
+			//
+{
+	mypistone->SetDerivataStatoPistone();
+	memcpy(derivatastato,mypistone->derivatastatopistone,(n*sizeof(double)));
+	
+	//*(derivatastato)=mypistone->derivatastatopistone[0];
+	//*(derivatastato+1)=mypistone->derivatastatopistone[1];
+	//*(derivatastato+2)=mypistone->derivatastatopistone[2];
+	//*(derivatastato+3)=mypistone->derivatastatopistone[3];
+}
+
+
+void sis_attuatore_3_2::derivate(double *s, double *ds)
+
+{
+	mypistone->SetStatoDer(s,ds);
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
diff --git a/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.h b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.h
new file mode 100644
index 0000000..07713a4
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2.h
@@ -0,0 +1,60 @@
+#ifndef _SIS_ATTUATORE_3_2_H			//*****
+#define _SIS_ATTUATORE_3_2_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: sis_attuatore_3_2.h
+//
+// Descrizione		:
+//
+//
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include "pistone_3_2.h"
+#include "sistema.h"
+
+
+namespace chrono
+{
+namespace pneumatics
+{
+
+/// Pneumatic actuator system, with two 3-2 valves.
+
+class sis_attuatore_3_2 : public sistema {
+
+public:
+	pistone_3_2 *mypistone;
+
+public:
+	sis_attuatore_3_2();	//{mypistone = NULL; mypistone = new pistone_3_2();};
+	virtual ~sis_attuatore_3_2();	// {if(mypistone) delete mypistone; mypistone = NULL;};
+
+	virtual void InizializzaSistema();
+
+	virtual void SetStato();	// Qui agir� il controllore?????
+
+	virtual void SetDerivataStato();
+
+	virtual void derivate(double *s, double *ds); // metodo che serve a RK4
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif									//*****
+
diff --git a/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2_prop.cpp b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2_prop.cpp
new file mode 100644
index 0000000..c18ea08
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2_prop.cpp
@@ -0,0 +1,253 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: sis_attuatore_3_2_prop.cpp
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "sis_attuatore_3_2_prop.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+sis_attuatore_3_2_prop::sis_attuatore_3_2_prop()
+			// Costruttore
+{
+	mypistone = NULL;
+	mypistone = new pistone_3_2_prop();
+
+	
+	//mycontrollore = NULL;
+	//mycontrollore = new controllore();
+
+	//myfunzione = NULL;
+	//myfunzione = new gen_funzioni();
+
+
+}
+
+
+sis_attuatore_3_2_prop::~sis_attuatore_3_2_prop()
+			// Distruttore
+{
+	if(mypistone) delete mypistone;
+	mypistone = NULL;
+
+	//if(mycontrollore) delete mycontrollore;
+	//mycontrollore = NULL;
+
+	//if(myfunzione) delete myfunzione;
+	//myfunzione = NULL;
+}
+
+
+void sis_attuatore_3_2_prop::InizializzaSistema()
+			// Metodi che inizializza il sistema(condizioni iniziali nel sistema)
+{	
+	memcpy(stato,mypistone->statopistone,(n*sizeof(double)));
+	memcpy(derivatastato,mypistone->derivatastatopistone,(n*sizeof(double)));
+}
+
+void sis_attuatore_3_2_prop::SetStato()
+			// Seta lo stato tenendo conto dell'effetto del controllore			
+{
+	// Scarico da 0 a 1000, Chiusa = 0, Alimentazione da -1000 a 0
+	// SetComando(valvola A,valvola B);
+	
+	//double setA,coA;
+	//setA=coA=0;
+	//setA = (myfunzione->Rampa((GetT())));
+	//coA = (mycontrollore->proporzionale(setA, *(stato+1)));
+	
+	//mypistone->SetComando(coA,-500);
+
+	memcpy(mypistone->statopistone,stato,(n*sizeof(double)));
+	//Copio da stato del sistema a stato del pistone (statopistone)
+	
+	mypistone->SetStatoPistone(); // Qui faccio i controlli funzionali e il controllore?????
+	
+}
+
+
+void sis_attuatore_3_2_prop::SetDerivataStato()
+			//
+{
+	mypistone->SetDerivataStatoPistone();
+	memcpy(derivatastato,mypistone->derivatastatopistone,(n*sizeof(double)));
+}
+
+
+void sis_attuatore_3_2_prop::derivate(double *s, double *ds)
+
+{
+	mypistone->SetStatoDer(s,ds);
+}
+
+
+void sis_attuatore_3_2_prop::Comanda(double *com)
+
+{
+	mypistone->SetComando(*(com),*(com+1));
+}
+
+
+void sis_attuatore_3_2_prop::Salva(int myi)
+			// Metodo che salva i dati sul disco
+{
+	/*k=0;
+	file<<t<<" ";
+	while (k<n) {file<<*(stato+k) <<" "; k++;}
+	file<<"\n";
+	// Scrivendo come sopra scrivo tutto lo stato qualsiasi sia la sua lunghezza
+
+	dataout
+		<<t<<" "<<setpoint
+		<<" "<<*(stato)<<" "<<*(stato+1)<<" "<<*(derivatastato+1)
+		<<" "<<*(stato+2)<<" "<<*(stato+3)<<" "<<*(derivatastato+2)<<" "<<*(derivatastato+3)
+		
+		<<" "<<mypistone->GetValvA()->GetPortata()<<" "<<mypistone->GetValvB()->GetPortata()
+		
+		<<" "<<mypistone->GetValvA()->b<<" "<<mypistone->GetValvA()->beta
+		<<" "<<mypistone->GetValvB()->b<<" "<<mypistone->GetValvB()->beta
+		
+		<<" "<<*(comandi)<<" "<<*(comandi+1)<<"\n";
+	*/
+	
+	if (myi < num) {
+
+	datisalv.tempo[myi] =t;
+	datisalv.setpoint[myi] =setpoint;
+	datisalv.posizione[myi] = *(stato);
+	datisalv.setpointvel[myi] =setpointvel;
+	datisalv.velocita[myi] = *(stato+1);
+	datisalv.setpointacc[myi] =setpointacc;
+	datisalv.accelerazione[myi] = *(derivatastato+1);
+	
+	datisalv.pres_a[myi] = *(stato+2);
+	datisalv.pres_b[myi] = *(stato+3);
+	datisalv.der_pres_a[myi] = *(derivatastato+2);
+	datisalv.der_pres_b[myi] = *(derivatastato+3);
+	
+	datisalv.portata_a[myi]= mypistone->GetValvA()->GetPortata();
+	datisalv.portata_b[myi] = mypistone->GetValvB()->GetPortata();
+	datisalv.b_a[myi] = mypistone->GetValvA()->b;
+	datisalv.beta_a[myi] = mypistone->GetValvA()->beta;
+	datisalv.b_b[myi] = mypistone->GetValvB()->b;
+	datisalv.beta_b[myi] = mypistone->GetValvB()->beta;
+/*	
+	// Anello di posizione
+	datisalv.pidvel_p[myi] =*(comandi+5);
+			//datisalv.pidvel_i[myi] =*(comandi+6);  OCIO manca dato nella struttura dati
+	datisalv.pidvel_d[myi] =*(comandi+7);
+	// Anello di velocit�
+	datisalv.pidpos_p[myi] =*(comandi+2);
+			//datisalv.pidpos_i[myi] =*(comandi+3);  OCIO manca dato nella struttura dati
+	datisalv.pidpos_d[myi] =*(comandi+4);
+	
+*/
+	datisalv.supsliding[myi] =*(comandi + 2);
+	datisalv.m1_e[myi] =*(comandi + 3);
+	datisalv.m2_e1[myi] =*(comandi + 4);
+	datisalv.e2[myi] =*(comandi + 5);
+
+	datisalv.e[myi] =*(comandi + 6);
+	datisalv.e1[myi] =*(comandi + 7);
+
+	datisalv.segno_s[myi] =*(comandi + 8);
+	datisalv.segno_se[myi] =*(comandi + 9);
+	datisalv.segno_se1[myi] =*(comandi + 10);
+	datisalv.segno_se2[myi] =*(comandi + 11);
+
+	datisalv.u_k1[myi] =*(comandi + 12);
+	datisalv.u_k2[myi] =*(comandi + 13);
+	datisalv.u_eta[myi] =*(comandi + 14);
+
+	datisalv.u_n[myi] =*(comandi + 15);
+	datisalv.u_l[myi] =*(comandi + 16);
+	datisalv.u_2[myi] =*(comandi + 17);
+
+	datisalv.comando_a[myi] =(mypistone->GetValvA())->GetComando();  //*(comandi);
+	datisalv.comando_b[myi] =(mypistone->GetValvB())->GetComando();  //*(comandi+1);
+	}
+
+}
+
+void sis_attuatore_3_2_prop::ScriviFile()
+			// Metodo che scrive i dati su disco
+{
+	// Tolgo il primo punto perch� ho setpvel e setpacc che fanno casino!!
+	/*
+	for (j=1;j<num;j++) 
+	{
+		dataout
+			<<datisalv.tempo[j]<<" \t"				//1
+			<<datisalv.setpoint[j]<<" \t"			//2
+			<<datisalv.posizione[j]<<" \t"			//3
+			<<datisalv.setpointvel[j]<<" \t"		//4
+			<<datisalv.velocita[j]<<" \t"			//5
+			<<datisalv.setpointacc[j]<<" \t"		//6
+			<<datisalv.accelerazione[j]<<" \t"		//7
+			
+			<<datisalv.pres_a[j]<<" \t"				//8
+			<<datisalv.pres_b[j]<<" \t"				//9
+			<<(datisalv.pres_a[j]-datisalv.pres_b[j])<<" \t"			//10 //<<datisalv.der_pres_a[j]<<" \t"			//10
+			<<datisalv.der_pres_b[j]<<" \t"			//11
+			
+			<<datisalv.portata_a[j]<<" \t"			//12
+			<<datisalv.portata_b[j]<<" \t"			//13
+			<<datisalv.b_a[j]<<" \t"				//14
+			<<datisalv.beta_a[j]<<" \t"				//15
+			<<datisalv.b_b[j]<<" \t"				//16
+			<<datisalv.beta_b[j]<<" \t"				//17
+			
+			//<<datisalv.pidvel_p[j]<<" \t"			//1
+			//<<datisalv.pidvel_d[j]<<" \t"			//1
+			//<<datisalv.pidpos_p[j]<<" \t"			//1
+			//<<datisalv.pidpos_d[j]<<" \t"			//1
+
+			<<datisalv.supsliding[j]<<" \t"			//18
+			<<datisalv.m1_e[j]<<" \t"				//19
+			<<datisalv.m2_e1[j]<<" \t"				//20
+			<<datisalv.e2[j]<<" \t"					//21
+
+			<<datisalv.e[j]<<" \t"					//22
+			<<datisalv.e1[j]<<" \t"					//23
+
+			<<datisalv.segno_s[j]<<" \t"			//24
+			<<datisalv.segno_se[j]<<" \t"			//25
+			<<datisalv.segno_se1[j]<<" \t"			//26
+			<<datisalv.segno_se2[j]<<" \t"			//27
+
+			<<datisalv.u_k1[j]<<" \t"				//28
+			<<datisalv.u_k2[j]<<" \t"				//29
+			<<datisalv.u_eta[j]<<" \t"				//30
+
+			<<datisalv.u_n[j]<<" \t"				//31
+			<<datisalv.u_l[j]<<" \t"				//32
+			<<datisalv.u_2[j]<<" \t"				//33
+			
+			<<datisalv.comando_a[j]<<" \t"			//34
+			<<datisalv.comando_b[j]<<"\n";			//35
+		
+		// Escludo in questo modo la parte finale della simulazione se ha valori senza senso
+		// ... credo...
+		if (datisalv.tempo[j+1]==0 || datisalv.setpoint[j+1]< 0) j=num;
+	}
+	*/
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2_prop.h b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2_prop.h
new file mode 100644
index 0000000..75cd3cc
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/sis_attuatore_3_2_prop.h
@@ -0,0 +1,71 @@
+#ifndef _SIS_ATTUATORE_3_2_PROP_H			//*****
+#define _SIS_ATTUATORE_3_2_PROP_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: sis_attuatore_3_2_prop.h
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include "pistone_3_2_prop.h"
+#include "sistema.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+/// Pneumatic actuator system, with two 3-2 proportional valves.
+
+class sis_attuatore_3_2_prop : public sistema {
+
+public:
+	pistone_3_2_prop *mypistone;
+	
+	
+	//controllore *mycontrollore;
+	//gen_funzioni *myfunzione;
+
+public:
+	sis_attuatore_3_2_prop();	//{mypistone = NULL; mypistone = new pistone_3_2();};
+	virtual ~sis_attuatore_3_2_prop();	// {if(mypistone) delete mypistone; mypistone = NULL;};
+
+	virtual void InizializzaSistema();
+	
+	virtual void Salva(int myi);
+	
+	virtual void ScriviFile();
+
+	virtual void SetStato();	// Qui agir� il controllore?????
+
+	virtual void SetDerivataStato();
+
+	virtual void Comanda(double *com);
+
+	virtual void derivate(double *s, double *ds); // metodo che serve a RK4
+
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif									//*****
+
diff --git a/SRC/ChronoEngine/pneumatica/sistema.cpp b/SRC/ChronoEngine/pneumatica/sistema.cpp
new file mode 100644
index 0000000..83aeca5
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/sistema.cpp
@@ -0,0 +1,216 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: sistema.cpp
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "sistema.h"
+#include "math.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+sistema::sistema()
+			// Costruttore di sistema
+{
+	n=nc=k=0;
+	t=setpoint=0;
+	stato=derivatastato=NULL; 
+
+	
+}
+
+sistema::~sistema()
+			// Distruttore di sistema
+{
+
+/*
+	delete [] datisalv.tempo;
+	delete [] datisalv.setpoint;
+	delete [] datisalv.posizione;
+	delete [] datisalv.setpointvel;
+	delete [] datisalv.velocita;
+	delete [] datisalv.setpointacc;
+	delete [] datisalv.accelerazione;
+
+	delete [] datisalv.pres_a;
+	delete [] datisalv.pres_b;
+	delete [] datisalv.der_pres_a;
+	delete [] datisalv.der_pres_b;
+
+	//delete [] datisalv.portata_a;
+	//delete [] datisalv.portata_b;
+	//delete [] datisalv.b_a;
+	//delete [] datisalv.beta_a;
+	//delete [] datisalv.b_b;
+	//delete [] datisalv.beta_b;
+
+	//delete [] datisalv.pidvel_p;
+	//delete [] datisalv.pidvel_d;
+	//delete [] datisalv.pidpos_p;
+	//delete [] datisalv.pidpos_d;
+
+	delete [] datisalv.supsliding;
+	delete [] datisalv.m1_e;
+	delete [] datisalv.m2_e1;
+	delete [] datisalv.e2;
+	
+	delete [] datisalv.e;
+	delete [] datisalv.e1;
+
+	delete [] datisalv.segno_s;
+	delete [] datisalv.segno_se;
+	delete [] datisalv.segno_se1;
+	delete [] datisalv.segno_se2;
+
+	delete [] datisalv.u_k1;
+	delete [] datisalv.u_k2;
+	delete [] datisalv.u_eta;
+
+	delete [] datisalv.u_n;
+	delete [] datisalv.u_l;
+	delete [] datisalv.u_2;
+
+	delete [] datisalv.comando_a;
+	delete [] datisalv.comando_b;
+*/
+}
+
+int sistema::NSistema()
+			// Metodo che restituisce il numero di variabili da integrare.
+{
+	n=4;
+	return n;
+}
+
+int sistema::NcSistema()
+			// Metodo che restitusce il numero di comandi;
+{
+	nc=2;
+	return nc;
+}
+
+void sistema::SetSistema()
+			// Metodo che alloca memoria per stato e derivatastato
+{
+	NSistema();	// Chiamo questo metodo che scrive in n un numero e poi uso n
+	NcSistema(); // Scrive in nc il numero dei comandi utilizzati da sistema 
+	
+	stato = new double[n];				memset(stato,0x0,sizeof(double)*n);
+	derivatastato = new double[n];		memset(derivatastato,0x0,sizeof(double)*n);
+	// Aggiungo a nc 6 per poter contenere i contributi del PID cfr->controllore.cpp
+	comandi = new double[nc+20];			memset(comandi,0x0,sizeof(double)*(nc+20));
+	
+//OCIO //Per salvare i dati bisogna inizializzare num
+	// Alloco memoria per salvare i dati della simulazione -> num � la dimensione 
+/*	
+	datisalv.tempo = new double[num];				memset(datisalv.tempo,0x0,sizeof(double)*(num));
+	datisalv.setpoint = new double[num];			memset(datisalv.setpoint,0x0,sizeof(double)*(num));
+	datisalv.posizione = new double[num];			memset(datisalv.posizione,0x0,sizeof(double)*(num));
+	datisalv.setpointvel = new double[num];			memset(datisalv.setpointvel,0x0,sizeof(double)*(num));
+	datisalv.velocita = new double[num];			memset(datisalv.velocita,0x0,sizeof(double)*(num));
+	datisalv.setpointacc = new double[num];			memset(datisalv.setpointacc,0x0,sizeof(double)*(num));
+	datisalv.accelerazione = new double[num];		memset(datisalv.accelerazione,0x0,sizeof(double)*(num));
+	
+	datisalv.pres_a = new double[num];				memset(datisalv.pres_a,0x0,sizeof(double)*(num));
+	datisalv.pres_b = new double[num];				memset(datisalv.pres_b,0x0,sizeof(double)*(num));
+	datisalv.der_pres_a = new double[num];			memset(datisalv.der_pres_a,0x0,sizeof(double)*(num));
+	datisalv.der_pres_b = new double[num];			memset(datisalv.der_pres_b,0x0,sizeof(double)*(num));
+	
+	datisalv.portata_a = new double[num];			memset(datisalv.portata_a,0x0,sizeof(double)*(num));
+	datisalv.portata_b = new double[num];			memset(datisalv.portata_b,0x0,sizeof(double)*(num));
+	datisalv.b_a = new double[num];				memset(datisalv.b_a,0x0,sizeof(double)*(num));
+	datisalv.beta_a = new double[num];			memset(datisalv.beta_a,0x0,sizeof(double)*(num));
+	datisalv.b_b = new double[num];				memset(datisalv.b_b,0x0,sizeof(double)*(num));
+	datisalv.beta_b = new double[num];			memset(datisalv.beta_b,0x0,sizeof(double)*(num));
+
+	//datisalv.pidvel_p = new double[num];			memset(datisalv.pidvel_p,0x0,sizeof(double)*(num));
+	//datisalv.pidvel_d = new double[num];			memset(datisalv.pidvel_d,0x0,sizeof(double)*(num));
+	//datisalv.pidpos_p = new double[num];			memset(datisalv.pidpos_p,0x0,sizeof(double)*(num));
+	//datisalv.pidpos_d = new double[num];			memset(datisalv.pidpos_d,0x0,sizeof(double)*(num));
+	
+	
+	datisalv.supsliding = new double[num];			memset(datisalv.supsliding,0x0,sizeof(double)*(num));
+	datisalv.m1_e = new double[num];				memset(datisalv.m1_e,0x0,sizeof(double)*(num));
+	datisalv.m2_e1 = new double[num];				memset(datisalv.m2_e1,0x0,sizeof(double)*(num));
+	datisalv.e2 = new double[num];					memset(datisalv.e2,0x0,sizeof(double)*(num));
+
+	datisalv.e = new double[num];					memset(datisalv.e,0x0,sizeof(double)*(num));
+	datisalv.e1 = new double[num];					memset(datisalv.e1,0x0,sizeof(double)*(num));
+
+	datisalv.segno_s = new double[num];				memset(datisalv.segno_s,0x0,sizeof(double)*(num));
+	datisalv.segno_se = new double[num];			memset(datisalv.segno_se,0x0,sizeof(double)*(num));
+	datisalv.segno_se1 = new double[num];			memset(datisalv.segno_se1,0x0,sizeof(double)*(num));
+	datisalv.segno_se2 = new double[num];			memset(datisalv.segno_se2,0x0,sizeof(double)*(num));
+
+	datisalv.u_k1 = new double[num];				memset(datisalv.u_k1,0x0,sizeof(double)*(num));
+	datisalv.u_k2 = new double[num];				memset(datisalv.u_k2,0x0,sizeof(double)*(num));
+	datisalv.u_eta = new double[num];				memset(datisalv.u_eta,0x0,sizeof(double)*(num));
+
+	datisalv.u_n = new double[num];					memset(datisalv.u_n,0x0,sizeof(double)*(num));
+	datisalv.u_l = new double[num];					memset(datisalv.u_l,0x0,sizeof(double)*(num));
+	datisalv.u_2 = new double[num];					memset(datisalv.u_2,0x0,sizeof(double)*(num));
+	
+	
+	datisalv.comando_a = new double[num];			memset(datisalv.comando_a,0x0,sizeof(double)*(num));
+	datisalv.comando_b = new double[num];			memset(datisalv.comando_b,0x0,sizeof(double)*(num));
+*/
+}
+
+
+
+void sistema::Salva(int myi)
+			// Metodo che salva i dati sul disco
+{
+	/*k=0;
+	file<<t<<" ";
+	while (k<n) {file<<*(stato+k) <<" "; k++;}
+	file<<"\n";*/
+	// Scrivendo come sopra scrivo tutto lo stato qualsiasi sia la sua lunghezza
+/*
+	dataout<<t<<" "<<*(stato)<<" "<<*(stato+1)<<" "<<*(derivatastato+1)<<" "<<*(stato+2)<<" "<<*(stato+3)<<" "<<*(comandi)<<" "<<*(comandi+1)<<"\n";
+*/
+}
+ 
+void sistema::ScriviFile()
+			// Metodo che scrive su file i dati salvati
+{
+
+}
+
+void sistema::SetStato()
+			//metodo che setta lo stato
+{
+
+}
+
+
+void sistema::SetDerivataStato()
+			//metodo che setta lo stato derivato
+{
+
+}
+
+void sistema::derivate(double *s, double *ds)
+
+{
+
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/pneumatica/sistema.h b/SRC/ChronoEngine/pneumatica/sistema.h
new file mode 100644
index 0000000..e1089e0
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/sistema.h
@@ -0,0 +1,163 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: sistema.h
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef _SISTEMA_H			//*****
+#define _SISTEMA_H			//*****
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include <stdlib.h>
+#include <fstream>
+#include <string.h>
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+/// A pneumatic system. This class can be specialized for 
+/// representing more specific systems (for example a piston
+/// with valves, etc.).
+
+class sistema {
+
+public:
+	int n,nc,k;		// n = numero di elementi di stato, nc = num di comandi,k = contatore in salva
+	int num;		// num = numero di punti da salvare
+	double t;		// t = tempo (nell'integratore non � definito)
+	double dt;
+	double *stato, *derivatastato;
+	double *comandi;
+	double setpoint;
+	double setpointvel;
+	double setpointacc;
+	
+	struct save {
+		double *tempo;
+		double *setpoint;
+		double *posizione;
+		double *setpointvel;
+		double *velocita;
+		double *setpointacc;
+		double *accelerazione;
+		
+		double *pres_a;
+		double *pres_b;
+		double *der_pres_a;
+		double *der_pres_b;
+		
+		double *portata_a;
+		double *portata_b;
+		double *b_a;
+		double *beta_a;
+		double *b_b;
+		double *beta_b;
+	
+		//double *pidvel_p;
+		//double *pidvel_d;
+		//double *pidpos_p;
+		//double *pidpos_d;
+
+		double *supsliding;
+		double *m1_e;
+		double *m2_e1;
+		double *e2;
+
+		double *e;
+		double *e1;
+
+		double *segno_s;
+		double *segno_se;
+		double *segno_se1;
+		double *segno_se2;
+
+		double *u_k1;
+		double *u_k2;
+		double *u_eta;
+
+		double *u_n;
+		double *u_l;
+		double *u_2;
+		
+		double *comando_a;
+		double *comando_b;
+	} datisalv;		// Struttura che contiene di dati da salvare in memoria
+
+public:
+	//ofstream dataout;		//crea un stream di output
+
+public:
+	sistema();
+	virtual ~sistema();
+	
+	void SetNum (int mynum) { num= mynum;};
+	int GetNum () {return num;};
+
+	void SetSetpoint (double mysetpoint) { setpoint= mysetpoint;};
+	double GetSetpoint () {return setpoint;};
+
+	void SetSetpointVel (double mysetpointvel) { setpointvel= mysetpointvel;};
+	double GetSetpointVel () {return setpointvel;};
+
+	void SetSetpointAcc (double mysetpointacc) { setpointacc= mysetpointacc;};
+	double GetSetpointAcc () {return setpointacc;};
+	
+	void SetT (double myt) { t= myt;};
+	double GetT () {return t;};
+	
+	void SetDt (double mydt) { dt= mydt;};
+	double GetDt () {return dt;};
+
+	virtual int NSistema();
+			// Metodo che restitusce il numero di variabili da integrare (dimensione dello stato);
+	virtual int NcSistema();
+			// Metodo che restitusce il numero di comandi;
+	
+	virtual void SetSistema();
+			// Metodo che alloca memoria per stato e derivatastato
+	virtual void InizializzaSistema() {};
+	
+	virtual void Salva(int myi);
+			// Metodo che salva i dati i memoria
+	virtual void ScriviFile();
+			// Metodi che scrive su file i dati salvati
+	
+	virtual void Comanda(double *) {};
+			// Metodo che distribusce i comandi su i vari oggetti di sistema
+	
+	virtual double *GetStato() {return stato;};				//metodo che restituisce un puntare a stato;
+	virtual void SetStato();	// Qui faccio i controlli funzionali e il controllore?????
+
+	virtual double *GetDerivataStato() {return derivatastato;};		//metodo che restituisce un puntare a derivatastato;
+	virtual void SetDerivataStato();
+
+	virtual double *GetComandi() {return comandi;};		//metodo che restituisce un puntare a comandi;
+	virtual void SetComandi(){};
+
+	
+	virtual void derivate(double *s, double *ds);
+
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif						//*****
diff --git a/SRC/ChronoEngine/pneumatica/ugello.cpp b/SRC/ChronoEngine/pneumatica/ugello.cpp
new file mode 100644
index 0000000..7208cff
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello.cpp
@@ -0,0 +1,91 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello.cpp
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "ugello.h"
+#include <math.h>
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+double ugello::Portata()
+			//Restituisce il valore della portata assegnate le pressioni a cavallo dell'ugello
+{
+	
+	/*double Q, pres;			
+			// Portata massica [kg/s]
+	double fi;
+			// Funzione che discrimina fra flusso sonico e subsonico (fattore sonico)
+	double rho;
+			// Densit� normale dell'aria [kg/m^3]
+	double t0;
+			// Temperatura in condizioni normali [K]
+	double tambiente;
+			// Temperatura ambiente [K], (25�C)
+	rho=1.225;
+	t0=293.15;
+	tambiente=298;*/
+	
+
+	if (!isopen) { return 0;};
+			// Verifica se la valvola � aperta o no
+	
+	b=SetDirezione();	// Beta temporaneo
+	beta = GetBeta();	// Beta del ugello per quel comando
+
+	if (beta < b)
+		{ fi=sqrt(1.0-( pow((b-beta) / (1.0-beta) , 2.0)  ) );}
+			// condizioni subsoniche
+	else
+		{fi=1;}
+			// condizioni soniche
+	
+	(verso==flusso_in) ? (pres=pmonte) : (pres=-pvalle);
+
+	Q= GetConduttanza()*pres*fi*rho*sqrt(t0/tambiente);
+				// Calcola la portata attribuebdo a pres il segno e il valore corretto
+	return Q;
+		
+}
+
+
+double ugello::SetDirezione()
+			// Impone una direzione al flusso a seconda delle pressioni a cavallo della valvola
+{
+	double btemp;
+			// pM = pressione maggiore, pm = pressione minore, btemp = beta del momento
+
+	if((pmonte/pvalle)>1)
+		{
+		btemp = pvalle/pmonte;
+		verso = flusso_in;
+		}
+	else
+		{
+		btemp = pmonte/pvalle;
+		verso = flusso_out;
+		}
+	
+    return btemp;
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
diff --git a/SRC/ChronoEngine/pneumatica/ugello.h b/SRC/ChronoEngine/pneumatica/ugello.h
new file mode 100644
index 0000000..394a6df
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello.h
@@ -0,0 +1,103 @@
+#ifndef _UGELLO_H			//*****
+#define _UGELLO_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello.h
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include <string.h>
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+/// Class defining pneumatic nozzles.
+
+class ugello {
+
+protected:
+	double ci, co, bi, bo;	
+			// ci=Conduttanzain ingresso; co=Conduttanza in uscita [m^3/(s*Pa)]
+			// bi=beta in ingresso; bo=beta in uscita
+	double pvalle, pmonte;
+			// Pvalle=Pressione a valle dell'ugello; Pmonte=pressione a monte
+	bool isopen;
+			// Variabile che definisce se la valvola � aperta o chiusa
+
+	double Q, pres;			
+			// Portata massica [kg/s]
+	double fi;
+			// Funzione che discrimina fra flusso sonico e subsonico (fattore sonico)
+	double rho;
+			// Densit� normale dell'aria [kg/m^3]
+	double t0;
+			// Temperatura in condizioni normali [K]
+	double tambiente;
+			// Temperatura ambiente [K], (25�C)
+
+
+	double b;			//beta istantaneo 
+	double beta;		//beta della valvola
+
+
+public:
+	enum TipoFlusso {flusso_out = 0, flusso_in = 1} verso;
+			// verso definisce la direzione del flusso flusso_out = 0, flusso_in =1
+
+public:
+	ugello()  {isopen = true;verso = flusso_in; ci=co=bi=bo=pvalle=pmonte=.0;
+				rho=1.225;t0=293.15;tambiente=298; b=beta=0;};
+	virtual ~ugello() {};
+
+	void SetCi(double myci) {ci = myci;};
+	double GetCi() {return ci;};
+	void SetCo(double myco) {co = myco;};
+	double GetCo() {return co;};
+	void SetBi(double mybi) {bi = mybi;};
+	double GetBi() {return bi;};
+	void SetBo(double mybo) {bo = mybo;};
+	double GetBo() {return bo;};
+	
+	double GetB() {return b;};
+	double GetBe() {return beta;};
+	
+	void SetPvalle(double mypvalle) { pvalle= mypvalle;};
+	double GetPvalle() {return pvalle;};
+	void SetPmonte(double mypmonte) { pmonte= mypmonte;};
+	double GetPmonte() {return pmonte;};
+	
+	void SetIsopen(bool myisopen) {isopen = myisopen;};
+	bool GetIsopen() {return isopen;};
+	
+	virtual double GetConduttanza() { if (verso == flusso_in) {return ci;}; return co;};				
+			// Decide in funzione del verso quale C usare
+	virtual double GetBeta() { if (verso == flusso_in) {return bi;}; return bo;};						
+			// Decide in funzione del verso quale b usare
+	double Portata();	
+			// Restituisce il valore della portata
+	double SetDirezione();
+			// Impone la diresione del flusso a seconda delle pressioni a cavallo della valvola
+
+	
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif						//*****
diff --git a/SRC/ChronoEngine/pneumatica/ugello_controllato.cpp b/SRC/ChronoEngine/pneumatica/ugello_controllato.cpp
new file mode 100644
index 0000000..d01b68e
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello_controllato.cpp
@@ -0,0 +1,66 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello_controllato.cpp
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "ugello_controllato.h"
+#include <math.h>
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+double ugello_controllato::GetConduttanza()
+			// Sceglie in funzione del verso il valore della conduttanza
+{	
+	if (verso == flusso_in) {return ConduttanzaIn();}; return ConduttanzaOut();
+}
+
+double ugello_controllato::GetBeta()
+			// Sceglie in funzione del verso il valore di beta
+{
+	if (verso == flusso_in) {return BetaIn();}; return BetaOut();
+}
+
+
+
+double ugello_controllato::ConduttanzaIn()
+			// Definisce la conduttanza in ingresso in funzione della tensione
+{
+	return ci*comando;
+}
+
+double ugello_controllato::ConduttanzaOut()
+			// Definisce la conduttanza in uscita in funzione della tensione
+{
+	return co*comando;
+}
+
+double ugello_controllato::BetaIn()
+			// Definisce il beta in ingresso in funzione della tensione
+{
+	return bi*comando;
+}
+
+double ugello_controllato::BetaOut()
+			// Definisce il beta in uscita in funzione della tensione
+{
+	return bo*comando;
+}
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/pneumatica/ugello_controllato.h b/SRC/ChronoEngine/pneumatica/ugello_controllato.h
new file mode 100644
index 0000000..322774a
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello_controllato.h
@@ -0,0 +1,64 @@
+#ifndef _UGELLO_CONTROLLATO_H			//*****
+#define _UGELLO_CONTROLLATO_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello_controllato.h
+//
+// Descrizione		:
+//
+//
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "ugello.h"
+
+
+
+namespace chrono
+{
+namespace pneumatics
+{
+
+
+/// Class defining controlled pneumatic nozzles.
+
+class ugello_controllato : public ugello {
+
+protected:
+	double comando;
+			// comando fornito all'ugello
+
+public:
+	ugello_controllato() {comando = 0;};
+	virtual ~ugello_controllato() {};
+
+	virtual void SetComando(double mycomando) {comando = mycomando;};
+	virtual double GetComando() {return comando;};
+			// Assegna il comando all'ugello
+
+	virtual double ConduttanzaIn();
+	virtual double ConduttanzaOut();
+	virtual double BetaIn();
+	virtual double BetaOut();
+			// Funzioni che definiscono la conduttanza e il beta
+
+	virtual double GetConduttanza();
+			// Decide in funzione del verso quale C usare
+	virtual double GetBeta();
+			// Decide in funzione del verso quale b usare
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif									//*****
diff --git a/SRC/ChronoEngine/pneumatica/ugello_controllato_PA.cpp b/SRC/ChronoEngine/pneumatica/ugello_controllato_PA.cpp
new file mode 100644
index 0000000..71d40b2
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello_controllato_PA.cpp
@@ -0,0 +1,59 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello_controllato_PA.cpp
+//
+// Descrizione		: PA -> dal serbatoio all'utilizzatore
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "ugello_controllato_PA.h"
+#include <math.h>
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+double ugello_controllato_PA::ConduttanzaIn()
+			// Definisce la conduttanza in ingresso in funzione della tensione
+{
+	return  /*2.5e-8*(comando/5-1);*/ /*2.5e-8/1000*comando;*/ (2.5e-8)*comando;
+	//-5.35e-17*pow(comando,3)+6.7e-14*pow(comando,2)+1.23e-11*comando-1.83e-9;
+}
+
+double ugello_controllato_PA::ConduttanzaOut()
+			// Definisce la conduttanza in uscita in funzione della tensione
+{
+	return /*2.4e-8*(comando/5-1);*/ /*2.4e-8/1000*comando;*/ (2.4e-8)*comando;
+	//-5.69e-17*pow(comando,3)+6.61e-14*pow(comando,2)+1.74e-11*comando-3.23e-9;
+}
+
+double ugello_controllato_PA::BetaIn()
+			// Definisce il beta in ingresso in funzione della tensione
+{
+	return /*3.5e-1*(comando/5-1);*/(3.5e-1)*comando;
+	//-3.5e-12*pow(comando,4)+9.2e-9*pow(comando,3)-8.3e-6*pow(comando,2)+2.9e-3*comando-1.2e-3;
+	
+}
+
+double ugello_controllato_PA::BetaOut()
+			// Definisce il beta in uscita in funzione della tensione
+{
+	return /*3.5e-1*(comando/5-1);*/(3.5e-1)*comando;
+	//1.7e-9*pow(comando,3)-2.8e-6*pow(comando,2)+1.2e-3*comando+1.9e-1;
+	
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/pneumatica/ugello_controllato_PA.h b/SRC/ChronoEngine/pneumatica/ugello_controllato_PA.h
new file mode 100644
index 0000000..c0bd59d
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello_controllato_PA.h
@@ -0,0 +1,59 @@
+#ifndef _UGELLO_CONTROLLATO_PA_H			//*****
+#define _UGELLO_CONTROLLATO_PA_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello_controllato_PA.h
+//
+// Descrizione		: PA -> dal serbatoio all'utilizzatore
+//
+//
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+#include "ugello_controllato.h"
+
+
+namespace chrono
+{
+namespace pneumatics
+{
+
+
+/// Class defining pneumatic nozzles (into).
+
+
+class ugello_controllato_PA : public ugello_controllato {
+
+protected:
+	double comando;
+			// comando fornito all'ugello
+
+public:
+	ugello_controllato_PA() {comando = 0;};
+	virtual ~ugello_controllato_PA() {};
+
+	virtual void SetComando(double mycomando) {comando = mycomando;};
+	virtual double GetComando() {return comando;};
+			// Assegna il comando all'ugello
+
+	virtual double ConduttanzaIn();
+	virtual double ConduttanzaOut();
+	virtual double BetaIn();
+	virtual double BetaOut();
+			// Funzioni che definiscono la conduttanza e il beta
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif									//*****
diff --git a/SRC/ChronoEngine/pneumatica/ugello_controllato_RA.cpp b/SRC/ChronoEngine/pneumatica/ugello_controllato_RA.cpp
new file mode 100644
index 0000000..b8e9473
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello_controllato_RA.cpp
@@ -0,0 +1,57 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello_controllato_RA.cpp
+//
+// Descrizione		: RA -> dallo scarico all'utilizzatore
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "ugello_controllato_RA.h"
+#include <math.h>
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+double ugello_controllato_RA::ConduttanzaIn()
+			// Definisce la conduttanza in ingresso in funzione della tensione
+{
+	return /*2.6e-8*(comando/5-1);*/(2.6e-8)*comando;
+	//-4.71e-17*pow(comando,3)+4.18e-14*pow(comando,2)+3.42e-11*comando-2.63e-9;
+}
+
+double ugello_controllato_RA::ConduttanzaOut()
+			// Definisce la conduttanza in uscita in funzione della tensione
+{
+	return /*2.4e-8*(comando/5-1);*/(2.4e-8)*comando;
+	//-3.76e-17*pow(comando,3)+2.8e-14*pow(comando,2)+3.55e-11*comando-2.76e-9;
+}
+
+double ugello_controllato_RA::BetaIn()
+			// Definisce il beta in ingresso in funzione della tensione
+{
+	return  /*3.8e-1*(comando/5-1);*/(3.8e-1)*comando;
+	//-4.5e-12*pow(comando,4)+1.2e-8*pow(comando,3)-1.1e-5*pow(comando,2)+3.8e-3*comando-4.0e-2;
+}
+
+double ugello_controllato_RA::BetaOut()
+			// Definisce il beta in uscita in funzione della tensione
+{
+	return  /*3.8e-1*(comando/5-1);*/(3.8e-1)*comando;
+	//-8.5e-12*pow(comando,4)+2.0e-8*pow(comando,3)-1.6e-5*pow(comando,2)+4.7e-3*comando-1.5e-2;
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/pneumatica/ugello_controllato_RA.h b/SRC/ChronoEngine/pneumatica/ugello_controllato_RA.h
new file mode 100644
index 0000000..8ea114b
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/ugello_controllato_RA.h
@@ -0,0 +1,53 @@
+#ifndef _UGELLO_CONTROLLATO_RA_H			//*****
+#define _UGELLO_CONTROLLATO_RA_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: ugello_controllato_RA.h
+//
+// Descrizione		: RA -> dallo scarico all'utilizzatore
+//
+//
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+
+#include "ugello_controllato_PA.h"
+
+
+namespace chrono
+{
+namespace pneumatics
+{
+
+
+/// Class defining pneumatic nozzles (outro).
+
+class ugello_controllato_RA : public ugello_controllato_PA {
+
+protected:
+
+public:
+	ugello_controllato_RA() {};
+	virtual ~ugello_controllato_RA() {};
+
+	virtual double ConduttanzaIn();
+	virtual double ConduttanzaOut();
+	virtual double BetaIn();
+	virtual double BetaOut();
+			// Funzioni che definiscono la conduttanza e il beta
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif									//*****
diff --git a/SRC/ChronoEngine/pneumatica/valvola_3_2.cpp b/SRC/ChronoEngine/pneumatica/valvola_3_2.cpp
new file mode 100644
index 0000000..422a1ac
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/valvola_3_2.cpp
@@ -0,0 +1,132 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: valvola_3_2.cpp
+//
+// Descrizione		: Valvola a tre vie, del tipo ON/OFF:
+//					  P-> Alimentazione	R-> Scarico		A-> Utilizzatore
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#include "valvola_3_2.h"
+
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+valvola_3_2::valvola_3_2()
+			// Costruttore di valvola_3_2
+{
+	stato=chiusa;
+	pp=pr=pa=portata=0;
+
+	b=beta=0;
+	
+	ug1=ug2=NULL;
+	//SetupUgelli();
+}
+
+valvola_3_2::~valvola_3_2()
+			// Distruttore di valvola_3_2
+{
+	if(ug1) delete ug1;
+	ug1 = NULL;
+	if(ug2) delete ug2;
+	ug2 = NULL;
+}
+
+void valvola_3_2::SetupUgelli()
+			// Definisce come costruire gli ugelli componenti la valvola
+{
+	ug1 = new ugello();
+	ug2 = new ugello();
+}
+
+
+
+void valvola_3_2::SetupValvola(double mci1, double mco1, double mbi1, double mbo1, double mci2, double mco2, double mbi2, double mbo2, double mpp, double mpr, double mpa)
+			// Inizializza la valvola			
+			// Ugello 1: mci1, mco1, mbi1, mbo1;
+			// Ugello 2: mci2, mco2, mbi2, mbo2;
+			// Condizioni iniziali: mpp, mpr, mpa
+{
+	ug1 -> SetCi(mci1);
+	ug1 -> SetCo(mco1);
+	ug1 -> SetBi(mbi1);
+	ug1 -> SetBo(mbo1);
+
+	ug2 -> SetCi(mci2);
+	ug2 -> SetCo(mco2);
+	ug2 -> SetBi(mbi2);
+	ug2 -> SetBo(mbo2);
+
+	SetPp(mpp);
+	SetPr(mpr);
+	SetPa(mpa);
+}
+
+
+void valvola_3_2::Funzionamento()
+			// Definisce il funzionamento della valvola
+{
+			// L'oggetto ug1 rappresenta il canale di Alimentazione
+	ug1 -> SetPmonte(pp);
+	ug1 -> SetPvalle(pa);
+
+			// L'oggetto ug2 rappresenta il canale di Scarico
+	ug2 -> SetPmonte(pr);
+	ug2 -> SetPvalle(pa);
+
+	switch (stato) {
+	case scarico:
+		ug1->SetIsopen(false);
+		ug2->SetIsopen(true);
+		
+		portata = (ug1->Portata() + ug2->Portata());
+		b=ug2->GetB();
+		beta=ug2->GetBe();
+		
+		break;
+	case chiusa:
+		ug1->SetIsopen(false);
+		ug2->SetIsopen(false);
+
+		portata = 0;		//(ug1->Portata() + ug2->Portata())
+		b=0;		//ug2->GetB(); potrebbe essere utile vedere il b a valvola chiusa
+		beta=0;		//ug2->GetBe();
+
+		break;
+	case alimentazione:	
+		ug1->SetIsopen(true);
+		ug2->SetIsopen(false);
+
+		portata = (ug1->Portata() + ug2->Portata());
+		b=ug1->GetB();
+		beta=ug1->GetBe();
+
+		break;
+	}
+
+}
+
+
+double valvola_3_2::Portata()
+			// Restituisce la portata transitante nella valvola
+{
+	Funzionamento();
+	//portata = (ug1->Portata() + ug2->Portata()); 
+	return portata;
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/pneumatica/valvola_3_2.h b/SRC/ChronoEngine/pneumatica/valvola_3_2.h
new file mode 100644
index 0000000..cdde735
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/valvola_3_2.h
@@ -0,0 +1,86 @@
+#ifndef _VALVOLA_3_2_H			//*****
+#define _VALVOLA_3_2_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: valvola_3_2.h
+//
+// Descrizione		: Valvola a tre vie, del tipo ON/OFF:
+//					  P-> Alimentazione	R-> Scarico		A-> Utilizzatore
+//
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include <math.h>
+#include "ugello.h"
+
+
+
+namespace chrono
+{
+namespace pneumatics
+{
+
+/// Class defining the 3-ways valve (3-2), with on-off behaviour.
+
+class valvola_3_2 {
+
+protected:
+	ugello *ug1, *ug2;
+			// Puntatori ad ugello
+	double pp, pr, pa;
+			// pp= pressione all'alimentazione  pr= pres.allo scarico  pa= pres.all'utilizzatore
+	double portata;
+			// portata che attraversa la valvola
+public:
+	double b,beta;
+
+public:
+	enum StatoValvola { scarico = -1, chiusa = 0, alimentazione = 1} stato;
+
+public:
+
+	valvola_3_2();
+	virtual ~valvola_3_2();
+
+	virtual void SetupUgelli();
+
+	void SetPp (double mypp) { pp= mypp;};
+	double GetPp () {return pp;};
+	void SetPr (double mypr) { pr= mypr;};
+	double GetPr () {return pr;};
+	void SetPa (double mypa) { pa= mypa;};
+	double GetPa () {return pa;};
+
+	double GetPortata() {return portata;};
+
+	ugello *GetUgello1() {return ug1;};
+	ugello *GetUgello2() {return ug2;};
+
+	void SetStato (StatoValvola mystato) { stato = mystato;};
+	StatoValvola GetStato () {return stato;};
+
+	void SetupValvola(double mci1, double mco1, double mbi1, double mbo1, double mci2, double mco2, double mbi2, double mbo2, double mpp, double mpr, double mpa);
+	// Ugello 1: mci1, mco1, mbi1, mbo1; Ugello 2: mci2, mco2, mbi2, mbo2; Condizioni iniziali: mpp, mpr, mpa
+
+
+	/*virtual*/ void Funzionamento();
+	virtual double Portata();
+
+
+};
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+#endif						//*****
diff --git a/SRC/ChronoEngine/pneumatica/valvola_3_2_prop.cpp b/SRC/ChronoEngine/pneumatica/valvola_3_2_prop.cpp
new file mode 100644
index 0000000..231d93b
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/valvola_3_2_prop.cpp
@@ -0,0 +1,88 @@
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: valvola_3_2_prop.cpp
+//
+// Descrizione		: 
+//					  
+//					  
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+#include "valvola_3_2_prop.h"
+#include "ugello_controllato_PA.h"
+#include "ugello_controllato_RA.h"
+ 
+
+namespace chrono 
+{
+namespace pneumatics
+{
+
+
+valvola_3_2_prop::valvola_3_2_prop()
+{
+	comando=comandomin=comandomax=comandochius=0;
+		
+	comandomin =1000;
+	comandochius =0;
+	comandomax =-1000;
+	
+
+	// non metto niente perch� uso il costruttore della classe base....
+}
+
+valvola_3_2_prop::~valvola_3_2_prop()
+{
+	if(ug1) delete ug1;
+	ug1 = NULL;
+	if(ug2) delete ug2;
+	ug2 = NULL;
+}
+
+void valvola_3_2_prop::SetupUgelli()
+			// Definisce come costruire gli ugelli componenti la valvola
+{
+	ug1 = new ugello_controllato_PA();
+	ug2 = new ugello_controllato_RA();
+}
+
+
+void valvola_3_2_prop::ApplicaComando()
+
+{
+	if (comando>comandomax) comando=comandomax;
+	else if (comando<comandomin) comando= comandomin;
+
+	if (comando < (comandochius+1e-3) && comando > (comandochius-1e-3)) // comando < (comandochius+1e-3) && comando < (comandochius-1e-3)
+		stato = chiusa;
+	else if ((comando < comandochius))
+		{
+		((ugello_controllato_PA*)ug1) -> SetComando((comandochius-comando)/fabs(comandomin-comandochius)); //SetComando(comandochius-comando);
+		stato = alimentazione;
+		}
+	else if ((comando > comandochius))
+		{
+		((ugello_controllato_RA*)ug2) -> SetComando((comando-comandochius)/fabs(comandomax-comandochius)); //SetComando(comando-comandochius);
+		stato = scarico;
+		}
+	//else if (comando == comandochius) stato = chiusa;
+}
+
+double valvola_3_2_prop::Portata()
+{
+ApplicaComando();
+Funzionamento();		// scrive anche in portata la portata del momento
+//portata = (ug1->Portata() + ug2->Portata());
+
+return portata;
+}
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
diff --git a/SRC/ChronoEngine/pneumatica/valvola_3_2_prop.h b/SRC/ChronoEngine/pneumatica/valvola_3_2_prop.h
new file mode 100644
index 0000000..844736b
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/valvola_3_2_prop.h
@@ -0,0 +1,68 @@
+#ifndef _VALVOLA_3_2_PROP_H
+#define _VALVOLA_3_2_PROP_H
+
+//////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: valvola_3_2_prop.h
+//
+// Descrizione		:
+//
+//
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef NULL
+ #define NULL 0
+#endif
+
+#include "valvola_3_2.h"
+
+
+
+namespace chrono
+{
+namespace pneumatics
+{
+
+/// Class defining a proportional 3-ways valve (3-2), with
+/// proportional actuation.
+
+class valvola_3_2_prop : public valvola_3_2 {
+
+protected :
+	double comando;
+	double comandomin, comandomax, comandochius;
+
+public:
+	valvola_3_2_prop();
+	virtual ~valvola_3_2_prop();
+
+	void SetComando (double mycomando) { comando = mycomando;};
+	double GetComando() {return comando;};
+
+	void SetComandoMin (double mycomandomin) { comandomin = mycomandomin;};
+	double GetComandoMin() {return comandomin;};
+	void SetComandoMax (double mycomandomax) { comandomax = mycomandomax;};
+	double GetComandoMax() {return comandomax;};
+	void SetComandoChius (double mycomandochius) { comandochius = mycomandochius;};
+	double GetComandoChius() {return comandochius;};
+
+	virtual void SetupUgelli();
+
+	void ApplicaComando();
+	virtual double Portata();
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif						//*****
diff --git a/SRC/ChronoEngine/pneumatica/volume.h b/SRC/ChronoEngine/pneumatica/volume.h
new file mode 100644
index 0000000..3e7f266
--- /dev/null
+++ b/SRC/ChronoEngine/pneumatica/volume.h
@@ -0,0 +1,65 @@
+#ifndef _VOLUME_H			//*****
+#define _VOLUME_H			//*****
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// File				: volume.h
+//
+// Descrizione		:
+//
+//
+//
+// Autore			: Hermes Giberti
+// Data				: Marzo 2002
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+
+#include <math.h>
+
+
+namespace chrono
+{
+namespace pneumatics
+{
+
+
+/// Class defining the properties of a pneumatic volume of
+/// air, with density, pressure, etc.
+
+class volume {
+
+private:
+	double rho, n, p0;
+			// rho = densit� normale dell'aria [kg/m^3], p0 = pressione normale dell'aria
+			// n = coefficiente della politropica
+	double g, p, v, v1;
+			// rispettivamente portata, pressione, volume, derivata del volume;
+
+public:
+	volume() {rho=1.225; p0=101325, n = 1.4;g=p=v=v1=0;};
+	virtual ~volume() {};
+
+	void SetG (double myg) { g = myg;};
+	double GetG () {return g;};
+	void SetP (double myp) { p = myp;};
+	double GetP () {return p;};
+	void SetV (double myv) { v = myv;};
+	double GetV () {return v;};
+	void SetV1 (double myv1) { v1 = myv1;};
+	double GetV1 () {return v1;};
+
+	double Pressione1() {return ( (g-rho* pow((p/p0),(1/n)) *v1)*n*p0/(rho*v)*pow((p0/p),((1-n)/n)) ) ;}
+
+};
+
+
+
+} // END_OF_NAMESPACE____
+} // END_OF_NAMESPACE____
+
+
+
+#endif						//*****
diff --git a/SRC/OpenMeca/Core/Action/Action.cpp b/SRC/OpenMeca/Core/Action/Action.cpp
new file mode 100644
index 0000000..fceeed0
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/Action.cpp
@@ -0,0 +1,58 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Core/Action/Action.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    Action::Action(const QIcon & icon, const QString & text,  const std::string& id)
+      :QAction(icon, text, &Gui::MainWindow::Get()),
+       id_(id)
+    {
+      QAction::setIconVisibleInMenu(true);
+      QObject::connect(this, SIGNAL(triggered()), this, SLOT(ActionRequired()));
+    }
+
+    Action::~Action()
+    {
+    }
+
+    void
+    Action::ActionRequired()
+    {
+      DoAction();
+    }
+    
+    const std::string& 
+    Action::GetId()
+    {
+      return id_;
+    }
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Core/Action/Action.hpp b/SRC/OpenMeca/Core/Action/Action.hpp
new file mode 100644
index 0000000..922ca2e
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/Action.hpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Action_ActionBase_hpp
+#define OpenMeca_Action_ActionBase_hpp
+
+#include <QAction>
+
+
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    class Action : public QAction
+    {
+      Q_OBJECT
+    public:    
+      Action(const QIcon&,  const QString&, const std::string&);
+      virtual ~Action();
+      const std::string& GetId();
+		       
+    protected slots:
+      void ActionRequired();
+
+    protected:
+      virtual void DoAction() = 0;
+
+    private:
+      Action();                         // Not Allowed
+      Action(const Action&);            // Not Allowed    
+      Action& operator=(const Action&); // Not Allowed
+
+    private:
+      const std::string id_;
+      
+    };
+    
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/Action.pro b/SRC/OpenMeca/Core/Action/Action.pro
new file mode 100644
index 0000000..8a999c2
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/Action.pro
@@ -0,0 +1,36 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Core/Action/Action.hpp \
+           Core/Action/ActionDeleteUserItem.hpp \
+           Core/Action/ActionEditGlobalSetting.hpp \
+           Core/Action/ActionEditSystemSetting.hpp \
+           Core/Action/ActionEditItem.hpp \
+           Core/Action/ActionNewUserItem.hpp \
+           Core/Action/ActionNewUserItemWithSelection.hpp \
+           Core/Action/ActionNewUserItemWithAutomaticSelection.hpp \
+           Core/Action/ActionWithoutSelection.hpp \
+           Core/Action/ActionWithSelectedItem.hpp \
+           Core/Action/ActionWithSelectedItemT.hpp
+
+
+SOURCES += Core/Action/Action.cpp \
+           Core/Action/ActionWithSelectedItem.cpp
+
diff --git a/SRC/OpenMeca/Core/Action/ActionDeleteUserItem.hpp b/SRC/OpenMeca/Core/Action/ActionDeleteUserItem.hpp
new file mode 100644
index 0000000..f7f171f
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionDeleteUserItem.hpp
@@ -0,0 +1,112 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Action_DeleteUserItem_hpp
+#define OpenMeca_Action_DeleteUserItem_hpp
+
+
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogCheckDeleteItem.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    template <class T>
+    class ActionDeleteUserItem
+    {
+    public:
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      template<class Action> static void DoAction(T&, Action&);
+      template<class Action> static void DeleteItem(T&, Action&);
+    };
+    
+    template<class T> 
+    inline QString
+    ActionDeleteUserItem<T>::Text()
+    {
+      return Action::tr("Delete"); 
+    }
+
+    template<class T> 
+    inline std::string
+    ActionDeleteUserItem<T>::Id()
+    {
+      return "Delete"; 
+    }
+
+    template<class T> 
+    inline QIcon
+    ActionDeleteUserItem<T>::Icon()
+    {
+      QPixmap pixmap = Core::Singleton< Core::ItemCommonProperty<T> >::Get().GetIconSymbol().pixmap(14,14);
+      QPainter painter(&pixmap);
+      QPen pen(Qt::red);
+      pen.setWidth(2);
+      painter.setPen(pen);
+      painter.drawLine (0,  14,  14, 0);
+      painter.drawLine (14, 14,  0,  0);
+      return QIcon(pixmap);
+    }
+
+    template<class T>
+    template<class Action> 
+    inline void
+    ActionDeleteUserItem<T>::DeleteItem(T& item, Action& action)
+    {
+      Core::System::Get().DisableDrawing();
+      delete(&item);
+      Core::System::Get().EnableDrawing();
+      Core::System::Get().Update();
+      Core::System::Get().GetHistoric().SystemEdited();
+      Gui::MainWindow::Get().AddToHistoric(action);
+    }
+
+
+
+    template<class T>
+    template<class Action>    
+    inline void
+    ActionDeleteUserItem<T>::DoAction(T& item, Action& action)
+    {
+      const Core::SetOfBase<Core::UserItem>& dependentItems = item.GetAllDependentItems();
+      if (dependentItems.GetTotItemNumber() == 0)
+	{
+	  DeleteItem(item, action);
+	}
+      else
+        {
+	  Gui::DialogCheckDeleteItem& dialog = Gui::DialogCheckDeleteItem::Get();
+	  dialog.BuildListView(dependentItems);
+	  if (dialog.exec())
+	    {
+	      DeleteItem(item, action);
+	    }
+	}
+    }
+   
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionEditGlobalSetting.hpp b/SRC/OpenMeca/Core/Action/ActionEditGlobalSetting.hpp
new file mode 100644
index 0000000..90df330
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionEditGlobalSetting.hpp
@@ -0,0 +1,79 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionEditGlobalSetting_hpp
+#define OpenMeca_Core_Action_ActionEditGlobalSetting_hpp
+
+
+
+#include "OpenMeca/Core/Action/Action.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    template <class T>
+    class ActionEditGlobalSetting
+    {
+    public:    
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      static void DoAction(Action& action);
+    };
+    
+    template<class T> 
+    inline QString 
+    ActionEditGlobalSetting<T>::Text()
+    {
+      return Action::tr("Edit");
+    }
+
+    template<class T> 
+    inline std::string
+    ActionEditGlobalSetting<T>::Id()
+    {
+      return "Edit";
+    }
+    
+    
+    
+    template<class T>
+    inline QIcon
+    ActionEditGlobalSetting<T>::Icon()
+    {
+      return QIcon(":/Rsc/Img/"+QString(T::GetStrType().c_str()) + "_" + Text() + ".png");
+    }
+    
+    template<class T>
+    inline void
+    ActionEditGlobalSetting<T>::DoAction(Action&)
+    {
+      OMC_ASSERT_MSG(0, "TODO");
+    }
+
+ 
+   
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionEditItem.hpp b/SRC/OpenMeca/Core/Action/ActionEditItem.hpp
new file mode 100644
index 0000000..bbb58b3
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionEditItem.hpp
@@ -0,0 +1,86 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionEditItem_hpp
+#define OpenMeca_Core_Action_ActionEditItem_hpp
+
+
+
+#include "OpenMeca/Core/Action/ActionWithSelectedItemT.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    template <class T>
+    class ActionEditItem
+    {
+      public:    
+      static QString Text();
+      static std::string Id();
+
+      static QIcon Icon();
+      template<class Action> static void DoAction(T&, Action& action);
+    };
+    
+    template<class T> 
+    inline QString
+    ActionEditItem<T>::Text()
+    {
+      return Action::tr("Edit"); 
+    }
+
+    template<class T> 
+    inline std::string
+    ActionEditItem<T>::Id()
+    {
+      return "Edit"; 
+    }
+
+    template<class T> 
+    inline QIcon
+    ActionEditItem<T>::Icon()
+    {
+      QPixmap pixmap = Core::Singleton< Core::ItemCommonProperty<T> >::Get().GetIconSymbol().pixmap(14,14);
+      QPainter painter(&pixmap);
+      QPen pen(Qt::darkGreen);
+      pen.setWidth(2);
+      painter.setPen(pen);
+      painter.drawLine (0,  14, 7,  7);
+      painter.drawLine (7,  7,  7,  11);
+      painter.drawLine (7,  7,  3,  7);
+      return QIcon(pixmap);
+    }
+
+    template<class T>
+    template<class Action> 
+    inline void
+    ActionEditItem<T>::DoAction(T& item, Action& action)
+    {
+      Core::Singleton< Core::ItemCommonProperty<T> >::Get().GetDialog().Edit(action, item);
+    }
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionEditSystemSetting.hpp b/SRC/OpenMeca/Core/Action/ActionEditSystemSetting.hpp
new file mode 100644
index 0000000..eebab24
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionEditSystemSetting.hpp
@@ -0,0 +1,73 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionEditSystemSetting_hpp
+#define OpenMeca_Core_Action_ActionEditSystemSetting_hpp
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    template <class T>
+    class ActionEditSystemSetting
+    {
+    public:    
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      static void DoAction(Action& action);
+    };
+    
+    template<class T> 
+    inline QString
+    ActionEditSystemSetting<T>::Text()
+    {
+      return Action::tr("Edit");
+    }
+
+    template<class T> 
+    inline std::string
+    ActionEditSystemSetting<T>::Id()
+    {
+      return "Edit";
+    }
+
+    template<class T> 
+    inline QIcon
+    ActionEditSystemSetting<T>::Icon()
+    {
+      return SystemSettingT<T>::GetIcon();
+    }
+
+    template<class T>
+    inline void
+    ActionEditSystemSetting<T>::DoAction(Action& action)
+    {
+      T& t = SystemSettingT<T>::Get();
+      Core::Singleton<Core::ItemCommonProperty<T> >::Get().GetDialog().Edit(action, t);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionNewUserItem.hpp b/SRC/OpenMeca/Core/Action/ActionNewUserItem.hpp
new file mode 100644
index 0000000..4255a12
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionNewUserItem.hpp
@@ -0,0 +1,85 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionNewUserItem_hpp
+#define OpenMeca_Core_Action_ActionNewUserItem_hpp
+
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    template <class T>
+    class ActionNewUserItem
+    {
+    public:    
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      template<class Action> static void DoAction(Action& action);											    
+    };
+    
+
+
+    template<class T> 
+    inline QString 
+    ActionNewUserItem<T>::Text()
+    {
+      return Action::tr("New");
+    }
+
+    template<class T> 
+    inline std::string
+    ActionNewUserItem<T>::Id()
+    {
+      return "New";
+    }
+
+
+
+    template<class T>
+    inline QIcon
+    ActionNewUserItem<T>::Icon()
+    {
+      QPixmap pixmap = Core::Singleton< Core::ItemCommonProperty<T> >::Get().GetIconSymbol().pixmap(14,14);
+      QPainter painter(&pixmap);
+      QPen pen(Qt::darkGreen);
+      pen.setWidth(2);
+      painter.setPen(pen);
+      painter.drawLine (6, 9, 12,  9);
+      painter.drawLine (9, 6,  9,  12);
+      return QIcon(pixmap);
+ 
+    }
+
+    template<class T>
+    template<class Action> 
+    inline void
+    ActionNewUserItem<T>::DoAction(Action& action)
+    {
+      Core::Singleton< Core::ItemCommonProperty<T> >::Get().GetDialog().New(action);      
+    }
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionNewUserItemWithAutomaticSelection.hpp b/SRC/OpenMeca/Core/Action/ActionNewUserItemWithAutomaticSelection.hpp
new file mode 100644
index 0000000..898ae76
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionNewUserItemWithAutomaticSelection.hpp
@@ -0,0 +1,99 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionNewUserItemWithAutomaticSelection_hpp
+#define OpenMeca_Core_Action_ActionNewUserItemWithAutomaticSelection_hpp
+
+
+//
+// This action call the constructor with the first item of the global set as parent
+//
+
+#include "OpenMeca/Core/Action/ActionWithSelectedItemT.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    template <class T, class New>
+    class ActionNewUserItemWithAutomaticSelection
+    {
+      public:    
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      template<class Action> static void DoAction(Action& action);
+    };
+    
+    template<class T, class New> 
+    inline QString
+    ActionNewUserItemWithAutomaticSelection<T,New>::Text()
+    {
+      return Action::tr("New");
+    }
+
+    template<class T, class New> 
+    inline std::string
+    ActionNewUserItemWithAutomaticSelection<T,New>::Id()
+    {
+      return "New";
+    }
+
+    template<class T, class Parent> 
+    inline QIcon
+    ActionNewUserItemWithAutomaticSelection<T,Parent>::Icon()
+    {
+      QPixmap pixmap = Core::Singleton< Core::ItemCommonProperty<T> >::Get().GetIconSymbol().pixmap(14,14);
+      QPainter painter(&pixmap);
+      QPen pen(Qt::darkGreen);
+      pen.setWidth(2);
+      painter.setPen(pen);
+      painter.drawLine (6, 9, 12,  9);
+      painter.drawLine (9, 6,  9,  12);
+      return QIcon(pixmap);
+    }
+
+    template<class T, class Parent>
+    template<class Action> 
+    inline void
+    ActionNewUserItemWithAutomaticSelection<T,Parent>::DoAction(Action& action)
+    {
+      if (Core::System::Get().GetSetOf<Parent>().GetTotItemNumber() ==0)
+	{
+          QString msg = Action::tr("You must build a ") + 
+	    Parent::GetQStrType() + Action::tr(" instance first");
+          QMessageBox::warning(&Gui::MainWindow::Get(), Action::tr("Warning"), msg);
+	  return;
+	}
+      OMC_ASSERT_MSG(Core::System::Get().GetSetOf<Parent>().GetTotItemNumber() > 0,
+		 "Can't automatically create item because there is not any possible parent");
+      Parent& item = Core::System::Get().GetSetOf<Parent>()(0);
+      Core::Singleton< Core::ItemCommonProperty<T> >::Get().GetDialog().New(action, item);
+    }
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionNewUserItemWithSelection.hpp b/SRC/OpenMeca/Core/Action/ActionNewUserItemWithSelection.hpp
new file mode 100644
index 0000000..6b4b941
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionNewUserItemWithSelection.hpp
@@ -0,0 +1,84 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionNewUserItemWithSelection_hpp
+#define OpenMeca_Core_Action_ActionNewUserItemWithSelection_hpp
+
+
+
+#include "OpenMeca/Core/Action/ActionWithSelectedItemT.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    template <class T, class New>
+    class ActionNewUserItemWithSelection
+    {
+      public:    
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      template<class Action> static void DoAction(T&, Action& action);
+    };
+    
+    template<class T, class New> 
+    inline QString
+    ActionNewUserItemWithSelection<T,New>::Text()
+    {
+      return Action::tr("New ") + New::GetQStrType(); 
+    }
+
+    template<class T, class New> 
+    inline std::string
+    ActionNewUserItemWithSelection<T,New>::Id()
+    {
+      return "New " + New::GetStrType(); 
+    }
+
+    template<class T, class New> 
+    inline QIcon
+    ActionNewUserItemWithSelection<T,New>::Icon()
+    {
+      QPixmap pixmap = Core::Singleton< Core::ItemCommonProperty<New> >::Get().GetIconSymbol().pixmap(14,14);
+      QPainter painter(&pixmap);
+      QPen pen(Qt::darkGreen);
+      pen.setWidth(2);
+      painter.setPen(pen);
+      painter.drawLine (6, 9, 12,  9);
+      painter.drawLine (9, 6,  9,  12);
+      return QIcon(pixmap);
+    }
+
+    template<class T, class New>
+    template<class Action> 
+    inline void
+    ActionNewUserItemWithSelection<T,New>::DoAction(T& item, Action& action)
+    {
+      Core::Singleton< Core::ItemCommonProperty<New> >::Get().GetDialog().New(action, item);
+    }
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionWithSelectedItem.cpp b/SRC/OpenMeca/Core/Action/ActionWithSelectedItem.cpp
new file mode 100644
index 0000000..be360e5
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionWithSelectedItem.cpp
@@ -0,0 +1,64 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Core/Action/ActionWithSelectedItem.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    Core::SetOf<ActionWithSelectedItem> ActionWithSelectedItem::all_ = 
+      Core::SetOf<ActionWithSelectedItem>();
+
+    ActionWithSelectedItem::ActionWithSelectedItem(const QIcon & icon, 
+						   const QString & text,
+						   const std::string& id)
+      :Action(icon, text, id)
+    {
+      QAction::setEnabled(false);
+      all_.AddItem(*this);
+    }
+
+    ActionWithSelectedItem::~ActionWithSelectedItem()
+    {
+      all_.RemoveItem(*this);
+    }
+
+    void
+    ActionWithSelectedItem::Enable(Core::Item& item)
+    {
+      Core::SetOf<ActionWithSelectedItem>::it it;
+      for ( it=all_.Begin() ; it != all_.End(); it++ )
+	(*it)->setEnabled((*it)->IsMyType(item));
+    }
+
+     void
+    ActionWithSelectedItem::DisableAll()
+    {
+      Core::SetOf<ActionWithSelectedItem>::it it;
+      for ( it=all_.Begin() ; it != all_.End(); it++ )
+	(*it)->setEnabled(false);
+    }
+    
+    
+  }
+}
+
diff --git a/SRC/OpenMeca/Core/Action/ActionWithSelectedItem.hpp b/SRC/OpenMeca/Core/Action/ActionWithSelectedItem.hpp
new file mode 100644
index 0000000..df53993
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionWithSelectedItem.hpp
@@ -0,0 +1,61 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionWithSelectedItem_hpp
+#define OpenMeca_Core_Action_ActionWithSelectedItem_hpp
+
+
+
+#include "OpenMeca/Core/Action/Action.hpp"
+#include "OpenMeca/Core/Item.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    class ActionWithSelectedItem : public Action, 
+				   public Core::AutoRegister<ActionWithSelectedItem> 
+    {
+    public:    
+      static void Enable(Core::Item&);
+      static void DisableAll();
+
+      ActionWithSelectedItem(const QIcon&, const QString&, const std::string&);
+      virtual ~ActionWithSelectedItem();
+      
+      
+    private:
+      ActionWithSelectedItem();                                          //Not Allowed
+      ActionWithSelectedItem(const ActionWithSelectedItem&);            //Not Allowed    
+      ActionWithSelectedItem& operator=(const ActionWithSelectedItem&); //Not Allowed
+
+    protected:
+      virtual bool IsMyType(Core::Item&) = 0;
+
+    private:
+      static Core::SetOf<ActionWithSelectedItem> all_;      
+    };
+    
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionWithSelectedItemT.hpp b/SRC/OpenMeca/Core/Action/ActionWithSelectedItemT.hpp
new file mode 100644
index 0000000..03137b0
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionWithSelectedItemT.hpp
@@ -0,0 +1,107 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionWithSelectedItemT_hpp
+#define OpenMeca_Core_Action_ActionWithSelectedItemT_hpp
+
+
+#include <QAction>
+#include <typeinfo>
+
+#include "OpenMeca/Core/Action/ActionWithSelectedItem.hpp"
+#include "OpenMeca/Core/Item.hpp"
+#include "OpenMeca/Core/SelectionManager.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    template <class T, class Do>
+    class ActionWithSelectedItemT : public ActionWithSelectedItem
+    {
+    public:    
+      ActionWithSelectedItemT();
+      virtual ~ActionWithSelectedItemT();
+      void DoAction();
+
+    protected:
+
+    private:
+      ActionWithSelectedItemT(const ActionWithSelectedItemT<T,Do>&);              //Not Allowed    
+      ActionWithSelectedItemT<T,Do>& operator=(const ActionWithSelectedItemT<T,Do>&);//Not Allowed
+										            
+    private:
+      void ItemSelected(Core::Item* item);
+      T& GetItemSelected();
+      bool IsMyType(Core::Item&);
+      
+    };
+    
+    template<class T, class Do>
+    inline 
+    ActionWithSelectedItemT<T,Do>::ActionWithSelectedItemT()
+      :ActionWithSelectedItem(Do::Icon(), Do::Text(), Do::Id())
+    {
+    }
+
+    template<class T, class Do>
+    inline 
+    ActionWithSelectedItemT<T,Do>::~ActionWithSelectedItemT()
+    {
+    }
+    
+    template<class T, class Do>
+    inline void
+    ActionWithSelectedItemT<T,Do>::ItemSelected(Core::Item* item)
+    {
+      
+      QAction::setEnabled(typeid(T*) == typeid(item));
+    }
+    
+    template<class T, class Do>
+    inline T& 
+    ActionWithSelectedItemT<T,Do>::GetItemSelected()
+    {
+      //return SelectionManager::Get().GetSelectedItem<T>();
+    }
+
+    template<class T, class Do>
+    inline bool 
+    ActionWithSelectedItemT<T,Do>::IsMyType(Core::Item& item)
+    {
+      return (typeid(T)==typeid(item));
+    }
+
+    template<class T, class Do>
+    inline void 
+    ActionWithSelectedItemT<T,Do>::DoAction()
+    {
+      T& item = static_cast<T&>(Core::Singleton<Core::SelectionManager>::Get().GetItemSelected());
+      OMC_ASSERT_MSG(AutoRegister<T>::Exist(item), "The item does not exist");
+      Do::DoAction(item, *this);      
+	     
+    }
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/Action/ActionWithoutSelection.hpp b/SRC/OpenMeca/Core/Action/ActionWithoutSelection.hpp
new file mode 100644
index 0000000..c07ebf2
--- /dev/null
+++ b/SRC/OpenMeca/Core/Action/ActionWithoutSelection.hpp
@@ -0,0 +1,76 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Action_ActionWithoutSelection_hpp
+#define OpenMeca_Core_Action_ActionWithoutSelection_hpp
+
+
+#include <QAction>
+#include <typeinfo>
+
+#include "OpenMeca/Core/Action/Action.hpp"
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Core/SystemSetting.hpp"
+#include "OpenMeca/Core/SelectionManager.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    template <class T, class Do>
+    class ActionWithoutSelection : public Action
+    {
+    public:    
+      ActionWithoutSelection();
+      virtual ~ActionWithoutSelection();
+      void DoAction();
+
+    private:
+      ActionWithoutSelection(const ActionWithoutSelection<T,Do>&);                  //Not Allowed    
+      ActionWithoutSelection<T,Do>& operator=(const ActionWithoutSelection<T,Do>&); //Not Allowed										            
+    };
+    
+    template<class T, class Do>
+    inline 
+    ActionWithoutSelection<T,Do>::ActionWithoutSelection()
+      :Action(Do::Icon(), Do::Text(), Do::Id())
+    {
+    }
+
+    template<class T, class Do>
+    inline 
+    ActionWithoutSelection<T,Do>::~ActionWithoutSelection()
+    {
+    }
+    
+
+    template<class T, class Do>
+    inline void 
+    ActionWithoutSelection<T,Do>::DoAction()
+    {
+      Do::DoAction(static_cast<Action&>(*this)); 
+    }
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/AutoRegister.hpp b/SRC/OpenMeca/Core/AutoRegister.hpp
new file mode 100644
index 0000000..36660a8
--- /dev/null
+++ b/SRC/OpenMeca/Core/AutoRegister.hpp
@@ -0,0 +1,34 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_AutoRegister_hpp
+#define OpenMeca_Core_AutoRegister_hpp
+
+#include "OpenMeca/Core/SetOf.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    // Definition and declaration are inside SetOf.hpp
+    // to avoid forward declaration problems
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/AutoRegisteredPtr.hpp b/SRC/OpenMeca/Core/AutoRegisteredPtr.hpp
new file mode 100644
index 0000000..9e1033b
--- /dev/null
+++ b/SRC/OpenMeca/Core/AutoRegisteredPtr.hpp
@@ -0,0 +1,262 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Core_AutoRegisterdPtr_hpp
+#define OpenMeca_Core_AutoRegisterdPtr_hpp
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+
+    // Smart openmeca's pointer class. It allows automatic registering by classes
+    // that own the pointer.
+    template<class Ptr, class Registered>
+    class AutoRegisteredPtr
+    {
+    public:
+      typedef Ptr PtrType;
+      typedef Registered RegisteredType;
+
+
+    public:
+      AutoRegisteredPtr();
+      AutoRegisteredPtr(Registered&);
+      AutoRegisteredPtr(Registered&, Ptr&);
+      AutoRegisteredPtr(const AutoRegisteredPtr&);
+      ~AutoRegisteredPtr();
+      Ptr* operator->();
+      Ptr* operator=(Ptr*);
+      AutoRegisteredPtr<Ptr, Registered>& operator=(const AutoRegisteredPtr<Ptr, Registered> &);
+      Ptr* GetPtr();
+      const Ptr* GetPtr() const;
+      void Unregister();
+      void SetNullPtr();
+      const std::string Debug() const;
+
+      
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive & ar, const unsigned int) const;
+      template<class Archive> void load(Archive & ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER() 
+
+
+    private:
+      Ptr* pt_;
+      Registered* object_;
+      bool isCopy_;
+      bool childItemAdded_;
+    };
+
+
+    template<class Ptr, class Registered>
+    template<class Archive>
+    inline void
+    AutoRegisteredPtr<Ptr, Registered>::save(Archive & ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_NVP(pt_);
+      ar << BOOST_SERIALIZATION_NVP(object_);
+    }
+
+    template<class Ptr, class Registered>
+    template<class Archive>
+    inline void
+    AutoRegisteredPtr<Ptr, Registered>::load(Archive & ar, const unsigned int)
+    {
+      Unregister();
+      ar >> BOOST_SERIALIZATION_NVP(pt_);
+      ar >> BOOST_SERIALIZATION_NVP(object_);
+      if (pt_->GetDependentItems().Contain(*object_) == false)
+	{
+	  childItemAdded_ = true;
+	  pt_->AddChildItem(*object_);
+	}
+      else
+	{
+	  childItemAdded_ = false;
+	}
+    }
+
+
+    template<class Ptr, class Registered>
+    inline
+    AutoRegisteredPtr<Ptr, Registered>::AutoRegisteredPtr(Registered& object)
+      :pt_(0),
+       object_(&object),
+       isCopy_(false),
+       childItemAdded_(false)
+    {
+    }
+
+    template<class Ptr, class Registered>
+    inline
+    AutoRegisteredPtr<Ptr, Registered>::AutoRegisteredPtr(Registered& object, Ptr& pt)
+      :pt_(0),
+       object_(&object),
+       isCopy_(false),
+       childItemAdded_(false)
+    {
+      (*this)=&pt;
+    }
+
+    template<class Ptr, class Registered>
+    inline
+    AutoRegisteredPtr<Ptr, Registered>::AutoRegisteredPtr(const AutoRegisteredPtr<Ptr, Registered>& copy)
+      :pt_(copy.pt_),
+       object_(copy.object_),
+       isCopy_(true),
+       childItemAdded_(false)
+    {
+    }
+    
+    template<class Ptr, class Registered>
+    inline
+    AutoRegisteredPtr<Ptr, Registered>::~AutoRegisteredPtr()
+    {
+      if (isCopy_ == false)
+	Unregister();
+    }
+    
+
+    template<class Ptr, class Registered>
+    inline void
+    AutoRegisteredPtr<Ptr, Registered>::Unregister()
+    {
+      if (pt_ != 0 && object_ !=0)
+	{
+	  if (childItemAdded_ == true)
+	    pt_->EraseChildItem(*object_);
+	  pt_ = 0;
+	}
+    }
+
+    template<class Ptr, class Registered>
+    inline void
+    AutoRegisteredPtr<Ptr, Registered>::SetNullPtr()
+    {
+      pt_ = 0;
+    }
+    
+    template<class Ptr, class Registered>
+    inline Ptr*
+    AutoRegisteredPtr<Ptr, Registered>::operator->()
+    {
+      OMC_ASSERT_MSG(pt_ != 0, "Can't invoke pointer because it is null");
+      return pt_;
+    }
+    
+    
+    template<class Ptr, class Registered>
+    inline Ptr*
+    AutoRegisteredPtr<Ptr, Registered>::operator=(Ptr* pt)
+    {
+      if (pt_ != 0 && isCopy_ == false)
+	{
+	  pt_->EraseChildItem(*object_);
+	}
+    
+      pt_ = pt;
+    
+      if (pt_ != 0 && isCopy_ == false)
+	{
+	  childItemAdded_ = true;
+	  pt_->AddChildItem(*object_);
+	}
+
+      return pt_;
+    }
+
+    template<class Ptr, class Registered>
+    inline AutoRegisteredPtr<Ptr, Registered>&
+    AutoRegisteredPtr<Ptr, Registered>::operator=(const AutoRegisteredPtr<Ptr, Registered> & apt)
+    {
+
+      object_ = apt.object_;
+
+      if ( object_->GetMainTreeItem().parent() == &pt_->GetMainTreeItem())
+	object_->ChangeParentTreeItem(apt.pt_->GetMainTreeItem());
+
+      (*this) = apt.pt_;
+
+      // Check if an object is its own child
+      OMC_ASSERT_MSG(object_->HasChild(*pt_) == false, "The object can't be its own child");
+      OMC_ASSERT_MSG(object_->HasChild(*object_) == false, "The object can't be its own child");
+
+      return *this;
+      
+    }
+
+
+
+    template<class Ptr, class Registered>
+    inline Ptr*
+    AutoRegisteredPtr<Ptr, Registered>::GetPtr()      
+    {
+      return pt_;
+    }
+
+    template<class Ptr, class Registered>
+    inline const Ptr*
+    AutoRegisteredPtr<Ptr, Registered>::GetPtr() const
+    {
+      return pt_;
+    }
+
+
+    template<class Ptr, class Registered>
+    inline
+    AutoRegisteredPtr<Ptr, Registered>::AutoRegisteredPtr()
+      :pt_(0),
+       object_(0)
+    {
+    }
+
+
+    template<class Ptr, class Registered>
+    inline const std::string
+    AutoRegisteredPtr<Ptr, Registered>::Debug() const
+    {
+      std::string str = "AutoRegisteredPtr<" + std::string(typeid(Ptr).name()) + "," +  std::string(typeid(Registered).name()) + ">";
+
+      str += "\n with pt_=";
+      if (pt_ != 0)
+	str += pt_->GetName();
+      else
+	str += "0";
+	
+	str += "\n and object_=";
+	if (object_ != 0)
+	  str += object_->GetName();
+	else
+	  str += "0";
+      return str;
+    }
+  
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/CommonProperty.cpp b/SRC/OpenMeca/Core/CommonProperty.cpp
new file mode 100644
index 0000000..bf530a6
--- /dev/null
+++ b/SRC/OpenMeca/Core/CommonProperty.cpp
@@ -0,0 +1,123 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QFile>
+#include <QDomDocument>
+#include <QDomNode>
+
+
+#include "OpenMeca/Core/CommonProperty.hpp"
+#include "OpenMeca/Core/XmlConfigFile.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    std::map<const std::string, CommonProperty* > CommonProperty::registeredClasses_ = std::map<const std::string, CommonProperty* >();
+
+    void 
+    CommonProperty::AddClass(const std::string id, CommonProperty& theClass)
+    {
+      OMC_ASSERT_MSG(registeredClasses_.count(id)==0, "The class is already registered");
+      registeredClasses_[id] = &theClass;
+    }
+
+    CommonProperty&
+    CommonProperty::GetClass(const std::string id)
+    {
+      OMC_ASSERT_MSG(registeredClasses_.count(id)==1, "The class is not registered");
+      return *registeredClasses_[id];
+    }
+   
+
+    CommonProperty::CommonProperty()
+      :registeredActions_(),
+       registeredPopUpActions_(),
+       subMenu_(),
+       popUpMenu_()
+    {
+    }
+
+    CommonProperty::~CommonProperty()
+    {
+    }
+    
+    void 
+    CommonProperty::AddAction(Action& action)
+    {
+      OMC_ASSERT_MSG(registeredActions_.count(action.text().toStdString())==0,
+		 "The action is already registered");
+      registeredActions_[action.GetId()] = &action;
+    }
+
+    void 
+    CommonProperty::AddPopUpAction(Action& action, const std::string subMenuID)
+    {
+      OMC_ASSERT_MSG(registeredPopUpActions_.count(action.text().toStdString())==0,
+		 "The action is already registered");
+      registeredPopUpActions_[action.GetId()] = &action;
+      if (subMenuID == "")
+	popUpMenu_.addAction(&action);
+      else
+	GetSubMenu(subMenuID).addAction(&action);
+    }
+
+    void 
+    CommonProperty::AddPopUpSeparator()
+    {
+      popUpMenu_.addSeparator();
+    }
+
+    Action& 
+    CommonProperty::GetAction(const std::string id)
+    {
+      OMC_ASSERT_MSG(registeredActions_.count(id)==1,
+		 "The action is not registered");
+      return *registeredActions_[id];
+    }
+
+    QMenu&
+    CommonProperty::GetPopUpMenu()
+    {
+      return popUpMenu_;
+    }
+
+    
+
+    void 
+    CommonProperty::AddPopUpSubMenu(const std::string& title, const QIcon & icon)
+    {
+      QMenu* sub = popUpMenu_.addMenu(icon, QObject::tr(title.c_str()));
+      OMC_ASSERT_MSG(subMenu_.count(title)==0, "The id of this submenu is already taken");
+      subMenu_[title] = sub;
+    }
+
+
+    QMenu& 
+    CommonProperty::GetSubMenu(const std::string& title)
+    {
+      OMC_ASSERT_MSG(subMenu_.count(title)==1, "Can't find the required submenu with this id");
+      return *subMenu_[title];
+    }
+  }
+}
+
diff --git a/SRC/OpenMeca/Core/CommonProperty.hpp b/SRC/OpenMeca/Core/CommonProperty.hpp
new file mode 100644
index 0000000..84e13ba
--- /dev/null
+++ b/SRC/OpenMeca/Core/CommonProperty.hpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_CommonProperty_hpp
+#define OpenMeca_Core_CommonProperty_hpp
+
+#include <map>
+#include <QMenu>
+
+#include "OpenMeca/Core/Action/Action.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    // Base class for common property. A common property resumes all the properties
+    // that are shared by miscellaneous classes. It replaces 'static' attributes 
+    // for classes.
+    class CommonProperty
+    {    
+    public:
+      static CommonProperty& GetClass(const std::string);
+      
+      Action& GetAction(const std::string);
+      QMenu& GetPopUpMenu();
+
+    public:
+      static void AddClass(const std::string, CommonProperty&);
+      void AddAction(Action&);
+      void AddPopUpAction(Action&, const std::string subMenuID = "");
+      void AddPopUpSeparator();
+      void AddPopUpSubMenu(const std::string& title, const QIcon & icon);
+      QMenu& GetSubMenu(const std::string& title);
+      
+
+      CommonProperty();
+      virtual ~CommonProperty();
+      
+
+    private:
+      static std::map<const std::string, CommonProperty*> registeredClasses_;
+      std::map<const std::string, Action*> registeredActions_;
+      std::map<const std::string, Action*> registeredPopUpActions_;
+      std::map<const std::string, QMenu*> subMenu_;
+      QMenu popUpMenu_;
+
+    private:
+      CommonProperty(const CommonProperty&);               //Not Allowed    
+      CommonProperty& operator=(const CommonProperty&); //Not Allowed
+    };
+
+    
+
+    
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Condition.hpp b/SRC/OpenMeca/Core/Condition.hpp
new file mode 100644
index 0000000..2f9914b
--- /dev/null
+++ b/SRC/OpenMeca/Core/Condition.hpp
@@ -0,0 +1,117 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Condition_hpp
+#define OpenMeca_Core_Condition_hpp
+
+#include <QString>
+#include <iostream>
+#include <sstream>
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    template<typename T>
+    class Condition
+    {
+    public:
+      Condition();
+      virtual Condition<T>* Copy() const = 0;
+      virtual QString ErrorMessage() const = 0;
+      virtual bool Check(const T&) const = 0;
+      virtual ~Condition();
+    };
+    
+    template<typename T>
+    inline
+    Condition<T>::Condition()
+    {
+    }
+
+    template<typename T>
+    inline
+    Condition<T>::~Condition()
+    {
+    }
+    
+    // ----------------- //
+    // STRICTLY SUPERIOR //
+    // ----------------- //
+    template<typename T>
+    class Superior : public Condition<T>
+    {
+    public:
+      Superior(const T& treshold);
+      Condition<T>* Copy() const;
+      QString ErrorMessage() const;
+      bool Check(const T&) const;
+      ~Superior();
+
+    private:
+      const T treshold_;
+      
+    };
+    
+    template<typename T>
+    inline
+    Superior<T>::Superior(const T& treshold)
+      :Condition<T>(),
+       treshold_(treshold)
+    {
+    }
+
+    template<typename T>
+    inline Condition<T>* 
+    Superior<T>::Copy() const
+    {
+      return new Superior<T>(treshold_);
+    }
+
+    template<typename T>
+    inline QString
+    Superior<T>::ErrorMessage() const
+    {
+      QString msg(QObject::tr("Must be superior to "));
+      std::ostringstream ss;
+      ss << treshold_;
+      QString val(ss.str().c_str());
+      msg+=val;
+      return msg;
+    }
+
+    template<typename T>
+    inline bool
+    Superior<T>::Check(const T& val) const
+    {
+      return (val >= treshold_);
+    }
+
+    template<typename T>
+    inline Superior<T>::~Superior()
+    {
+    }
+
+      
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Core/ConfigDirectory.cpp b/SRC/OpenMeca/Core/ConfigDirectory.cpp
new file mode 100644
index 0000000..d210664
--- /dev/null
+++ b/SRC/OpenMeca/Core/ConfigDirectory.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+
+
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/ConfigDirectory.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    QDir ConfigDirectory::dir_ = QDir();
+
+    const QDir&
+    ConfigDirectory::Get()
+    {
+      dir_ = QDir::home();
+      
+      if (dir_.exists(GetConfigDirectoryName())==false)
+	{
+	OMC_ASSERT_MSG(dir_.mkdir(GetConfigDirectoryName())==true, "Can't create the config directory");
+	
+	dir_.cd(GetConfigDirectoryName());
+
+	const QString msg = QObject::tr("The config file directory of openmeca does not exist, openmeca will build a new config directory \"") + dir_.absolutePath() + "\"";
+	OMC_INFO_MSG(msg);
+	dir_.cdUp();
+	}
+	 
+      OMC_ASSERT_MSG(dir_.cd(GetConfigDirectoryName())==true, "Can't cd to config directory");
+      return dir_;
+    }
+
+    QString 
+    ConfigDirectory::GetConfigDirectoryName()
+    {
+      return "openmeca";
+    }
+
+    bool
+    ConfigDirectory::Delete()
+    {
+      dir_ = QDir::home();
+      if (dir_.exists(GetConfigDirectoryName())==true)
+	{
+	  dir_.cd(GetConfigDirectoryName());
+	  return dir_.removeRecursively();
+	}
+      return true;
+    }
+
+
+    
+    
+  }
+}
diff --git a/SRC/OpenMeca/Core/ConfigDirectory.hpp b/SRC/OpenMeca/Core/ConfigDirectory.hpp
new file mode 100644
index 0000000..db16c91
--- /dev/null
+++ b/SRC/OpenMeca/Core/ConfigDirectory.hpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_ConfigDirectory_hpp
+#define OpenMeca_Core_ConfigDirectory_hpp
+
+#include <QDir>
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+
+    // The config directory manager class. By default it is $USER/openmeca
+    class ConfigDirectory
+    {
+    
+    public:
+      static const QDir& Get();
+      static bool Delete();
+
+    private:
+      static QString GetConfigDirectoryName();
+      static QDir dir_;
+      
+      
+
+    private:
+      ConfigDirectory();                                //Not Allowed    
+      ConfigDirectory(const ConfigDirectory&);            //Not Allowed    
+      ConfigDirectory& operator=(const ConfigDirectory&); //Not Allowed
+
+
+    };
+
+    
+
+    
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/ConfigFile.cpp b/SRC/OpenMeca/Core/ConfigFile.cpp
new file mode 100644
index 0000000..7bb0059
--- /dev/null
+++ b/SRC/OpenMeca/Core/ConfigFile.cpp
@@ -0,0 +1,142 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+
+#include "OpenMeca/Core/ConfigFile.hpp"
+#include "OpenMeca/Core/ConfigDirectory.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    std::map<const std::string, ConfigFile*> ConfigFile::all_ = std::map<const std::string, ConfigFile*>();
+
+     void
+     ConfigFile::RestoreAll()
+     {
+       OMC_ASSERT_MSG(all_.size() > 0, "Cannot find config file");
+       std::map<const std::string, ConfigFile*>::iterator it;
+       for (it=all_.begin(); it!=all_.end(); ++it)
+	 it->second->RestoreBackup();
+     }
+
+
+
+    ConfigFile::ConfigFile(const std::string name, const std::string directory)
+      :name_(name), 
+       directory_(directory),
+       file_(),
+       backupFile_(":/Rsc/" + QString(directory_.c_str()) + "/" + QString(name_.c_str()))
+    {
+      OMC_ASSERT_MSG(backupFile_.exists(), 
+                     "The backup file \"" +  name + "\" does not exist");
+      
+      OMC_ASSERT_MSG(all_.count(name_)==0, "This config file already exist");
+      all_[name_]=this;
+    }
+
+    ConfigFile::~ConfigFile()
+    {
+      OMC_ASSERT_MSG(all_.count(name_)==1, "This config does not exist");
+      all_.erase(name_);
+    }
+    
+    QFile&
+    ConfigFile::GetBackupFile()
+    {
+      return backupFile_;
+    }
+
+    QFile&
+    ConfigFile::Open()
+    {
+      file_.close();
+      QDir dir = GetConfigFileDirectory();
+      
+      const QString filePath = GetAbsPath();
+      if (QFile::exists(filePath)==false)
+	RestoreBackup();
+
+      file_.setFileName(filePath);
+      OMC_ASSERT_MSG(file_.open(QIODevice::ReadOnly | QIODevice::Text)==true,
+		 "Can't open the required config file");
+      return file_;
+    }
+
+    void 
+    ConfigFile::RestoreBackup()
+    {
+      QDir dir = GetConfigFileDirectory();
+      const QString filePath = GetAbsPath();
+      if (QFile::exists(filePath)==true)
+	{
+	  file_.close();
+	  file_.setFileName(filePath);
+	  OMC_ASSERT_MSG(file_.remove(), 
+			 "Can't remove the " + file_.fileName().toStdString() + " " +
+			 "file in the config directory");
+	}
+
+      OMC_ASSERT_MSG(backupFile_.copy(filePath), 
+		 "Can't copy the " + file_.fileName().toStdString() + " " +
+		 "file in the config directory");
+      QFile f(filePath);
+      f.setPermissions(QFile::ReadOwner | QFile::WriteOwner | 
+		       QFile::ReadUser  | QFile::WriteUser  |
+		       QFile::ReadGroup | QFile::WriteGroup |
+		       QFile::ReadOther | QFile::WriteOther);
+      f.close();
+    }
+
+    QDir 
+    ConfigFile::GetConfigFileDirectory()
+    {
+      QDir dir = ConfigDirectory::Get();
+      
+      if (dir.exists(directory_.c_str())==false)
+	
+OMC_ASSERT_MSG(dir.mkdir(directory_.c_str()),
+		   "Can't make the config directory");
+	  
+      OMC_ASSERT_MSG(dir.cd(directory_.c_str())==true,
+		 "Can't cd to the required directory");
+      return dir;
+    }
+
+    QString
+    ConfigFile::GetAbsPath()
+    {
+      QDir dir = GetConfigFileDirectory();
+      const QString filePath = dir.absolutePath() + "/" + QString(name_.c_str());
+      return filePath;
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Core/ConfigFile.hpp b/SRC/OpenMeca/Core/ConfigFile.hpp
new file mode 100644
index 0000000..59140a0
--- /dev/null
+++ b/SRC/OpenMeca/Core/ConfigFile.hpp
@@ -0,0 +1,68 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_ConfigFile_hpp
+#define OpenMeca_Core_ConfigFile_hpp
+
+#include <QFile>
+#include <QDir>
+#include <map>
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+
+    // Base class that manages Xml config files used to save/load  global settings.
+    class ConfigFile
+    {
+    
+    public:
+      static void RestoreAll();
+      
+      ConfigFile(const std::string name, const std::string directory);      
+      virtual ~ConfigFile(); 
+      void RestoreBackup();
+      QFile& Open();
+      QFile& GetBackupFile();
+      QDir GetConfigFileDirectory();
+      QString GetAbsPath();
+    private:
+      ConfigFile();                                //Not Allowed    
+      ConfigFile(const ConfigFile&);            //Not Allowed    
+      ConfigFile& operator=(const ConfigFile&); //Not Allowed
+
+      
+
+    private:
+      static std::map<const std::string, ConfigFile*> all_;
+ 
+    protected:
+      const std::string name_;
+      const std::string directory_;
+      QFile file_;
+      QFile backupFile_;
+    };
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Core.pro b/SRC/OpenMeca/Core/Core.pro
new file mode 100644
index 0000000..4f0677a
--- /dev/null
+++ b/SRC/OpenMeca/Core/Core.pro
@@ -0,0 +1,70 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+include(./Action/Action.pro)
+
+HEADERS += Core/AutoRegisteredPtr.hpp \
+           Core/Macro.hpp \
+           Core/ConfigDirectory.hpp \
+           Core/Condition.hpp \
+           Core/GlobalSetting.hpp \
+           Core/ItemCommonProperty.hpp \
+           Core/SelectionManager.hpp \
+           Core/Singleton.hpp \
+           Core/SystemSetting.hpp \
+           Core/UserItem.hpp \
+           Core/ConfigFile.hpp \
+           Core/XmlConfigFile.hpp \
+           Core/AutoRegister.hpp \
+           Core/Drawable.hpp \
+           Core/DrawableUserItem.hpp \
+           Core/GlobalSettingT.hpp \
+           Core/Item.hpp \
+           Core/SetOfBase.hpp \
+           Core/System.hpp \
+           Core/Software.hpp \
+           Core/SystemSettingT.hpp \
+           Core/UserRootItemCommonProperty.hpp \
+           Core/CommonProperty.hpp \
+           Core/GlobalSettingCommonProperty.hpp \
+           Core/HistoricManager.hpp \
+           Core/None.hpp \
+           Core/SetOf.hpp \
+           Core/SystemSettingCommonProperty.hpp \
+           Core/UserItemCommonProperty.hpp \
+           Core/UserRootItem.hpp
+
+SOURCES += Core/Macro.cpp \
+           Core/CommonProperty.cpp \
+           Core/ConfigDirectory.cpp \
+           Core/Drawable.cpp \
+           Core/DrawableUserItem.cpp \
+           Core/GlobalSetting.cpp \
+           Core/HistoricManager.cpp \
+           Core/Item.cpp \
+           Core/SelectionManager.cpp \
+           Core/SetOfBase.cpp \
+           Core/SetOf.cpp \
+           Core/System.cpp \
+           Core/Software.cpp \
+           Core/SystemSetting.cpp \
+           Core/UserItem.cpp \
+           Core/UserRootItem.cpp \
+           Core/ConfigFile.cpp \
+           Core/XmlConfigFile.cpp
diff --git a/SRC/OpenMeca/Core/Drawable.cpp b/SRC/OpenMeca/Core/Drawable.cpp
new file mode 100644
index 0000000..a044550
--- /dev/null
+++ b/SRC/OpenMeca/Core/Drawable.cpp
@@ -0,0 +1,45 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Core/Drawable.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+ 
+
+    Drawable::Drawable()
+    {
+    }
+
+    Drawable::~Drawable()
+    {
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Core/Drawable.hpp b/SRC/OpenMeca/Core/Drawable.hpp
new file mode 100644
index 0000000..feaa813
--- /dev/null
+++ b/SRC/OpenMeca/Core/Drawable.hpp
@@ -0,0 +1,55 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Drawable_hpp
+#define OpenMeca_Core_Drawable_hpp
+
+
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {  
+    class Body;
+  }
+  
+  namespace Core
+  {
+
+    // Base class for all 3D drawable items.
+    class Drawable : public AutoRegister<Drawable>
+    {
+    public:
+      Drawable();
+      virtual ~Drawable();
+      virtual void Draw(bool withName = false) = 0;      
+    };
+
+
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/DrawableUserItem.cpp b/SRC/OpenMeca/Core/DrawableUserItem.cpp
new file mode 100644
index 0000000..feca055
--- /dev/null
+++ b/SRC/OpenMeca/Core/DrawableUserItem.cpp
@@ -0,0 +1,126 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OSX
+  #include <GL/glu.h>
+#else
+  #include <OpenGL/glu.h>
+#endif
+
+
+#include "OpenMeca/Core/DrawableUserItem.hpp"
+#include "OpenMeca/Core/SelectionManager.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Core::DrawableUserItem)
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    int DrawableUserItem::drawableItemCounter_ = 0;
+    std::map<int, DrawableUserItem*> DrawableUserItem::map_ = std::map<int, DrawableUserItem*>();
+
+    DrawableUserItem& 
+    DrawableUserItem::GetDrawableItemByGLKey(int itemGLKey)
+    {
+      OMC_ASSERT_MSG((map_.count(itemGLKey)==1), "Can't find itemGLKey");
+      return *map_[itemGLKey];      
+    }
+
+
+
+
+    const std::string 
+    DrawableUserItem::GetStrType() 
+    {
+      return "DrawableUserItem";
+    }
+
+    DrawableUserItem::DrawableUserItem(const std::string strType, QTreeWidgetItem& parent, bool isSelectable)
+      :Core::UserItem(strType, parent),
+       itemGLKey_(drawableItemCounter_),
+       isSelectable_(isSelectable),
+       drawLocalFrame_(false)
+    {
+      OMC_ASSERT_MSG(map_.count(itemGLKey_)==0, "The ItemGLKey is already used");
+      map_[itemGLKey_] = this;
+      drawableItemCounter_++;
+    }
+
+    DrawableUserItem::~DrawableUserItem()
+    {
+    }
+
+ 
+    void
+    DrawableUserItem::Draw(bool withName)
+    {
+      BeginDraw();
+
+      if (IsSelected())
+	Core::Singleton<Core::SelectionManager>::Get().GetSelectedColor().ApplyGLColor();
+      else
+	GetColor().ApplyGLColor();
+
+      
+      GetFrame().UpdateGLMatrix();
+
+      glPushMatrix();
+
+      if (withName == true && IsSelectable())
+	glPushName(GetItemGLKey());
+
+      glMultMatrixd(GetFrame().GetGLMatrix());
+
+      if (drawLocalFrame_)
+	GetFrame().Draw();      
+
+      DrawShape();
+
+      if (withName == true && IsSelectable())
+	glPopName();
+
+      glPopMatrix();
+      
+      EndDraw();
+    }
+
+    unsigned int 
+    DrawableUserItem::GetItemGLKey() const
+    {
+      return itemGLKey_;
+    }
+
+    bool 
+    DrawableUserItem::IsSelectable() const
+    {
+      return isSelectable_;
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Core/DrawableUserItem.hpp b/SRC/OpenMeca/Core/DrawableUserItem.hpp
new file mode 100644
index 0000000..e2c7d5b
--- /dev/null
+++ b/SRC/OpenMeca/Core/DrawableUserItem.hpp
@@ -0,0 +1,109 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_DrawableUserItem_hpp
+#define OpenMeca_Core_DrawableUserItem_hpp
+
+
+#include <string>
+#include <map>
+
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+#include "OpenMeca/Util/Color.hpp"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {  
+    class Body;
+  }
+  
+  namespace Core
+  {
+
+    // Base class for all 3D drawable items.
+    class DrawableUserItem : public UserItem, public Drawable, public AutoRegister<DrawableUserItem>
+    {
+    
+    public:
+      static const std::string GetStrType(); 
+      static DrawableUserItem& GetDrawableItemByGLKey(int);
+
+    public:
+      DrawableUserItem(const std::string strType, QTreeWidgetItem& parent, bool isSelectable);
+      virtual ~DrawableUserItem();
+            
+      virtual void DrawShape()  = 0;
+      virtual void BeginDraw(){};
+      virtual void EndDraw(){};
+      
+      void Draw(bool withName = false);
+      unsigned int GetItemGLKey() const;
+      bool IsSelectable() const;
+
+
+      //Accessor
+      OMC_ACCESSOR(DrawLocalFrame, bool, drawLocalFrame_);
+
+
+    private:
+      DrawableUserItem(const DrawableUserItem&);             //Not Allowed
+      DrawableUserItem& operator=(const DrawableUserItem&);  //Not Allowed
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive& ar, const unsigned int);
+      
+
+    private:
+      static int drawableItemCounter_;
+      static std::map<int, DrawableUserItem*> map_;
+
+    private:
+      const unsigned int itemGLKey_;
+      bool isSelectable_;
+      bool drawLocalFrame_;
+
+    };
+
+    template<class Archive>
+    void DrawableUserItem::serialize(Archive& ar, const unsigned int)
+    {
+       ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(UserItem);
+       ar & BOOST_SERIALIZATION_NVP(drawLocalFrame_);
+    }
+
+
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/GlobalSetting.cpp b/SRC/OpenMeca/Core/GlobalSetting.cpp
new file mode 100644
index 0000000..eb7d907
--- /dev/null
+++ b/SRC/OpenMeca/Core/GlobalSetting.cpp
@@ -0,0 +1,59 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include "OpenMeca/Core/GlobalSetting.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    GlobalSetting::GlobalSetting(const std::string strType)
+      :Item(strType),
+       file_(Item::GetStrType())
+    {
+      //Gui::MainWindow::Get().AddGlobalSetting(*this);
+      
+    }
+
+    GlobalSetting::~GlobalSetting()
+    {
+      //Gui::MainWindow::Get().RemoveGlobalSetting(*this);
+    }
+    
+     QFile&
+     GlobalSetting::OpenXmlConfigFile()
+     {
+       return file_.Open();
+     }
+
+    void
+    GlobalSetting::SaveXmlConfigFile(QDomDocument& doc)
+    {
+      return file_.SaveXml(doc);
+    }
+
+    
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Core/GlobalSetting.hpp b/SRC/OpenMeca/Core/GlobalSetting.hpp
new file mode 100644
index 0000000..2edb9e6
--- /dev/null
+++ b/SRC/OpenMeca/Core/GlobalSetting.hpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_GlobalSetting_hpp
+#define OpenMeca_Core_GlobalSetting_hpp
+
+#include <QFile>
+#include "OpenMeca/Core/XmlConfigFile.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/Item.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Base class for global setting. A global setting is a unique setting 
+    // that belongs to the openmeca software.
+    class GlobalSetting : public Item, 
+			  public AutoRegister<GlobalSetting>
+    {
+    public:    
+      GlobalSetting(const std::string strType);
+      virtual ~GlobalSetting();
+      
+      virtual void ReadXmlFile() = 0;
+      virtual void WriteXmlFile() = 0;
+
+      QFile& OpenXmlConfigFile();
+      void SaveXmlConfigFile(QDomDocument&);
+      
+    private :
+      GlobalSetting(const GlobalSetting&);             //Not Allowed
+      GlobalSetting& operator=(const GlobalSetting&);  //Not Allowed
+
+    protected:
+      XmlConfigFile file_;
+
+    }; 
+    
+    
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/GlobalSettingCommonProperty.hpp b/SRC/OpenMeca/Core/GlobalSettingCommonProperty.hpp
new file mode 100644
index 0000000..0a53805
--- /dev/null
+++ b/SRC/OpenMeca/Core/GlobalSettingCommonProperty.hpp
@@ -0,0 +1,94 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_GlobalSettingCommonProperty_hpp
+#define OpenMeca_Core_GlobalSettingCommonProperty_hpp
+
+
+#include <QString>
+#include <QIcon>
+
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+#include "OpenMeca/Core/Action/ActionWithoutSelection.hpp"
+#include "OpenMeca/Core/Action/ActionEditGlobalSetting.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Common property for the classes that inherit from the 'GlobalSetting' class
+    template<class T>
+    class GlobalSettingCommonProperty : public ItemCommonProperty<T>, public Singleton< GlobalSettingCommonProperty<T> >
+    {
+      friend class Singleton< GlobalSettingCommonProperty<T> >;
+
+    public:
+      
+      void RegisterAction();
+      void RegisterAction_Specialized();//Specialize this to add specific item
+
+    protected:
+      GlobalSettingCommonProperty();
+      virtual ~GlobalSettingCommonProperty();
+    
+    private:
+      GlobalSettingCommonProperty(const GlobalSettingCommonProperty<T>&);               //Not Allowed    
+      GlobalSettingCommonProperty<T>& operator=(const GlobalSettingCommonProperty<T>&); //Not Allowed
+    };
+
+
+    template<class T>
+    inline  
+    GlobalSettingCommonProperty<T>::GlobalSettingCommonProperty()
+      :ItemCommonProperty<T>()
+    {
+      RegisterAction();
+    }
+    
+    template<class T>
+    inline  
+    GlobalSettingCommonProperty<T>::~GlobalSettingCommonProperty()
+    {
+     
+    }
+  
+    template<class T>
+    inline void 
+    GlobalSettingCommonProperty<T>::RegisterAction()
+    {
+      Action& edit = 
+	*new ActionWithoutSelection<T, ActionEditGlobalSetting<T> >();
+      ItemCommonProperty<T>::AddAction(edit);
+    }
+    
+    template<class T>
+    inline void 
+    GlobalSettingCommonProperty<T>::RegisterAction_Specialized() 
+    {
+      
+    }
+  
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/GlobalSettingT.hpp b/SRC/OpenMeca/Core/GlobalSettingT.hpp
new file mode 100644
index 0000000..bc81dbc
--- /dev/null
+++ b/SRC/OpenMeca/Core/GlobalSettingT.hpp
@@ -0,0 +1,65 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_GlobalSettingInterfaceT_hpp
+#define OpenMeca_Core_GlobalSettingInterfaceT_hpp
+
+#include <QFile>
+#include "OpenMeca/Core/GlobalSetting.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Template class that allows static inheritence
+    template<class T>
+    class GlobalSettingT : public GlobalSetting, public Singleton<T>
+    {
+  
+    public:    
+      GlobalSettingT();
+      virtual ~GlobalSettingT();
+      
+      
+      
+    private :
+      GlobalSettingT(const GlobalSettingT&);             //Not Allowed
+      GlobalSettingT& operator=(const GlobalSettingT&);  //Not Allowed
+    }; 
+    
+    template<class T>
+    inline
+    GlobalSettingT<T>::GlobalSettingT()
+      :GlobalSetting(T::GetStrType()),
+       Singleton<T>()
+    {
+    }
+    
+    template<class T>
+    inline
+    GlobalSettingT<T>::~GlobalSettingT()
+    {
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/HistoricManager.cpp b/SRC/OpenMeca/Core/HistoricManager.cpp
new file mode 100644
index 0000000..82c42f6
--- /dev/null
+++ b/SRC/OpenMeca/Core/HistoricManager.cpp
@@ -0,0 +1,129 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Core/HistoricManager.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    HistoricManager::HistoricManager(System& system)
+      :system_(system),
+       archives_(),
+       historicNavigator_(),
+       lastUserSavedArchive_()
+    {
+      Init();
+    }
+
+    HistoricManager::~HistoricManager()
+    {
+      
+    }
+
+    void
+    HistoricManager::Init()
+    {
+      archives_.push_back(std::string());
+      historicNavigator_ =  --archives_.end();
+      system_.Save(*historicNavigator_);
+      lastUserSavedArchive_ = std::string();
+    }
+
+    
+    void
+    HistoricManager::SystemEdited()
+    {
+      if (IsInUndoRedoMode()==true)
+	{
+	  archives_.erase(++historicNavigator_, archives_.end());
+	}
+      archives_.push_back(std::string());
+      historicNavigator_ =  --archives_.end();
+      system_.Save(*historicNavigator_);
+    }
+
+    bool
+    HistoricManager::IsInUndoRedoMode()
+    {
+      return (historicNavigator_ !=  --archives_.end());
+    }
+
+     void
+    HistoricManager::LoadPreviousState()
+    {
+      OMC_ASSERT_MSG(historicNavigator_ != archives_.begin(), "Can't load previous state");
+      system_.Reset();
+      --historicNavigator_;
+      system_.Load(*historicNavigator_);
+      system_.Update();
+    }
+
+    void
+    HistoricManager::LoadNextState()
+    {
+      OMC_ASSERT_MSG(historicNavigator_ != --archives_.end(), "Can't load next state");
+      system_.Reset();
+      ++historicNavigator_;
+      system_.Load(*historicNavigator_);
+      system_.Update();
+    }
+
+    void 
+    HistoricManager::Reset()
+    {
+      archives_.clear();
+      Init();
+    }
+
+
+    bool
+    HistoricManager::IsUndoPossible() const
+    {
+      OMC_ASSERT_MSG(historicNavigator_ != archives_.end(), "Historic is at end");
+      return (historicNavigator_ != archives_.begin());
+    }
+
+    bool
+    HistoricManager::IsRedoPossible() const
+    {
+      OMC_ASSERT_MSG(historicNavigator_ != archives_.end(), "Historic is at end");
+      return (historicNavigator_ != --archives_.end());
+    }
+
+    bool
+    HistoricManager::IsSystemEdited() const
+    {
+      return (*(--archives_.end()) != lastUserSavedArchive_  && IsUndoPossible()==true);
+    }
+
+    void
+    HistoricManager::UserSave()
+    {
+      OMC_ASSERT_MSG(archives_.size() > 0, "Problem with historic, it can't be empty");
+      lastUserSavedArchive_ = *(--archives_.end());
+    }
+    
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Core/HistoricManager.hpp b/SRC/OpenMeca/Core/HistoricManager.hpp
new file mode 100644
index 0000000..44abdec
--- /dev/null
+++ b/SRC/OpenMeca/Core/HistoricManager.hpp
@@ -0,0 +1,68 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_HistoricManager_hpp
+#define OpenMeca_Core_HistoricManager_hpp
+
+#include <string>
+#include <vector>
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    class System;
+    
+    // The historic manager class that manages the undo/redo feature
+    class HistoricManager
+    {
+    public:
+      HistoricManager(System& system);
+      ~HistoricManager();
+      
+      void LoadPreviousState();
+      void LoadNextState();
+      void Reset();
+      bool IsUndoPossible() const;
+      bool IsRedoPossible() const;
+      bool IsSystemEdited() const;
+      void SystemEdited();
+      void UserSave();
+
+    private:
+      void Init();
+      bool IsInUndoRedoMode();
+      
+      HistoricManager();                          //Not Allowed
+      HistoricManager(const HistoricManager&);             //Not Allowed
+      HistoricManager& operator=(const HistoricManager&);  //Not Allowed
+
+      private :
+      System& system_;
+      std::vector< std::string > archives_;
+      std::vector< std::string >::iterator historicNavigator_;
+      std::string lastUserSavedArchive_;
+    };
+    
+    
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/Item.cpp b/SRC/OpenMeca/Core/Item.cpp
new file mode 100644
index 0000000..d3cb8aa
--- /dev/null
+++ b/SRC/OpenMeca/Core/Item.cpp
@@ -0,0 +1,161 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Core/Item.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    void
+    Item::UnselectAll()
+    {
+      SetOf<Item>& set = AutoRegister<Item>::GetGlobalSet();
+      SetOf<Item>::it it;
+      for (it=set.Begin() ; it != set.End(); it++ )
+	(*it)->SetIsSelected(false);
+    }
+
+
+
+    Item::Item(const std::string strType, QTreeWidgetItem* parent)
+      :icon_(),
+       mainTreeItem_(0), // Can't instanciate mainTreeItem here
+       isSelected_(false),
+       secondaryTreeItems_(),
+       strType_(strType)
+    {
+      if (parent != 0)
+	 mainTreeItem_ = new Gui::MainTreeItem(*parent, *this);
+    }
+
+
+    Item::~Item()
+    {
+      if (mainTreeItem_ != 0)
+	delete mainTreeItem_;
+    }
+
+
+    System&
+    Item::GetSystem()
+    {
+      return System::Get();
+    }
+
+    const std::string&
+    Item::GetStrType() const
+    {
+      return strType_;
+    }
+
+    void
+    Item::SaveState()
+    {
+    }
+
+    void 
+    Item::ResetState()
+    {
+    }
+
+    void 
+    Item::RecoveryState(unsigned int)
+    {
+    }
+
+    void
+    Item::MainTreeItemIsDeleted()
+    {
+      mainTreeItem_ = 0;
+    }
+
+    const std::string& 
+    Item::GetName() const
+    {
+      return strType_;
+    }
+
+    void
+    Item::Select()
+    {
+      isSelected_ = true;
+    }
+
+    void
+    Item::UnSelect()
+    {
+      isSelected_ = false;
+    }
+
+
+    void
+    Item::SetIsSelected(bool val)
+    {
+      isSelected_ = val;
+    }
+
+
+    bool
+    Item::IsSelected() const
+    {
+      return isSelected_;
+    }
+
+    void 
+    Item::AddSecondaryTreeItem(Gui::SecondaryTreeItem& item)
+    {
+      secondaryTreeItems_.AddItem(item);
+    }
+
+    void 
+    Item::Update()
+    {
+      for (unsigned int i = 0; i < secondaryTreeItems_.GetTotItemNumber(); ++i)
+	secondaryTreeItems_(i).Update();
+    }
+
+    void 
+    Item::InitChSystem(chrono::ChSystem&)
+    {
+    }
+
+    void 
+    Item::BuildChSystem(chrono::ChSystem&)
+    {
+    }
+
+    void 
+    Item::UpdateValueFromCh()
+    {
+    }
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Core/Item.hpp b/SRC/OpenMeca/Core/Item.hpp
new file mode 100644
index 0000000..499f3d3
--- /dev/null
+++ b/SRC/OpenMeca/Core/Item.hpp
@@ -0,0 +1,119 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Item_hpp
+#define OpenMeca_Core_Item_hpp
+
+
+#include <QString>
+#include <QIcon>
+
+#include "OpenMeca/Gui/MainTreeItem.hpp"
+#include "OpenMeca/Gui/SecondaryTreeItem.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "ChronoEngine/physics/ChSystem.h"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    class System;
+
+    // Base class for all openmeca items : user or automatically created
+    class Item : public AutoRegister<Item>
+    {
+    public:
+      static void UnselectAll();
+
+  
+    public:    
+      Item(const std::string strType_, QTreeWidgetItem* parent = 0);
+      virtual ~Item();
+      System& GetSystem();
+      const std::string& GetStrType() const;
+
+      // To save item's state during simulation
+      virtual void SaveState();
+      virtual void ResetState();
+      virtual void RecoveryState(unsigned int);
+      
+      virtual const std::string& GetName() const;
+
+      // Tree item
+      void MainTreeItemIsDeleted();
+
+
+      virtual void Select();
+      virtual void UnSelect(); 
+      virtual bool IsSelected() const;
+      virtual void SetIsSelected(bool);
+      virtual void Update();
+
+      // Chrono::Engine management
+      virtual void InitChSystem(chrono::ChSystem&);
+      virtual void BuildChSystem(chrono::ChSystem&);
+      virtual void UpdateValueFromCh();
+
+
+      //Accessor
+      OMC_ACCESSOR    (Icon        , QIcon            , icon_);
+      OMC_ACCESSOR_PTR(MainTreeItem, Gui::MainTreeItem, mainTreeItem_);
+
+
+    protected:
+      void AddSecondaryTreeItem(Gui::SecondaryTreeItem&);
+
+
+    protected :
+      QIcon icon_;
+      Gui::MainTreeItem* mainTreeItem_;
+      bool isSelected_;
+      SetOfBase<Gui::SecondaryTreeItem> secondaryTreeItems_;
+      
+    private :
+      const std::string strType_;
+
+    private :
+      Item();                        //Not Allowed
+      Item(const Item&);             //Not Allowed
+      Item& operator=(const Item&);  //Not Allowed
+
+      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int)
+      {
+	ar & BOOST_SERIALIZATION_NVP(const_cast<std::string&>(strType_));
+      }
+    }; 
+    
+  }
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/ItemCommonProperty.hpp b/SRC/OpenMeca/Core/ItemCommonProperty.hpp
new file mode 100644
index 0000000..1944c5d
--- /dev/null
+++ b/SRC/OpenMeca/Core/ItemCommonProperty.hpp
@@ -0,0 +1,133 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_ItemCommonProperty_hpp
+#define OpenMeca_Core_ItemCommonProperty_hpp
+
+
+#include <QIcon>
+
+
+#include "OpenMeca/Core/CommonProperty.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Common property for the classes that inherit from the 'Item' class
+    template<class T>
+    class ItemCommonProperty :public CommonProperty,  public Singleton< ItemCommonProperty<T> >
+    {
+      friend class Singleton< ItemCommonProperty<T> >;
+    
+    public:
+      const std::string& GetStrType() const;
+      const QString GetQStrType() const;
+
+      const QIcon& GetIconSymbol() const; 
+      
+      typedef typename T::Dialog Dialog;
+      Dialog& GetDialog();
+      
+      
+    private:
+      ItemCommonProperty(const ItemCommonProperty<T>&);               //Not Allowed    
+      ItemCommonProperty<T>& operator=(const ItemCommonProperty<T>&); //Not Allowed
+      void BuildIconSymbol();
+
+    protected:
+      ItemCommonProperty();
+      virtual ~ItemCommonProperty();
+    
+    private:
+      const std::string strType_;
+      QIcon iconSymbol_;
+      
+
+   
+    };
+
+    
+
+    template<class T>
+    inline  
+    ItemCommonProperty<T>::ItemCommonProperty()
+      :CommonProperty(),
+       strType_(T::GetStrType()),
+       //iconSymbol_(":/Rsc/Img/" + QString(strType_.c_str()) + ".png")
+       iconSymbol_()
+    {
+      CommonProperty::AddClass(strType_, *this);
+      BuildIconSymbol();
+    }
+    
+    template<class T>
+    inline  
+    ItemCommonProperty<T>::~ItemCommonProperty()
+    {
+     
+    }
+      
+    template<class T>
+    inline void
+    ItemCommonProperty<T>::BuildIconSymbol()
+    {
+      //Specialize this !
+    }
+
+
+    template<class T>
+    inline const std::string&
+    ItemCommonProperty<T>::GetStrType() const
+    {
+      return strType_;
+    }
+
+    template<class T>
+    inline const QString
+    ItemCommonProperty<T>::GetQStrType() const
+    {
+      return T::GetQStrType();
+    }
+
+    template<class T>
+    inline const QIcon&
+    ItemCommonProperty<T>::GetIconSymbol() const
+    {
+      return iconSymbol_;
+    }
+
+    template<class T>
+    inline typename T::Dialog& 
+    ItemCommonProperty<T>::GetDialog()
+    {
+      return Core::Singleton< Dialog >::Get();
+
+    }
+
+  
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/Macro.cpp b/SRC/OpenMeca/Core/Macro.cpp
new file mode 100644
index 0000000..23496ea
--- /dev/null
+++ b/SRC/OpenMeca/Core/Macro.cpp
@@ -0,0 +1,97 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    void RaiseAssertion(int line, const std::string& file,
+			const std::string& condition, const std::string& message)
+    {
+
+      if (Gui::MainWindow::Exist())
+	{
+	  QString text = "<b>" + QObject::tr("Sorry, openmeca encounters an error") + "</b><br><br>";
+	  
+	  text += QObject::tr("Error details :") + "<br>";
+	  text += QObject::tr("source file :") + file.c_str() + "<br>";
+	  text += QObject::tr("line :") + QString::number(line) + "<br>";
+	  text += QObject::tr("condition :") + condition.c_str() + "<br>";
+	  
+	  if (!message.empty())
+	    text += QObject::tr("message :") + message.c_str() + "<br>";
+	  text += "<br><br>";
+	  text += QObject::tr("The program may be unstable now, do you really want to continue ?") + "<br>";
+	  Gui::MainWindow* win = &Gui::MainWindow::Get();
+	  
+	  int  stay = QMessageBox::critical(win, QObject::tr("Error"), text, 
+					    QMessageBox::Yes|QMessageBox::No);
+	  
+	  if (stay == QMessageBox::Yes)
+	    return;
+
+	  QString saveStr = QObject::tr("Do You want to save your work before quitting OpenMeca ?");
+	  int  save = QMessageBox::question(win, QObject::tr("Question"), saveStr, 
+					    QMessageBox::Yes|QMessageBox::No);
+	  if (save == QMessageBox::Yes)
+	     win->SaveAs();
+
+	}
+      else
+	{
+          std::string text = "Sorry, openmeca encounters an error\n\n";
+          text += "Error details :\n";
+          text += "source file :" + file + "\n";
+          text += "line :" + std::to_string(line) + "\n";
+	  text += "condition :" + condition + "\n";
+	  
+	  if (!message.empty())
+	    text += "message :" + message + "\n";
+	  text += "\n\n";
+	  text += "The program will stop";
+          std::cout << text << std::endl;
+
+	}
+      assert(0);
+    }
+
+    void DisplayInfoMsg(const QString& msg)
+    {
+      if (Gui::MainWindow::Exist())
+	QMessageBox::information(&Gui::MainWindow::Get(), QObject::tr("Information"), msg);
+      else
+	std::cout << "[OpenMeca info:] " << msg.toStdString() << std::endl;
+    }
+
+
+    void DisplayWarningMsg(const QString& msg)
+    {
+      if (Gui::MainWindow::Exist())
+	QMessageBox::warning(&Gui::MainWindow::Get(), QObject::tr("Warning"), msg);
+      else
+	std::cout << "[OpenMeca warn:] " << msg.toStdString() << std::endl;
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Core/Macro.hpp b/SRC/OpenMeca/Core/Macro.hpp
new file mode 100644
index 0000000..a5c59e3
--- /dev/null
+++ b/SRC/OpenMeca/Core/Macro.hpp
@@ -0,0 +1,104 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Macro_hpp
+#define OpenMeca_Core_Macro_hpp
+
+
+// This is a macro to autmatic access to class member, for example the macro
+// OMC_ACCESSOR(Mass, double, mass_); -> will give the 4 members fonctions
+//    -        double& GetMass()       {return mass_};
+//    -  const double& GetMass() const {return mass_};
+//
+// Note that these functions are inlined !
+
+
+#define OMC_ACCESS(method, type, variable)    \
+  type & Get##method () {return variable;}    
+
+#define OMC_ACCESS_CST(method, type, variable) \
+  const type & Get##method () const {return variable;}                  
+
+#define OMC_ACCESSOR(method, type, variable) \
+  OMC_ACCESS      (method, type, variable)   \
+  OMC_ACCESS_CST(method, type, variable)
+
+
+
+#define OMC_ACCESS_PTR(method, type, variable)    \
+  type & Get##method () {assert(variable!=0);return *variable;}    
+
+#define OMC_ACCESS_CST_PTR(method, type, variable) \
+  const type & Get##method () const {assert(variable!=0);return *variable;}                  
+
+#define OMC_ACCESSOR_PTR(method, type, variable)  \
+  OMC_ACCESS_PTR      (method, type, variable)	  \
+  OMC_ACCESS_CST_PTR(method, type, variable) 
+
+
+
+// This macro can replace the standard 'assert' macro.
+// If the assertion is raised, it stop the program and prints the given message.
+#ifndef NDEBUG
+#   define OMC_ASSERT_MSG(condition, message) \
+    do { \
+        if (! (condition)) { \
+	  OpenMeca::Core::RaiseAssertion(__LINE__,  __FILE__, #condition, message); \
+        }   \
+    } while (false)
+#else
+#   define OMC_ASSERT_MSG(condition, message) do { } while (false)
+#endif
+
+#ifndef NDEBUG
+#   define OMC_ASSERT(condition) \
+    do { \
+        if (! (condition)) { \
+	  OpenMeca::Core::RaiseAssertion(__LINE__,  __FILE__, #condition, ""); \
+        }   \
+    } while (false)
+#else
+#   define OMC_ASSERT(condition, message) do { } while (false)
+#endif
+
+
+#define OMC_INFO_MSG(message)  \
+  OpenMeca::Core::DisplayInfoMsg(message)
+
+#define OMC_WARNING_MSG(message)  \
+  OpenMeca::Core::DisplayWarningMsg(message)
+
+#include <string>
+#include <QString>
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    void RaiseAssertion(int line, const std::string& file, const std::string& condition, const std::string& message);
+
+    void DisplayInfoMsg(const QString& message);
+    void DisplayWarningMsg(const QString& message);
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/None.hpp b/SRC/OpenMeca/Core/None.hpp
new file mode 100644
index 0000000..f38da94
--- /dev/null
+++ b/SRC/OpenMeca/Core/None.hpp
@@ -0,0 +1,36 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_None_hpp
+#define OpenMeca_Core_None_hpp
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // This do nothing
+    struct None
+    {
+    };
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/SelectionManager.cpp b/SRC/OpenMeca/Core/SelectionManager.cpp
new file mode 100644
index 0000000..0f7036a
--- /dev/null
+++ b/SRC/OpenMeca/Core/SelectionManager.cpp
@@ -0,0 +1,101 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Core/SelectionManager.hpp"
+#include "OpenMeca/Core/DrawableUserItem.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+#include "OpenMeca/Core/Action/ActionWithSelectedItem.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    SelectionManager::SelectionManager()
+      :QObject(),
+       itemSelected_(0),
+       selectedColor_(Qt::yellow)
+    {
+    }
+
+    SelectionManager::~SelectionManager()
+    {
+    }
+      
+    void 
+    SelectionManager::SetItemSelected(Item& item)
+    {
+      Item::UnselectAll();
+      itemSelected_ = &item;
+      itemSelected_->Select();
+      ActionWithSelectedItem::Enable(item);
+      emit ItemSelected(item);
+      Gui::MainWindow::Get().GetViewer().updateGL(); 
+    }
+
+    void 
+    SelectionManager::SetDrawableItemSelected(int i)
+    {
+      DrawableUserItem& drawableItem = DrawableUserItem::GetDrawableItemByGLKey(i);
+      Gui::MainWindow::Get().GetTreeView().setCurrentItem(&drawableItem.GetMainTreeItem(), 0);
+      SetItemSelected(drawableItem);
+    }
+
+
+    void  
+    SelectionManager::SetNoItemSelected()
+    {
+      itemSelected_ = 0;
+      ActionWithSelectedItem::DisableAll();
+      Item::UnselectAll();
+      Gui::MainWindow::Get().GetTreeView().setCurrentItem(0);
+      Gui::MainWindow::Get().GetViewer().updateGL(); 
+    }
+
+    bool 
+    SelectionManager::IsItemSelected()
+    {
+      return itemSelected_ != 0;
+    }
+
+    Item& 
+    SelectionManager::GetItemSelected()
+    {
+      return GetItem();
+    }
+    
+    Item& 
+    SelectionManager::GetItem()
+    {
+      OMC_ASSERT_MSG(itemSelected_ != 0, "The selected item is null");
+      return *itemSelected_;
+    }
+
+    const Util::Color&
+    SelectionManager::GetSelectedColor() const
+    {
+      return selectedColor_;
+    }
+
+  }
+}
+ 
+
diff --git a/SRC/OpenMeca/Core/SelectionManager.hpp b/SRC/OpenMeca/Core/SelectionManager.hpp
new file mode 100644
index 0000000..6bd3ab7
--- /dev/null
+++ b/SRC/OpenMeca/Core/SelectionManager.hpp
@@ -0,0 +1,70 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_SelectionManager_hpp
+#define OpenMeca_Core_SelectionManager_hpp
+
+#include <QObject>
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Core/Item.hpp"
+#include "OpenMeca/Util/Color.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+
+    // SelectionManager class that manages and stores the items selected by the user.
+    class SelectionManager :  public QObject, public Singleton<SelectionManager>
+    {
+      Q_OBJECT
+      friend class Singleton<SelectionManager>;
+
+    public:    
+      void SetItemSelected(Item&);
+      void SetDrawableItemSelected(int);
+      void SetNoItemSelected();
+      bool IsItemSelected();
+      Item& GetItemSelected();
+
+      const Util::Color& GetSelectedColor() const;
+    
+    signals:
+      void ItemSelected(Core::Item&);
+
+    private:
+      SelectionManager();
+      virtual ~SelectionManager();
+      Item& GetItem();
+      SelectionManager(const SelectionManager&);            //Not Allowed    
+      SelectionManager& operator=(const SelectionManager&); //Not Allowed
+
+    private:
+      Item* itemSelected_;
+      Util::Color selectedColor_;
+            
+    };
+
+  }
+}
+ 
+#endif
diff --git a/SRC/OpenMeca/Core/SetOf.cpp b/SRC/OpenMeca/Core/SetOf.cpp
new file mode 100755
index 0000000..ec5b1ae
--- /dev/null
+++ b/SRC/OpenMeca/Core/SetOf.cpp
@@ -0,0 +1,30 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include "OpenMeca/Core/SetOf.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {    
+  }
+}
+
diff --git a/SRC/OpenMeca/Core/SetOf.hpp b/SRC/OpenMeca/Core/SetOf.hpp
new file mode 100755
index 0000000..34ce87d
--- /dev/null
+++ b/SRC/OpenMeca/Core/SetOf.hpp
@@ -0,0 +1,390 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_SetOf_hpp
+#define OpenMeca_Core_SetOf_hpp
+
+
+
+#include <list>
+#include <iostream>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Core/SetOfBase.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    // SetOf class is the openmeca's smart container. 
+    // The SetOf class can contains AutoRegister<T> child class instances with 
+    // automatically registering and unregistering when they are destroyed or created
+     template<typename type>
+    class SetOf : public SetOfBase<type>
+    {
+    public:
+      static SetOf<type>& GetGlobalSet();
+      typedef typename std::list<type *>::iterator it;
+      typedef typename std::list<type *>::const_iterator const_it;
+
+    public:
+
+      SetOf();
+      SetOf(const SetOf &);
+      SetOf& operator=(const SetOf &);
+
+      ~SetOf();
+
+      void AddItem(type&);      
+      void RemoveItem(type&);
+      void ClearAndDelete();
+      void DeleteAllItem();
+      //unsigned int GetRank (type *) const;
+
+      unsigned int GetRank (const type *) const;
+      void EraseDoublet();
+      
+      void CheckForDoublet();
+      void UnCheckForDoublet();
+
+      bool IsGlobalSet() const;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive & ar, const unsigned int) const;
+      template<class Archive> void load(Archive & ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER() 
+
+    private:
+      static SetOf<type>* globalSet_;
+      
+    private:
+      bool checkForDoublet_;
+    };
+
+    // The item must static inherit from AutoRegister<T> class to be contained 
+    // by a SetOf<T>
+    template <class T>
+    class AutoRegister
+    {
+    
+    public:
+      static bool Exist(T&);
+      static SetOf<T>& GetGlobalSet();
+      static void Debug();
+
+    public :
+      void AddSet(SetOf<T>&);
+      void RemoveSet(SetOf<T>&);
+
+    protected: 
+      AutoRegister();
+      virtual ~AutoRegister();
+      
+
+    private :
+      AutoRegister(const AutoRegister&);             //Not Allowed
+      AutoRegister& operator=(const AutoRegister&);  //Not Allowed
+    
+    private:
+      std::list<SetOf<T>*> allSet_;
+    }; 
+
+
+    // ** Definition of SetOf class ** 
+    template<typename type> 
+    SetOf<type>* SetOf<type>::globalSet_=0;
+
+    template<typename type> 
+    inline SetOf<type>&
+    SetOf<type>::GetGlobalSet()
+    {
+      if (globalSet_==0)
+	globalSet_ = new SetOf<type>();
+      return *globalSet_;
+    }
+
+
+    template<typename type> 
+    template<class Archive>
+    inline void
+    SetOf<type>::save(Archive & ar, const unsigned int) const
+    {
+      unsigned int totItemNumber = SetOfBase<type>::set_.size();
+      ar << BOOST_SERIALIZATION_NVP(totItemNumber);
+      typename std::list<type *>::const_iterator it;
+      for (it=SetOfBase<type>::set_.begin() ; it != SetOfBase<type>::set_.end(); it++ )
+	{
+	  ar << BOOST_SERIALIZATION_NVP(*it);
+	} 
+    }
+
+    template<typename type> 
+    template<class Archive>
+    inline void
+    SetOf<type>::load(Archive & ar, const unsigned int)
+     {
+       bool isGlobal = IsGlobalSet();
+       unsigned int totItemNumber = 0;
+       ar >> BOOST_SERIALIZATION_NVP(totItemNumber);
+       for (unsigned int i=0;  i< totItemNumber; ++i)
+	 {
+	   type* ptr=0;
+	   ar >> BOOST_SERIALIZATION_NVP(ptr);
+	   OMC_ASSERT_MSG(ptr != 0, "Can't serialize the pointer");
+
+	   if (!isGlobal)
+	     AddItem(*ptr);
+	 }
+     }
+      
+    template<typename type> 
+    inline
+    SetOf<type>::~SetOf()
+    {
+      typename std::list<type *>::iterator it;
+      for ( it=SetOfBase<type>::set_.begin() ; it != SetOfBase<type>::set_.end(); it++ )
+	{
+	  type& item = **it;
+	  static_cast<AutoRegister<type>& >(item).RemoveSet(*this);
+	}
+    }
+
+    
+    template<typename type> 
+    inline
+    SetOf<type>::SetOf(const SetOf &set)
+      : SetOfBase<type>(set),
+	checkForDoublet_(set.checkForDoublet_)
+    {
+      typename std::list<type *>::iterator it;
+      for ( it=SetOfBase<type>::set_.begin() ; it != SetOfBase<type>::set_.end(); it++ )
+	{
+	  type& item = **it;
+	  static_cast<AutoRegister<type>& >(item).AddSet(*this);
+	}
+    }
+    
+    template<typename type> 
+    inline SetOf<type>& 
+    SetOf<type>::operator=(const SetOf &set)
+    {
+      SetOfBase<type>::set_ = set.SetOfBase<type>::set_;
+      checkForDoublet_ = SetOfBase<type>::set_.checkForDoublet_;
+      typename std::list<type *>::iterator it;
+      for ( it=SetOfBase<type>::set_.begin() ; it != SetOfBase<type>::set_.end(); it++ )
+	{
+	  type& item = **it;
+	  static_cast<AutoRegister<type>& >(item).AddSet(*this);
+	}
+      return *this;
+    }
+
+
+    template<typename type> 
+    inline 
+    SetOf<type>::SetOf()
+      :SetOfBase<type>(),
+       checkForDoublet_(true)
+					  
+    {
+    }
+
+        
+    template<typename type>
+    inline void
+    SetOf<type>::AddItem(type& item)
+    {
+      typename std::list<type *>::iterator it;
+      for (it=SetOfBase<type>::set_.begin() ; it != SetOfBase<type>::set_.end(); it++ )
+	{
+	  if (*it==&item && checkForDoublet_==true)
+	    {
+	      OMC_ASSERT_MSG(0, "This item is already present in this set");
+	    }
+	}
+     SetOfBase<type>::set_.push_back(&item);
+     static_cast<AutoRegister<type>& >(item).AddSet(*this);
+    }
+    
+    template<typename type>
+    inline void
+    SetOf<type>::EraseDoublet()
+    {
+      for (unsigned int i=0; i<SetOfBase<type>::GetTotItemNumber(); ++i)
+	{
+	  for (unsigned int j=i+1; j<SetOfBase<type>::GetTotItemNumber(); ++j)
+	    {
+	      if (SetOfBase<type>::set_[i]==SetOfBase<type>::set_[j])
+		{
+		  RemoveItem(*SetOfBase<type>::set_[j]);
+		}
+	    }
+	}
+    }
+
+    template<typename type>
+    inline void
+    SetOf<type>::RemoveItem(type& item)
+    {
+      typename std::list<type *>::iterator it;
+      for ( it=SetOfBase<type>::set_.begin() ; it != SetOfBase<type>::set_.end(); it++ )
+	{
+	  if (*it==&item)
+	    {
+	      SetOfBase<type>::set_.erase(it);
+	      static_cast<AutoRegister<type>& >(item).RemoveSet(*this);
+	      return;
+	    }
+	}
+      OMC_ASSERT_MSG(0, "Can't find the item in this set");
+    }
+
+   
+
+    template<typename type>
+    inline void
+    SetOf<type>::ClearAndDelete()
+    {
+      DeleteAllItem();
+      SetOfBase<type>::set_.clear();
+    }
+
+    template<typename type>
+    inline void
+     SetOf<type>::DeleteAllItem()
+    {
+      typename std::list<type *>::iterator it;
+      while(SetOfBase<type>::GetTotItemNumber() > 0)
+       {
+	 const unsigned int size = SetOfBase<type>::GetTotItemNumber();
+	 it=SetOfBase<type>::set_.begin();
+	 delete (*it);
+	 OMC_ASSERT_MSG(SetOfBase<type>::GetTotItemNumber() < size, "Problem while set deletion");
+       }
+    }
+
+
+
+    template<typename type>
+    inline void 
+    SetOf<type>::CheckForDoublet()
+    {
+      checkForDoublet_ = true;
+    }
+
+    template<typename type>
+    inline void 
+    SetOf<type>::UnCheckForDoublet()
+    {
+      checkForDoublet_ = false;
+    }
+
+
+    template<typename type>
+    inline  bool
+    SetOf<type>::IsGlobalSet() const
+    {
+      return (this == &SetOf<type>::GetGlobalSet());
+    }
+
+    // ** Definition of AutoRegister class ** 
+    template<class T> 
+    inline SetOf<T>&
+    AutoRegister<T>::GetGlobalSet()
+    {
+      return SetOf<T>::GetGlobalSet();
+    }
+    
+
+    template<class T>
+    inline bool
+    AutoRegister<T>::Exist(T& item)
+    {
+      return GetGlobalSet().Contain(item);
+    }
+
+    template<class T>
+    inline void
+    AutoRegister<T>::Debug()
+    {
+      std::cout << "---- AutoRegister<T>::Debug() ----" << std::endl;
+      std::cout << " container adress :" << &GetGlobalSet() << std::endl;
+      typename Core::SetOf<T>::it it;
+      for (it = GetGlobalSet().Begin() ; it != GetGlobalSet().End(); it++ )
+	std::cout << "Contain, " << (*it)->GetName() << std::endl;
+      std::cout << "---- ------------------------ ----" << std::endl;
+    }
+
+    template<class T>
+    inline
+    AutoRegister<T>::AutoRegister()
+    {
+      GetGlobalSet().AddItem(*static_cast<T*>(this));
+    }
+
+
+    template<class T>
+    inline
+    AutoRegister<T>::~AutoRegister()
+    {
+      typename std::list<SetOf<T>*>::iterator it;
+      while (allSet_.size() > 0)
+	{
+	  unsigned int size = allSet_.size();
+	  (*allSet_.begin())->RemoveItem(*static_cast<T*>(this));
+	  OMC_ASSERT_MSG(allSet_.size() == size-1, "The item was not registered");
+	}
+      OMC_ASSERT_MSG(GetGlobalSet().Contain(static_cast<T*>(this))==false,
+		 "The item was not registered");
+    }
+
+    template<class T>
+    inline void 
+    AutoRegister<T>::AddSet(SetOf<T>& set)
+    {
+      allSet_.push_back(&set);
+    }
+    
+    template<class T>
+    inline void 
+    AutoRegister<T>::RemoveSet(SetOf<T>& set)
+    {
+      typename std::list<SetOf<T>*>::iterator it;
+      for ( it=allSet_.begin() ; it != allSet_.end(); it++ )
+	{
+	  if ((*it)==&set)
+	    {
+	      allSet_.erase(it); 
+	      return;
+	    }
+	}
+      
+      OMC_ASSERT_MSG(0, "Can't find a set that registers this item");
+    }
+    
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/SetOfBase.cpp b/SRC/OpenMeca/Core/SetOfBase.cpp
new file mode 100644
index 0000000..b310a4b
--- /dev/null
+++ b/SRC/OpenMeca/Core/SetOfBase.cpp
@@ -0,0 +1,29 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Core/SetOfBase.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {    
+  }
+}
+
diff --git a/SRC/OpenMeca/Core/SetOfBase.hpp b/SRC/OpenMeca/Core/SetOfBase.hpp
new file mode 100644
index 0000000..23d1e73
--- /dev/null
+++ b/SRC/OpenMeca/Core/SetOfBase.hpp
@@ -0,0 +1,286 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_SetOfBase_hpp
+#define OpenMeca_Core_SetOfBase_hpp
+
+
+
+#include <list>
+#include <iostream>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "Serialization/list.hpp"
+
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Base class for openmeca's smart container
+    template<typename type>
+    class SetOfBase
+    {
+    public:
+      static SetOfBase<type>& GetGlobalSet();
+      typedef typename std::list<type *>::iterator it;
+      typedef typename std::list<type *>::const_iterator const_it;
+
+    public:
+
+      SetOfBase();
+      SetOfBase(const SetOfBase &);
+      SetOfBase& operator=(const SetOfBase &);
+      type& operator()(unsigned int);
+      const type& operator()(unsigned int) const;
+
+      virtual ~SetOfBase();
+
+      it Begin();
+      it End();
+
+      const_it Begin() const;
+      const_it End() const;
+
+      unsigned int GetTotItemNumber() const;
+
+      void Clear();
+
+      virtual void AddItem(type&);
+      virtual void RemoveItem(type&);
+      virtual void ClearAndDelete();
+      //unsigned int GetRank (type *) const;
+      unsigned int GetRank (const type *) const;
+      bool Contain(type *) const;
+      bool Contain(type &) const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+      
+    protected:
+      std::list<type *>  set_;
+    };
+
+    
+    template<typename type> 
+    template<class Archive>
+    inline void
+    SetOfBase<type>::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(set_);
+    }
+
+      
+    template<typename type> 
+    inline
+    SetOfBase<type>::~SetOfBase()
+    {
+    }
+
+    
+    template<typename type> 
+    inline
+    SetOfBase<type>::SetOfBase(const SetOfBase &set)
+      : set_(set.set_)
+    {
+    }
+    
+    template<typename type> 
+    inline SetOfBase<type>& 
+    SetOfBase<type>::operator=(const SetOfBase &set)
+    {
+      Clear();
+      typename std::list<type *>::const_iterator it;
+      for (it=set.Begin() ; it != set.End(); it++ )
+	AddItem(**it);
+      return *this;
+    }
+
+
+    template<typename type> 
+    inline type& 
+    SetOfBase<type>::operator()(unsigned int i)
+    {
+      unsigned int index = 0;
+      OMC_ASSERT_MSG(i < GetTotItemNumber(), 
+		 "Can't access to an index superior to the number of item");
+      typename std::list<type *>::iterator it;
+      for (it=set_.begin() ; it != set_.end(); it++ )
+	{
+	  if (index == i)
+	    return **it;
+	  index++;
+	} 
+      OMC_ASSERT_MSG(0, "Can't find the required item");      
+      return (**(Begin()));
+    }
+
+    template<typename type> 
+    inline const type& 
+    SetOfBase<type>::operator()(unsigned int i) const
+    {
+      unsigned int index = 0;
+      OMC_ASSERT_MSG(i < GetTotItemNumber(), 
+		 "Can't access to an index superior to the number of item");
+      typename std::list<type *>::const_iterator it;
+      for (it=set_.begin() ; it != set_.end(); it++ )
+	{
+	  if (index == i)
+	    return **it;
+	  index++;
+	} 
+      OMC_ASSERT_MSG(0, "Can't find the required item");      
+      return (**(Begin()));
+    }
+
+
+    template<typename type> 
+    inline 
+    SetOfBase<type>::SetOfBase()
+      :set_()
+					  
+    {
+    }
+    
+    template<typename type> 
+    inline typename SetOfBase<type>::it 
+    SetOfBase<type>::Begin()
+    {
+      return set_.begin();
+    }
+
+    template<typename type> 
+    inline typename SetOfBase<type>::it 
+    SetOfBase<type>::End()
+    {
+      return set_.end();
+    }
+
+    template<typename type> 
+    inline typename SetOfBase<type>::const_it 
+    SetOfBase<type>::Begin() const
+    {
+      return set_.begin();
+    }
+
+    template<typename type> 
+    inline typename SetOfBase<type>::const_it 
+    SetOfBase<type>::End() const
+    {
+      return set_.end();
+    }
+
+    
+    template<typename type> 
+    inline unsigned int 
+    SetOfBase<type>::GetTotItemNumber() const
+    {
+      return set_.size();
+    }
+        
+    template<typename type>
+    inline void
+    SetOfBase<type>::AddItem(type& item)
+    {
+      set_.push_back(&item);
+    }
+    
+
+    template<typename type>
+    inline void
+    SetOfBase<type>::RemoveItem(type& item)
+    {
+      typename std::list<type *>::iterator it;
+      for ( it=set_.begin() ; it != set_.end(); it++ )
+	{
+	  if (*it==&item)
+	    {
+	      set_.erase(it);
+	      return;
+	    }
+	}
+      OMC_ASSERT_MSG(0, "Can't find the required item to remove");      
+    }
+
+   
+    template<typename type>
+    inline void
+    SetOfBase<type>::Clear()
+    {
+      set_.clear();
+    }
+
+    template<typename type>
+    inline void
+    SetOfBase<type>::ClearAndDelete()
+    {
+      typename std::list<type *>::const_iterator it;
+      for ( it=set_.begin() ; it != set_.end(); it++ )
+	{
+	  delete (*it);
+	}
+      set_.clear();
+    }
+
+    template<typename type>
+    inline unsigned int
+    SetOfBase<type>::GetRank(const type * item) const
+    {
+      for (unsigned int i=0; i<GetTotItemNumber(); ++i)
+	{
+	  if (set_[i]==item)
+	    {
+	      return i;
+	    }
+	}
+      OMC_ASSERT_MSG(0, "Can't find the required item to get rank");      
+      return  0;
+    }
+
+    template<typename type>
+    inline bool 
+    SetOfBase<type>::Contain(type* item) const
+    {
+      typename std::list<type *>::const_iterator it;
+      for ( it=set_.begin() ; it != set_.end(); it++ )
+	{
+	  if ((*it) == item)
+	    return true;
+	}
+      return  false;
+    }
+
+     template<typename type>
+    inline bool 
+    SetOfBase<type>::Contain(type& item) const
+    {
+      return Contain(&item);
+    }
+
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Core/Singleton.hpp b/SRC/OpenMeca/Core/Singleton.hpp
new file mode 100644
index 0000000..eb9d897
--- /dev/null
+++ b/SRC/OpenMeca/Core/Singleton.hpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#ifndef OpenMeca_Core_Singleton_hpp
+#define OpenMeca_Core_Singleton_hpp
+
+#include <type_traits>
+
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    // The famous singleton design pattern
+    template <typename T>
+    class Singleton
+    {
+    protected:
+      Singleton();
+      virtual ~Singleton();
+      
+    public:
+      static T &Get();  
+      static bool Instanciate();
+
+    private:
+      static T* me_;
+      static unsigned int instanceNumber_;
+      
+    };
+    
+    template<class T> T* Singleton<T>::me_ = 0;
+    template<class T> unsigned int Singleton<T>::instanceNumber_ = 0;
+
+    template<class T>
+    inline
+    Singleton<T>::Singleton()
+    {
+      instanceNumber_++;
+      me_ = static_cast<T*>(this);
+      OMC_ASSERT_MSG(instanceNumber_ == 1, "The number of singleton instance is superior to 1");
+    }
+
+    template<class T>
+    inline
+    Singleton<T>::~Singleton()
+    {
+    }
+    
+
+
+    template<class T>
+    inline T&
+    Singleton<T>::Get()
+    {
+      static_assert((std::is_base_of<Singleton<T>, T>::value),
+		    "T must be a descendant of Singleton");
+      if (me_ == 0)
+	new T;
+      return *me_;
+    }
+    
+    template<class T>
+    inline bool
+    Singleton<T>::Instanciate()
+    {
+      if (me_ == 0)
+	{
+	  new T;
+	  return true;
+	}
+      return false;
+    }
+    
+    
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/Software.cpp b/SRC/OpenMeca/Core/Software.cpp
new file mode 100644
index 0000000..c634808
--- /dev/null
+++ b/SRC/OpenMeca/Core/Software.cpp
@@ -0,0 +1,152 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QFile>
+#include <QTextStream>
+#include <QString>
+#include <QStringList>
+
+#include "OpenMeca/Core/Software.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Core
+  {
+
+    Software* Software::me_ = 0;
+
+    Software& 
+    Software::Get()
+    {
+      if (me_==0)
+    	me_ = new Software();
+      return *me_;
+    }
+
+
+      Software::Software()
+      : fileInfo_(":/Info.txt"),
+	info_(),
+	version_()
+    {
+      ReadInfo();
+      version_ = Util::Version(GetInfoField("Version"));
+    }
+
+    
+   const Util::Version& 
+   Software::Version() const
+   {
+     return version_;
+   }
+
+    
+
+    QString
+    Software::HtmlText() const
+    {
+      QString info;
+      std::map<const std::string, std::string>::const_iterator it;
+
+      info += "<table>";
+      for (it=info_.begin(); it!=info_.end(); ++it)
+	{
+	  info +="<tr>";
+	  info += "<td><i>" + QObject::tr(it->first.c_str()) + "</i></td>";
+	  info += "<td>" + QString(it->second.c_str()) + "</td>";
+	  info +="</tr>";
+	}
+      return info;
+    }
+
+    std::string 
+    Software::GetInfoField(const std::string& key) const
+    {
+      OMC_ASSERT_MSG(info_.count(key)==1, "Problem while accessing software info file, the key does not exist");
+      return info_.at(key);
+    }
+
+    
+    void
+    Software::ReadInfo()
+    {
+      QFile file(fileInfo_.c_str());
+      if(!file.open(QIODevice::ReadOnly))
+	{
+	  OMC_ASSERT_MSG(0, "Can't read the sofware file info");
+	}
+      QTextStream in(&file);
+
+      while(!in.atEnd())
+	{
+	  QString line = in.readLine();    
+	  QStringList fields = line.split(":");
+	  OMC_ASSERT_MSG(fields.count()==2, "Problem while reading software info file");
+	  fields.first().replace(" ","");
+	  const std::string key   = (fields.first()).toStdString();
+	  const std::string value = (fields.last()).toStdString();
+
+	  OMC_ASSERT_MSG(info_.count(key)==0, "Problem while reading software info file, the key value is already used");
+	  info_[key] = value;
+	}
+    }
+
+
+      void 
+      Software::FakeTranslate()
+      {
+	// It's just to force translation of some keywords...
+
+	// Keyword inside xml menumanager file
+	QObject::tr("Geometry");
+	QObject::tr("Cosmetic");
+	QObject::tr("Loading");
+	QObject::tr("Plot data...");
+	QObject::tr("Save data...");
+	QObject::tr("Help");
+	QObject::tr("About...");
+	QObject::tr("Help...");
+	QObject::tr("3D viewer help...");
+	
+	// Keyword inside the info.txt file
+	QObject::tr("Author(s)");
+	QObject::tr("Version");
+	QObject::tr("Licence");
+	QObject::tr("Contact");
+	QObject::tr("Project");
+
+	// Example keyword
+	QObject::tr("gears");
+	QObject::tr("gyroscope");
+	QObject::tr("reprap");
+	QObject::tr("robot");
+	QObject::tr("screw");
+	QObject::tr("steering");
+	QObject::tr("cranck-shaft");		
+      }
+
+  }
+}
+
+
+
+
+
diff --git a/SRC/OpenMeca/Core/Software.hpp b/SRC/OpenMeca/Core/Software.hpp
new file mode 100644
index 0000000..9210050
--- /dev/null
+++ b/SRC/OpenMeca/Core/Software.hpp
@@ -0,0 +1,72 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Software_hpp
+#define OpenMeca_Core_Software_hpp
+
+
+#include <string>
+#include <map>
+
+#include "OpenMeca/Util/Version.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    class Software
+    {
+    public:
+      static Software& Get();
+
+
+    public:
+      ~Software();
+      void FakeTranslate();
+      QString HtmlText() const;
+      std::string GetInfoField(const std::string&) const;
+      const Util::Version& Version() const;
+
+    private :
+      Software();                          
+      Software(const Software&);             //Not Allowed
+      Software& operator=(const Software&);  //Not Allowed
+      
+      void ReadInfo();
+      
+
+    private :
+      static Software* me_;
+
+    private:
+      std::string fileInfo_;
+      std::string rawContentInfofile_;
+      std::map<const std::string, std::string> info_;
+      Util::Version version_;
+  
+    }; 
+    
+
+
+  
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/System.cpp b/SRC/OpenMeca/Core/System.cpp
new file mode 100755
index 0000000..ec5b4b5
--- /dev/null
+++ b/SRC/OpenMeca/Core/System.cpp
@@ -0,0 +1,382 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+#include <fstream>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Util/Var.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Item/PartLinkT.hpp"
+#include "OpenMeca/Item/PartUserPoint.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Software.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Core
+  {
+
+    //************** Static member and attributes *************************
+    System* System::activeSystem_ = 0;
+
+    bool System::deleted_ = false;
+
+    chrono::ChSystem* System::chSystem_ = 0;
+  
+    const float System::Version = 2.0; 
+
+    bool
+    System::IsDeleted()
+    {
+      return deleted_;
+    }
+
+
+    System& 
+    System::Get()
+    {
+      OMC_ASSERT_MSG(IsDeleted() == false, "The system is deleted");
+      if (activeSystem_==0)
+    	activeSystem_ = new System();
+      return *activeSystem_;
+    }
+
+    void
+    System::Quit()
+    {
+      delete &System::Get();
+      System::deleted_ = true;
+    }
+
+
+  
+    //************** Constructors and Destructors *************************
+    System::System()
+      :version_("2.0"), 
+       historic_(*this), 
+       enableDrawing_(true),
+       time_(0.)
+    {
+    }
+
+    System::~System()
+    {
+      GetSetOf<UserRootItem>().DeleteAllItem();
+      GetSetOf<SystemSetting>().DeleteAllItem();
+    }
+    
+    void 
+    System::DisableDrawing()
+    {
+      enableDrawing_ = false;
+    }
+
+    void 
+    System::EnableDrawing()
+    {
+      enableDrawing_ = true;
+    }
+
+    
+
+    bool
+    System::IsEdited()
+    {
+      return historic_.IsSystemEdited();
+    }
+
+    void
+    System::Update()
+    {
+      Util::Expr::UpdateAll();
+      {
+	Core::SetOf<UserRootItem>::it it;
+	Core::SetOf<UserRootItem>& set = GetSetOf<UserRootItem>();
+	for (it = set.Begin() ; it != set.End(); it++ )
+	  (*it)->Update();
+      }
+
+
+      {
+	Core::SetOf<SystemSetting>::it it;
+	Core::SetOf<SystemSetting>& set = GetSetOf<SystemSetting>();
+	for (it = set.Begin() ; it != set.End(); it++ )
+	  (*it)->Update();
+      }
+
+      Gui::MainWindow::Get().GetViewer().updateGL(); 
+    }
+
+    HistoricManager& 
+    System::GetHistoric()
+    {
+      return historic_;
+    }
+    
+
+    const HistoricManager& 
+    System::GetHistoric() const
+    {
+      return historic_;
+    }
+    
+
+
+    void
+    System::Save(std::string& str)
+    {
+      std::stringstream ss;
+      boost::archive::text_oarchive oa(ss);
+      oa << *this; 
+      str = ss.str();
+    }
+    
+
+    void
+    System::Load(const std::string& str)
+    {      
+      Reset();
+      std::stringstream ss;
+      ss << str;
+      boost::archive::text_iarchive ia(ss);
+      ia >> *this;
+    }
+
+
+    void
+    System::SaveFile(const std::string& str)
+    {
+      std::ofstream ofs(str.c_str());
+      if (!ofs.is_open())
+	{
+	  QString msg = QObject::tr("Can't save file") + " \"";
+	  msg += QString(str.c_str()) + "\"";
+	  OMC_WARNING_MSG(msg);
+	  return;
+	}
+
+      boost::archive::text_oarchive oa(ofs);
+      oa << *this;
+      historic_.UserSave();
+    }
+    
+    void
+    System::LoadFile(const std::string& str)
+    {    
+      Reset();
+      std::ifstream ifs(str.c_str());
+      if (!ifs.is_open())
+	{
+	  QString msg = QObject::tr("Can't open file") + " \"";
+	  msg += QString(str.c_str()) + "\"";
+	  OMC_WARNING_MSG(msg);
+	  return;
+	}
+      boost::archive::text_iarchive ia(ifs);
+      ia >> *this;
+      historic_.Reset();
+      Update();
+    }
+
+    void
+    System::Reset()
+    {
+      Singleton<SelectionManager>::Get().SetNoItemSelected();
+      GetSetOf<UserRootItem>().ClearAndDelete();
+      OMC_ASSERT_MSG(GetSetOf<UserRootItem>().GetTotItemNumber() == 0,
+		 "The user root item set must be empty after system reset");
+      OMC_ASSERT_MSG(GetSetOf<UserItem>().GetTotItemNumber() == 0,
+		 "The user item set must be empty after system reset");
+    }
+
+    void
+    System::Draw() const
+    {
+      if (enableDrawing_)
+	{
+	  SetOf<Drawable>::const_it it;
+	  for (it=GetSetOf<Drawable>().Begin() ; it != GetSetOf<Drawable>().End(); it++ )
+	    (*it)->Draw();
+
+	  typedef OpenMeca::Item::Body Body;
+	  SetOf<Body>::const_it it_body;
+	  for (it_body=GetSetOf<Body>().Begin() ; it_body != GetSetOf<Body>().End(); it_body++ )
+	    (*it_body)->Draw();
+	}
+
+      
+    }
+
+    void
+    System::DrawWithNames() const
+    {
+      if (enableDrawing_)
+	{
+	  SetOf<Drawable>::const_it it;
+	  for (it=GetSetOf<Drawable>().Begin() ; it != GetSetOf<Drawable>().End(); it++ )
+	    (*it)->Draw(true);
+	}
+    }
+    
+
+
+    std::string
+    System::GetAutomaticName(const std::string& childTypeStr) const
+    {
+      int maxNumber = 0;
+      SetOf<UserItem>::const_it it;
+      for (it=GetSetOf<UserItem>().Begin() ; it != GetSetOf<UserItem>().End(); it++ )
+	{
+	  std::size_t size = (*it)->GetName().find(childTypeStr);
+	  if (size != std::string::npos)
+	    {
+	      if ((*it)->GetName().size() >= childTypeStr.size() + 2)
+		{
+		  std::string copy = (*it)->GetName();
+		  copy.erase(0, childTypeStr.size() + 1);
+		  int num = atoi (copy.c_str());
+		  if (num > maxNumber)
+		    maxNumber = num;
+		}
+	    }
+	}
+      maxNumber++;
+      return childTypeStr + '_' + std::to_string(maxNumber);
+    }
+
+    OpenMeca::Setting::Scales& 
+    System::GetScales()
+    {
+      return SystemSettingT<OpenMeca::Setting::Scales>::Get();
+    }
+    
+    const OpenMeca::Setting::Scales& 
+    System::GetScales () const
+    {
+      return SystemSettingT<OpenMeca::Setting::Scales>::Get();
+    }
+
+    chrono::ChSystem& 
+    System::GetChSystem()
+    {
+      if (chSystem_ == 0)
+	chSystem_ = new chrono::ChSystem();
+      return *chSystem_;
+    }
+
+
+    void 
+    System::BuildChSystem()
+    {
+      chrono::ChSystem& chSystem = GetChSystem();
+      chSystem.Clear();
+
+      Core::SetOf<Item>::it it;
+      
+      for (it = GetSetOf<Item>().Begin() ; it != GetSetOf<Item>().End(); it++ )
+	(*it)->InitChSystem(chSystem);
+      
+      for (it = GetSetOf<Item>().Begin() ; it != GetSetOf<Item>().End(); it++ )
+	(*it)->BuildChSystem(chSystem);
+
+      time_ = 0.;
+      
+    }
+
+    void 
+    System::UpdateValueFromCh()
+    {
+      Core::SetOf<UserItem>::it it;
+      for (it = GetSetOf<UserItem>().Begin() ; it != GetSetOf<UserItem>().End(); it++ )
+	(*it)->UpdateValueFromCh();
+
+      time_ = GetChSystem().GetChTime();
+    }
+
+    void 
+    System::SaveState()
+    {
+      Core::SetOf<UserItem>::it it;
+      for (it = GetSetOf<UserItem>().Begin() ; it != GetSetOf<UserItem>().End(); it++ )
+	(*it)->SaveState();
+    }
+
+    void 
+    System::ResetState()
+    {
+      Core::SetOf<UserItem>::it it;
+      for (it = GetSetOf<UserItem>().Begin() ; it != GetSetOf<UserItem>().End(); it++ )
+	(*it)->ResetState();      
+    }
+    
+    void 
+    System::RecoveryState(unsigned int i)
+    {
+      Core::SetOf<UserItem>::it it;
+      for (it = GetSetOf<UserItem>().Begin() ; it != GetSetOf<UserItem>().End(); it++ )
+	(*it)->RecoveryState(i);
+    }
+
+
+    void
+    System::ManageLoadedFileVersion(const Util::Version& archiveVersion)
+    {
+      if ((GetSoftwareVersion() == archiveVersion) == false)
+	{
+	  OMC_ASSERT_MSG(GetSoftwareVersion() > archiveVersion,
+			 "the file version must be lower than the system version");
+	}
+
+      // Display message or not ? The answer is no !!!
+      // if (archiveVersion < GetSoftwareVersion())
+      // 	{
+      // 	  QString text = QObject::tr("You are loading a file created with an") + " ";
+      // 	  text += QObject::tr("older version of openmeca") + ".\n";
+
+      // 	  text += QObject::tr("Note that your file version is") + " ";
+      // 	  text += QString(archiveVersion.ToString().c_str()) + " ";
+      // 	  text += QObject::tr("and the software version is") + " ";
+      // 	  text += QString(GetSoftwareVersion().ToString().c_str());
+      // 	  text += ".";
+      // 	  OMC_INFO_MSG(text);
+      // 	}
+    }
+
+    const Util::Version& 
+    System::GetSoftwareVersion() const
+    {
+      return Core::Software::Get().Version();
+    }
+
+
+  }
+}
+
+
+
+
+
diff --git a/SRC/OpenMeca/Core/System.hpp b/SRC/OpenMeca/Core/System.hpp
new file mode 100755
index 0000000..9a0203c
--- /dev/null
+++ b/SRC/OpenMeca/Core/System.hpp
@@ -0,0 +1,173 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_System_hpp
+#define OpenMeca_Core_System_hpp
+
+#include <sstream>
+#include <vector>
+
+
+#include "OpenMeca/Core/SetOf.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/HistoricManager.hpp"
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Util/Version.hpp"
+#include "OpenMeca/Util/Var.hpp"
+#include "OpenMeca/Setting/Scales.hpp"
+
+#include "ChronoEngine/physics/ChSystem.h"
+
+
+namespace OpenMeca
+{
+
+  namespace Core
+  {
+    class UserItem;
+    class UserRootItem;
+
+    
+    // The System class is the openmeca's meastro class. 
+    // All the item are registered by the system class.
+    // The undo/redo is obtained by serialization/deserialization of the system.
+    class System
+    {
+    public:
+      static System& Get();
+      static void Quit();
+      static bool IsDeleted();
+      static const float Version; 
+
+      ~System();
+   
+      template<class T> SetOf<T>& GetSetOf();
+      template<class T> const SetOf<T>& GetSetOf() const;
+
+      bool IsEdited();
+      void Update();
+      std::string GetAutomaticName(const std::string&) const;
+      void SaveFile(const std::string&);
+      void LoadFile(const std::string&);
+      void Reset();
+      HistoricManager& GetHistoric();
+      const HistoricManager& GetHistoric() const;
+      void Save(std::string&);
+      void Load(const std::string&);
+      void Draw() const;
+      void DrawWithNames() const;
+
+      OpenMeca::Setting::Scales& GetScales();
+      const OpenMeca::Setting::Scales& GetScales() const;
+
+      void BuildChSystem();
+      void UpdateValueFromCh();
+      chrono::ChSystem& GetChSystem();
+      
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+      
+      void DisableDrawing();
+      void EnableDrawing();
+
+      const Util::Version& GetSoftwareVersion() const;
+
+      OMC_ACCESSOR(Time   , double   , time_);
+
+    private :
+      System();                          //Not Allowed
+      System(const System&);             //Not Allowed
+      System& operator=(const System&);  //Not Allowed
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive & ar, const unsigned int) const;
+      template<class Archive> void load(Archive & ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER() 
+      
+      void ManageLoadedFileVersion(const Util::Version& archiveVersion);
+
+    private :
+      static System* activeSystem_;
+      static bool deleted_;
+      static chrono::ChSystem* chSystem_;
+
+    private :
+      const std::string version_;
+      HistoricManager historic_; //Always at the end !
+      bool enableDrawing_;
+      double time_;
+    }; 
+    
+    
+    
+
+    template<class Archive>
+    inline void
+    System::save(Archive & ar, const unsigned int version) const
+    {
+      
+      ar << GetSoftwareVersion(); 
+      ar << GetSetOf<UserItem>();
+
+      SystemSetting::SaveAll(ar, version);
+    }
+
+    template<class Archive>
+    inline void
+    System::load(Archive & ar, const unsigned int version)
+    {
+      Util::Version archiveVersion = GetSoftwareVersion();
+      if (version == 0)
+	{
+	  float fileVersion = 0.;
+	  ar >> fileVersion; 
+	}
+      if (version >= 1)
+	ar >> archiveVersion; 
+
+      ManageLoadedFileVersion(archiveVersion);
+
+      ar >> GetSetOf<UserItem>();
+      SystemSetting::LoadAll(ar, version);
+    }
+
+    template<class T>  
+    inline SetOf<T>&
+    System::GetSetOf()
+    {
+      return AutoRegister<T>::GetGlobalSet();
+    }
+
+    template<class T>  
+    inline const SetOf<T>&
+    System::GetSetOf() const
+    {
+      return AutoRegister<T>::GetGlobalSet();
+    }
+
+  
+  }
+}
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Core::System, 2)
+
+#endif
diff --git a/SRC/OpenMeca/Core/SystemSetting.cpp b/SRC/OpenMeca/Core/SystemSetting.cpp
new file mode 100644
index 0000000..6ef4826
--- /dev/null
+++ b/SRC/OpenMeca/Core/SystemSetting.cpp
@@ -0,0 +1,125 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Core/SystemSetting.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+
+
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    QTreeWidgetItem* SystemSetting::rootTreeWidgetItem_ = 0;
+    
+    std::map<const std::string, SystemSetting*> SystemSetting::instances_ = 
+      std::map<const std::string, SystemSetting*>();
+
+    void 
+    SystemSetting::SaveAll(boost::archive::text_oarchive& ar, const unsigned int version)
+    {
+      const unsigned int instanceNumber = instances_.size();
+      ar << instanceNumber;
+      
+      std::map<const std::string, SystemSetting*>::iterator it;
+      for (it=instances_.begin(); it!=instances_.end(); ++it)
+	{
+	  const std::string key = it->first;
+	  ar << key;
+	  it->second->Save(ar, version);
+	}
+    }
+    
+    void 
+    SystemSetting::LoadAll(boost::archive::text_iarchive& ar, const unsigned int version)
+    {
+      unsigned int instanceNumber = 0;
+      ar >> instanceNumber;
+      OMC_ASSERT_MSG(instanceNumber > 0,
+		 "It's impossible that the number of instance equal zero");
+      
+      for (unsigned int i=0; i < instanceNumber; ++i)
+	{
+	  std::string key = "";
+	  ar >> key;
+	  OMC_ASSERT_MSG(key != "", "The key can't be null");
+	  OMC_ASSERT_MSG(instances_.count(key) == 1, "The key " + key + " is not registered");
+	  instances_[key]->Load(ar, version);
+	}
+    }
+    
+    const std::string
+    SystemSetting::GetStrType()
+    {
+      return "System";
+    }
+
+
+    const QString
+    SystemSetting::GetQStrType()
+    {
+      return QObject::tr("System");
+    }
+
+    QTreeWidgetItem& 
+    SystemSetting::GetRootTreeWidgetItem()
+    {
+      if (rootTreeWidgetItem_ == 0)
+	{
+	  rootTreeWidgetItem_ = new QTreeWidgetItem(&(Gui::MainWindow::Get().GetTreeView()));
+	  QIcon icon = Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/" + QString(SystemSetting::GetStrType().c_str()) + ".svg");
+	  rootTreeWidgetItem_->setIcon(0, icon);
+	  rootTreeWidgetItem_->setText(0, GetQStrType());
+	}
+      return *rootTreeWidgetItem_;
+    }
+    
+    SystemSetting::SystemSetting(const std::string strType)
+      :Item(strType, &GetRootTreeWidgetItem()),
+       strChildType_(strType)
+    {
+      OMC_ASSERT_MSG(instances_.count(strType) == 0,
+		 "The instance is already registered");
+      instances_[strType] = this;
+    }
+
+    
+    SystemSetting::~SystemSetting()
+    {
+      instances_.erase(instances_.find(strChildType_)); 
+    }
+    
+    void 
+    SystemSetting::Update()
+    {
+    }
+
+
+
+  }
+}
+ 
+
diff --git a/SRC/OpenMeca/Core/SystemSetting.hpp b/SRC/OpenMeca/Core/SystemSetting.hpp
new file mode 100644
index 0000000..8bc0e2e
--- /dev/null
+++ b/SRC/OpenMeca/Core/SystemSetting.hpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_SystemSetting_hpp
+#define OpenMeca_Core_SystemSetting_hpp
+
+
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/Item.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    
+    // Base class for the system setting classes like simulation settings, scales...
+    class SystemSetting : public Item,
+			  public AutoRegister<SystemSetting>
+    {
+
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+      static QTreeWidgetItem& GetRootTreeWidgetItem();
+      static void SaveAll(boost::archive::text_oarchive& ar, const unsigned int);
+      static void LoadAll(boost::archive::text_iarchive& ar, const unsigned int);
+    
+
+    public:    
+      SystemSetting(const std::string strType);
+      virtual ~SystemSetting();
+
+      virtual void Update();
+      virtual void Save(boost::archive::text_oarchive&, const unsigned int) = 0;
+      virtual void Load(boost::archive::text_iarchive&, const unsigned int) = 0;
+
+    private:
+      SystemSetting();
+      SystemSetting(const SystemSetting&);            //Not Allowed    
+      SystemSetting& operator=(const SystemSetting&); //Not Allowed
+
+
+    private:
+      static QTreeWidgetItem* rootTreeWidgetItem_;
+      static std::map<const std::string, SystemSetting*> instances_;
+
+    private:
+      const std::string strChildType_;
+
+    };
+
+  
+
+
+  
+
+  }
+}
+ 
+#endif
diff --git a/SRC/OpenMeca/Core/SystemSettingCommonProperty.hpp b/SRC/OpenMeca/Core/SystemSettingCommonProperty.hpp
new file mode 100644
index 0000000..3e5dffe
--- /dev/null
+++ b/SRC/OpenMeca/Core/SystemSettingCommonProperty.hpp
@@ -0,0 +1,101 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_SystemSettingCommonProperty_hpp
+#define OpenMeca_Core_SystemSettingCommonProperty_hpp
+
+
+#include <QString>
+#include <QIcon>
+
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Core/Action/ActionEditSystemSetting.hpp"
+#include "OpenMeca/Core/Action/ActionWithoutSelection.hpp"
+#include "OpenMeca/Util/Color.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Common property for the classes that inherit from the 'SystemSetting' class
+    template<class T>
+    class SystemSettingCommonProperty : public ItemCommonProperty<T>, 
+					public Singleton< SystemSettingCommonProperty<T> >
+    {
+      friend class Singleton< SystemSettingCommonProperty<T> >;
+
+    public:
+      void RegisterAction();
+      void RegisterAction_Specialized();//Specialize this to add specific item
+      
+
+    protected:
+      SystemSettingCommonProperty();
+      virtual ~SystemSettingCommonProperty();
+    
+    private:
+      SystemSettingCommonProperty(const SystemSettingCommonProperty<T>&);               //Not Allowed    
+      SystemSettingCommonProperty<T>& operator=(const SystemSettingCommonProperty<T>&); //Not Allowed
+
+    
+    };
+
+   
+
+    template<class T>
+    inline  
+    SystemSettingCommonProperty<T>::SystemSettingCommonProperty()
+      :ItemCommonProperty<T>()
+    {
+      
+      
+    }
+    
+    template<class T>
+    inline  
+    SystemSettingCommonProperty<T>::~SystemSettingCommonProperty()
+    {
+      
+    }
+  
+    template<class T>
+    inline void 
+    SystemSettingCommonProperty<T>::RegisterAction()
+    {
+      Action& edit = 
+	*new ActionWithoutSelection<T, ActionEditSystemSetting<T> >();
+      ItemCommonProperty<T>::AddAction(edit);
+      CommonProperty::AddPopUpAction(edit);
+    }
+    
+    template<class T>
+    inline void 
+    SystemSettingCommonProperty<T>::RegisterAction_Specialized() 
+    {
+      
+    }
+  
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/SystemSettingT.hpp b/SRC/OpenMeca/Core/SystemSettingT.hpp
new file mode 100644
index 0000000..836b087
--- /dev/null
+++ b/SRC/OpenMeca/Core/SystemSettingT.hpp
@@ -0,0 +1,134 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_SystemSettingT_hpp
+#define OpenMeca_Core_SystemSettingT_hpp
+
+#include <QFile>
+#include <type_traits>
+
+#include "OpenMeca/Core/SystemSetting.hpp"
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Template class that allows static inheritence
+    template<class T>
+    class SystemSettingT : public SystemSetting
+    {
+
+    public:
+      static const QIcon GetIcon();
+      static const std::string GetStrType();
+      static T& Get();
+
+    public:    
+      SystemSettingT();
+      virtual ~SystemSettingT();
+      
+    private :
+      SystemSettingT(const SystemSettingT&);             //Not Allowed
+      SystemSettingT& operator=(const SystemSettingT&);  //Not Allowed
+
+           // - BOOST SERIALIZATION - //
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive&, const unsigned int) const;
+      template<class Archive> void load(Archive&, const unsigned int); 
+      BOOST_SERIALIZATION_SPLIT_MEMBER()     
+
+    private:
+      static SystemSettingT<T>* me_;
+
+    }; 
+
+    template<class T> SystemSettingT<T>* SystemSettingT<T>::me_ = 0;
+
+    template<class T>
+    template<class Archive>
+    void 
+    SystemSettingT<T>::save(Archive& ar, const unsigned int ) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(SystemSetting);
+    }
+
+    template<class T>
+    template<class Archive>
+    void 
+    SystemSettingT<T>::load(Archive& ar, const unsigned int ) 
+    {
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(SystemSetting);
+      me_ = this;
+    }
+
+    
+
+    template<class T>
+    inline const QIcon
+    SystemSettingT<T>::GetIcon()
+    {
+      const QString file = ":/Rsc/Img/SystemSetting/" + QString(T::GetStrType().c_str()) + ".svg";
+      return Util::Icon::DrawIconFromSvgFile(file);
+    }
+
+    template<class T>
+    inline const std::string 
+    SystemSettingT<T>::GetStrType()
+    {
+      return T::GetStrType();
+    }
+    
+    template<class T>
+    inline T& 
+    SystemSettingT<T>::Get()
+    {
+      BOOST_STATIC_ASSERT_MSG((boost::is_base_of<SystemSettingT<T>, T>::value),
+			      "T must be a descendant of Singleton");
+      if (me_ == 0)
+	new T();
+      OMC_ASSERT_MSG(me_ != 0, "The singleton is not built");
+      return static_cast<T&>(*me_);
+    }
+    
+
+    template<class T>
+    inline
+    SystemSettingT<T>::SystemSettingT()
+      :SystemSetting(T::GetStrType())
+    {
+      Item::icon_ = GetIcon();
+      GetMainTreeItem().setIcon(0, Item::icon_);
+      me_ = this;
+    }
+    
+    template<class T>
+    inline
+    SystemSettingT<T>::~SystemSettingT()
+    {
+      if (me_ == this)
+	me_ = 0;
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Core/UserItem.cpp b/SRC/OpenMeca/Core/UserItem.cpp
new file mode 100644
index 0000000..fc000b8
--- /dev/null
+++ b/SRC/OpenMeca/Core/UserItem.cpp
@@ -0,0 +1,283 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include <iostream>
+#include <QMessageBox>
+
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+
+    UserItem::UserItem(const std::string strType,  QTreeWidgetItem& parent)
+      :Item(strType, &parent),
+       name_(strType),
+       dependentItems_(),
+       parentsItems_()
+    {
+      name_ = System::Get().GetAutomaticName(strType);
+    }
+
+
+    UserItem::~UserItem()
+    {
+      dependentItems_.DeleteAllItem();
+    }
+
+
+
+    void 
+    UserItem::AddChildItem(UserItem& item)
+    {
+      // std::cout << "-- begin --" << std::endl;
+      // std::cout << "  debug, UserItem::AddChildItem, id=" << GetName() << std::endl;
+      // std::cout << "  child item is : " << item.GetName() << std::endl;;
+      
+      // std::cout << "  dependant item contain : " << std::endl;
+      // SetOf<UserItem>& set = dependentItems_;
+      // SetOf<UserItem>::it it;
+      // for (it=set.Begin() ; it != set.End(); it++ )
+      // 	{
+      // 	  std::cout << "    - " << (*it)->GetName() << std::endl;
+      // 	}
+      dependentItems_.AddItem(item);
+      // std::cout << "  now, dependant item contain : " << std::endl;
+      // for (it=set.Begin() ; it != set.End(); it++ )
+      // 	{
+      // 	  std::cout << "    - " << (*it)->GetName() << std::endl;
+      // 	}
+
+      // std::cout << "-- end --" << std::endl;
+    }
+
+    void 
+    UserItem::EraseChildItem(UserItem& item)
+    {
+      // std::cout << "-- begin --" << std::endl;
+      // std::cout << "  debug, UserItem::EraseChildItem, id=" << GetName() << std::endl;
+      // std::cout << "  child item is : " << item.GetName();
+      // std::cout << "  dependant item contain : " << std::endl;
+      // SetOf<UserItem>& set = dependentItems_;
+      // SetOf<UserItem>::it it;
+      // for (it=set.Begin() ; it != set.End(); it++ )
+      // 	std::cout << "    - " << (*it)->GetName() << std::endl;
+
+      dependentItems_.RemoveItem(item);      
+
+      // std::cout << "  now, dependant item contain : " << std::endl;
+      // for (it=set.Begin() ; it != set.End(); it++ )
+      // 	std::cout << "    - " << (*it)->GetName() << std::endl;
+      // std::cout << "-- end --" << std::endl;
+    }
+
+    const SetOf<UserItem>& 
+    UserItem::GetDependentItems() const
+    {
+      return dependentItems_;
+    }
+
+
+    SetOf<UserItem>& 
+    UserItem::GetDependentItems()
+    {
+      return dependentItems_;
+    }
+
+    SetOfBase<UserItem> 
+    UserItem::GetAllDependentItems()
+    {
+      SetOfBase<UserItem> allDependentItems;
+      ConcatenateDependentItems(allDependentItems);
+      return allDependentItems;
+    }
+
+
+    bool
+    UserItem::HasChild(const UserItem& item) const
+    {
+      UserItem& me = const_cast<UserItem&>(*this);
+      const SetOfBase<UserItem> allChild = me.GetAllDependentItems();
+      for (unsigned int i = 0; i < allChild.GetTotItemNumber(); ++i)
+	{
+	  const UserItem& current_item = allChild(i);
+	  if (&current_item == &item)
+	    return true;
+	}
+      return false;
+    }
+
+    void 
+    UserItem::ConcatenateDependentItems(SetOfBase<UserItem>& allDependentItems)
+    {
+      SetOf<UserItem>& set = dependentItems_;
+      SetOf<UserItem>::it it;
+      for (it=set.Begin() ; it != set.End(); it++ )
+	{
+	  if (allDependentItems.Contain(**it) == false)
+	    {
+	      allDependentItems.AddItem(**it);
+	      (*it)->ConcatenateDependentItems(allDependentItems);
+	    }
+	}
+    }
+
+    const std::string&
+    UserItem::GetName() const
+    {
+      return name_;
+    }
+
+    std::string&
+    UserItem::GetName()
+    {
+      return name_;
+    }
+
+    void
+    UserItem::Update()
+    {
+      Item::Update();
+      GetMainTreeItem().setText(0, GetName().c_str());
+      UpdateIcon();
+      GetMainTreeItem().Update();
+      Core::SetOf<UserItem>::it it;
+      for (it = dependentItems_.Begin() ; it != dependentItems_.End(); it++ )
+	{
+	  (*it)->Update();
+	}
+    }
+    
+    void
+    UserItem::ChangeParentTreeItem(QTreeWidgetItem& newparent)
+    {
+      QTreeWidgetItem*  myparent = GetMainTreeItem().parent();
+      
+      if (myparent != &newparent)
+	{
+	  myparent->removeChild(mainTreeItem_);
+	  newparent.addChild(mainTreeItem_);
+	}
+    }
+    
+    void
+    UserItem::Select()
+    {
+      isSelected_ = true;
+
+      SetOfBase<UserItem> set = GetAssociatedSelectedItem();
+      SetOfBase<UserItem>::it it;
+      for (it=set.Begin() ; it != set.End(); it++ )
+	(*it)->Select();
+
+    }
+
+    void
+    UserItem::UnSelect()
+    {
+      isSelected_ = false;
+      SetOfBase<UserItem> set = GetAssociatedSelectedItem();
+      SetOfBase<UserItem>::it it;
+      for (it=set.Begin() ; it != set.End(); it++ )
+	(*it)->UnSelect();
+    }
+
+
+    void
+    UserItem::SetIsSelected(bool val)
+    {
+      isSelected_ = val;
+    }
+
+
+    bool
+    UserItem::IsSelected() const
+    {
+      return isSelected_;
+    }
+
+    SetOfBase<UserItem> 
+    UserItem::GetAssociatedSelectedItem()
+    {
+      return SetOfBase<UserItem>();
+    }
+
+    std::function<const Geom::Frame<_3D>& ()> 
+    UserItem::GetFrameFct() const
+    {
+      const UserItem& me = *this;
+      const Geom::Frame<_3D>&(UserItem::*fnpt)() const = &UserItem::GetFrame;
+      std::function<const Geom::Frame<_3D>& ()> f = std::bind(fnpt, std::ref(me));
+      return f;
+    }
+
+
+      const Geom::Frame<_3D>& 
+      UserItem::GetReferenceFrame() const 
+      {
+	OMC_ASSERT_MSG(0, "This method can not be called from base class"); 
+	return *(Geom::Frame<_3D>*)(0);
+      }
+
+      const Geom::Frame<_3D>& 
+      UserItem::GetFrame() const
+      {
+	OMC_ASSERT_MSG(0, "This method can not be called from base class");
+	return *(Geom::Frame<_3D>*)(0);
+      }
+
+      const Util::Color& 
+      UserItem::GetColor() const 
+      {
+	OMC_ASSERT_MSG(0, "This method can not be called from base class");
+	return *(Util::Color*)(0);
+      }
+
+      Util::Color& 
+      UserItem::GetColor() 
+      {
+	OMC_ASSERT_MSG(0, "This method can not be called from base class");
+	return *(Util::Color*)(0);
+      }
+
+    const OpenMeca::Item::Body& 
+      UserItem::GetBody() const 
+      {
+	OMC_ASSERT_MSG(0, "This method can not be called from base class");
+	return *(OpenMeca::Item::Body*)(0);
+      }
+
+      OpenMeca::Item::Body& 
+      UserItem::GetBody()
+      {
+	OMC_ASSERT_MSG(0, "This method can not be called from base class");
+	return *(OpenMeca::Item::Body*)(0);
+      }
+
+  
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Core/UserItem.hpp b/SRC/OpenMeca/Core/UserItem.hpp
new file mode 100644
index 0000000..8292deb
--- /dev/null
+++ b/SRC/OpenMeca/Core/UserItem.hpp
@@ -0,0 +1,136 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_UserItem_hpp
+#define OpenMeca_Core_UserItem_hpp
+
+#include <string>
+#include <QIcon>
+#include <QTreeWidgetItem>
+#include <functional>
+
+
+#include "OpenMeca/Core/Item.hpp"
+#include "OpenMeca/Core/SetOf.hpp"
+#include "OpenMeca/Gui/SecondaryTreeItem.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+#include "OpenMeca/Util/Color.hpp"
+
+
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class MainTreeItem;
+    class SecondaryTreeItem;
+  }
+
+  namespace Item
+  {
+    class Body;
+  }
+
+
+
+  namespace Core
+  {
+    
+    // The user item base class.
+    // An user item is an item that can be created, deleted, and edited by a user.
+    class UserItem : public Item, public AutoRegister<UserItem>
+    {
+    public:    
+      UserItem(const std::string strType, QTreeWidgetItem& parent);
+      virtual ~UserItem();
+      
+      void AddChildItem(UserItem&);
+      void EraseChildItem(UserItem&);
+
+      const std::string& GetName() const;
+      std::string& GetName();
+      
+      virtual void Update();
+
+      const SetOf<UserItem>& GetDependentItems() const;
+      SetOf<UserItem>& GetDependentItems();
+
+      SetOfBase<UserItem> GetAllDependentItems(); // recursive computation of dependant item
+
+      void ChangeParentTreeItem(QTreeWidgetItem& parent);
+
+      void Select();
+      void UnSelect(); 
+      bool IsSelected() const;
+      void SetIsSelected(bool);
+
+      bool HasChild(const UserItem&) const;
+
+      
+
+      std::function<const Geom::Frame<_3D>& ()> GetFrameFct() const;
+
+      virtual const Geom::Frame<_3D>& GetReferenceFrame() const; // forbidden
+      virtual const Geom::Frame<_3D>& GetFrame() const; // forbidden
+      virtual const Util::Color& GetColor() const; // forbidden
+      virtual Util::Color& GetColor(); // forbidden 
+      virtual const OpenMeca::Item::Body& GetBody() const; // forbidden
+      virtual OpenMeca::Item::Body& GetBody(); // forbidden
+    
+    protected:
+      virtual void UpdateIcon() = 0;
+      virtual SetOfBase<UserItem> GetAssociatedSelectedItem(); //Default return empty set
+      void ConcatenateDependentItems(SetOfBase<UserItem>&);
+
+    private :
+      std::string name_;
+      SetOf<UserItem> dependentItems_;
+      SetOf<UserItem> parentsItems_;
+      
+
+    private :
+      UserItem();                            //Not Allowed
+      UserItem(const UserItem&);             //Not Allowed
+      UserItem& operator=(const UserItem&);  //Not Allowed
+      
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+      
+    }; 
+
+    template<class Archive>
+    inline void
+    UserItem::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Item);
+      ar & BOOST_SERIALIZATION_NVP(name_);
+    }
+
+
+    
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/UserItemCommonProperty.hpp b/SRC/OpenMeca/Core/UserItemCommonProperty.hpp
new file mode 100644
index 0000000..1f50a46
--- /dev/null
+++ b/SRC/OpenMeca/Core/UserItemCommonProperty.hpp
@@ -0,0 +1,175 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_UserItemCommonProperty_hpp
+#define OpenMeca_Core_UserItemCommonProperty_hpp
+
+
+#include <QString>
+#include <QIcon>
+
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Core/Action/ActionNewUserItem.hpp"
+#include "OpenMeca/Core/Action/ActionWithoutSelection.hpp"
+#include "OpenMeca/Core/Action/ActionWithSelectedItemT.hpp"
+#include "OpenMeca/Core/Action/ActionNewUserItemWithSelection.hpp"
+#include "OpenMeca/Core/Action/ActionNewUserItemWithAutomaticSelection.hpp"
+#include "OpenMeca/Core/Action/ActionDeleteUserItem.hpp"
+#include "OpenMeca/Core/Action/ActionEditItem.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Common property for the classes that inherit from the 'UserItem' class
+    // It allows to automatically create the required action like 'new', 'edit' and
+    // to define the user item generic icons, etc...
+    template<class T>
+    class UserItemCommonProperty : public ItemCommonProperty<T>, Singleton< UserItemCommonProperty<T> >
+    {
+      
+      friend class Singleton< UserItemCommonProperty<T> >;
+    
+    public:
+      void CreateAction_New();
+      template <class New> void CreateAction_NewWithSelection(const std::string popUpSubMenuID="");
+      template <class Parent> void CreateAction_NewWithAutomaticSelection();
+
+      void CreateAction_Edit();
+      void CreateAction_Delete();
+      void CreateAction_Specialized();//Specialize this to add specific item
+      void CreateAction_All();
+      void CreateAction_Nothing();
+      void AddPopUpSeparator();
+
+    protected:
+      UserItemCommonProperty();
+      virtual ~UserItemCommonProperty();
+
+    private:
+      UserItemCommonProperty(const UserItemCommonProperty<T>&);               //Not Allowed    
+      UserItemCommonProperty<T>& operator=(const UserItemCommonProperty<T>&); //Not Allowed
+    };
+
+
+    template<class T>
+    inline  
+    UserItemCommonProperty<T>::UserItemCommonProperty()
+      :ItemCommonProperty<T>()
+    {
+    }
+    
+    template<class T>
+    inline  
+    UserItemCommonProperty<T>::~UserItemCommonProperty()
+    {
+     
+    }
+
+    template<class T>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_New()
+    {
+      Action& newAction    = *new ActionWithoutSelection<T, ActionNewUserItem<T> >();
+      CommonProperty::AddAction(newAction);
+    }
+
+    template<class T>
+    template<class Parent>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_NewWithAutomaticSelection()
+    {
+      Action& newAction    = 
+	*new ActionWithoutSelection<T, ActionNewUserItemWithAutomaticSelection<T,Parent> >();
+      CommonProperty::AddAction(newAction);
+    }
+
+
+    template<class T>
+    template<class New>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_NewWithSelection(const std::string popUpSubMenuID)
+    {
+      Action& newAction    = 
+	*new ActionWithSelectedItemT<T, ActionNewUserItemWithSelection<T,New> >();
+      CommonProperty::AddAction(newAction);
+      CommonProperty::AddPopUpAction(newAction, popUpSubMenuID);
+    }
+
+
+    template<class T>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_Edit()
+    {
+       Action& editAction   = 
+	 *new ActionWithSelectedItemT<T, ActionEditItem<T> >();
+      CommonProperty::AddAction(editAction);
+      CommonProperty::AddPopUpAction(editAction);
+    }
+
+    
+    template<class T>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_Delete()
+    {
+      Action& deleteAction = 
+	*new ActionWithSelectedItemT<T, ActionDeleteUserItem<T> >();
+      CommonProperty::AddAction(deleteAction);
+      CommonProperty::AddPopUpAction(deleteAction);
+    }
+
+    
+    template<class T>
+    inline void 
+    UserItemCommonProperty<T>::AddPopUpSeparator()
+    {
+      CommonProperty::AddPopUpSeparator();
+    }
+
+    template<class T>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_Specialized()
+    {
+      
+    }
+  
+    template<class T>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_All()
+    {
+      CreateAction_New();
+      CreateAction_Edit();
+      CreateAction_Delete();
+      CreateAction_Specialized();
+    }
+
+    template<class T>
+    inline void 
+    UserItemCommonProperty<T>::CreateAction_Nothing()
+    {
+    }
+
+  
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/UserRootItem.cpp b/SRC/OpenMeca/Core/UserRootItem.cpp
new file mode 100644
index 0000000..3863ade
--- /dev/null
+++ b/SRC/OpenMeca/Core/UserRootItem.cpp
@@ -0,0 +1,48 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Core/UserRootItem.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    const std::string 
+    UserRootItem::GetStrType()
+    {
+      return "UserRootItem";
+    }
+
+    UserRootItem::UserRootItem(const std::string strType, QTreeWidgetItem& parent)
+      : UserItem(strType, parent)
+    {
+    }
+    
+    UserRootItem::~UserRootItem()
+    {
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Core/UserRootItem.hpp b/SRC/OpenMeca/Core/UserRootItem.hpp
new file mode 100644
index 0000000..9ece650
--- /dev/null
+++ b/SRC/OpenMeca/Core/UserRootItem.hpp
@@ -0,0 +1,64 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_UserRootItem_hpp
+#define OpenMeca_Core_UserRootItem_hpp
+
+
+#include "OpenMeca/Core/UserItem.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    // The user root item base class.
+    // An user root item is an user item that is root in the openmeca hierarchy.
+    // An user root item have not any parent. 
+    // For example, this is a body or a link.
+    class UserRootItem : public UserItem, public AutoRegister<UserRootItem>
+    {
+    public: 
+      static const std::string GetStrType(); 
+
+      UserRootItem(const std::string strType, QTreeWidgetItem& parent);
+      virtual ~UserRootItem();
+
+    private :
+      UserRootItem();                                //Not Allowed
+      UserRootItem(const UserRootItem&);             //Not Allowed
+      UserRootItem& operator=(const UserRootItem&);  //Not Allowed
+      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int)
+      {
+	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(UserItem);
+      }
+
+
+    }; 
+    
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/UserRootItemCommonProperty.hpp b/SRC/OpenMeca/Core/UserRootItemCommonProperty.hpp
new file mode 100644
index 0000000..a49b4c5
--- /dev/null
+++ b/SRC/OpenMeca/Core/UserRootItemCommonProperty.hpp
@@ -0,0 +1,87 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_UserRootItemCommonProperty_hpp
+#define OpenMeca_Core_UserRootItemCommonProperty_hpp
+
+#include <QTreeWidgetItem>
+
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Gui/TreeView.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    // Common property for the classes that inherit from the 'UserRootItem' class
+    template<class T>
+    class UserRootItemCommonProperty : public UserItemCommonProperty<T>, public Singleton< UserRootItemCommonProperty<T> >
+    {
+
+
+      friend class Singleton< UserRootItemCommonProperty<T> >;
+    public:
+      QTreeWidgetItem& GetRootTreeWidgetItem();
+
+
+    protected:
+      UserRootItemCommonProperty();
+      virtual ~UserRootItemCommonProperty();
+    
+    private:
+      QTreeWidgetItem* rootTreeWidgetItem_;
+
+    private:
+      UserRootItemCommonProperty(const UserRootItemCommonProperty<T>&);               //Not Allowed    
+      UserRootItemCommonProperty<T>& operator=(const UserRootItemCommonProperty<T>&); //Not Allowed
+    };
+
+
+    template<class T>
+    inline  
+    UserRootItemCommonProperty<T>::UserRootItemCommonProperty()
+      :UserItemCommonProperty<T>(),
+       rootTreeWidgetItem_(new QTreeWidgetItem(&(Gui::MainWindow::Get().GetTreeView())))
+    {
+      rootTreeWidgetItem_->setIcon(0,ItemCommonProperty<T>::GetIconSymbol());
+      rootTreeWidgetItem_->setText(0,ItemCommonProperty<T>::GetQStrType());
+    }
+    
+    template<class T>
+    inline  
+    UserRootItemCommonProperty<T>::~UserRootItemCommonProperty()
+    {
+     
+    }
+    
+    template<class T>
+    inline  QTreeWidgetItem& 
+    UserRootItemCommonProperty<T>::GetRootTreeWidgetItem()
+    {
+      return *rootTreeWidgetItem_;
+    }
+  
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Core/XmlConfigFile.cpp b/SRC/OpenMeca/Core/XmlConfigFile.cpp
new file mode 100644
index 0000000..c60e140
--- /dev/null
+++ b/SRC/OpenMeca/Core/XmlConfigFile.cpp
@@ -0,0 +1,146 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QTextStream>
+#include <QDebug>
+
+#include "OpenMeca/Core/XmlConfigFile.hpp"
+#include "OpenMeca/Core/ConfigDirectory.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+    std::string 
+    XmlConfigFile::GetDirectoryName()
+    {
+      return std::string("Xml");
+    }
+    
+    std::string 
+    XmlConfigFile::GetSuffix()
+    {
+      return std::string(".xml");
+    }
+
+
+    XmlConfigFile::XmlConfigFile(const std::string name)
+      :ConfigFile(name + GetSuffix(), GetDirectoryName()),
+       name_(name)
+    {
+      CheckFileVersion();
+    }
+
+    XmlConfigFile::~XmlConfigFile()
+    {
+    }
+
+    void 
+    XmlConfigFile::CheckFileVersion()
+    {
+      const Util::Version localVersion = GetLocalFileVersion();
+      const Util::Version softVersion  = GetSoftFileVersion();
+
+      if (localVersion < softVersion)
+	{
+	  QString msg = "";
+	  msg += QObject::tr("The version of your local configuration file \"") + " ";
+	  msg += QString(name_.c_str()) + "\" ";
+	  msg += QObject::tr("is obsolete") + ". ";
+	  msg += QObject::tr("OpenMeca will replace it") + ".";
+	  OMC_INFO_MSG(msg);
+	  RestoreBackup();
+	}
+    }
+
+    Util::Version 
+    XmlConfigFile::GetLocalFileVersion()
+    {
+      QFile& file = ConfigFile::Open();
+      return ReadFileVersion(file, name_);
+    }
+    
+    Util::Version 
+    XmlConfigFile::GetSoftFileVersion()
+    {
+      QFile file(":/Rsc/Xml/" + QString(name_.c_str()) + ".xml");
+      
+      OMC_ASSERT_MSG(file.open(QIODevice::ReadOnly | QIODevice::Text)==true,
+		     "Can't open the \"" + file.fileName().toStdString() + "\" config file because : " + file.errorString().toStdString());
+      
+      Util::Version v = ReadFileVersion(file, name_);
+      return v;
+    }
+
+    void
+    XmlConfigFile::SaveXml(QDomDocument& doc)
+    {
+      QDir dir = GetConfigFileDirectory();
+      const QString filePath = GetAbsPath();
+      if (QFile::exists(filePath)==false)
+	{
+	  file_.setFileName(filePath);
+	  file_.remove();
+	}
+      file_.close();
+      file_.setFileName(filePath);
+      OMC_ASSERT_MSG(file_.open(QIODevice::WriteOnly), "Can't write config file");
+      QTextStream TextStream(&file_);
+      doc.save(TextStream, 0);
+      file_.close();
+    }
+    
+
+    Util::Version 
+    XmlConfigFile::ReadFileVersion(QFile& file, const std::string& xmlTagName)
+    {
+      QDomDocument doc("");
+      QString errorMsg = "";
+      OMC_ASSERT_MSG(doc.setContent(&file, true, &errorMsg), 
+		     "Can't set content of the xml doc " + file.fileName().toStdString() + " error is :" + errorMsg.toStdString());
+      QDomNode n = doc.firstChild();
+      while (!n.isNull()) 
+	{
+	  if (n.isElement()) 
+	    {
+	      QDomElement e = n.toElement();
+	      if (e.tagName()==xmlTagName.c_str())
+		{
+		  if (e.hasAttribute("Version"))
+		    {
+		      const std::string v = e.attribute ("Version").toStdString();
+		      return Util::Version(v);
+		    }
+		}
+	    }
+	  n = n.nextSibling();
+	}
+      return Util::Version("0.0.0");
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Core/XmlConfigFile.hpp b/SRC/OpenMeca/Core/XmlConfigFile.hpp
new file mode 100644
index 0000000..450d3aa
--- /dev/null
+++ b/SRC/OpenMeca/Core/XmlConfigFile.hpp
@@ -0,0 +1,69 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_XmlConfigFile_hpp
+#define OpenMeca_Core_XmlConfigFile_hpp
+
+#include <QDomDocument>
+
+#include "OpenMeca/Core/ConfigFile.hpp"
+#include "OpenMeca/Util/Version.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+
+
+    // Base class that manages Xml config files used to save/load  global settings.
+    class XmlConfigFile : public ConfigFile
+    {
+    
+    public:
+      static std::string GetSuffix(); 
+      
+      XmlConfigFile(const std::string);      
+      ~XmlConfigFile(); 
+
+      void SaveXml(QDomDocument& doc);
+      void CheckFileVersion();
+      Util::Version GetLocalFileVersion();
+      Util::Version GetSoftFileVersion();
+
+
+      
+    private:
+      XmlConfigFile();                                //Not Allowed    
+      XmlConfigFile(const XmlConfigFile&);            //Not Allowed    
+      XmlConfigFile& operator=(const XmlConfigFile&); //Not Allowed
+
+    private:
+      static std::string GetDirectoryName(); 
+      static Util::Version ReadFileVersion(QFile& file, const std::string& xmlTagName);
+
+    private:
+      const std::string name_;
+
+    };
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Geom/Coordinate.cpp b/SRC/OpenMeca/Geom/Coordinate.cpp
new file mode 100644
index 0000000..de274f4
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Coordinate.cpp
@@ -0,0 +1,37 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org 
+
+#include "OpenMeca/Geom/Coordinate.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+    template<> const char * Coordinate<_1D, Cartesian>::componentLabel[_1D] = {"X"};    
+    template<> const char * Coordinate<_2D, Cartesian>::componentLabel[_2D] = {"X","Y"};    
+    template<> const char * Coordinate<_3D, Cartesian>::componentLabel[_3D] = {"X","Y","Z"};
+    template<> const double Coordinate<_3D, Cartesian>::epsilon = 1.e-20;
+  } 
+}
diff --git a/SRC/OpenMeca/Geom/Coordinate.hpp b/SRC/OpenMeca/Geom/Coordinate.hpp
new file mode 100644
index 0000000..602da48
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Coordinate.hpp
@@ -0,0 +1,572 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org 
+
+
+
+#ifndef _OpenMeca_Geom_Coordinate_hpp
+#define _OpenMeca_Geom_Coordinate_hpp
+
+#include <cmath>
+#include <cassert>
+#include <typeinfo>
+#include <iostream>
+#include <array>
+#include <functional>
+
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "Serialization/array.hpp"
+
+
+
+#include "OpenMeca/Geom/SpaceDim.hpp"
+#include "OpenMeca/Geom/CoordinateSystem.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+#include "OpenMeca/Util/Expr.hpp"
+
+using OpenMeca::Geom::_3D;
+using OpenMeca::Geom::SpaceDim;
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+    
+    template<SpaceDim N> class Frame;
+    template<SpaceDim N> class Matrix;
+
+    template<SpaceDim N, typename coordSystem = Cartesian>
+    class Coordinate
+    {
+    public: 	// Data
+      static const double epsilon;
+      static std::string GetStrKey(){return std::string("Coordinate" + SpaceDimUtil<N>::GetStrKey());}
+      static const char * componentLabel[N];
+
+      friend class Matrix<N>;
+      friend class Vector<N>;
+      friend class Point<N>;
+      friend class Quaternion<N>;
+      
+      //Coordinate operator
+      template<SpaceDim M, typename coordSyst> friend bool operator==(const Coordinate<M, coordSyst> &, const Coordinate<M, coordSyst> &);    
+      template<SpaceDim M, typename coordSyst> friend bool operator!=(const Coordinate<M, coordSyst> &, const Coordinate<M, coordSyst> &);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator+   (const Coordinate<M, coordSyst> &a, const Coordinate<M, coordSyst> &b);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator-   (const Coordinate<M, coordSyst> &a, const Coordinate<M, coordSyst> &b);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator-   (const Coordinate<M, coordSyst> &a);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator+   (const Coordinate<M, coordSyst> &a, double k);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator-   (const Coordinate<M, coordSyst> &a, double k);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator*   (const Coordinate<M, coordSyst> &a, double k);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator*   (double k, const Coordinate<M, coordSyst> &a);
+      template<SpaceDim M, typename coordSyst> friend Coordinate<M, coordSyst> operator/   (const Coordinate<M, coordSyst> &a, double k);
+      //Vector operator
+      template<SpaceDim M> friend std::ostream& operator<< (std::ostream &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator+ (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator- (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator- (const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator* (const Vector<M> &, const double &);
+      template<SpaceDim M> friend Vector<M> operator* (const double &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator/ (const Vector<M> &, const double &);
+      template<SpaceDim M> friend double   operator* (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator* (const Vector<M> &, const typename Vector<M>::DoubleArray &);
+      template<SpaceDim M> friend Vector<M> operator^ (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend bool     operator!= (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend bool     operator== (const Vector<M> &, const Vector<M> &);
+      //Quaternion operator
+      template<SpaceDim M> friend std::ostream & operator<< (std::ostream& o, const Quaternion<M>& q);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Quaternion<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Vector<M> &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Quaternion<M> &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Quaternion<M> &, const double &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const double &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator+  (const Quaternion<M> &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator-  (const Quaternion<M> &, const Quaternion<M> &);
+      //Matrix operator
+      friend Vector<_3D> operator* (const Matrix<_3D> &, const Vector<_3D> &);
+      friend Matrix<_3D> operator* (const double &, const Matrix<_3D> &);
+      friend Matrix<_3D> operator* (const Matrix<_3D> &, const double &);
+      friend Matrix<_3D> operator* (const Matrix<_3D> &m, const Matrix<_3D> &);
+      friend Matrix<_3D> operator/ (const Matrix<_3D> &, const double &);
+
+    public:
+      explicit Coordinate(std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      Coordinate(double x, double y, double z, std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      ~Coordinate();
+
+      Coordinate(const Coordinate & source);
+      Coordinate & operator=(const Coordinate<N, coordSystem> & source);
+
+      typedef coordSystem myCoordSystem;
+
+      const Frame<N> & GetFrame() const;
+
+      double & operator[](int i);
+      const double & operator[](int i) const;
+
+      void operator+= (double k);
+      void operator-= (double k);
+      void operator*= (double k);
+      void operator/= (double k);
+      void operator+= (const Coordinate<N, coordSystem> &);
+      void operator-= (const Coordinate<N, coordSystem> &);
+      void Clear();
+ 
+      std::ostream &  Write(std::ostream & out) const;
+      std::ostream &  XmlWrite(std::ostream & out) const;
+
+      const double* GetCoordinates() const {return c_;}
+      unsigned int GetRank() {return GetFrame().GetRank();};
+
+      std::function<const Frame<N>& ()>& GetFrameFunctionAccess() {return getFrame_;}
+      const std::function<const Frame<N>& ()>& GetFrameFunctionAccess() const {return getFrame_;}
+
+      //Expression management
+      std::array<Util::Expr,N>& GetExpression();
+      const std::array<Util::Expr,N>& GetExpression() const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive & ar, const unsigned int) const;
+      template<class Archive> void load(Archive & ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER() 
+
+    private:  // Data
+      boost::array<double,N> c_;
+      std::function<const Frame<N>& ()> getFrame_;
+
+    public: 	// Data
+      const SpaceDim dimension;
+    };
+
+    //** SERIALIZATION**
+    template<SpaceDim N, typename coordSystem>
+    template<class Archive>
+    inline void
+    Coordinate<N, coordSystem>::save(Archive & ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_NVP(c_);
+    }
+
+    template<SpaceDim N, typename coordSystem>
+    template<class Archive>
+    inline void
+    Coordinate<N, coordSystem>::load(Archive & ar, const unsigned int)
+    {
+      ar >> BOOST_SERIALIZATION_NVP(c_);
+    }
+    //** END OF SERIALIZATION **
+
+    
+    template<> inline
+    void
+    Coordinate<_3D, Cartesian>::operator+= (const Coordinate<_3D, Cartesian>& c)
+    {
+      OMC_ASSERT(GetFrame() == c.GetFrame());
+      c_[0]+=c.c_[0];
+      c_[1]+=c.c_[1];
+      c_[2]+=c.c_[2];
+    }
+
+    template<> inline
+    void
+    Coordinate<_3D, Cartesian>::operator-= (const Coordinate<_3D, Cartesian>& c)
+    {
+      OMC_ASSERT(GetFrame() == c.GetFrame());
+      c_[0]-=c.c_[0];
+      c_[1]-=c.c_[1];
+      c_[2]-=c.c_[2];
+    }
+
+    template<SpaceDim N, typename coordSystem>
+    bool operator==(const Coordinate<N, coordSystem> &, const Coordinate<N, coordSystem> &);
+    
+    template<SpaceDim N, typename coordSystem>
+    bool operator!=(const Coordinate<N, coordSystem> &, const Coordinate<N, coordSystem> &);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator+   (const Coordinate<N, coordSystem> &a, const Coordinate<N, coordSystem> &b);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator-   (const Coordinate<N, coordSystem> &a, const Coordinate<N, coordSystem> &b);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator-   (const Coordinate<N, coordSystem> &a);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator+   (const Coordinate<N, coordSystem> &a, double k);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator-   (const Coordinate<N, coordSystem> &a, double k);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator*   (const Coordinate<N, coordSystem> &a, double k);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator*   (double k, const Coordinate<N, coordSystem> &a);
+
+    template<SpaceDim N, typename coordSystem>
+    Coordinate<N, coordSystem> operator/   (const Coordinate<N, coordSystem> &a, double k);
+
+    //
+    // Vorbidden non-specialized methods (sould be specialized)
+    //
+
+    template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem>::Coordinate(std::function<const Frame<N>& ()> f)
+      : getFrame_(f), dimension(N)
+    {
+      OMC_ASSERT(!"Coordinate<N, coordSystem> generic constructour should not be called !!!");
+    }
+
+    //
+    // Template methods
+    //
+
+    //Descructor
+    template<SpaceDim N, typename coordSystem>
+    inline Coordinate<N, coordSystem>::~Coordinate()
+    {}
+         
+    
+    // Conversions ...
+
+    // Accessors ...
+
+    template<SpaceDim N, typename coordSystem>
+    inline const Frame<N> & 
+    Coordinate<N, coordSystem>::GetFrame() const
+    {
+      return getFrame_();
+    }
+
+    template<SpaceDim N, typename coordSystem>
+    inline double &
+    Coordinate<N, coordSystem>::operator[](int i) 
+    {
+      OMC_ASSERT(i>=0 && i<N);
+      return c_[i];
+    }
+
+    template<SpaceDim N, typename coordSystem>
+    inline const double &
+    Coordinate<N, coordSystem>::operator[](int i) const
+    {
+      OMC_ASSERT(i>=0 && i<N);
+      return c_[i];
+    }
+    
+
+    // External Operators ...
+
+    template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem> 
+    operator+(const Coordinate<N, coordSystem> &a, const Coordinate<N, coordSystem> &b)
+    {
+      Coordinate<N, coordSystem> copy(a);
+      copy+=b;
+      return copy;
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem> 
+    operator-(const Coordinate<N, coordSystem> &a, const Coordinate<N, coordSystem> &b)
+    {
+      Coordinate<N, coordSystem> copy(a);
+      copy-=b;
+      return copy;
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem> 
+    operator-(const Coordinate<N, coordSystem> &a)
+    {
+      return a*(-1.);
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem> 
+    operator+(const Coordinate<N, coordSystem> &c, double k)
+    {
+      Coordinate<N, coordSystem> copy(c);
+      for(int i=0; i< N; ++i)
+	{
+	  copy.c_[i]+=k;
+	}
+      return copy;
+    }
+
+   template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem> 
+    operator-(const Coordinate<N, coordSystem> &c, double k)
+    {
+      Coordinate<N, coordSystem> copy(c);
+      for(int i=0; i< N; ++i)
+	{
+	  copy.c_[i]-=k;
+	}
+      return copy;
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem> 
+    operator*(const Coordinate<N, coordSystem> &c, double k)
+    {
+      Coordinate<N, coordSystem> copy(c);
+      for(int i=0; i< N; ++i)
+	{
+	  copy.c_[i]*=k;
+	}
+      return copy;
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    Coordinate<N, coordSystem> 
+    operator/(const Coordinate<N, coordSystem> &c, double k)
+    {
+      Coordinate<N, coordSystem> copy(c);
+      //if (fabs(k) < Coordinate<N, coordSystem>::epsilon) 
+      if (fabs(k) ==0.)
+	{
+	  std::cerr << "operator/ : dividing a coordinate by a null value " << k << std::endl;
+	  // TODO : generate an exception !!!
+	}
+      else
+	{
+	  for(int i=0; i< N; ++i)
+	    {
+	      copy.c_[i]/=k;
+	    }
+	}
+      return copy;
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    bool
+    operator==(const Coordinate<N, coordSystem> & a, const Coordinate<N, coordSystem> & b)
+    {
+      OMC_ASSERT(a.GetFrame() == b.GetFrame());
+      OMC_ASSERT(typeid(a.myCoordSystem) == typeid(b.myCoordSystem));
+      bool res=true;
+      for(int i=0; i<N; ++i)
+	{
+	  res = res & (a.c_[i]==b.c_[i]);
+	}
+      return res;
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    bool
+    operator!=(const Coordinate<N, coordSystem> & a, const Coordinate<N, coordSystem> & b)
+    {
+      return(!(a==b));
+    }
+
+    // Class Operators ...
+
+    template<SpaceDim N, typename coordSystem> inline
+    void
+    Coordinate<N, coordSystem>::operator+= (double k)
+    {
+      for(int i=0; i<N; ++i)
+	{
+	  c_[i]+=k;
+	}
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    void
+    Coordinate<N, coordSystem>::operator-= (double k)
+    {
+      for(int i=0; i<N; ++i)
+	{
+	  c_[i]-=k;
+	}
+    }
+	
+    template<SpaceDim N, typename coordSystem> inline
+    void
+    Coordinate<N, coordSystem>::operator*= (double k)
+    {
+      for(int i=0; i<N; ++i)
+	{
+	  c_[i]*=k;
+	}
+    }
+    
+    template<SpaceDim N, typename coordSystem> inline
+    void
+    Coordinate<N, coordSystem>::Clear ()
+    {
+      for(int i=0; i<N; ++i)
+	{
+	  c_[i]=0.;
+	}
+    }
+    
+    template<SpaceDim N, typename coordSystem> inline
+    void
+    Coordinate<N, coordSystem>::operator/= (double k)
+    {
+      /*if (fabs(k)<Coordinate<N, coordSystem>::epsilon)  
+	{
+	  std::cerr << "Coordinate::operator/= : dividing by a null value (" << k << ")" << std::endl;
+	  // TODO : generate an exception !!!
+	  }*/
+       for(int i=0; i<N; ++i)
+	{
+	  c_[i]/=k;
+	}
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    void
+    Coordinate<N, coordSystem>::operator+= (const Coordinate<N, coordSystem> & c)
+    {
+      OMC_ASSERT(GetFrame() == c.GetFrame());
+      for(int i=0; i<N-1; ++i)
+	{
+	  c_[i]+=c.c_[i];
+	}
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    void
+    Coordinate<N, coordSystem>::operator-= (const Coordinate<N, coordSystem> & c)
+    {
+      OMC_ASSERT(GetFrame() == c.GetFrame());
+      for(int i=0; i<N; ++i)
+	{
+	  c_[i]-=c.c_[i];
+	}
+    }
+
+     // Other Methods ...
+
+    template<SpaceDim N, typename coordSystem> inline
+    std::ostream & 
+    Coordinate<N, coordSystem>::Write(std::ostream & out) const
+    {
+      std::cout.setf(std::ios::scientific, std::ios::floatfield);
+      OMC_ASSERT(typeid(myCoordSystem) == typeid(Cartesian));
+
+      for (int i=0; i<N-1 ; ++i)
+	{
+	  out << c_[i] << ", " ;
+	}
+      return out <<  c_[N-1];
+    }
+
+    template<SpaceDim N, typename coordSystem> inline
+    std::ostream & 
+    Coordinate<N, coordSystem>::XmlWrite(std::ostream & out) const
+    {
+      std::cout.setf(std::ios::scientific, std::ios::floatfield);
+      OMC_ASSERT(typeid(myCoordSystem) == typeid(Cartesian));
+      out << "<" << GetStrKey() << " " ;
+       
+      for (int i=0; i<N-1 ; ++i)
+	{
+	  out << componentLabel[i] << "=\"" << c_[i] << "\", " ;
+	}
+      out << componentLabel[N-1] << "=\"" <<  c_[N-1] << "\" />";
+      return out;
+    }
+
+
+
+
+
+    //////////////////////////////////////////////////////////////////////////////////////////
+    // 	template specialisation : _1D
+    //////////////////////////////////////////////////////////////////////////////////////////
+
+
+    ///////////////////////////////////
+    // template specialisation : _2D //
+    ///////////////////////////////////
+
+
+    ///////////////////////////////////
+    // template specialisation : _3D //
+    ///////////////////////////////////
+
+    // Constructors ...
+
+    template<> inline
+    Coordinate<_3D, Cartesian>::Coordinate(std::function<const Frame<_3D>& ()> f)
+      :  getFrame_(f), dimension(_3D)
+    {
+      c_[0]=c_[1]=c_[2]=0.;
+    }
+
+    template<> inline
+    Coordinate<_3D, Cartesian>::Coordinate(double x, double y, double z, std::function<const Frame<_3D>& ()> f)
+      : getFrame_(f), dimension(_3D)
+    {
+      c_[0]=x;
+      c_[1]=y;
+      c_[2]=z;
+    }
+
+    //
+    // Only authorized const Coordinate<_3D> & c can be used (authorized combination of coordSystem
+    // and SpaceDim)
+    //
+
+    template<> inline
+    Coordinate<_3D, Cartesian>::Coordinate(const Coordinate<_3D, Cartesian> & c)
+      : getFrame_(c.getFrame_), dimension(_3D)
+    {
+      c_[0]=c.c_[0]; c_[1]=c.c_[1]; c_[2]=c.c_[2];
+    }
+
+    //
+    // In this version only coordinate of same "coordSystem" are canidate for operator=().
+    //
+
+    template<> inline
+    Coordinate<_3D> &
+    Coordinate<_3D, Cartesian>::operator=(const Coordinate<_3D, Cartesian> & c)
+    {
+      OMC_ASSERT(GetFrame() == c.GetFrame());
+
+      if (this == &c)
+	return *this;
+
+      c_[0]=c.c_[0]; 
+      c_[1]=c.c_[1]; 
+      c_[2]=c.c_[2];
+
+      return *this;
+    }
+
+  } // namespace Geom
+}
+
+
+
+
+#endif
+
diff --git a/SRC/OpenMeca/Geom/CoordinateSystem.hpp b/SRC/OpenMeca/Geom/CoordinateSystem.hpp
new file mode 100644
index 0000000..e5f01d0
--- /dev/null
+++ b/SRC/OpenMeca/Geom/CoordinateSystem.hpp
@@ -0,0 +1,59 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org 
+
+
+
+#ifndef _OpenMeca_CoordinateSystem_hpp_
+#define _OpenMeca_CoordinateSystem_hpp_
+
+namespace OpenMeca
+{
+  namespace Geom 
+  {
+
+    // Only the Cartesian system is used
+    class CoordinateSystem
+    {
+    };
+    
+    class Cartesian : public CoordinateSystem
+    {
+    };
+  
+    class Cylindrical : public CoordinateSystem
+    {
+    };
+  
+    class Spherical : public CoordinateSystem
+    {
+    };
+    
+    class Polar : public CoordinateSystem
+    {
+    };
+    
+
+  }
+}
+      
+#endif
diff --git a/SRC/OpenMeca/Geom/Frame.cpp b/SRC/OpenMeca/Geom/Frame.cpp
new file mode 100755
index 0000000..c0d6bb0
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Frame.cpp
@@ -0,0 +1,188 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org and 
+// the qglviewer library : http://www.libqglviewer.com
+
+
+
+#include <cmath>
+#include <iostream>
+#include <QGLViewer/qglviewer.h>
+
+#include "OpenMeca/Geom/Frame.hpp"
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Geom/Vector.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Geom 
+  {
+ 
+    template<> const Point<_3D>       Frame<_3D>::GlobalCenter = Point<_3D>();
+    template<> const Quaternion<_3D>  Frame<_3D>::GlobalQuaternion= Quaternion<_3D>();
+    template<> const Frame<_3D>       Frame<_3D>::Global = Frame<_3D>(Frame<_3D>::GlobalCenter, Frame<_3D>::GlobalQuaternion);
+    
+    template<> const Point<_3D>       Frame<_3D>::NullCenter = Point<_3D>();
+    template<> const Quaternion<_3D>  Frame<_3D>::NullQuaternion= Quaternion<_3D>();
+    template<> const Frame<_3D>       Frame<_3D>::Null  = Frame<_3D>(Frame<_3D>::NullCenter, Frame<_3D>::NullQuaternion); 
+    
+  
+    template<> 
+    chrono::ChCoordsys<double> 
+    Frame<_3D>::ToChCoordsys() const
+    {
+      return chrono::ChCoordsys<double>(GetCenter().ToChVector(), 
+					GetQuaternion().ToChQuaternion());
+    }
+
+    template<> 
+    chrono::ChCoordsys<double> 
+    Frame<_3D>::ToChCoordsys_Global() const
+    {
+      Point<_3D> point(GetCenter(), &Frame<_3D>::GetGlobal);
+      Quaternion<_3D> quat(GetQuaternion(), &Frame<_3D>::GetGlobal);
+      return chrono::ChCoordsys<double>(point.ToChVector(), quat.ToChQuaternion());
+    }
+
+    template<> 
+    chrono::ChCoordsys<double> 
+    Frame<_3D>::ToChCoordsys_Local() const
+    {
+      const Geom::Point<_3D> &center = GetCenter();
+      const Geom::Quaternion<_3D> &quat = GetQuaternion();
+      return chrono::ChCoordsys<double>(center.ToChVector(), quat.ToChQuaternion());
+    }
+
+
+    template<> void
+    Frame<_3D>::DeleteAxis()
+    {
+      delete xAxis_;
+      delete yAxis_;
+      delete zAxis_;
+    }
+    
+    template<> void
+    Frame<_3D>::BuildAxis()
+    {
+      std::function<const Frame<_3D>& ()> f = std::bind(&Frame<_3D>::GetMe, std::ref(*this));
+      xAxis_ = new Vector<_3D>(1.,0.,0.,f);
+      yAxis_ = new Vector<_3D>(0.,1.,0.,f);
+      zAxis_ = new Vector<_3D>(0.,0.,1.,f);
+    }
+
+  
+
+    template<>
+    void
+    Frame<_3D>::UpdateGLMatrix()
+    {
+      if (GetRank()==0)
+	{
+	  m_[0][0] = 1.;
+	  m_[1][0] = 0.;
+	  m_[2][0] = 0.;
+	  m_[0][1] = 0.;
+	  m_[1][1] = 1.;
+	  m_[2][1] = 0.;
+	  m_[0][2] = 0.;
+	  m_[1][2] = 0.;
+	  m_[2][2] = 1.;
+	  m_[0][3] = 0.;
+	  m_[1][3] = 0.;
+	  m_[2][3] = 0.;
+	  m_[3][0] = 0.;
+	  m_[3][1] = 0.;
+	  m_[3][2] = 0.;
+	  m_[3][3] = 1.;
+	  //Translation 
+	  m_[3][0] = 0.;
+	  m_[3][1] = 0.;
+	  m_[3][2] = 0.;
+	}
+      else
+	{
+	  
+	  Quaternion<_3D> quat(GetQuaternion(), &Frame<_3D>::GetGlobal);
+	  //Rotation with quaternion
+	  const double q00 = 2. * quat[0] * quat[0];
+	  const double q11 = 2. * quat[1] * quat[1];
+	  const double q22 = 2. * quat[2] * quat[2];
+	  const double q01 = 2. * quat[0] * quat[1];
+	  const double q02 = 2. * quat[0] * quat[2];
+	  const double q03 = 2. * quat[0] * quat.GetReal();
+	  const double q12 = 2. * quat[1] * quat[2];
+	  const double q13 = 2. * quat[1] * quat.GetReal();
+	  const double q23 = 2. * quat[2] * quat.GetReal();
+	  m_[0][0] = 1. - q11 - q22;
+	  m_[1][0] = q01 - q23;
+	  m_[2][0] = q02 + q13;
+	  m_[0][1] = q01 + q23;
+	  m_[1][1] = 1. - q22 - q00;
+	  m_[2][1] = q12 - q03;
+	  m_[0][2] = q02 - q13;
+	  m_[1][2] = q12 + q03;
+	  m_[2][2] = 1. - q11 - q00;
+	  m_[0][3] = 0.;
+	  m_[1][3] = 0.;
+	  m_[2][3] = 0.;
+	  m_[3][0] = 0.;
+	  m_[3][1] = 0.;
+	  m_[3][2] = 0.;
+	  m_[3][3] = 1.;
+	  //Translation with point
+	  Point<_3D> point(GetCenter(), &Frame<_3D>::GetGlobal);
+	  m_[3][0] = point[0];
+	  m_[3][1] = point[1];
+	  m_[3][2] = point[2];
+	}
+    }
+
+    template<>
+    void
+    Frame<_3D>::UpdateGLMatrix() const
+    {
+      Frame<_3D>* me = const_cast< Frame<_3D>* >(this);
+      me->UpdateGLMatrix();
+    }
+
+    template<>
+    void
+    Frame<_3D>::Draw(const double scale) const
+    {
+      QGLViewer::drawAxis(scale);
+    }
+
+    template<>
+    void
+    Frame<_3D>::Draw() const
+    {
+      const double scale = 
+	    Core::System::Get().GetScales().GetScaleValue(OpenMeca::Geom::Frame<_3D>::GetStrType());
+      QGLViewer::drawAxis(scale);
+    }
+ 
+  }
+}
diff --git a/SRC/OpenMeca/Geom/Frame.hpp b/SRC/OpenMeca/Geom/Frame.hpp
new file mode 100755
index 0000000..b42a28b
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Frame.hpp
@@ -0,0 +1,344 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org and 
+// the qglviewer library : http://www.libqglviewer.com
+
+
+#ifndef  _OpenMeca_Geom_FRAME_hpp_
+#define  _OpenMeca_Geom_FRAME_hpp_
+
+#include <iostream>
+#include <QString>
+#include <QObject>
+
+#ifndef OSX
+  #include <GL/gl.h>
+#else
+  #include <OpenGL/gl.h>
+#endif
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Geom/SpaceDim.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+#include "ChronoEngine/core/ChCoordsys.h"
+
+using OpenMeca::Geom::_3D;
+using OpenMeca::Geom::SpaceDim;
+
+
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+    
+    template<SpaceDim N> class Point;
+    template<SpaceDim N> class Quaternion;
+    template<SpaceDim N> class Vector;
+
+    template<SpaceDim N>
+    class Frame
+    {
+
+    public:
+      static const Frame<N> Global;
+      static const Point<N> GlobalCenter;
+      static const Quaternion<N> GlobalQuaternion;
+      static const Frame<N> Null;
+      static const Point<N> NullCenter;
+      static const Quaternion<N> NullQuaternion;
+      static std::string GetStrKey(){return std::string("Frame" + SpaceDimUtil<N>::GetStrKey());}
+      static std::string GetStrType(){return std::string("Frame");}
+      static QString GetQStrType(){return QObject::tr("Frame");}
+
+      static const Frame<N>& GetGlobal() {return Global;}
+   
+    public:
+      //CONSTRUCTORS & DESTRUCTORS
+      Frame(const Frame& frame);
+      Frame(const Point<N> &center, const Quaternion<N> &quaternion);
+      Frame();
+      ~Frame();
+
+      //CHRONO CONVERSION
+      chrono::ChCoordsys<double> ToChCoordsys() const;
+      chrono::ChCoordsys<double> ToChCoordsys_Global() const;
+      chrono::ChCoordsys<double> ToChCoordsys_Local() const;
+
+      //DRAW 
+      void Draw(const double scale) const;
+      void Draw() const;
+
+      //OPERATORS
+      Frame& operator=(const Frame& frame);
+
+      const Quaternion<N> & GetQuaternion() const;
+      const Point<N> & GetCenter() const;
+      const Vector<N>& GetXAxis() const;
+      const Vector<N>& GetYAxis() const;
+      const Vector<N>& GetZAxis() const;
+      SpaceDim GetDimension() const ;
+      const Frame<N>& GetReferenceFrame() const;
+
+      //USEFULL
+      const Frame<N>* GetCommonFrame(Frame<N> *f) const;
+      int GetRank() const { return rank_; };
+
+
+      const GLdouble* GetGLMatrix() const {return &m_[0][0];}
+
+      void UpdateGLMatrix();
+      void UpdateGLMatrix() const; 
+
+      const Frame<_3D>& GetMe() const;
+
+    private:
+      // - BOOST SERIALIZATION - //
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive&, const unsigned int) const;
+      template<class Archive> void load(Archive&, const unsigned int); 
+      BOOST_SERIALIZATION_SPLIT_MEMBER()     
+      
+    private:
+      const SpaceDim dimension_;
+      const Point<N>* const p_;
+      const Quaternion<N>* const q_;
+      const int rank_;	       // rank_ = 0 is for the Global Frame
+#ifndef SERVER
+      GLdouble m_[4][4];
+#endif
+      const Vector<N>* xAxis_; // Needs pointer because of multiple inclusion of .hpp  :(
+      const Vector<N>* yAxis_; // Needs pointer because of multiple inclusion of .hpp  :(
+      const Vector<N>* zAxis_; // Needs pointer because of multiple inclusion of .hpp  :(      
+
+    private:
+      void BuildAxis();
+      void DeleteAxis();
+    };
+
+    template<> const Frame<_3D> Frame<_3D>::Null;
+
+    //*************************
+    //DECLARATION OF EXTERN OPERATORS
+      
+    template<SpaceDim N>
+    std::ostream& operator<< (std::ostream& o, const Frame<N>& f);
+
+    template<SpaceDim N>
+    bool operator==(const Frame<N>& f1, const Frame<N>& f2);
+    
+    template<SpaceDim N>
+    bool operator!=(const Frame<N>& f1, const Frame<N>& f2);
+    
+    
+    template<SpaceDim N>
+    std::ostream& operator<< (std::ostream& o, const Frame<N>& f);
+    
+    
+    //
+    // Vorbidden non-specialized methods (sould be specialized)
+    //
+
+    //
+    // Template methods
+    //
+
+    // Constructors ...
+
+    template<SpaceDim N> inline
+    Frame<N>::Frame()
+      : dimension_(N), 
+	p_(0), 
+	q_(0), 
+	rank_(-1)
+    {
+      BuildAxis();
+    }
+
+    template<SpaceDim N> inline
+    Frame<N>::Frame(const Point<N>& center, const Quaternion<N>& quaternion)
+      : dimension_(N), 
+	p_(&center), 
+	q_(&quaternion), 
+	rank_( (this ==  &Frame<N>::Global) ? 0 : center.GetFrame().rank_+1)
+    {
+      OMC_ASSERT(center.GetFrame() == quaternion.GetFrameFrom()); //must be expressed in the SAME Frame !
+      BuildAxis();
+      const_cast<Quaternion<N> &>(*q_).SetFrameTo(this);      // Sorry !!! ;-)
+    }
+
+    template<SpaceDim N> inline
+    Frame<N>::~Frame()
+    {
+      DeleteAxis();
+    }
+    
+
+    // - BOOST SERIALIZATION - //
+    template<SpaceDim N> 
+    template<class Archive>
+    void 
+    Frame<N>::save(Archive& ar, const unsigned int ) const
+    {
+      OMC_ASSERT(rank_>=0);
+      ar << BOOST_SERIALIZATION_NVP(rank_);
+      ar << BOOST_SERIALIZATION_NVP(p_);
+      ar << BOOST_SERIALIZATION_NVP(q_);
+    }
+
+    // - BOOST SERIALIZATION - //
+    template<SpaceDim N> 
+    template<class Archive>
+    void 
+    Frame<N>::load(Archive& ar, const unsigned int ) 
+      {
+	ar >> BOOST_SERIALIZATION_NVP(const_cast<int&>(rank_));
+	ar >> BOOST_SERIALIZATION_NVP(const_cast<Point<_3D>*&>(p_));
+	ar >> BOOST_SERIALIZATION_NVP(const_cast<Quaternion<_3D>*&>(q_));
+	OMC_ASSERT(rank_>=0);
+	if (rank_>0)
+	  {
+	    if (&q_->GetFrameTo() == &Frame<N>::Null)
+	      const_cast<Quaternion<N> &>(*q_).SetFrameTo(this);
+	  }
+	else 	  
+	  delete this;
+	UpdateGLMatrix();
+      }
+
+
+    // Accessors ...
+    template<SpaceDim N> inline
+    const Frame<_3D>& 
+    Frame<N>::GetMe() const
+    {
+      return *this;
+    }
+
+    template<SpaceDim N> inline
+    const Point<N>&
+    Frame<N>::GetCenter() const
+    {
+      return *p_;
+    }
+
+    template<SpaceDim N> inline 
+    const Quaternion<N>&
+    Frame<N>::GetQuaternion() const
+    {
+      return *q_;
+    }
+
+    template<SpaceDim N>inline
+    SpaceDim
+    Frame<N>::GetDimension() const
+    {
+      return dimension_;
+    }
+
+    template<SpaceDim N>inline
+    const Frame<N>& 
+    Frame<N>::GetReferenceFrame() const
+    {
+      return p_->GetFrame();
+    }
+
+    // External Operators ... 
+     
+    template<SpaceDim N>inline 
+    bool 
+    operator==(const Frame<N>& f1, const Frame<N>& f2)
+    {
+      // TODO
+      return &f1 == &f2;
+    }
+
+    template<SpaceDim N>inline 
+    bool 
+    operator!=(const Frame<N>& f1, const Frame<N>& f2)
+    {
+      return  ! (f1 == f2);
+    }
+
+    template<SpaceDim N> inline
+    std::ostream&
+    operator<< (std::ostream& o, const Frame<N>& f)
+    {
+      return o << f.GetCenter() << '\t' << f.GetQuaternion();
+    }
+
+    // Class Operators ...
+
+
+    template<SpaceDim N> inline 
+    const Vector<N>& 
+    Frame<N>::GetXAxis() const
+    {
+      return *xAxis_;
+    }
+
+    template<SpaceDim N> inline 
+    const Vector<N>& 
+    Frame<N>::GetYAxis() const
+    {
+      return *yAxis_;
+    }
+
+    template<SpaceDim N> inline 
+    const Vector<N>& 
+    Frame<N>::GetZAxis() const
+    {
+      return *zAxis_;
+    }
+    
+    //Usefull methods
+    template<SpaceDim N> inline
+    const Frame<N>* 
+    Frame<N>::GetCommonFrame(Frame<N> *f) const
+    {
+      Frame<N> *my_RefFrame = &GetReferenceFrame();
+      Frame<N> *f_RefFrame = f;
+      do
+	{
+	  do
+	    {
+	      if (my_RefFrame==f_RefFrame)
+		{
+		  return my_RefFrame;
+		}
+	      my_RefFrame = my_RefFrame->GetReferenceFrame();
+	    }while(my_RefFrame!=&Frame<N>::Global);
+	  f_RefFrame = f_RefFrame->GetReferenceFrame();
+	}while(f_RefFrame!=&Frame<N>::Global);
+      OMC_ASSERT(0);
+    }
+
+    // Template spesialization 3D_
+   
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Geom/Geom.pro b/SRC/OpenMeca/Geom/Geom.pro
new file mode 100644
index 0000000..c732a9d
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Geom.pro
@@ -0,0 +1,39 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http:##www.gnu.org/licenses/>.
+
+
+HEADERS += Geom/Coordinate.hpp \
+           Geom/CoordinateSystem.hpp \
+           Geom/Frame.hpp \
+           Geom/Matrix.hpp \
+           Geom/Point.hpp \
+           Geom/Quaternion.hpp \
+           Geom/SpaceDim.hpp \
+           Geom/Vector.hpp
+
+
+
+SOURCES += Geom/Coordinate.cpp \
+           Geom/Frame.cpp \
+           Geom/Matrix.cpp \
+           Geom/Point.cpp \
+           Geom/Quaternion.cpp \
+           Geom/SpaceDim.cpp \
+           Geom/Vector.cpp
+
diff --git a/SRC/OpenMeca/Geom/Matrix.cpp b/SRC/OpenMeca/Geom/Matrix.cpp
new file mode 100755
index 0000000..7279f85
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Matrix.cpp
@@ -0,0 +1,65 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org
+
+
+#include "OpenMeca/Geom/Matrix.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Point.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+
+    chrono::ChMatrix33<double> 
+    Matrix<_3D>::ToChMatrix() const
+    {
+      const Matrix<_3D>& me = *this;
+      chrono::ChMatrix33<double> ch; 
+      for (unsigned int i = 0; i < 3; i++)
+	for (unsigned int j = 0; j < 3; j++)
+	  ch(i,j) = me[i][j];
+
+      return ch;
+   }
+
+
+    Matrix<_3D>::Matrix(const Matrix<_3D>& M, std::function<const Frame<_3D>& ()> f):
+      c0_(f), c1_(f), c2_(f)
+    {
+      c_[0] = &c0_;
+      c_[1] = &c1_;
+      c_[2] = &c2_;
+      Quaternion<_3D> q(M.GetFrame().GetQuaternion(),f);
+      Matrix<_3D> B =q.ToRotationMatrix();
+      *this = (B*M)*B.GetInverse();
+    }
+    
+  }
+}
+
+
+
diff --git a/SRC/OpenMeca/Geom/Matrix.hpp b/SRC/OpenMeca/Geom/Matrix.hpp
new file mode 100755
index 0000000..11df2a5
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Matrix.hpp
@@ -0,0 +1,321 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org
+
+
+
+#ifndef _OpenMeca_Geom_MATRIX_hpp_
+#define _OpenMeca_Geom_MATRIX_hpp_
+
+#include <cmath>
+#include <iostream>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Geom/Vector.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+#include "ChronoEngine/core/ChMatrix.h"
+
+
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+    
+  
+    //**********************************
+    // Proxy Class to get operator [][]
+    //**********************************
+    template<SpaceDim N>
+    class proxy
+    {
+    public:
+      proxy(Coordinate<N> *m): m_(m){};
+      double& operator[](unsigned int c) {return  (*m_)[c];};
+    private:
+      Coordinate<N> *m_;
+    };
+
+    template<SpaceDim N>
+    class proxyConst
+    {
+    public:
+      proxyConst(const Coordinate<N> *m): m_(m){};
+      //double& operator[](unsigned int c) {return  m_[c];};
+      const double& operator[](unsigned int c) const {return  (*m_)[c];};
+    private:
+      Coordinate<N> const *m_;
+    };
+    //***************************************
+    //***************************************
+
+
+    template<SpaceDim N> class Matrix;
+    
+    template<>
+    class Matrix<_3D>
+    {
+    public:
+      Matrix(std::function<const Frame<_3D>& ()> = &Frame<_3D>::GetGlobal);
+      Matrix(double, double, double, double, double, double, double, double, double, std::function<const Frame<_3D>& ()> = &Frame<_3D>::GetGlobal);
+      Matrix(const Matrix<_3D>&);
+      Matrix(const Matrix<_3D>&, std::function<const Frame<_3D>& ()>);
+      Matrix& operator=(const Matrix<_3D>&);
+      static std::string GetStrKey(){return std::string("Matrix" + SpaceDimUtil<_3D>::GetStrKey());}
+      static std::string GetStrType(){return std::string("Matrix");}
+      static QString GetQStrType(){return QObject::tr("Matrix");}
+      
+      //CHRONO CONVERSION
+      chrono::ChMatrix33<double> ToChMatrix() const;
+  
+     
+      proxy<_3D> operator[](unsigned int l){ return proxy<_3D>(c_[l]); };
+      const proxyConst<_3D> operator[](unsigned int l) const {return proxyConst<_3D>(c_[l]);};
+      
+      double GetValue(unsigned int i, unsigned int j) const;
+      void SetValue(unsigned int i, unsigned int j, double val);
+
+      
+      void Clear();
+      const Frame<_3D>& GetFrame() const;
+      double GetDeterminant();
+      Matrix<_3D> GetTranspose();
+      Matrix<_3D> GetInverse();
+      
+      friend Vector<_3D> operator* (const Matrix<_3D> &m, const Vector<_3D> &v);
+      friend Matrix<_3D> operator* (const double &d, const Matrix<_3D> &m);
+      friend Matrix<_3D> operator* (const Matrix<_3D> &m, const double &d);
+      friend Matrix<_3D> operator* (const Matrix<_3D> &m1, const Matrix<_3D> &m2);
+      friend Matrix<_3D> operator/ (const Matrix<_3D> &m, const double &d);
+
+      
+      const Coordinate<_3D>& GetLine0() const {return c0_;}
+      const Coordinate<_3D>& GetLine1() const {return c1_;}
+      const Coordinate<_3D>& GetLine2() const {return c2_;}
+
+      std::function<const Frame<_3D>& ()>& GetFrameFunctionAccess() {return c0_.GetFrameFunctionAccess();}
+      const std::function<const Frame<_3D>& ()>& GetFrameFunctionAccess() const {return c0_.GetFrameFunctionAccess();}
+  
+    private:
+      //double m_[N*N]; //-------->[line][colums] || [x] = [3*l + c]
+      Coordinate<_3D> c0_, c1_, c2_;
+      Coordinate<_3D> *c_[3];
+
+      //BOOST SERIALIZATION       
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int ) 
+      {
+	//a simple way to serialize without saving frame tree
+	//be carefull...
+	ar &c0_;
+	ar &c1_;
+	ar &c2_;
+      }
+     
+
+    };
+    
+    template<SpaceDim M> Vector<M> operator* (const Matrix<M> &m, const Vector<M> &v);
+    template<SpaceDim M> Matrix<M> operator* (const double &d, const Matrix<M> &m);
+    template<SpaceDim M> Matrix<M> operator* (const Matrix<M> &m, const double &d);
+    template<SpaceDim M> Matrix<M> operator* (const Matrix<M> &m1, const Matrix<M> &m2);
+    template<SpaceDim M> Matrix<M> operator/ (const Matrix<M> &m, const double &d);
+    template<SpaceDim N> std::ostream& operator<< (std::ostream& o, const Matrix<_3D>& M);
+
+    //
+    //EXTERNALS OPERATORS
+    //
+    inline 
+    std::ostream& 
+    operator<< (std::ostream& o, const Matrix<_3D>& M)
+    { 
+      return o << M[0][0] << '\t' << M[0][1] << '\t' << M[0][2] << '\n'
+	       << M[1][0] << '\t' << M[1][1] << '\t' << M[1][2] << '\n'
+	       << M[2][0] << '\t' << M[2][1] << '\t' << M[2][2] << '\n';
+    }
+    
+     inline Vector<_3D> 
+    operator*(const Matrix<_3D> &m, const Vector<_3D> &v)
+    {
+      return Vector<_3D>(m.c0_.c_[0]*v[0] + m.c0_.c_[1]*v.coord_.c_[1] + m.c0_.c_[2]*v.coord_.c_[2],
+			 m.c1_.c_[0]*v.coord_.c_[0] + m.c1_.c_[1]*v.coord_.c_[1] + m.c1_.c_[2]*v.coord_.c_[2],
+			 m.c2_.c_[0]*v.coord_.c_[0] + m.c2_.c_[1]*v.coord_.c_[1] + m.c2_.c_[2]*v.coord_.c_[2],v.GetFrameFunctionAccess());
+
+    }
+    
+    inline Matrix<_3D> 
+    operator*(const double &d, const Matrix<_3D> &m)
+    {
+      return Matrix<_3D>(m.c0_.c_[0]*d, m.c0_.c_[1]*d, m.c0_.c_[2]*d,
+			 m.c1_.c_[0]*d, m.c1_.c_[1]*d, m.c1_.c_[2]*d,
+			 m.c2_.c_[0]*d, m.c2_.c_[1]*d, m.c2_.c_[2]*d, 
+			 m.GetFrameFunctionAccess());
+    }
+    
+    inline Matrix<_3D> 
+    operator*(const Matrix<_3D> &m, const double &d)
+    {
+      return d*m;
+    }
+    
+    inline Matrix<_3D> 
+    operator* (const Matrix<_3D> &m1, const Matrix<_3D> &m2)
+    {
+      //OMC_ASSERT(m1.GetFrame() == m2.GetFrame());
+      return Matrix<_3D>(m1.c0_.c_[0]*m2.c0_.c_[0] + m1.c0_.c_[1]*m2.c1_.c_[0] + m1.c0_.c_[2]*m2.c2_.c_[0],
+			 m1.c0_.c_[0]*m2.c0_.c_[1] + m1.c0_.c_[1]*m2.c1_.c_[1] + m1.c0_.c_[2]*m2.c2_.c_[1],
+			 m1.c0_.c_[0]*m2.c0_.c_[2] + m1.c0_.c_[1]*m2.c1_.c_[2] + m1.c0_.c_[2]*m2.c2_.c_[2],
+
+			 m1.c1_.c_[0]*m2.c0_.c_[0] + m1.c1_.c_[1]*m2.c1_.c_[0] + m1.c1_.c_[2]*m2.c2_.c_[0],
+			 m1.c1_.c_[0]*m2.c0_.c_[1] + m1.c1_.c_[1]*m2.c1_.c_[1] + m1.c1_.c_[2]*m2.c2_.c_[1],
+			 m1.c1_.c_[0]*m2.c0_.c_[2] + m1.c1_.c_[1]*m2.c1_.c_[2] + m1.c1_.c_[2]*m2.c2_.c_[2],
+
+			 m1.c2_.c_[0]*m2.c0_.c_[0] + m1.c2_.c_[1]*m2.c1_.c_[0] + m1.c2_.c_[2]*m2.c2_.c_[0],
+			 m1.c2_.c_[0]*m2.c0_.c_[1] + m1.c2_.c_[1]*m2.c1_.c_[1] + m1.c2_.c_[2]*m2.c2_.c_[1],
+			 m1.c2_.c_[0]*m2.c0_.c_[2] + m1.c2_.c_[1]*m2.c1_.c_[2] + m1.c2_.c_[2]*m2.c2_.c_[2],
+			 m1.GetFrameFunctionAccess());
+    }
+
+
+    inline Matrix<_3D> 
+    operator/(const Matrix<_3D> &m, const double &d)
+    {
+      return Matrix<_3D>(m.c0_.c_[0]/d, m.c0_.c_[1]/d, m.c0_.c_[2]/d,
+			 m.c1_.c_[0]/d, m.c1_.c_[1]/d, m.c1_.c_[2]/d,
+			 m.c2_.c_[0]/d, m.c2_.c_[1]/d, m.c2_.c_[2]/d,
+			 m.GetFrameFunctionAccess());
+    }
+    
+
+    //
+    //CONSTRUCTOR
+    //
+    inline 
+    Matrix<_3D>::Matrix(double d0, double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, std::function<const Frame<_3D>& ()> f)
+      : c0_(d0,d1,d2,f), c1_(d3,d4,d5,f), c2_(d6,d7,d8,f) 
+    {
+      c_[0] = &c0_;
+      c_[1] = &c1_;
+      c_[2] = &c2_;
+    }
+
+  
+    
+    inline 
+    Matrix<_3D>::Matrix(std::function<const Frame<_3D>& ()> f)
+    :c0_(0,0,0,f), c1_(0,0,0,f), c2_(0,0,0,f)
+    {
+      c_[0] = &c0_;
+      c_[1] = &c1_;
+      c_[2] = &c2_;
+    }
+    
+    inline 
+    Matrix<_3D>::Matrix(const Matrix<_3D>& M)
+      :c0_(M.c0_), c1_(M.c1_), c2_(M.c2_)
+    {
+      c_[0] = &c0_;
+      c_[1] = &c1_;
+      c_[2] = &c2_;
+    }
+    
+    inline Matrix<_3D> & 
+    Matrix<_3D>::operator=(const Matrix<_3D>& M)
+    {
+      c0_ = M.c0_;
+      c1_ = M.c1_;
+      c2_ = M.c2_;
+      return *this;
+    }
+    
+
+    inline double 
+    Matrix<_3D>::GetValue(unsigned int i, unsigned int j) const
+    {
+      return (*this)[i][j];
+    }
+
+    
+    inline void 
+    Matrix<_3D>::SetValue(unsigned int i, unsigned int j, double val)
+    {
+      (*this)[i][j] = val;
+    } 
+    //
+    //UTIL METHOD
+    //
+    
+    inline double 
+    Matrix<_3D>::GetDeterminant()
+    {
+      return c0_.c_[0]*(c1_.c_[1]*c2_.c_[2]-c1_.c_[2]*c2_.c_[1]) - c0_.c_[1]*(c1_.c_[0]*c2_.c_[2]-c1_.c_[2]*c2_.c_[0]) + c0_.c_[2]*(c1_.c_[0]*c2_.c_[1]-c1_.c_[1]*c2_.c_[0]);
+    }
+    
+    inline Matrix<_3D> 
+    Matrix<_3D>::GetTranspose()
+    {
+      return Matrix<_3D>(c0_.c_[0],c1_.c_[0],c2_.c_[0],c0_.c_[1],c1_.c_[1],c2_.c_[1],c0_.c_[2],c1_.c_[2],c2_.c_[2],GetFrameFunctionAccess());
+    }
+    
+    inline Matrix<_3D> 
+    Matrix<_3D>::GetInverse()
+    {
+      const double det = GetDeterminant();
+      return Matrix<_3D>(c1_.c_[1]*c2_.c_[2] - c2_.c_[1]*c1_.c_[2],
+			 c2_.c_[0]*c1_.c_[2] - c1_.c_[0]*c2_.c_[2],
+			 c1_.c_[0]*c2_.c_[1] - c2_.c_[0]*c1_.c_[1],
+			 c2_.c_[1]*c0_.c_[2] - c0_.c_[1]*c2_.c_[2],
+			 c0_.c_[0]*c2_.c_[2] - c2_.c_[0]*c0_.c_[2],
+			 c2_.c_[0]*c0_.c_[1] - c0_.c_[0]*c2_.c_[1],
+			 c0_.c_[1]*c1_.c_[2] - c1_.c_[1]*c0_.c_[2],
+			 c1_.c_[0]*c0_.c_[2] - c0_.c_[0]*c1_.c_[2],
+			 c0_.c_[0]*c1_.c_[1] - c1_.c_[0]*c0_.c_[1],
+			 GetFrameFunctionAccess()
+			 ).GetTranspose()/det;
+    }  
+
+    inline void 
+    Matrix<_3D>::Clear()
+    {
+      c0_.Clear();
+      c1_.Clear();
+      c2_.Clear();
+    }
+    
+    inline const Frame<_3D> &
+    Matrix<_3D>::GetFrame() const
+    {
+      return c0_.GetFrame();
+    }
+  
+
+  }
+}	
+
+
+
+#endif
+
diff --git a/SRC/OpenMeca/Geom/Point.cpp b/SRC/OpenMeca/Geom/Point.cpp
new file mode 100755
index 0000000..0337f34
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Point.cpp
@@ -0,0 +1,43 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org
+
+
+#include "OpenMeca/Geom/Point.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Geom 
+  {
+
+    template<> 
+    chrono::ChVector<double> 
+    Point<_3D>::ToChVector() const
+    {
+      const Point<_3D>& me = *this;
+      return chrono::ChVector<double>(me[0], me[1], me[2]);
+    }
+
+  } 
+}
diff --git a/SRC/OpenMeca/Geom/Point.hpp b/SRC/OpenMeca/Geom/Point.hpp
new file mode 100644
index 0000000..a3ecd92
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Point.hpp
@@ -0,0 +1,452 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org
+
+
+#ifndef _OpenMeca_Geom_Point_hpp_
+#define _OpenMeca_Geom_Point_hpp_
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "OpenMeca/Geom/SpaceDim.hpp"
+#include "OpenMeca/Geom/Coordinate.hpp"
+#include "OpenMeca/Geom/Vector.hpp"
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "ChronoEngine/core/ChVector.h"
+
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+    template<SpaceDim N>
+    class Point
+    {
+    
+      friend class Vector<N>;
+      template<Geom::SpaceDim M> friend std::ostream& operator<<(std::ostream &, const Point<M> &);
+      
+    public:    
+      static std::string GetStrKey(){return std::string("Point" + SpaceDimUtil<N>::GetStrKey());}
+      static std::string GetStrType(){return std::string("Point");}
+      static QString GetQStrType(){return QObject::tr("Point");}
+
+
+    public:
+      //CONSTRUCTORS & DESTRUCTORS
+      explicit Point(std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal) ;
+      explicit Point(const Point<N> &, std::function<const Frame<N>& ()>);
+      explicit Point(double, double, double, std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      Point(const Point &);
+      virtual ~Point();
+
+      //CHRONO CONVERSION
+      chrono::ChVector<double> ToChVector() const;
+
+      //OPERATORS
+      Point & operator=(const Point &);
+      Point & operator=(const chrono::ChVector<double>&);
+
+      const double & operator[](int i) const;
+      double& operator[](int i);	
+
+      //ACCESSORS
+      SpaceDim GetDimension() const;
+      const Frame<N> & GetFrame() const;
+
+      const Coordinate<N> & GetCoordinate() const;
+      Coordinate<N> & GetCoordinate();
+      
+      Vector<N> & GetPositionVector();
+      const Vector<N> & GetPositionVector() const;
+
+      //UTILS
+      double ComputeDistanceFrom(const Point &) const;
+      std::ostream& Write(std::ostream&) const;      
+
+      //FRAME OPERATIONS
+      Point ToGlobalFrame() const;
+
+      unsigned int GetStateNumber() const;
+      void SetAsFirstState();
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+
+      std::function<const Frame<N>& ()>& GetFrameFunctionAccess(); 
+      const std::function<const Frame<N>& ()>& GetFrameFunctionAccess() const;
+
+      const double* GetPtr() const;
+
+    private:
+      // - BOOST SERIALIZATION - //
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive&, const unsigned int );
+    
+    private:
+      Coordinate<N, Cartesian> coord_;  
+      std::vector< std::array<double,N> > states_;
+      
+    };
+
+
+    // - BOOST SERIALIZATION - //
+    template<SpaceDim N>
+    template<class Archive>
+    inline void 
+    Point<N>::serialize(Archive & ar , const unsigned int ) 
+    {
+      ar & BOOST_SERIALIZATION_NVP(coord_);
+    }   
+
+    // Vorbidden non-specialized methods (sould be specialized)
+    //
+
+    
+    template<SpaceDim N>
+    Point<N>::Point(double x, double y, double z, std::function<const Frame<N>& ()> f)
+    {
+      OMC_ASSERT(!"Generic constructour should not be called !!!");
+    }
+
+
+    //
+    // Template methods
+    //
+
+    // Constructors ...
+
+    template<SpaceDim N> inline
+    Point<N>::Point(std::function<const Frame<N>& ()> f)
+      :  coord_(f)
+    {
+    }
+
+    template<SpaceDim N> inline
+    Point<N>::Point(const Point<N> &p)
+      :  coord_(p.coord_)
+    {
+    }
+
+
+    template<SpaceDim N> inline 
+    Point<N>::Point(const Point<N> & p, std::function<const Frame<N>& ()> f) 
+      :  coord_(f)
+    {
+      if (p.GetFrame()==f())
+	{
+	  //std::cerr << "point conversion: nothing to do..." << std::endl << std::flush;
+	  *this=p;
+	}
+
+      else if (p.GetFrame().GetReferenceFrame()==f())//Frame<N>::Global)
+	{
+	  GetPositionVector()  = p.GetFrame().GetQuaternion().Rotate(p.GetPositionVector());
+	  GetPositionVector() += p.GetFrame().GetCenter().GetPositionVector();
+	}
+
+      else if (p.GetFrame()==f().GetReferenceFrame())//Frame<N>::Global)
+	{
+	  GetPositionVector()  = f().GetQuaternion().InverseRotate(p.GetPositionVector());
+	  GetPositionVector() -= Vector<N>(f().GetCenter().GetPositionVector(),f);
+	}
+
+      else if (f()==Frame<N>::Global)
+	{
+	  GetPositionVector() = Vector<N>(p.GetPositionVector(),&Frame<N>::GetGlobal);
+	  const Frame<N> *refFrame = &p.GetFrame();
+	  while(refFrame->GetRank()>1)
+	    {
+	      GetPositionVector() += Vector<N>(refFrame->GetCenter().GetPositionVector(), &Frame<N>::GetGlobal);
+	      refFrame = &refFrame->GetReferenceFrame();
+	    }
+	  GetPositionVector() += refFrame->GetCenter().GetPositionVector();
+	}
+      
+      else 
+	{
+	  GetPositionVector() += Vector<N>(p.GetPositionVector(),f);
+	  const Frame<N> *refFrame = &p.GetFrame();
+	  while(refFrame!=&Frame<N>::Global)
+	    {
+	      GetPositionVector() += Vector<N>(refFrame->GetCenter().GetPositionVector(), f);
+	      refFrame = &refFrame->GetReferenceFrame();
+	    }
+	  
+	  refFrame = &f();
+	  while(refFrame!=&Frame<N>::Global)
+	    {
+	      GetPositionVector() -= Vector<N>(refFrame->GetCenter().GetPositionVector(), f);
+	      refFrame = &refFrame->GetReferenceFrame();
+	    }
+	}
+    }
+
+    template<SpaceDim N> inline
+    Point<N>::~Point()
+    {
+    }
+
+    // Accessors
+
+    template<SpaceDim N>
+    inline SpaceDim 
+    Point<N>::GetDimension() const
+    {
+      return coord_.dimension;
+    }
+
+    template<SpaceDim N>
+    inline Vector<N> & 
+    Point<N>::GetPositionVector()
+    {
+      return *reinterpret_cast<Vector<N> *>(this);
+    }
+
+    template<SpaceDim N>
+    inline const Vector<N> & 
+    Point<N>::GetPositionVector() const
+    {
+      return *reinterpret_cast<const Vector<N> *>(this);
+    }
+
+    template<SpaceDim N>
+    inline const Coordinate<N> &
+    Point<N>::GetCoordinate() const
+    {
+      return coord_;
+    }
+
+    template<SpaceDim N>
+    inline Coordinate<N> &
+    Point<N>::GetCoordinate()
+    {
+      return coord_;
+    }
+
+ 
+    template<SpaceDim N>
+    inline const Frame<N> & 
+    Point<N>::GetFrame() const
+    {
+      return coord_.GetFrame();
+    }
+    
+    
+    // External Operators ...
+    
+
+    // Class Operators ...
+
+    template <SpaceDim N> inline 
+    const double &
+    Point<N>::operator[](int i) const
+    { 
+      return coord_.c_[i];
+    }
+
+    template <SpaceDim N> inline 
+    double &
+    Point<N>::operator[](int i) 
+    { 
+      return coord_.c_[i];
+    }
+
+    template<SpaceDim N> inline
+    std::ostream & 
+    Point<N>::Write(std::ostream & out) const
+    {
+      std::cout.setf(std::ios::scientific, std::ios::floatfield);
+      switch (N)
+      {
+        case _3D : return out << "Point<_3D> (" << coord_[0] << ", " << coord_[1] << ", " << coord_[2] << ")"; break;
+        case _2D : return out << "Point<_2D> (" << coord_[0] << ", " << coord_[1]  << ")"; break;
+        case _1D : return out << "Point<_1D> (" << coord_[0]  << ")"; break;
+        case _0D : return out << "Point<_0D> ()"; break;
+        default : OMC_ASSERT(0); break;
+      }
+    }
+
+    template<SpaceDim N> inline
+    std::ostream & 
+    operator<<(std::ostream& out, const Point<N>& pt)
+    { 
+      std::cout.setf(std::ios::scientific, std::ios::floatfield);
+      switch (N)
+      {
+        case _3D : return out <<  pt.coord_[0] << "\t" << pt.coord_[1] << "\t"  << pt.coord_[2] <<"\t" ; break;
+        case _2D : return out << pt.coord_[0] << "\t"  << pt.coord_[1]  << "\t" ; break;
+        case _1D : return out << pt.coord_[0]  << "\t" ; break;
+        case _0D : return out << "\t" ; break;
+        default : OMC_ASSERT(0); break;
+      }
+    }
+
+    template<SpaceDim N>
+    inline Point<N> &
+    Point<N>::operator=(const Point<N> & p)
+    {
+      OMC_ASSERT(GetFrame() == p.GetFrame());
+
+      if (this == &p)
+	return *this;
+
+      coord_=p.coord_;
+
+      return *this;
+    }
+
+    template<SpaceDim N>
+    inline Point<N> &
+    Point<N>::operator=(const chrono::ChVector<double>&v)
+    {
+      GetPositionVector() = v;
+      return *this;
+    }
+    
+
+
+    template <SpaceDim N>
+    inline Point<N> 
+    Point<N>::ToGlobalFrame() const
+    {
+      const Point<N>& me = *this;
+      return Point<N>(me, &Frame<N>::GetGlobal);
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Point<N>::SetAsFirstState()
+    {
+      states_.clear();
+      SaveState();
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Point<N>::SaveState()
+    {
+      states_.push_back(std::array<double,N>());
+      std::array<double,N>& array = states_[states_.size() - 1];
+      for (int i = 0; i < N; ++i)
+	array[i] = coord_.c_[i];
+    }
+
+    template<SpaceDim N> inline 
+    unsigned int
+    Point<N>::GetStateNumber() const
+    {
+      return states_.size();
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Point<N>::ResetState()
+    {
+      if (states_.size() > 0)
+	RecoveryState(0);
+      states_.clear();
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Point<N>::RecoveryState(unsigned int i)
+    {
+      OMC_ASSERT(i < states_.size());
+      std::array<double,N>& array = states_[i];
+      for (int i = 0; i < N; ++i)
+	coord_.c_[i] = array[i];
+    }
+
+
+      template<SpaceDim N> inline 
+    std::function<const Frame<N>& ()>& 
+    Point<N>::GetFrameFunctionAccess() 
+    {
+      return coord_.GetFrameFunctionAccess();
+    }
+    
+    template<SpaceDim N> inline 
+    const std::function<const Frame<N>& ()>& 
+    Point<N>::GetFrameFunctionAccess() const 
+    {
+      return coord_.GetFrameFunctionAccess();
+    }
+
+    
+    template<SpaceDim N> inline 
+    const double* 
+    Point<N>::GetPtr() const
+    {
+      return &coord_.c_[0];
+    }
+
+    ///////////////////////////////////
+    // template specialisation : _3D //
+    ///////////////////////////////////
+
+    // Constructors ...
+
+    template<> inline 
+    Point<_3D>::Point(double x, double y, double z, std::function<const Frame<_3D>& ()> f)
+      :  coord_(x,y,z,f)
+    {
+    }
+
+#ifdef CHRONO_ENGINE
+
+    template<> inline
+    Point<_3D>::Point (const chrono::ChVector<double> & v, const Frame<_3D> & f)
+      :  coord_ (v.x, v.y, v.z, f)
+    {
+    }
+
+#endif
+
+    // Accessors ...
+
+    // External Operators ...
+
+    // Class Operators ...
+
+    // Usefull Methods
+
+    template<> inline 
+    double 
+    Point<_3D>::ComputeDistanceFrom(const Point & pt) const
+    {
+      return sqrt( (coord_.c_[0]-pt.coord_.c_[0])*(coord_.c_[0]-pt.coord_.c_[0])+
+		   (coord_.c_[1]-pt.coord_.c_[1])*(coord_.c_[1]-pt.coord_.c_[1])+
+		   (coord_.c_[2]-pt.coord_.c_[2])*(coord_.c_[2]-pt.coord_.c_[2]));
+    }
+
+  
+
+  } // namespace Geom
+}
+
+#endif
diff --git a/SRC/OpenMeca/Geom/Quaternion.cpp b/SRC/OpenMeca/Geom/Quaternion.cpp
new file mode 100755
index 0000000..a25b2b7
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Quaternion.cpp
@@ -0,0 +1,104 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org and
+// the qglviewer library : http://www.libqglviewer.com
+
+
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Matrix.hpp" 
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+
+    template<>
+    chrono::ChQuaternion<double> 
+    Quaternion<_3D>::ToChQuaternion() const
+    {
+      const Quaternion<_3D>& me = *this;
+      return chrono::ChQuaternion<double>(me.GetReal(), me[0], me[1], me[2]);
+    }
+
+
+    template<>
+    Quaternion<_3D>& Quaternion<_3D>::operator=(const chrono::ChQuaternion<double>& Q)
+    {
+     
+      q_.c_[0] = Q.e1;
+      q_.c_[1] = Q.e2;
+      q_.c_[2] = Q.e3;
+      real_ = Q.e0;
+      return (*this);
+    }
+
+    template<>
+    Vector<_3D>
+    Quaternion<_3D>::GetAxis() const
+    {
+      
+      return ToVector(GetFrameFunctionAccess()).Unit();
+    }
+
+    template<>
+    double 
+    Quaternion<_3D>::GetAngle() const
+    {
+      //assert (real_ >=-1 && real_ <=1);
+      return  2.0*acos(real_);
+    }
+
+    template<>
+    void
+    Quaternion<_3D>::GetAxisAngle(Vector<_3D>& axis, double& angle) const
+    {
+      angle = GetAngle();
+      axis = GetAxis();
+    }
+
+    template<>
+    Matrix<_3D>  
+    Quaternion<_3D>::ToRotationMatrix() const
+    {
+      std::function<const Frame<_3D>& ()> f = std::bind(&Quaternion<_3D>::GetFrameTo, std::ref(*this));
+      Matrix<_3D> m(f);
+      m[0][0] = 1. - 2.*q_[1]*q_[1] - 2*q_[2]*q_[2];
+      m[1][1] = 1. - 2.*q_[0]*q_[0] - 2*q_[2]*q_[2];
+      m[2][2] = 1. - 2.*q_[0]*q_[0] - 2*q_[1]*q_[1];
+
+      m[0][1] = 2*q_[0]*q_[1] - 2*q_[2]*real_;
+      m[1][0] = 2*q_[0]*q_[1] + 2*q_[2]*real_;
+
+      m[0][2] = 2*q_[0]*q_[2] + 2*q_[1]*real_;
+      m[2][0] = 2*q_[0]*q_[2] - 2*q_[1]*real_;
+
+      m[1][2] = 2*q_[1]*q_[2] - 2*q_[0]*real_;
+      m[2][1] = 2*q_[1]*q_[2] + 2*q_[0]*real_;
+
+      return m;
+    }
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Geom/Quaternion.hpp b/SRC/OpenMeca/Geom/Quaternion.hpp
new file mode 100755
index 0000000..82d89b2
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Quaternion.hpp
@@ -0,0 +1,836 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org and
+// the qglviewer library : http://www.libqglviewer.com
+
+
+#ifndef _OpenMeca_Geom_QUATERNION_hpp_
+#define _OpenMeca_Geom_QUATERNION_hpp_
+
+#include <cmath>
+#include <iostream>
+#include <functional>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Geom/SpaceDim.hpp"
+#include "OpenMeca/Geom/Vector.hpp"
+#include "OpenMeca/Geom/Coordinate.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+#include "ChronoEngine/core/ChQuaternion.h"
+
+
+
+
+namespace OpenMeca
+{
+  namespace Geom
+  {
+    
+    template<SpaceDim N> class Matrix;
+
+    template<SpaceDim N>
+    class Quaternion
+    {
+      template<SpaceDim M> friend std::ostream & operator<< (std::ostream& o, const Quaternion<M>& q);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Quaternion<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Vector<M> &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Quaternion<M> &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Quaternion<M> &, const double &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const double &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator+  (const Quaternion<M> &, const Quaternion<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator-  (const Quaternion<M> &, const Quaternion<M> &);
+
+    public:
+      static std::string GetStrKey(){return std::string("Quaternion" + SpaceDimUtil<N>::GetStrKey());}
+      static std::string GetStrType(){return std::string("Quaternion");}
+      static QString GetQStrType(){return QObject::tr("Quaternion");}
+
+    public:
+      //CONSTRUCTORS & DESTRUCTORS
+      Quaternion(std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      Quaternion(double , double , double , double , std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      Quaternion(double , double , double , double , std::function<const Frame<N>& ()>, const Frame<N>&);
+      Quaternion(const Vector<_3D>&, double, std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      Quaternion(const Quaternion<N> &);
+      Quaternion(const Quaternion<N> &, std::function<const Frame<N>& ()>);
+      Quaternion(const Vector<N> &, const Vector<N> &);
+      ~Quaternion();
+
+
+      //CHRONO CONVERSION
+      chrono::ChQuaternion<double> ToChQuaternion() const;
+
+     
+     //ACCESSORS
+      void SetVecFromTo(const Vector<N>& from, const Vector<N>& to);
+      void SetAxisAngle(const Vector<N>& axis, double angle);
+      void SetValue(double q0, double q1, double q2, double q3);
+      void SetFrameTo(const Frame<N>*);
+
+      const Frame<N> & GetFrameFrom() const;
+      const Frame<N> & GetFrameTo() const;
+      const Frame<N>* GetFrameToPtr() const{return frameTo_;}; 
+
+      Vector<N> GetAxis() const;
+      double GetAngle() const;
+      void GetAxisAngle(Vector<N>& axis, double& angle) const;
+      Vector<N> ToVector(std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal) const;
+
+      //OPERATORS
+      Quaternion& operator=(const Quaternion& Q);
+      Quaternion& operator=(const chrono::ChQuaternion<double>& Q);
+
+      const double& operator[](int i) const;
+      double& operator[](int i);
+
+      const double & GetReal() const;
+      double& GetReal();
+      const Coordinate<N> & GetCoordinate() const{return q_;};
+      Coordinate<N> & GetCoordinate(){return q_;};
+
+      Quaternion& operator*=(const Quaternion &Q);
+      Quaternion& operator*=(const Vector<N> &v);
+      Quaternion& operator*=(const double &d);
+      Quaternion& operator+=(const Quaternion &Q);
+      Quaternion& operator-=(const Quaternion &Q);
+
+
+      //UTILS
+      void Rotate(const Vector<N> & v_in, Vector<N> & v_out) const;
+      void InverseRotate(const Vector<N> & v_in, Vector<N> & v_out) const;
+
+      Vector<N> Rotate(const Vector<N> & v_in) const;
+      Vector<N> InverseRotate(const Vector<N> & v_in) const;
+
+      void Clear();
+      const Quaternion& GetConjugate() const;
+      void Invert();
+      void Negate();
+      double GetNorm() const;
+      double GetSquaredNorm() const;
+      double Normalize();
+      Quaternion GetNormalized() const;
+      SpaceDim GetDimension() const ;
+      Matrix<N> ToRotationMatrix() const;
+      std::ostream & Write (std::ostream & out) const;
+
+            std::function<const Frame<N>& ()>& GetFrameFunctionAccess() {return q_.GetFrameFunctionAccess();}
+      const std::function<const Frame<N>& ()>& GetFrameFunctionAccess() const {return q_.GetFrameFunctionAccess();}
+
+      unsigned int GetStateNumber() const;
+      void SetAsFirstState();
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+
+
+    private:
+      Quaternion(double , double , double , double , 
+		 std::function<const Frame<N>& ()>, const Frame<N>&, Quaternion*);
+      void EqualComponent(const Quaternion<_3D> &);
+      // - BOOST SERIALIZATION - //
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive & ar, const unsigned int );
+      
+   
+    private:
+      double real_;
+      Coordinate<N> q_;
+      const Frame<N> *frameTo_;
+      std::vector< std::array<double,N+1> > states_;
+      Quaternion<N>* conjugate_;
+    };
+
+
+    // - BOOST SERIALIZATION - //  
+    template<SpaceDim N>
+    template<class Archive>
+    inline void 
+    Quaternion<N>::serialize(Archive & ar, const unsigned int ) 
+    {
+      ar  &BOOST_SERIALIZATION_NVP(q_);
+      ar  &BOOST_SERIALIZATION_NVP(real_);
+    }
+
+    //EXTERN OPERATOR
+    template<SpaceDim N>
+    std::ostream & operator<< (std::ostream& o, const Quaternion<N>& q);
+
+    template<SpaceDim N>
+    Quaternion<N> operator*  (const Quaternion<N> &, const Vector<N> &);
+
+    template<SpaceDim N>
+    Quaternion<N> operator*  (const Vector<N> &, const Quaternion<N> &);
+
+    template<SpaceDim N>
+    Quaternion<N> operator*  (const Quaternion<N> &, const Quaternion<N> &);
+
+    template<SpaceDim N>
+    Quaternion<N> operator*  (const Quaternion<N> &, const double &);
+
+    template<SpaceDim N>
+    Quaternion<N> operator*  (const double &, const Quaternion<N> &);
+
+    template<SpaceDim N>
+    Quaternion<N> operator+  (const Quaternion<N> &, const Quaternion<N> &);
+
+    template<SpaceDim N>
+    Quaternion<N> operator-  (const Quaternion<N> &, const Quaternion<N> &);
+
+
+    template<SpaceDim N>
+    inline SpaceDim
+    Quaternion<N>::GetDimension() const
+    {
+      return q_.dimension;
+    }
+
+    template<SpaceDim N>
+    inline const Frame<N> & 
+    Quaternion<N>::GetFrameFrom() const
+    {
+      return q_.GetFrame();
+    }
+
+    template<SpaceDim N>
+    inline const Frame<N> & 
+    Quaternion<N>::GetFrameTo() const
+    {
+      OMC_ASSERT(frameTo_!=0);
+      return *frameTo_;
+    }
+
+    template<SpaceDim N>
+    inline const double &
+    Quaternion<N>::GetReal() const
+    {
+      return real_;
+    }
+
+    template<SpaceDim N>
+    inline double &
+    Quaternion<N>::GetReal()
+    {
+      return real_;
+    }
+
+    template<SpaceDim N>
+    inline const double &
+    Quaternion<N>::operator[](int i) const
+    {
+      OMC_ASSERT(i>=0 && i <N);
+      return q_.c_[i];    
+    }
+
+    template<SpaceDim N>
+    inline double &
+    Quaternion<N>::operator[](int i) 
+    {
+      OMC_ASSERT(i>=0 && i <N);
+     return q_.c_[i];
+    }
+
+    template<SpaceDim N>
+    inline void
+    Quaternion<N>::SetFrameTo(const Frame<N>* frameTo)
+    {
+      frameTo_ = frameTo;
+    }
+
+    template<SpaceDim N> inline
+    void 
+    Quaternion<N>::SetVecFromTo(const Vector<N>& from, const Vector<N>& to)
+    {
+      OMC_ASSERT(GetFrameFrom()==from.GetFrame());
+      OMC_ASSERT(GetFrameFrom()==to.GetFrame());
+      const float epsilon = 1E-10f;
+      
+      const float fromSqNorm = from.GetSquaredNorm();
+      const float toSqNorm   = to.GetSquaredNorm();
+      // Identity Quaternion when one vector is null
+      if ((fromSqNorm < epsilon) || (toSqNorm < epsilon))
+	{
+	  q_[0]=q_[1]=q_[2]=0.;
+	  real_=1.;
+	}
+      else
+	{
+	  Vector<N> axis = from^to;
+	  const float axisSqNorm = axis.GetSquaredNorm();
+	  
+	  // Aligned vectors, pick any axis, not aligned with from or to
+	  if (axisSqNorm < epsilon)
+	    {
+	      axis = from.GetOrthogonalVector();
+	    }
+	  
+	  double angle = asin(sqrt(axisSqNorm / (fromSqNorm * toSqNorm)));
+	  
+	  if (from*to < 0.0)
+	    {
+	      angle = M_PI-angle;
+	    }
+	  
+	  SetAxisAngle(axis, angle);
+	}
+
+    }
+     
+    template<SpaceDim N> inline
+    Quaternion<N>::Quaternion(const Vector<N> &from, const Vector<N> &to)
+      :q_(from.GetFrame()), frameTo_(&Frame<N>::Null), conjugate_(0)
+    {
+      SetVecFromTo(from,to);
+    }
+
+    template<SpaceDim N> inline
+    Quaternion<N>::~Quaternion()
+    {
+      if (conjugate_ != 0)
+	{
+	  assert(conjugate_->conjugate_ == this);
+	  conjugate_->conjugate_ = 0;
+	  delete conjugate_;
+	}
+    }
+    
+
+
+    template<SpaceDim N> inline 
+    unsigned int
+    Quaternion<N>::GetStateNumber() const
+    {
+      return states_.size();
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Quaternion<N>::SetAsFirstState()
+    {
+      states_.clear();
+      SaveState();
+    }
+
+
+    template<SpaceDim N> inline 
+    void
+    Quaternion<N>::SaveState()
+    {
+      states_.push_back(std::array<double,N+1>());
+      std::array<double,N+1>& array = states_[states_.size() - 1];
+      for (int i = 0; i < N; ++i)
+	array[i] = q_.c_[i];
+      array[N] = real_;
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Quaternion<N>::ResetState()
+    {
+      if (states_.size() > 0)
+	RecoveryState(0);
+      states_.clear();
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Quaternion<N>::RecoveryState(unsigned int i)
+    {
+      OMC_ASSERT(i < states_.size());
+      std::array<double,N+1>& array = states_[i];
+      for (int i = 0; i < N; ++i)
+	q_.c_[i] = array[i];
+      real_ = array[N];
+      
+    }
+
+
+    //***********************************************************
+    //3D SPECIALISATION
+
+    template<>
+    inline void
+    Quaternion<_3D>::SetAxisAngle(const Vector<_3D>& axis, double angle)
+    {
+      OMC_ASSERT(GetFrameFrom()==axis.GetFrame());
+      const double norm = axis.GetNorm();
+      // if (norm < epsilon)
+      //   {
+      //     q_.c_[0] = 0.0; 
+      //     q_.c_[1] = 0.0;
+      //     q_.c_[2] = 0.0;
+      //     real_ = 1.0;
+      //    }
+      // else
+      // {
+      const double sin_half_angle = sin(angle / 2.0);
+      q_.c_[0] = sin_half_angle*axis.coord_.c_[0]/norm;
+      q_.c_[1] = sin_half_angle*axis.coord_.c_[1]/norm;
+      q_.c_[2] = sin_half_angle*axis.coord_.c_[2]/norm;
+      real_ = cos(angle / 2.0);
+      //}
+    }
+
+
+    //
+    // Constructors
+    //
+    template<> inline
+    Quaternion<_3D>::Quaternion(std::function<const Frame<_3D>& ()>f)
+      : real_(1.), q_(0.,0.,0.,f), frameTo_(&Frame<_3D>::Null), conjugate_(0)
+    {
+     
+    }
+
+    template<> inline
+    Quaternion<_3D>::Quaternion(const Vector<_3D>& axis, double angle, std::function<const Frame<_3D>& ()> f)
+      : real_(1.), q_(0.,0.,0.,f), frameTo_(&Frame<_3D>::Null), conjugate_(0)
+    {
+      SetAxisAngle(axis, angle);
+    }
+
+    template<> inline
+    Quaternion<_3D>::Quaternion(double q0, double q1, double q2, double real, std::function<const Frame<_3D>& ()> f)
+      : real_(real), q_(q0,q1,q2,f), frameTo_(&Frame<_3D>::Null), conjugate_(0)
+    {
+    }
+
+    template<> inline
+    Quaternion<_3D>::Quaternion(double q0, double q1, double q2, double real, std::function<const Frame<_3D>& ()> f, const Frame<_3D>& to)
+      :real_(real), q_(q0,q1,q2,f), frameTo_(&to), conjugate_(0)
+    {
+    }
+
+    
+    template<> inline
+    Quaternion<_3D>::Quaternion(const Quaternion<_3D>& Q)
+      : real_(Q.real_), q_(Q.q_), frameTo_(&Frame<_3D>::Null), conjugate_(0)
+    {
+    }
+
+
+
+
+    template<> inline 
+    std::ostream&
+    operator<<(std::ostream& o, const Quaternion<_3D>& q)
+    {
+      return o << q.q_.c_[0] << '\t' << q.q_.c_[1] << '\t' << q.q_.c_[2] << '\t' << q.GetReal();
+    }
+
+    template<> inline 
+    Quaternion<_3D>
+    operator*(const Quaternion<_3D>& q1, const Quaternion<_3D>& q2)
+    {
+       return Quaternion<_3D> (q1.real_*q2.q_.c_[0]  + q1.q_.c_[0]*q2.real_  + q1.q_.c_[1]*q2.q_.c_[2] - q1.q_.c_[2]*q2.q_.c_[1],
+			 q1.real_*q2.q_.c_[1]        + q1.q_.c_[1]*q2.real_  + q1.q_.c_[2]*q2.q_.c_[0] - q1.q_.c_[0]*q2.q_.c_[2],
+			 q1.real_*q2.q_.c_[2]        + q1.q_.c_[2]*q2.real_  + q1.q_.c_[0]*q2.q_.c_[1] - q1.q_.c_[1]*q2.q_.c_[0],
+			 q1.real_*q2.real_ - q1.q_.c_[0]* q2.q_.c_[0]        - q1.q_.c_[1]*q2.q_.c_[1] - q1.q_.c_[2]*q2.q_.c_[2],
+			 q1.GetFrameFunctionAccess(), q2.GetFrameTo() );
+    }
+
+    template<> inline 
+    Quaternion<_3D>
+    operator*(const Quaternion<_3D>& q, const Vector<_3D>& v)
+    {
+      return Quaternion<_3D>(q.real_*v.coord_.c_[0] + q.q_.c_[1]*v.coord_.c_[2] - q.q_.c_[2]*v.coord_.c_[1],
+                             q.real_*v.coord_.c_[1] + q.q_.c_[2]*v.coord_.c_[0] - q.q_.c_[0]*v.coord_.c_[2],
+                             q.real_*v.coord_.c_[2] + q.q_.c_[0]*v.coord_.c_[1] - q.q_.c_[1]*v.coord_.c_[0],
+                             - v.coord_.c_[0]*q.q_.c_[0] - q.q_.c_[1]*v.coord_.c_[1] - q.q_.c_[2]*v.coord_.c_[2] );
+    }
+
+    template<> inline 
+    Quaternion<_3D>
+    operator*  (const Vector<_3D>& v, const Quaternion<_3D>& q)
+    {
+      return Quaternion<_3D>(q.real_*v.coord_.c_[0] + v.coord_.c_[1]*q.q_.c_[2] - v.coord_.c_[2]*q.q_.c_[1],
+                             q.real_*v.coord_.c_[1] + v.coord_.c_[2]*q.q_.c_[0] - v.coord_.c_[0]*q.q_.c_[2],
+                             q.real_*v.coord_.c_[2] + v.coord_.c_[0]*q.q_.c_[1] - v.coord_.c_[1]*q.q_.c_[0],
+                             - q.q_.c_[0]*v.coord_.c_[0] - v.coord_.c_[1]*q.q_.c_[1] - v.coord_.c_[2]*q.q_.c_[2] );
+    }
+
+    template<> inline 
+    Quaternion<_3D>
+    operator*  (const Quaternion<_3D>& q, const double& d)
+    {
+      return Quaternion<_3D>(  q.q_.c_[0]*d , q.q_.c_[1]*d ,  q.q_.c_[2]*d  , q.real_*d );
+    }
+
+
+    template<> inline 
+    Quaternion<_3D>
+    operator*  (const double& d, const Quaternion<_3D>& q)
+    {
+      return Quaternion<_3D>(  q.q_.c_[0]*d , q.q_.c_[1]*d ,  q.q_.c_[2]*d  , q.real_*d );
+    }
+
+    template<> inline 
+    Quaternion<_3D>
+    operator+  (const Quaternion<_3D>& q1, const Quaternion<_3D>& q2)
+    {
+      return Quaternion<_3D>(  q1.q_.c_[0]+q2.q_.c_[0] , q1.q_.c_[1]+q2.q_.c_[1] ,  q1.q_.c_[2]+q2.q_.c_[2]  , q1.real_+q2.real_  );
+    }
+
+    template<> inline 
+    Quaternion<_3D>
+    operator-  (const Quaternion<_3D>& q1, const Quaternion<_3D>& q2)
+    {
+      return Quaternion<_3D>(  q1.q_.c_[0]-q2.q_.c_[0] , q1.q_.c_[1]-q2.q_.c_[1] ,  q1.q_.c_[2]-q2.q_.c_[2]  , q1.real_-q2.real_  );
+    }
+    
+    template<> inline 
+    void
+    Quaternion<_3D>::SetValue(double q0, double q1, double q2, double q3)
+    {
+      q_.c_[0]=q0;
+      q_.c_[1]=q1;
+      q_.c_[2]=q2;
+      real_=q3;
+    }
+
+    template<> inline 
+    Quaternion<_3D>& Quaternion<_3D>::operator=(const Quaternion<_3D>& Q)
+    {
+      OMC_ASSERT(&GetFrameFrom() == &Q.GetFrameFrom());
+      //OMC_ASSERT(frameTo_ == &Q.GetFrameTo());
+      q_.c_[0] = Q.q_.c_[0];
+      q_.c_[1] = Q.q_.c_[1];
+      q_.c_[2] = Q.q_.c_[2];
+      real_ = Q.real_;
+      return (*this);
+    }
+    
+   
+    
+
+    template<> inline 
+    Quaternion<_3D>&
+    Quaternion<_3D>::operator*=(const Vector<_3D> &v)
+    {
+      const double q0(q_.c_[0]);
+      const double q1(q_.c_[1]);
+      const double q2(q_.c_[2]);
+      const double real(real_);
+      q_.c_[0] =   real*v.coord_.c_[0] + q1*v.coord_.c_[2] - q2*v.coord_.c_[1];
+      q_.c_[1] =   real*v.coord_.c_[1] + q2*v.coord_.c_[0] - q0*v.coord_.c_[2];
+      q_.c_[2] =   real*v.coord_.c_[2] + q0*v.coord_.c_[1] - q1*v.coord_.c_[0];
+      real_ = - v.coord_.c_[0]*q0   - q1*v.coord_.c_[1] - q2*v.coord_.c_[2];
+      return *this;
+    }
+    
+    template<> inline 
+    Quaternion<_3D>&
+    Quaternion<_3D>::operator*=(const double &d)
+    {
+      q_.c_[0] *= d;
+      q_.c_[1] *= d;
+      q_.c_[2] *= d;
+      real_ *= d;
+      return *this;
+    }
+
+    template<> inline 
+    Quaternion<_3D>&
+    Quaternion<_3D>::operator*=(const Quaternion<_3D> &q)
+    {
+      const double q0(q_.c_[0]);
+      const double q1(q_.c_[1]);
+      const double q2(q_.c_[2]);
+      const double real(real_);
+      q_.c_[0] = real*q.q_.c_[0]        + q0*q.GetReal() + q1*q.q_.c_[2] - q2*q.q_.c_[1];
+      q_.c_[1] = real*q.q_.c_[1]        + q1*q.GetReal() + q2*q.q_.c_[0] - q0*q.q_.c_[2];
+      q_.c_[2] = real*q.q_.c_[2]        + q2*q.GetReal() + q0*q.q_.c_[1] - q1*q.q_.c_[0];
+      real_ = real*q.GetReal() - q0*q.q_.c_[0]        - q1*q.q_.c_[1] - q2*q.q_.c_[2];
+      return *this;
+    }
+
+    template<> inline 
+    Quaternion<_3D>&
+    Quaternion<_3D>::operator+=(const Quaternion<_3D> &Q)
+    {
+      q_.c_[0] += Q.q_.c_[0];
+      q_.c_[1] += Q.q_.c_[1];
+      q_.c_[2] += Q.q_.c_[2];
+      real_ += Q.real_;
+      return *this;
+    }
+
+    template<> inline 
+    Quaternion<_3D>&
+    Quaternion<_3D>::operator-=(const Quaternion<_3D> &Q)
+    {
+      q_.c_[0] -= Q.q_.c_[0];
+      q_.c_[1] -= Q.q_.c_[1];
+      q_.c_[2] -= Q.q_.c_[2];
+      real_ -= Q.real_;
+      return *this;
+    }
+
+    template<> inline 
+    const Quaternion<_3D>&
+    Quaternion<_3D>::GetConjugate() const
+    {
+      //Need to invert frameFrom & frameTo
+      Quaternion<_3D>& me = const_cast<Quaternion<_3D>&>(*this);
+      if (me.conjugate_ == 0)
+	{
+	  me.conjugate_= new Quaternion<_3D>(-q_.c_[0], -q_.c_[1], -q_.c_[2], real_, 
+					     GetFrameFunctionAccess(), GetFrameFrom());
+	  me.conjugate_->conjugate_ = &me;
+	}
+      else
+	{
+	  me.conjugate_->q_.c_[0] = -q_.c_[0];
+	  me.conjugate_->q_.c_[1] = -q_.c_[1];
+	  me.conjugate_->q_.c_[2] = -q_.c_[2];
+	  me.conjugate_->real_ = real_;
+	}
+      assert(conjugate_->conjugate_ == this);
+      return *me.conjugate_;
+    }
+
+    template<> inline 
+    double
+    Quaternion<_3D>::GetSquaredNorm() const
+    {
+      return (q_.c_[0]*q_.c_[0] + q_.c_[1]*q_.c_[1] + q_.c_[2]*q_.c_[2] + real_*real_);
+    }
+
+    template<> inline 
+    double
+    Quaternion<_3D>::GetNorm() const
+    {
+      return sqrt(q_.c_[0]*q_.c_[0] + q_.c_[1]*q_.c_[1] + q_.c_[2]*q_.c_[2] + real_*real_);
+    }
+
+    template<> inline 
+    double
+    Quaternion<_3D>::Normalize()
+    {
+      const double norm = sqrt(q_.c_[0]*q_.c_[0] + q_.c_[1]*q_.c_[1] + q_.c_[2]*q_.c_[2] + real_*real_);
+      q_.c_[0] /= norm;
+      q_.c_[1] /= norm;
+      q_.c_[2] /= norm;
+      real_ /= norm;
+      return norm;
+    }
+
+    template<> inline 
+    Quaternion<_3D>
+    Quaternion<_3D>::GetNormalized() const
+    {
+      double Q[4];
+      const double norm = sqrt(q_.c_[0]*q_.c_[0] + q_.c_[1]*q_.c_[1] + q_.c_[2]*q_.c_[2] + real_*real_);
+      Q[0] = q_.c_[0] / norm;
+      Q[1] = q_.c_[1] / norm;
+      Q[2] = q_.c_[2] / norm;
+      Q[3] = real_ / norm;
+      return Quaternion<_3D>(Q[0], Q[1], Q[2], Q[3]);
+    }
+
+    template<> inline 
+    void
+    Quaternion<_3D>::Rotate(const Vector<_3D>& v_in, Vector<_3D>& v_out) const
+    {
+      const double q00 = 2.0 * q_.c_[0] * q_.c_[0];
+      const double q11 = 2.0 * q_.c_[1] * q_.c_[1];
+      const double q22 = 2.0 * q_.c_[2] * q_.c_[2];
+      const double q01 = 2.0 * q_.c_[0] * q_.c_[1];
+      const double q02 = 2.0 * q_.c_[0] * q_.c_[2];
+      const double q03 = 2.0 * q_.c_[0] * real_;
+      const double q12 = 2.0 * q_.c_[1] * q_.c_[2];
+      const double q13 = 2.0 * q_.c_[1] * real_;
+      const double q23 = 2.0 * q_.c_[2] * real_;
+
+      v_out.coord_.c_[0] = (1.0 - q11 - q22) * (v_in[0]) + (q01 - q23) * v_in[1] + (q02 + q13) * v_in[2];
+      v_out.coord_.c_[1] = (q01 + q23) * v_in[0] + (1.0 - q22 - q00) * v_in[1] + (q12 - q03) * v_in[2];
+      v_out.coord_.c_[2] = (q02 - q13) * v_in[0] + (q12 + q03) * v_in[1] + (1.0 - q11 - q00) * v_in[2];
+    }
+
+    template<> inline 
+    void
+    Quaternion<_3D>::InverseRotate(const Vector<_3D> & v_in, Vector<_3D> & v_out) const
+    {
+      const double q00 = 2.0 * q_.c_[0] * q_.c_[0];
+      const double q11 = 2.0 * q_.c_[1] * q_.c_[1];
+      const double q22 = 2.0 * q_.c_[2] * q_.c_[2];
+      const double q01 = 2.0 * q_.c_[0] * q_.c_[1];
+      const double q02 = 2.0 * q_.c_[0] * q_.c_[2];
+      const double q03 = - 2.0 * q_.c_[0] * real_;
+      const double q12 = 2.0 * q_.c_[1] * q_.c_[2];
+      const double q13 = - 2.0 * q_.c_[1] * real_;
+      const double q23 = - 2.0 * q_.c_[2] * real_;
+      
+      v_out.coord_.c_[0] = (1.0 - q11 - q22)*v_in[0] + (q01 - q23)*v_in[1] + (q02 + q13)*v_in[2];
+      v_out.coord_.c_[1] = (q01 + q23)*v_in[0] + (1.0 - q22 - q00)*v_in[1] + (q12 - q03)*v_in[2];
+      v_out.coord_.c_[2] = (q02 - q13)*v_in[0] + (q12 + q03)*v_in[1] + (1.0 - q11 - q00)*v_in[2];
+    }
+
+    template<> inline 
+    Vector<_3D>
+    Quaternion<_3D>::Rotate(const Vector<_3D> & v_in) const
+    {
+      const double q00 = 2.0 * q_.c_[0] * q_.c_[0];
+      const double q11 = 2.0 * q_.c_[1] * q_.c_[1];
+      const double q22 = 2.0 * q_.c_[2] * q_.c_[2];
+      const double q01 = 2.0 * q_.c_[0] * q_.c_[1];
+      const double q02 = 2.0 * q_.c_[0] * q_.c_[2];
+      const double q03 = 2.0 * q_.c_[0] * real_;
+      const double q12 = 2.0 * q_.c_[1] * q_.c_[2];
+      const double q13 = 2.0 * q_.c_[1] * real_;
+      const double q23 = 2.0 * q_.c_[2] * real_;
+      
+      return Vector<_3D> ((1.0 - q11 - q22)*v_in[0] + (q01 - q23)*v_in[1] + (q02 + q13)*v_in[2],
+			  (q01 + q23)*v_in[0] + (1.0 - q22 - q00)*v_in[1] + (q12 - q03)*v_in[2],
+			  (q02 - q13)*v_in[0] + (q12 + q03)*v_in[1] + (1.0 - q11 - q00)*v_in[2],
+			  GetFrameFunctionAccess());
+      
+    }
+    
+    template<> inline
+    Vector<_3D>
+    Quaternion<_3D>::InverseRotate(const Vector<_3D> & v_in) const
+    {
+      const double q00 = 2.0 * q_.c_[0] * q_.c_[0];
+      const double q11 = 2.0 * q_.c_[1] * q_.c_[1];
+      const double q22 = 2.0 * q_.c_[2] * q_.c_[2];
+      const double q01 = 2.0 * q_.c_[0] * q_.c_[1];
+      const double q02 = 2.0 * q_.c_[0] * q_.c_[2];
+      const double q03 = - 2.0 * q_.c_[0] * real_;
+      const double q12 = 2.0 * q_.c_[1] * q_.c_[2];
+      const double q13 = - 2.0 * q_.c_[1] * real_;
+      const double q23 = - 2.0 * q_.c_[2] * real_;
+      
+      
+      std::function<const Frame<_3D>& ()> f = std::bind(&Quaternion<_3D>::GetFrameTo, std::ref(*this));
+
+      return Vector<_3D> ((1.0 - q11 - q22)*v_in[0] + (q01 - q23)*v_in[1] + (q02 + q13)*v_in[2],
+			  (q01 + q23)*v_in[0] + (1.0 - q22 - q00)*v_in[1] + (q12 - q03)*v_in[2],
+			  (q02 - q13)*v_in[0] + (q12 + q03)*v_in[1] + (1.0 - q11 - q00)*v_in[2],
+			  f);
+    }
+
+    template<> inline 
+    void
+    Quaternion<_3D>::Clear()
+    {
+      q_.c_[0] = 0.;
+      q_.c_[1] = 0.;
+      q_.c_[2] = 0.;
+      real_ = 0.;
+    }
+    
+    
+    template<> inline 
+    Vector<_3D> 
+    Quaternion<_3D>::ToVector(std::function<const Frame<_3D>& ()> f) const
+    {
+      return Vector<_3D>(q_.c_[0],q_.c_[1],q_.c_[2], f);
+    }
+
+    template<> inline 
+    void 
+    Quaternion<_3D>::EqualComponent(const Quaternion<_3D> &Q)
+    {
+      q_.c_[0] = Q.q_.c_[0];
+      q_.c_[1] = Q.q_.c_[1];
+      q_.c_[2] = Q.q_.c_[2];
+      real_ = Q.real_;
+    }
+
+    template<> inline 
+    std::ostream &
+    Quaternion<_3D>::Write(std::ostream & out) const
+    {
+      return out << "Quaternion<_3D> (" << q_.c_[0] << ", " << q_.c_[1] << ", " << q_.c_[2] << ", " << real_ << ")";
+    }
+      
+    //ENDS OF 3D SPECIALIZATION
+    //***********************************
+
+    template<SpaceDim N> inline
+    Quaternion<N>::Quaternion(const Quaternion<N>& q, std::function<const Frame<N>& ()> f)
+      : real_(q.real_), q_(q.q_.c_[0],q.q_.c_[1],q.q_.c_[2],f), 
+	frameTo_(&q.GetFrameTo()), conjugate_(0)
+    {
+      
+      if (q.GetFrameTo() != Frame<_3D>::Null && q.GetFrameTo()==f() && q.GetFrameFrom()==f())
+	{
+	  OMC_ASSERT_MSG(0, "&q.GetFrameTo()==&f && &q.GetFrameFrom()==&f");
+	}
+      
+      else if (q.GetFrameTo() != Frame<_3D>::Null && q.GetFrameTo() == f())
+	{
+	  OMC_ASSERT_MSG(0, "&q.GetFrameTo()!=0 && &q.GetFrameTo()==&f");
+	  //frameTo_ = &q.GetFrameFrom();
+	  //this->operator=(q.GetConjugate());
+	}
+
+      else if (q.GetFrameFrom() == f())
+	{
+	  EqualComponent(q);
+	}
+      else
+	{
+	  //TODO : Faire une méthode plus propre et surtout plus rapide
+	  //No common Frame
+	  std::vector< const Quaternion<_3D>* > quaternions;
+	  const Frame<N> *refFrame = &q.GetFrameFrom();
+	  quaternions.push_back(&q);
+	  while(refFrame!=&Frame<N>::Global)
+	    {
+	      
+	      quaternions.push_back(&refFrame->GetQuaternion());
+	      refFrame = &refFrame->GetReferenceFrame();
+	    }
+	  
+	  //
+	  // Build Parent Frame tree  -> to be able to scan inverse tree later
+	  //
+	  std::vector<const Frame<N>*> vectorFrame;
+	  refFrame = &f();
+	  while(refFrame!=&Frame<N>::Global)
+	    {
+	      vectorFrame.push_back(refFrame);
+	      refFrame = &refFrame->GetReferenceFrame();
+	    }
+	  
+	  for (int i = vectorFrame.size()-1; i>=0; --i)
+	    {
+	      quaternions.push_back(&vectorFrame[i]->GetQuaternion().GetConjugate());
+	    }
+
+	  EqualComponent(*quaternions[quaternions.size()-1]);
+	  for (int i = quaternions.size()-2; i>=0; --i)
+	    {
+	      (*this)*=(*quaternions[i]);
+	    }
+	}
+    }
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Geom/SpaceDim.cpp b/SRC/OpenMeca/Geom/SpaceDim.cpp
new file mode 100644
index 0000000..550d40c
--- /dev/null
+++ b/SRC/OpenMeca/Geom/SpaceDim.cpp
@@ -0,0 +1,37 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org
+
+
+#include "OpenMeca/Geom/SpaceDim.hpp"
+
+namespace OpenMeca
+{
+  namespace Geom 
+  {
+    template<> std::string SpaceDimUtil<_0D>::GetStrKey(){return std::string("0D");}
+    template<> std::string SpaceDimUtil<_1D>::GetStrKey(){return std::string("1D");}
+    template<> std::string SpaceDimUtil<_2D>::GetStrKey(){return std::string("2D");}
+    template<> std::string SpaceDimUtil<_3D>::GetStrKey(){return std::string("3D");}
+  } 
+}
+
diff --git a/SRC/OpenMeca/Geom/SpaceDim.hpp b/SRC/OpenMeca/Geom/SpaceDim.hpp
new file mode 100755
index 0000000..caec214
--- /dev/null
+++ b/SRC/OpenMeca/Geom/SpaceDim.hpp
@@ -0,0 +1,52 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org
+
+
+#ifndef _OpenMeca_Geom_SpaceDim1_H
+#define _OpenMeca_Geom_SpaceDim1_H
+
+#include <string>
+
+namespace OpenMeca
+{
+  namespace Geom 
+  {
+    
+    enum SpaceDim
+      {
+	_0D =0,
+	_1D =1,
+	_2D =2,
+	_3D =3
+      };
+
+    template<SpaceDim N>
+    struct SpaceDimUtil
+    {
+      static std::string GetStrKey();
+    };
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Geom/Vector.cpp b/SRC/OpenMeca/Geom/Vector.cpp
new file mode 100644
index 0000000..170aefd
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Vector.cpp
@@ -0,0 +1,134 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org and
+// the qglviewer library : http://www.libqglviewer.com
+
+
+#include "OpenMeca/Geom/Vector.hpp" 
+#include "OpenMeca/Geom/Frame.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Geom 
+  {
+    template<> 
+    chrono::ChVector<double> 
+    Vector<_3D>::ToChVector() const
+    {
+      const Vector<_3D>& me = *this;
+      return chrono::ChVector<double>(me[0], me[1], me[2]);
+    }
+
+    template<> 
+    qglviewer::Vec
+    Vector<_3D>::ToQGLVector() const
+    {
+      const Vector<_3D>& me = *this;
+      return qglviewer::Vec(me[0], me[1], me[2]);
+    }
+
+
+    template<>
+    void 
+    Vector<_3D>::ProjectOnAxis(const Vector<_3D> & direction)
+    {
+      const double dirSquaredNorm = direction.GetSquaredNorm();
+      if ( dirSquaredNorm < 1.0E-10)
+	{
+	  std::cerr << "Vector<_3D>::ProjectOnAxis: axis direction is not normalized (norm=" << direction.GetNorm() << ")" << std::endl;
+	}
+      *this = (((*this)*direction) / dirSquaredNorm) * direction;
+    }
+
+    template<>
+    void 
+    Vector<_3D>::ProjectOnPlane(const Vector<_3D> & normal)
+    {
+      const double normSquaredNorm = normal.GetSquaredNorm();
+      if ( normSquaredNorm < 1.0E-10)
+	{
+	  std::cerr << "Vector<_3d>::ProjectOnPlane: plane normal is not normalized (norm=" << normal.GetNorm() <<")" << std::endl;
+	}
+      *this -= (((*this)*normal) / normSquaredNorm) * normal;
+    }
+    
+    template<>
+    Vector<_3D> 
+    Vector<_3D>::GetOrthogonalVector() const
+    {
+      // Find smallest component. Keep equal case for null values.
+      if ((fabs(coord_[1]) >= 0.9*fabs(coord_[0])) && (fabs(coord_[2]) >= 0.9*fabs(coord_[0])))
+	return Vector<_3D>(0.0, -coord_[2], coord_[1], GetFrameFunctionAccess());
+      else
+	if ((fabs(coord_[0]) >= 0.9*fabs(coord_[1])) && (fabs(coord_[2]) >= 0.9*fabs(coord_[1])))
+	  return Vector<_3D>(-coord_[2], 0.0, coord_[0], GetFrameFunctionAccess());
+	else
+	  return Vector<_3D>(-coord_[1], coord_[0], 0.0, GetFrameFunctionAccess());
+    }
+
+    template<>
+    Vector<_3D> &
+    Vector<_3D>::operator= (const chrono::ChVector<double>& v)
+    {
+      
+      coord_[0] = v.x;
+      coord_[1] = v.y;
+      coord_[2] = v.z;
+      return *this;
+    }
+
+
+    template<>
+    void
+    Vector<_3D>::Draw(const double scale) const
+    {
+      const Geom::Vector<_3D> vec1 = (*this) * scale;
+      const Geom::Vector<_3D> vec2 = vec1.GetOrthogonalVector().Unit();
+      const Geom::Vector<_3D> vec3 = (vec1^ vec2).Unit();
+
+      glLineWidth(1.0f);
+      glBegin(GL_LINES);
+      glVertex3f(0., 0., 0.);
+      glVertex3dv(vec1.GetPtr());
+      glEnd();
+
+      Geom::Vector<_3D> vecArrow1;
+      Geom::Vector<_3D> vecArrow2;
+      float r = 0.02 * vec1.GetNorm();
+      float l = 0.1  * vec1.GetNorm();
+      for (double i=0; i<=2*M_PI; i=i+0.2)
+	{
+	  glBegin(GL_TRIANGLE_STRIP);
+	  vecArrow1 = - l*vec1.Unit() + r*vec2.Unit()*cos(i)     + r*vec3.Unit()*sin(i) ;
+	  vecArrow2 = - l*vec1.Unit() + r*vec2.Unit()*cos(i+0.2) + r*vec3.Unit()*sin(i+0.2);
+	  glVertex3dv(vec1.GetPtr());
+	  glVertex3dv((vec1 + vecArrow1).GetPtr());
+	  glVertex3dv((vec1 + vecArrow2).GetPtr());
+	  glEnd();
+	}
+      glPopMatrix();
+    }
+
+
+  } // namespace Geom
+}
diff --git a/SRC/OpenMeca/Geom/Vector.hpp b/SRC/OpenMeca/Geom/Vector.hpp
new file mode 100644
index 0000000..d614da2
--- /dev/null
+++ b/SRC/OpenMeca/Geom/Vector.hpp
@@ -0,0 +1,851 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired of the "libGeometrical" from 
+// the GranOO workbench : http://www.granoo.org and
+// the qglviewer library : http://www.libqglviewer.com
+
+
+#ifndef _OpenMeca_Geom_Vector_hpp_
+#define _OpenMeca_Geom_Vector_hpp_
+
+#include <vector>
+
+#include <iostream>
+#include <string>
+#include <cmath>
+
+#include "OpenMeca/Geom/SpaceDim.hpp"
+#include "OpenMeca/Geom/Coordinate.hpp"
+
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "Serialization/array.hpp"
+
+#include "ChronoEngine/core/ChVector.h"
+#include <QGLViewer/qglviewer.h>
+
+//
+// This is the Free Vector in a dimension N workspace.
+//
+
+
+namespace OpenMeca
+{
+
+  namespace Geom
+  {
+
+    //*************************
+    // EXTERN OPERATOR
+
+    template<SpaceDim N>
+    std::ostream& operator<< (std::ostream &, const Vector<N> &);
+
+    template<SpaceDim N>
+    Vector<N> operator+ (const Vector<N> &, const Vector<N> &);
+
+    template<SpaceDim N>
+    Vector<N> operator- (const Vector<N> &, const Vector<N> &);
+
+    template<SpaceDim N>
+    Vector<N> operator- (const Vector<N> &);
+
+    template<SpaceDim N>
+    Vector<N> operator* (const Vector<N> &, const double &);
+
+    template<SpaceDim N>
+    Vector<N> operator* (const double &, const Vector<N> &);
+
+    template<SpaceDim N>
+    Vector<N> operator/ (const Vector<N> &, const double &);
+
+    template<SpaceDim N>
+    double   operator* (const Vector<N> &, const Vector<N> &);
+
+    template<SpaceDim N>
+    Vector<N> operator* (const Vector<N> &, const typename Vector<N>::DoubleArray &);
+
+    template<SpaceDim N>
+    Vector<N> operator^ (const Vector<N> &, const Vector<N> &);
+
+    template<SpaceDim N>
+    bool     operator!= (const Vector<N> &, const Vector<N> &);
+
+    template<SpaceDim N>
+    bool     operator== (const Vector<N> &, const Vector<N> &);
+
+
+    template<SpaceDim N> class Point;
+
+    template<SpaceDim N>
+    class Vector
+    {
+
+    public: // Data
+      
+      static std::string GetStrKey(){return std::string("Vector" + SpaceDimUtil<N>::GetStrKey());}
+      static std::string GetStrType(){return std::string("Vector");}
+      static QString GetQStrType(){return QObject::tr("Vector");}
+
+      typedef double DoubleArray[N];
+
+      friend class Quaternion<N>;
+      //Vector Operator
+      template<SpaceDim M> friend std::ostream& operator<< (std::ostream &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator+ (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator- (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator- (const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator* (const Vector<M> &, const double &);
+      template<SpaceDim M> friend Vector<M> operator* (const double &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator/ (const Vector<M> &, const double &);
+      template<SpaceDim M> friend double   operator* (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Vector<M> operator* (const Vector<M> &, const typename Vector<M>::DoubleArray &);
+      template<SpaceDim M> friend Vector<M> operator^ (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend bool     operator!= (const Vector<M> &, const Vector<M> &);
+      template<SpaceDim M> friend bool     operator== (const Vector<M> &, const Vector<M> &);
+      //Quaternion Operator
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Quaternion<M> &, const Vector<M> &);
+      template<SpaceDim M> friend Quaternion<M> operator*  (const Vector<M> &, const Quaternion<M> &);
+      //Matrix Operator
+      friend Vector<_3D> operator*(const Matrix<_3D>&, const Vector<_3D> &);
+
+    public: // Methods
+      explicit Vector (chrono::ChVector<double>&, 
+		       std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      explicit Vector (std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      Vector (const Vector<N> &);
+      explicit Vector (const Vector<N> &, std::function<const Frame<N>& ()>);
+      explicit Vector (const Coordinate<N, Cartesian> &);
+      explicit Vector (const Point<N> &);
+      explicit Vector (const Point<N> &, const Point<N>&);
+      Vector (double x, double y, double z, std::function<const Frame<N>& ()> = &Frame<N>::GetGlobal);
+      virtual ~Vector();
+
+      //CONVERSION
+      chrono::ChVector<double> ToChVector() const;
+      qglviewer::Vec ToQGLVector() const;
+
+      //DRAW 
+      void Draw(const double scale) const;
+
+      // CAST TO POINT
+      Point<N> & GetPoint();
+      const Point<N> & GetPoint() const;
+
+      Vector & operator= (const Vector &);
+      Vector & operator= (const chrono::ChVector<double>&);
+
+      SpaceDim GetDimension() const ;
+      const Frame<N> & GetFrame() const;
+
+      Coordinate<N, Cartesian> & GetCoordinate();
+      const Coordinate<N, Cartesian> & GetCoordinate() const;
+
+      void Clear();
+
+      void Set(const Point<N> &,const Point<N> &);
+      void Minus(const Vector<N> &,const Vector<N> &);
+
+      std::ostream & Write (std::ostream &) const;
+      std::ostream & XmlWrite (std::ostream &) const;
+
+      // OPERATOR
+      void operator+= (const Vector &);
+      void operator-= (const Vector &);
+      void operator*= (double k);
+      void operator/= (double k);
+
+      const double & operator[] (int i) const;
+      double& operator[] (int i);
+
+      // BOOLEAN ALGEBRA
+      bool IsNull() const;
+
+      // NORLMALIZING OPERATION
+      double GetSquaredNorm() const;
+      double GetNorm() const;
+      double GetNorm1() const;
+      double Normalize();
+      Vector Unit() const;
+
+      // PROJECTION
+      void ProjectOnAxis (const Vector & direction);
+      void ProjectOnPlane (const Vector & normal);
+      Vector GetOrthogonalVector() const;
+
+      // Changing Frame
+      Vector ToGlobalFrame() const;
+      Vector ToLocalFrame(const Frame<N>&) const;
+
+      void ToGlobalFrame(Vector<N>&) const;
+      void ToLocalFrame(const Frame<N>&, Vector<N>&) const;
+      
+      std::function<const Frame<N>& ()>& GetFrameFunctionAccess(); 
+      const std::function<const Frame<N>& ()>& GetFrameFunctionAccess() const;
+
+      // STATE 
+      unsigned int GetStateNumber() const;
+      void SetAsFirstState();
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+      const std::vector< std::array<double,N> >& GetRecordedState();
+
+      const double* GetPtr() const;
+
+    private:
+      Coordinate<N, Cartesian> coord_;
+      std::vector< std::array<double,N> > states_;
+
+      //BOOST SERIALIZATION       
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar , const unsigned int ) 
+      {
+	ar & BOOST_SERIALIZATION_NVP( coord_);
+      }
+
+    };
+
+    //
+    // Definition of static generic template data must be in header file:
+    //
+
+    
+
+    //
+    // Vorbidden non-specialized methods (should be specialized)
+    //
+
+    //
+    // Template methods
+    //
+
+    // Constructors ...
+    template<SpaceDim N> inline
+    Vector<N>::Vector (chrono::ChVector<double>& v,
+		       std::function<const Frame<N>& ()> f)
+      : coord_ ( f)
+    {
+      coord_.c_[0] = v.x;
+      coord_.c_[1] = v.y; 
+      coord_.c_[2] = v.z;
+    }
+
+    template<SpaceDim N> inline
+    Vector<N>::Vector (std::function<const Frame<N>& ()> f)
+        : coord_ (f)
+    {
+    }
+
+    template<SpaceDim N> inline
+    Vector<N>::Vector (const Vector<N> & v)
+        : coord_ (v.coord_)
+    {
+    }
+
+    template<SpaceDim N> inline
+    Vector<N>::Vector (const Vector<N> & v, std::function<const Frame<N>& ()> f)
+        :  coord_ (f)
+    {
+      if (v.GetFrame()==f())
+	{
+	  *this=v;
+	}
+
+      else if (v.GetFrame().GetReferenceFrame()==f())
+	{
+	  *this  = v.GetFrame().GetQuaternion().Rotate(v);
+	}
+
+      else if (v.GetFrame()==f().GetReferenceFrame())
+	{
+	  *this  = f().GetQuaternion().InverseRotate(v);
+	}
+      
+      else 
+	{
+	  Quaternion<N> q(v.GetFrame().GetQuaternion(),f);
+	  //q.Rotate(v,*this); //TODO::Debug this function
+	  *this = q.Rotate(v);
+	}
+    }
+
+
+    template<SpaceDim N> inline
+    Vector<N>::Vector (const Point<N> & p)
+        : coord_ (p.GetCoordinate())
+    {
+      assert (typeid (typename Point<N>::myCoordSystem) == typeid (Cartesian));
+    }
+
+    template<SpaceDim N> inline
+    Vector<N>::Vector (const Point<N> & p1, const Point<N> & p2)
+      : coord_ (p2.coord_ - p1.coord_)
+    {
+       assert (typeid (typename Coordinate<N, Cartesian>::myCoordSystem) == typeid (Cartesian));
+    }
+
+    template<SpaceDim N> inline
+    Vector<N>::~Vector ()
+    {
+    }
+
+
+    // Conversions ...
+
+    template<SpaceDim N> inline
+    Point<N> &
+    Vector<N>::GetPoint()
+    {
+      return *reinterpret_cast<Point<N> *> (this);
+    }
+
+    template<SpaceDim N> inline
+    const Point<N> &
+    Vector<N>::GetPoint() const
+    {
+      return *reinterpret_cast<const Point<N> *> (this);
+    }
+
+    // Accessors ...
+
+    template<SpaceDim N> inline
+    SpaceDim
+    Vector<N>::GetDimension() const
+    {
+      return coord_.dimension;
+    }
+
+    template<SpaceDim N> inline
+    const Frame<N> &
+    Vector<N>::GetFrame() const
+    {
+      return coord_.GetFrame();
+    }
+
+    template<SpaceDim N> inline
+    Coordinate<N, Cartesian> &
+    Vector<N>::GetCoordinate()
+    {
+      return coord_;
+    }
+
+    template<SpaceDim N> inline
+    const Coordinate<N, Cartesian> &
+    Vector<N>::GetCoordinate() const
+    {
+      return coord_;
+    }
+
+    template <SpaceDim N> inline
+    const double &
+    Vector<N>::operator[] (int i) const
+    {
+      return coord_.c_[i];
+    }
+
+    template <SpaceDim N> inline
+    double &
+    Vector<N>::operator[] (int i)
+    {
+      return coord_.c_[i];
+    }
+
+    // External Operators ...
+
+    template<SpaceDim N> inline
+    bool
+    operator== (const Vector<N> &a, const Vector<N> &b)
+    {
+      return (a -b).GetSquaredNorm() < Coordinate<N>::epsilon;
+    }
+
+    template<SpaceDim N> inline
+    bool
+    operator!= (const Vector<N> &a, const Vector<N> &b)
+    {
+      return ! (a == b);
+    }
+
+    template<SpaceDim N> inline
+    std::ostream&
+    operator<< (std::ostream &out, const Vector<N> &v)
+    {
+      std::cout.setf(std::ios::scientific, std::ios::floatfield);
+      switch (N)
+      {
+        case _3D : return out << v.coord_[0] << "\t" << v.coord_[1] << "\t"  << v.coord_[2] <<"\t" ; break;
+        case _2D : return out << v.coord_[0] << "\t"  << v.coord_[1]  << "\t" ; break;
+        case _1D : return out << v.coord_[0]  << "\t" ; break;
+        case _0D : return out << "\t" ; break;
+        default : OMC_ASSERT(0); break;
+	}
+    }
+
+
+    template<SpaceDim N> inline
+    Vector<N>
+    operator* (const double & k, const Vector<N> &v)
+    {
+      return v*k;
+    }
+
+
+    template<SpaceDim N> inline
+    double
+    operator* (const Vector<N> &a, const Vector<N> &b)
+    {
+      assert (a.GetFrame() == b.GetFrame());
+      double sum = 0;
+
+      for (int i = 0; i < N; ++i)
+      {
+        sum += a.coord_.c_[i] * b.coord_.c_[i];
+      }
+
+      return sum;
+    }
+
+    template<SpaceDim N> inline
+    Vector<N>
+    operator* (const Vector<N> &a, const typename Vector<N>::DoubleArray & b)
+    {
+      Vector<N> v(a);
+      for (int i = 0; i < N; ++i)
+      {
+        v.coord_.c_[i] *= b[i];
+      }
+      return v;
+    }
+
+    template<SpaceDim N> inline
+    double
+    GetAngleBetweenUnitVectors (const Vector<N> &a, const Vector<N> &b)
+    {
+      return acos(a*b);
+    }
+    
+    // Class Operators ...
+
+    template<SpaceDim N> inline
+    Vector<N> &
+    Vector<N>::operator= (const Vector<N> & v)
+    {
+      coord_ = v.coord_;
+      return *this;
+    }
+
+    
+
+    template<SpaceDim N> inline
+    void
+    Vector<N>::operator+= (const Vector<N> & a)
+    {
+      coord_ += a.coord_;
+    }
+
+    template<SpaceDim N> inline
+    void
+    Vector<N>::operator-= (const Vector<N> & a)
+    {
+      coord_ -= a.coord_;
+    }
+
+    template<SpaceDim N> inline
+    void
+    Vector<N>::operator*= (double k)
+    {
+      coord_ *= k;
+    }
+
+    template<SpaceDim N> inline
+    void
+    Vector<N>::operator/= (double k)
+    {
+      coord_ /= k;
+    }
+
+    template<SpaceDim N> inline
+    double
+    Vector<N>::GetSquaredNorm() const
+    {
+      double sum = 0;
+
+      for (int i = 0; i < N; ++i)
+      {
+        sum += coord_.c_[i] * coord_.c_[i];
+      }
+
+      return sum;
+    }
+
+    template<SpaceDim N> inline
+    double
+    Vector<N>::GetNorm() const
+    {
+      return sqrt (GetSquaredNorm());
+    }
+
+    template<SpaceDim N> inline
+    double
+    Vector<N>::GetNorm1() const
+    {
+      double sum = 0;
+
+      for (int i = 0; i < N; ++i)
+      {
+        sum += fabs(coord_.c_[i]);
+      }
+      return sum;
+    }
+
+    // Other Methods
+
+    template<SpaceDim N> inline
+    void
+    Vector<N>::Clear()
+    {
+      for (int i = 0; i < N; ++i)
+      {
+        coord_.c_[i]=0.;
+      }
+    }
+
+    template<SpaceDim N> inline
+    void
+    Vector<N>::Set(const Point<N> &p1, const Point<N> &p2)
+    {
+      coord_  = p2.coord_;
+      coord_ -= p1.coord_;
+    }
+    
+    template<SpaceDim N> inline
+    void
+    Vector<N>::Minus(const Vector<N> &v1, const Vector<N> &v2)
+    {
+      coord_  = v1.coord_;
+      coord_ -= v2.coord_;
+    }
+
+    template <SpaceDim N> inline
+    bool
+    Vector<N>::IsNull() const
+    {
+      return (GetSquaredNorm() < Coordinate<N>::epsilon);
+    }
+
+    template<SpaceDim N> inline
+    Vector<N>
+    Vector<N>::Unit() const
+    {
+      Vector<N> v (*this);
+      v.Normalize();
+      return v;
+    }
+
+    template <SpaceDim N>  inline 
+    Vector<N> 
+    Vector<N>::ToGlobalFrame() const
+    {
+      //Return expression of this vector in the globalFrame.
+      //Available only if the rank of the vector is 1.
+      //Usefull to boost computation
+      assert (GetFrame().GetRank()==1);
+      return GetFrame().GetQuaternion().Rotate(*this);
+    }
+
+    template <SpaceDim N> inline 
+    Vector<N> 
+    Vector<N>::ToLocalFrame(const Frame<N>& f) const
+    {
+      //Return expression of this vector in local frame.
+      //Available only if the rank of the vector is 0 (express in GlobalFrame) and localFrame is 1.
+      //Usefull to boost computation
+      assert (GetFrame().GetRank()==0 && f.GetRank()==1);
+      return f.GetQuaternion().InverseRotate(*this);
+    }
+    
+
+    template <SpaceDim N> inline
+    void 
+    Vector<N>::ToGlobalFrame(Vector<N>& v_out) const
+    {
+      //Return expression of this vector in local frame in v_out.
+      //Similar to "ToGlobalFrame()" method without temporary copy (faster)
+      //Usefull to boost computation
+      assert (GetFrame().GetRank()==1);
+      GetFrame().GetQuaternion().Rotate(*this, v_out);
+    }
+      
+    template <SpaceDim N> inline
+    void
+    Vector<N>::ToLocalFrame(const Frame<N>& f, Vector<N>& v_out) const
+    {
+      //Return expression of this vector in local frame.
+      //Similar to "ToLocalFrame(const Frame<N>&)" method without temporary copy (faster)
+      //Usefull to boost computation
+      assert (GetFrame().GetRank()==0 && f.GetRank()==1);
+      f.GetQuaternion().InverseRotate(*this, v_out);
+    }
+
+    template<SpaceDim N> inline 
+    std::ostream &
+    Vector<N>::Write (std::ostream & out) const
+    {
+      std::cout.setf (std::ios::scientific, std::ios::floatfield);
+
+      switch (N)
+      {
+
+      case _3D :
+        return out << "Vector<_3D> (" << coord_.c_[0] << ", " << coord_.c_[1] << ", " << coord_.c_[2] << ")";
+        break;
+
+      case _2D :
+        return out << "Vector<_2D> (" << coord_.c_[0] << ", " << coord_.c_[1]  << ")";
+        break;
+
+      case _1D :
+        return out << "Vector<_1D> (" << coord_.c_[0]  << ")";
+        break;
+
+      case _0D :
+        return out << "Vector<_0D> ()";
+        break;
+
+      default :
+        assert (0);
+        break;
+      }
+    }
+
+    template<SpaceDim N> inline 
+    std::ostream &
+    Vector<N>::XmlWrite (std::ostream & out) const
+    {
+      std::cout.setf (std::ios::scientific, std::ios::floatfield);
+      out << "<" << GetStrKey() << "> " ;
+      coord_.XmlWrite (out);
+      out << "</" << GetStrKey() << "> " ;
+      return out;
+    }
+
+    
+    template<SpaceDim N> inline 
+    unsigned int
+    Vector<N>::GetStateNumber() const
+    {
+      return states_.size();
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Vector<N>::SetAsFirstState()
+    {
+      states_.clear();
+      SaveState();
+    }
+
+
+    template<SpaceDim N> inline 
+    void
+    Vector<N>::SaveState()
+    {
+      states_.push_back(std::array<double,N>());
+      std::array<double,N>& array = states_[states_.size() - 1];
+      for (int i = 0; i < N; ++i)
+	array[i] = coord_.c_[i];
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Vector<N>::ResetState()
+    {
+      if (states_.size() > 0)
+	RecoveryState(0);
+      states_.clear();
+    }
+
+    template<SpaceDim N> inline 
+    void
+    Vector<N>::RecoveryState(unsigned int i)
+    {
+      OMC_ASSERT(i < states_.size());
+      std::array<double,N>& array = states_[i];
+      for (int i = 0; i < N; ++i)
+	coord_.c_[i] = array[i];
+    }
+
+    template<SpaceDim N> inline 
+    const std::vector< std::array<double,N> >&
+    Vector<N>::GetRecordedState()
+    {
+      return states_;
+    }
+
+
+    template<SpaceDim N> inline 
+    const double* 
+    Vector<N>::GetPtr() const
+    {
+      return &coord_.c_[0];
+    }
+
+
+    template<SpaceDim N> inline 
+    std::function<const Frame<N>& ()>& 
+    Vector<N>::GetFrameFunctionAccess() 
+    {
+      return coord_.GetFrameFunctionAccess();
+    }
+    
+    template<SpaceDim N> inline 
+    const std::function<const Frame<N>& ()>& 
+    Vector<N>::GetFrameFunctionAccess() const 
+    {
+      return coord_.GetFrameFunctionAccess();
+    }
+
+
+    
+    ///////////////////////////////////
+    // template specialisation : _3D //
+    ///////////////////////////////////
+
+    // Constructors ...
+    
+
+    template<> inline
+    Vector<_3D>::Vector (double x, double y, double z, std::function<const Frame<_3D>& ()> f)
+        : coord_ (x, y, z, f)
+    {
+    }
+
+    // Accessors ...
+
+    // External Operators ...
+
+    template<> inline
+    Vector<_3D>
+    operator+ (const Vector<_3D> &a, const Vector<_3D> &b)
+    {
+      assert (a.GetFrame() == b.GetFrame());
+      return Vector<_3D> (a.coord_.c_[0] + b.coord_.c_[0], a.coord_.c_[1] + b.coord_.c_[1], a.coord_.c_[2] + b.coord_.c_[2], a.GetFrameFunctionAccess());
+    }
+
+    template<> inline
+    Vector<_3D>
+    operator- (const Vector<_3D> &a, const Vector<_3D> &b)
+    {
+      assert (a.GetFrame() == b.GetFrame());
+      return Vector<_3D> (a.coord_.c_[0] - b.coord_.c_[0], a.coord_.c_[1] - b.coord_.c_[1], a.coord_.c_[2] - b.coord_.c_[2], a.GetFrameFunctionAccess());
+    }
+
+    template<> inline
+    Vector<_3D>
+    operator- (const Vector<_3D> &a)
+    {
+      return Vector<_3D> (-a.coord_.c_[0], -a.coord_.c_[1], -a.coord_.c_[2], a.GetFrameFunctionAccess());
+    }
+
+    template<> inline
+    Vector<_3D>
+    operator* (const Vector<_3D> &a, const double &d)
+    {
+      return Vector<_3D> (d*a.coord_.c_[0], d*a.coord_.c_[1], d*a.coord_.c_[2], a.GetFrameFunctionAccess());
+    }
+
+    template<> inline
+    Vector<_3D>
+    operator/ (const Vector<_3D> &a, const double &k)
+    {
+      if (fabs (k) == 0.)
+      {
+        std::cerr << "operator/ : dividing a vector by a quasi-null value : " << k << std::endl << std::flush;
+        assert (0);
+        // TODO : generate an exception !!!
+      }
+
+      return Vector<_3D> (a.coord_.c_[0] / k, a.coord_.c_[1] / k, a.coord_.c_[2] / k, a.GetFrameFunctionAccess());
+    }
+
+    // Class Operators ...
+
+    template<> inline
+    double
+    Vector<_3D>::GetNorm() const
+    {
+      return sqrt(coord_.c_[0]*coord_.c_[0] + coord_.c_[1]*coord_.c_[1] + coord_.c_[2]*coord_.c_[2]);
+    }
+
+    // Other Methods ...
+
+    template<> inline
+    Vector<_3D>
+    operator^ (const Vector<_3D> &a, const Vector<_3D> &b)
+    {
+      assert (a.GetFrame() == b.GetFrame());
+      return Vector<_3D> (a.coord_.c_[1]*b.coord_.c_[2] - a.coord_.c_[2]*b.coord_.c_[1],
+                          a.coord_.c_[2]*b.coord_.c_[0] - a.coord_.c_[0]*b.coord_.c_[2],
+                          a.coord_.c_[0]*b.coord_.c_[1] - a.coord_.c_[1]*b.coord_.c_[0],
+                          a.GetFrameFunctionAccess());
+    }
+
+    template<> inline
+    double
+    Vector<_3D>::Normalize()
+    {
+      const double n = GetNorm();
+
+      if (n == 0.)
+      {
+        // std::cerr << "vector3d::normalize: normalizing a null vector (norm=" << n << "), the vector stay null." << std::endl;
+        coord_.c_[0] = 0.;
+        coord_.c_[1] = 0.;
+        coord_.c_[2] = 0.;
+        return 0.;
+      }
+      else
+      {
+        *this /= n;
+        return n;
+      }
+    }
+    
+    ///////////////////////////////////
+    // template specialisation : _2D //
+    ///////////////////////////////////
+
+    // Accessors ...
+
+    // External Operators ...
+
+    // Class Operators ...
+
+    // Other Methods ...
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Gui/AbstractTreeItem.cpp b/SRC/OpenMeca/Gui/AbstractTreeItem.cpp
new file mode 100644
index 0000000..7290812
--- /dev/null
+++ b/SRC/OpenMeca/Gui/AbstractTreeItem.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/AbstractTreeItem.hpp"
+#include "OpenMeca/Gui/TreeView.hpp"
+#include "OpenMeca/Core/UserItem.hpp"
+
+namespace OpenMeca
+{
+  
+  namespace Gui
+  {
+
+    TreeView* AbstractTreeItem::treeView_ = 0;
+
+    void AbstractTreeItem::SetTreeView(TreeView& treeView)
+    {
+      OMC_ASSERT_MSG(treeView_==0, "The treeview is already affected");
+      treeView_ = &treeView;
+    }
+
+    TreeView& AbstractTreeItem::GetTreeView()
+    {
+      OMC_ASSERT_MSG(treeView_!=0, "The treeview is null");
+      return *treeView_;
+    }
+
+     AbstractTreeItem::AbstractTreeItem(QTreeWidgetItem* parent)
+       :QTreeWidgetItem(parent,0),
+	relatedItemIsDeleted_(false)
+    {
+      GetTreeView().AddAbstractTreeItem(*this);
+    }
+
+    AbstractTreeItem::~AbstractTreeItem()
+    {
+      GetTreeView().EraseAbstractTreeItem(*this);
+    }
+    
+    void 
+    AbstractTreeItem::Update()
+    {
+      QTreeWidgetItem::setIcon(0,GetItem().GetIcon());
+      QTreeWidgetItem::setText(0,GetItem().GetName().c_str());
+    }
+
+    void 
+    AbstractTreeItem::RelatedItemIsDeleted()
+    {
+      relatedItemIsDeleted_ = true;
+    }
+    
+    bool
+    AbstractTreeItem::IsRelatedItemIsDeleted() const
+    {
+      return relatedItemIsDeleted_;
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/AbstractTreeItem.hpp b/SRC/OpenMeca/Gui/AbstractTreeItem.hpp
new file mode 100644
index 0000000..5945570
--- /dev/null
+++ b/SRC/OpenMeca/Gui/AbstractTreeItem.hpp
@@ -0,0 +1,71 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_AbstractTreeItem_hpp
+#define OpenMeca_Gui_AbstractTreeItem_hpp
+
+#include <QTreeWidgetItem>
+#include <QIcon>
+
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    class Item;
+  }
+  
+
+  namespace Gui
+  {
+
+    class TreeView;
+    
+    class AbstractTreeItem : public QTreeWidgetItem, public Core::AutoRegister<AbstractTreeItem>
+    {
+    
+    public:
+      static void SetTreeView(TreeView&);
+      static TreeView& GetTreeView();
+
+      AbstractTreeItem(QTreeWidgetItem* parent);
+      virtual ~AbstractTreeItem();
+
+      void Update();
+      virtual Core::Item& GetItem() = 0;
+    
+      void RelatedItemIsDeleted();
+      bool IsRelatedItemIsDeleted() const;
+
+    private:
+      AbstractTreeItem();                        //Not allowed
+      AbstractTreeItem(const AbstractTreeItem&);             //Not Allowed
+      AbstractTreeItem& operator=(const AbstractTreeItem&);  //Not Allowed
+
+    private:
+      static TreeView* treeView_;
+      bool relatedItemIsDeleted_;
+
+    };
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Dialog.cpp b/SRC/OpenMeca/Gui/Dialog/Dialog.cpp
new file mode 100644
index 0000000..b744a28
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Dialog.cpp
@@ -0,0 +1,132 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/Dialog.hpp"
+#include "OpenMeca/Gui/Prop/Prop.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    Dialog::Dialog()
+      :QWidget(&MainWindow::Get().GetDialogContainer()),
+       widgets_(),
+       action_(0)
+    {
+     
+    }
+
+    
+    Dialog::~Dialog()
+    {
+      Core::SetOf<Prop>::it it;
+      for (it = widgets_.Begin() ; it != widgets_.End(); it++ )
+	(*it)->ParentDeleted();
+    }
+
+    void 
+    Dialog::Show_CallBack()
+    {
+      MainWindow::Get().DialogContainerIsBusy(*this);
+    }
+
+    void 
+    Dialog::Hide_CallBack()
+    {
+      MainWindow::Get().DialogContainerIsFree(*this);
+    }
+
+    void 
+    Dialog::AddProp(Prop& w)
+    {
+      widgets_.AddItem(w);
+    }
+
+    bool 
+    Dialog::Check()
+    {
+      Core::SetOf<Prop>::it it;
+      for (it = widgets_.Begin() ; it != widgets_.End(); it++ )
+	if ((*it)->Check()==false)
+	  return false;
+      return true;
+    }
+
+    
+
+    void
+    Dialog::ApplyChangement()
+    {
+      Core::SetOf<Prop>::it it;
+      for (it = widgets_.Begin() ; it != widgets_.End(); it++ )
+	(*it)->ApplyChangement();      
+    }
+
+    void
+    Dialog::CancelChangement()
+    {
+      Core::SetOf<Prop>::it it;
+      for (it = widgets_.Begin() ; it != widgets_.End(); it++ )
+	(*it)->CancelChangement();      
+    }
+
+
+    void 
+    Dialog::SetAction(QAction& action)
+    {
+      action_ = &action;
+    }
+    
+    QAction&
+    Dialog::GetAction()
+    {
+      OMC_ASSERT_MSG(action_ != 0, "The action is null");
+      return *action_;
+    }
+
+    void 
+    Dialog::Reset()
+    {
+      action_ = 0;
+      Core::SetOf<Prop>::it it;
+      for (it = widgets_.Begin() ; it != widgets_.End(); it++ )
+	(*it)->Reset();
+    }
+
+    void 
+    Dialog::AddActionToHistoric()
+    {
+      MainWindow::Get().AddToHistoric(GetAction());
+      
+    }
+
+    bool
+    Dialog::IsPossibleToClose()
+    {
+      return true;
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Dialog.hpp b/SRC/OpenMeca/Gui/Dialog/Dialog.hpp
new file mode 100644
index 0000000..f610577
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Dialog.hpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Dialog_hpp 
+#define OpenMeca_Gui_Dialog_hpp 
+
+#include <QWidget>
+#include <QAction>
+
+#include "OpenMeca/Core/SetOf.hpp"
+
+
+namespace OpenMeca
+{
+
+  namespace Gui
+  {
+    
+    class Prop;
+
+
+    class Dialog : public QWidget
+    {
+      Q_OBJECT
+      
+     protected:
+      Dialog();
+      virtual ~Dialog();
+      
+    public:
+      void AddProp(Prop&);
+      void RemoveProp(Prop& w){widgets_.RemoveItem(w);}; // Must be here du to mingw32 link bug
+
+      virtual bool Check();
+      virtual void Ok() = 0;
+      virtual void Cancel() = 0;
+      virtual bool IsPossibleToClose(); 
+
+    protected : 
+      void Show_CallBack();
+      void Hide_CallBack();
+      virtual void ApplyChangement();
+      virtual void CancelChangement();
+      void SetAction(QAction& action);
+      QAction& GetAction();
+      virtual void Reset();
+      void AddActionToHistoric();
+
+
+    protected:
+      Core::SetOfBase<Prop> widgets_;
+      
+    private:
+      QAction* action_;
+
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Dialog.pro b/SRC/OpenMeca/Gui/Dialog/Dialog.pro
new file mode 100644
index 0000000..a22a8ff
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Dialog.pro
@@ -0,0 +1,78 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+include(./Shape/Shape.pro)
+include(./Physic/Physic.pro)
+
+FORMS   += Gui/Dialog/DialogUserItem.ui \
+           Gui/Dialog/DialogCheckDeleteItem.ui \
+           Gui/Dialog/DialogSimulation.ui
+
+HEADERS += Gui/Dialog/Dialog.hpp \
+           Gui/Dialog/DialogUserItem.hpp \
+           Gui/Dialog/DialogNone.hpp \
+           Gui/Dialog/DialogBody.hpp \
+           Gui/Dialog/DialogLinkT.hpp \
+           Gui/Dialog/DialogPartUserJunction.hpp \
+           Gui/Dialog/DialogPartUserPoint.hpp \
+           Gui/Dialog/DialogSystemSetting.hpp \
+           Gui/Dialog/DialogCheckDeleteItem.hpp \
+           Gui/Dialog/DialogLink.hpp \
+           Gui/Dialog/DialogLinkMotor.hpp \
+           Gui/Dialog/DialogLinkLinearMotor.hpp \
+           Gui/Dialog/DialogLinkScrew.hpp \
+           Gui/Dialog/DialogLinkGear.hpp \
+           Gui/Dialog/DialogLinkPulley.hpp \
+           Gui/Dialog/DialogLinkRackPinion.hpp \
+           Gui/Dialog/DialogLinkSpring.hpp \
+           Gui/Dialog/DialogPartUserPipe.hpp \
+           Gui/Dialog/DialogPartUserShapeT.hpp \
+           Gui/Dialog/DialogSimulation.hpp \
+           Gui/Dialog/DialogScales.hpp \
+           Gui/Dialog/DialogGravity.hpp \
+           Gui/Dialog/DialogScene.hpp \
+           Gui/Dialog/DialogSystemSettingT.hpp \
+           Gui/Dialog/DialogUserItemT.hpp \
+           Gui/Dialog/DialogSensorT.hpp \
+           Gui/Dialog/DialogLoadT.hpp \
+           Gui/Dialog/DialogVariable.hpp
+           
+
+SOURCES += Gui/Dialog/Dialog.cpp \
+           Gui/Dialog/DialogBody.cpp \
+           Gui/Dialog/DialogUserItem.cpp \
+           Gui/Dialog/DialogCheckDeleteItem.cpp \
+           Gui/Dialog/DialogLink.cpp \
+           Gui/Dialog/DialogLinkMotor.cpp \
+           Gui/Dialog/DialogLinkLinearMotor.cpp \
+           Gui/Dialog/DialogLinkScrew.cpp \
+           Gui/Dialog/DialogLinkGear.cpp \
+           Gui/Dialog/DialogLinkPulley.cpp \
+           Gui/Dialog/DialogLinkRackPinion.cpp \
+           Gui/Dialog/DialogLinkSpring.cpp \
+           Gui/Dialog/DialogPartUserJunction.cpp \
+           Gui/Dialog/DialogPartUserPipe.cpp \
+           Gui/Dialog/DialogPartUserPoint.cpp \
+           Gui/Dialog/DialogSimulation.cpp \
+           Gui/Dialog/DialogScales.cpp \
+           Gui/Dialog/DialogGravity.cpp \
+           Gui/Dialog/DialogScene.cpp \
+           Gui/Dialog/DialogSystemSetting.cpp \           
+           Gui/Dialog/DialogVariable.cpp
+
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogBody.cpp b/SRC/OpenMeca/Gui/Dialog/DialogBody.cpp
new file mode 100644
index 0000000..ef1aacd
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogBody.cpp
@@ -0,0 +1,115 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include "OpenMeca/Gui/Dialog/DialogBody.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+    DialogBody::DialogBody()
+      :DialogUserItemT<Item::Body>(),
+       id_(this),
+       color_(this),
+       ground_(this),
+       showReferenceFrame_(this),
+       showMassCenter_(this),
+       mass_(this),
+       massCenter_(this),
+       inertia_(this),
+       staticFrictionCoef_(this),
+       slidingFrictionCoef_(this)
+    {
+      id_.SetLabel(QObject::tr("Name"));
+      
+      color_.SetLabel(QObject::tr("Color"));
+      
+      ground_.SetLabel(QObject::tr("Clamped"));
+      showReferenceFrame_.SetLabel(QObject::tr("Show local frame"));
+      showMassCenter_.SetLabel(QObject::tr("Show mass center"));
+      
+      mass_.SetDimension(Util::Dimension::Get("Mass"));
+      mass_.SetLabel(QObject::tr("Mass"));
+      mass_.AddCondition(new Core::Superior<double>(0.));
+      
+      massCenter_.SetLabel(QObject::tr("Center"));
+      massCenter_.SetDimension(Util::Dimension::Get("Length"));
+      
+      inertia_.SetDimension(Util::Dimension::Get("Inertia"));
+      inertia_.SetLabel(QObject::tr("Inertia"));
+      inertia_.AddComponentCondition(new Core::Superior<double>(0.));
+      
+      staticFrictionCoef_.SetLabel(QObject::tr("Static friction coeficient"));
+      staticFrictionCoef_.SetDimension(Util::Dimension::Get("Null"));
+
+      slidingFrictionCoef_.SetLabel(QObject::tr("Sliding friction coeficient"));
+      slidingFrictionCoef_.SetDimension(Util::Dimension::Get("Null"));
+
+      // Init table
+      GetPropTree().Add(id_);
+      GetPropTree().Add(color_);
+      GetPropTree().Add(ground_);
+      GetPropTree().Add(showReferenceFrame_);
+      GetPropTree().Add(showMassCenter_);
+      GetPropTree().Add(mass_);
+      GetPropTree().Add(massCenter_);
+      GetPropTree().Add(inertia_);
+      GetPropTree().Add(staticFrictionCoef_);
+      GetPropTree().Add(slidingFrictionCoef_);
+
+    }
+  
+    DialogBody::~DialogBody()
+    {
+    }
+
+    void
+    DialogBody::Init()
+    {
+       id_.SetValue(GetCurrentItem().GetName());
+       color_.SetValue(GetCurrentItem().GetColor());
+       ground_.SetValue(GetCurrentItem().GetFixed());
+       showReferenceFrame_.SetValue(GetCurrentItem().IsReferenceFrameShown());
+       showMassCenter_.SetValue(GetCurrentItem().IsMassCenterShown());
+       mass_.SetValue(GetCurrentItem().GetMass());
+       massCenter_.SetValue(GetCurrentItem().GetMassCenter());
+       inertia_.SetValue(GetCurrentItem().GetInertia());
+       staticFrictionCoef_.SetValue(GetCurrentItem().GetStaticFrictionCoef());
+       slidingFrictionCoef_.SetValue(GetCurrentItem().GetSlidingFrictionCoef());
+
+    }
+
+    void
+    DialogBody::ApplyChangement()
+    {
+      DialogUserItemT<Item::Body>::ApplyChangement();
+      GetCurrentItem().InitAndManageState();      
+    }
+
+   
+
+  
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogBody.hpp b/SRC/OpenMeca/Gui/Dialog/DialogBody.hpp
new file mode 100644
index 0000000..023bd6c
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogBody.hpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Dialog_DialogBody_hpp
+#define OpenMeca_Gui_Dialog_DialogBody_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+
+#include "OpenMeca/Gui/Prop/PropBool.hpp"
+#include "OpenMeca/Gui/Prop/PropColor.hpp"
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropMatrix.hpp"
+#include "OpenMeca/Gui/Prop/PropPoint.hpp"
+#include "OpenMeca/Gui/Prop/PropExprPoint.hpp"
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    class Body;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogBody : public DialogUserItemT<Item::Body>, 
+		       public Core::Singleton<DialogBody>
+    {
+      
+    public:
+      DialogBody();
+      ~DialogBody();
+
+    private:
+      void Init();
+
+    protected:
+      virtual void ApplyChangement();
+
+    private:
+      PropString id_;
+      PropColor color_;
+      PropBool ground_;
+      PropBool showReferenceFrame_;
+      PropBool showMassCenter_;
+      PropDouble mass_;
+      PropExprPoint massCenter_;
+      PropMatrix inertia_;
+      PropDouble staticFrictionCoef_;
+      PropDouble slidingFrictionCoef_;
+
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.cpp b/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.cpp
new file mode 100644
index 0000000..e0dde84
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.cpp
@@ -0,0 +1,73 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <iostream>
+#include <QListWidgetItem>
+
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogCheckDeleteItem.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    DialogCheckDeleteItem* DialogCheckDeleteItem::me_ = 0;
+
+    DialogCheckDeleteItem& 
+    DialogCheckDeleteItem::Get()
+    {
+      if (me_ == 0)
+	{
+	  new DialogCheckDeleteItem();
+	}
+      return *me_;
+    }
+
+
+  
+    DialogCheckDeleteItem::DialogCheckDeleteItem()
+      :QDialog(&MainWindow::Get())
+    {
+      OMC_ASSERT_MSG(me_ == 0, "The singleton is null");
+      Ui::DialogCheckDeleteItem::setupUi(this);
+      setModal(true);
+      me_ = this;
+    }
+
+    
+    DialogCheckDeleteItem::~DialogCheckDeleteItem()
+    {
+      me_ = 0;
+    }
+
+
+    void 
+    DialogCheckDeleteItem::BuildListView(const Core::SetOfBase<Core::UserItem>& childs)
+    {
+      listWidget_->clear();
+      typename std::list<Core::UserItem *>::const_iterator it;
+      for ( it=childs.Begin(); it != childs.End(); it++ )
+	{
+	  new QListWidgetItem((*it)->GetIcon(), (*it)->GetName().c_str(), listWidget_);
+	}
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.hpp b/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.hpp
new file mode 100644
index 0000000..5a2be67
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.hpp
@@ -0,0 +1,61 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogCheckDeleteItem_hpp 
+#define OpenMeca_Gui_DialogCheckDeleteItem_hpp 
+
+#include <QDialog>
+
+#include "ui_DialogCheckDeleteItem.h"
+#include "OpenMeca/Core/SetOfBase.hpp"
+
+namespace OpenMeca
+{
+   namespace Core
+   {
+     class UserItem;
+   }
+
+  namespace Gui
+  {
+
+    class DialogCheckDeleteItem : public QDialog, private Ui::DialogCheckDeleteItem
+    {
+      Q_OBJECT
+      
+      public:
+      static DialogCheckDeleteItem& Get();
+      
+      virtual ~DialogCheckDeleteItem();
+
+      void BuildListView(const Core::SetOfBase<Core::UserItem>&);
+
+    private:
+      DialogCheckDeleteItem();
+
+    private:
+      static DialogCheckDeleteItem* me_;
+
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.ui b/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.ui
new file mode 100644
index 0000000..d10f258
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogCheckDeleteItem.ui
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>DialogCheckDeleteItem</class>
+ <widget class="QDialog" name="DialogCheckDeleteItem">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Are you sure ?</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="2" column="0">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::No|QDialogButtonBox::Yes</set>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Delete this item with all its child ?</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QListWidget" name="listWidget_"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>DialogCheckDeleteItem</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>DialogCheckDeleteItem</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogGravity.cpp b/SRC/OpenMeca/Gui/Dialog/DialogGravity.cpp
new file mode 100644
index 0000000..297c424
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogGravity.cpp
@@ -0,0 +1,56 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+
+
+#include "OpenMeca/Setting/Gravity.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogGravity.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    DialogGravity::DialogGravity()
+      :DialogUserItemT<Setting::Gravity>(),
+       g_(this)
+    {
+      g_.SetLabel(QObject::tr("Gravity"));
+      g_.SetDimension(Util::Dimension::Get("LinearAcceleration"));
+      GetPropTree().Add(g_);
+    }
+
+    DialogGravity::~DialogGravity()
+    {
+    }
+
+    void
+    DialogGravity::Init()
+    {
+      g_.SetValue(GetCurrentItem().GetValue());
+    }
+
+  
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogGravity.hpp b/SRC/OpenMeca/Gui/Dialog/DialogGravity.hpp
new file mode 100644
index 0000000..9d71079
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogGravity.hpp
@@ -0,0 +1,54 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogGravity_hpp 
+#define OpenMeca_Gui_DialogGravity_hpp 
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Gui/Prop/PropVector.hpp"
+#include "OpenMeca/Setting/Gravity.hpp"
+
+
+namespace OpenMeca
+{
+ 
+  namespace Gui
+  {
+    class DialogGravity :  public DialogUserItemT<Setting::Gravity>, 
+			   public Core::Singleton<DialogGravity>
+    {
+
+      Q_OBJECT
+    public:
+      DialogGravity();
+      virtual ~DialogGravity();
+		  
+    private:
+      void Init();
+      
+    private :
+      PropVector g_;
+    };
+  }
+}
+
+#endif
+    
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLink.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLink.cpp
new file mode 100644
index 0000000..f5e5c88
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLink.cpp
@@ -0,0 +1,113 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QSpacerItem>
+#include <QMessageBox>
+
+#include "OpenMeca/Gui/Dialog/DialogLink.hpp"
+#include "OpenMeca/Gui/Dialog/DialogUserItem.hpp"
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+    DialogLink::DialogLink(DialogUserItem* me)
+      :me_(*me),
+       id_(me),
+       body1_(me),
+       body2_(me),
+       point_(me),
+       quaternion_(me),
+       drawLocalFrame_(me)
+    { 
+      id_.SetLabel(DialogUserItem::tr("Name"));
+      body1_.Prop::SetLabel(DialogUserItem::tr("First body"));
+      body2_.Prop::SetLabel(DialogUserItem::tr("Second body"));
+
+      point_.Prop::SetLabel(DialogUserItem::tr("Center"));
+      point_.SetDimension(Util::Dimension::Get("Length"));
+      
+      quaternion_.SetLabel(DialogUserItem::tr("Rotation"));
+
+      drawLocalFrame_.Prop::SetLabel(DialogUserItem::tr("Draw local frame"));
+      
+      // Init table
+      me_.GetPropTree().Add(id_);
+      me_.GetPropTree().Add(body1_);
+      me_.GetPropTree().Add(body2_);
+      me_.GetPropTree().Add(point_);
+      me_.GetPropTree().Add(quaternion_);
+      me_.GetPropTree().Add(drawLocalFrame_);
+    }
+    
+    DialogLink::~DialogLink()
+    {
+    }
+
+    void 
+    DialogLink::Init()
+    {
+      id_.SetValue(GetCurrentLink().GetName());
+
+      body1_.SetList(Core::AutoRegister<Item::Body>::GetGlobalSet());
+      body2_.SetList(Core::AutoRegister<Item::Body>::GetGlobalSet());
+      body1_.SetValue(GetCurrentLink().GetBody1Ptr());
+      body2_.SetValue(GetCurrentLink().GetBody2Ptr());
+
+      point_.SetValue(GetCurrentLink().GetCenter());
+      
+      quaternion_.SetValue(GetCurrentLink().GetQuaternion());
+     
+      drawLocalFrame_.SetValue(GetCurrentLink().DrawLocalFrame());
+
+    }
+    
+
+    bool
+    DialogLink::Check()
+    {
+      if (&body1_.GetSelectedItem() == &body2_.GetSelectedItem())
+	{
+	  QMessageBox::warning(&me_, QObject::tr("Warning"), 
+			       QObject::tr("The bodys must be different"));
+	  return false;
+	}
+      return true;
+    }
+
+    PropSelectItemT<Core::AutoRegisteredPtr<Item::Body, Item::Link> >& 
+    DialogLink::GetPropSelectItemBody1()
+    {
+      return body1_;
+    }
+    
+    PropSelectItemT<Core::AutoRegisteredPtr<Item::Body, Item::Link> >&
+    DialogLink::GetPropSelectItemBody2()
+    {
+      return body2_;
+    }
+
+    
+  
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLink.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLink.hpp
new file mode 100644
index 0000000..40565ba
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLink.hpp
@@ -0,0 +1,71 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLink_hpp
+#define OpenMeca_Gui_DialogLink_hpp
+
+#include <QWidget>
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Gui/Prop/PropSelectItemT.hpp"
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropExprPoint.hpp"
+#include "OpenMeca/Gui/Prop/PropExprAttitude.hpp"
+#include "OpenMeca/Gui/Prop/PropMotionLaw.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    class DialogUserItem;
+    
+    class DialogLink
+    {
+      
+    public:
+      DialogLink(DialogUserItem* me);
+      virtual ~DialogLink();
+
+    protected:
+      bool Check();
+      PropSelectItemT<Core::AutoRegisteredPtr<Item::Body, Item::Link> >& GetPropSelectItemBody1();
+      PropSelectItemT<Core::AutoRegisteredPtr<Item::Body, Item::Link> >& GetPropSelectItemBody2();
+      virtual Item::Link& GetCurrentLink() = 0;
+      void Init();
+
+    private:
+      DialogUserItem& me_;
+      PropString id_; 
+      PropSelectItemT<Core::AutoRegisteredPtr<Item::Body, Item::Link> > body1_;
+      PropSelectItemT<Core::AutoRegisteredPtr<Item::Body, Item::Link> > body2_;
+      PropExprPoint point_;
+      PropExprAttitude quaternion_;
+      PropBool drawLocalFrame_;
+
+      
+    };
+
+
+   
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkGear.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkGear.cpp
new file mode 100644
index 0000000..a29cc77
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkGear.cpp
@@ -0,0 +1,94 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogLinkGear.hpp"
+#include "OpenMeca/Item/Link/Gear.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    DialogLinkGear::DialogLinkGear()
+      :DialogLinkT<Item::LinkT<Item::Gear> >(),
+       ratio_(this),
+       interAxisLength_(this),
+       modulus_(this),
+       angleOfAction_(this),
+       internalTeeth_(this)
+    {
+      ratio_.SetLabel(QObject::tr("Ratio"));
+      ratio_.SetDimension(Util::Dimension::Get("Null"));
+
+      interAxisLength_.SetLabel(QObject::tr("Length between axes"));
+      interAxisLength_.SetDimension(Util::Dimension::Get("Length"));
+
+      modulus_.SetLabel(QObject::tr("Modulus"));
+      modulus_.SetDimension(Util::Dimension::Get("Length"));
+      
+      angleOfAction_.SetLabel(QObject::tr("Angle of action"));
+      angleOfAction_.SetDimension(Util::Dimension::Get("Angle"));
+
+      internalTeeth_.SetLabel(QObject::tr("Internal teeth"));
+
+      GetPropTree().Add(ratio_);
+      GetPropTree().Add(interAxisLength_);
+      GetPropTree().Add(modulus_);
+      GetPropTree().Add(angleOfAction_);
+      GetPropTree().Add(internalTeeth_);
+    }
+
+    
+    DialogLinkGear::~DialogLinkGear()
+    {
+    }
+
+    void
+    DialogLinkGear::Init()
+    {
+      DialogLinkT<Item::LinkT<Item::Gear> >::Init();
+      ratio_.SetValue(GetCurrentItem().GetLinkType().GetRatio());
+      interAxisLength_.SetValue(GetCurrentItem().GetLinkType().GetInterAxisLength());
+      modulus_.SetValue(GetCurrentItem().GetLinkType().GetModulus());
+      angleOfAction_.SetValue(GetCurrentItem().GetLinkType().GetAngleOfAction());
+      internalTeeth_.SetValue(GetCurrentItem().GetLinkType().GetInternalTeeth());
+    }
+
+
+    bool
+    DialogLinkGear::Check()
+    {   
+      bool check = DialogLinkT<Item::LinkT<Item::Gear> >::Check();
+      if (internalTeeth_.GetCopy() == true && ratio_.GetCopy() == 1.)
+	{
+	  const QString help = QObject::tr("You can't set a ratio of 100% with internal teeth gear");
+	  ratio_.DisplayHelp(help);
+	  check = false;
+	}
+
+      return check;
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkGear.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkGear.hpp
new file mode 100644
index 0000000..e814cc7
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkGear.hpp
@@ -0,0 +1,65 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkGear_hpp
+#define OpenMeca_Gui_DialogLinkGear_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    template <class T> class LinkT;
+    struct Gear;
+  }
+  
+  
+  namespace Gui
+  {
+    class DialogLinkGear :  public DialogLinkT<Item::LinkT<Item::Gear> >, 
+			     public Core::Singleton<DialogLinkGear>
+    {
+      
+    public:
+      DialogLinkGear();
+      ~DialogLinkGear();
+      virtual bool Check();
+
+    protected:
+      virtual void Init();
+
+    private:
+      PropDouble ratio_;
+      PropDouble interAxisLength_;
+      PropDouble modulus_;
+      PropDouble angleOfAction_;
+      PropBool   internalTeeth_;
+      
+    };
+
+
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.cpp
new file mode 100644
index 0000000..f2166e4
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.cpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogLinkLinearMotor.hpp"
+#include "OpenMeca/Item/Link/LinearMotor.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    DialogLinkLinearMotor::DialogLinkLinearMotor()
+      :DialogLinkT<Item::LinkT<Item::LinearMotor> >(),
+       displacement_(this)
+    {
+      displacement_.SetLabel(QObject::tr("Displacement"));
+      displacement_.SetDimension(Util::Dimension::Get("Length"));
+      GetPropTree().Add(displacement_);
+    }
+
+    
+    DialogLinkLinearMotor::~DialogLinkLinearMotor()
+    {
+    }
+
+    void
+    DialogLinkLinearMotor::Init()
+    {
+      DialogLinkT<Item::LinkT<Item::LinearMotor> >::Init();
+      displacement_.SetValue(GetCurrentItem().GetLinkType().GetDisplacement());
+    }
+
+
+    bool
+    DialogLinkLinearMotor::Check()
+    {      
+      return DialogLinkT<Item::LinkT<Item::LinearMotor> >::Check();
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.hpp
new file mode 100644
index 0000000..5b635c3
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkLinearMotor.hpp
@@ -0,0 +1,60 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkLinearMotor_hpp
+#define OpenMeca_Gui_DialogLinkLinearMotor_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+#include "OpenMeca/Gui/Prop/PropExpr.hpp"
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    template <class T> class LinkT;
+    struct LinearMotor;
+  }
+  
+  
+  namespace Gui
+  {
+    class DialogLinkLinearMotor :  public DialogLinkT<Item::LinkT<Item::LinearMotor> >, 
+			     public Core::Singleton<DialogLinkLinearMotor>
+    {
+      
+    public:
+      DialogLinkLinearMotor();
+      ~DialogLinkLinearMotor();
+      virtual bool Check();
+
+    protected:
+      virtual void Init();
+
+    private:
+      PropExpr displacement_;
+    };
+
+
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.cpp
new file mode 100644
index 0000000..e218775
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.cpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogLinkMotor.hpp"
+#include "OpenMeca/Item/Link/Motor.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    DialogLinkMotor::DialogLinkMotor()
+      :DialogLinkT<Item::LinkT<Item::Motor> >(),
+       velocity_(this)
+    {
+      velocity_.SetLabel(QObject::tr("Angular velocity"));
+      velocity_.SetDimension(Util::Dimension::Get("AngularVelocity"));
+      GetPropTree().Add(velocity_);
+    }
+
+    
+    DialogLinkMotor::~DialogLinkMotor()
+    {
+    }
+
+    void
+    DialogLinkMotor::Init()
+    {
+      DialogLinkT<Item::LinkT<Item::Motor> >::Init();
+      velocity_.SetValue(GetCurrentItem().GetLinkType().GetVelocity());
+    }
+
+
+    bool
+    DialogLinkMotor::Check()
+    {      
+      return DialogLinkT<Item::LinkT<Item::Motor> >::Check();
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.hpp
new file mode 100644
index 0000000..26f0233
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkMotor.hpp
@@ -0,0 +1,60 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkMotor_hpp
+#define OpenMeca_Gui_DialogLinkMotor_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+#include "OpenMeca/Gui/Prop/PropExpr.hpp"
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    template <class T> class LinkT;
+    struct Motor;
+  }
+  
+  
+  namespace Gui
+  {
+    class DialogLinkMotor :  public DialogLinkT<Item::LinkT<Item::Motor> >, 
+			     public Core::Singleton<DialogLinkMotor>
+    {
+      
+    public:
+      DialogLinkMotor();
+      ~DialogLinkMotor();
+      virtual bool Check();
+
+    protected:
+      virtual void Init();
+
+    private:
+      PropExpr velocity_;
+    };
+
+
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.cpp
new file mode 100644
index 0000000..e6391b2
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.cpp
@@ -0,0 +1,75 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogLinkPulley.hpp"
+#include "OpenMeca/Item/Link/Pulley.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    DialogLinkPulley::DialogLinkPulley()
+      :DialogLinkT<Item::LinkT<Item::Pulley> >(),
+       radius1_(this),
+       radius2_(this),
+       interAxisLength_(this)
+    {
+      radius1_.SetLabel(QObject::tr("Pinion 1 radius"));
+      radius1_.SetDimension(Util::Dimension::Get("Length"));
+
+      radius2_.SetLabel(QObject::tr("Pinion 2 radius"));
+      radius2_.SetDimension(Util::Dimension::Get("Length"));
+
+      interAxisLength_.SetLabel(QObject::tr("Length between axes"));
+      interAxisLength_.SetDimension(Util::Dimension::Get("Length"));
+
+      GetPropTree().Add(radius1_);
+      GetPropTree().Add(radius2_);
+      GetPropTree().Add(interAxisLength_);
+    }
+
+    
+    DialogLinkPulley::~DialogLinkPulley()
+    {
+    }
+
+    void
+    DialogLinkPulley::Init()
+    {
+      DialogLinkT<Item::LinkT<Item::Pulley> >::Init();
+      radius1_.SetValue(GetCurrentItem().GetLinkType().GetRadius1());
+      radius2_.SetValue(GetCurrentItem().GetLinkType().GetRadius2());
+      interAxisLength_.SetValue(GetCurrentItem().GetLinkType().GetInterAxisLength());
+    }
+
+
+    bool
+    DialogLinkPulley::Check()
+    {      
+      return DialogLinkT<Item::LinkT<Item::Pulley> >::Check();
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.hpp
new file mode 100644
index 0000000..3a1a636
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkPulley.hpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkPulley_hpp
+#define OpenMeca_Gui_DialogLinkPulley_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    template <class T> class LinkT;
+    struct Pulley;
+  }
+  
+  
+  namespace Gui
+  {
+    class DialogLinkPulley :  public DialogLinkT<Item::LinkT<Item::Pulley> >, 
+			     public Core::Singleton<DialogLinkPulley>
+    {
+      
+    public:
+      DialogLinkPulley();
+      ~DialogLinkPulley();
+      virtual bool Check();
+
+    protected:
+      virtual void Init();
+
+    private:
+      PropDouble radius1_;
+      PropDouble radius2_;
+      PropDouble interAxisLength_;
+    };
+
+
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.cpp
new file mode 100644
index 0000000..7188806
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.cpp
@@ -0,0 +1,81 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogLinkRackPinion.hpp"
+#include "OpenMeca/Item/Link/RackPinion.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    DialogLinkRackPinion::DialogLinkRackPinion()
+      :DialogLinkT<Item::LinkT<Item::RackPinion> >(),
+       ratio_(this),
+       pinionRadius_(this),
+       modulus_(this),
+       angleOfAction_(this)
+    {
+      ratio_.SetLabel(QObject::tr("Ratio"));
+      ratio_.SetDimension(Util::Dimension::Get("Null"));
+
+      pinionRadius_.SetLabel(QObject::tr("Pinion radius"));
+      pinionRadius_.SetDimension(Util::Dimension::Get("Length"));
+
+      modulus_.SetLabel(QObject::tr("Modulus"));
+      modulus_.SetDimension(Util::Dimension::Get("Length"));
+      
+      angleOfAction_.SetLabel(QObject::tr("Angle of action"));
+      angleOfAction_.SetDimension(Util::Dimension::Get("Angle"));
+
+      GetPropTree().Add(ratio_);
+      GetPropTree().Add(pinionRadius_);
+      GetPropTree().Add(modulus_);
+      GetPropTree().Add(angleOfAction_);
+    }
+
+    
+    DialogLinkRackPinion::~DialogLinkRackPinion()
+    {
+    }
+
+    void
+    DialogLinkRackPinion::Init()
+    {
+      DialogLinkT<Item::LinkT<Item::RackPinion> >::Init();
+      ratio_.SetValue(GetCurrentItem().GetLinkType().GetRatio());
+      pinionRadius_.SetValue(GetCurrentItem().GetLinkType().GetPinionRadius());
+      modulus_.SetValue(GetCurrentItem().GetLinkType().GetModulus());
+      angleOfAction_.SetValue(GetCurrentItem().GetLinkType().GetAngleOfAction());
+    }
+
+
+    bool
+    DialogLinkRackPinion::Check()
+    {      
+      return DialogLinkT<Item::LinkT<Item::RackPinion> >::Check();
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.hpp
new file mode 100644
index 0000000..0378403
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkRackPinion.hpp
@@ -0,0 +1,63 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkRackPinion_hpp
+#define OpenMeca_Gui_DialogLinkRackPinion_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    template <class T> class LinkT;
+    struct RackPinion;
+  }
+  
+  
+  namespace Gui
+  {
+    class DialogLinkRackPinion :  public DialogLinkT<Item::LinkT<Item::RackPinion> >, 
+			     public Core::Singleton<DialogLinkRackPinion>
+    {
+      
+    public:
+      DialogLinkRackPinion();
+      ~DialogLinkRackPinion();
+      virtual bool Check();
+
+    protected:
+      virtual void Init();
+
+    private:
+      PropDouble ratio_;
+      PropDouble pinionRadius_;
+      PropDouble modulus_;
+      PropDouble angleOfAction_;
+    };
+
+
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.cpp
new file mode 100644
index 0000000..ba70f0a
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.cpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogLinkScrew.hpp"
+#include "OpenMeca/Item/Link/Screw.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    DialogLinkScrew::DialogLinkScrew()
+      :DialogLinkT<Item::LinkT<Item::Screw> >(),
+       tau_(this)
+    {
+      tau_.SetLabel(QObject::tr("Step"));
+      tau_.SetDimension(Util::Dimension::Get("Step"));
+      GetPropTree().Add(tau_);
+    }
+
+    
+    DialogLinkScrew::~DialogLinkScrew()
+    {
+    }
+
+    void
+    DialogLinkScrew::Init()
+    {
+      DialogLinkT<Item::LinkT<Item::Screw> >::Init();
+      tau_.SetValue(GetCurrentItem().GetLinkType().GetTau());
+    }
+
+
+    bool
+    DialogLinkScrew::Check()
+    {      
+      return DialogLinkT<Item::LinkT<Item::Screw> >::Check();
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.hpp
new file mode 100644
index 0000000..a43d92d
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkScrew.hpp
@@ -0,0 +1,60 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkScrew_hpp
+#define OpenMeca_Gui_DialogLinkScrew_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    template <class T> class LinkT;
+    struct Screw;
+  }
+  
+  
+  namespace Gui
+  {
+    class DialogLinkScrew :  public DialogLinkT<Item::LinkT<Item::Screw> >, 
+			     public Core::Singleton<DialogLinkScrew>
+    {
+      
+    public:
+      DialogLinkScrew();
+      ~DialogLinkScrew();
+      virtual bool Check();
+
+    protected:
+      virtual void Init();
+
+    private:
+      PropDouble tau_;
+    };
+
+
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.cpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.cpp
new file mode 100644
index 0000000..673226a
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.cpp
@@ -0,0 +1,85 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogLinkSpring.hpp"
+#include "OpenMeca/Item/Link/Spring.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+
+
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    DialogLinkSpring::DialogLinkSpring()
+      :DialogLinkT<Item::LinkT<Item::Spring> >(),
+       stiffness_(this),
+       dampingFactor_(this),
+       freeLength_(this),
+       initialLength_(this)
+    {
+      stiffness_.SetLabel(QObject::tr("Stiffness"));
+      stiffness_.SetDimension(Util::Dimension::Get("Stiffness"));
+
+      dampingFactor_.SetLabel(QObject::tr("Damping factor"));
+      dampingFactor_.SetDimension(Util::Dimension::Get("DampingFactor"));
+
+      dampingFactor_.SetLabel(QObject::tr("Damping factor"));
+      dampingFactor_.SetDimension(Util::Dimension::Get("DampingFactor"));
+
+      freeLength_.Prop::SetLabel(QObject::tr("Free length"));
+      freeLength_.SetDimension(Util::Dimension::Get("Length"));
+
+      initialLength_.Prop::SetLabel(QObject::tr("Initial length"));
+      initialLength_.SetDimension(Util::Dimension::Get("Length"));
+
+      GetPropTree().Add(stiffness_);
+      GetPropTree().Add(dampingFactor_);
+      GetPropTree().Add(freeLength_);
+      GetPropTree().Add(initialLength_);
+    }
+
+    
+    DialogLinkSpring::~DialogLinkSpring()
+    {
+    }
+
+    void
+    DialogLinkSpring::Init()
+    {
+      DialogLinkT<Item::LinkT<Item::Spring> >::Init();
+      stiffness_.SetValue(GetCurrentItem().GetLinkType().GetStiffness());
+      dampingFactor_.SetValue(GetCurrentItem().GetLinkType().GetDampingFactor());
+      freeLength_.SetValue(GetCurrentItem().GetLinkType().GetFreeLength());
+      initialLength_.SetValue(GetCurrentItem().GetLinkType().GetInitialLength());
+    }
+
+    bool
+    DialogLinkSpring::Check()
+    {      
+      return DialogLinkT<Item::LinkT<Item::Spring> >::Check();
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.hpp
new file mode 100644
index 0000000..ac6c741
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkSpring.hpp
@@ -0,0 +1,63 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkSpring_hpp
+#define OpenMeca_Gui_DialogLinkSpring_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    template <class T> class LinkT;
+    struct Spring;
+  }
+  
+  
+  namespace Gui
+  {
+    class DialogLinkSpring :  public DialogLinkT<Item::LinkT<Item::Spring> >, 
+			     public Core::Singleton<DialogLinkSpring>
+    {
+      
+    public:
+      DialogLinkSpring();
+      ~DialogLinkSpring();
+      virtual bool Check();
+
+    protected:
+      virtual void Init();
+
+    private:
+      PropDouble stiffness_;
+      PropDouble dampingFactor_;
+      PropDouble freeLength_;
+      PropDouble initialLength_;
+    };
+
+
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLinkT.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLinkT.hpp
new file mode 100644
index 0000000..93ac5fc
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLinkT.hpp
@@ -0,0 +1,139 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLinkT_hpp
+#define OpenMeca_Gui_DialogLinkT_hpp
+
+#include <QMessageBox>
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLink.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    template <class Link>
+    class DialogLinkT :  public DialogUserItemT<Link>, 
+			 public Core::Singleton<DialogLinkT <Link> >,
+			 public DialogLink
+    {
+      
+    public:
+      DialogLinkT();
+      virtual ~DialogLinkT();
+      virtual bool Check();
+      virtual bool IsNewItemAllowed() const;
+
+    protected:
+      virtual void Init();
+      virtual void ApplyChangement();
+      Item::Link& GetCurrentLink();
+
+    private:
+      
+
+    };
+
+
+    template <class Link>
+    inline 
+    DialogLinkT <Link>::DialogLinkT()
+      : DialogUserItemT<Link>(),
+	DialogLink(this)
+    {
+    }
+    
+    template <class Link>
+    inline
+    DialogLinkT <Link>::~DialogLinkT()
+    {
+    }
+    
+    template <class Link>
+    inline void
+    DialogLinkT <Link>::Init()
+    {
+      DialogLink::Init();
+    }
+
+    template <class Link>
+    inline Item::Link&
+    DialogLinkT <Link>::GetCurrentLink()
+    {
+      return DialogUserItemT<Link>::GetCurrentItem(); 
+    }
+
+
+
+    template <class Link>
+    inline bool
+    DialogLinkT<Link>::Check()
+    {
+      if (!DialogLink::Check())
+	return false;
+
+      DialogUserItemT<Link>::GetCurrentItem().GetBody1().GetDependentItems().UnCheckForDoublet();
+      DialogUserItemT<Link>::GetCurrentItem().GetBody2().GetDependentItems().UnCheckForDoublet();      
+      bool ok = DialogUserItem::Check(); 
+
+      DialogUserItemT<Link>::GetCurrentItem().GetBody1().GetDependentItems().CheckForDoublet();
+      DialogUserItemT<Link>::GetCurrentItem().GetBody2().GetDependentItems().CheckForDoublet();   
+
+      return ok;
+    }
+
+    template <class Link>
+    inline void
+    DialogLinkT<Link>::ApplyChangement()
+    {
+      DialogUserItemT<Link>::GetCurrentItem().GetBody1().GetDependentItems().UnCheckForDoublet();
+      DialogUserItemT<Link>::GetCurrentItem().GetBody2().GetDependentItems().UnCheckForDoublet(); 
+      DialogUserItem::ApplyChangement();
+      DialogUserItemT<Link>::GetCurrentItem().GetBody1().GetDependentItems().CheckForDoublet();
+      DialogUserItemT<Link>::GetCurrentItem().GetBody2().GetDependentItems().CheckForDoublet();  
+    }
+
+
+    template <class Link>
+    inline bool
+    DialogLinkT<Link>::IsNewItemAllowed() const
+    {
+      if (Core::System::Get().GetSetOf<Item::Body>().GetTotItemNumber() < 2)
+	{
+	  const QString msg = QObject::tr("You must build 2 bodys before adding a new link");
+	  const QWidget* me_const = this;
+	  QWidget* me = const_cast<QWidget*>(me_const);
+	  QMessageBox::warning(me, QObject::tr("Warning"), msg);
+	  return false;
+	}
+      return true;
+    }
+   
+   
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogLoadT.hpp b/SRC/OpenMeca/Gui/Dialog/DialogLoadT.hpp
new file mode 100644
index 0000000..32b6354
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogLoadT.hpp
@@ -0,0 +1,110 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogLoadT_hpp
+#define OpenMeca_Gui_DialogLoadT_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+#include "OpenMeca/Gui/Prop/PropSelectItemT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    template<class Parent, class Quantity, class How>
+    class LoadT;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    template<class Parent, class Quantity, class How>
+    class DialogLoadT : public DialogUserItemT<Item::LoadT<Parent, Quantity, How> >, 
+			public Core::Singleton<DialogLoadT<Parent, Quantity, How> >
+    {
+      
+    public:
+      DialogLoadT();
+      ~DialogLoadT();
+
+    private:
+      void Init();
+
+    private:
+      PropString id_;
+      PropSelectItemT< Core::AutoRegisteredPtr<Parent, Item::LoadT<Parent, Quantity, How> > > parent_;
+      typename Quantity::GuiManager phys_;
+
+    };
+
+    template<class Parent, class Quantity, class How>
+    inline
+    DialogLoadT<Parent, Quantity, How>::DialogLoadT()
+      :DialogUserItemT<Item::LoadT<Parent, Quantity, How> >(),
+       id_(this),
+       parent_(this),
+       phys_(this)
+    {
+      id_.SetLabel(QObject::tr("Name"));
+      parent_.Prop::SetLabel(QObject::tr("Parent"));
+      
+      // Init table
+      DialogUserItem::GetPropTree().Add(id_);
+      DialogUserItem::GetPropTree().Add(parent_);
+      phys_.Add(DialogUserItem::GetPropTree());
+    }
+  
+    template<class Parent, class Quantity, class How>
+    inline
+    DialogLoadT<Parent, Quantity, How>::~DialogLoadT()
+    {
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void
+    DialogLoadT<Parent, Quantity, How>::Init()
+    {
+      Item::LoadT<Parent, Quantity, How>& currentItem = 
+	DialogUserItemT<Item::LoadT<Parent, Quantity, How> >::GetCurrentItem();
+
+      id_.SetValue(currentItem.GetName());
+
+      // populate parent list
+      Core::SetOfBase<Parent>& parent = 
+	Core::System::Get().GetSetOf<Parent>();
+      OMC_ASSERT_MSG(parent.GetTotItemNumber() > 0, "There is not any item in the parent set");
+      parent_.SetList(parent);
+      parent_.SetValue(currentItem.GetParentItemPtr());
+
+      phys_.Init(currentItem.GetQuantity());
+
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogNone.hpp b/SRC/OpenMeca/Gui/Dialog/DialogNone.hpp
new file mode 100644
index 0000000..7ad670d
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogNone.hpp
@@ -0,0 +1,46 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogNone_hpp
+#define OpenMeca_Gui_DialogNone_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    template <class T>
+    class DialogNone : public DialogUserItemT<T>,  public Core::Singleton<DialogNone <T> >
+    {
+      
+    public:
+      DialogNone() {OMC_ASSERT_MSG(0, "Invoking this method is not allowed");}
+      ~DialogNone(){OMC_ASSERT_MSG(0, "Invoking this method is not allowed");}
+
+    private:
+      void Init(){OMC_ASSERT_MSG(0, "Invoking this method is not allowed");}
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.cpp b/SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.cpp
new file mode 100644
index 0000000..6e2279d
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.cpp
@@ -0,0 +1,86 @@
+ // This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+ // Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QVBoxLayout>
+
+#include "OpenMeca/Gui/Dialog/DialogPartUserJunction.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Item/PartUserJunction.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+    DialogPartUserJunction::DialogPartUserJunction()
+      :DialogUserItemT<Item::PartUserJunction>(),
+       id_(this),
+       endPoint_(this)
+    {
+      id_.SetLabel(QObject::tr("Name"));
+      endPoint_.Prop::SetLabel(QObject::tr("End Point"));
+
+            // Init table
+      GetPropTree().Add(id_);
+      GetPropTree().Add(endPoint_);
+    }
+    
+    DialogPartUserJunction::~DialogPartUserJunction()
+    {
+    }
+    
+    void
+    DialogPartUserJunction::Init()
+    {
+      Core::SetOfBase<Item::PartPoint> set = GetCurrentItem().GetBody().GetChildSet<Item::PartPoint>();
+      // Check that the number of available point
+      if (set.GetTotItemNumber() < 2)
+	{
+	  QMessageBox::warning(this, QObject::tr("Warning"), 
+			       QObject::tr("Need two points to build a junction"));
+	  hide();
+	  return;
+	}
+
+      endPoint_.SetList(set);
+
+      id_.SetValue(GetCurrentItem().GetName());
+      endPoint_.SetValue(GetCurrentItem().GetEndPointPtr());
+      
+    }
+    
+    
+    bool
+    DialogPartUserJunction::Check()
+    {
+      if (&endPoint_.GetSelectedItem() == &GetCurrentItem().GetStartPoint())
+	{
+	  QMessageBox::warning(this, QObject::tr("Warning"), 
+			       QObject::tr("The end point is the same as the start point"));
+	  return false;
+	}
+      return true;
+    }
+
+    
+    
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.hpp b/SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.hpp
new file mode 100644
index 0000000..63cddf9
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogPartUserJunction.hpp
@@ -0,0 +1,65 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogPartUserJunction_hpp
+#define OpenMeca_Gui_DialogPartUserJunction_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+#include "OpenMeca/Gui/Prop/PropSelectItemT.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    class PartUserJunction;
+    class PartPoint;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogPartUserJunction : public DialogUserItemT<Item::PartUserJunction>, 
+				   public Core::Singleton<DialogPartUserJunction>
+    {
+      
+    public:
+      DialogPartUserJunction();
+      ~DialogPartUserJunction();
+      bool Check();
+
+    private:
+      void Init();
+
+    private:
+      PropString id_; 
+      PropSelectItemT< Core::AutoRegisteredPtr<Item::PartPoint, Item::PartUserJunction > > endPoint_;
+      
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.cpp b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.cpp
new file mode 100644
index 0000000..4d23eab
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.cpp
@@ -0,0 +1,84 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QVBoxLayout>
+
+#include "OpenMeca/Gui/Dialog/DialogPartUserPipe.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Item/PartUserPipe.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+    DialogPartUserPipe::DialogPartUserPipe()
+      :DialogUserItemT<Item::PartUserPipe>(),
+       id_(this),
+       parent_(this),
+       axis_(this),
+       length_(this)
+    {
+      id_.SetLabel(QObject::tr("Name"));
+      parent_.Prop::SetLabel(QObject::tr("Attached to point"));
+      axis_.SetLabel(QObject::tr("Axis"));
+      axis_.SetDimension(Util::Dimension::Get("Length"));
+
+      length_.SetLabel(QObject::tr("Length"));      
+      length_.SetDimension(Util::Dimension::Get("Length"));
+
+      // Init table
+      GetPropTree().Add(id_);
+      GetPropTree().Add(parent_);
+      GetPropTree().Add(axis_);
+      GetPropTree().Add(length_);
+
+    }
+    
+    DialogPartUserPipe::~DialogPartUserPipe()
+    {
+    }
+    
+    void
+    DialogPartUserPipe::Init()
+    {
+      id_.SetValue(GetCurrentItem().GetName());
+      axis_.SetValue(GetCurrentItem().GetAxis());
+      length_.SetValue(GetCurrentItem().GetLength());
+
+      // populate parent list
+      Core::SetOfBase<OpenMeca::Item::PartPoint>& points = 
+	Core::System::Get().GetSetOf<OpenMeca::Item::PartPoint>();
+      
+      Core::SetOfBase<Core::UserItem> set;
+      for (unsigned int i = 0; i < points.GetTotItemNumber(); ++i)
+	{
+	  Core::UserItem& item = points(i);
+	  if (!GetCurrentItem().HasChild(item))
+	    set.AddItem(item);
+	}
+      OMC_ASSERT_MSG(set.GetTotItemNumber() > 0, "The set number is null");
+      parent_.SetList(set);
+      parent_.SetValue(GetCurrentItem().GetParentItemPtr());
+      
+    }
+    
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.hpp b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.hpp
new file mode 100644
index 0000000..4c8b843
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPipe.hpp
@@ -0,0 +1,70 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogPartUserPipe_hpp
+#define OpenMeca_Gui_DialogPartUserPipe_hpp
+
+
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Gui/Prop/PropAttitude.hpp"
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropVector.hpp"
+#include "OpenMeca/Gui/Prop/PropSelectItemT.hpp"
+
+#include "OpenMeca/Item/PartUser.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    class PartUserPipe;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogPartUserPipe : public DialogUserItemT<Item::PartUserPipe>, 
+			       public Core::Singleton<DialogPartUserPipe>
+    {
+      
+    public:
+      DialogPartUserPipe();
+      ~DialogPartUserPipe();
+
+    private:
+      void Init();
+
+    private:
+      PropString id_; 
+      PropSelectItemT< Core::AutoRegisteredPtr<Core::UserItem, Item::PartUser > > parent_;
+      PropVector axis_;
+      PropDouble length_;
+      
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.cpp b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.cpp
new file mode 100644
index 0000000..9faf1c5
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.cpp
@@ -0,0 +1,76 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogPartUserPoint.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Item/PartUserPoint.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+    DialogPartUserPoint::DialogPartUserPoint()
+      :DialogUserItemT<Item::PartUserPoint>(),
+       id_(this),
+       parent_(this),
+       point_(this)
+    {
+      id_.SetLabel(QObject::tr("Name"));
+      parent_.Prop::SetLabel(QObject::tr("Parent Item"));
+      point_.SetLabel(QObject::tr("Center"));
+      point_.SetDimension(Util::Dimension::Get("Length"));
+
+      // Init table
+      GetPropTree().Add(id_);
+      GetPropTree().Add(parent_);
+      GetPropTree().Add(point_);
+    }
+  
+    DialogPartUserPoint::~DialogPartUserPoint()
+    {
+    }
+
+    void
+    DialogPartUserPoint::Init()
+    {
+      point_.SetValue(GetCurrentItem().GetCenterExpr());
+      id_.SetValue(GetCurrentItem().GetName());
+
+      // populate parent list
+      Core::SetOfBase<OpenMeca::Item::Body>& body = 
+	Core::System::Get().GetSetOf<OpenMeca::Item::Body>();
+      
+      Core::SetOfBase<Core::UserItem> set;
+      for (unsigned int i = 0; i < body.GetTotItemNumber(); ++i)
+	{
+	  Core::UserItem& item = body(i);
+	  set.AddItem(item);
+	}
+      
+      
+      OMC_ASSERT_MSG(set.GetTotItemNumber() > 0, "The number of item is null");
+      parent_.SetList(set);
+      parent_.SetValue(GetCurrentItem().GetParentItemPtr());
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.hpp b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.hpp
new file mode 100644
index 0000000..501fb31
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogPartUserPoint.hpp
@@ -0,0 +1,66 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogPartUserPoint_hpp
+#define OpenMeca_Gui_DialogPartUserPoint_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+#include "OpenMeca/Gui/Prop/PropExprPoint.hpp"
+#include "OpenMeca/Gui/Prop/PropSelectItemT.hpp"
+
+#include "OpenMeca/Item/PartUser.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    class PartUserPoint;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogPartUserPoint : public DialogUserItemT<OpenMeca::Item::PartUserPoint>, 
+				public Core::Singleton<DialogPartUserPoint>
+    {
+      
+    public:
+      DialogPartUserPoint();
+      ~DialogPartUserPoint();
+
+    private:
+      void Init();
+
+    private:
+      PropString id_;
+      PropSelectItemT< Core::AutoRegisteredPtr<Core::UserItem, Item::PartUser > > parent_;
+      PropExprPoint point_;
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogPartUserShapeT.hpp b/SRC/OpenMeca/Gui/Dialog/DialogPartUserShapeT.hpp
new file mode 100644
index 0000000..d76e674
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogPartUserShapeT.hpp
@@ -0,0 +1,133 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogPartUserShapeT_hpp
+#define OpenMeca_Gui_DialogPartUserShapeT_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+#include "OpenMeca/Gui/Prop/PropPoint.hpp"
+#include "OpenMeca/Gui/Prop/PropBool.hpp"
+#include "OpenMeca/Gui/Prop/PropSelectItemT.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    template <class T> class PartUserShapeT;
+    class PartUserPoint;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    template <class T>
+    class DialogPartUserShapeT : public DialogUserItemT<Item::PartUserShapeT<T> >, 
+				 public Core::Singleton<DialogPartUserShapeT<T> >
+    {
+      
+    public:
+      DialogPartUserShapeT();
+      ~DialogPartUserShapeT();
+
+
+    private:
+      void Init();
+
+    private:
+      PropString id_;
+      PropSelectItemT< Core::AutoRegisteredPtr<Core::UserItem, Item::PartUser > > parent_;
+      PropBool collision_;
+      typename T::GuiManager dim_;
+    };
+
+    template <class T>
+    inline
+    DialogPartUserShapeT<T>::DialogPartUserShapeT()
+      :DialogUserItemT<Item::PartUserShapeT<T> >(),
+       id_(this),
+       parent_(this),
+       collision_(this),
+       dim_(this)
+    {
+      id_.SetLabel(QObject::tr("Name"));
+      parent_.Prop::SetLabel(QObject::tr("Point"));
+      collision_.SetLabel(QObject::tr("Enable collision detection"));
+
+
+      // Init table
+      DialogUserItem::GetPropTree().Add(id_);
+      DialogUserItem::GetPropTree().Add(parent_);
+      if (T::CollisionDetectionAllowed)
+	DialogUserItem::GetPropTree().Add(collision_);
+
+      dim_.Add(DialogUserItem::GetPropTree());
+    }
+  
+    template <class T>
+    inline
+    DialogPartUserShapeT<T>::~DialogPartUserShapeT()
+    {
+    }
+
+    template <class T>
+    inline void
+    DialogPartUserShapeT<T>::Init()
+    {
+      Item::PartUserShapeT<T>& currentItem = 
+	DialogUserItemT<Item::PartUserShapeT<T> >::GetCurrentItem();
+
+      id_.SetValue(currentItem.GetName());
+      collision_.SetValue(currentItem.GetCollisionState());
+
+      // populate parent list
+      Core::SetOfBase<OpenMeca::Item::PartPoint>& points = 
+	Core::System::Get().GetSetOf<OpenMeca::Item::PartPoint>();
+      
+      Core::SetOfBase<Core::UserItem> set;
+      for (unsigned int i = 0; i < points.GetTotItemNumber(); ++i)
+	{
+    OpenMeca::Core::UserItem &item = (OpenMeca::Core::UserItem &)points(i);
+	  if (!currentItem.HasChild(item))
+	    set.AddItem(const_cast<Core::UserItem&>(item));
+	}
+      OMC_ASSERT_MSG(set.GetTotItemNumber() > 0, "The number of user item is null");
+      parent_.SetList(set);
+      
+      
+      OMC_ASSERT_MSG(set.GetTotItemNumber() > 0, "The number of user item is null");
+      parent_.SetList(set);
+      parent_.SetValue(currentItem.GetParentItemPtr());
+
+      dim_.Init(currentItem.GetShape());
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogScales.cpp b/SRC/OpenMeca/Gui/Dialog/DialogScales.cpp
new file mode 100644
index 0000000..99fee95
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogScales.cpp
@@ -0,0 +1,80 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+
+
+#include "OpenMeca/Setting/Scales.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogScales.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    DialogScales::DialogScales()
+      :DialogUserItemT<Setting::Scales>(),
+       propScales_()
+    {
+      Setting::Scales& scales =  Core::SystemSettingT<Setting::Scales>::Get();
+      std::vector<std::string> keys =  scales.GetKeys();
+
+      for (unsigned int i = 0; i < keys.size(); ++i)
+	{
+	  
+	  const std::string scaleKey = keys[i];
+	  PropDouble* prop = new PropDouble(this);
+	  prop->SetLabel(QObject::tr(keys[i].c_str()));
+	  prop->AddCondition(new Core::Superior<double>(0.));
+	  prop->SetDimension(Util::Dimension::Get("Percent"));
+	  GetPropTree().Add(*prop);
+
+	  OMC_ASSERT_MSG(propScales_.count(scaleKey) == 0, "Can't find this scale key");
+	  propScales_[scaleKey] = prop;
+	}
+    }
+
+    DialogScales::~DialogScales()
+    {
+      std::map<std::string, PropDouble*>::iterator it;
+      for (it=propScales_.begin(); it!=propScales_.end(); ++it)
+	{
+	  delete it->second;
+	}
+    }
+
+    void
+    DialogScales::Init()
+    {
+      std::map<std::string, PropDouble*>::iterator it;
+      for (it=propScales_.begin(); it!=propScales_.end(); ++it)
+	{
+	  PropDouble* prop = it->second;
+	  const std::string key = it->first;
+	  prop->SetValue(GetCurrentItem().GetScaleValue(key));
+	}
+    }
+
+  
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogScales.hpp b/SRC/OpenMeca/Gui/Dialog/DialogScales.hpp
new file mode 100644
index 0000000..7ea58e6
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogScales.hpp
@@ -0,0 +1,56 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogScales_hpp 
+#define OpenMeca_Gui_DialogScales_hpp 
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Gui/Prop/PropEnumT.hpp"
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Setting/Scales.hpp"
+
+
+namespace OpenMeca
+{
+ 
+  namespace Gui
+  {
+    class DialogScales :  public DialogUserItemT<Setting::Scales>, 
+			  public Core::Singleton<DialogScales>
+    {
+
+      Q_OBJECT
+    public:
+      DialogScales();
+      virtual ~DialogScales();
+		  
+    private:
+      void Init();
+      
+    private :
+      std::map<std::string, PropDouble*> propScales_;
+      
+    };
+  }
+}
+
+#endif
+    
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogScene.cpp b/SRC/OpenMeca/Gui/Dialog/DialogScene.cpp
new file mode 100644
index 0000000..fd0dc0d
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogScene.cpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+
+
+#include "OpenMeca/Setting/Scene.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogScene.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    DialogScene::DialogScene()
+      :DialogUserItemT<Setting::Scene>(),
+       drawAxis_(this),
+       backgroundColor_(this),
+       sceneCenter_(this),
+       sceneRadius_(this),
+       cameraType_(this)
+    {
+      drawAxis_.SetLabel(QObject::tr("Draw scene axis"));
+
+      backgroundColor_.SetLabel(QObject::tr("Background color"));
+      
+      sceneCenter_.SetLabel(QObject::tr("Scene center"));
+      sceneCenter_.SetDimension(Util::Dimension::Get("Length"));
+
+      sceneRadius_.SetLabel(QObject::tr("Scene radius"));
+      sceneRadius_.SetDimension(Util::Dimension::Get("Length"));
+
+      cameraType_.Prop::SetLabel(QObject::tr("Camera"));
+
+      GetPropTree().Add(drawAxis_);
+      GetPropTree().Add(backgroundColor_);
+      GetPropTree().Add(sceneCenter_);
+      GetPropTree().Add(sceneRadius_);
+      GetPropTree().Add(cameraType_);
+    }
+
+    DialogScene::~DialogScene()
+    {
+    }
+
+    void
+    DialogScene::Init()
+    {
+      drawAxis_.SetValue(GetCurrentItem().GetDrawAxis());
+      backgroundColor_.SetValue(GetCurrentItem().GetBackgroundColor());
+      sceneCenter_.SetValue(GetCurrentItem().GetSceneCenter());
+      sceneRadius_.SetValue(GetCurrentItem().GetSceneRadius());
+      cameraType_.SetValue(GetCurrentItem().GetCameraType());
+    }
+
+  
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogScene.hpp b/SRC/OpenMeca/Gui/Dialog/DialogScene.hpp
new file mode 100644
index 0000000..2ab910f
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogScene.hpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogScene_hpp 
+#define OpenMeca_Gui_DialogScene_hpp 
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Gui/Prop/PropVector.hpp"
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropColor.hpp"
+#include "OpenMeca/Gui/Prop/PropBool.hpp"
+#include "OpenMeca/Setting/Scene.hpp"
+#include "OpenMeca/Gui/Prop/PropEnumT.hpp"
+
+namespace OpenMeca
+{
+ 
+  namespace Gui
+  {
+    class DialogScene :  public DialogUserItemT<Setting::Scene>, 
+			  public Core::Singleton<DialogScene>
+    {
+
+      Q_OBJECT
+    public:
+      DialogScene();
+      virtual ~DialogScene();
+		  
+    private:
+      void Init();
+      
+    private :
+      PropBool drawAxis_;
+      PropColor backgroundColor_;
+      PropVector sceneCenter_;
+      PropDouble sceneRadius_;
+      PropEnumT<qglviewer::Camera::Type> cameraType_;
+      
+    };
+  }
+}
+
+#endif
+    
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogSensorT.hpp b/SRC/OpenMeca/Gui/Dialog/DialogSensorT.hpp
new file mode 100644
index 0000000..ee3bece
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogSensorT.hpp
@@ -0,0 +1,104 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogSensorT_hpp
+#define OpenMeca_Gui_DialogSensorT_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+#include "OpenMeca/Gui/Prop/PropSelectItemT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    template<class Parent, class Quantity, class How>
+    class SensorT;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    template<class Parent, class Quantity, class How>
+    class DialogSensorT : public DialogUserItemT<Item::SensorT<Parent, Quantity, How> >, 
+			  public Core::Singleton<DialogSensorT<Parent, Quantity, How> >
+    {
+      
+    public:
+      DialogSensorT();
+      ~DialogSensorT();
+
+    private:
+      void Init();
+
+    private:
+      PropString id_;
+      PropSelectItemT< Core::AutoRegisteredPtr<Parent, Item::SensorT<Parent, Quantity, How> > > parent_;
+    };
+
+    template<class Parent, class Quantity, class How>
+    inline
+    DialogSensorT<Parent, Quantity, How>::DialogSensorT()
+      :DialogUserItemT<Item::SensorT<Parent, Quantity, How> >(),
+       id_(this),
+       parent_(this)
+    {
+      id_.SetLabel(QObject::tr("Name"));
+      parent_.Prop::SetLabel(QObject::tr("Parent"));
+      
+      // Init table
+      DialogUserItem::GetPropTree().Add(id_);
+      DialogUserItem::GetPropTree().Add(parent_);
+    }
+  
+    template<class Parent, class Quantity, class How>
+    inline
+    DialogSensorT<Parent, Quantity, How>::~DialogSensorT()
+    {
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void
+    DialogSensorT<Parent, Quantity, How>::Init()
+    {
+      Item::SensorT<Parent, Quantity, How>& currentItem = 
+	DialogUserItemT<Item::SensorT<Parent, Quantity, How> >::GetCurrentItem();
+
+      id_.SetValue(currentItem.GetName());
+
+      // populate parent list
+      Core::SetOfBase<Parent>& parent = 
+	Core::System::Get().GetSetOf<Parent>();
+      OMC_ASSERT_MSG(parent.GetTotItemNumber() > 0, "The number of item is null");
+      parent_.SetList(parent);
+      parent_.SetValue(currentItem.GetParentItemPtr());
+
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogSimulation.cpp b/SRC/OpenMeca/Gui/Dialog/DialogSimulation.cpp
new file mode 100755
index 0000000..c57ae2d
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogSimulation.cpp
@@ -0,0 +1,172 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+
+
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogSimulation.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    DialogSimulation::DialogSimulation()
+      :DialogSystemSettingT<Setting::Simulation>(),
+       step_(this),
+       time_(this),
+       solver_(this),
+       integrationType_(this),
+       animationPeriod_(this)
+    {
+      Ui::DialogSimulation::setupUi(this);
+      QObject::connect(player_, SIGNAL(Played()) , this, SLOT(Start()));
+      QObject::connect(player_, SIGNAL(Stopped()), this, SLOT(Stop()));
+      QObject::connect(player_, SIGNAL(Paused()) , this, SLOT(Pause()));
+      QObject::connect(close_ , SIGNAL(clicked()), this, SLOT(Close()));
+
+      step_.SetDimension(Util::Dimension::Get("Time"));
+      step_.SetLabel(QObject::tr("time step"));
+      step_.AddCondition(new Core::Superior<double>(0.));
+
+      time_.SetDimension(Util::Dimension::Get("Time"));
+      time_.SetLabel(QObject::tr("total simulation time"));
+      time_.AddCondition(new Core::Superior<double>(0.));
+
+      solver_.Prop::SetLabel(QObject::tr("Solver"));
+      integrationType_.Prop::SetLabel(QObject::tr("Integration"));
+      
+      animationPeriod_.SetDimension(Util::Dimension::Get("Time"));
+      animationPeriod_.Prop::SetLabel(QObject::tr("Animation period"));
+      animationPeriod_.AddCondition(new Core::Superior<double>(0.));
+
+
+      GetPropTree().Add(step_);
+      GetPropTree().Add(time_);
+      GetPropTree().Add(solver_);
+      GetPropTree().Add(integrationType_);
+      GetPropTree().Add(animationPeriod_);
+    }
+
+    DialogSimulation::~DialogSimulation()
+    {
+      
+    }
+
+    void
+    DialogSimulation::Init()
+    {
+      step_.SetValue(GetSetting().GetTimeStep());
+      time_.SetValue(GetSetting().GetTotalSimulationTime());
+      solver_.SetValue(GetSetting().GetSolver());
+      integrationType_.SetValue(GetSetting().GetIntegrationType());
+      animationPeriod_.SetValue(GetSetting().GetAnimationPeriod());
+
+      step_.AddCondition(new Core::Superior<double>(0.));
+      time_.AddCondition(new Core::Superior<double>(0.));
+      animationPeriod_.AddCondition(new Core::Superior<double>(0.));
+
+    }
+
+
+    bool
+    DialogSimulation::Check()
+    {
+      if (!Dialog::Check())
+	return false;
+      
+      const double stepValue = step_.GetCopy();
+      const double timeValue = time_.GetCopy();
+    
+      if (stepValue > timeValue)
+	{
+	  OMC_WARNING_MSG(tr("The time step must be lower than the total simulation time"));
+	  return false;
+	}
+
+      
+      return true;
+    }
+
+    void 
+    DialogSimulation::Stop()
+    {
+      GetSetting().Stop();
+    }
+
+    void 
+    DialogSimulation::Start()
+    {
+      if (Check())
+	{
+	  ApplyChangement();
+	  GetSetting().Start();
+	}
+      
+    }
+
+    void 
+    DialogSimulation::Pause()
+    {
+      if (Check())
+	{
+	  ApplyChangement();
+	  GetSetting().Pause();
+	}
+    }
+
+    bool
+    DialogSimulation::IsPossibleToClose()
+    {
+      if (Core::SystemSettingT<Setting::Simulation>::Get().IsRunning())
+	{
+	  OMC_INFO_MSG(tr("Please stop your simulation first"));
+	  return false;
+	}
+      return true;
+    }
+
+    
+    void 
+    DialogSimulation::Close()
+    {
+      player_->Stop();
+      
+      
+
+      if (Check())
+	ApplyChangement();
+      
+      Ok();
+      //Cancel();
+      //Reset();
+    }
+
+    void 
+    DialogSimulation::Ok()
+    {
+      DialogSystemSetting::Ok();
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogSimulation.hpp b/SRC/OpenMeca/Gui/Dialog/DialogSimulation.hpp
new file mode 100755
index 0000000..0a93424
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogSimulation.hpp
@@ -0,0 +1,73 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_DialogSimulation_hpp 
+#define OpenMeca_Gui_DialogSimulation_hpp 
+
+#include "ui_DialogSimulation.h"
+#include "OpenMeca/Core/Singleton.hpp"
+#include "OpenMeca/Gui/Dialog/DialogSystemSettingT.hpp"
+#include "OpenMeca/Gui/Prop/PropEnumT.hpp"
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Setting/Simulation.hpp"
+
+#include "ChronoEngine/physics/ChSystem.h"
+
+namespace OpenMeca
+{
+
+  namespace Gui
+  {
+
+    class DialogSimulation :  public DialogSystemSettingT<Setting::Simulation>, 
+			      private Ui::DialogSimulation,
+			      public Core::Singleton<DialogSimulation>
+    {
+
+      Q_OBJECT
+    public:
+      DialogSimulation();
+      virtual ~DialogSimulation();
+      virtual bool Check();
+      PropTree& GetPropTree(){return *tree_;}
+      bool IsPossibleToClose();
+		  
+    private slots:
+      void Stop();
+      void Start();
+      void Pause();
+      void Close();
+
+    private:
+      void Init();
+      void Ok();
+      
+    private :
+      PropDouble step_;
+      PropDouble time_;
+      PropEnumT<chrono::ChSystem::eCh_lcpSolver> solver_;
+      PropEnumT<chrono::ChSystem::eCh_integrationType> integrationType_;
+      PropDouble animationPeriod_;
+    };
+  }
+}
+
+#endif
+    
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogSimulation.ui b/SRC/OpenMeca/Gui/Dialog/DialogSimulation.ui
new file mode 100755
index 0000000..124b49f
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogSimulation.ui
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>DialogSimulation</class>
+ <widget class="QWidget" name="DialogSimulation">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>364</width>
+    <height>339</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QGridLayout">
+   <item row="3" column="0">
+    <widget class="QPushButton" name="close_">
+     <property name="text">
+      <string>Close</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <layout class="QVBoxLayout" name="enumLayout_"/>
+   </item>
+   <item row="2" column="0">
+    <widget class="OpenMeca::Gui::Player" name="player_" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>50</height>
+      </size>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0">
+    <widget class="OpenMeca::Gui::PropTree" name="tree_">
+     <column>
+      <property name="text">
+       <string notr="true">1</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>OpenMeca::Gui::Player</class>
+   <extends>QWidget</extends>
+   <header>OpenMeca/Gui/Player.hpp</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>OpenMeca::Gui::PropTree</class>
+   <extends>QTreeWidget</extends>
+   <header>OpenMeca/Gui/Prop/PropTree.hpp</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="../../Resources.qrc"/>
+  <include location="../../Resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.cpp b/SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.cpp
new file mode 100644
index 0000000..e24033a
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.cpp
@@ -0,0 +1,72 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QShowEvent>
+#include <QMessageBox>
+
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogSystemSetting.hpp"
+#include "OpenMeca/Gui/Prop/Prop.hpp"
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    DialogSystemSetting::DialogSystemSetting()
+      :Dialog()
+    {
+    }
+
+    
+    DialogSystemSetting::~DialogSystemSetting()
+    {
+    }
+    
+    void 
+    DialogSystemSetting::showEvent(QShowEvent* event)
+    {
+      Dialog::showEvent(event);
+    }
+
+    
+    void 
+    DialogSystemSetting::Cancel()
+    {
+      CancelChangement();
+      QWidget::hide();
+      Dialog::Hide_CallBack();
+      Reset();
+    }
+
+    void 
+    DialogSystemSetting::Ok()
+    {
+      if (Check())
+	{
+	  ApplyChangement();
+	  QWidget::hide();
+	  Dialog::Hide_CallBack();
+	  Reset();
+	}
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.hpp b/SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.hpp
new file mode 100644
index 0000000..c09d916
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogSystemSetting.hpp
@@ -0,0 +1,52 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Gui_Dialog_DialogSystemSetting_hpp
+#define OpenMeca_Gui_Dialog_DialogSystemSetting_hpp
+
+#include "OpenMeca/Gui/Dialog/Dialog.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Gui
+  {
+
+    class Widget;
+
+    class DialogSystemSetting : public Dialog
+    {
+     protected:
+      DialogSystemSetting();
+      virtual ~DialogSystemSetting();
+
+      virtual void showEvent (QShowEvent* event );
+      virtual void Init() = 0;
+      
+      void Cancel();
+      virtual void Ok();
+
+      
+
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogSystemSettingT.hpp b/SRC/OpenMeca/Gui/Dialog/DialogSystemSettingT.hpp
new file mode 100644
index 0000000..e13a4d9
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogSystemSettingT.hpp
@@ -0,0 +1,87 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Gui_Dialog_DialogSystemSettingT_hpp
+#define OpenMeca_Gui_Dialog_DialogSystemSettingT_hpp
+
+#include <iostream>
+#include <QAction>
+
+#include "OpenMeca/Gui/Dialog/DialogSystemSetting.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    template <class T>
+    class DialogSystemSettingT : public DialogSystemSetting
+   {
+
+   public:
+     void Edit(QAction& action, T& item);
+      
+   protected:
+     DialogSystemSettingT();
+     virtual ~DialogSystemSettingT();
+     
+     T& GetSetting();
+      
+    };
+
+    template <class T>
+    inline
+    DialogSystemSettingT<T>::DialogSystemSettingT()
+      :DialogSystemSetting()
+    {
+    }
+    
+    template <class T>
+    inline
+    DialogSystemSettingT<T>::~DialogSystemSettingT()
+    {
+    }
+
+    template <class T>
+    inline T&
+    DialogSystemSettingT<T>::GetSetting()
+    {
+      return Core::SystemSettingT<T>::Get();
+    }
+    
+    template <class T>
+    inline void
+    DialogSystemSettingT<T>::Edit(QAction& action, T&)
+    {
+      Dialog::Show_CallBack();
+      DialogSystemSetting::SetAction(action);
+      typename T::Dialog* me = static_cast< typename T::Dialog*>(this);
+      QString title = QString("Edit ") + QString(T::GetStrType().c_str());
+      MainWindow::Get().GetDialogContainer().insertItem(1, me, title);
+      MainWindow::Get().GetDialogContainer().setCurrentIndex(1);
+      Init();
+      me->show();
+    }
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogUserItem.cpp b/SRC/OpenMeca/Gui/Dialog/DialogUserItem.cpp
new file mode 100644
index 0000000..187f58f
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogUserItem.cpp
@@ -0,0 +1,163 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QShowEvent>
+#include <QMessageBox>
+
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogUserItem.hpp"
+#include "OpenMeca/Gui/Prop/Prop.hpp"
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+   
+
+    DialogUserItem::DialogUserItem()
+      :Dialog(),
+       newItemMode_(false)
+    {
+      Ui::DialogUserItem::setupUi(this);
+      QObject::connect(preview_, SIGNAL(clicked()), this, SLOT(Preview()));
+      QObject::connect(cancel_ , SIGNAL(clicked()), this, SLOT(Cancel()));
+      QObject::connect(ok_     , SIGNAL(clicked()), this, SLOT(Ok()));
+    }
+
+    
+    DialogUserItem::~DialogUserItem()
+    {
+    }
+
+
+    void 
+    DialogUserItem::Preview()
+    {
+      if (!IsCurrentUserItemStillExist())
+	{
+	  ManageUserItemNotExist();
+	  return;
+	}
+
+      if (Check())
+	{
+	  ApplyChangement();
+	  Core::System::Get().Update();
+	}
+    }
+    
+    void DialogUserItem::Ok()
+    {
+      if (!IsCurrentUserItemStillExist())
+	{
+	  ManageUserItemNotExist();
+	  return;
+	}
+
+      if (Check())
+	{
+	  ApplyChangement();
+	  QWidget::hide();
+	  Dialog::Hide_CallBack();
+	  Core::System::Get().Update();
+	  Core::System::Get().GetHistoric().SystemEdited();
+	  Dialog::AddActionToHistoric();
+	  Reset();
+	}
+    }
+    
+    void DialogUserItem::Cancel()
+    {
+      CancelChangement();
+      QWidget::hide();
+      Dialog::Hide_CallBack();
+      if (IsCurrentUserItemStillExist())
+	{
+	  if (newItemMode_)
+	    delete &GetCurrentUserItem();
+	  Core::System::Get().Update();
+	}
+      Reset();
+    }
+
+    
+    void DialogUserItem::showEvent(QShowEvent* event)
+    {
+      QWidget::showEvent(event);
+    }
+
+    void
+    DialogUserItem::ApplyChangement()
+    {
+      OMC_ASSERT_MSG(IsCurrentUserItemStillExist() == true, 
+		 "The current item no longer exist");
+      Dialog::ApplyChangement();
+    }
+
+    void 
+    DialogUserItem::DisplayWarningUserItemNotExist()
+    {
+      QMessageBox::warning(this, tr("OpenMeca"), tr("The current edited item was deleted.\n"
+						    "The dialog will be closed"));
+    }
+
+    void 
+    DialogUserItem::ManageUserItemNotExist()
+    {
+      DisplayWarningUserItemNotExist();
+      QWidget::hide();
+      Dialog::Hide_CallBack();
+      Reset();
+    }
+
+
+    void 
+    DialogUserItem::Reset()
+    {
+      Dialog::Reset();
+      newItemMode_ = false;
+    }
+
+    bool 
+    DialogUserItem::IsNewItemAllowed() const
+    {
+      return true;
+    }
+
+
+
+
+    void 
+    DialogUserItem::ActiveNewItemMode()
+    {
+      newItemMode_ = true;
+    }
+    
+    void 
+    DialogUserItem::DisableNewItemMode()
+    {
+      newItemMode_ = false;
+    }
+    
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogUserItem.hpp b/SRC/OpenMeca/Gui/Dialog/DialogUserItem.hpp
new file mode 100644
index 0000000..642beba
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogUserItem.hpp
@@ -0,0 +1,80 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Gui_Dialog_DialogUserItem_hpp_1 
+#define OpenMeca_Gui_Dialog_DialogUserItem_hpp_1 
+
+#include <QWidget>
+
+#include "ui_DialogUserItem.h"
+#include "OpenMeca/Gui/Dialog/Dialog.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    class UserItem;
+  }
+
+  namespace Gui
+  {
+
+
+    class DialogUserItem : public Dialog, 
+			   private Ui::DialogUserItem
+    {
+      Q_OBJECT
+      
+    public slots:
+      void Preview();
+      void Ok();
+      void Cancel();
+
+
+    public:
+      PropTree& GetPropTree(){return *tree_;}
+
+     protected:
+      DialogUserItem();
+      virtual ~DialogUserItem();
+      
+      virtual void showEvent (QShowEvent* event );
+      virtual void Init() = 0;
+      virtual Core::UserItem& GetCurrentUserItem() = 0;
+      virtual bool IsCurrentUserItemStillExist() = 0;
+      virtual void Reset();
+      virtual bool IsNewItemAllowed() const; //return true by default
+      virtual void ApplyChangement();
+
+      void ActiveNewItemMode();
+      void DisableNewItemMode();
+      
+    private:
+      
+      void DisplayWarningUserItemNotExist();
+      void ManageUserItemNotExist();
+
+    private:
+      bool newItemMode_;
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogUserItem.ui b/SRC/OpenMeca/Gui/Dialog/DialogUserItem.ui
new file mode 100644
index 0000000..b0bf4e8
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogUserItem.ui
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>DialogUserItem</class>
+ <widget class="QWidget" name="DialogUserItem">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>816</width>
+    <height>394</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="OpenMeca::Gui::PropTree" name="tree_">
+     <column>
+      <property name="text">
+       <string notr="true">1</string>
+      </property>
+     </column>
+    </widget>
+   </item>
+   <item>
+    <widget class="QWidget" name="widget_2" native="true">
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>60</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>60</height>
+      </size>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>40</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <property name="sizeConstraint">
+         <enum>QLayout::SetDefaultConstraint</enum>
+        </property>
+        <item>
+         <widget class="QPushButton" name="preview_">
+          <property name="minimumSize">
+           <size>
+            <width>100</width>
+            <height>30</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>100</width>
+            <height>30</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>Preview</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <spacer name="horizontalSpacer">
+          <property name="orientation">
+           <enum>Qt::Horizontal</enum>
+          </property>
+          <property name="sizeHint" stdset="0">
+           <size>
+            <width>40</width>
+            <height>20</height>
+           </size>
+          </property>
+         </spacer>
+        </item>
+        <item>
+         <widget class="QPushButton" name="cancel_">
+          <property name="minimumSize">
+           <size>
+            <width>100</width>
+            <height>30</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>100</width>
+            <height>30</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>Cancel</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="ok_">
+          <property name="minimumSize">
+           <size>
+            <width>100</width>
+            <height>30</height>
+           </size>
+          </property>
+          <property name="maximumSize">
+           <size>
+            <width>100</width>
+            <height>30</height>
+           </size>
+          </property>
+          <property name="text">
+           <string>OK</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>OpenMeca::Gui::PropTree</class>
+   <extends>QTreeWidget</extends>
+   <header>OpenMeca/Gui/Prop/PropTree.hpp</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogUserItemT.hpp b/SRC/OpenMeca/Gui/Dialog/DialogUserItemT.hpp
new file mode 100644
index 0000000..836cc96
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogUserItemT.hpp
@@ -0,0 +1,175 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Gui_Dialog_DialogUserItemT_hpp
+#define OpenMeca_Gui_Dialog_DialogUserItemT_hpp
+
+#include <iostream>
+#include <QAction>
+
+#include "OpenMeca/Gui/Dialog/DialogUserItem.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    template <class T>
+    class DialogUserItemT : public DialogUserItem
+   {
+
+   public:
+     void New(QAction& action);
+     template<class Parent> void New(QAction& action, Parent& parent);
+     void Edit(QAction& action, T& item);
+      
+   protected:
+     DialogUserItemT();
+     virtual ~ DialogUserItemT();
+     Core::UserItem& GetCurrentUserItem();
+     T& GetCurrentItem();
+     bool IsCurrentUserItemStillExist();
+     
+   private:
+     void Reset();
+
+    private:
+     T* currentItem_;
+      
+    };
+
+    template <class T>
+    inline
+    DialogUserItemT<T>::DialogUserItemT()
+      : DialogUserItem(),
+       currentItem_(0)
+    {
+    }
+    
+    template <class T>
+    inline
+    DialogUserItemT<T>::~DialogUserItemT()
+    {
+    }
+    
+    template <class T>
+    inline void
+    DialogUserItemT<T>::New(QAction& action)
+    {
+      if (!MainWindow::Get().CloseDialog(true))
+	return ;
+      
+      if (IsNewItemAllowed())
+	{
+	  Dialog::Show_CallBack(); 
+	  DialogUserItem::ActiveNewItemMode();
+	  DialogUserItem::SetAction(action);
+	  OMC_ASSERT_MSG(currentItem_ == 0, "the current item is not null");
+	  currentItem_ = new T();
+	  typename T::Dialog* me = static_cast< typename T::Dialog*>(this);
+	  QString title = QObject::tr("New ") + T::GetQStrType();
+	  MainWindow::Get().GetDialogContainer().insertItem(1, me, title);
+	  MainWindow::Get().GetDialogContainer().setCurrentIndex(1);
+	  Init();
+	  me->show();
+	}
+    }
+
+    template <class T>
+    template <class Parent>
+    inline void
+    DialogUserItemT<T>::New(QAction& action, Parent& parent)
+    {
+      if (!MainWindow::Get().CloseDialog(false))
+	return ;
+
+      if (IsNewItemAllowed())
+	{
+	  Dialog::Show_CallBack();
+	  DialogUserItem::ActiveNewItemMode();
+	  DialogUserItem::SetAction(action);
+	  OMC_ASSERT_MSG(currentItem_ == 0, "the current item is not null");
+	  currentItem_ = new T(parent);
+	  typename T::Dialog* me = static_cast< typename T::Dialog*>(this);
+	  QString title = QString("New ") + QString(T::GetStrType().c_str());
+	  MainWindow::Get().GetDialogContainer().insertItem(1, me, title);
+	  MainWindow::Get().GetDialogContainer().setCurrentIndex(1);
+	  Init();
+	  me->show();
+	}
+    }
+
+
+    template <class T>
+    inline void
+    DialogUserItemT<T>::Edit(QAction& action, T& item)
+    {
+      if (!MainWindow::Get().CloseDialog(true))
+	return ;
+      
+      Dialog::Show_CallBack();
+      DialogUserItem::DisableNewItemMode();
+      DialogUserItem::SetAction(action);
+      OMC_ASSERT_MSG(currentItem_ == 0, "the current item is not null");
+      currentItem_ = &item;
+      typename T::Dialog* me = static_cast< typename T::Dialog*>(this);
+      QString title = QString("Edit ") + QString(T::GetStrType().c_str());
+      MainWindow::Get().GetDialogContainer().insertItem(1, me, title);
+      MainWindow::Get().GetDialogContainer().setCurrentIndex(1);
+      Init();
+      me->show();
+    }
+
+    template <class T>
+    inline bool
+    DialogUserItemT<T>::IsCurrentUserItemStillExist()
+    {
+      OMC_ASSERT_MSG(currentItem_ != 0, "the current item is null");
+      return Core::AutoRegister<T>::Exist(*currentItem_);
+    }
+    
+    template <class T>
+    inline Core::UserItem& 
+    DialogUserItemT<T>::GetCurrentUserItem()
+    {
+      OMC_ASSERT_MSG(currentItem_ != 0, "the current item is null");
+      return reinterpret_cast<Core::UserItem& >(*currentItem_);
+    }
+
+    template <class T>
+    inline T& 
+    DialogUserItemT<T>::GetCurrentItem()
+    {
+      OMC_ASSERT_MSG(currentItem_ != 0, "the current item is null");
+      return *currentItem_;
+    }
+
+    template <class T>
+    inline void
+    DialogUserItemT<T>::Reset()
+    {
+      DialogUserItem::Reset();
+      currentItem_=0;
+    }
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogVariable.cpp b/SRC/OpenMeca/Gui/Dialog/DialogVariable.cpp
new file mode 100644
index 0000000..de595ca
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogVariable.cpp
@@ -0,0 +1,112 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Dialog/DialogVariable.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Item/Variable.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+    DialogVariable::DialogVariable()
+      :DialogUserItemT<Item::Variable>(),
+       symbol_(this),
+       value_(this)
+    {
+      symbol_.SetLabel(QObject::tr("Symbol"));
+      
+      value_.SetDimension(Util::Dimension::Get("Null"));
+      value_.SetLabel(QObject::tr("Value"));
+
+      // Init table
+      GetPropTree().Add(symbol_);
+      GetPropTree().Add(value_);
+    }
+  
+    DialogVariable::~DialogVariable()
+    {
+    }
+
+    void
+    DialogVariable::Init()
+    {
+      // Equalize symbol and name
+      //GetCurrentItem().GetSymbol() = GetCurrentItem().GetName();
+      symbol_.SetValue(GetCurrentItem().GetSymbol());
+      value_.SetValue(GetCurrentItem().GetValue());
+    }
+
+    void
+    DialogVariable::ApplyChangement()
+    {
+      DialogUserItemT<Item::Variable>::ApplyChangement();
+      
+      // Equalize symbol and name
+      const std::string name = GetCurrentItem().GetSymbol() + " = " + 
+	value_.GetInputString().toStdString();
+      GetCurrentItem().GetName() = name;
+    }
+
+    void
+    DialogVariable::CancelChangement()
+    {
+      DialogUserItemT<Item::Variable>::CancelChangement();
+      
+      // Equalize symbol and name
+      const std::string name = GetCurrentItem().GetSymbol() + " = " + 
+	value_.GetInputString().toStdString();
+      GetCurrentItem().GetName() = name;
+    }
+    
+    bool 
+    DialogVariable::Check()
+    {
+      if (!DialogUserItemT<Item::Variable>::Check())
+	return false;
+      
+      Util::Var& var = GetCurrentItem();
+      const std::string initialSymbol = var.GetSymbol();
+      var.GetSymbol() = symbol_.GetCopy();
+      if (var.IsDoublon())
+	{
+	  symbol_.DisplayHelp(QObject::tr("The name of the variable is already used"));
+	  var.GetSymbol() = initialSymbol;
+	  return false;
+	}
+
+      if (!var.IsValid())
+	{
+	  symbol_.DisplayHelp(QObject::tr("It's not a valid variable name"));
+	  var.GetSymbol() = initialSymbol;
+	  return false;
+	}
+      
+      var.GetSymbol() = initialSymbol;
+      return true;
+    }
+    
+   
+
+  
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/DialogVariable.hpp b/SRC/OpenMeca/Gui/Dialog/DialogVariable.hpp
new file mode 100644
index 0000000..05b00d5
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/DialogVariable.hpp
@@ -0,0 +1,68 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Dialog_DialogVariable_hpp
+#define OpenMeca_Gui_Dialog_DialogVariable_hpp
+
+#include "OpenMeca/Gui/Dialog/DialogUserItemT.hpp"
+#include "OpenMeca/Core/Singleton.hpp"
+
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    class Variable;
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogVariable : public DialogUserItemT<Item::Variable>, 
+			   public Core::Singleton<DialogVariable>
+    {
+      
+    public:
+      DialogVariable();
+      ~DialogVariable();
+
+    private:
+      void Init();
+
+    protected:
+      virtual void ApplyChangement();
+      virtual void CancelChangement();
+      virtual bool Check();
+
+    private:
+      PropString symbol_;
+      PropDouble value_;
+
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.cpp b/SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.cpp
new file mode 100644
index 0000000..2fd4762
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.cpp
@@ -0,0 +1,56 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Physic/Force.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Physic
+    {
+    
+      DialogForce::DialogForce(QWidget* widget)
+	:DialogMechanicalAction(widget)
+      {
+	const std::string & unitStr = OpenMeca::Physic::Force::GetStrType();
+	DialogMechanicalAction::value_.SetDimension(Util::Dimension::Get(unitStr));
+      }
+
+      DialogForce::~DialogForce()
+      {
+      }
+      
+      void 
+      DialogForce::Add(Gui::PropTree& prop)
+      {
+	DialogMechanicalAction::Add(prop);
+      }
+      
+      void 
+      DialogForce::Init(OpenMeca::Physic::Force& f)
+      {
+	DialogMechanicalAction::Init(f);
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.hpp b/SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.hpp
new file mode 100644
index 0000000..f3f048b
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Physic/DialogForce.hpp
@@ -0,0 +1,54 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Physic_DialogForce_hpp
+#define OpenMeca_Gui_Physic_DialogForce_hpp
+
+#include "OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.hpp"
+
+
+namespace OpenMeca
+{ 
+  namespace Physic
+  { 
+    class Force; 
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Physic
+    {
+      class DialogForce : public DialogMechanicalAction
+      {
+      public:
+	DialogForce(QWidget* widget);
+	~DialogForce();
+	void Add(Gui::PropTree& prop);
+	void Init(OpenMeca::Physic::Force& f);
+      };
+
+      
+    }
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.cpp b/SRC/OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.cpp
new file mode 100644
index 0000000..ea0a8e4
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.cpp
@@ -0,0 +1,61 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Physic/MechanicalAction.hpp"
+#include "OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Physic
+    {
+    
+      DialogMechanicalAction::DialogMechanicalAction(QWidget* widget):
+	value_(widget),
+	direction_(widget)
+      {
+	value_.SetLabel(QObject::tr("Value"));
+	direction_.SetLabel(QObject::tr("Direction coordinate"));
+      }
+
+      DialogMechanicalAction::~DialogMechanicalAction()
+      {
+      }
+      
+      void 
+      DialogMechanicalAction::Add(Gui::PropTree& prop)
+      {
+	prop.Add(value_);
+	prop.Add(direction_);
+      }
+      
+      void 
+      DialogMechanicalAction::Init(OpenMeca::Physic::MechanicalAction& f)
+      {
+	value_.SetValue(f.GetValue());
+	direction_.SetValue(f.GetDirectionMode());
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.hpp b/SRC/OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.hpp
new file mode 100644
index 0000000..b18f519
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.hpp
@@ -0,0 +1,60 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Physic_DialogMechanicalAction_hpp
+#define OpenMeca_Gui_Physic_DialogMechanicalAction_hpp
+
+#include <QWidget>
+#include "OpenMeca/Gui/Prop/PropEnumT.hpp"
+#include "OpenMeca/Gui/Prop/PropVector.hpp"
+#include "OpenMeca/Physic/PhysEnum.hpp"
+
+namespace OpenMeca
+{ 
+  namespace Physic
+  { 
+    class MechanicalAction; 
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Physic
+    {
+      class DialogMechanicalAction
+      {
+      public:
+	DialogMechanicalAction(QWidget* widget);
+	virtual ~DialogMechanicalAction();
+	virtual void Add(Gui::PropTree& prop);
+	virtual void Init(OpenMeca::Physic::MechanicalAction& f);
+	
+      protected:
+	PropVector value_;
+	PropEnumT<OpenMeca::Physic::MechActionEnum::DirectionMode> direction_;
+      };
+
+      
+    }
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.cpp b/SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.cpp
new file mode 100644
index 0000000..0d2a438
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.cpp
@@ -0,0 +1,56 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Physic/Torque.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Physic
+    {
+    
+      DialogTorque::DialogTorque(QWidget* widget)
+	:DialogMechanicalAction(widget)
+      {
+	const std::string & unitStr = OpenMeca::Physic::Torque::GetStrType();
+	DialogMechanicalAction::value_.SetDimension(Util::Dimension::Get(unitStr));
+      }
+
+      DialogTorque::~DialogTorque()
+      {
+      }
+      
+      void 
+      DialogTorque::Add(Gui::PropTree& prop)
+      {
+	DialogMechanicalAction::Add(prop);
+      }
+      
+      void 
+      DialogTorque::Init(OpenMeca::Physic::Torque& f)
+      {
+	DialogMechanicalAction::Init(f);
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.hpp b/SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.hpp
new file mode 100644
index 0000000..2e61e47
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Physic/DialogTorque.hpp
@@ -0,0 +1,54 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Physic_DialogTorque_hpp
+#define OpenMeca_Gui_Physic_DialogTorque_hpp
+
+#include "OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.hpp"
+
+
+namespace OpenMeca
+{ 
+  namespace Physic
+  { 
+    class Torque; 
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Physic
+    {
+      class DialogTorque : public DialogMechanicalAction
+      {
+      public:
+	DialogTorque(QWidget* widget);
+	~DialogTorque();
+	void Add(Gui::PropTree& prop);
+	void Init(OpenMeca::Physic::Torque& f);
+      };
+
+      
+    }
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Physic/Physic.pro b/SRC/OpenMeca/Gui/Dialog/Physic/Physic.pro
new file mode 100644
index 0000000..02d4b8b
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Physic/Physic.pro
@@ -0,0 +1,27 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Gui/Dialog/Physic/DialogForce.hpp \
+           Gui/Dialog/Physic/DialogTorque.hpp \
+           Gui/Dialog/Physic/DialogMechanicalAction.hpp 
+
+SOURCES += Gui/Dialog/Physic/DialogForce.cpp \
+           Gui/Dialog/Physic/DialogTorque.cpp \
+           Gui/Dialog/Physic/DialogMechanicalAction.cpp 
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.cpp b/SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.cpp
new file mode 100644
index 0000000..618e207
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.cpp
@@ -0,0 +1,70 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Item/Shape/Cylinder.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/DialogCylinder.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+    
+      DialogCylinder::DialogCylinder(QWidget* widget):
+	radius_(widget),
+	length_(widget),
+	axis_(widget)
+      {
+	radius_.SetDimension(Util::Dimension::Get("Length"));
+	radius_.SetLabel(QObject::tr("Radius"));
+	radius_.AddCondition(new Core::Superior<double>(0.));
+
+	length_.SetDimension(Util::Dimension::Get("Length"));
+	length_.SetLabel(QObject::tr("Length"));
+	length_.AddCondition(new Core::Superior<double>(0.));
+
+	axis_.SetDimension(Util::Dimension::Get("Length"));
+	axis_.SetLabel(QObject::tr("Axis"));
+      }
+      
+      void 
+      DialogCylinder::Add(Gui::PropTree& prop)
+      {
+	prop.Add(radius_);
+	prop.Add(length_);
+	prop.Add(axis_);
+      }
+      
+      void 
+      DialogCylinder::Init(OpenMeca::Item::Shape::Cylinder& s)
+      {
+	radius_.SetValue(s.GetRadius());
+	length_.SetValue(s.GetLength());
+	axis_.SetValue(s.GetAxis());
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.hpp b/SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.hpp
new file mode 100644
index 0000000..8afa455
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/DialogCylinder.hpp
@@ -0,0 +1,63 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Shape_DialogCylinder_hpp
+#define OpenMeca_Gui_Shape_DialogCylinder_hpp
+
+#include <QWidget>
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropAxis.hpp"
+#include "OpenMeca/Gui/Prop/PropAttitude.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+      class Cylinder;
+    }
+  }
+}
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+      class DialogCylinder
+      {
+      public:
+	DialogCylinder(QWidget* widget);
+	void Add(Gui::PropTree& prop);
+	void Init(OpenMeca::Item::Shape::Cylinder& s);
+	
+      private:
+	Gui::PropDouble radius_;
+	Gui::PropDouble length_;
+	Gui::PropAxis axis_;
+      };
+
+    }
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.cpp b/SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.cpp
new file mode 100644
index 0000000..7cabe15
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.cpp
@@ -0,0 +1,52 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "OpenMeca/Item/Shape/Ground.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/DialogGround.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+    
+      DialogGround::DialogGround(QWidget* widget):
+	axis_(widget)
+      {
+	axis_.SetDimension(Util::Dimension::Get("Length"));
+	axis_.SetLabel(QObject::tr("Axis"));
+      }
+      
+      void 
+      DialogGround::Add(Gui::PropTree& prop)
+      {
+	prop.Add(axis_);
+      }
+      
+      void 
+      DialogGround::Init(OpenMeca::Item::Shape::Ground& s)
+      {
+	axis_.SetValue(s.GetAxis());
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.hpp b/SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.hpp
new file mode 100644
index 0000000..fdffc9d
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/DialogGround.hpp
@@ -0,0 +1,63 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Shape_DialogGround_hpp
+#define OpenMeca_Item_Shape_DialogGround_hpp
+
+#include <QWidget>
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropAxis.hpp"
+#include "OpenMeca/Gui/Prop/PropAttitude.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+      class Ground;
+    }
+  }
+}
+
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+    
+      class DialogGround
+      {
+      public:
+	DialogGround(QWidget* widget);
+	void Add(Gui::PropTree& prop);
+	void Init(OpenMeca::Item::Shape::Ground& s);
+	
+      private:
+	Gui::PropAxis axis_;
+      };
+
+    }
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.cpp b/SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.cpp
new file mode 100644
index 0000000..3bf6dcd
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.cpp
@@ -0,0 +1,56 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Shape/Sphere.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/DialogSphere.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/DialogSphere.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+    
+      DialogSphere::DialogSphere(QWidget* widget):
+	radius_(widget)
+      {
+	radius_.SetDimension(Util::Dimension::Get("Length"));
+	radius_.SetLabel(QObject::tr("Radius"));
+	radius_.AddCondition(new Core::Superior<double>(0.));
+      }
+      
+      void 
+      DialogSphere::Add(Gui::PropTree& prop)
+      {
+	prop.Add(radius_);
+      }
+      
+      void 
+      DialogSphere::Init(OpenMeca::Item::Shape::Sphere& s)
+      {
+	radius_.SetValue(s.GetRadius());
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.hpp b/SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.hpp
new file mode 100644
index 0000000..81c7ef7
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/DialogSphere.hpp
@@ -0,0 +1,64 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Shape_DialogSphere_hpp
+#define OpenMeca_Gui_Shape_DialogSphere_hpp
+
+#include <QWidget>
+#include <QWidget>
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropAxis.hpp"
+#include "OpenMeca/Gui/Prop/PropAttitude.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+      class Sphere;
+    }
+  }
+}
+
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+      class DialogSphere
+      {
+      public:
+	DialogSphere(QWidget* widget);
+	void Add(Gui::PropTree& prop);
+	void Init(OpenMeca::Item::Shape::Sphere& s);
+	
+      private:
+	Gui::PropDouble radius_;
+      };
+
+      
+    }
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/Shape.pro b/SRC/OpenMeca/Gui/Dialog/Shape/Shape.pro
new file mode 100644
index 0000000..0a2f857
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/Shape.pro
@@ -0,0 +1,29 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Gui/Dialog/Shape/ShapeDialogBox.hpp \
+           Gui/Dialog/Shape/DialogSphere.hpp \
+           Gui/Dialog/Shape/DialogCylinder.hpp \
+           Gui/Dialog/Shape/DialogGround.hpp
+
+SOURCES += Gui/Dialog/Shape/ShapeDialogBox.cpp \
+           Gui/Dialog/Shape/DialogSphere.cpp \
+           Gui/Dialog/Shape/DialogCylinder.cpp \
+           Gui/Dialog/Shape/DialogGround.cpp
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.cpp b/SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.cpp
new file mode 100644
index 0000000..5798f5e
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.cpp
@@ -0,0 +1,75 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Item/Shape/Box.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+    
+      ShapeDialogBox::ShapeDialogBox(QWidget* widget):
+	lx_(widget),
+	ly_(widget),
+	lz_(widget),
+	attitude_(widget)
+      {
+	lx_.SetDimension(Util::Dimension::Get("Length"));
+	lx_.SetLabel(QObject::tr("Length along X"));
+	lx_.AddCondition(new Core::Superior<double>(0.));
+	
+	ly_.SetDimension(Util::Dimension::Get("Length"));
+	ly_.SetLabel(QObject::tr("Length along Y"));
+	ly_.AddCondition(new Core::Superior<double>(0.));
+
+	lz_.SetDimension(Util::Dimension::Get("Length"));
+	lz_.SetLabel(QObject::tr("Length along Z"));
+	lz_.AddCondition(new Core::Superior<double>(0.));
+
+	attitude_.SetLabel(QObject::tr("Rotation"));
+      }
+      
+      void 
+      ShapeDialogBox::Add(Gui::PropTree& prop)
+      {
+	prop.Add(lx_);
+	prop.Add(ly_);
+	prop.Add(lz_);
+	prop.Add(attitude_);
+      }
+      
+      void 
+      ShapeDialogBox::Init(OpenMeca::Item::Shape::Box& s)
+      {
+	lx_.SetValue(s.GetLengthX());
+	ly_.SetValue(s.GetLengthY());
+	lz_.SetValue(s.GetLengthZ());
+	attitude_.SetValue(s.GetAttitude());
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.hpp b/SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.hpp
new file mode 100644
index 0000000..2de5877
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.hpp
@@ -0,0 +1,64 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Shape_DialogBox_hpp
+#define OpenMeca_Gui_Shape_DialogBox_hpp
+
+#include <QWidget>
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropAxis.hpp"
+#include "OpenMeca/Gui/Prop/PropAttitude.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+      class Box;
+    }
+  }
+}
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    namespace Shape
+    {
+    
+      class ShapeDialogBox
+      {
+      public:
+	ShapeDialogBox(QWidget* widget);
+	void Add(Gui::PropTree& prop);
+	void Init(OpenMeca::Item::Shape::Box& s);
+	
+      private:
+	Gui::PropDouble lx_;
+	Gui::PropDouble ly_;
+	Gui::PropDouble lz_;
+	Gui::PropAttitude attitude_;
+      };
+      
+    }
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/ExampleAction.cpp b/SRC/OpenMeca/Gui/ExampleAction.cpp
new file mode 100644
index 0000000..2e4b7b2
--- /dev/null
+++ b/SRC/OpenMeca/Gui/ExampleAction.cpp
@@ -0,0 +1,61 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QMouseEvent>
+#include <QTemporaryDir>
+
+#include "OpenMeca/Gui/ExampleAction.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+namespace OpenMeca
+{
+  
+  namespace Gui
+  {
+    ExampleAction::ExampleAction(QString fileName, QWidget * parent)
+      :QAction(QObject::tr(fileName.remove(".omc").toStdString().c_str()), parent),
+       fileName_(fileName)
+    {
+      QObject::connect(this, SIGNAL(triggered()), this, SLOT(OpenExample()));
+    }
+    
+    ExampleAction::~ExampleAction()
+    {
+    }
+
+    void
+    ExampleAction::OpenExample()
+    {
+      if (MainWindow::Get().CloseDialog(true))
+	{
+      
+	  QFile file(":/Rsc/Example/"+fileName_+".omc");
+	  QTemporaryDir dir;
+	  OMC_ASSERT_MSG(file.copy(dir.path() + fileName_+".omc"), "can't copy file in temporary dir !");
+	  
+	  const std::string file_cp = QString(dir.path()+fileName_+".omc").toStdString();
+	  Core::System::Get().LoadFile(file_cp);
+	}
+    }
+  
+    
+  }
+}
diff --git a/SRC/OpenMeca/Gui/ExampleAction.hpp b/SRC/OpenMeca/Gui/ExampleAction.hpp
new file mode 100644
index 0000000..0cb2688
--- /dev/null
+++ b/SRC/OpenMeca/Gui/ExampleAction.hpp
@@ -0,0 +1,53 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#ifndef OpenMeca_Gui_ExampleAction_hpp
+#define OpenMeca_Gui_ExampleAction_hpp
+
+#include <QAction>
+#include <QString>
+
+namespace OpenMeca
+{
+
+  namespace Gui
+  {
+
+    class ExampleAction : public QAction
+    { 
+      Q_OBJECT
+
+    public:
+      ExampleAction(QString fileName, QWidget * parent);
+      virtual ~ExampleAction();
+
+    public slots:
+      void OpenExample();
+		      
+    private:
+      const QString fileName_;
+      
+    };
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/GeneralSetting.cpp b/SRC/OpenMeca/Gui/GeneralSetting.cpp
new file mode 100644
index 0000000..fdab2b5
--- /dev/null
+++ b/SRC/OpenMeca/Gui/GeneralSetting.cpp
@@ -0,0 +1,101 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QMenu>
+#include <QMessageBox>
+#include <qwt/qwt_legend.h>
+
+#include "OpenMeca/Gui/GeneralSetting.hpp"
+#include "OpenMeca/Core/ConfigDirectory.hpp"
+#include "OpenMeca/Setting/LangManager.hpp"
+#include "OpenMeca/Util/Lang.hpp"
+#include "OpenMeca/Core/ConfigDirectory.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+
+    GeneralSetting::GeneralSetting(QWidget * parent)
+      :QDialog(parent)
+    {
+      setupUi(this);
+      ReadLang();
+
+      QObject::connect(buttonBox_, SIGNAL(accepted()), this, SLOT(Apply()));
+      QObject::connect(pushButtonReset_, SIGNAL(clicked()), this, SLOT(Reset()));
+    }
+    
+    GeneralSetting::~GeneralSetting()
+    {
+    }
+    
+
+    void
+    GeneralSetting::ReadLang()
+    {
+      const Util::Lang& current = Setting::LangManager::Get().GetUserChoice();
+      std::map<const std::string, Util::Lang*>& lang = Util::Lang::GetAll();
+      std::map<const std::string, Util::Lang*>::iterator it;
+
+      for (it = lang.begin(); it != lang.end(); ++it)
+	comboBoxLang_->addItem(it->second->GetName().c_str());
+      comboBoxLang_->setCurrentIndex(current.GetIndex());
+    }
+  
+    void
+    GeneralSetting::Apply()
+    {
+      ApplyLang();
+      NotifyRestart();
+      
+    }
+
+    void
+    GeneralSetting::NotifyRestart()
+    {
+      QMessageBox::information(this, tr("Information"),
+			       tr("You must restart openmeca to apply settings"));
+    }
+
+    void
+    GeneralSetting::ApplyLang()
+    {
+      const Util::Lang& lang = Util::Lang::GetByIndex(comboBoxLang_->currentIndex());
+      Setting::LangManager::Get().SetUserChoice(lang);
+    }
+
+    void
+    GeneralSetting::Reset()
+    {
+      QString msg;
+      msg += QObject::tr("You are going to reset the setting of openmeca, are you sure ?");
+      QMessageBox mbox(QMessageBox::Information, tr("Question"), msg,
+		       QMessageBox::Yes|QMessageBox::No); 
+      if (QMessageBox::Yes == mbox.exec())
+	{
+	  Core::ConfigFile::RestoreAll();
+	  NotifyRestart();
+	  hide();
+	}
+    }
+    
+  }
+}
diff --git a/SRC/OpenMeca/Gui/GeneralSetting.hpp b/SRC/OpenMeca/Gui/GeneralSetting.hpp
new file mode 100644
index 0000000..285dea4
--- /dev/null
+++ b/SRC/OpenMeca/Gui/GeneralSetting.hpp
@@ -0,0 +1,57 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_GeneralSetting_hpp
+#define OpenMeca_Gui_GeneralSetting_hpp
+
+#include <QDialog>
+
+#include "ui_GeneralSetting.h"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class GeneralSetting : public QDialog, 
+		           private Ui::GeneralSetting
+    {
+      Q_OBJECT
+    public:
+      GeneralSetting(QWidget * parent);
+      virtual ~GeneralSetting();
+      
+      
+      
+   private:
+      void ReadLang();
+      void ApplyLang();
+      void NotifyRestart();		      
+
+    private slots:
+      void Apply();
+      void Reset();
+
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/GeneralSetting.ui b/SRC/OpenMeca/Gui/GeneralSetting.ui
new file mode 100644
index 0000000..d321e32
--- /dev/null
+++ b/SRC/OpenMeca/Gui/GeneralSetting.ui
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>GeneralSetting</class>
+ <widget class="QDialog" name="GeneralSetting">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>355</width>
+    <height>270</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>General setting</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <widget class="QTabWidget" name="tabWidget">
+     <property name="currentIndex">
+      <number>0</number>
+     </property>
+     <widget class="QWidget" name="tab">
+      <attribute name="title">
+       <string>Language</string>
+      </attribute>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QLabel" name="label">
+         <property name="text">
+          <string>Choose your language :</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QComboBox" name="comboBoxLang_"/>
+       </item>
+       <item>
+        <spacer name="verticalSpacer">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>20</width>
+           <height>40</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+      </layout>
+     </widget>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QPushButton" name="pushButtonReset_">
+       <property name="text">
+        <string>Reset Setting</string>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+     <item>
+      <widget class="QDialogButtonBox" name="buttonBox_">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="standardButtons">
+        <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>buttonBox_</sender>
+   <signal>accepted()</signal>
+   <receiver>GeneralSetting</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox_</sender>
+   <signal>rejected()</signal>
+   <receiver>GeneralSetting</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Gui.pro b/SRC/OpenMeca/Gui/Gui.pro
new file mode 100644
index 0000000..be1e7ff
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Gui.pro
@@ -0,0 +1,55 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+include(./Widget/Widget.pro)
+include(./Dialog/Dialog.pro)
+include(./Prop/Prop.pro)
+
+FORMS   += Gui/MainWindow.ui \
+           Gui/MainPlotWindow.ui \
+           Gui/ImageDialog.ui \
+           Gui/Player.ui \
+           Gui/GeneralSetting.ui
+
+HEADERS += Gui/AbstractTreeItem.hpp \
+           Gui/ExampleAction.hpp \
+           Gui/MainTreeItem.hpp \
+           Gui/MainWindow.hpp \
+           Gui/HelpBrowser.hpp \
+           Gui/MainPlotWindow.hpp \
+           Gui/GeneralSetting.hpp \
+           Gui/ImageDialog.hpp \
+           Gui/Player.hpp \
+           Gui/SecondaryTreeItem.hpp \
+           Gui/RootTreeItemT.hpp \
+           Gui/TreeView.hpp \
+           Gui/Viewer.hpp
+
+SOURCES += Gui/AbstractTreeItem.cpp \
+           Gui/ExampleAction.cpp \
+           Gui/MainWindow.cpp \
+           Gui/Player.cpp \
+           Gui/Viewer.cpp \
+           Gui/MainTreeItem.cpp \
+           Gui/GeneralSetting.cpp \
+           Gui/HelpBrowser.cpp \
+           Gui/MainPlotWindow.cpp \
+           Gui/ImageDialog.cpp \
+           Gui/SecondaryTreeItem.cpp \
+           Gui/TreeView.cpp
diff --git a/SRC/OpenMeca/Gui/HelpBrowser.cpp b/SRC/OpenMeca/Gui/HelpBrowser.cpp
new file mode 100644
index 0000000..79e22dc
--- /dev/null
+++ b/SRC/OpenMeca/Gui/HelpBrowser.cpp
@@ -0,0 +1,43 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "OpenMeca/Gui/HelpBrowser.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+    HelpBrowser::HelpBrowser(QHelpEngine* helpEngine, QWidget* parent)
+      :QTextBrowser(parent),
+       helpEngine(helpEngine)
+    {
+    }
+
+    QVariant 
+    HelpBrowser::loadResource(int type, const QUrl &name)
+    {
+      if (name.scheme() == "qthelp")
+        return QVariant(helpEngine->fileData(name));
+      else
+        return QTextBrowser::loadResource(type, name);
+    }
+    
+  }
+}
diff --git a/SRC/OpenMeca/Gui/HelpBrowser.hpp b/SRC/OpenMeca/Gui/HelpBrowser.hpp
new file mode 100644
index 0000000..aab5164
--- /dev/null
+++ b/SRC/OpenMeca/Gui/HelpBrowser.hpp
@@ -0,0 +1,45 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_HelpBrowser_hpp
+#define OpenMeca_Gui_HelpBrowser_hpp
+
+#include <QHelpEngine>
+#include <QTextBrowser>
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    class HelpBrowser : public QTextBrowser
+    {
+     public:
+    HelpBrowser(QHelpEngine* helpEngine, QWidget* parent = 0);
+    QVariant loadResource (int type, const QUrl& name);
+private:
+    QHelpEngine* helpEngine;
+      
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/ImageDialog.cpp b/SRC/OpenMeca/Gui/ImageDialog.cpp
new file mode 100755
index 0000000..c21cc51
--- /dev/null
+++ b/SRC/OpenMeca/Gui/ImageDialog.cpp
@@ -0,0 +1,71 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/ImageDialog.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    QString ImageDialog::defaultFileExtension_("");
+    int  ImageDialog::defaultPrecision_(-1);
+
+
+    ImageDialog::ImageDialog(QWidget * parent, const QStringList & extensions, int& precision, QString& fileExtension)
+      :QDialog (parent),
+       precision_(precision),
+       fileExtension_(fileExtension)
+    {
+      setupUi(this);
+      comboBox_extension->addItems(extensions);
+      if (!(defaultFileExtension_=="" && defaultPrecision_==-1))
+	{
+	  spinBox_quality->setValue(defaultPrecision_);
+	  OMC_ASSERT_MSG(comboBox_extension->findText(defaultFileExtension_)!=-1,
+		     "Can't find image extension");
+	  comboBox_extension->setCurrentIndex(comboBox_extension->findText(defaultFileExtension_));
+	}
+    }
+
+    ImageDialog::~ImageDialog()
+    {
+    }
+
+    void
+    ImageDialog::accept()
+    {
+      precision_ = spinBox_quality->value();
+      fileExtension_ = comboBox_extension->currentText();
+      defaultPrecision_ = precision_ ;
+      defaultFileExtension_ = fileExtension_ ;
+  
+
+      QDialog::accept();
+    }
+
+  }
+}
+
+
+
+
+
diff --git a/SRC/OpenMeca/Gui/ImageDialog.hpp b/SRC/OpenMeca/Gui/ImageDialog.hpp
new file mode 100755
index 0000000..24891eb
--- /dev/null
+++ b/SRC/OpenMeca/Gui/ImageDialog.hpp
@@ -0,0 +1,55 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#ifndef OpenMeca_Gui_hpp
+#define OpenMeca_Gui_hpp
+
+#include <QDialog>
+
+#include "ui_ImageDialog.h"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+
+    class ImageDialog : public QDialog, public Ui::ImageDialog
+    {
+      Q_OBJECT
+  
+    public:
+      ImageDialog(QWidget * parent, const QStringList & extensions, int& precision, QString& fileExtension);
+      ~ImageDialog();
+      void accept();     
+    private:
+      int& precision_;
+      QString& fileExtension_;
+
+      static QString defaultFileExtension_;
+      static int defaultPrecision_;
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/ImageDialog.ui b/SRC/OpenMeca/Gui/ImageDialog.ui
new file mode 100755
index 0000000..e177f11
--- /dev/null
+++ b/SRC/OpenMeca/Gui/ImageDialog.ui
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>ImageDialog</class>
+ <widget class="QDialog" name="ImageDialog">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>227</width>
+    <height>130</height>
+   </rect>
+  </property>
+  <property name="minimumSize">
+   <size>
+    <width>200</width>
+    <height>130</height>
+   </size>
+  </property>
+  <property name="maximumSize">
+   <size>
+    <width>227</width>
+    <height>130</height>
+   </size>
+  </property>
+  <property name="windowTitle">
+   <string>Save image as...</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../Resources.qrc">
+    <normaloff>:/Rsc/Img/Flower.svg</normaloff>:/Rsc/Img/Flower.svg</iconset>
+  </property>
+  <property name="toolTip">
+   <string/>
+  </property>
+  <property name="whatsThis">
+   <string>Choose image parameter</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="0" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QLabel" name="label">
+       <property name="minimumSize">
+        <size>
+         <width>120</width>
+         <height>30</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>120</width>
+         <height>30</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>Image quality </string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QSpinBox" name="spinBox_quality">
+       <property name="buttonSymbols">
+        <enum>QAbstractSpinBox::NoButtons</enum>
+       </property>
+       <property name="suffix">
+        <string>%</string>
+       </property>
+       <property name="maximum">
+        <number>100</number>
+       </property>
+       <property name="value">
+        <number>95</number>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="1" column="0">
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <widget class="QLabel" name="label_2">
+       <property name="minimumSize">
+        <size>
+         <width>120</width>
+         <height>30</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>120</width>
+         <height>30</height>
+        </size>
+       </property>
+       <property name="text">
+        <string>Image format</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QComboBox" name="comboBox_extension"/>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0">
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../Resources.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>ImageDialog</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>ImageDialog</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/SRC/OpenMeca/Gui/MainPlotWindow.cpp b/SRC/OpenMeca/Gui/MainPlotWindow.cpp
new file mode 100644
index 0000000..5738b0c
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainPlotWindow.cpp
@@ -0,0 +1,218 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QMenu>
+#include <QMessageBox>
+#include <qwt/qwt_legend.h>
+
+#include "OpenMeca/Gui/MainPlotWindow.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+
+    MainPlotWindow* MainPlotWindow::me_ = 0;
+
+    MainPlotWindow& 
+    MainPlotWindow::Get()
+    {
+      OMC_ASSERT_MSG(me_!=0, "The singleton pointer is null");
+      return *me_;
+    }
+
+    MainPlotWindow::MainPlotWindow(QWidget * parent)
+      :QMainWindow(parent),
+       time_(Core::SystemSettingT<Setting::Simulation>::Get().GetTimeArray()),
+       data_(),
+       currentUnitPtr_(0)
+    {
+      OMC_ASSERT_MSG(me_ == 0, "The singleton pointer is not null");
+      setupUi(this);
+      me_ = this;
+
+      // pop-up menu when right-click
+      plot_->setContextMenuPolicy(Qt::CustomContextMenu);
+
+      // legend
+      QwtLegend *legend = new QwtLegend;
+      legend->setFrameStyle(QFrame::Box|QFrame::Sunken);
+      plot_->insertLegend(legend, QwtPlot::BottomLegend);
+      
+      // axis
+      plot_->setAxisTitle(QwtPlot::xBottom, "Time (s)");
+      
+
+      // Signal & slots
+      Setting::Simulation* simu = &Core::SystemSettingT<Setting::Simulation>::Get();
+      QObject::connect(actionClear_, SIGNAL(triggered()), this, SLOT(Clear()));
+      QObject::connect(simu, SIGNAL(StepChanged(OpenMeca::Setting::Simulation::Step)), 
+		       this, SLOT(Update(OpenMeca::Setting::Simulation::Step)));
+      QObject::connect(plot_, SIGNAL(customContextMenuRequested(const QPoint &)), 
+		       this, SLOT(PopUpMenu(const QPoint &)));
+    }
+    
+    MainPlotWindow::~MainPlotWindow()
+    {
+    }
+    
+    bool
+    MainPlotWindow::SetUnit(const Util::Unit& unit)
+    {
+      if (currentUnitPtr_ == 0)
+	{
+	  currentUnitPtr_ = &unit;
+	  QString ylabel = unit.GetDimension().GetName().c_str();
+	  ylabel += " (" + QString(unit.GetSymbol().c_str()) + " )";
+	  plot_->setAxisTitle(QwtPlot::yLeft, ylabel);
+	  return true;
+	}
+      else if (currentUnitPtr_ != &unit)
+	{
+	  const std::string msg = "You want to add a data with a different unit from the current displayed data on the graph. Are you sure ?";
+
+	  int ret = QMessageBox::warning(this, tr("openmeca (plot)"),
+					 tr(msg.c_str()),
+					 QMessageBox::YesRole|QMessageBox::NoRole,
+					 QMessageBox::NoRole);
+	  if (ret==QMessageBox::NoRole)
+	    {
+	      plot_->setAxisTitle(QwtPlot::yLeft, "?");
+	      return true;
+	    }
+	  return false;
+	}
+      return true;
+    }
+
+    void
+    MainPlotWindow::showEvent(QShowEvent * event)
+    {
+      QMainWindow::showEvent(event);
+      UpdateDataMenu(menuAdd_);
+    }
+
+    void MainPlotWindow::Update(OpenMeca::Setting::Simulation::Step)
+    {
+      if (isHidden()==true)
+	return;
+      
+      std::map<QwtPlotCurve*, const std::vector<double>*>::iterator it;
+      for (it=data_.begin(); it!=data_.end(); ++it)
+	{
+	  QwtPlotCurve* curve =it->first;
+	  const std::vector<double>& data = *it->second;
+	  SetSample(data, curve);
+	}
+      plot_->replot();
+    }
+
+    void
+    MainPlotWindow::UpdateDataMenu(QMenu *menu)
+    {
+      menu->clear();
+
+      Core::SetOfBase<Item::Physical>& physicals = 
+	Core::System::Get().GetSetOf<Item::Physical>();
+      
+      for (unsigned int i = 0; i < physicals.GetTotItemNumber(); ++i)
+	{
+	  Item::Physical& phys = physicals(i);
+	  const QString title = phys.GetName().c_str();
+	  const QIcon icon = phys.GetIcon();
+	  QMenu* submenu = menu->addMenu(icon, title); 
+	  phys.FillDataMenu(submenu);
+	}
+
+    }
+
+    void
+    MainPlotWindow::AddData(const std::vector<double>& data, 
+			    const QString& label, 
+			    const Util::Unit& unit,
+			    const Physic::Type& type)
+    {
+      if (SetUnit(unit))
+	{
+	  QwtPlotCurve* curve = new QwtPlotCurve(label); 
+	  SetSample(data, curve);
+	  curve->attach(plot_);
+	  curve->setPen(* new QPen(Util::Color().GetQColor(),2, Qt::SolidLine));    
+	  plot_->replot();
+	  OMC_ASSERT_MSG(data_.count(curve) == 0, "The curve is already registered");
+	  data_[curve] = &data;
+	}
+      recordedType_.push_back(&type);
+    }
+
+    void
+    MainPlotWindow::Clear()
+    {
+      plot_->detachItems();
+      recordedType_.clear();
+      data_.clear();
+      plot_->setAxisTitle(QwtPlot::yLeft, "");
+      currentUnitPtr_ = 0;
+      plot_->replot();
+    }
+
+    void MainPlotWindow::PopUpMenu(const QPoint &pos) 
+    {
+      UpdateDataMenu(menuAdd_);
+      menuPlot_->exec(plot_->mapToGlobal(pos));
+    }
+    
+    
+    void MainPlotWindow::DataDeleted(const Physic::Type& type)
+    {
+      for (unsigned int i = 0; i < recordedType_.size(); ++i)
+	{
+	  if (recordedType_[i] == &type)
+	    {
+	      if (isVisible())
+		{
+		  const QString msg = QObject::tr("One of the data seems to be deleted, the plot will be cleared");
+		  OMC_WARNING_MSG(msg);
+		}
+	      Clear();
+	    }
+	}
+    }
+
+    void MainPlotWindow::SetSample(const std::vector<double>& data, 
+				   QwtPlotCurve* curve)
+    {
+
+      // OMC_ASSERT_MSG(data.size() == time_.size() || data.size() + 1 == time_.size(),
+      // 		     "The number of data point is incoherent");
+
+      int datasize = data.size();
+      if (datasize > int(time_.size()))
+	datasize =  time_.size();
+
+      curve->setSamples(&time_[0], &data[0], datasize);
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/MainPlotWindow.hpp b/SRC/OpenMeca/Gui/MainPlotWindow.hpp
new file mode 100644
index 0000000..3d89326
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainPlotWindow.hpp
@@ -0,0 +1,74 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_MainPlotWindow_hpp
+#define OpenMeca_Gui_MainPlotWindow_hpp
+
+#include <QMainWindow>
+#include <qwt/qwt_plot.h>
+#include <qwt/qwt_plot_curve.h>
+
+#include "ui_MainPlotWindow.h"
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Physic/Type.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class MainPlotWindow : public QMainWindow, 
+		           private Ui::MainPlotWindow
+    {
+      Q_OBJECT
+    public:
+      static MainPlotWindow& Get();
+
+      MainPlotWindow(QWidget * parent=0);
+      virtual ~MainPlotWindow();
+      
+      void AddData(const std::vector<double>&, const QString& label, const Util::Unit&, const Physic::Type&);
+      void DataDeleted(const Physic::Type&);												    
+
+      
+    private slots:
+      void Clear();
+      void Update(OpenMeca::Setting::Simulation::Step);
+      void PopUpMenu(const QPoint &);
+
+    private:
+      bool SetUnit(const Util::Unit&);
+      void SetSample(const std::vector<double>&, QwtPlotCurve* );
+      void UpdateDataMenu(QMenu *menu);
+      void showEvent(QShowEvent * event);
+      
+    private:
+      static MainPlotWindow* me_;
+      const std::vector<double>& time_;
+      std::map<QwtPlotCurve*, const std::vector<double>*> data_;
+      std::vector<const Physic::Type*> recordedType_;
+      const Util::Unit* currentUnitPtr_;
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/MainPlotWindow.ui b/SRC/OpenMeca/Gui/MainPlotWindow.ui
new file mode 100644
index 0000000..c2ba2b0
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainPlotWindow.ui
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>MainPlotWindow</class>
+ <widget class="QMainWindow" name="MainPlotWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>800</width>
+    <height>600</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>openmeca (plot)</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout">
+    <item row="0" column="0">
+     <widget class="QwtPlot" name="plot_"/>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar_">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>800</width>
+     <height>20</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuPlot_">
+    <property name="title">
+     <string>Plot</string>
+    </property>
+    <widget class="QMenu" name="menuAdd_">
+     <property name="title">
+      <string>Add data</string>
+     </property>
+    </widget>
+    <addaction name="actionClear_"/>
+    <addaction name="menuAdd_"/>
+   </widget>
+   <addaction name="menuPlot_"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="actionClear_">
+   <property name="text">
+    <string>Clear</string>
+   </property>
+  </action>
+  <action name="actionSdqs">
+   <property name="text">
+    <string>sdqs</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>QwtPlot</class>
+   <extends>QFrame</extends>
+   <header>qwt/qwt_plot.h</header>
+  </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/MainTreeItem.cpp b/SRC/OpenMeca/Gui/MainTreeItem.cpp
new file mode 100644
index 0000000..b23cf92
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainTreeItem.cpp
@@ -0,0 +1,53 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/MainTreeItem.hpp"
+#include "OpenMeca/Gui/TreeView.hpp"
+#include "OpenMeca/Core/Item.hpp"
+
+namespace OpenMeca
+{
+  
+  namespace Gui
+  {
+
+
+    MainTreeItem::MainTreeItem(QTreeWidgetItem& parent, Core::Item& item)
+      :AbstractTreeItem(&parent),
+       item_(item)
+    {
+      Update();
+    }
+
+    MainTreeItem::~MainTreeItem()
+    {
+      if (IsRelatedItemIsDeleted() == false)
+	GetItem().MainTreeItemIsDeleted();
+    }
+
+  
+    Core::Item& 
+    MainTreeItem::GetItem()
+    {
+      return item_;
+    }
+  }
+
+}
diff --git a/SRC/OpenMeca/Gui/MainTreeItem.hpp b/SRC/OpenMeca/Gui/MainTreeItem.hpp
new file mode 100644
index 0000000..562c543
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainTreeItem.hpp
@@ -0,0 +1,60 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_MainTreeItem_hpp
+#define OpenMeca_Gui_MainTreeItem_hpp
+
+#include "OpenMeca/Gui/AbstractTreeItem.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    class Item;
+  }
+  
+
+  namespace Gui
+  {
+
+    class TreeView;
+    
+    class MainTreeItem : public AbstractTreeItem
+    {
+    
+    public:
+      MainTreeItem(QTreeWidgetItem& parent, Core::Item& item);
+      ~MainTreeItem();
+
+      Core::Item& GetItem();
+    
+    private:
+      MainTreeItem();                        //Not allowed
+      MainTreeItem(const MainTreeItem&);             //Not Allowed
+      MainTreeItem& operator=(const MainTreeItem&);  //Not Allowed
+
+    private:
+      Core::Item& item_;
+
+    };
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/MainWindow.cpp b/SRC/OpenMeca/Gui/MainWindow.cpp
new file mode 100755
index 0000000..8bf3cb9
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainWindow.cpp
@@ -0,0 +1,727 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QCloseEvent>
+#include <QBuffer>
+#include <QHelpEngine>
+#include <QHelpContentWidget>
+#include <QHelpIndexWidget>
+#include <QDockWidget>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/HelpBrowser.hpp"
+#include "OpenMeca/Gui/Dialog/Dialog.hpp"
+#include "OpenMeca/Gui/ExampleAction.hpp"
+#include "OpenMeca/Core/CommonProperty.hpp"
+#include "OpenMeca/Core/UserRootItemCommonProperty.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/ConfigFile.hpp"
+#include "OpenMeca/Core/Software.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Item/Variable.hpp"
+
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/PartLinkT.hpp"
+#include "OpenMeca/Item/Link/All.hpp"
+
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Item/PartUserPoint.hpp"
+#include "OpenMeca/Item/PartUserPipe.hpp"
+#include "OpenMeca/Item/PartUserJunction.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+#include "OpenMeca/Item/Shape/Sphere.hpp"
+#include "OpenMeca/Item/Shape/Box.hpp"
+#include "OpenMeca/Item/Shape/Cylinder.hpp"
+#include "OpenMeca/Item/Shape/Ground.hpp"
+
+#include "OpenMeca/Item/How/GetLinPos.hpp"
+#include "OpenMeca/Item/How/GetLinVel.hpp"
+#include "OpenMeca/Item/How/GetLinAcc.hpp"
+#include "OpenMeca/Item/How/GetAngPos.hpp"
+#include "OpenMeca/Item/How/GetAngVel.hpp"
+#include "OpenMeca/Item/How/GetAngAcc.hpp"
+#include "OpenMeca/Item/How/GetReacForce.hpp"
+#include "OpenMeca/Item/How/GetReacTorque.hpp"
+#include "OpenMeca/Item/How/SetForce.hpp"
+#include "OpenMeca/Item/How/SetTorque.hpp"
+
+
+#include "OpenMeca/Setting/MenuManager.hpp"
+#include "OpenMeca/Setting/UnitManager.hpp"
+#include "OpenMeca/Core/GlobalSettingCommonProperty.hpp"
+
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Setting/Scales.hpp"
+#include "OpenMeca/Setting/Gravity.hpp"
+#include "OpenMeca/Setting/Scene.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+
+    
+    MainWindow* MainWindow::me_ = 0;
+
+    MainWindow& 
+    MainWindow::Get()
+    {
+      OMC_ASSERT_MSG(me_!=0, "The singleton pointer is null");
+      return *me_;
+    }
+
+    bool
+    MainWindow::Exist()
+    {
+      return (me_ != 0);
+    }
+
+
+    MainWindow::MainWindow(std::string openFileName)
+      :QMainWindow(0),
+       init_(true),
+       openFileNameQueryAtStart_(openFileName),
+       iconSize_(24),
+       icon_(),
+       currentDialog_(0),
+       userActions_(),
+       currentFileName_(),
+       widgetScales_(0),
+       plot_(0),
+       helpWindow_(0),
+       setting_(0),
+       exampleToLoad_("")
+    {
+      OMC_ASSERT_MSG(iconSize_ > 0, "The icon size must be higher than zero");
+      OMC_ASSERT_MSG(me_==0, "The singleton pointer must be null");
+      me_ = this;
+      setupUi(this);
+      icon_ = Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Mini-Logo.svg");
+      setWindowIcon(icon_);
+      BuildHelpWindow();
+      treeView_->setIconSize(QSize(iconSize_,iconSize_));
+      treeView_->setAutoScrollMargin(iconSize_);
+      treeView_->headerItem()->setText(0, tr("Mechanical System"));
+
+      // The system setting must be placed at first
+      Setting::Scales::Init();
+      Setting::Gravity::Init();
+      Setting::Simulation::Init();
+      // Note that the Scene::Init() has moved in the showEvent because of a qt bug
+
+
+      // Init widget
+      widgetScales_ = new WidgetScales(this),
+      plot_         = new MainPlotWindow(this);
+      toolBar_->addWidget(widgetScales_);
+      setting_ = new GeneralSetting(this);
+
+      // Instanciate user root item
+      Core::Singleton<Core::UserRootItemCommonProperty<Item::Variable> >::Instanciate();      
+      Core::Singleton<Core::UserRootItemCommonProperty<Item::Body> >::Instanciate();
+      Core::Singleton<Core::UserRootItemCommonProperty<Item::Link> >::Instanciate();
+
+      // Init variable
+      Item::Variable::Init();
+
+     
+
+      // And after the item
+      Item::PartUserJunction::Init();
+      Item::PartUserPipe::Init();
+      Item::PartPoint::Init();
+      Item::PartUserPoint::Init();
+      Item::PartUserShapeT<Item::Shape::Sphere>::Init();
+      Item::PartUserShapeT<Item::Shape::Box>::Init();
+      Item::PartUserShapeT<Item::Shape::Cylinder>::Init();
+      Item::PartUserShapeT<Item::Shape::Ground>::Init();
+      
+      Item::Body::Init();
+      Item::Link::Init();
+      
+
+      Item::LinkT<Item::Revolute>::Init();
+      Item::PartLinkT<Item::Revolute,1>::Init();
+      Item::PartLinkT<Item::Revolute,2>::Init();
+
+      Item::LinkT<Item::Motor>::Init();
+      Item::PartLinkT<Item::Motor,1>::Init();
+      Item::PartLinkT<Item::Motor,2>::Init();
+
+      Item::LinkT<Item::LinearMotor>::Init();
+      Item::PartLinkT<Item::LinearMotor,1>::Init();
+      Item::PartLinkT<Item::LinearMotor,2>::Init();
+
+      Item::LinkT<Item::Slider>::Init();
+      Item::PartLinkT<Item::Slider,1>::Init();
+      Item::PartLinkT<Item::Slider,2>::Init();
+
+      Item::LinkT<Item::Cylindrical>::Init();
+      Item::PartLinkT<Item::Cylindrical,1>::Init();
+      Item::PartLinkT<Item::Cylindrical,2>::Init();
+
+      Item::LinkT<Item::Planar>::Init();
+      Item::PartLinkT<Item::Planar,1>::Init();
+      Item::PartLinkT<Item::Planar,2>::Init();
+
+      Item::LinkT<Item::PointLine>::Init();
+      Item::PartLinkT<Item::PointLine,1>::Init();
+      Item::PartLinkT<Item::PointLine,2>::Init();
+
+      Item::LinkT<Item::PointPlane>::Init();
+      Item::PartLinkT<Item::PointPlane,1>::Init();
+      Item::PartLinkT<Item::PointPlane,2>::Init();
+
+      Item::LinkT<Item::Spherical>::Init();
+      Item::PartLinkT<Item::Spherical,1>::Init();
+      Item::PartLinkT<Item::Spherical,2>::Init();
+
+      Item::LinkT<Item::Screw>::Init();
+      Item::PartLinkT<Item::Screw,1>::Init();
+      Item::PartLinkT<Item::Screw,2>::Init();
+
+      Item::LinkT<Item::Gear>::Init();
+      Item::PartLinkT<Item::Gear,1>::Init();
+      Item::PartLinkT<Item::Gear,2>::Init();
+
+      Item::LinkT<Item::Pulley>::Init();
+      Item::PartLinkT<Item::Pulley,1>::Init();
+      Item::PartLinkT<Item::Pulley,2>::Init();
+
+      Item::LinkT<Item::RackPinion>::Init();
+      Item::PartLinkT<Item::RackPinion,1>::Init();
+      Item::PartLinkT<Item::RackPinion,2>::Init();
+
+      Item::LinkT<Item::Spring>::Init();
+      Item::PartLinkT<Item::Spring,1>::Init();
+      Item::PartLinkT<Item::Spring,2>::Init();
+
+
+      Item::How::GetLinPos::MySensor::Init();
+      Item::How::GetLinVel::MySensor::Init();
+      Item::How::GetLinAcc::MySensor::Init();
+      Item::How::GetAngPos::MySensor::Init();     
+      Item::How::GetAngVel::MySensor::Init();     
+      Item::How::GetAngAcc::MySensor::Init();     
+      Item::How::GetReacForce::MySensor::Init();     
+      Item::How::GetReacTorque::MySensor::Init();     
+      Item::How::SetForce::MyLoad::Init();
+      Item::How::SetTorque::MyLoad::Init();
+
+      
+
+      //Init the globalsetting (Always at the end)
+      Setting::MenuManager::Init();
+      Setting::UnitManager::Init();
+
+      // Get some action defined in the "MenuManager.xml" file
+      Setting::MenuManager& menuManager = Core::Singleton<Setting::MenuManager>::Get();
+      QAction* actionShowData    =  menuManager.GetQAction("ShowData");
+      QAction* actionSaveData    =  menuManager.GetQAction("SaveData");
+      QAction* actionAbout       =  menuManager.GetQAction("About");
+      QAction* actionHelp        =  menuManager.GetQAction("Help");
+      QAction* actionHelpViewer  =  menuManager.GetQAction("HelpViewer");
+
+      QObject::connect(actionNew, SIGNAL(triggered()), this, SLOT(New()));
+      QObject::connect(actionUndo, SIGNAL(triggered()), this, SLOT(Undo()));
+      QObject::connect(actionRedo, SIGNAL(triggered()), this, SLOT(Redo()));
+      QObject::connect(actionSaveAs, SIGNAL(triggered()), this, SLOT(SaveAs()));
+      QObject::connect(actionSave, SIGNAL(triggered()), this, SLOT(Save()));
+      QObject::connect(actionLoad, SIGNAL(triggered()), this, SLOT(Load()));
+      QObject::connect(actionQuit, SIGNAL(triggered()), this, SLOT(close()));
+      QObject::connect(actionSettings, SIGNAL(triggered()), this, SLOT(ShowSetting()));
+      QObject::connect(actionShowData, SIGNAL(triggered()), this, SLOT(ShowData()));
+      QObject::connect(actionSaveData, SIGNAL(triggered()), this, SLOT(SaveData()));
+      QObject::connect(actionAbout, SIGNAL(triggered()), this, SLOT(ShowAbout()));
+      QObject::connect(actionHelp, SIGNAL(triggered()), this, SLOT(ShowHelp()));
+      QObject::connect(actionHelpViewer, SIGNAL(triggered()), viewer_, SLOT(help()));
+
+      
+      UpdateHistoric();
+      BuildExampleMenu();
+      
+      Core::System::Get().Update();
+      
+      //Begin a system sample
+      // Item::Body& b1 = *new Item::Body();
+      // Item::Body& b2 = *new Item::Body();
+      // b2.ToggleFix();
+      // new Item::LinkT<Item::Motor>(b1, b2);
+
+    }
+  
+    MainWindow::~MainWindow()
+    {
+      Core::System::Quit();
+      me_ = 0;   
+      delete viewer_;
+      delete treeView_;
+    }
+
+
+    TreeView& 
+    MainWindow::GetTreeView()
+    {
+      return *treeView_;
+    }
+
+    const TreeView& 
+    MainWindow::GetTreeView() const
+    {
+      return *treeView_;
+    }
+
+    Viewer& 
+    MainWindow::GetViewer()
+    {
+      return *viewer_;
+    }
+
+    const Viewer& 
+    MainWindow::GetViewer() const
+    {
+      return *viewer_;
+    }
+
+
+
+    int
+    MainWindow::GetIconSize()
+    {
+      return iconSize_;
+    }
+
+
+    void
+    MainWindow::AddGlobalSetting(Core::GlobalSetting& globalSetting)
+    {
+      globalSet_.AddItem(globalSetting);
+    }
+    
+    void
+    MainWindow::RemoveGlobalSetting(Core::GlobalSetting& globalSetting)
+    {
+      globalSet_.RemoveItem(globalSetting);
+    }
+
+    bool
+    MainWindow::CloseDialog(bool allowCancellation)
+    {
+      if (currentDialog_==0)
+	return true;
+      else 
+	{
+	  if (!currentDialog_->IsPossibleToClose())
+	    return false;
+	  
+	  if (currentDialog_->Check())
+	    {
+	      currentDialog_->Ok();
+	      toolBox_->removeItem(1);
+	      OMC_ASSERT_MSG(currentDialog_ ==0, "The current dialog must be set to zero");
+	      return true;
+	    }
+	  else if (allowCancellation)
+	    {
+	      currentDialog_->Cancel();
+	      toolBox_->removeItem (1);
+	      OMC_ASSERT_MSG(currentDialog_ ==0, "The current dialog must be set to zero");
+	      return true;
+	    }
+	}
+      return false;
+    }
+
+    void
+    MainWindow::DialogContainerIsBusy(Dialog& dial)
+    {
+      if (currentDialog_!=0)
+	{
+	  if (currentDialog_->Check())
+	    currentDialog_->Ok();
+	  else
+	    currentDialog_->Cancel();
+	  
+	  toolBox_->removeItem (1);
+	}
+      OMC_ASSERT_MSG(currentDialog_ ==0, "The current dialog must be set to zero");
+      currentDialog_ = &dial;
+    }
+
+    void
+    MainWindow::DialogContainerIsFree(Dialog& dial)
+    {
+      OMC_ASSERT_MSG(currentDialog_ == &dial, "The current dialog must be equal the dial");
+      currentDialog_ = 0;
+      toolBox_->removeItem (1);
+      toolBox_->setCurrentIndex(0);
+    }
+
+    QToolBox&
+    MainWindow::GetDialogContainer()
+    {
+      return *toolBox_;
+    }
+
+    void
+    MainWindow::AddToHistoric(QAction& action)
+    {
+      userActions_.push_back(&action);
+      UpdateHistoric();
+    }
+
+    void 
+    MainWindow::Undo()
+    {
+      Core::System::Get().GetHistoric().LoadPreviousState();
+      UpdateHistoric();
+    }
+
+    void 
+    MainWindow::Redo()
+    {
+      Core::System::Get().GetHistoric().LoadNextState();
+      UpdateHistoric();
+    }
+
+    
+    void 
+    MainWindow::UpdateHistoric()
+    {
+      const bool undo = Core::System::Get().GetHistoric().IsUndoPossible();
+      const bool redo = Core::System::Get().GetHistoric().IsRedoPossible();
+      actionUndo->setEnabled(undo);
+      actionRedo->setEnabled(redo);
+    }
+
+    
+    void 
+    MainWindow::SaveAs()
+    {
+      if (CloseDialog(true))
+	{
+	  
+	  //the qt QFileDialog::getSaveFileName static method don't manage suffix
+	  //it's boring
+	  QFileDialog fileDialog(this, tr("Save As"));
+	  fileDialog.setFilter (QDir::Files);
+	  fileDialog.setDefaultSuffix ("omc");
+	  fileDialog.setFileMode(QFileDialog::AnyFile);
+	  fileDialog.setAcceptMode(QFileDialog::AcceptSave);
+	  QString fileName;
+	  if (fileDialog.exec()) 
+	    { 
+	      QStringList fileNames = fileDialog.selectedFiles(); 
+	      if ( fileNames.count() ) 
+		fileName = fileNames.at(0); 
+	}
+	  
+	  
+	  if (!fileName.isEmpty())
+	    {
+	      OMC_ASSERT_MSG(fileName.endsWith(".omc"), "The .omc extension must be respected");
+	      currentFileName_ = fileName.toStdString();
+	      Save();
+	    }
+	}
+    }
+
+    
+    void 
+    MainWindow::New()
+    {
+      if (CloseDialog(true))
+	{
+	  if (Core::System::Get().IsEdited())
+	    {
+	      const QString msg = tr("The current action will clear your system, do you want to continue ?");
+	      
+	      QMessageBox mBox(QMessageBox::Question, tr("Are you sure ?"), 
+			       msg, QMessageBox::Yes|QMessageBox::No);
+	      if (QMessageBox::No == mBox.exec()) 
+		return;
+	    }
+	  Core::System::Get().Reset();
+	}
+    }
+
+    void 
+    MainWindow::Save()
+    {
+      if (CloseDialog(true))
+	{
+	  
+	  if (currentFileName_.empty())
+	    {
+	      SaveAs();
+	      return;
+	    }
+	  QString qfileNameStr = currentFileName_.c_str();
+	  OMC_ASSERT_MSG(qfileNameStr.endsWith(".omc"), "The .omc extension must be respected");
+	  Core::System::Get().SaveFile(currentFileName_);
+	}
+    }
+    
+    
+    void 
+    MainWindow::Load()
+    {
+      if (CloseDialog(true))
+	{
+	  
+	  //Todo check if system is edited
+	  QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),"", tr("OpenMeca Files (*.omc)"));
+	  if (!fileName.isEmpty())
+	    {
+	      currentFileName_ = fileName.toStdString();
+	      Core::System::Get().LoadFile(currentFileName_);
+	      UpdateHistoric();
+	    }
+	}
+    }
+
+    void 
+    MainWindow::showEvent(QShowEvent* event ) 
+    {
+      QWidget::showEvent(event);
+      if (init_)
+	{
+	  // This is a trick because if the Update() method 
+	  // is called in the constructor it bugs.
+	  // This is a Qt problem, not an openmeca problem.
+	  Setting::Scene::Init();
+	  Core::SystemSettingT<Setting::Scene>::Get().Update();
+	  init_ = false;
+	  if (openFileNameQueryAtStart_ != "")
+	    {
+	      Core::System::Get().LoadFile(openFileNameQueryAtStart_);
+	      openFileNameQueryAtStart_ = "";
+	    }
+	}
+    }
+    
+
+
+    void 
+    MainWindow::closeEvent(QCloseEvent* event)
+    {
+      Core::SystemSettingT<Setting::Simulation>::Get().Stop();
+      Core::SystemSettingT<Setting::Simulation>::Get().wait();
+      
+      if (!CloseDialog(true))
+	{
+	  event->ignore();
+	  return;
+	}
+	  
+		       
+      if (Core::System::Get().IsEdited())
+	{
+	  QMessageBox msgBox;
+	  msgBox.setText(tr("The document has been modified."));
+	  msgBox.setInformativeText(tr("Do you want to save your changes?"));
+	  msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
+	  msgBox.setDefaultButton(QMessageBox::Save);
+	  int ret = msgBox.exec();
+	  switch (ret) 
+	  {
+	  case QMessageBox::Save:
+	    event->accept();
+	    Save();
+	    break;
+	  case QMessageBox::Discard:
+	    event->accept();
+	    break;
+	  case QMessageBox::Cancel:
+	    event->ignore();
+	    return;
+	    break;
+	  default:
+	    OMC_ASSERT_MSG(0, "The default case is not allowed");
+	    break;
+	  }
+	}
+      Core::System::Get().Reset();
+      
+    }
+    
+    void 
+    MainWindow::ShowData()
+    {
+      plot_->show(); 
+    }    
+
+    void 
+    MainWindow::SaveData()
+    {
+      //the qt QFileDialog::getSaveFileName static method don't manage suffix
+      //it's boring
+      QFileDialog fileDialog(this, tr("Save data as"));
+      fileDialog.setFilter(QDir::Files);
+      fileDialog.setDefaultSuffix ("txt");
+      fileDialog.setFileMode(QFileDialog::AnyFile);
+      fileDialog.setAcceptMode(QFileDialog::AcceptSave);
+      QString fileName;
+      if (fileDialog.exec()) 
+	{ 
+	  QStringList fileNames = fileDialog.selectedFiles(); 
+	  if ( fileNames.count() ) 
+	    fileName = fileNames.at(0); 
+	}
+
+      
+      if (!fileName.isEmpty())
+	{
+	  OMC_ASSERT_MSG(fileName.endsWith(".txt"), "The .txt extension must be respected");
+	  Item::Physical::DumpAllDataToFile(fileName.toStdString());
+	}
+    }
+
+    void 
+    MainWindow::ShowAbout()
+    {
+      const QString version = QString::number(Core::System::Version,'f', 1);
+      QByteArray byteArray;
+      QBuffer buffer(&byteArray);
+      QPixmap pixmap(":/Rsc/Img/Logo.png");
+      pixmap.save(&buffer, "PNG");
+      QString img = QString("<p align=\"center\"> <img src=\"data:image/png;base64,");
+      img += byteArray.toBase64() + "\"/> </p>";
+
+      QString text;
+      text += "<h2>" + tr("Welcome to openmeca !") + "</h2>";
+      text += tr("Openmeca is an easy to use software that helps you to build mechanical systems and simulate it");
+      text += "<br>";
+      text += img;
+      text += tr("OpenMeca is distributed under the free GPL v3 license");
+      text += "<br>";
+      text += tr("It means that you are free to use and to distribute it !");
+      text += "<br><br>";
+
+      text += "<b>" + tr("Acknowledgement") + "</b>";
+      text += "<br>";
+      text += "openmeca is directly based on the <a href=\"http://chronoengine.info\">ChronoEngine library</a>, the <a href=\"http://www.boost.org\">Boost library</a>, the <a href=\"http://qwt.sf.net\">Qwt library</a>, the <a href=\"http://libqglviewer.com\">QGLViewer library</a> and a lot of others. Many thanks to their authors !"; 
+      text += "<br><br>";
+
+      
+      text += "<b>" + tr("Main informations") + "</b>";
+      text += Core::Software::Get().HtmlText();
+	
+
+      QMessageBox::about(this, tr("About openmeca"), text);
+      
+    }
+
+    void 
+    MainWindow::ShowHelp()
+    {
+      OMC_ASSERT_MSG(helpWindow_ != 0, "The help window pointer must not be null");
+      helpWindow_->show();
+    }
+    
+    void 
+    MainWindow::BuildHelpWindow()
+    {
+      // use config file to ensure that the files exist in the config file dir
+      // use RestoreBackup() to force their update
+      Core::ConfigFile qhc_file("Help.qhc", "Help");
+      qhc_file.RestoreBackup();
+      qhc_file.Open(); 
+
+      Core::ConfigFile qch_file("Help.qch", "Help");
+      qch_file.RestoreBackup();
+      qch_file.Open();
+
+      QHelpEngine* helpEngine = new QHelpEngine(qhc_file.GetAbsPath());
+      
+      helpEngine->setupData();
+      
+      QTabWidget* tWidget = new QTabWidget;
+      tWidget->setMaximumWidth(200);
+      tWidget->addTab(helpEngine->contentWidget(), "Contents");
+      tWidget->addTab(helpEngine->indexWidget(), "Index");
+      
+      HelpBrowser *textViewer = new HelpBrowser(helpEngine);
+      textViewer->setSource(QUrl("qthelp://OpenMeca/Help/Help.html"));
+      QObject::connect(helpEngine->contentWidget(),  SIGNAL(linkActivated(QUrl)),
+		       textViewer, SLOT(setSource(QUrl)));
+      
+      QObject::connect(helpEngine->indexWidget(), SIGNAL(linkActivated(QUrl, QString)), 
+		       textViewer, SLOT(setSource(QUrl)));
+      
+      QSplitter *horizSplitter = new QSplitter(Qt::Horizontal);
+      horizSplitter->insertWidget(0, tWidget);
+      horizSplitter->insertWidget(1, textViewer);
+      horizSplitter->hide();
+      
+      helpWindow_ = new QDockWidget(tr("Help"), this);
+      helpWindow_->setWidget(horizSplitter);
+      helpWindow_->hide();
+      addDockWidget(Qt::TopDockWidgetArea, helpWindow_);
+    }
+
+    void 
+    MainWindow::BuildExampleMenu()
+    {
+      QStringList list = QDir(":/Rsc/Example/").entryList(QDir::Files);
+      for (int i = 0; i < list.size(); ++i)
+	{
+	  QAction* action = new ExampleAction(list[i], menuExample);
+	  menuExample->addAction(action);
+	}
+      
+    }
+
+    void 
+    MainWindow::LoadExample()
+    {
+      
+    }
+
+    
+    
+    void 
+    MainWindow::ShowSetting()
+    {
+      setting_->show();
+    }
+
+
+    const QIcon& 
+    MainWindow::GetIcon() const
+     {
+       return icon_;
+      }		 
+  
+
+
+
+  }
+}
+
+
+
diff --git a/SRC/OpenMeca/Gui/MainWindow.hpp b/SRC/OpenMeca/Gui/MainWindow.hpp
new file mode 100755
index 0000000..bc87873
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainWindow.hpp
@@ -0,0 +1,114 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_MainWindow_hpp
+#define OpenMeca_Gui_MainWindow_hpp
+
+#include <QMainWindow>
+#include <qwt/qwt_plot.h>
+
+#include "ui_MainWindow.h"
+#include "OpenMeca/Core/GlobalSetting.hpp"
+#include "OpenMeca/Gui/Widget/WidgetScales.hpp"
+#include "OpenMeca/Gui/MainPlotWindow.hpp"
+#include "OpenMeca/Gui/GeneralSetting.hpp"
+#include "OpenMeca/Util/Version.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class Dialog;
+
+    class MainWindow : public QMainWindow, 
+		       private Ui::MainWindow
+    {
+      Q_OBJECT
+      
+      public:
+      static MainWindow& Get();
+      static bool Exist();
+
+      MainWindow(std::string openFileName);
+      ~MainWindow();
+      
+      TreeView& GetTreeView();
+      const TreeView& GetTreeView() const;
+
+      Viewer& GetViewer();
+      const Viewer& GetViewer() const;
+      
+      bool CloseDialog(bool allowCancellation);
+      void AddGlobalSetting(Core::GlobalSetting&);
+      void RemoveGlobalSetting(Core::GlobalSetting&);
+      QToolBox& GetDialogContainer();
+      void DialogContainerIsBusy(Dialog&);
+      void DialogContainerIsFree(Dialog&);					 
+      void AddToHistoric(QAction&);
+      int GetIconSize();
+      const QIcon& GetIcon() const;
+      void BuildHelpWindow();
+      void BuildExampleMenu();
+
+    public slots:
+      void Undo();
+      void Redo();
+      void New();
+      void SaveAs();
+      void Save();
+      void Load();
+      void ShowData();
+      void SaveData();
+      void ShowAbout();
+      void ShowHelp();
+      void ShowSetting();
+      void LoadExample();
+
+
+    private:
+      void UpdateHistoric();
+      void closeEvent(QCloseEvent* event);
+      void showEvent(QShowEvent *ev);
+
+
+    private:
+      static MainWindow* me_;
+      bool init_;
+      std::string openFileNameQueryAtStart_;
+      const int iconSize_;
+      QIcon icon_;
+      Core::SetOf<Core::GlobalSetting> globalSet_;
+      Dialog* currentDialog_;
+      std::vector<QAction*> userActions_;
+      std::string currentFileName_;
+      WidgetScales* widgetScales_;
+      MainPlotWindow* plot_;
+      QDockWidget* helpWindow_;
+      GeneralSetting* setting_;
+      std::string exampleToLoad_;
+      // QBoxLayout *dialogContainerLayout_;
+
+
+      
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/MainWindow.ui b/SRC/OpenMeca/Gui/MainWindow.ui
new file mode 100755
index 0000000..beb9081
--- /dev/null
+++ b/SRC/OpenMeca/Gui/MainWindow.ui
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>911</width>
+    <height>631</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>openmeca</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../Resources.qrc">
+    <normaloff>:/Rsc/Img/Mini-Logo.svg</normaloff>:/Rsc/Img/Mini-Logo.svg</iconset>
+  </property>
+  <property name="toolButtonStyle">
+   <enum>Qt::ToolButtonTextBesideIcon</enum>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QGridLayout" name="gridLayout_3">
+    <item row="0" column="0">
+     <widget class="QSplitter" name="splitter">
+      <property name="orientation">
+       <enum>Qt::Horizontal</enum>
+      </property>
+      <widget class="OpenMeca::Gui::Viewer" name="viewer_" native="true">
+       <property name="sizePolicy">
+        <sizepolicy hsizetype="Maximum" vsizetype="Maximum">
+         <horstretch>0</horstretch>
+         <verstretch>0</verstretch>
+        </sizepolicy>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>16777215</width>
+         <height>16777215</height>
+        </size>
+       </property>
+      </widget>
+      <widget class="QToolBox" name="toolBox_">
+       <property name="currentIndex">
+        <number>0</number>
+       </property>
+       <widget class="QWidget" name="page">
+        <property name="geometry">
+         <rect>
+          <x>0</x>
+          <y>0</y>
+          <width>651</width>
+          <height>505</height>
+         </rect>
+        </property>
+        <attribute name="label">
+         <string>Global View</string>
+        </attribute>
+        <layout class="QGridLayout" name="gridLayout">
+         <item row="0" column="0">
+          <widget class="OpenMeca::Gui::TreeView" name="treeView_">
+           <property name="autoScrollMargin">
+            <number>32</number>
+           </property>
+           <property name="iconSize">
+            <size>
+             <width>32</width>
+             <height>32</height>
+            </size>
+           </property>
+           <column>
+            <property name="text">
+             <string>1</string>
+            </property>
+           </column>
+          </widget>
+         </item>
+        </layout>
+       </widget>
+      </widget>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>911</width>
+     <height>19</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <widget class="QMenu" name="menuExample">
+     <property name="title">
+      <string>Example</string>
+     </property>
+    </widget>
+    <addaction name="actionNew"/>
+    <addaction name="actionSave"/>
+    <addaction name="actionSaveAs"/>
+    <addaction name="actionLoad"/>
+    <addaction name="menuExample"/>
+    <addaction name="separator"/>
+    <addaction name="actionQuit"/>
+    <addaction name="separator"/>
+    <addaction name="actionSettings"/>
+   </widget>
+   <widget class="QMenu" name="menuEdit">
+    <property name="title">
+     <string>Edit</string>
+    </property>
+    <addaction name="actionUndo"/>
+    <addaction name="actionRedo"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menuEdit"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <widget class="QToolBar" name="toolBar_">
+   <property name="windowTitle">
+    <string>ToolBar</string>
+   </property>
+   <property name="toolButtonStyle">
+    <enum>Qt::ToolButtonIconOnly</enum>
+   </property>
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="separator"/>
+   <addaction name="actionUndo"/>
+   <addaction name="actionRedo"/>
+  </widget>
+  <action name="actionSave">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/Save.svg</normaloff>:/Rsc/Img/MainWindow/Save.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Save</string>
+   </property>
+  </action>
+  <action name="actionSaveAs">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/Save-as.svg</normaloff>:/Rsc/Img/MainWindow/Save-as.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Save as...</string>
+   </property>
+  </action>
+  <action name="actionLoad">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/Open.svg</normaloff>:/Rsc/Img/MainWindow/Open.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Open...</string>
+   </property>
+  </action>
+  <action name="actionUndo">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/Undo.svg</normaloff>:/Rsc/Img/MainWindow/Undo.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Undo</string>
+   </property>
+   <property name="iconVisibleInMenu">
+    <bool>true</bool>
+   </property>
+  </action>
+  <action name="actionRedo">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/Redo.svg</normaloff>:/Rsc/Img/MainWindow/Redo.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Redo</string>
+   </property>
+   <property name="iconVisibleInMenu">
+    <bool>true</bool>
+   </property>
+  </action>
+  <action name="actionQuit">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/Quit.svg</normaloff>:/Rsc/Img/MainWindow/Quit.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Quit...</string>
+   </property>
+  </action>
+  <action name="actionShowPlot">
+   <property name="text">
+    <string>Show...</string>
+   </property>
+  </action>
+  <action name="actionSettings">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/Preference.svg</normaloff>:/Rsc/Img/MainWindow/Preference.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Settings...</string>
+   </property>
+  </action>
+  <action name="actionNew">
+   <property name="icon">
+    <iconset resource="../Resources.qrc">
+     <normaloff>:/Rsc/Img/MainWindow/New.svg</normaloff>:/Rsc/Img/MainWindow/New.svg</iconset>
+   </property>
+   <property name="text">
+    <string>New system</string>
+   </property>
+  </action>
+  <action name="actionSdqs">
+   <property name="text">
+    <string>sdqs</string>
+   </property>
+  </action>
+ </widget>
+ <customwidgets>
+  <customwidget>
+   <class>OpenMeca::Gui::Viewer</class>
+   <extends>QWidget</extends>
+   <header>OpenMeca/Gui/Viewer.hpp</header>
+   <container>1</container>
+  </customwidget>
+  <customwidget>
+   <class>OpenMeca::Gui::TreeView</class>
+   <extends>QTreeWidget</extends>
+   <header>OpenMeca/Gui/TreeView.hpp</header>
+  </customwidget>
+ </customwidgets>
+ <resources>
+  <include location="../Resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Player.cpp b/SRC/OpenMeca/Gui/Player.cpp
new file mode 100644
index 0000000..1aa251c
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Player.cpp
@@ -0,0 +1,175 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QImageReader>
+#include <QFileDialog>
+
+#include "OpenMeca/Gui/Player.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/ImageDialog.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+
+    Player::Player(QWidget * parent)
+      :QWidget(parent),
+       timeLabelPrefix_(tr("Simulated time : ")),
+       iterLabelPrefix_(tr("Iteration number : ")),
+       step_()
+    {
+      
+      setupUi(this);
+      Setting::Simulation* simu = &Core::SystemSettingT<Setting::Simulation>::Get();
+      qRegisterMetaType<OpenMeca::Setting::Simulation::Step>("OpenMeca::Setting::Simulation::Step");
+
+      QObject::connect(compute_, SIGNAL(toggled(bool)),    this, SLOT(TogglePlay(bool)));
+      QObject::connect(stop_,    SIGNAL(clicked()),        this, SLOT(Stop()));
+      QObject::connect(slider_,  SIGNAL(sliderMoved(int)), this, SLOT(Move(int)));
+      QObject::connect(simu,     SIGNAL(End()),            this, SLOT(End()));
+      QObject::connect(record_,  SIGNAL(clicked())       , this, SLOT(Record()));
+
+      QObject::connect(simu, SIGNAL(StepChanged(OpenMeca::Setting::Simulation::Step)), 
+		       this, SLOT(Update(OpenMeca::Setting::Simulation::Step)));
+
+
+      QObject::connect(this, SIGNAL(MovedTo(unsigned int)), 
+		       simu, SLOT(GoToStep(unsigned int)));
+      step_.Init();
+      slider_->setMinimum(0);
+      UpdateWidget();
+    }
+    
+    Player::~Player()
+    {
+    }
+
+    void
+    Player::TogglePlay(bool play)
+    {
+      if (play)
+	Play();
+      else
+	Pause();
+    }
+    
+    void
+    Player::Stop()
+    {
+      // compute_->setChecked(false);
+      // Pause();
+      emit Stopped();
+      Core::SystemSettingT<Setting::Simulation>::Get().wait();
+      compute_->setChecked(false);
+    }
+
+    void
+    Player::Play()
+    {
+      OMC_ASSERT_MSG(compute_->isChecked() == true, "The compute button must be checked");
+      emit Played();
+    }
+
+    void
+    Player::Pause()
+    {
+      OMC_ASSERT_MSG(compute_->isChecked() == false, "The compute button must not be checked");
+      emit Paused();
+      Core::SystemSettingT<Setting::Simulation>::Get().wait();
+    }
+
+    void
+    Player::End()
+    {
+      compute_->setChecked(false);
+      Pause();
+    }
+
+
+  
+    void
+    Player::Update(OpenMeca::Setting::Simulation::Step step)
+    {
+      step_ = step;
+      UpdateWidget();
+    }
+
+    void
+    Player::UpdateWidget()
+    {
+      time_->setText(timeLabelPrefix_ + QString::number(step_.time) + " s");
+      iter_->setText(iterLabelPrefix_ + QString::number(step_.iterNumber) + " / " + QString::number(step_.totalIterNumber));
+      slider_->setMaximum(step_.totalIterNumber);
+      slider_->setSliderPosition(step_.iterNumber);    
+    }
+    
+    void
+    Player::Move(int pos)
+    {
+      compute_->setChecked(false);
+      const unsigned int iterNumber = pos; 
+      emit MovedTo(iterNumber);
+    }
+
+    
+    QStringList
+    Player::GetSupportedImageFormat() const
+    {
+      QList<QByteArray> formatList = QImageReader::supportedImageFormats();
+      QStringList strList;
+      for (int i = 0; i<formatList.size();++i)
+	strList.push_back(QString(formatList[i]));
+      
+      return strList;
+    }
+
+
+    void
+    Player::Record()
+    {
+      Pause();
+      Viewer& viewer = MainWindow::Get().GetViewer();
+      bool toggle = record_->isChecked();
+      if (toggle)
+	{
+	  int quality = 0;
+	  QString format = "";
+	  QStringList strList = GetSupportedImageFormat();
+	  ImageDialog dialog(this, GetSupportedImageFormat(), quality, format);
+	  if (dialog.exec())
+	    {
+	      viewer.setSnapshotFormat(format);
+	      viewer.setSnapshotQuality(quality);
+	      QString dir = QFileDialog::getExistingDirectory(this, tr("Save files in directory"),"", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+	      if (dir!="")
+		{
+		  viewer.SetSnapShotMode(true);
+		  viewer.setSnapshotFileName(dir+QDir::separator()+"save."+format);
+		  return;
+		}
+	    }
+	}
+      record_->setChecked(false);
+      viewer.SetSnapShotMode(false);
+    }
+    
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Player.hpp b/SRC/OpenMeca/Gui/Player.hpp
new file mode 100644
index 0000000..fe64f54
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Player.hpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Player_hpp
+#define OpenMeca_Gui_Player_hpp
+
+#include <QWidget>
+#include "ui_Player.h"
+#include "OpenMeca/Setting/Simulation.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+
+    class Player : public QWidget,
+		   private Ui::Player
+		   
+    {
+      Q_OBJECT
+      
+    public:
+      Player(QWidget * parent);
+      ~Player();
+      
+    signals:
+      void Stopped();
+      void Played();
+      void Paused();
+		   
+
+    public slots:
+      void TogglePlay(bool);
+      void Stop();
+      void Move(int);
+      void Pause();
+      void End();
+
+    public slots:
+      void Update(OpenMeca::Setting::Simulation::Step);
+      void Record();
+
+    signals:
+      void MovedTo(unsigned int);
+
+    private:
+      void Play();
+      QStringList GetSupportedImageFormat() const;
+      
+      void UpdateWidget();
+
+    private:
+      const QString timeLabelPrefix_;
+      const QString iterLabelPrefix_;
+      Setting::Simulation::Step step_;
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Player.ui b/SRC/OpenMeca/Gui/Player.ui
new file mode 100644
index 0000000..221a5a5
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Player.ui
@@ -0,0 +1,178 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>Player</class>
+ <widget class="QWidget" name="Player">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>471</width>
+    <height>106</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <property name="toolTip">
+   <string>Play/Pause</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="1" column="0">
+    <layout class="QHBoxLayout">
+     <item>
+      <widget class="QPushButton" name="compute_">
+       <property name="minimumSize">
+        <size>
+         <width>40</width>
+         <height>40</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>40</width>
+         <height>40</height>
+        </size>
+       </property>
+       <property name="whatsThis">
+        <string/>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="../Resources.qrc">
+         <normaloff>:/Rsc/Img/Player/Play.svg</normaloff>:/Rsc/Img/Player/Play.svg</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="stop_">
+       <property name="minimumSize">
+        <size>
+         <width>40</width>
+         <height>40</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>40</width>
+         <height>40</height>
+        </size>
+       </property>
+       <property name="toolTip">
+        <string>Stop and reset</string>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="../Resources.qrc">
+         <normaloff>:/Rsc/Img/Player/Stop.svg</normaloff>:/Rsc/Img/Player/Stop.svg</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="record_">
+       <property name="enabled">
+        <bool>true</bool>
+       </property>
+       <property name="minimumSize">
+        <size>
+         <width>40</width>
+         <height>40</height>
+        </size>
+       </property>
+       <property name="maximumSize">
+        <size>
+         <width>40</width>
+         <height>40</height>
+        </size>
+       </property>
+       <property name="toolTip">
+        <string>Record image</string>
+       </property>
+       <property name="text">
+        <string/>
+       </property>
+       <property name="icon">
+        <iconset resource="../Resources.qrc">
+         <normaloff>:/Rsc/Img/Player/Record.svg</normaloff>:/Rsc/Img/Player/Record.svg</iconset>
+       </property>
+       <property name="iconSize">
+        <size>
+         <width>32</width>
+         <height>32</height>
+        </size>
+       </property>
+       <property name="checkable">
+        <bool>true</bool>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QSlider" name="slider_">
+       <property name="toolTip">
+        <string>Current simulation step</string>
+       </property>
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item row="2" column="0">
+    <widget class="QLabel" name="iter_">
+     <property name="text">
+      <string>Iteration number : </string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="0">
+    <widget class="QLabel" name="time_">
+     <property name="text">
+      <string>Simulated time : </string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../Resources.qrc"/>
+ </resources>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Prop/Prop.cpp b/SRC/OpenMeca/Gui/Prop/Prop.cpp
new file mode 100644
index 0000000..716f0cc
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/Prop.cpp
@@ -0,0 +1,135 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <iostream>
+
+
+#include "OpenMeca/Gui/Prop/Prop.hpp"
+#include "OpenMeca/Gui/Dialog/Dialog.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+    Prop::Prop(QWidget& parent)
+      : item_(),
+	subItem_(),
+	color_(Qt::white),
+	label_(""),
+	parent_(0),
+	parentDeleted_(false)
+    {
+      bool castOk = false;
+      QObject* widget = &parent;
+      do
+	{
+	  if (CouldCastToDialog(widget)==true)
+	    {
+	      parent_ = static_cast<Dialog*>(widget);
+	      castOk = true;
+	      break;
+	    }
+	  OMC_ASSERT_MSG(widget != 0, "The widget pointer is null");
+	  widget = widget->parent();
+	} while (castOk == false);
+      
+      GetParent().AddProp(*this);
+
+      QFont font("" , 9 , QFont::Bold );
+      item_.setFont( 0,  font );
+
+      QBrush b(QColor(100,100,100));
+      item_.setForeground(0, b);
+    }
+  
+    Prop::~Prop()
+    {
+      if (parentDeleted_==false)
+	GetParent().RemoveProp(*this);
+    }
+
+    bool
+    Prop::CouldCastToDialog(QObject* widget)
+    {
+      Dialog* test = 0;
+      test = dynamic_cast<Dialog*>(widget);	  
+      return (test!=0);
+    }
+
+    Dialog& 
+    Prop::GetParent()
+    {
+      OMC_ASSERT_MSG(parent_!=0, "The parent pointer is null");
+      OMC_ASSERT_MSG(parentDeleted_ == false, "The parent is deleted");
+      return *parent_;
+    }
+
+    void
+    Prop::ParentDeleted()
+    {
+      parentDeleted_ = true;
+    }
+
+    void 
+    Prop::SetLabel(const QString& str)
+    {
+      label_ = str;
+    }
+
+    QString 
+    Prop::GetLabel() const
+    {
+      return label_;
+    }
+
+    QTreeWidgetItem& 
+    Prop::GetTreeWidgetItem()
+    {
+      return item_;
+    }
+
+    void 
+    Prop::SetColor(const QColor& c)
+    {
+      color_ = c;
+      QBrush b(color_);
+      item_.setBackground(0, b);
+      item_.setBackground(1, b);
+      for (unsigned int i = 0; i < subItem_.size(); ++i)
+	{
+	  subItem_[i]->setBackground(0, b);
+	  subItem_[i]->setBackground(1, b);
+	}
+    }
+
+    void
+    Prop::AddSubItem(QTreeWidgetItem* item)
+    {
+      subItem_.push_back(item);
+    }
+
+    void
+    Prop::DisplayHelp(const std::string&)
+    {
+      OMC_ASSERT_MSG(0, "Can't call this method on base class !");
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Prop/Prop.hpp b/SRC/OpenMeca/Gui/Prop/Prop.hpp
new file mode 100644
index 0000000..f12a537
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/Prop.hpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Prop_Prop_hpp
+#define OpenMeca_Gui_Prop_Prop_hpp
+
+#include <QWidget>
+#include <QTreeWidgetItem>
+#include <QColor>
+#include <QToolTip>
+
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class Dialog;
+    class PropTree;
+    
+    class Prop
+    {
+      
+    public:
+      Prop(QWidget& parent);
+      virtual ~Prop();
+      virtual bool Check()=0;  
+      virtual void ApplyChangement() = 0;
+      virtual void CancelChangement() = 0;
+      virtual void Reset() = 0;
+      virtual void Insert(PropTree&){assert(0);};
+      Dialog& GetParent();
+      void ParentDeleted();
+      void DisplayHelp(const std::string& message); //Assert here
+      void SetLabel(const QString&);
+      QString GetLabel() const;
+      QTreeWidgetItem& GetTreeWidgetItem();
+      void SetColor(const QColor&);
+
+    private:
+      bool CouldCastToDialog(QObject* widget);
+
+    protected:
+      void AddSubItem(QTreeWidgetItem*);
+      
+    protected:
+      QTreeWidgetItem item_;
+      std::vector<QTreeWidgetItem*> subItem_;
+      QColor color_;
+
+    private:
+      QString label_;
+      Dialog* parent_;
+      bool parentDeleted_;
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Prop/Prop.pro b/SRC/OpenMeca/Gui/Prop/Prop.pro
new file mode 100644
index 0000000..1d891b9
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/Prop.pro
@@ -0,0 +1,55 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+HEADERS += Gui/Prop/Prop.hpp \
+           Gui/Prop/PropT.hpp \
+           Gui/Prop/PropAxis.hpp \
+           Gui/Prop/PropTree.hpp \
+           Gui/Prop/PropString.hpp \
+           Gui/Prop/PropColor.hpp \
+           Gui/Prop/PropVector.hpp \
+           Gui/Prop/PropDouble.hpp \
+           Gui/Prop/PropEnumT.hpp \
+           Gui/Prop/PropPoint.hpp \
+           Gui/Prop/PropExprPoint.hpp \
+           Gui/Prop/PropExprAttitude.hpp \
+           Gui/Prop/PropSelectItemT.hpp \
+           Gui/Prop/PropBool.hpp \
+           Gui/Prop/PropMatrix.hpp \
+           Gui/Prop/PropAttitude.hpp \
+           Gui/Prop/PropMotionLaw.hpp \
+           Gui/Prop/PropExpr.hpp 
+
+SOURCES += Gui/Prop/Prop.cpp \
+           Gui/Prop/PropTree.cpp \
+           Gui/Prop/PropAxis.cpp \
+           Gui/Prop/PropString.cpp \
+           Gui/Prop/PropColor.cpp \
+           Gui/Prop/PropVector.cpp \
+           Gui/Prop/PropDouble.cpp \
+           Gui/Prop/PropPoint.cpp \
+           Gui/Prop/PropExprPoint.cpp \
+           Gui/Prop/PropExprAttitude.cpp \
+           Gui/Prop/PropBool.cpp \
+           Gui/Prop/PropMatrix.cpp \
+           Gui/Prop/PropAttitude.cpp \
+           Gui/Prop/PropMotionLaw.cpp \
+           Gui/Prop/PropExpr.cpp
diff --git a/SRC/OpenMeca/Gui/Prop/PropAttitude.cpp b/SRC/OpenMeca/Gui/Prop/PropAttitude.cpp
new file mode 100644
index 0000000..ba8905b
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropAttitude.cpp
@@ -0,0 +1,125 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropAttitude.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    PropAttitude::PropAttitude(QWidget* parent)
+      :PropT<Geom::Quaternion<_3D> >(*parent),
+       itemAxis_(),
+       itemX_(),
+       itemY_(),
+       itemZ_(),
+       itemA_(),
+       x_(0),
+       y_(0),
+       z_(0),
+       a_(0)
+    {
+      AddSubItem(&itemAxis_);
+      AddSubItem(&itemX_);
+      AddSubItem(&itemY_);
+      AddSubItem(&itemZ_);
+      AddSubItem(&itemA_);
+
+      x_.SetDimension(Util::Dimension::Get("Length"));
+      y_.SetDimension(Util::Dimension::Get("Length"));
+      z_.SetDimension(Util::Dimension::Get("Length"));
+      a_.SetDimension(Util::Dimension::Get("Angle"));
+    }
+
+    PropAttitude::~PropAttitude()
+    {
+    }
+
+    void 
+    PropAttitude::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      item_.addChild(&itemAxis_);
+      itemAxis_.setText(0, "Axis");
+
+      itemAxis_.addChild(&itemX_);
+      itemX_.setText(0, "X");
+      tree.setItemWidget(&itemX_,1, &x_);
+
+      itemAxis_.addChild(&itemY_);
+      itemY_.setText(0, "Y");
+      tree.setItemWidget(&itemY_,1, &y_);
+
+      itemAxis_.addChild(&itemZ_);
+      itemZ_.setText(0, "Z");
+      tree.setItemWidget(&itemZ_,1, &z_);
+
+      item_.addChild(&itemA_);
+      itemA_.setText(0, "Angle");
+      tree.setItemWidget(&itemA_,1, &a_);
+
+    }
+
+    void 
+    PropAttitude::Init()
+    {
+      const Geom::Quaternion<_3D>& q =  PropT<Geom::Quaternion<_3D> >::GetValue();
+      Geom::Vector<_3D> v = q.GetAxis();
+      if (v.GetNorm() == 0.)
+	v[0] = 1.;
+      const double a = q.GetAngle();
+      x_.SetNumber(v[0]);
+      y_.SetNumber(v[1]);
+      z_.SetNumber(v[2]);
+      a_.SetNumber(a);
+    }
+    
+
+    bool
+    PropAttitude::Check()
+    {
+      double x, y, z, a;
+      bool ok = (x_.GetValue(x) && y_.GetValue(y) && z_.GetValue(z) && a_.GetValue(a));
+      if (ok == false)
+	return false;
+
+      Geom::Vector<_3D>v(x,y,z);
+      if (v.GetNorm()==0.)
+	{
+	  QString msg(QObject::tr("The axis can't be null"));
+	  x_.DisplayHelp(msg);
+	  return false;
+	}
+      Geom::Quaternion<_3D> q(Geom::Vector<_3D>(x,y,z), a);
+      PropT<Geom::Quaternion<_3D> >::GetCopy() = q;
+      return true;;
+    }
+
+  }
+}
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropAttitude.hpp b/SRC/OpenMeca/Gui/Prop/PropAttitude.hpp
new file mode 100644
index 0000000..7525f8e
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropAttitude.hpp
@@ -0,0 +1,74 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropAttitude_hpp
+#define OpenMeca_Prop_PropAttitude_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetDouble.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropAttitude:  public PropT<Geom::Quaternion<_3D> >
+    {
+      public:
+      PropAttitude(QWidget* parent);
+      virtual ~PropAttitude();
+      
+      void Insert(PropTree&);
+
+      bool Check();
+      void ApplyValue();
+
+    private:
+      void Init();
+
+    private:
+      QTreeWidgetItem itemAxis_;
+      QTreeWidgetItem itemX_;
+      QTreeWidgetItem itemY_;
+      QTreeWidgetItem itemZ_;
+      QTreeWidgetItem itemA_;
+      WidgetDouble x_;
+      WidgetDouble y_;
+      WidgetDouble z_;
+      WidgetDouble a_;
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropAxis.cpp b/SRC/OpenMeca/Gui/Prop/PropAxis.cpp
new file mode 100644
index 0000000..dbb5a16
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropAxis.cpp
@@ -0,0 +1,121 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropAxis.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropAxis::PropAxis(QWidget* parent)
+      :PropT<Geom::Vector<_3D> >(*parent),
+       itemX_(),
+       itemY_(),
+       itemZ_(),
+       x_(0),
+       y_(0),
+       z_(0)
+    {
+      AddSubItem(&itemX_);
+      AddSubItem(&itemY_);
+      AddSubItem(&itemZ_);
+    }
+
+    PropAxis::~PropAxis()
+    {
+    }
+
+    
+    void 
+    PropAxis::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      item_.addChild(&itemX_);
+      itemX_.setText(0, "X");
+      tree.setItemWidget(&itemX_,1, &x_);
+
+      item_.addChild(&itemY_);
+      itemY_.setText(0, "Y");
+      tree.setItemWidget(&itemY_,1, &y_);
+
+      item_.addChild(&itemZ_);
+      itemZ_.setText(0, "Z");
+      tree.setItemWidget(&itemZ_,1, &z_);
+
+    }
+
+    void 
+    PropAxis::SetDimension(const Util::Dimension& dim)
+    {
+      x_.SetDimension(dim);
+      y_.SetDimension(dim);
+      z_.SetDimension(dim);
+    }
+
+
+
+    void 
+    PropAxis::Init()
+    {
+      const Geom::Vector<_3D>& p =  PropT<Geom::Vector<_3D> >::GetValue();    
+      x_.SetNumber(p[0]);
+      y_.SetNumber(p[1]);
+      z_.SetNumber(p[2]);
+    }
+    
+
+   
+    bool
+    PropAxis::Check()
+    {
+      double x, y, z;
+      bool ok = (x_.GetValue(x) && y_.GetValue(y) && z_.GetValue(z));
+      if (ok)
+	{
+	  Geom::Vector<_3D> &p = PropT<Geom::Vector<_3D> >::GetCopy();
+	  if (x == 0. && y == 0. && z == 0.)
+	    {
+	      ok = false;
+	      x_.DisplayHelp(QObject::tr("The axis can not be null"));
+	    }
+	  else
+	    {
+	      p[0] = x;
+	      p[1] = y;
+	      p[2] = z;
+	      p.Normalize();
+	    }
+	}
+      return ok;
+    }
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropAxis.hpp b/SRC/OpenMeca/Gui/Prop/PropAxis.hpp
new file mode 100644
index 0000000..9bf3659
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropAxis.hpp
@@ -0,0 +1,73 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropAxis_hpp
+#define OpenMeca_Prop_PropAxis_hpp
+
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetDouble.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+#include "OpenMeca/Geom/Vector.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropAxis: public PropT<Geom::Vector<_3D> >
+    {
+      public:
+      PropAxis(QWidget* parent);
+      virtual ~PropAxis();
+
+      void Insert(PropTree&);
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool Check();
+      void ApplyValue();
+
+
+    private:
+      void Init();
+
+    private:
+      QTreeWidgetItem itemX_;
+      QTreeWidgetItem itemY_;
+      QTreeWidgetItem itemZ_;
+      WidgetDouble x_;
+      WidgetDouble y_;
+      WidgetDouble z_;
+ 
+   
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropBool.cpp b/SRC/OpenMeca/Gui/Prop/PropBool.cpp
new file mode 100644
index 0000000..c3b4bbb
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropBool.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropBool.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropBool::PropBool(QWidget* parent)
+      :PropT<bool>(*parent),
+       checkBox_()
+    {
+      checkBox_.setAttribute(Qt::WA_TranslucentBackground);
+    }
+    
+    PropBool::~PropBool()
+    {
+    }
+
+    void
+    PropBool::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, GetLabel());
+      tree.setItemWidget(&item_,1, &checkBox_);
+    }
+
+
+    void 
+    PropBool::Init()
+    {
+      const bool value =  PropT<bool>::GetValue();
+      if (value)
+	checkBox_.setCheckState(Qt::Checked);
+      else
+	checkBox_.setCheckState(Qt::Unchecked);
+    }
+   
+    bool
+    PropBool::Check()
+    {
+      if (checkBox_.checkState() == Qt::Checked)
+	PropT<bool>::GetCopy() = true;
+      else if (checkBox_.checkState() == Qt::Unchecked)
+	PropT<bool>::GetCopy() = false;
+      else
+	OMC_ASSERT_MSG(0, "This case is forbidden");
+
+      return true;
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Prop/PropBool.hpp b/SRC/OpenMeca/Gui/Prop/PropBool.hpp
new file mode 100644
index 0000000..7b65b9c
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropBool.hpp
@@ -0,0 +1,54 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropBool_hpp
+#define OpenMeca_Prop_PropBool_hpp
+
+
+#include <QCheckBox>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropBool: public PropT<bool>
+    {
+      
+    public:
+      PropBool(QWidget* parent);
+      virtual ~PropBool();
+
+      void Insert(PropTree&);
+      bool Check();
+
+      
+    private:
+      void Init();	
+
+    private:
+      QCheckBox checkBox_;
+    };
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropColor.cpp b/SRC/OpenMeca/Gui/Prop/PropColor.cpp
new file mode 100644
index 0000000..aec504c
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropColor.cpp
@@ -0,0 +1,88 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <iostream>
+#include <QColorDialog>
+#include <QPalette>
+
+#include "OpenMeca/Gui/Prop/PropColor.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    PropColor::PropColor(QWidget* parent)
+      :PropT<Util::Color>(*parent),
+       pushButton_()
+    {
+      QObject::connect(&pushButton_, SIGNAL( clicked() ), this, SLOT( NewPropColor() ) );
+      pushButton_.setMaximumHeight(15);
+    }
+  
+    PropColor::~PropColor()
+    {
+    }
+
+    void
+    PropColor::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, GetLabel());
+      tree.setItemWidget(&item_,1, &pushButton_);
+      
+    }
+
+    void
+    PropColor::Init()
+    {
+      UpdateBackground();
+    }
+
+    bool 
+    PropColor::Check()
+    {
+      return true;
+    }
+
+ 
+    void 
+    PropColor::NewPropColor()
+    {
+      QColor newColor = QColorDialog::getColor();
+      if (newColor.isValid())
+	{
+	  GetCopy()=Util::Color(newColor);
+	  UpdateBackground();
+	}
+     
+    }
+
+
+    void 
+    PropColor::UpdateBackground()
+    {
+      QPalette palette = pushButton_.palette();
+      QColor color = GetCopy().GetQColor();
+      palette.setColor(QPalette::Button, color);
+      pushButton_.setPalette(palette);
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Prop/PropColor.hpp b/SRC/OpenMeca/Gui/Prop/PropColor.hpp
new file mode 100644
index 0000000..0271c39
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropColor.hpp
@@ -0,0 +1,61 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Prop_PropColor_hpp
+#define OpenMeca_Gui_Prop_PropColor_hpp
+
+#include <QWidget>
+#include <QPushButton>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Util/Color.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropColor : public QObject, 
+		      public PropT<Util::Color>
+		      
+    {
+      Q_OBJECT
+      
+      public:
+      PropColor(QWidget* parent);
+      ~PropColor();
+      bool Check();
+      void ApplyValue();
+      void Insert(PropTree& tree);
+      
+      
+    private:
+      void UpdateBackground();
+      void Init();
+		 
+    private slots:
+      void NewPropColor();
+
+    private:
+      QPushButton pushButton_;
+    };
+    
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Prop/PropDouble.cpp b/SRC/OpenMeca/Gui/Prop/PropDouble.cpp
new file mode 100644
index 0000000..e041870
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropDouble.cpp
@@ -0,0 +1,97 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropDouble.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropDouble::PropDouble(QWidget* parent)
+      :PropT<double>(*parent),
+       widgetDouble_(0)
+    {
+    }
+
+    PropDouble::~PropDouble()
+    {
+    }
+
+    void 
+    PropDouble::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      tree.setItemWidget(&item_,1, &widgetDouble_);
+    }
+    
+    void 
+    PropDouble::SetDimension(const Util::Dimension& dim)
+    {
+      widgetDouble_.SetDimension(dim);
+    }
+
+    const Util::Dimension&
+    PropDouble::GetDimension() const
+    {
+      return widgetDouble_.GetDimension();
+    }
+
+    void 
+    PropDouble::Init()
+    {
+      const double& value =  PropT<double>::GetValue();
+      widgetDouble_.SetNumber(value);
+    }
+   
+    bool
+    PropDouble::Check()
+    {
+      double& value = PropT<double>::GetCopy();
+      return (widgetDouble_.GetValue(value));
+    }
+
+    void 
+    PropDouble::DisplayHelp(const QString& message)
+    {
+      widgetDouble_.DisplayHelp(message);
+    }
+
+    void 
+    PropDouble::AddCondition(const Core::Condition<double>* cond)
+    {
+      widgetDouble_.AddCondition(cond);
+    }
+
+    QString 
+    PropDouble::GetInputString() const
+    {
+      return widgetDouble_.GetInputString();
+    }
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropDouble.hpp b/SRC/OpenMeca/Gui/Prop/PropDouble.hpp
new file mode 100644
index 0000000..1aa6db3
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropDouble.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropDouble_hpp
+#define OpenMeca_Prop_PropDouble_hpp
+
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetDouble.hpp"
+#include "OpenMeca/Core/Condition.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+    class PropDouble: public PropT<double>
+    {
+      
+    public:
+      PropDouble(QWidget* parent);
+      virtual ~PropDouble();
+      
+      void Insert(PropTree&);
+
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool Check();
+      void ApplyValue();
+
+      void DisplayHelp(const QString& message);
+      void AddCondition(const Core::Condition<double>* cond);
+
+      QString GetInputString() const;
+
+    private:
+      void Init();
+
+    private:
+      WidgetDouble widgetDouble_;
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropEnumT.hpp b/SRC/OpenMeca/Gui/Prop/PropEnumT.hpp
new file mode 100644
index 0000000..cc14c3b
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropEnumT.hpp
@@ -0,0 +1,109 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropEnumT_hpp
+#define OpenMeca_Prop_PropEnumT_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QComboBox>
+
+#include "OpenMeca/Util/Enum.hpp"
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetEnum.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    template<typename T>
+    class PropEnumT: public PropT<T>
+    {
+      
+    public:
+      PropEnumT(QWidget* parent);
+      virtual ~PropEnumT();
+
+      void Insert(PropTree&);
+
+      bool Check();
+      void ApplyValue();
+
+    private:
+      void UpdateComboBox();
+      void Init();   
+
+    private:
+      WidgetEnum enum_;
+      bool isInit_;
+    };
+
+
+    template<typename T>
+    inline
+    PropEnumT<T>::PropEnumT(QWidget* parent)
+      :PropT<T>(*parent),
+       enum_(parent),
+       isInit_(false)
+    {
+      const std::vector<std::string> str = Util::Enum<T>::List();
+      for (unsigned int i = 0; i < str.size(); ++i)
+	enum_.addItem(str[i].c_str());
+    }
+
+    template<typename T>
+    inline
+    PropEnumT<T>::~PropEnumT()
+    {
+    }
+
+    template<typename T>
+    inline void 
+    PropEnumT<T>::Insert(PropTree& tree)
+    {
+      QTreeWidgetItem& item = Prop::item_;
+      tree.addTopLevelItem(&item);
+      item.setText(0, Prop::GetLabel());
+      tree.setItemWidget(&item,1, &enum_);
+    }
+
+    template<typename T>
+    inline void 
+    PropEnumT<T>::Init()
+    {
+ 
+    }
+    
+    template<typename T>
+    inline bool
+    PropEnumT<T>::Check()
+    {
+      const std::string str = enum_.currentText().toStdString();
+      PropT<T>::GetCopy() = Util::Enum<T>::ToEnum(str);
+      return true;
+    }
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropExpr.cpp b/SRC/OpenMeca/Gui/Prop/PropExpr.cpp
new file mode 100644
index 0000000..6d0aebb
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropExpr.cpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QApplication>
+#include <QToolTip>
+#include <QWidget>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropExpr.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropExpr::PropExpr(QWidget* parent)
+      :PropT<Util::Expr>(*parent),
+       widgetExpr_(0)
+    {
+    }
+
+    PropExpr::~PropExpr()
+    {
+    }
+
+    void 
+    PropExpr::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      tree.setItemWidget(&item_,1, &widgetExpr_);
+    }
+
+    void 
+    PropExpr::SetDimension(const Util::Dimension& dim)
+    {
+      widgetExpr_.SetDimension(dim);
+    }
+
+    const Util::Dimension&
+    PropExpr::GetDimension() const
+    {
+      return widgetExpr_.GetDimension();
+    }
+    
+    
+    void 
+    PropExpr::Init()
+    {
+      widgetExpr_.SetExpr(PropT<Util::Expr>::GetValue());
+    }
+   
+    bool
+    PropExpr::Check()
+    {
+      return (widgetExpr_.GetExpr(PropT<Util::Expr>::GetCopy()));
+    }
+
+    void 
+    PropExpr::DisplayHelp(const QString& message)
+    {
+      widgetExpr_.DisplayHelp(message);
+    }
+
+    void 
+    PropExpr::AddCondition(const Core::Condition<double>* cond)
+    {
+      widgetExpr_.AddCondition(cond);
+    }
+
+    void 
+    PropExpr::PostChangement()
+    {
+      PropT<Util::Expr>::GetValue().Update();
+    }
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropExpr.hpp b/SRC/OpenMeca/Gui/Prop/PropExpr.hpp
new file mode 100644
index 0000000..45f8a22
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropExpr.hpp
@@ -0,0 +1,65 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropExpr_hpp
+#define OpenMeca_Prop_PropExpr_hpp
+
+
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetExpr.hpp"
+#include "OpenMeca/Util/Expr.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+    class PropExpr: public PropT<Util::Expr>
+    {
+      
+    public:
+      PropExpr(QWidget* parent);
+      virtual ~PropExpr();
+      
+      void Insert(PropTree&);
+
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+
+      bool Check();
+      void ApplyValue();
+
+      void DisplayHelp(const QString& message);
+      void AddCondition(const Core::Condition<double>* cond);
+      void PostChangement();
+
+    private:
+      void Init();
+
+    private:
+      WidgetExpr widgetExpr_;
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropExprAttitude.cpp b/SRC/OpenMeca/Gui/Prop/PropExprAttitude.cpp
new file mode 100644
index 0000000..b6783a7
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropExprAttitude.cpp
@@ -0,0 +1,135 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropExprAttitude.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropExprAttitude::PropExprAttitude(QWidget* parent)
+      :PropT<Util::ExprAttitude>(*parent),
+       itemAxis_(),
+       itemX_(),
+       itemY_(),
+       itemZ_(),
+       x_(0),
+       y_(0),
+       z_(0),
+       a_(0)
+    {
+      AddSubItem(&itemAxis_);
+      AddSubItem(&itemX_);
+      AddSubItem(&itemY_);
+      AddSubItem(&itemZ_);
+      AddSubItem(&itemA_);
+
+      x_.SetDimension(Util::Dimension::Get("Length"));
+      y_.SetDimension(Util::Dimension::Get("Length"));
+      z_.SetDimension(Util::Dimension::Get("Length"));
+      a_.SetDimension(Util::Dimension::Get("Angle"));
+    }
+
+    PropExprAttitude::~PropExprAttitude()
+    {
+    }
+
+    
+    void 
+    PropExprAttitude::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      item_.addChild(&itemAxis_);
+      itemAxis_.setText(0, "Axis");
+
+      itemAxis_.addChild(&itemX_);
+      itemX_.setText(0, "X");
+      tree.setItemWidget(&itemX_,1, &x_);
+
+      itemAxis_.addChild(&itemY_);
+      itemY_.setText(0, "Y");
+      tree.setItemWidget(&itemY_,1, &y_);
+
+      itemAxis_.addChild(&itemZ_);
+      itemZ_.setText(0, "Z");
+      tree.setItemWidget(&itemZ_,1, &z_);
+
+      item_.addChild(&itemA_);
+      itemA_.setText(0, "Angle");
+      tree.setItemWidget(&itemA_,1, &a_);
+    }
+
+
+
+    void 
+    PropExprAttitude::Init()
+    {
+      Util::ExprAttitude& p = PropT<Util::ExprAttitude >::GetValue();    
+      x_.SetExpr(p.GetAxis().GetExpressionX());
+      y_.SetExpr(p.GetAxis().GetExpressionY());
+      z_.SetExpr(p.GetAxis().GetExpressionZ());
+      a_.SetExpr(p.GetAngle().GetExpression());
+    }
+    
+
+   
+    bool
+    PropExprAttitude::Check()
+    {
+      Util::ExprAttitude& p = PropT<Util::ExprAttitude >::GetCopy();
+      Util::Expr& x = p.GetAxis().GetExpressionX();
+      Util::Expr& y = p.GetAxis().GetExpressionY();
+      Util::Expr& z = p.GetAxis().GetExpressionZ();
+      Util::Expr& a = p.GetAngle().GetExpression();
+
+      if (x_.GetExpr(x) && y_.GetExpr(y) && z_.GetExpr(z) && a_.GetExpr(a))
+	{
+	  if (x()==0 && y()==0 && z()==0.)
+	    {
+	      QString msg(QObject::tr("The axis can't be null"));
+	      x_.DisplayHelp(msg);
+	      return false;
+	    }
+	  return true;
+	}
+      return false;
+    }
+
+    void     
+    PropExprAttitude::PostChangement()
+    {   
+      Util::ExprAttitude& q = PropT<Util::ExprAttitude >::GetValue();
+      q.Update();
+    }
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropExprAttitude.hpp b/SRC/OpenMeca/Gui/Prop/PropExprAttitude.hpp
new file mode 100644
index 0000000..e47e49f
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropExprAttitude.hpp
@@ -0,0 +1,79 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropExprQuaternion_hpp
+#define OpenMeca_Prop_PropExprQuaternion_hpp
+
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetExpr.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+#include "OpenMeca/Util/ExprAttitude.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropExprAttitude: public PropT<Util::ExprAttitude>
+    {
+      public:
+      PropExprAttitude(QWidget* parent);
+      virtual ~PropExprAttitude();
+
+      void Insert(PropTree&);
+      
+      bool Check();
+      void ApplyValue();
+
+      void PostChangement();
+
+    private:
+      void Init();
+
+    private:
+      QTreeWidgetItem itemAxis_;
+      QTreeWidgetItem itemX_;
+      QTreeWidgetItem itemY_;
+      QTreeWidgetItem itemZ_;
+      QTreeWidgetItem itemA_;
+      WidgetExpr x_;
+      WidgetExpr y_;
+      WidgetExpr z_;
+      WidgetExpr a_;
+ 
+   
+    };
+
+
+ 
+
+    
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropExprPoint.cpp b/SRC/OpenMeca/Gui/Prop/PropExprPoint.cpp
new file mode 100644
index 0000000..e1e74d7
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropExprPoint.cpp
@@ -0,0 +1,129 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropExprPoint.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropExprPoint::PropExprPoint(QWidget* parent)
+      :PropT<Util::ExprPoint>(*parent),
+       itemX_(),
+       itemY_(),
+       itemZ_(),
+       x_(0),
+       y_(0),
+       z_(0)
+    {
+      AddSubItem(&itemX_);
+      AddSubItem(&itemY_);
+      AddSubItem(&itemZ_);
+    }
+
+    PropExprPoint::~PropExprPoint()
+    {
+    }
+
+    
+    void 
+    PropExprPoint::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      item_.addChild(&itemX_);
+      itemX_.setText(0, "X");
+      tree.setItemWidget(&itemX_,1, &x_);
+
+      item_.addChild(&itemY_);
+      itemY_.setText(0, "Y");
+      tree.setItemWidget(&itemY_,1, &y_);
+
+      item_.addChild(&itemZ_);
+      itemZ_.setText(0, "Z");
+      tree.setItemWidget(&itemZ_,1, &z_);
+
+    }
+
+    void 
+    PropExprPoint::SetDimension(const Util::Dimension& dim)
+    {
+      x_.SetDimension(dim);
+      y_.SetDimension(dim);
+      z_.SetDimension(dim);
+    }
+
+    const Util::Dimension& 
+    PropExprPoint::GetDimension() const
+    {
+      return x_.GetDimension();
+    }
+
+    void 
+    PropExprPoint::Init()
+    {
+      Util::ExprPoint& p = PropT<Util::ExprPoint >::GetValue();    
+      x_.SetExpr(p.GetExpressionX());
+      y_.SetExpr(p.GetExpressionY());
+      z_.SetExpr(p.GetExpressionZ());
+    }
+    
+
+   
+    bool
+    PropExprPoint::Check()
+    {
+      Util::ExprPoint& p = PropT<Util::ExprPoint >::GetCopy();
+      Util::Expr& x = p.GetExpressionX();
+      Util::Expr& y = p.GetExpressionY();
+      Util::Expr& z = p.GetExpressionZ();
+      return (x_.GetExpr(x) && y_.GetExpr(y) && z_.GetExpr(z));
+    }
+
+    void 
+    PropExprPoint::AddComponentCondition(const Core::Condition<double>* cond)
+    {
+      x_.AddCondition(cond);
+      y_.AddCondition(cond->Copy());
+      z_.AddCondition(cond->Copy());
+    }
+
+    void     
+    PropExprPoint::PostChangement()
+    {
+      Util::ExprPoint& p = PropT<Util::ExprPoint >::GetValue();
+      p.GetExpressionX().Update();
+      p.GetExpressionY().Update();
+      p.GetExpressionZ().Update();
+    }
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropExprPoint.hpp b/SRC/OpenMeca/Gui/Prop/PropExprPoint.hpp
new file mode 100644
index 0000000..42d4ba6
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropExprPoint.hpp
@@ -0,0 +1,80 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropExprPoint_hpp
+#define OpenMeca_Prop_PropExprPoint_hpp
+
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetExpr.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+#include "OpenMeca/Util/ExprPoint.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropExprPoint: public PropT<Util::ExprPoint>
+    {
+      public:
+      PropExprPoint(QWidget* parent);
+      virtual ~PropExprPoint();
+
+      void Insert(PropTree&);
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool Check();
+      void ApplyValue();
+
+      void AddComponentCondition(const Core::Condition<double>*);
+      void PostChangement();
+
+    private:
+      void Init();
+
+    private:
+      QTreeWidgetItem itemX_;
+      QTreeWidgetItem itemY_;
+      QTreeWidgetItem itemZ_;
+      WidgetExpr x_;
+      WidgetExpr y_;
+      WidgetExpr z_;
+ 
+   
+    };
+
+
+ 
+
+    
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropMatrix.cpp b/SRC/OpenMeca/Gui/Prop/PropMatrix.cpp
new file mode 100644
index 0000000..fe696cf
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropMatrix.cpp
@@ -0,0 +1,226 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropMatrix.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    PropMatrix::PropMatrix(QWidget* parent)
+      :PropT<Geom::Matrix<_3D> >(*parent),
+       itemXX_(),
+       itemXY_(),
+       itemXZ_(),
+       itemYX_(),
+       itemYY_(),
+       itemYZ_(),
+       itemZX_(),
+       itemZY_(),
+       itemZZ_(),
+       xx_(0),
+       yx_(0),
+       zx_(0),
+       xy_(0),
+       yy_(0),
+       zy_(0),
+       xz_(0),
+       yz_(0),
+       zz_(0)
+    {
+      QObject::connect(&xy_.GetLineEdit(), SIGNAL(textChanged(const QString&)), 
+		       this               , SLOT(XYEdited(const QString&))); 
+      QObject::connect(&xz_.GetLineEdit(), SIGNAL(textChanged(const QString&)), 
+		       this               , SLOT(XZEdited(const QString&))); 
+      QObject::connect(&yz_.GetLineEdit(), SIGNAL(textChanged(const QString&)), 
+		       this               , SLOT(YZEdited(const QString&))); 
+
+      AddSubItem(&itemXX_);
+      AddSubItem(&itemXY_);
+      AddSubItem(&itemXZ_);
+      AddSubItem(&itemYX_);
+      AddSubItem(&itemYY_);
+      AddSubItem(&itemYZ_);
+      AddSubItem(&itemZX_);
+      AddSubItem(&itemZY_);
+      AddSubItem(&itemZZ_);
+    }
+
+    PropMatrix::~PropMatrix()
+    {
+    }
+
+    void 
+    PropMatrix::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      // X
+      item_.addChild(&itemXX_);
+      itemXX_.setText(0, "XX");
+      tree.setItemWidget(&itemXX_,1, &xx_);
+
+      item_.addChild(&itemXY_);
+      itemXY_.setText(0, "XY");
+      tree.setItemWidget(&itemXY_,1, &xy_);
+
+      item_.addChild(&itemXZ_);
+      itemXZ_.setText(0, "XZ");
+      tree.setItemWidget(&itemXZ_,1, &xz_);
+
+      // Y
+      item_.addChild(&itemYX_);
+      itemYX_.setText(0, "YX");
+      tree.setItemWidget(&itemYX_,1, &yx_);
+
+      item_.addChild(&itemYY_);
+      itemYY_.setText(0, "YY");
+      tree.setItemWidget(&itemYY_,1, &yy_);
+
+      item_.addChild(&itemYZ_);
+      itemYZ_.setText(0, "YZ");
+      tree.setItemWidget(&itemYZ_,1, &yz_);
+
+      // Z
+      item_.addChild(&itemZX_);
+      itemZX_.setText(0, "ZX");
+      tree.setItemWidget(&itemZX_,1, &zx_);
+
+      item_.addChild(&itemZY_);
+      itemZY_.setText(0, "ZY");
+      tree.setItemWidget(&itemZY_,1, &zy_);
+
+      item_.addChild(&itemZZ_);
+      itemZZ_.setText(0, "ZZ");
+      tree.setItemWidget(&itemZZ_,1, &zz_);
+
+    }
+
+    
+    void 
+    PropMatrix::SetDimension(const Util::Dimension& dim)
+    {
+      xx_.SetDimension(dim);
+      xy_.SetDimension(dim);
+      xz_.SetDimension(dim);
+
+      yx_.SetDimension(dim);
+      yy_.SetDimension(dim);
+      yz_.SetDimension(dim);
+
+      zx_.SetDimension(dim);
+      zy_.SetDimension(dim);
+      zz_.SetDimension(dim);
+    }
+
+
+  
+
+    void 
+    PropMatrix::Init()
+    {
+      const Geom::Matrix<_3D>& m =  PropT<Geom::Matrix<_3D> >::GetValue();    
+      xx_.SetNumber(m[0][0]);
+      xy_.SetNumber(m[0][1]);
+      xz_.SetNumber(m[0][2]);
+
+      yx_.SetNumber(m[1][0]);
+      yy_.SetNumber(m[1][1]);
+      yz_.SetNumber(m[1][2]);
+
+      zx_.SetNumber(m[2][0]);
+      zy_.SetNumber(m[2][1]);
+      zz_.SetNumber(m[2][2]);
+
+    }
+    
+   
+    bool
+    PropMatrix::Check()
+    {
+      double xx, xy, xz, yx, yy, yz, zx, zy, zz;
+      bool ok = (xx_.GetValue(xx) && xy_.GetValue(xy) && xz_.GetValue(xz) &&
+		 yx_.GetValue(yx) && yy_.GetValue(yy) && yz_.GetValue(yz) &&
+		 zx_.GetValue(zx) && zy_.GetValue(zy) && zz_.GetValue(zz));
+       if (ok)
+	{
+	  Geom::Matrix<_3D> &m = PropT<Geom::Matrix<_3D> >::GetCopy();
+	  m[0][0] = xx;
+	  m[0][1] = xy;
+	  m[0][2] = xz;
+	  
+	  m[1][0] = yx;
+	  m[1][1] = yy;
+	  m[1][2] = yz;
+	  
+	  m[2][0] = zx;
+	  m[2][1] = zy;
+	  m[2][2] = zz;
+
+	}
+      return ok;
+    
+    }
+
+    void
+    PropMatrix::XYEdited(const QString& str)
+    {
+      yx_.GetLineEdit().setText(str);
+    }
+
+    void
+    PropMatrix::XZEdited(const QString& str)
+    {
+      zx_.GetLineEdit().setText(str);
+    }
+
+    void
+    PropMatrix::YZEdited(const QString& str)
+    {
+      zy_.GetLineEdit().setText(str);
+    }
+
+       
+    void 
+    PropMatrix::AddComponentCondition(const Core::Condition<double>* cond)
+    {
+      xx_.AddCondition(cond);
+      xy_.AddCondition(cond->Copy());
+      xz_.AddCondition(cond->Copy());
+
+      yx_.AddCondition(cond->Copy());
+      yy_.AddCondition(cond->Copy());
+      yz_.AddCondition(cond->Copy());
+
+      zx_.AddCondition(cond->Copy());
+      zy_.AddCondition(cond->Copy());
+      zz_.AddCondition(cond->Copy());
+    }
+
+
+  }
+}
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropMatrix.hpp b/SRC/OpenMeca/Gui/Prop/PropMatrix.hpp
new file mode 100644
index 0000000..213096b
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropMatrix.hpp
@@ -0,0 +1,104 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropMatrix_hpp
+#define OpenMeca_Prop_PropMatrix_hpp
+
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetDouble.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/Condition.hpp"
+
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+#include "OpenMeca/Geom/Matrix.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropMatrix: public QObject, public PropT<Geom::Matrix<_3D> >
+    {
+      Q_OBJECT
+      public:
+      PropMatrix(QWidget* parent);
+      virtual ~PropMatrix();
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool Check();
+      void ApplyValue();
+
+      void Insert(PropTree& tree);
+
+      void AddComponentCondition(const Core::Condition<double>*);
+
+    private:
+      void Init();
+
+    private slots:
+      void XYEdited(const QString&);
+      void XZEdited(const QString&);
+      void YZEdited(const QString&);
+
+    private:
+      QTreeWidgetItem itemXX_;
+      QTreeWidgetItem itemXY_;
+      QTreeWidgetItem itemXZ_;
+
+      QTreeWidgetItem itemYX_;
+      QTreeWidgetItem itemYY_;
+      QTreeWidgetItem itemYZ_;
+
+      QTreeWidgetItem itemZX_;
+      QTreeWidgetItem itemZY_;
+      QTreeWidgetItem itemZZ_;
+
+      WidgetDouble xx_;
+      WidgetDouble yx_;
+      WidgetDouble zx_;
+
+      WidgetDouble xy_;
+      WidgetDouble yy_;
+      WidgetDouble zy_;
+
+      WidgetDouble xz_;
+      WidgetDouble yz_;
+      WidgetDouble zz_;
+
+   
+    };
+
+    
+    
+    
+
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropMotionLaw.cpp b/SRC/OpenMeca/Gui/Prop/PropMotionLaw.cpp
new file mode 100644
index 0000000..53bb78f
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropMotionLaw.cpp
@@ -0,0 +1,118 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropMotionLaw.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropMotionLaw::PropMotionLaw(QWidget* parent)
+      :PropT<Util::MotionLaw>(*parent),
+       itemCheckBox_(),
+       itemWidgetExpr_(),
+       checkBox_(),
+       widgetExpr_(0)
+    {
+      AddSubItem(&itemCheckBox_);
+      AddSubItem(&itemWidgetExpr_);
+    }
+
+    PropMotionLaw::~PropMotionLaw()
+    {
+    }
+
+    
+    void 
+    PropMotionLaw::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      item_.addChild(&itemCheckBox_);
+      itemCheckBox_.setText(0, QObject::tr("Enabled"));
+      tree.setItemWidget(&itemCheckBox_,1, &checkBox_);
+
+      item_.addChild(&itemWidgetExpr_);
+      itemWidgetExpr_.setText(0, QObject::tr("Motion Law"));
+      tree.setItemWidget(&itemWidgetExpr_,1, &widgetExpr_);
+    }
+
+    void 
+    PropMotionLaw::SetDimension(const Util::Dimension& dim)
+    {
+      widgetExpr_.SetDimension(dim);
+    }
+
+
+    const Util::Dimension&
+    PropMotionLaw::GetDimension() const
+    {
+
+      
+      return widgetExpr_.GetDimension();
+    }
+
+
+    void 
+    PropMotionLaw::Init()
+    {
+      const bool value =  PropT<Util::MotionLaw>::GetCopy().IsEnabled();
+      if (value)
+	checkBox_.setCheckState(Qt::Checked);
+      else
+	checkBox_.setCheckState(Qt::Unchecked);
+
+      widgetExpr_.SetExpr(PropT<Util::MotionLaw>::GetCopy().GetLaw());
+    }
+    
+    void 
+    PropMotionLaw::DisplayHelp(const QString& message)
+    {
+      widgetExpr_.DisplayHelp(message);
+    }
+
+   
+    bool
+    PropMotionLaw::Check()
+    {
+     
+      if (checkBox_.checkState() == Qt::Checked)
+	PropT<Util::MotionLaw>::GetCopy().GetEnabled() = true;
+      else if (checkBox_.checkState() == Qt::Unchecked)
+	PropT<Util::MotionLaw>::GetCopy().GetEnabled() = false;
+      else
+	OMC_ASSERT_MSG(0, "This case is forbidden");
+
+      return (widgetExpr_.GetExpr(PropT<Util::MotionLaw>::GetCopy().GetLaw()));
+    }
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropMotionLaw.hpp b/SRC/OpenMeca/Gui/Prop/PropMotionLaw.hpp
new file mode 100644
index 0000000..7f0c6cf
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropMotionLaw.hpp
@@ -0,0 +1,69 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropMotionLaw_hpp
+#define OpenMeca_Prop_PropMotionLaw_hpp
+
+
+#include <QLabel>
+#include <QCheckBox>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetExpr.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+#include "OpenMeca/Util/MotionLaw.hpp"
+
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropMotionLaw: public PropT<Util::MotionLaw>
+    {
+      public:
+      PropMotionLaw(QWidget* parent);
+      virtual ~PropMotionLaw();
+
+      void Insert(PropTree&);
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool Check();
+      void ApplyValue();
+
+      void DisplayHelp(const QString& message);
+
+    private:
+      void Init();
+
+    private:
+      QTreeWidgetItem itemCheckBox_;
+      QTreeWidgetItem itemWidgetExpr_;
+      QCheckBox checkBox_;
+      WidgetExpr widgetExpr_;
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropPoint.cpp b/SRC/OpenMeca/Gui/Prop/PropPoint.cpp
new file mode 100644
index 0000000..1997a5a
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropPoint.cpp
@@ -0,0 +1,120 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropPoint.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropPoint::PropPoint(QWidget* parent)
+      :PropT<Geom::Point<_3D> >(*parent),
+       itemX_(),
+       itemY_(),
+       itemZ_(),
+       x_(0),
+       y_(0),
+       z_(0)
+    {
+      AddSubItem(&itemX_);
+      AddSubItem(&itemY_);
+      AddSubItem(&itemZ_);
+    }
+
+    PropPoint::~PropPoint()
+    {
+    }
+
+    
+    void 
+    PropPoint::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      item_.addChild(&itemX_);
+      itemX_.setText(0, "X");
+      tree.setItemWidget(&itemX_,1, &x_);
+
+      item_.addChild(&itemY_);
+      itemY_.setText(0, "Y");
+      tree.setItemWidget(&itemY_,1, &y_);
+
+      item_.addChild(&itemZ_);
+      itemZ_.setText(0, "Z");
+      tree.setItemWidget(&itemZ_,1, &z_);
+
+    }
+
+    void 
+    PropPoint::SetDimension(const Util::Dimension& dim)
+    {
+      x_.SetDimension(dim);
+      y_.SetDimension(dim);
+      z_.SetDimension(dim);
+    }
+
+
+
+    void 
+    PropPoint::Init()
+    {
+      const Geom::Point<_3D>& p =  PropT<Geom::Point<_3D> >::GetValue();    
+      x_.SetNumber(p[0]);
+      y_.SetNumber(p[1]);
+      z_.SetNumber(p[2]);
+    }
+    
+
+   
+    bool
+    PropPoint::Check()
+    {
+      double x, y, z;
+      bool ok = (x_.GetValue(x) && y_.GetValue(y) && z_.GetValue(z));
+      if (ok)
+	{
+	  Geom::Point<_3D> &p = PropT<Geom::Point<_3D> >::GetCopy();
+	  p[0] = x;
+	  p[1] = y;
+	  p[2] = z;
+	}
+      return ok;
+    }
+
+    void 
+    PropPoint::AddComponentCondition(const Core::Condition<double>* cond)
+    {
+      x_.AddCondition(cond);
+      y_.AddCondition(cond->Copy());
+      z_.AddCondition(cond->Copy());
+    }
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropPoint.hpp b/SRC/OpenMeca/Gui/Prop/PropPoint.hpp
new file mode 100644
index 0000000..76f762f
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropPoint.hpp
@@ -0,0 +1,75 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropPoint_hpp
+#define OpenMeca_Prop_PropPoint_hpp
+
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetDouble.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropPoint: public PropT<Geom::Point<_3D> >
+    {
+      public:
+      PropPoint(QWidget* parent);
+      virtual ~PropPoint();
+
+      void Insert(PropTree&);
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool Check();
+      void ApplyValue();
+
+      void AddComponentCondition(const Core::Condition<double>*);
+
+
+    private:
+      void Init();
+
+    private:
+      QTreeWidgetItem itemX_;
+      QTreeWidgetItem itemY_;
+      QTreeWidgetItem itemZ_;
+      WidgetDouble x_;
+      WidgetDouble y_;
+      WidgetDouble z_;
+ 
+   
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropSelectItemT.hpp b/SRC/OpenMeca/Gui/Prop/PropSelectItemT.hpp
new file mode 100644
index 0000000..b7a4a63
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropSelectItemT.hpp
@@ -0,0 +1,129 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropSelectItemT_hpp
+#define OpenMeca_Prop_PropSelectItemT_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QComboBox>
+
+
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/UserItem.hpp"
+#include "OpenMeca/Gui/Widget/WidgetSelectItemT.hpp"
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    template<class T>
+    class PropSelectItemT: public PropT<T>
+    {
+      
+    public:
+      PropSelectItemT(QWidget* parent);
+      virtual ~PropSelectItemT();
+
+      void Insert(PropTree&);
+
+      bool Check();
+      void ApplyValue();
+      void SetList(Core::SetOfBase<typename T::PtrType>& set);
+
+      typename T::PtrType& GetSelectedItem();
+
+    private:
+      void Init();
+
+    private:
+      WidgetSelectItemT<T> widgetSelect_;
+
+    };
+
+
+    template<class T>
+    inline
+    PropSelectItemT<T>::PropSelectItemT(QWidget* parent)
+      :PropT<T>(*parent),
+       widgetSelect_(parent)
+    {
+    
+    }
+    
+
+    template<class T>
+    inline
+    PropSelectItemT<T>::~PropSelectItemT()
+    {
+    }
+
+    template<class T>
+    inline void
+    PropSelectItemT<T>::Insert(PropTree& tree)
+    {
+      QTreeWidgetItem* item = &PropT<T>::GetTreeWidgetItem();
+      tree.addTopLevelItem(item);
+      item->setText(0, Prop::GetLabel());
+      tree.setItemWidget(item,1, &widgetSelect_);
+    }
+
+  
+
+    template<class T>
+    inline void 
+    PropSelectItemT<T>::Init()
+    {
+      widgetSelect_.SetSelectedItem(*PropT<T>::GetCopy().GetPtr());
+    }
+    
+
+   
+    template<class T>
+    inline bool
+    PropSelectItemT<T>::Check()
+    {
+      PropT<T>::GetCopy() = &widgetSelect_.GetSelectedItem();
+      return true;
+    }
+
+
+    template<class T>
+    inline void 
+    PropSelectItemT<T>::SetList(Core::SetOfBase<typename T::PtrType>& set)
+    {
+      widgetSelect_.SetList(set);
+    }
+
+    template<class T>
+    inline  typename T::PtrType&
+    PropSelectItemT<T>::GetSelectedItem()
+    {
+      return widgetSelect_.GetSelectedItem();
+    }
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropString.cpp b/SRC/OpenMeca/Gui/Prop/PropString.cpp
new file mode 100644
index 0000000..5478292
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropString.cpp
@@ -0,0 +1,86 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Gui/Prop/PropString.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    PropString::PropString(QWidget* parent)
+      :PropT<std::string>(*parent),
+       lineEdit_()
+    {
+      lineEdit_.setAttribute(Qt::WA_TranslucentBackground);
+    }
+
+    PropString::~PropString()
+    {
+    }
+
+    void
+    PropString::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      tree.setItemWidget(&item_,1, &lineEdit_);
+    }
+
+    void 
+    PropString::Init()
+    {
+      const std::string value =  PropT<std::string>::GetValue();
+      lineEdit_.setText(value.c_str());
+    }
+    
+    bool
+    PropString::Check()
+    {
+      if (lineEdit_.text().isEmpty())
+	{
+	  QPalette p = lineEdit_.palette();
+	  p.setColor(QPalette::Base, Qt::red);
+	  lineEdit_.setPalette(p);
+	  DisplayHelp("The text is empty !");
+	  return false;
+	}
+      else
+	{
+	  lineEdit_.setPalette(QApplication::palette());
+	  PropT<std::string>::GetCopy() = lineEdit_.text().toStdString();
+	}
+      return true;
+    }
+
+     
+    void 
+    PropString::DisplayHelp(const QString& msg)
+    {
+      QToolTip::showText(lineEdit_.mapToGlobal(QPoint(0,0)), msg);
+    }
+
+
+
+  }
+}
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropString.hpp b/SRC/OpenMeca/Gui/Prop/PropString.hpp
new file mode 100644
index 0000000..550acad
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropString.hpp
@@ -0,0 +1,56 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropString_hpp
+#define OpenMeca_Prop_PropString_hpp
+
+
+#include <QLineEdit>
+
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropString: public PropT<std::string>
+    {
+    public:
+      PropString(QWidget* parent);
+      virtual ~PropString();
+      
+      virtual void Insert(PropTree&);
+      virtual bool Check();
+
+      virtual void DisplayHelp(const QString& message);
+
+    protected:
+      virtual void Init();
+
+    protected:
+      QLineEdit lineEdit_;
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropT.hpp b/SRC/OpenMeca/Gui/Prop/PropT.hpp
new file mode 100644
index 0000000..a922e6e
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropT.hpp
@@ -0,0 +1,155 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Prop_PropBaseT_hpp
+#define OpenMeca_Gui_Prop_PropBaseT_hpp
+
+
+
+#include "OpenMeca/Gui/Prop/Prop.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    template<class T>
+    class PropT : public Prop
+    {
+      
+    public:
+      PropT(QWidget& parent);
+      virtual ~PropT();
+      virtual void SetValue(T&);
+      void ApplyChangement();
+      T& GetCopy();
+      T& GetValue();
+      T& GetInitialValue();
+      void CancelChangement();
+      void Reset();
+      virtual bool Check() = 0;
+      virtual void PostChangement();
+
+    protected:
+      virtual void Init() = 0;
+
+    private:
+      T* val_;
+      T* copy_;
+      T* initialValue_;
+    };
+
+    template<class T>
+    inline
+    PropT<T>::PropT(QWidget & parent)
+      :Prop(parent),
+       val_(0),
+       copy_(0),
+       initialValue_(0)
+    {
+    }
+    
+    template<class T>
+    inline
+    PropT<T>::~PropT()
+    {
+    }
+
+    template<class T>
+    inline T&
+    PropT<T>::GetValue()
+    {
+      OMC_ASSERT_MSG(val_!=0, "The val pointer is null");
+      return *val_;
+    }
+
+
+
+    template<class T>
+    inline void 
+    PropT<T>::SetValue(T& val)
+    {
+      OMC_ASSERT_MSG(val_==0, "The val pointer must be null");
+      OMC_ASSERT_MSG(copy_ == 0, "The copy pointer must be null");
+      OMC_ASSERT_MSG(initialValue_ == 0, "The initial value must be null");
+      val_ = &val;
+      copy_         = new T(val);
+      initialValue_ = new T(val);
+      Init();
+    }
+
+
+    template<class T>
+    inline void     
+    PropT<T>::CancelChangement()
+    {
+      GetValue() = GetInitialValue();
+      GetCopy() = GetValue();
+      Init();
+      PostChangement();
+    }
+
+    template<class T>
+    inline void     
+    PropT<T>::ApplyChangement()
+    {
+      OMC_ASSERT_MSG(Check()==true, "The widget must be valid before applying changement");
+      GetValue() = GetCopy();
+      PostChangement();
+    }
+
+    template<class T>
+    inline void     
+    PropT<T>::Reset()
+    {
+      delete copy_;
+      delete initialValue_;
+      val_          = 0;
+      copy_         = 0;
+      initialValue_ = 0;
+    }
+
+
+    template<class T>
+    inline T&  
+    PropT<T>::GetCopy()
+    {
+      OMC_ASSERT_MSG(copy_ != 0, "The copy can't be null");
+      return *copy_;
+    }
+
+    
+    template<class T>
+    inline T&  
+    PropT<T>::GetInitialValue()
+    {
+      OMC_ASSERT_MSG(initialValue_ != 0, "The initial value can't be null");
+      return *initialValue_;
+    }
+
+    template<class T>
+    inline void 
+    PropT<T>::PostChangement()
+    {
+    }
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Prop/PropTree.cpp b/SRC/OpenMeca/Gui/Prop/PropTree.cpp
new file mode 100644
index 0000000..d3b0917
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropTree.cpp
@@ -0,0 +1,71 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Gui/Dialog/Dialog.hpp"
+#include "OpenMeca/Gui/Prop/Prop.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+  
+    PropTree::PropTree(QWidget* parent)
+      :QTreeWidget(parent),
+       init_(false)
+    {
+     setColumnCount(2);
+     QStringList list = (QStringList() << QObject::tr("Property") << QObject::tr("Value"));
+     setHeaderLabels(list);
+     setStyleSheet("QLineEdit{border: none;background:transparent;} QLineEdit:focus {background:white;}");
+    }
+
+    
+    PropTree::~PropTree()
+    {
+    }
+
+    void 
+    PropTree::Init()
+    {
+      setColumnCount(2);
+      QStringList list = (QStringList() << QObject::tr("Property") << QObject::tr("Value"));
+      setHeaderLabels(list);
+      init_ = true;
+    }
+
+    void 
+    PropTree::Add(Prop& prop)
+    {
+      if (!init_)
+	Init();
+
+      prop.Insert(*this);
+
+      if (topLevelItemCount() % 2 == 0)
+	prop.SetColor(QColor(255, 255, 180));
+      else
+	prop.SetColor(QColor(255, 255, 200));
+    }
+
+  
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Prop/PropTree.hpp b/SRC/OpenMeca/Gui/Prop/PropTree.hpp
new file mode 100644
index 0000000..5b67292
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropTree.hpp
@@ -0,0 +1,53 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_PropTree_hpp 
+#define OpenMeca_Gui_PropTree_hpp 
+
+
+#include <QTreeWidget>
+#include <QWidget>
+
+namespace OpenMeca
+{
+
+  namespace Gui
+  {
+    
+    class Prop;
+
+    class PropTree : public QTreeWidget
+    {
+      
+     public:
+      PropTree(QWidget* parent);
+      virtual ~PropTree();
+      void Add(Prop& );
+      void Init();
+    
+    private:
+      bool init_;
+
+    };
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Prop/PropVector.cpp b/SRC/OpenMeca/Gui/Prop/PropVector.cpp
new file mode 100644
index 0000000..14386a9
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropVector.cpp
@@ -0,0 +1,120 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Prop/PropVector.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    PropVector::PropVector(QWidget* parent)
+      :PropT<Geom::Vector<_3D> >(*parent),
+       itemX_(),
+       itemY_(),
+       itemZ_(),
+       x_(0),
+       y_(0),
+       z_(0)
+    {
+      AddSubItem(&itemX_);
+      AddSubItem(&itemY_);
+      AddSubItem(&itemZ_);
+    }
+
+    PropVector::~PropVector()
+    {
+    }
+
+    
+    void 
+    PropVector::Insert(PropTree& tree)
+    {
+      tree.addTopLevelItem(&item_);
+      item_.setText(0, Prop::GetLabel());
+      
+      item_.addChild(&itemX_);
+      itemX_.setText(0, "X");
+      tree.setItemWidget(&itemX_,1, &x_);
+
+      item_.addChild(&itemY_);
+      itemY_.setText(0, "Y");
+      tree.setItemWidget(&itemY_,1, &y_);
+
+      item_.addChild(&itemZ_);
+      itemZ_.setText(0, "Z");
+      tree.setItemWidget(&itemZ_,1, &z_);
+
+    }
+
+    void 
+    PropVector::SetDimension(const Util::Dimension& dim)
+    {
+      x_.SetDimension(dim);
+      y_.SetDimension(dim);
+      z_.SetDimension(dim);
+    }
+
+
+
+    void 
+    PropVector::Init()
+    {
+      const Geom::Vector<_3D>& p =  PropT<Geom::Vector<_3D> >::GetValue();    
+      x_.SetNumber(p[0]);
+      y_.SetNumber(p[1]);
+      z_.SetNumber(p[2]);
+    }
+    
+
+   
+    bool
+    PropVector::Check()
+    {
+      double x, y, z;
+      bool ok = (x_.GetValue(x) && y_.GetValue(y) && z_.GetValue(z));
+      if (ok)
+	{
+	  Geom::Vector<_3D> &p = PropT<Geom::Vector<_3D> >::GetCopy();
+	  p[0] = x;
+	  p[1] = y;
+	  p[2] = z;
+	}
+      return ok;
+    }
+
+    void 
+    PropVector::AddComponentCondition(const Core::Condition<double>* cond)
+    {
+      x_.AddCondition(cond);
+      y_.AddCondition(cond->Copy());
+      z_.AddCondition(cond->Copy());
+    }
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Prop/PropVector.hpp b/SRC/OpenMeca/Gui/Prop/PropVector.hpp
new file mode 100644
index 0000000..9d70a92
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Prop/PropVector.hpp
@@ -0,0 +1,75 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Prop_PropVector_hpp
+#define OpenMeca_Prop_PropVector_hpp
+
+
+#include <QLabel>
+#include <QLineEdit>
+
+#include "OpenMeca/Gui/Prop/PropT.hpp"
+#include "OpenMeca/Gui/Widget/WidgetDouble.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+#include "OpenMeca/Geom/Vector.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class PropVector: public PropT<Geom::Vector<_3D> >
+    {
+      public:
+      PropVector(QWidget* parent);
+      virtual ~PropVector();
+
+      void Insert(PropTree&);
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool Check();
+      void ApplyValue();
+
+      void AddComponentCondition(const Core::Condition<double>*);
+
+
+    private:
+      void Init();
+
+    private:
+      QTreeWidgetItem itemX_;
+      QTreeWidgetItem itemY_;
+      QTreeWidgetItem itemZ_;
+      WidgetDouble x_;
+      WidgetDouble y_;
+      WidgetDouble z_;
+ 
+   
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/RootTreeItemT.hpp b/SRC/OpenMeca/Gui/RootTreeItemT.hpp
new file mode 100644
index 0000000..bb76411
--- /dev/null
+++ b/SRC/OpenMeca/Gui/RootTreeItemT.hpp
@@ -0,0 +1,73 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_RootTreeItemT_hpp
+#define OpenMeca_Gui_RootTreeItemT_hpp
+
+#include <QTreeWidgetItem>
+#include <QIcon>
+
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+
+    template<class T>
+    class RootTreeItemT
+    {
+    public:
+      static QTreeWidgetItem& Get();
+      
+
+    private:
+      RootTreeItemT();                                 //Not allowed
+      RootTreeItemT(const RootTreeItemT&);             //Not Allowed
+      RootTreeItemT& operator=(const RootTreeItemT&);  //Not Allowed
+
+    private:
+      static QTreeWidgetItem* item_;
+
+    };
+
+    template<class T> QTreeWidgetItem* RootTreeItemT<T>::item_ = 0;
+
+    template<class T>
+    inline QTreeWidgetItem&
+    RootTreeItemT<T>::Get()
+    {
+      if (item_==0)
+	{
+	  QString svgFileName = ":/Rsc/Img/" + QString(T::GetStrType().c_str()) + ".svg";
+	  QIcon icon = Util::Icon::DrawIconFromSvgFile(svgFileName);
+	  item_ = new QTreeWidgetItem();
+	  item_->setIcon(0, icon);
+	  item_->setText(0, T::GetQStrType());
+	  MainWindow::Get().GetTreeView().addTopLevelItem(item_);
+	}
+      return *item_;
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/SecondaryTreeItem.cpp b/SRC/OpenMeca/Gui/SecondaryTreeItem.cpp
new file mode 100644
index 0000000..f8f039b
--- /dev/null
+++ b/SRC/OpenMeca/Gui/SecondaryTreeItem.cpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Gui/SecondaryTreeItem.hpp"
+#include "OpenMeca/Gui/TreeView.hpp"
+#include "OpenMeca/Core/Item.hpp"
+
+namespace OpenMeca
+{
+  
+  namespace Gui
+  {
+
+    SecondaryTreeItem::SecondaryTreeItem(QTreeWidgetItem& parent,
+					 std::function<Core::Item& ()> item)
+      :AbstractTreeItem(&parent),
+       itemFn_(new std::function<Core::Item& ()>(item)),
+       itemPtr_(0)
+    {
+    }
+
+    SecondaryTreeItem::SecondaryTreeItem(QTreeWidgetItem& parent,
+					 Core::Item& item)
+      :AbstractTreeItem(&parent),
+       itemFn_(0),
+       itemPtr_(&item)
+    {
+    }
+
+
+
+
+    SecondaryTreeItem::~SecondaryTreeItem()
+    {
+    }
+
+    Core::Item& 
+    SecondaryTreeItem::GetItem()
+    {
+      if (itemFn_ != 0)
+	{
+	  OMC_ASSERT_MSG(itemPtr_ == 0, "The item pointer is null");
+	  return (*itemFn_)();
+	}
+      OMC_ASSERT_MSG(itemPtr_ != 0, "The item pointer is null");
+      return *itemPtr_;
+    }
+  }
+
+}
diff --git a/SRC/OpenMeca/Gui/SecondaryTreeItem.hpp b/SRC/OpenMeca/Gui/SecondaryTreeItem.hpp
new file mode 100644
index 0000000..1b47137
--- /dev/null
+++ b/SRC/OpenMeca/Gui/SecondaryTreeItem.hpp
@@ -0,0 +1,59 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_SecondaryTreeItem_hpp
+#define OpenMeca_Gui_SecondaryTreeItem_hpp
+
+#include "OpenMeca/Gui/AbstractTreeItem.hpp"
+
+namespace OpenMeca
+{
+  namespace Core
+  {
+    class UserItem;
+  }
+  
+
+  namespace Gui
+  {
+    
+    class SecondaryTreeItem : public AbstractTreeItem
+    {
+    
+    public:
+      SecondaryTreeItem(QTreeWidgetItem& parent, std::function<Core::Item& ()>);
+      SecondaryTreeItem(QTreeWidgetItem& parent, Core::Item& item);
+      ~SecondaryTreeItem();
+
+      Core::Item& GetItem();
+    
+    private:
+      SecondaryTreeItem();                        //Not allowed
+      SecondaryTreeItem(const SecondaryTreeItem&);             //Not Allowed
+      SecondaryTreeItem& operator=(const SecondaryTreeItem&);  //Not Allowed
+
+    private:
+      std::function<Core::Item& ()>* itemFn_;
+      Core::Item* itemPtr_;
+
+    };
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/TreeView.cpp b/SRC/OpenMeca/Gui/TreeView.cpp
new file mode 100755
index 0000000..fa1ad71
--- /dev/null
+++ b/SRC/OpenMeca/Gui/TreeView.cpp
@@ -0,0 +1,100 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QMouseEvent>
+
+#include "OpenMeca/Gui/TreeView.hpp"
+#include "OpenMeca/Gui/AbstractTreeItem.hpp"
+#include "OpenMeca/Core/SelectionManager.hpp"
+#include "OpenMeca/Core/CommonProperty.hpp"
+
+namespace OpenMeca
+{
+  
+  namespace Gui
+  {
+    TreeView::TreeView(QWidget *parent )
+      :QTreeWidget(parent)
+    {
+      AbstractTreeItem::SetTreeView(*this);
+      QObject::connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(ItemSelect()));
+    }
+    
+    TreeView::~TreeView()
+    {
+
+    }
+    
+    void 
+    TreeView::AddAbstractTreeItem(AbstractTreeItem& treeItem)
+    {
+      treeItems_.AddItem(treeItem);
+    }
+
+    void 
+    TreeView::EraseAbstractTreeItem(AbstractTreeItem& treeItem)
+    {
+      treeItems_.RemoveItem(treeItem);
+    }
+
+    void 
+    TreeView::ItemSelect()
+    {
+      QList<QTreeWidgetItem *> list = selectedItems ();
+      if (list.size()==0)
+	{
+	  return;
+	}
+      OMC_ASSERT_MSG(list.size()==1, "The selected item list size must contoin one element");
+      AbstractTreeItem* treeItem = ConvertToAbstractTreeItem(list[0]);
+      if (treeItem != 0)
+	Core::Singleton<Core::SelectionManager>::Get().SetItemSelected(treeItem->GetItem());
+      else
+	Core::Singleton<Core::SelectionManager>::Get().SetNoItemSelected();
+    }
+
+    AbstractTreeItem*
+    TreeView::ConvertToAbstractTreeItem(QTreeWidgetItem* qItem)
+    {
+      AbstractTreeItem* treeItem = static_cast<AbstractTreeItem*>(qItem);
+      if (treeItems_.Contain(treeItem))
+	return treeItem;
+      else
+	return 0;
+    }
+
+    void TreeView::mousePressEvent(QMouseEvent* e)
+    {
+      QTreeWidgetItem* qItem = itemAt(e->pos());
+      AbstractTreeItem* treeItem = ConvertToAbstractTreeItem(qItem);
+      if (treeItem != 0)
+      	{
+      	  if (e->button() == Qt::RightButton)
+      	    {
+      	      Core::Singleton<Core::SelectionManager>::Get().SetItemSelected(treeItem->GetItem());
+      	      Core::CommonProperty::GetClass(treeItem->GetItem().GetStrType()).GetPopUpMenu().popup(mapToGlobal(e->pos()));
+	      return;
+      	    }
+      	}
+      QTreeWidget::mousePressEvent(e);
+    }
+    
+  }
+}
diff --git a/SRC/OpenMeca/Gui/TreeView.hpp b/SRC/OpenMeca/Gui/TreeView.hpp
new file mode 100755
index 0000000..62ff469
--- /dev/null
+++ b/SRC/OpenMeca/Gui/TreeView.hpp
@@ -0,0 +1,61 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#ifndef OpenMeca_Gui_TreeView_hpp
+#define OpenMeca_Gui_TreeView_hpp
+
+#include <QTreeWidget>
+
+#include "OpenMeca/Core/SetOf.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Gui
+  {
+
+    class AbstractTreeItem;
+
+    class TreeView : public QTreeWidget
+    { 
+      Q_OBJECT
+
+    public:
+      TreeView(QWidget * parent);
+      ~TreeView();
+      void AddAbstractTreeItem(AbstractTreeItem&);
+      void EraseAbstractTreeItem(AbstractTreeItem&);
+
+    private slots:
+      void ItemSelect();
+
+    private:
+      AbstractTreeItem* ConvertToAbstractTreeItem(QTreeWidgetItem*);
+      void mousePressEvent(QMouseEvent* e);
+    private:
+      Core::SetOf<AbstractTreeItem> treeItems_;
+      
+    };
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Gui/Viewer.cpp b/SRC/OpenMeca/Gui/Viewer.cpp
new file mode 100755
index 0000000..e9e79c0
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Viewer.cpp
@@ -0,0 +1,203 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QMouseEvent>
+
+#include "OpenMeca/Gui/Viewer.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/SelectionManager.hpp"
+#include "OpenMeca/Core/DrawableUserItem.hpp"
+#include "OpenMeca/Core/CommonProperty.hpp"
+#include "OpenMeca/Setting/Simulation.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+  
+
+    Viewer::Viewer(QWidget * parent)
+      :QGLViewer(parent),
+       rightClick_(false),
+       snapshot_(false),
+       drawAxis_(false)
+    {
+    }
+    
+    Viewer::~Viewer()
+    {
+    }
+
+    void 
+    Viewer::SetSnapShotMode(bool mode)
+    {
+      snapshot_ = mode;
+    }
+
+    void 
+    Viewer::draw()
+    {
+      //glPolygonMode(GL_FRONT,GL_LINE);
+      if (drawAxis_)
+	Geom::Frame<_3D>::Global.Draw();
+            
+      Core::System::Get().Draw();
+    }
+
+
+    void 
+    Viewer::drawWithNames()
+    {
+      Core::System::Get().DrawWithNames();
+    }
+
+    void Viewer::postDraw()
+    {
+      QGLViewer::postDraw();
+      DrawCornerAxis();
+    }
+
+
+    void 
+    Viewer::mousePressEvent(QMouseEvent* e)
+    {
+      Core::Singleton<Core::SelectionManager>::Get().SetNoItemSelected();
+      if (e->button() == Qt::RightButton)
+	rightClick_ = true;
+      else
+	rightClick_ = false;
+
+
+      QGLViewer::mousePressEvent(e);
+    }
+
+    void 
+    Viewer::postSelection(const QPoint& p)
+    {
+      if (selectedName() == -1)
+	Core::Singleton<Core::SelectionManager>::Get().SetNoItemSelected();
+      else
+	{
+	  Core::Singleton<Core::SelectionManager>::Get().SetDrawableItemSelected(selectedName());
+	  Core::UserItem& item = Core::DrawableUserItem::GetDrawableItemByGLKey(selectedName());
+	  if (rightClick_)
+	    Core::CommonProperty::GetClass(item.GetStrType()).GetPopUpMenu().popup(mapToGlobal(p));
+	}
+    }
+
+    void 
+    Viewer::init()
+    {
+      setMouseBinding(Qt::ShiftModifier, Qt::RightButton, SELECT);
+    }
+
+    void 
+    Viewer::animate()
+    {
+      if (snapshot_)
+	saveSnapshot();
+    }
+
+    void
+    Viewer::DrawAxis(bool draw)
+    {
+      drawAxis_ = draw;
+    }
+
+    void 
+    Viewer::DrawText(const std::string& str, const Geom::Point<_3D>& p)
+    {
+      glDisable(GL_LIGHTING);
+      glDisable(GL_DEPTH_TEST);
+      glColor3f(1.0f, 1.0f, 1.0f);
+      const Geom::Point<_3D> p_glob(p, &Geom::Frame<_3D>::GetGlobal);
+      QGLWidget::renderText(p_glob[0], p_glob[1],p_glob[2], str.c_str());
+      glEnable(GL_DEPTH_TEST);
+      glEnable(GL_LIGHTING);
+    }
+    
+
+    void Viewer::DrawCornerAxis()
+    {
+
+      int viewport[4];
+      int scissor[4];
+  
+      // The viewport and the scissor are changed to fit the lower left
+      // corner. Original values are saved.
+      glGetIntegerv(GL_VIEWPORT, viewport);
+      glGetIntegerv(GL_SCISSOR_BOX, scissor);
+  
+      // Axis viewport size, in pixels
+      const int size = 150;
+      glViewport(0,0,size,size);
+      glScissor(0,0,size,size);
+  
+      // The Z-buffer is cleared to make the axis appear over the
+      // original image.
+      glClear(GL_DEPTH_BUFFER_BIT);
+  
+      // Tune for best line rendering
+      glDisable(GL_LIGHTING);
+      glLineWidth(3.0);
+  
+      glMatrixMode(GL_PROJECTION);
+      glPushMatrix();
+      glLoadIdentity();
+      glOrtho(-1, 1, -1, 1, -1, 1);
+  
+      glMatrixMode(GL_MODELVIEW);
+      glPushMatrix();
+      glLoadIdentity();
+      glMultMatrixd(camera()->orientation().inverse().matrix());
+  
+      glBegin(GL_LINES);
+      glColor3f(1.0, 0.0, 0.0);
+      glVertex3f(0.0, 0.0, 0.0);
+      glVertex3f(1.0, 0.0, 0.0);
+  
+      glColor3f(0.0, 1.0, 0.0);
+      glVertex3f(0.0, 0.0, 0.0);
+      glVertex3f(0.0, 1.0, 0.0);
+  
+      glColor3f(0.0, 0.0, 1.0);
+      glVertex3f(0.0, 0.0, 0.0);
+      glVertex3f(0.0, 0.0, 1.0);
+      glEnd();
+
+
+      glMatrixMode(GL_PROJECTION);
+      glPopMatrix();
+  
+      glMatrixMode(GL_MODELVIEW);
+      glPopMatrix();
+  
+      glEnable(GL_LIGHTING);
+  
+      // The viewport and the scissor are restored.
+      glScissor(scissor[0],scissor[1],scissor[2],scissor[3]);
+      glViewport(viewport[0],viewport[1],viewport[2],viewport[3]);
+
+    }
+
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Gui/Viewer.hpp b/SRC/OpenMeca/Gui/Viewer.hpp
new file mode 100755
index 0000000..582ec76
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Viewer.hpp
@@ -0,0 +1,64 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Viewer_hpp
+#define OpenMeca_Gui_Viewer_hpp
+
+#include <QMessageBox>
+#include <QGLViewer/qglviewer.h>
+#include "OpenMeca/Geom/Point.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class Viewer : public QGLViewer
+    {
+      Q_OBJECT
+      
+    public:
+      Viewer(QWidget * parent);
+      ~Viewer();
+      void SetSnapShotMode(bool);
+      void DrawAxis(bool);
+      void DrawText(const std::string&, const Geom::Point<_3D>&);
+      void DrawCornerAxis();
+
+
+    protected :
+      virtual void draw(); 
+      virtual void drawWithNames();
+      virtual void postDraw();
+      virtual void postSelection(const QPoint& point);
+      virtual void init();
+      virtual void animate();
+      virtual void mousePressEvent(QMouseEvent*);
+
+    private:
+      bool rightClick_;
+      bool snapshot_;
+      bool drawAxis_;
+
+      
+    };
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Gui/Widget/Widget.pro b/SRC/OpenMeca/Gui/Widget/Widget.pro
new file mode 100644
index 0000000..109a8c3
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/Widget.pro
@@ -0,0 +1,40 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+FORMS   += Gui/Widget/WidgetScales.ui \ 
+           Gui/Widget/WidgetDouble.ui \
+           Gui/Widget/WidgetExpr.ui \
+           Gui/Widget/WidgetSelectItem.ui
+
+HEADERS += Gui/Widget/WidgetScales.hpp \
+           Gui/Widget/WidgetDouble.hpp \
+           Gui/Widget/WidgetExpr.hpp \
+           Gui/Widget/WidgetEnum.hpp \
+           Gui/Widget/WidgetSelectItem.hpp \
+           Gui/Widget/WidgetSelectItemT.hpp
+
+
+SOURCES += Gui/Widget/WidgetScales.cpp \
+           Gui/Widget/WidgetDouble.cpp \
+           Gui/Widget/WidgetExpr.cpp \
+           Gui/Widget/WidgetEnum.cpp \
+           Gui/Widget/WidgetSelectItem.cpp
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetDouble.cpp b/SRC/OpenMeca/Gui/Widget/WidgetDouble.cpp
new file mode 100644
index 0000000..d43b3e9
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetDouble.cpp
@@ -0,0 +1,149 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QToolTip>
+#include <iostream>
+
+#include "OpenMeca/Gui/Widget/WidgetDouble.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    WidgetDouble::WidgetDouble(QWidget* parent)
+      :QWidget(parent),
+       dim_(0)
+    {
+      Ui::WidgetDouble::setupUi(this);
+    }
+
+    WidgetDouble::~WidgetDouble()
+    {
+      for (unsigned int i = 0; i < condition_.size(); ++i)
+	delete condition_[i];
+    }
+
+    
+    void 
+    WidgetDouble::SetDimension(const Util::Dimension& dim)
+    {
+      dim_ = &dim;
+      unitLabel_->setText(dim_->GetUserChoice().GetSymbol().c_str());
+    }
+
+    const Util::Dimension&
+    WidgetDouble::GetDimension() const
+    {
+      OMC_ASSERT_MSG(dim_!=0, "The widget double has no dimension");
+      return *dim_;
+    }
+
+    void 
+    WidgetDouble::SetNumber(double value)
+    {
+      double val = value/dim_->GetUserChoice().GetFactor();
+      GetLineEdit().setText(QString::number(val));
+    }
+   
+    bool
+    WidgetDouble::GetValue(double& val)
+    {
+      bool conversionOk = false;
+      double curVal = lineEdit_->text().toDouble(&conversionOk);
+      if (conversionOk==false)
+	{
+	  DisplayHelp("This is not a number");
+	}
+      else
+	{
+	  conversionOk = CheckCondition(curVal);
+	  if (conversionOk)
+	    {
+	      lineEdit_->setPalette(QApplication::palette());
+	      val = curVal * dim_->GetUserChoice().GetFactor();
+	    }
+	}
+      return conversionOk;
+    }
+
+    QLineEdit&
+    WidgetDouble::GetLineEdit()
+    {
+      return *lineEdit_;
+    }
+
+    void 
+    WidgetDouble::DisplayHelp(const QString& msg)
+    {
+      QToolTip::showText(mapToGlobal( QPoint( 0, 0 ) ), msg);
+    }
+
+    void 
+    WidgetDouble::AddCondition(const Core::Condition<double>* cond)
+    {
+      condition_.push_back(cond);
+    }
+
+    bool
+    WidgetDouble::CheckCondition(const double& val)
+    {
+      for (unsigned int i = 0; i < condition_.size(); ++i)
+	{
+	  if (condition_[i]->Check(val) == false)
+	    {
+	      DisplayHelp(condition_[i]->ErrorMessage());
+	      return false;
+	    }
+	}
+      return true;
+    }
+
+    QString 
+    WidgetDouble::GetInputString() const
+    {
+      return lineEdit_->text();
+    }
+
+
+  }
+}
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetDouble.hpp b/SRC/OpenMeca/Gui/Widget/WidgetDouble.hpp
new file mode 100644
index 0000000..a6ca983
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetDouble.hpp
@@ -0,0 +1,74 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Widget_WidgetDouble_hpp
+#define OpenMeca_Widget_WidgetDouble_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+
+#include "ui_WidgetDouble.h"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/Condition.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+    class WidgetDouble: public QWidget, 
+			private Ui::WidgetDouble
+    {
+      
+    public:
+      WidgetDouble(QWidget* parent);
+      virtual ~WidgetDouble();
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      bool GetValue(double& val);
+      void ApplyValue();
+      QLineEdit& GetLineEdit();
+
+      void DisplayHelp(const QString& message);
+
+      void SetNumber(double);
+
+      void AddCondition(const Core::Condition<double>*);
+      bool CheckCondition(const double& );
+
+      QString GetInputString() const;
+
+    private:
+      const Util::Dimension* dim_;
+      std::vector< const Core::Condition<double>* > condition_;
+      
+   
+    };
+    
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetDouble.ui b/SRC/OpenMeca/Gui/Widget/WidgetDouble.ui
new file mode 100644
index 0000000..ffcddf6
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetDouble.ui
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>WidgetDouble</class>
+ <widget class="QWidget" name="WidgetDouble">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>493</width>
+    <height>39</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="windowOpacity">
+   <double>0.000000000000000</double>
+  </property>
+  <property name="autoFillBackground">
+   <bool>false</bool>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QLineEdit" name="lineEdit_">
+     <property name="autoFillBackground">
+      <bool>false</bool>
+     </property>
+     <property name="frame">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="unitLabel_">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetEnum.cpp b/SRC/OpenMeca/Gui/Widget/WidgetEnum.cpp
new file mode 100644
index 0000000..8c641bc
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetEnum.cpp
@@ -0,0 +1,51 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <iostream>
+
+#include "OpenMeca/Gui/Widget/WidgetEnum.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+   
+    WidgetEnum::WidgetEnum(QWidget* parent)
+      :QComboBox(parent)
+    {
+    }
+
+    WidgetEnum::~WidgetEnum()
+    {
+    }
+
+
+    void 
+    WidgetEnum::Clear()
+    {
+      while (QComboBox::count() > 0)
+	{
+	  QComboBox::removeItem(0);
+	}
+    }
+    
+  } 
+}
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetEnum.hpp b/SRC/OpenMeca/Gui/Widget/WidgetEnum.hpp
new file mode 100644
index 0000000..bad423e
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetEnum.hpp
@@ -0,0 +1,44 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Prop_WidgetEnum_hpp
+#define OpenMeca_Gui_Prop_WidgetEnum_hpp
+
+
+#include <QComboBox>
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class WidgetEnum :  public QComboBox
+    {
+      Q_OBJECT
+
+    public:
+      WidgetEnum(QWidget* parent);
+      virtual ~WidgetEnum();
+      void Clear();
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetExpr.cpp b/SRC/OpenMeca/Gui/Widget/WidgetExpr.cpp
new file mode 100644
index 0000000..7409d56
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetExpr.cpp
@@ -0,0 +1,151 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QToolTip>
+#include <iostream>
+
+#include "OpenMeca/Gui/Widget/WidgetExpr.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+
+    WidgetExpr::WidgetExpr(QWidget* parent)
+      :QWidget(parent),
+       dim_(0)
+    {
+      Ui::WidgetExpr::setupUi(this);
+    }
+
+    WidgetExpr::~WidgetExpr()
+    {
+      for (unsigned int i = 0; i < condition_.size(); ++i)
+	delete condition_[i];
+    }
+
+    
+    void 
+    WidgetExpr::SetDimension(const Util::Dimension& dim)
+    {
+      dim_ = &dim;
+      unitLabel_->setText(dim_->GetUserChoice().GetSymbol().c_str());
+    }
+
+    const Util::Dimension&
+    WidgetExpr::GetDimension() const
+    {
+      OMC_ASSERT_MSG(dim_!=0, "The widget double has no dimension");
+      return *dim_;
+    }
+
+    void 
+    WidgetExpr::SetExpr(const Util::Expr& expr)
+    {
+      OMC_ASSERT_MSG(dim_ == &expr.GetDimension(),
+		     "The specified dimension are not equals");
+
+      const QString str =  expr.ToString().c_str();
+      GetLineEdit().setText(str);
+      ComputeExpression();
+    }
+   
+    bool
+    WidgetExpr::ComputeExpression()
+    {
+      const std::string exp = GetLineEdit().text().toStdString();
+
+      if (Util::Expr::IsValid(exp) == false)
+	{
+	  DisplayHelp("The expression is not valid");
+	  result_->setText("=#@? ");
+	  return false;
+	}
+      result_->setText("=" + QString::number(Util::Expr::Compute(exp)) + " ");
+      return true;
+    }
+    
+
+    bool
+    WidgetExpr::GetExpr(Util::Expr& val)
+    {
+      const bool expr_ok = ComputeExpression();
+      if (expr_ok)
+	val.SetString(GetLineEdit().text().toStdString());
+      return expr_ok;
+    }
+
+    QLineEdit&
+    WidgetExpr::GetLineEdit()
+    {
+      return *lineEdit_;
+    }
+
+    void 
+    WidgetExpr::DisplayHelp(const QString& msg)
+    {
+      QToolTip::showText(mapToGlobal( QPoint( 0, 0 ) ), msg);
+    }
+
+    void 
+    WidgetExpr::AddCondition(const Core::Condition<double>* cond)
+    {
+      condition_.push_back(cond);
+    }
+
+    bool
+    WidgetExpr::CheckCondition(const double& val)
+    {
+      for (unsigned int i = 0; i < condition_.size(); ++i)
+	{
+	  if (condition_[i]->Check(val) == false)
+	    {
+	      DisplayHelp(condition_[i]->ErrorMessage());
+	      return false;
+	    }
+	}
+      return true;
+    }
+
+
+  }
+}
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetExpr.hpp b/SRC/OpenMeca/Gui/Widget/WidgetExpr.hpp
new file mode 100644
index 0000000..a47cbcb
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetExpr.hpp
@@ -0,0 +1,73 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Widget_WidgetExpr_hpp
+#define OpenMeca_Widget_WidgetExpr_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QLineEdit>
+
+#include "ui_WidgetExpr.h"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/Condition.hpp"
+#include "OpenMeca/Util/Expr.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    
+    class WidgetExpr: public QWidget, 
+		      private Ui::WidgetExpr
+    {
+      
+    public:
+      WidgetExpr(QWidget* parent);
+      virtual ~WidgetExpr();
+      
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      
+      void SetExpr(const Util::Expr& val);
+      bool GetExpr(Util::Expr& val);
+      bool ComputeExpression();
+
+      QLineEdit& GetLineEdit();
+
+      void DisplayHelp(const QString& message);
+
+      
+      void AddCondition(const Core::Condition<double>*);
+      bool CheckCondition(const double& );
+
+    private:
+      const Util::Dimension* dim_;
+      std::vector< const Core::Condition<double>* > condition_;
+      
+   
+    };
+    
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetExpr.ui b/SRC/OpenMeca/Gui/Widget/WidgetExpr.ui
new file mode 100644
index 0000000..bbd044c
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetExpr.ui
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>WidgetExpr</class>
+ <widget class="QWidget" name="WidgetExpr">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>597</width>
+    <height>27</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <property name="windowOpacity">
+   <double>0.000000000000000</double>
+  </property>
+  <property name="autoFillBackground">
+   <bool>false</bool>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="leftMargin">
+    <number>0</number>
+   </property>
+   <property name="topMargin">
+    <number>0</number>
+   </property>
+   <property name="rightMargin">
+    <number>0</number>
+   </property>
+   <property name="bottomMargin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QLineEdit" name="lineEdit_">
+     <property name="autoFillBackground">
+      <bool>false</bool>
+     </property>
+     <property name="frame">
+      <bool>false</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="result_">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="unitLabel_">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetScales.cpp b/SRC/OpenMeca/Gui/Widget/WidgetScales.cpp
new file mode 100644
index 0000000..0691004
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetScales.cpp
@@ -0,0 +1,112 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Gui/Widget/WidgetScales.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    WidgetScales::WidgetScales(QWidget* parent)
+      :QWidget(parent),
+       editScale_(new QAction(QString("Edit Scale"), this)),
+       index_()
+    {
+      Ui::WidgetScales::setupUi(this);
+
+      QObject::connect(doubleSpinBox_, SIGNAL(valueChanged(double)), 
+		       this, SLOT(ValueChanged(double)));
+      
+      QObject::connect(label_, SIGNAL(currentIndexChanged(const QString&)), 
+		       this, SLOT(ScaleChanged(const QString&)));
+      
+
+      OpenMeca::Setting::Scales& scales = Core::System::Get().GetScales();
+      scales.SetWidget(*this);
+
+      std::vector<std::string> vec = scales.GetKeys();
+      for (unsigned int i=0; i < vec.size(); i++)
+	{
+	  index_[i] = vec[i];
+	  label_->addItem(QObject::tr(vec[i].c_str()));
+	}
+      Update();
+    }
+
+    WidgetScales::~WidgetScales()
+    {
+    }
+
+    double& 
+    WidgetScales::GetScaleValue()
+    {
+      const int i = label_->currentIndex();
+      OMC_ASSERT_MSG(index_.count(i)==1, "The scale has no index");
+      return Core::System::Get().GetScales().GetScaleValue(index_[i]);
+    }
+    
+    void 
+    WidgetScales::UpdateStep()
+    {
+      doubleSpinBox_->setSingleStep(GetScaleValue()*100./2.);
+    }
+
+    void 
+    WidgetScales::Update()
+    {
+      QObject::disconnect(doubleSpinBox_, SIGNAL(valueChanged(double)), this, SLOT(ValueChanged(double)));
+      doubleSpinBox_->setValue(GetScaleValue()*100.);
+      UpdateStep();
+      QObject::connect(doubleSpinBox_, SIGNAL(valueChanged(double)), this, SLOT(ValueChanged(double)));
+    }
+
+    void 
+    WidgetScales::ScaleChanged(const QString&)
+    {
+      Update();
+    }
+
+
+    void
+    WidgetScales::ValueChanged(double currentValue)
+    {
+      GetScaleValue() = currentValue/100.;
+      UpdateStep();
+      IsEdited();
+    }
+   
+    void
+    WidgetScales::IsEdited()
+    {
+      Core::System::Get().GetHistoric().SystemEdited();
+      MainWindow::Get().AddToHistoric(*editScale_);
+      MainWindow::Get().GetViewer().updateGL(); 
+    }
+
+
+  }
+}
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetScales.hpp b/SRC/OpenMeca/Gui/Widget/WidgetScales.hpp
new file mode 100644
index 0000000..76b01dd
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetScales.hpp
@@ -0,0 +1,66 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Widget_WidgetScales_hpp
+#define OpenMeca_Widget_WidgetScales_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+
+#include "ui_WidgetScales.h"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class WidgetScales: public QWidget, 
+			private Ui::WidgetScales
+    {
+      Q_OBJECT
+      
+      public:
+      WidgetScales(QWidget* parent);
+      virtual ~WidgetScales();
+      
+      void Update();
+      void IsEdited();	 
+      double& GetScaleValue();
+		     
+		     
+    private slots:
+      void ValueChanged(double currentValue);
+      void ScaleChanged(const QString&);
+
+    private:
+      void UpdateStep();
+      
+    private:
+      QAction* editScale_;
+      std::map<int, std::string> index_;
+      
+    };
+    
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetScales.ui b/SRC/OpenMeca/Gui/Widget/WidgetScales.ui
new file mode 100644
index 0000000..af83d7b
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetScales.ui
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>WidgetScales</class>
+ <widget class="QWidget" name="WidgetScales">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>292</width>
+    <height>41</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QComboBox" name="label_"/>
+     </item>
+     <item>
+      <widget class="QDoubleSpinBox" name="doubleSpinBox_">
+       <property name="suffix">
+        <string>%</string>
+       </property>
+       <property name="maximum">
+        <double>100000.000000000000000</double>
+       </property>
+       <property name="value">
+        <double>100.000000000000000</double>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.cpp b/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.cpp
new file mode 100644
index 0000000..afc6003
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.cpp
@@ -0,0 +1,93 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QApplication>
+#include <iostream>
+
+#include "OpenMeca/Core/SelectionManager.hpp"
+#include "OpenMeca/Gui/Widget/WidgetSelectItem.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+   
+    WidgetSelectItem::WidgetSelectItem(QWidget* parent)
+      :QWidget(parent)
+    {
+      Ui::WidgetSelectItem::setupUi(this);
+
+      QObject::connect(&Core::Singleton<Core::SelectionManager>::Get(), 
+		       SIGNAL(ItemSelected(Core::Item&)), 
+		       this, SLOT(ItemSelected(Core::Item&)));
+      
+    }
+
+    WidgetSelectItem::~WidgetSelectItem()
+    {
+      QObject::disconnect(&Core::Singleton<Core::SelectionManager>::Get(), 0, this, 0);      
+    }
+
+    void
+    WidgetSelectItem::ItemSelected(Core::Item& item)
+    {
+      ItemSelected_CallBack(item);
+    }
+
+    void 
+    WidgetSelectItem::ClearComboBox()
+    {
+      while (comboBox_->count() > 0)
+	{
+	  comboBox_->removeItem(0);
+	}
+    }
+
+    QComboBox& 
+    WidgetSelectItem::GetComboBox()
+    {
+      return *comboBox_;
+    }
+
+  
+
+    void 
+    WidgetSelectItem::showEvent(QShowEvent *event)
+    {
+      QObject::connect(&Core::Singleton<Core::SelectionManager>::Get(), 
+		       SIGNAL(ItemSelected(Core::Item&)), 
+		       this, SLOT(ItemSelected(Core::Item&)));
+      
+      QWidget::showEvent(event);
+    }
+
+
+    void 
+    WidgetSelectItem::hideEvent(QHideEvent *event)
+    {
+      QObject::disconnect(&Core::Singleton<Core::SelectionManager>::Get(), 0, this, 0);
+      QWidget::hideEvent(event);
+    }
+
+    
+  } 
+}
+
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.hpp b/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.hpp
new file mode 100644
index 0000000..1ed4ed6
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.hpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Gui_Widget_WidgetSelectItem_hpp
+#define OpenMeca_Gui_Widget_WidgetSelectItem_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QComboBox>
+
+#include "OpenMeca/Core/Item.hpp"
+#include "ui_WidgetSelectItem.h"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class WidgetSelectItem :  public QWidget,
+			      private Ui::WidgetSelectItem
+    {
+      Q_OBJECT
+
+      public:
+      WidgetSelectItem(QWidget* parent);
+      virtual ~WidgetSelectItem();
+      QComboBox& GetComboBox();							     
+
+    protected:
+      virtual void ItemSelected_CallBack(Core::Item&) = 0;
+      void ClearComboBox();
+      
+      virtual void hideEvent(QHideEvent *event);
+      virtual void showEvent(QShowEvent *event);
+
+    public slots:
+      void ItemSelected(Core::Item&);
+
+    };
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.ui b/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.ui
new file mode 100644
index 0000000..d384781
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetSelectItem.ui
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<ui version="4.0">
+ <class>WidgetSelectItem</class>
+ <widget class="QWidget" name="WidgetSelectItem">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>493</width>
+    <height>39</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <property name="windowOpacity">
+   <double>0.000000000000000</double>
+  </property>
+  <property name="autoFillBackground">
+   <bool>false</bool>
+  </property>
+  <layout class="QHBoxLayout" name="horizontalLayout_2">
+   <property name="spacing">
+    <number>0</number>
+   </property>
+   <property name="margin">
+    <number>0</number>
+   </property>
+   <item>
+    <widget class="QComboBox" name="comboBox_"/>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/SRC/OpenMeca/Gui/Widget/WidgetSelectItemT.hpp b/SRC/OpenMeca/Gui/Widget/WidgetSelectItemT.hpp
new file mode 100644
index 0000000..d7d5b9a
--- /dev/null
+++ b/SRC/OpenMeca/Gui/Widget/WidgetSelectItemT.hpp
@@ -0,0 +1,166 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Widget_WidgetSelectItemT_hpp
+#define OpenMeca_Widget_WidgetSelectItemT_hpp
+
+
+#include <QWidget>
+#include <QBoxLayout>
+#include <QLabel>
+#include <QComboBox>
+
+
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/Item.hpp"
+#include "OpenMeca/Gui/Widget/WidgetSelectItem.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    template<class T>
+    class WidgetSelectItemT: public WidgetSelectItem
+    {
+      
+    public:
+      WidgetSelectItemT(QWidget* parent);
+      virtual ~WidgetSelectItemT();
+
+      void ApplyValue();
+      typename T::PtrType& GetSelectedItem();
+      void SetSelectedItem(typename T::PtrType&);
+
+      void SetList(Core::SetOfBase<typename T::PtrType>& set);
+
+    private:
+      void UpdateComboBox();
+      typename T::PtrType& GetItemAtIndex(int i);
+      int GetIndexForItem(typename T::PtrType& item);
+      void ItemSelected_CallBack(Core::Item&);
+
+
+    private:
+      std::map<unsigned int, typename T::PtrType*> map_;
+      Core::SetOfBase<typename T::PtrType> set_;
+    };
+
+
+    template<class T>
+    inline
+    WidgetSelectItemT<T>::WidgetSelectItemT(QWidget* parent)
+      :WidgetSelectItem(parent),
+       map_(),
+       set_()
+    {
+    
+    }
+    
+
+    template<class T>
+    inline
+    WidgetSelectItemT<T>::~WidgetSelectItemT()
+    {
+    }
+
+    template<class T>
+    inline void 
+    WidgetSelectItemT<T>::SetList(Core::SetOfBase<typename T::PtrType>& set)
+    {
+      set_ = set;
+      UpdateComboBox();
+    }
+
+
+    template<class T>
+    inline typename T::PtrType& 
+    WidgetSelectItemT<T>::GetItemAtIndex(int i)
+    {
+      OMC_ASSERT_MSG(map_.count(i)==1, "There is not any item registered at this index");
+      return *map_[i];
+    }
+
+    template<class T>
+    inline int
+    WidgetSelectItemT<T>::GetIndexForItem(typename T::PtrType& item)
+    {
+      typename std::map<unsigned int, typename T::PtrType*>::iterator it;
+      for ( it=map_.begin() ; it != map_.end(); it++ )
+	{
+	  if ((*it).second == &item)
+	    return (*it).first;
+	}
+      OMC_ASSERT_MSG(0, "Can't find item");
+      return -1;
+    }
+    
+
+    template<class T>
+    inline void 
+    WidgetSelectItemT<T>::UpdateComboBox()
+    {
+      WidgetSelectItem::ClearComboBox();
+      typename std::list<typename T::PtrType*>::iterator it;
+      unsigned int index = 0;
+      map_.clear();
+      for (it=set_.Begin() ; it != set_.End(); it++ )
+	{
+	  map_[index] = *it;
+	  const typename T::PtrType& item = **it;
+	  WidgetSelectItem::GetComboBox().addItem(item.GetIcon(), item.GetName().c_str());
+	  index ++;
+	}
+      
+    }
+    
+
+    template<class T>
+    inline void 
+    WidgetSelectItemT<T>::SetSelectedItem(typename T::PtrType& ptr)
+    {
+      UpdateComboBox();
+      const int currentIndex = GetIndexForItem(ptr);
+      WidgetSelectItem::GetComboBox().setCurrentIndex(currentIndex);
+    }
+
+
+    template<class T>
+    inline typename T::PtrType&
+    WidgetSelectItemT<T>::GetSelectedItem()
+    {
+      return GetItemAtIndex(WidgetSelectItem::GetComboBox().currentIndex());
+    }
+
+    template<class T>
+    inline void 
+    WidgetSelectItemT<T>::ItemSelected_CallBack(Core::Item& item)
+    {
+      if (typeid(typename T::PtrType)==typeid(item))
+	{
+	  typename T::PtrType& cast = static_cast<typename T::PtrType&>(item);
+	  WidgetSelectItem::GetComboBox().setCurrentIndex(GetIndexForItem(cast));
+	}
+    }
+
+  }
+}
+#endif
+
diff --git a/SRC/OpenMeca/Info.txt b/SRC/OpenMeca/Info.txt
new file mode 100644
index 0000000..0825809
--- /dev/null
+++ b/SRC/OpenMeca/Info.txt
@@ -0,0 +1,6 @@
+Project   : openmeca
+Authors   : Damien ANDRE (and some patches written by Cedric HUBERT)
+Version   : 2.2.5
+Licence   : GPL v3
+Contact   : openmeca at yakuru.fr
+Copyright : 2012-2017, Damien ANDRE
diff --git a/SRC/OpenMeca/Item/Body.cpp b/SRC/OpenMeca/Item/Body.cpp
new file mode 100644
index 0000000..c0697e2
--- /dev/null
+++ b/SRC/OpenMeca/Item/Body.cpp
@@ -0,0 +1,415 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QSvgRenderer>
+
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Item/PartUser.hpp"
+#include "OpenMeca/Item/PartUserPoint.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Core/UserRootItemCommonProperty.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Viewer.hpp"
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Item::Body)
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    void
+    Body::Init()
+    {
+      Core::Singleton< Core::UserRootItemCommonProperty<Body> >::Get().CreateAction_All();
+    }
+     
+  
+
+      
+    Body::Body()
+      :Core::UserRootItem(Body::GetStrType(), Core::Singleton< Core::UserRootItemCommonProperty<Body> >::Get().GetRootTreeWidgetItem()),
+       chBodyPtr_(0),
+       color_(),
+       mass_(1.),
+       center_(0., 0., 0.), 
+       quaternion_(0., 0., 0., 1.),
+       frame_(center_, quaternion_),
+       massCenter_(0., 0., 0., std::bind(GetFnPtrCstFrame(&Body::GetFrame), std::ref(*this))), 
+       inertia_(1.,0.,0., 0.,1.,0., 0.,0.,1.),
+       fixed_(false),
+       showReferenceFrame_(false),
+      staticFrictionCoef_(0.6),
+      slidingFrictionCoef_(0.6),
+      showMassCenter_(false)
+    {
+    }
+
+    Body::~Body()
+    {
+      // When deleting the chBodyPtr_ attribute, 
+      // chronoengine automatically delete the chBody_ attribute
+    }
+
+
+    void
+    Body::Draw()
+    {
+      if (showReferenceFrame_ || showMassCenter_)
+	{
+	  GetFrame().UpdateGLMatrix();
+	  glPushMatrix();
+	  glMultMatrixd(GetFrame().GetGLMatrix());
+
+	  if (showReferenceFrame_)
+	    GetFrame().Draw();
+
+	  if (showMassCenter_)
+	    {
+	      glDisable(GL_LIGHTING);
+	      glDisable(GL_DEPTH_TEST);
+	      glPointSize(5.0f);
+	      glColor3f(1.0f, 0.0f, 0.0f);
+	      glBegin(GL_POINTS);
+	      glVertex3f(massCenter_[0], massCenter_[1], massCenter_[2]);
+	      glEnd();
+	      glEnable(GL_DEPTH_TEST);
+	      glEnable(GL_LIGHTING);
+	    }
+	  glPopMatrix();
+	}
+      
+      if (showMassCenter_)
+	{
+	  const std::string str = "G_" + GetName();
+	  Gui::MainWindow::Get().GetViewer().DrawText(str, massCenter_);
+	}
+
+    }
+
+
+    const OpenMeca::Item::Body& 
+    Body::GetBody() const
+    {
+      return *this;
+    }
+
+    OpenMeca::Item::Body& 
+    Body::GetBody()
+    {
+      return *this;
+    }
+    
+
+    void 
+    Body::ToggleFix()
+    {
+      fixed_ = !fixed_;
+    }
+
+    const bool& 
+    Body::IsReferenceFrameShown() const
+    {
+      return showReferenceFrame_;
+    }
+
+    bool& 
+    Body::IsReferenceFrameShown()
+    {
+      return showReferenceFrame_;
+    }
+
+    const bool& 
+    Body::IsMassCenterShown() const
+    {
+      return showMassCenter_;
+    }
+
+    bool& 
+    Body::IsMassCenterShown()
+    {
+      return showMassCenter_;
+    }
+
+    void 
+    Body::ToggleShowReferenceFrame()
+    {
+      showReferenceFrame_ = !showReferenceFrame_;
+    }
+
+    void 
+    Body::UpdateIcon()
+    {
+      Body::DrawIcon(GetIcon(), color_.GetQColor(), fixed_);
+    }
+
+    Core::SetOfBase<Part> 
+    Body::GetParts()
+    {
+      Core::SetOfBase<Part> set;
+      Core::SetOfBase<Part>::it it;
+      Core::SetOf<Part>& partSet = Core::AutoRegister<Part>::GetGlobalSet();
+      for (it=partSet.Begin() ; it != partSet.End(); it++ )
+	{
+	  if (&(*it)->GetBody() == this)
+	    set.AddItem(**it);
+	}
+      return set;
+    }
+
+    Core::SetOfBase<Core::UserItem> 
+    Body::GetAssociatedSelectedItem()
+    {
+      Core::SetOfBase<Core::UserItem> itemSet;
+      Core::SetOfBase<Part> partSet = GetParts();
+      Core::SetOf<Part>::it it;
+      for (it=partSet.Begin() ; it != partSet.End(); it++ )
+	itemSet.AddItem(**it);
+
+      return itemSet;
+    }
+
+
+    void 
+    Body::DrawIcon(QIcon& icon, QColor color, bool fixed)
+    {
+      // Read svg icon file
+      QSvgRenderer* svgRenderer = 0;
+      if (fixed)
+	svgRenderer = new QSvgRenderer(Util::Icon::ChangeColorInSvgFile(":/Rsc/Img/Body-ground.svg", Qt::red, color));
+      else
+	svgRenderer = new QSvgRenderer(Util::Icon::ChangeColorInSvgFile(":/Rsc/Img/Body.svg", Qt::red, color));
+
+      // render it on pixmap and translate to icon
+      const int size = Gui::MainWindow::Get().GetIconSize();
+      QPixmap pixmap(QSize(size,size));
+      pixmap.fill(QColor (0, 0, 0, 0));
+      QPainter painter(&pixmap);
+      svgRenderer->render( &painter);
+      icon =  QIcon(pixmap);
+      delete svgRenderer;
+    }
+
+    chrono::ChSharedBodyPtr& 
+    Body::GetChBodyPtr()
+    {
+      OMC_ASSERT_MSG(chBodyPtr_ != 0, "The required pointer is null");
+      return chBodyPtr_;
+    }
+
+    const chrono::ChSharedBodyPtr& 
+    Body::GetChBodyPtr() const
+    {
+      OMC_ASSERT_MSG(chBodyPtr_ != 0, "The required pointer is null");
+      return chBodyPtr_;
+    }
+    
+    void
+    Body::InitChSystem(chrono::ChSystem& chSystem)
+    {
+      chBodyPtr_ = chrono::ChSharedBodyPtr(new chrono::ChBody());
+      chSystem.AddBody(chBodyPtr_);
+    }
+
+    void
+    Body::BuildChSystem(chrono::ChSystem&)
+    {
+      OMC_ASSERT_MSG(chBodyPtr_ != 0, "The required pointer is null");
+    
+      if (GetFixed())
+	chBodyPtr_->SetBodyFixed(true);
+
+      chBodyPtr_->SetMass(mass_);
+      chBodyPtr_->SetPos(massCenter_.ToChVector());
+      chBodyPtr_->SetRot(quaternion_.ToChQuaternion());
+
+      chrono::ChMatrix33<double> inertia = inertia_.ToChMatrix();
+      chBodyPtr_->SetInertia(&inertia);
+
+      chBodyPtr_->GetMaterialSurface()->SetSfriction(staticFrictionCoef_); 	
+      chBodyPtr_->GetMaterialSurface()->SetKfriction(slidingFrictionCoef_); 	
+    }
+
+    void
+    Body::UpdateValueFromCh()
+    {
+      chrono::ChFrame<double>& chFrame = chBodyPtr_->GetFrame_COG_to_abs();
+      const chrono::ChVector<double> pos = -massCenter_.GetPositionVector().ToChVector();
+      
+      const chrono::ChQuaternion<double>& chRot = chFrame.GetRot();
+      center_     = chFrame.TransformPointLocalToParent(pos);
+      quaternion_ = chRot;
+
+      // massCenter_ = chFrame.GetPos();
+      // quaternionMassCenter_ = chRot;
+    }
+
+
+    void 
+    Body::InitAndManageState() 
+    {
+      OMC_ASSERT_MSG(center_.GetStateNumber() <= 1,
+		     "Problem with registered state, they must be inferior or equal to one");
+      OMC_ASSERT_MSG(quaternion_.GetStateNumber() <= 1,
+		     "Problem with registered state, they must be inferior or equal to one");
+
+      if (center_.GetStateNumber() == 1)
+	center_.SetAsFirstState();
+
+      if (quaternion_.GetStateNumber() == 1)
+	quaternion_.SetAsFirstState();
+
+    }
+
+
+    void
+    Body::SaveState()
+    {
+      center_.SaveState();
+      quaternion_.SaveState();
+    }
+
+    void
+    Body::ResetState()
+    {
+      center_.ResetState();
+      quaternion_.ResetState();
+    }
+
+    void 
+    Body::RecoveryState(unsigned int num)
+    {
+      center_.RecoveryState(num);
+      quaternion_.RecoveryState(num);
+    }
+
+    chrono::ChVector<> 
+    Body::ExpressPointInLocalChFrame(const Geom::Point<_3D>& p) const
+    {
+      OMC_ASSERT_MSG(p.GetFrame() == frame_,
+		     "The point must be expressed in local frame coordinate");
+      chrono::ChVector<> chp = p.GetPositionVector().ToChVector() - 
+	GetMassCenter().GetPositionVector().ToChVector();
+      return chp;
+    }
+
+  }
+
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    QString
+    ActionFixBody::Text()
+    {
+      return Action::tr("Fix/Unfix");
+    }
+
+    std::string
+    ActionFixBody::Id()
+    {
+      return "Fix/Unfix";
+    }
+
+    QIcon
+    ActionFixBody::Icon()
+    {
+      QIcon icon;
+      OpenMeca::Item::Body::DrawIcon(icon, Qt::gray, true);
+      return icon;
+    }
+
+    void
+    ActionFixBody::DoAction(OpenMeca::Item::Body& body, Action& action)
+    {
+      body.ToggleFix();
+      Core::System::Get().Update();
+      Core::System::Get().GetHistoric().SystemEdited();
+      Gui::MainWindow::Get().AddToHistoric(action);
+    }
+
+    QString
+    ActionShowRefBody::Text()
+    {
+      return Action::tr("Show/Unshow local frame");
+    }
+
+    std::string
+    ActionShowRefBody::Id()
+    {
+      return "Show/Unshow local frame";
+    }
+
+
+    QIcon
+    ActionShowRefBody::Icon()
+    {
+      return Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Frame.svg");
+    }
+
+    void
+    ActionShowRefBody::DoAction(OpenMeca::Item::Body& body, Action& action)
+    {
+      body.ToggleShowReferenceFrame();
+      Core::System::Get().Update();
+      Core::System::Get().GetHistoric().SystemEdited();
+      Gui::MainWindow::Get().AddToHistoric(action);
+    }
+
+    
+
+    template<>
+    void 
+    UserItemCommonProperty<OpenMeca::Item::Body>::CreateAction_Specialized() 
+    {
+      Action& fixAction = 
+	*new ActionWithSelectedItemT<OpenMeca::Item::Body, ActionFixBody >();
+      CommonProperty::AddAction(fixAction);
+      CommonProperty::AddPopUpAction(fixAction);
+
+      Action& showRefAction = 
+	*new ActionWithSelectedItemT<OpenMeca::Item::Body, ActionShowRefBody >();
+      CommonProperty::AddAction(showRefAction);
+      CommonProperty::AddPopUpAction(showRefAction);
+
+      AddPopUpSeparator();
+      
+      // don't forget to instanciate 
+      Core::Singleton< Core::UserItemCommonProperty<OpenMeca::Item::PartUserPoint> >::Instanciate();
+      CreateAction_NewWithSelection<OpenMeca::Item::PartUserPoint>();
+    }
+
+
+    
+
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Item/Body.hpp b/SRC/OpenMeca/Item/Body.hpp
new file mode 100644
index 0000000..f8b87d5
--- /dev/null
+++ b/SRC/OpenMeca/Item/Body.hpp
@@ -0,0 +1,243 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Body_hpp
+#define OpenMeca_Item_Body_hpp
+
+#include "OpenMeca/Core/UserRootItem.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+#include "OpenMeca/Gui/Dialog/DialogBody.hpp"
+#include "OpenMeca/Util/Color.hpp"
+
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+#include "OpenMeca/Geom/Matrix.hpp"
+
+#include "ChronoEngine/physics/ChBody.h"
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    class Action;
+  }
+}
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    class Part;
+    class PartUser;
+
+    // The physical rigid body
+    class Body: public Core::UserRootItem, public Core::AutoRegister<Body>
+    {
+    
+    public:
+      static const std::string GetStrType() {return "Body";}; 
+      static const QString GetQStrType() {return QObject::tr("Body");}; 
+      static void Init();
+
+      friend class  Gui::DialogBody;
+      typedef Gui::DialogBody Dialog;
+
+      typedef  const Geom::Frame<_3D>&(Body::*GetFnPtrCstFrame)() const;   
+
+      static void DrawIcon(QIcon&, QColor, bool fixed);
+      
+    public:
+      Body();
+      ~Body();
+
+      void Draw();
+    
+
+      const OpenMeca::Item::Body& GetBody() const;
+      OpenMeca::Item::Body& GetBody();
+
+      void ToggleFix();
+
+      const bool& IsReferenceFrameShown() const;
+      bool& IsReferenceFrameShown();
+      const bool& IsMassCenterShown() const;
+      bool& IsMassCenterShown();
+      void ToggleShowReferenceFrame();
+      
+      Core::SetOfBase<Part> GetParts();
+
+      template<class T> Core::SetOfBase<T> GetChildSet();
+
+      void InitAndManageState();
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+
+      // Chrono::Engine management
+      void InitChSystem(chrono::ChSystem&);
+      void BuildChSystem(chrono::ChSystem&);
+      void UpdateValueFromCh();
+
+      chrono::ChVector<> ExpressPointInLocalChFrame(const Geom::Point<_3D>&) const; 
+
+      //Accessor
+      OMC_ACCESSOR    (Mass           , double                 , mass_           );
+      OMC_ACCESSOR    (Inertia        , Geom::Matrix<_3D>      , inertia_        );
+      OMC_ACCESSOR    (Quaternion     , Geom::Quaternion<_3D>  , quaternion_     );
+      OMC_ACCESSOR    (Frame          , Geom::Frame<_3D>       , frame_          );
+      OMC_ACCESSOR    (MassCenter     , Util::ExprPoint        , massCenter_     );
+      OMC_ACCESSOR    (Color          , Util::Color            , color_     );
+      OMC_ACCESSOR    (Fixed          , bool                   , fixed_     );
+      OMC_ACCESSOR    (StaticFrictionCoef , double, staticFrictionCoef_ );
+      OMC_ACCESSOR    (SlidingFrictionCoef, double, slidingFrictionCoef_);
+
+      chrono::ChSharedBodyPtr& GetChBodyPtr();
+      const chrono::ChSharedBodyPtr& GetChBodyPtr() const;
+
+    private:
+      Body(const Body&);             //Not Allowed
+      Body& operator=(const Body&);  //Not Allowed
+
+      void UpdateIcon();
+      Core::SetOfBase<Core::UserItem> GetAssociatedSelectedItem();
+      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      chrono::ChSharedBodyPtr chBodyPtr_;
+      Util::Color color_;
+      double mass_;
+      Geom::Point<_3D> center_;
+      Geom::Quaternion<_3D> quaternion_;
+      Geom::Frame<_3D> frame_;
+      Util::ExprPoint massCenter_;
+      Geom::Matrix<_3D> inertia_;
+      bool fixed_;
+      bool showReferenceFrame_;  
+      double staticFrictionCoef_;
+      double slidingFrictionCoef_;
+      bool showMassCenter_;  
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Body::serialize(Archive & ar, const unsigned int version)
+      {
+	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Core::UserRootItem);
+	ar & BOOST_SERIALIZATION_NVP(color_);
+	ar & BOOST_SERIALIZATION_NVP(mass_);
+	if (version >= 2)
+	  ar & BOOST_SERIALIZATION_NVP(massCenter_);
+	else
+	  {
+	    Geom::Point<_3D> p(std::bind(GetFnPtrCstFrame(&Body::GetFrame), std::ref(*this)));
+	    ar & BOOST_SERIALIZATION_NVP(p);
+	    massCenter_ = p;
+	  }
+	ar & BOOST_SERIALIZATION_NVP(quaternion_);
+	ar & BOOST_SERIALIZATION_NVP(inertia_);
+	ar & BOOST_SERIALIZATION_NVP(fixed_);
+	ar & BOOST_SERIALIZATION_NVP(showReferenceFrame_);
+	if (version >= 1)
+	  {
+	    ar & BOOST_SERIALIZATION_NVP(center_);
+	    ar & BOOST_SERIALIZATION_NVP(staticFrictionCoef_);
+	    ar & BOOST_SERIALIZATION_NVP(slidingFrictionCoef_);
+	  }
+	if (version >= 3)
+	  {
+	    ar & BOOST_SERIALIZATION_NVP(showMassCenter_);
+	  }
+      }
+
+    template<class T>
+    inline Core::SetOfBase<T>
+    Body::GetChildSet()
+    {
+      Core::SetOfBase<UserItem> all;
+      UserItem::ConcatenateDependentItems(all);
+      Core::SetOf<UserItem>::it it;
+      Core::SetOfBase<T> childs;
+      for (it=all.Begin() ; it != all.End(); it++ )
+	{
+	  T* ptr = 0;
+	  ptr = dynamic_cast<T*>(*it);
+	  if (ptr != 0 && &ptr->GetBody() == this)
+	    childs.AddItem(*ptr);
+	}
+      return childs;
+    }
+
+
+  }
+
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::Body>::BuildIconSymbol()
+    {
+      QIcon icon;
+      OpenMeca::Item::Body::DrawIcon(iconSymbol_, Qt::gray, false);
+    }
+
+
+    class ActionFixBody
+    {
+    public:
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      static void DoAction(OpenMeca::Item::Body&, Action& action);
+    };
+
+    class ActionShowRefBody
+    {
+    public:
+      static QString Text();
+      static std::string Id();
+      static QIcon Icon();
+      static void DoAction(OpenMeca::Item::Body&, Action& action);
+    };
+
+  }
+}
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Item::Body, 3)
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetAngAcc.cpp b/SRC/OpenMeca/Item/How/GetAngAcc.cpp
new file mode 100644
index 0000000..509f5da
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetAngAcc.cpp
@@ -0,0 +1,72 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetAngAcc.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetAngAcc::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetAngAcc::GetStrType()
+      {
+	return Physic::AngularAcceleration::GetStrType();
+      }
+
+      const QString
+      GetAngAcc::GetQStrType()
+      {
+	return Physic::AngularAcceleration::GetQStrType();
+      }
+
+      Geom::Vector<_3D> 
+      GetAngAcc::Acquire(MySensor& sensor)
+      {
+	PartPoint& parent =  sensor.GetParent();
+	Body& body = const_cast<Body&>(parent.GetBody());
+	
+	chrono::ChSharedBodyPtr& chbody = 
+	  const_cast<chrono::ChSharedBodyPtr&>(body.GetChBodyPtr());
+	
+	chrono::ChVector<> v = chbody->GetWacc_par();
+	return Geom::Vector<_3D>(v);
+
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetAngAcc.hpp b/SRC/OpenMeca/Item/How/GetAngAcc.hpp
new file mode 100644
index 0000000..383a178
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetAngAcc.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetAngAcc_hpp_
+#define _OpenMeca_Item_How_GetAngAcc_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/AngularAcceleration.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetAngAcc
+      {
+	typedef SensorT<PartPoint, Physic::AngularAcceleration, GetAngAcc> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static Geom::Vector<_3D> Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+   
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetAngAcc::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetAngAcc::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetAngPos.cpp b/SRC/OpenMeca/Item/How/GetAngPos.cpp
new file mode 100644
index 0000000..daeb3db
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetAngPos.cpp
@@ -0,0 +1,70 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetAngPos.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetAngPos::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetAngPos::GetStrType()
+      {
+	return Physic::AngularPosition::GetStrType();
+      }
+
+      const QString
+      GetAngPos::GetQStrType()
+      {
+	return Physic::AngularPosition::GetQStrType();
+      }
+
+      double
+      GetAngPos::Acquire(MySensor& sensor)
+      {
+	PartPoint& parent =  sensor.GetParent();
+	Body& body = const_cast<Body&>(parent.GetBody());
+
+	chrono::ChSharedBodyPtr& chbody = 
+	  const_cast<chrono::ChSharedBodyPtr&>(body.GetChBodyPtr());
+	
+	return chbody->GetRotAngle();
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetAngPos.hpp b/SRC/OpenMeca/Item/How/GetAngPos.hpp
new file mode 100644
index 0000000..790079e
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetAngPos.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetAngPos_hpp_
+#define _OpenMeca_Item_How_GetAngPos_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/AngularPosition.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetAngPos
+      {
+	typedef SensorT<PartPoint, Physic::AngularPosition, GetAngPos> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static double Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+   
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetAngPos::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetAngPos::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetAngVel.cpp b/SRC/OpenMeca/Item/How/GetAngVel.cpp
new file mode 100644
index 0000000..53c6163
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetAngVel.cpp
@@ -0,0 +1,72 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetAngVel.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetAngVel::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetAngVel::GetStrType()
+      {
+	return Physic::AngularVelocity::GetStrType();
+      }
+
+      const QString
+      GetAngVel::GetQStrType()
+      {
+	return Physic::AngularVelocity::GetQStrType();
+      }
+
+      Geom::Vector<_3D> 
+      GetAngVel::Acquire(MySensor& sensor)
+      {
+	PartPoint& parent =  sensor.GetParent();
+	Body& body = const_cast<Body&>(parent.GetBody());
+	
+	chrono::ChSharedBodyPtr& chbody = 
+	  const_cast<chrono::ChSharedBodyPtr&>(body.GetChBodyPtr());
+	
+	chrono::ChVector<> v = chbody->GetWvel_par();
+	return Geom::Vector<_3D>(v);
+
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetAngVel.hpp b/SRC/OpenMeca/Item/How/GetAngVel.hpp
new file mode 100644
index 0000000..d52c898
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetAngVel.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetAngVel_hpp_
+#define _OpenMeca_Item_How_GetAngVel_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/AngularVelocity.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetAngVel
+      {
+	typedef SensorT<PartPoint, Physic::AngularVelocity, GetAngVel> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static Geom::Vector<_3D> Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+   
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetAngVel::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetAngVel::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetLinAcc.cpp b/SRC/OpenMeca/Item/How/GetLinAcc.cpp
new file mode 100644
index 0000000..481f1c0
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetLinAcc.cpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetLinAcc.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetLinAcc::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetLinAcc::GetStrType()
+      {
+	return Physic::LinearAcceleration::GetStrType();
+      }
+
+      const QString
+      GetLinAcc::GetQStrType()
+      {
+	return Physic::LinearAcceleration::GetQStrType();
+      }
+
+      Geom::Vector<_3D> 
+      GetLinAcc::Acquire(MySensor& sensor)
+      {
+	PartPoint& parent =  sensor.GetParent();
+	Body& body = const_cast<Body&>(parent.GetBody());
+	Geom::Frame<_3D>&(Body::*fnptr)() = &Body::GetFrame;
+	
+	std::function<const Geom::Frame<_3D>& ()> f = 
+	  std::bind(fnptr, std::ref(body));
+	
+	const Geom::Point<_3D> p(parent.GetPoint(), f);
+	chrono::ChSharedBodyPtr& chbody = 
+	  const_cast<chrono::ChSharedBodyPtr&>(body.GetChBodyPtr());
+	
+	chrono::ChVector<> chp = body.ExpressPointInLocalChFrame(p);
+	chrono::ChVector<> v = chbody->RelPoint_AbsAcc(&chp);
+	return Geom::Vector<_3D>(v);
+
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetLinAcc.hpp b/SRC/OpenMeca/Item/How/GetLinAcc.hpp
new file mode 100644
index 0000000..d416b56
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetLinAcc.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetLinAcc_hpp_
+#define _OpenMeca_Item_How_GetLinAcc_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/LinearAcceleration.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetLinAcc
+      {
+	typedef SensorT<PartPoint, Physic::LinearAcceleration, GetLinAcc> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static Geom::Vector<_3D> Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetLinAcc::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetLinAcc::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+   
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetLinPos.cpp b/SRC/OpenMeca/Item/How/GetLinPos.cpp
new file mode 100644
index 0000000..51fa233
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetLinPos.cpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetLinPos.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetLinPos::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetLinPos::GetStrType()
+      {
+	return Physic::LinearPosition::GetStrType();
+      }
+
+      const QString
+      GetLinPos::GetQStrType()
+      {
+	return Physic::LinearPosition::GetQStrType();
+      }
+
+      Geom::Vector<_3D> 
+      GetLinPos::Acquire(MySensor& sensor)
+      {
+
+	PartPoint& parent =  sensor.GetParent();
+	Geom::Point<_3D> p(parent.GetPoint(), &Geom::Frame<_3D>::GetGlobal);
+	return p.GetPositionVector();
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetLinPos.hpp b/SRC/OpenMeca/Item/How/GetLinPos.hpp
new file mode 100644
index 0000000..3310708
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetLinPos.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetLinPos_hpp_
+#define _OpenMeca_Item_How_GetLinPos_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/LinearPosition.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetLinPos
+      {
+	typedef SensorT<PartPoint, Physic::LinearPosition, GetLinPos> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static Geom::Vector<_3D> Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+   
+ 
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetLinPos::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetLinPos::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+   
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetLinVel.cpp b/SRC/OpenMeca/Item/How/GetLinVel.cpp
new file mode 100644
index 0000000..caac16a
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetLinVel.cpp
@@ -0,0 +1,79 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetLinVel.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetLinVel::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetLinVel::GetStrType()
+      {
+	return Physic::LinearVelocity::GetStrType();
+      }
+
+      const QString
+      GetLinVel::GetQStrType()
+      {
+	return Physic::LinearVelocity::GetQStrType();
+      }
+
+      Geom::Vector<_3D> 
+      GetLinVel::Acquire(MySensor& sensor)
+      {
+	PartPoint& parent =  sensor.GetParent();
+	Body& body = const_cast<Body&>(parent.GetBody());
+	Geom::Frame<_3D>&(Body::*fnptr)() = &Body::GetFrame;
+
+	std::function<const Geom::Frame<_3D>& ()> f = 
+	  std::bind(fnptr, std::ref(body));
+	
+	const Geom::Point<_3D> p(parent.GetPoint(), f);
+	chrono::ChSharedBodyPtr& chbody = 
+	  const_cast<chrono::ChSharedBodyPtr&>(body.GetChBodyPtr());
+	
+	chrono::ChVector<> chp = body.ExpressPointInLocalChFrame(p);
+	chrono::ChVector<> v = chbody->RelPoint_AbsSpeed (&chp);
+
+	return Geom::Vector<_3D>(v);
+
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetLinVel.hpp b/SRC/OpenMeca/Item/How/GetLinVel.hpp
new file mode 100644
index 0000000..be41102
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetLinVel.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetLinVel_hpp_
+#define _OpenMeca_Item_How_GetLinVel_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/LinearVelocity.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetLinVel
+      {
+	typedef SensorT<PartPoint, Physic::LinearVelocity, GetLinVel> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static Geom::Vector<_3D> Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetLinVel::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetLinVel::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+   
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetReacForce.cpp b/SRC/OpenMeca/Item/How/GetReacForce.cpp
new file mode 100644
index 0000000..03594fe
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetReacForce.cpp
@@ -0,0 +1,69 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetReacForce.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetReacForce::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetReacForce::GetStrType()
+      {
+	return Physic::Force::GetStrType();
+      }
+
+      const QString
+      GetReacForce::GetQStrType()
+      {
+	return Physic::Force::GetQStrType();
+      }
+
+      Geom::Vector<_3D> 
+      GetReacForce::Acquire(MySensor& sensor)
+      {
+	Link& link  =  sensor.GetParent();
+	chrono::ChVector<> v_loc = link.GetChLink().Get_react_force ();
+	chrono::ChVector<> v_abs = link.GetChLink().GetLinkRelativeCoords().TrasformLocalToParent(v_loc);
+
+	return Geom::Vector<_3D>(v_abs);
+
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetReacForce.hpp b/SRC/OpenMeca/Item/How/GetReacForce.hpp
new file mode 100644
index 0000000..54b20e3
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetReacForce.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetReacForce_hpp_
+#define _OpenMeca_Item_How_GetReacForce_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Physic/Force.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetReacForce
+      {
+	typedef SensorT<Link, Physic::Force, GetReacForce> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static Geom::Vector<_3D> Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetReacForce::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetReacForce::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+   
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/GetReacTorque.cpp b/SRC/OpenMeca/Item/How/GetReacTorque.cpp
new file mode 100644
index 0000000..d7dc714
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetReacTorque.cpp
@@ -0,0 +1,69 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/GetReacTorque.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::GetReacTorque::MySensor)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      
+      const std::string 
+      GetReacTorque::GetStrType()
+      {
+	return Physic::Torque::GetStrType();
+      }
+
+      const QString
+      GetReacTorque::GetQStrType()
+      {
+	return Physic::Torque::GetQStrType();
+      }
+
+      Geom::Vector<_3D> 
+      GetReacTorque::Acquire(MySensor& sensor)
+      {
+	Link& link  =  sensor.GetParent();
+	chrono::ChVector<> v_loc = link.GetChLink().Get_react_torque ();
+	chrono::ChVector<> v_abs = link.GetChLink().GetLinkRelativeCoords().TrasformLocalToParent(v_loc);
+
+	return Geom::Vector<_3D>(v_abs);
+
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/GetReacTorque.hpp b/SRC/OpenMeca/Item/How/GetReacTorque.hpp
new file mode 100644
index 0000000..2e25dc1
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/GetReacTorque.hpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_GetReacTorque_hpp_
+#define _OpenMeca_Item_How_GetReacTorque_hpp_
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Physic/Torque.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct GetReacTorque
+      {
+	typedef SensorT<Link, Physic::Torque, GetReacTorque> MySensor;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static Geom::Vector<_3D> Acquire(MySensor&);
+      };
+
+
+    }
+  }
+}
+    
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::GetReacTorque::MySensor >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::GetReacTorque::MySensor::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+   
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/How.pro b/SRC/OpenMeca/Item/How/How.pro
new file mode 100644
index 0000000..670c579
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/How.pro
@@ -0,0 +1,42 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Item/How/GetLinPos.hpp \
+           Item/How/GetLinVel.hpp \
+           Item/How/GetLinAcc.hpp \
+           Item/How/GetAngPos.hpp \
+           Item/How/GetAngVel.hpp \
+           Item/How/GetAngAcc.hpp \
+           Item/How/GetReacForce.hpp \
+           Item/How/GetReacTorque.hpp \
+           Item/How/SetForce.hpp \
+           Item/How/SetTorque.hpp \
+           
+
+SOURCES += Item/How/GetLinPos.cpp \
+           Item/How/GetLinVel.cpp \
+           Item/How/GetLinAcc.cpp \
+           Item/How/GetAngPos.cpp \
+           Item/How/GetAngVel.cpp \
+           Item/How/GetAngAcc.cpp \
+           Item/How/GetReacForce.cpp \
+           Item/How/GetReacTorque.cpp \
+           Item/How/SetForce.cpp \
+           Item/How/SetTorque.cpp \
diff --git a/SRC/OpenMeca/Item/How/SetForce.cpp b/SRC/OpenMeca/Item/How/SetForce.cpp
new file mode 100644
index 0000000..34e0221
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/SetForce.cpp
@@ -0,0 +1,63 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/SetForce.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::SetForce::MyLoad)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      const std::string 
+      SetForce::GetStrType()
+      {
+	return "AbsoluteForce";
+      }
+
+      const QString 
+      SetForce::GetQStrType()
+      {
+	return QObject::tr("AbsoluteForce");
+      }
+
+      void
+      SetForce::Apply(MyLoad& load)
+      {
+	load.GetQuantity().Apply();
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/SetForce.hpp b/SRC/OpenMeca/Item/How/SetForce.hpp
new file mode 100644
index 0000000..d97e6e9
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/SetForce.hpp
@@ -0,0 +1,68 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_SetForce_hpp_
+#define _OpenMeca_Item_How_SetForce_hpp_
+
+
+#include "OpenMeca/Item/LoadT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/Force.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct SetForce
+      {
+	typedef LoadT<PartPoint, Physic::Force, SetForce> MyLoad;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static void Apply(MyLoad&);
+      };
+
+
+    }
+  }
+}
+    
+   
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::SetForce::MyLoad >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::SetForce::MyLoad::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/How/SetTorque.cpp b/SRC/OpenMeca/Item/How/SetTorque.cpp
new file mode 100644
index 0000000..fa1f138
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/SetTorque.cpp
@@ -0,0 +1,63 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Item/How/SetTorque.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::How::SetTorque::MyLoad)
+
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+      const std::string 
+      SetTorque::GetStrType()
+      {
+	return "AbsoluteTorque";
+      }
+
+      const QString 
+      SetTorque::GetQStrType()
+      {
+	return QObject::tr("AbsoluteTorque");
+      }
+
+      void
+      SetTorque::Apply(MyLoad& load)
+      {
+	load.GetQuantity().Apply();
+      }
+
+    }
+  }
+}
+    
+   
+
+    
+
diff --git a/SRC/OpenMeca/Item/How/SetTorque.hpp b/SRC/OpenMeca/Item/How/SetTorque.hpp
new file mode 100644
index 0000000..7bddc30
--- /dev/null
+++ b/SRC/OpenMeca/Item/How/SetTorque.hpp
@@ -0,0 +1,68 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_How_SetTorque_hpp_
+#define _OpenMeca_Item_How_SetTorque_hpp_
+
+
+#include "OpenMeca/Item/LoadT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Physic/Torque.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace How
+    {
+
+      struct SetTorque
+      {
+	typedef LoadT<PartPoint, Physic::Torque, SetTorque> MyLoad;
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	static void Apply(MyLoad&);
+      };
+
+
+    }
+  }
+}
+    
+   
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::How::SetTorque::MyLoad >::BuildIconSymbol()
+    {
+      OpenMeca::Item::How::SetTorque::MyLoad::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+    
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Item.pro b/SRC/OpenMeca/Item/Item.pro
new file mode 100644
index 0000000..ffb39b2
--- /dev/null
+++ b/SRC/OpenMeca/Item/Item.pro
@@ -0,0 +1,62 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+include(./Link/Link.pro)
+include(./Shape/Shape.pro)
+include(./How/How.pro)
+
+HEADERS += Item/Body.hpp \
+           Item/Link.hpp \
+           Item/LinkT.hpp \
+           Item/Part.hpp \
+           Item/PartPoint.hpp \
+           Item/PartUser.hpp \
+           Item/PartUserPoint.hpp \
+           Item/PartUserPipe.hpp \
+           Item/PartUserJunction.hpp \
+           Item/PartUserShape.hpp \
+           Item/PartUserShapeT.hpp \
+           Item/Physical.hpp \
+           Item/PartLinkT.hpp \
+           Item/Load.hpp \
+           Item/LoadT.hpp \
+           Item/Sensor.hpp \
+           Item/SensorT.hpp \
+           Item/Variable.hpp \
+           Item/PartPoint_CreateAction_SpecializedT.hpp
+
+
+
+SOURCES += Item/Body.cpp \
+           Item/Link.cpp \
+           Item/LinkT.cpp \
+           Item/Part.cpp \
+           Item/PartPoint.cpp \
+           Item/PartUser.cpp \
+           Item/PartUserPoint.cpp \
+           Item/PartUserPipe.cpp \
+           Item/PartUserJunction.cpp \
+           Item/PartUserShape.cpp \
+           Item/PartLinkT.cpp \
+           Item/Physical.cpp \
+           Item/Load.cpp \
+           Item/LoadT.cpp \
+           Item/Sensor.cpp \             
+           Item/SensorT.cpp \
+           Item/Variable.cpp
diff --git a/SRC/OpenMeca/Item/Link.cpp b/SRC/OpenMeca/Item/Link.cpp
new file mode 100644
index 0000000..2f92e92
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link.cpp
@@ -0,0 +1,319 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/UserRootItemCommonProperty.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Item::Link)
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    const std::string 
+    Link::GetStrType()
+    {
+      return "Link";
+    }
+
+    const QString 
+    Link::GetQStrType()
+    {
+      return QObject::tr("Link");
+    }
+
+
+    void
+    Link::Init()
+    {
+      Core::Singleton< Core::UserRootItemCommonProperty<Link> >::Get();
+      Core::Singleton< Core::UserItemCommonProperty<Link> >::Get();
+    }
+     
+
+    Link::Link(const std::string& strType)
+      :Core::UserRootItem(strType, Core::Singleton< Core::UserRootItemCommonProperty<Link> >::Get().GetRootTreeWidgetItem()),
+       body1_(*this, **  Core::System::Get().GetSetOf<Body>().Begin()),
+       body2_(*this, **++Core::System::Get().GetSetOf<Body>().Begin()),
+       treeItembody1_(0),
+       treeItembody2_(0),
+       center_(),
+       quaternion_(),
+       frame_(center_,quaternion_),
+
+       centerBody1_(std::bind(&Link::GetReferenceFrameBody1, std::ref(*this))),
+       quaternionBody1_(std::bind(&Link::GetReferenceFrameBody1, std::ref(*this))),
+       frameBody1_(centerBody1_, quaternionBody1_),
+
+       centerBody2_(std::bind(&Link::GetReferenceFrameBody2, std::ref(*this))),
+       quaternionBody2_(std::bind(&Link::GetReferenceFrameBody2, std::ref(*this))),
+      frameBody2_(centerBody2_, quaternionBody2_)
+    {
+      treeItembody1_ = new Gui::SecondaryTreeItem(GetMainTreeItem(), 
+						  std::bind(&Link::Body1, std::ref(*this)));
+      treeItembody2_ = new Gui::SecondaryTreeItem(GetMainTreeItem(), 
+						  std::bind(&Link::Body2, std::ref(*this)));
+      AddSecondaryTreeItem(*treeItembody1_);
+      AddSecondaryTreeItem(*treeItembody2_);
+      UpdateReferenceFrame();
+    }
+
+
+
+    Link::Link(const std::string& strType, Body& body1, Body& body2)
+      :Core::UserRootItem(strType, Core::Singleton< Core::UserRootItemCommonProperty<Link> >::Get().GetRootTreeWidgetItem()),
+       body1_(*this, body1),
+       body2_(*this, body2),
+       treeItembody1_(0),
+       treeItembody2_(0),
+       center_(),
+       quaternion_(),
+       frame_(center_,quaternion_),
+       
+       centerBody1_(std::bind(&Link::GetReferenceFrameBody1, std::ref(*this))),
+       quaternionBody1_(std::bind(&Link::GetReferenceFrameBody1, std::ref(*this))),
+      frameBody1_(centerBody1_, quaternionBody1_),
+      
+      centerBody2_(std::bind(&Link::GetReferenceFrameBody2, std::ref(*this))),
+      quaternionBody2_(std::bind(&Link::GetReferenceFrameBody2, std::ref(*this))),
+      frameBody2_(centerBody2_, quaternionBody2_)
+    {
+      treeItembody1_ = new Gui::SecondaryTreeItem(GetMainTreeItem(), 
+						  std::bind(&Link::Body1, std::ref(*this)));
+      treeItembody2_ = new Gui::SecondaryTreeItem(GetMainTreeItem(), 
+						  std::bind(&Link::Body2, std::ref(*this)));
+      AddSecondaryTreeItem(*treeItembody1_);
+      AddSecondaryTreeItem(*treeItembody2_);
+      UpdateReferenceFrame();
+    }
+
+
+
+      
+  
+
+    Link::~Link()
+    {
+    }
+
+    Body&
+    Link::GetBody1()
+    {
+      return *body1_.GetPtr();
+    }
+
+    Body&
+    Link::GetBody2()
+    {
+      return *body2_.GetPtr();
+    }
+
+    const Body& 
+    Link::GetBody1() const
+    {
+      return *body1_.GetPtr();
+    }
+
+
+    const Body& 
+    Link::GetBody2() const
+    {
+      return *body2_.GetPtr();
+    }
+
+    Body& 
+    Link::Body1()
+    {
+      return *body1_.GetPtr();
+    }
+
+
+    Body& 
+    Link::Body2()
+    {
+      return *body2_.GetPtr();
+    }
+
+
+    Core::AutoRegisteredPtr<Body, Link>& 
+    Link::GetBody1Ptr()
+    {
+      return body1_;
+    }
+
+    const Core::AutoRegisteredPtr<Body, Link>& 
+    Link::GetBody1Ptr() const
+    {
+      return body1_;
+    }
+
+    Core::AutoRegisteredPtr<Body, Link>& 
+    Link::GetBody2Ptr()
+    {
+      return body2_;
+    }
+
+    const Core::AutoRegisteredPtr<Body, Link>& 
+    Link::GetBody2Ptr() const
+    {
+      return body2_;
+    }
+
+    template<>
+    Body&
+    Link::GetBody<1>()
+    {
+      return GetBody1();
+    }
+
+    template<>
+    Body&
+    Link::GetBody<2>()
+    {
+      return GetBody2();
+    }
+
+    template<>
+    const Body& 
+    Link::GetBody<1>() const
+    {
+      return GetBody1();
+    }
+
+
+    template<>
+    const Body& 
+    Link::GetBody<2>() const
+    {
+      return GetBody2();
+    }
+
+
+    template<> 
+    Part& 
+    Link::GetPart<1>()
+    {
+      return GetPart1();
+    }
+
+    template<> 
+    const Part& 
+    Link::GetPart<1>() const
+    {
+      return GetPart1();
+    }
+
+    template<> 
+    Part& 
+    Link::GetPart<2>()
+    {
+      return GetPart2();
+    }
+
+    template<> 
+    const Part& 
+    Link::GetPart<2>() const
+    {
+      return GetPart2();
+    }
+
+
+    const Geom::Frame<_3D>& 
+    Link::GetReferenceFrameBody1() const
+    {
+      return GetBody1().GetFrame();
+    }
+
+    const Geom::Frame<_3D>& 
+    Link::GetReferenceFrameBody2() const
+    {
+      return GetBody2().GetFrame();
+    }
+
+
+    template<>
+    const Geom::Frame<_3D>& 
+    Link::GetFrameBody<1>() const
+    {
+      return frameBody1_;
+    }
+  
+    template<>
+    const Geom::Frame<_3D>& 
+    Link::GetFrameBody<2>() const
+    {
+      return frameBody2_;
+    }
+
+
+    void 
+    Link::UpdateReferenceFrame()
+    {
+      centerBody1_ = Geom::Point<_3D>(center_, 
+      				      std::bind(&Link::GetReferenceFrameBody1, std::ref(*this)));
+      quaternionBody1_ = Geom::Quaternion<_3D>(quaternion_, 
+      					       std::bind(&Link::GetReferenceFrameBody1, std::ref(*this)));
+      centerBody2_ = Geom::Point<_3D>(center_, 
+      				      std::bind(&Link::GetReferenceFrameBody2, std::ref(*this)));
+      quaternionBody2_ = Geom::Quaternion<_3D>(quaternion_, 
+      					       std::bind(&Link::GetReferenceFrameBody2, std::ref(*this)));
+
+    }
+
+
+
+    void 
+    Link::Update()
+    {
+      UpdateReferenceFrame();
+      Core::UserItem::Update();
+    }
+
+
+    bool&
+    Link::DrawLocalFrame()
+    {
+      return GetPart1().GetDrawLocalFrame();
+    }
+
+    const bool&
+    Link::DrawLocalFrame() const
+    {
+      return GetPart1().GetDrawLocalFrame();
+    }
+    
+    
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link.hpp b/SRC/OpenMeca/Item/Link.hpp
new file mode 100644
index 0000000..9a3522a
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link.hpp
@@ -0,0 +1,218 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_hpp
+#define OpenMeca_Item_Link_hpp
+
+#include "OpenMeca/Core/UserRootItem.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+#include "OpenMeca/Gui/SecondaryTreeItem.hpp"
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Util/MotionLaw.hpp"
+#include "OpenMeca/Core/None.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Util/ExprPoint.hpp"
+#include "OpenMeca/Util/ExprAttitude.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+
+#include "ChronoEngine/physics/ChLinkLock.h"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    class Body;
+
+    // Base for mechanical links
+    class Link: public Core::UserRootItem , public Core::AutoRegister<Link>
+    {
+    public:
+      static const std::string GetStrType(); 
+      static const QString GetQStrType(); 
+      static void Init();
+
+      typedef Core::None Dialog;
+
+    public:
+      Link(const std::string&);
+      Link(const std::string&, Body&, Body&);
+
+      virtual ~Link();
+
+      virtual void Update();
+      void UpdateReferenceFrame();
+
+      bool& DrawLocalFrame();
+      const bool& DrawLocalFrame() const;
+
+      //Accessor
+      OMC_ACCESSOR   (Center     , Util::ExprPoint      , center_    );
+      OMC_ACCESSOR   (Quaternion , Util::ExprAttitude , quaternion_);
+      OMC_ACCESSOR   (Frame      , Geom::Frame<_3D>     , frame_     );
+      OMC_ACCESS_CST (FrameBody1 , Geom::Frame<_3D>     , frameBody1_);
+      OMC_ACCESS_CST (FrameBody2 , Geom::Frame<_3D>     , frameBody2_);
+
+      Body& GetBody1();
+      Body& GetBody2();
+
+      Body& Body1();
+      Body& Body2();
+
+      const Body& GetBody1() const;
+      const Body& GetBody2() const;
+
+      Core::AutoRegisteredPtr<Body, Link>& GetBody1Ptr();
+      const Core::AutoRegisteredPtr<Body, Link>& GetBody1Ptr() const;
+
+      Core::AutoRegisteredPtr<Body, Link>& GetBody2Ptr();
+      const Core::AutoRegisteredPtr<Body, Link>& GetBody2Ptr() const;
+
+      template<int N> Body& GetBody();
+      template<int N> const Body& GetBody() const;
+
+      const Geom::Frame<_3D>& GetReferenceFrameBody1() const;
+      const Geom::Frame<_3D>& GetReferenceFrameBody2() const;
+
+      template<int N> const Geom::Frame<_3D>& GetFrameBody() const;
+      template<int N> std::function<const Geom::Frame<_3D>& ()> GetFrameFctBody() const;
+
+      virtual Part& GetPart1() = 0;
+      virtual const Part& GetPart1() const = 0;
+
+      virtual Part& GetPart2() = 0;
+      virtual const Part& GetPart2() const = 0;
+
+      template<int N> Part& GetPart();
+      template<int N> const Part& GetPart() const;
+
+      virtual chrono::ChLink& GetChLink() = 0;
+
+    private:
+      Link();                        //Not allowed
+      Link(const Link&);             //Not Allowed
+      Link& operator=(const Link&);  //Not Allowed
+
+      void EraseBody1();
+      void EraseBody2();
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    private:
+      Core::AutoRegisteredPtr<Body, Link> body1_;
+      Core::AutoRegisteredPtr<Body, Link> body2_;
+      Gui::SecondaryTreeItem* treeItembody1_;
+      Gui::SecondaryTreeItem* treeItembody2_;
+      Util::ExprPoint center_;
+      Util::ExprAttitude quaternion_;
+      Geom::Frame<_3D> frame_;      
+
+      Geom::Point<_3D> centerBody1_;
+      Geom::Quaternion<_3D> quaternionBody1_;
+      Geom::Frame<_3D> frameBody1_;      
+
+      Geom::Point<_3D> centerBody2_;
+      Geom::Quaternion<_3D> quaternionBody2_;
+      Geom::Frame<_3D> frameBody2_;
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Link::save(Archive& ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(Core::UserRootItem);
+      ar << BOOST_SERIALIZATION_NVP(body1_);
+      ar << BOOST_SERIALIZATION_NVP(body2_);
+      ar << BOOST_SERIALIZATION_NVP(center_);
+      ar << BOOST_SERIALIZATION_NVP(quaternion_);
+
+    }
+
+
+    template<class Archive>
+    inline void
+    Link::load(Archive& ar, const unsigned int version)
+    {
+      body1_.Unregister();
+      body2_.Unregister();
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(Core::UserRootItem);
+      ar >> BOOST_SERIALIZATION_NVP(body1_);
+      ar >> BOOST_SERIALIZATION_NVP(body2_);
+      if (version >= 1)
+	ar >> BOOST_SERIALIZATION_NVP(center_);
+      else
+	{
+	  Geom::Point<_3D> fake;
+	  ar >> BOOST_SERIALIZATION_NVP(fake);
+	  center_ = fake;
+	}
+      
+      if (version >= 2)
+	ar >> BOOST_SERIALIZATION_NVP(quaternion_);
+      else
+	{
+	  Geom::Quaternion<_3D> fake;
+	  ar >> BOOST_SERIALIZATION_NVP(fake);
+	  quaternion_ = fake;	  
+	}
+    }
+    
+    
+    template<int N> 
+    inline  std::function<const Geom::Frame<_3D>& ()> 
+    Link::GetFrameFctBody() const
+    {
+      const Link& me = *this;
+      const Geom::Frame<_3D>&(Link::*fnpt)() const = &Link::GetFrameBody<1>;
+      std::function<const Geom::Frame<_3D>& ()> f = std::bind(fnpt, std::ref(me));
+      return f;
+    }
+
+  }
+
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::Link>::BuildIconSymbol()
+    {
+      iconSymbol_ = Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Link.svg");
+    }
+
+  }
+}
+
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Item::Link, 2)
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/All.hpp b/SRC/OpenMeca/Item/Link/All.hpp
new file mode 100644
index 0000000..410a218
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/All.hpp
@@ -0,0 +1,39 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_All_hpp
+#define OpenMeca_Item_Link_All_hpp
+
+#include "OpenMeca/Item/Link/Revolute.hpp"
+#include "OpenMeca/Item/Link/Motor.hpp"
+#include "OpenMeca/Item/Link/LinearMotor.hpp"
+#include "OpenMeca/Item/Link/Slider.hpp"
+#include "OpenMeca/Item/Link/Cylindrical.hpp"
+#include "OpenMeca/Item/Link/Planar.hpp"
+#include "OpenMeca/Item/Link/PointLine.hpp"
+#include "OpenMeca/Item/Link/PointPlane.hpp"
+#include "OpenMeca/Item/Link/Spherical.hpp"
+#include "OpenMeca/Item/Link/Screw.hpp"
+#include "OpenMeca/Item/Link/Gear.hpp"
+#include "OpenMeca/Item/Link/Pulley.hpp"
+#include "OpenMeca/Item/Link/RackPinion.hpp"
+#include "OpenMeca/Item/Link/Spring.hpp"
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Cylindrical.cpp b/SRC/OpenMeca/Item/Link/Cylindrical.cpp
new file mode 100644
index 0000000..1394e9c
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Cylindrical.cpp
@@ -0,0 +1,114 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Cylindrical.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    const std::string 
+    Cylindrical::GetStrType()
+    {
+      return "Cylindrical";
+    }
+
+    const QString 
+    Cylindrical::GetQStrType()
+    {
+      return QObject::tr("Cylindrical");
+    }
+
+    Cylindrical::Cylindrical(Link& link)
+      :LinkTypeBase(link)
+    {
+    }
+
+    Cylindrical::~Cylindrical()
+    {
+    }
+
+    template<> 
+    void 
+    Cylindrical::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 1.0f*scale);
+    }
+
+    
+
+    template<>
+    void 
+    Cylindrical::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      PartPoint* p3 = new PartPoint(item);
+      p1->GetName() = "left";
+      p1->SetScaleCoordinate(0., 0., -0.5);
+      p2->GetName() = "middle";
+      p2->SetScaleCoordinate(0., 0., 0.);
+      p3->GetName() = "right";
+      p3->SetScaleCoordinate(0., 0., 0.5);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+      set.AddItem(*p3);
+    }
+
+
+    template<> 
+    void 
+    Cylindrical::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.1f*scale, 0.6f*scale);
+    }
+
+
+    template<>
+    void 
+    Cylindrical::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Cylindrical.hpp b/SRC/OpenMeca/Item/Link/Cylindrical.hpp
new file mode 100644
index 0000000..665ea15
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Cylindrical.hpp
@@ -0,0 +1,103 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Cylindrical_hpp
+#define OpenMeca_Item_Link_Cylindrical_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    class Cylindrical : public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkLockCylindrical ChLink; 
+      typedef Gui::DialogLinkT< LinkT<Cylindrical> > Dialog;
+      
+
+    public:
+      Cylindrical(Link&);
+      ~Cylindrical();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Cylindrical::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+    }
+
+
+   
+  }
+
+}
+
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Cylindrical> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Cylindrical>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Cylindrical> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Gear.cpp b/SRC/OpenMeca/Item/Link/Gear.cpp
new file mode 100644
index 0000000..a5beae0
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Gear.cpp
@@ -0,0 +1,148 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Gear.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Gear::GetStrType()
+    {
+      return "Gear";
+    }
+
+    const QString 
+    Gear::GetQStrType()
+    {
+      return QObject::tr("Gear");
+    }
+
+
+    Gear::Gear(Link& link)
+      :LinkTypeBase(link),
+       ratio_(1.),
+       interAxisLength_(0.),
+       modulus_(0.001),
+       angleOfAction_(M_PI*20./180.),
+       internalTeeth_(false)
+    {
+    }
+
+    Gear::~Gear()
+    {
+    }
+
+
+
+    template<> 
+    double
+    Gear::ComputeRadius<1>()
+    {
+      if (internalTeeth_ == false)
+	return interAxisLength_ / (1. + (1./ratio_));
+      return interAxisLength_ / (1. - (1./ratio_));
+      
+    }
+
+
+    template<> 
+    void 
+    Gear::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      const float l = 0.1f*scale;
+      const float R0 = ComputeRadius<1>();
+      const float Rb = R0*cos(angleOfAction_); 
+      OMC_ASSERT_MSG(R0==R0, "Problem while computing gear radius");
+      
+      glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
+      if (internalTeeth_ == false)
+	{
+	  glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+	  Util::Draw::Cylinder(Rb*1.01, l);
+	  glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
+	  Util::Draw::OuterCylinderTeeth(R0, modulus_, angleOfAction_, l);
+	}
+      else
+	{
+	  glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+	  Util::Draw::Cylinder(R0+(.1*R0), R0 + modulus_, l);
+	  Util::Draw::InnerCylinderTeeth(R0, modulus_, angleOfAction_, l);
+	}
+    }
+
+ 
+
+    template<> 
+    double
+    Gear::ComputeRadius<2>()
+    {
+      if (internalTeeth_ == false)
+	return interAxisLength_ / (1. + ratio_);
+      return interAxisLength_ / (ratio_ - 1.);
+    }
+
+    template<> 
+    void 
+    Gear::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      const float l = 0.1f*scale;
+      const float R0 = ComputeRadius<2>();
+      const float Rb = R0*cos(angleOfAction_); 
+      OMC_ASSERT_MSG(R0==R0, "Problem while computing gear radius");
+
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(Rb*1.01, l);
+      glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::OuterCylinderTeeth(R0, modulus_, angleOfAction_, l);
+    }
+
+
+    void 
+    Gear::UpdatePart()
+    {
+      GetLink().GetPart2().GetCenter()[1] = interAxisLength_;
+    }
+
+
+    
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Gear.hpp b/SRC/OpenMeca/Item/Link/Gear.hpp
new file mode 100644
index 0000000..fbaedc3
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Gear.hpp
@@ -0,0 +1,153 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Gear_hpp
+#define OpenMeca_Item_Link_Gear_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkGear.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+#include "ChronoEngine/physics/ChLinkLock.h"
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    class Gear : public LinkTypeBase
+    {
+
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkGear ChLink; 
+      typedef Gui::DialogLinkGear Dialog;
+
+
+    public:
+      Gear(Link&);
+      ~Gear();
+
+      void UpdatePart();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+      template <int N> double ComputeRadius();
+      template <int N> chrono::ChFrame<> ComputeLocalShaft();
+
+      // Accessors
+      OMC_ACCESSOR(Ratio          , double ,  ratio_          );
+      OMC_ACCESSOR(InterAxisLength, double ,  interAxisLength_);
+      OMC_ACCESSOR(Modulus        , double ,  modulus_);
+      OMC_ACCESSOR(AngleOfAction  , double ,  angleOfAction_);
+      OMC_ACCESSOR(InternalTeeth  , bool   ,  internalTeeth_);
+
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      double ratio_;
+      double interAxisLength_;
+      double modulus_;
+      double angleOfAction_;
+      bool internalTeeth_;
+    };
+
+    template<class Archive>
+    inline void
+    Gear::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+      ar & BOOST_SERIALIZATION_NVP(ratio_);
+      ar & BOOST_SERIALIZATION_NVP(interAxisLength_);
+      ar & BOOST_SERIALIZATION_NVP(modulus_);
+      ar & BOOST_SERIALIZATION_NVP(angleOfAction_);
+      ar & BOOST_SERIALIZATION_NVP(internalTeeth_);
+    }
+
+
+    template<int N>
+    void 
+    Gear::BuildPoints(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "center";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+    template<int N>
+    chrono::ChFrame<>
+    Gear::ComputeLocalShaft()
+    {
+      const Geom::Point<_3D> p(GetLink().GetPart<N>().GetCenter(), 
+			       GetLink().GetBody<N>().GetFrameFct());
+      
+      const Geom::Quaternion<_3D> q(GetLink().GetPart<N>().GetQuaternion(), 
+				    GetLink().GetBody<N>().GetFrameFct());
+      
+      const Geom::Frame<_3D> f(p, q);
+
+      return chrono::ChFrame<>(f.ToChCoordsys());
+    }
+
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Gear> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Gear>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Gear> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/LinearMotor.cpp b/SRC/OpenMeca/Item/Link/LinearMotor.cpp
new file mode 100644
index 0000000..08c2a71
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/LinearMotor.cpp
@@ -0,0 +1,160 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/LinearMotor.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Item/LinkT.hpp" 
+
+#include "OpenMeca/Item/LinkT.hpp" 
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    LinearMotor::GetStrType()
+    {
+      return "LinearMotor";
+    }
+
+    const QString 
+    LinearMotor::GetQStrType()
+    {
+      return QObject::tr("LinearMotor");
+    }
+
+    bool
+    LinearMotor::EnableMotionLaw()
+    {
+      return false;
+    }
+
+
+
+    LinearMotor::LinearMotor(Link& link)
+      :LinkTypeBase(link),
+       displacement_(Core::System::Get().GetTime(), 0.)
+    {
+      displacement_.SetDimension(Util::Dimension::Get("Length"));
+    }
+    
+    LinearMotor::~LinearMotor()
+    {
+    }
+
+
+    template<> 
+    void 
+    LinearMotor::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      float Lx = 0.2f*scale;
+      float Ly = 0.2f*scale;
+      float Lz = 0.6f*scale;
+      Util::Draw::Box(Lx,Ly,Lz);
+      
+      Lx = Lx/2;
+      Ly = Ly/2;
+      Lz = Lz/2;
+      glColor3f(0.0f, 0.0f, 0.0f);
+      
+      glDisable(GL_LIGHTING);
+      glLineWidth(3.0f);
+      glBegin(GL_LINES);
+      glVertex3f(Lx,Ly,Lz);
+      glVertex3f(-Lx,-Ly,Lz);
+      glVertex3f(Lx,-Ly,Lz);
+      glVertex3f(-Lx,Ly,Lz);
+      glVertex3f(Lx,Ly,-Lz);
+      glVertex3f(-Lx,-Ly,-Lz);
+      glVertex3f(Lx,-Ly,-Lz);
+      glVertex3f(-Lx,Ly,-Lz);
+      glEnd();
+      
+      glColor3f(1.0f, 1.0f, 1.0f);
+      const float s = 0.01f*scale;
+      Lx += s;
+      Ly *= 2./3.;
+      Lz *= 1./4.;
+      glBegin(GL_LINE_STRIP);
+      glVertex3f(Lx+s, -Ly, -Lz);
+      glVertex3f(Lx+s,  Ly, -Lz);
+      glVertex3f(Lx+s,  0.,  0.);
+      glVertex3f(Lx+s,  Ly,  Lz);
+      glVertex3f(Lx+s, -Ly,  Lz);
+      glEnd();
+      glEnable(GL_LIGHTING);
+    }
+
+    
+
+    template<>
+    void 
+    LinearMotor::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+
+    template<> 
+    void 
+    LinearMotor::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 1.0f*scale);
+    }
+
+
+    template<>
+    void 
+    LinearMotor::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      PartPoint* p3 = new PartPoint(item);
+      p1->GetName() = "left";
+      p1->SetScaleCoordinate(0., 0., -0.5);
+      p2->GetName() = "middle";
+      p2->SetScaleCoordinate(0., 0., 0.);
+      p3->GetName() = "right";
+      p3->SetScaleCoordinate(0., 0., 0.5);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+      set.AddItem(*p3);
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/LinearMotor.hpp b/SRC/OpenMeca/Item/Link/LinearMotor.hpp
new file mode 100644
index 0000000..d1a6fe9
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/LinearMotor.hpp
@@ -0,0 +1,115 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_LinearMotor_hpp
+#define OpenMeca_Item_Link_LinearMotor_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkLinearMotor.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+#include "OpenMeca/Util/CustomChFunction.hpp"
+
+#include "ChronoEngine/physics/ChLinkEngine.h"
+#include "ChronoEngine/physics/ChLinkEngine.h"
+
+
+namespace OpenMeca
+{    
+  namespace Item
+  {
+
+    class LinearMotor: public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+      static bool EnableMotionLaw();
+
+
+      typedef chrono::ChLinkLockLock ChLink; 
+      typedef Gui::DialogLinkLinearMotor Dialog;
+
+    public:
+      LinearMotor(Link&);
+      ~LinearMotor();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+      // Accessors
+      OMC_ACCESSOR(Displacement, Util::CustomChFunction,  displacement_);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+    
+    private:
+        Util::CustomChFunction displacement_;
+    };
+
+
+    template<class Archive>
+    inline void
+    LinearMotor::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+      ar & BOOST_SERIALIZATION_NVP(displacement_);
+    }
+
+
+  }
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::LinearMotor> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::LinearMotor>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::LinearMotor> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Item::LinearMotor, 0)
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Link.pro b/SRC/OpenMeca/Item/Link/Link.pro
new file mode 100644
index 0000000..ec1dbf6
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Link.pro
@@ -0,0 +1,51 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Item/Link/LinkTypeBase.hpp \
+           Item/Link/Revolute.hpp \
+           Item/Link/Slider.hpp \
+           Item/Link/Cylindrical.hpp \
+           Item/Link/LinearMotor.hpp \
+           Item/Link/Motor.hpp \
+           Item/Link/Planar.hpp \
+           Item/Link/PointLine.hpp \
+           Item/Link/PointPlane.hpp \
+           Item/Link/Spherical.hpp \
+           Item/Link/Screw.hpp \
+           Item/Link/Gear.hpp \
+           Item/Link/Pulley.hpp \
+           Item/Link/RackPinion.hpp \
+           Item/Link/Spring.hpp
+
+SOURCES += Item/Link/LinkTypeBase.cpp \
+           Item/Link/Revolute.cpp \
+           Item/Link/Slider.cpp \
+           Item/Link/Cylindrical.cpp \
+           Item/Link/LinearMotor.cpp \
+           Item/Link/Motor.cpp \
+           Item/Link/Planar.cpp \
+           Item/Link/PointLine.cpp \
+           Item/Link/PointPlane.cpp \
+           Item/Link/Spherical.cpp \
+           Item/Link/Screw.cpp \
+           Item/Link/Gear.cpp \
+           Item/Link/Pulley.cpp \
+           Item/Link/RackPinion.cpp \
+           Item/Link/Spring.cpp
diff --git a/SRC/OpenMeca/Item/Link/LinkTypeBase.cpp b/SRC/OpenMeca/Item/Link/LinkTypeBase.cpp
new file mode 100644
index 0000000..1e78e8d
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/LinkTypeBase.cpp
@@ -0,0 +1,70 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    LinkTypeBase::LinkTypeBase(Link& link)
+      :link_(link)
+    {
+    }
+
+    LinkTypeBase::~LinkTypeBase()
+    {
+    }
+
+    void
+    LinkTypeBase::UpdatePart()
+    {
+    }
+
+    Link& 
+    LinkTypeBase::GetLink()
+    {
+      return link_;
+    }
+
+    const Link& 
+    LinkTypeBase::GetLink() const
+    {
+      return link_;
+    }
+
+    void 
+    LinkTypeBase::BeginDraw1()
+    {
+    }
+
+    void 
+    LinkTypeBase::BeginDraw2()
+    {
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/LinkTypeBase.hpp b/SRC/OpenMeca/Item/Link/LinkTypeBase.hpp
new file mode 100644
index 0000000..2fd05a1
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/LinkTypeBase.hpp
@@ -0,0 +1,86 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_LinkTypeBase_hpp
+#define OpenMeca_Item_Link_LinkTypeBase_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Core/SetOf.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+#include "ChronoEngine/physics/ChLinkLock.h"
+
+namespace OpenMeca
+{  
+  namespace Core
+  { 
+    class DrawableUserItem;
+  } 
+}
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    class PartPoint;
+    class Link;
+    template <class T> class LinkT;
+    
+
+    class LinkTypeBase
+    {
+    public:
+      LinkTypeBase(Link&);
+      virtual ~LinkTypeBase();
+
+      virtual void UpdatePart();
+
+      virtual void BeginDraw1();
+      virtual void BeginDraw2();
+      
+      Link& GetLink();
+      const Link& GetLink() const;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      Link& link_;
+    };
+
+
+    template<class Archive>
+    inline void
+    LinkTypeBase::serialize(Archive&, const unsigned int)
+    {
+    }
+
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Motor.cpp b/SRC/OpenMeca/Item/Link/Motor.cpp
new file mode 100644
index 0000000..bc2d03b
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Motor.cpp
@@ -0,0 +1,144 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Motor.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Motor::GetStrType()
+    {
+      return "Motor";
+    }
+
+    const QString 
+    Motor::GetQStrType()
+    {
+      return QObject::tr("Motor");
+    }
+
+
+    Motor::Motor(Link& link)
+      :LinkTypeBase(link),
+       velocity_(Core::System::Get().GetTime(), 0.)
+    {
+      velocity_.SetDimension(Util::Dimension::Get("AngularVelocity"));
+    }
+    
+    Motor::~Motor()
+    {
+    }
+
+    template<> 
+    void 
+    Motor::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 1.0f*scale);
+     
+      glRotatef(90.0f, 0.0f, 0.0f, 1.0f);
+      glTranslatef(0.0f, 0.35f*scale, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 0.1f*scale);
+      glTranslatef(0.0f, -2*0.35f*scale, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 0.1f*scale);
+    }
+
+    
+
+    template<>
+    void 
+    Motor::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      PartPoint* p3 = new PartPoint(item);
+      p1->GetName() = "left";
+      p1->SetScaleCoordinate(0., 0., -0.5);
+      p2->GetName() = "middle";
+      p2->SetScaleCoordinate(0., 0., 0.);
+      p3->GetName() = "right";
+      p3->SetScaleCoordinate(0., 0., 0.5);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+      set.AddItem(*p3);
+    }
+
+
+    template<> 
+    void 
+    Motor::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.1f*scale, 0.6f*scale);
+      
+      double r = 0.1f*scale + 0.008f*scale;
+      double i;
+      glColor3f(1.0f, 1.0f, 1.0f);
+      glDisable(GL_LIGHTING);
+      glLineWidth(1.0f);
+      glBegin(GL_LINE_STRIP);
+      for (i=3.14/4.0f;i<=3.0f*3.14/4.0f  ;i=i+0.1)
+	{
+	  glVertex3f(-0.05f*scale,r*cos(i),r*sin(i));
+	}
+      glVertex3f(0.0f,r*cos(3.14/2.0),r*sin(3.14/2.0));
+      glVertex3f(0.05f*scale,r*cos(3.0f*3.14/4.0f),r*sin(3.0f*3.14/4.0f));
+      for (i=3.0f*3.14/4.0f;i>=3.14/4.0f  ;i=i-0.1)
+	{
+	  glVertex3f(0.05f*scale,r*cos(i),r*sin(i));
+	}
+      glEnd();
+      glEnable(GL_LIGHTING);
+      
+    }
+
+
+    template<>
+    void 
+    Motor::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Motor.hpp b/SRC/OpenMeca/Item/Link/Motor.hpp
new file mode 100644
index 0000000..b7c7c30
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Motor.hpp
@@ -0,0 +1,119 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Motor_hpp
+#define OpenMeca_Item_Link_Motor_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkMotor.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Util/CustomChFunction.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+#include "ChronoEngine/physics/ChLinkEngine.h"
+#include "ChronoEngine/physics/ChLinkEngine.h"
+
+
+namespace OpenMeca
+{    
+  namespace Item
+  {
+
+    class Motor: public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkEngine ChLink; 
+      typedef Gui::DialogLinkMotor Dialog;
+
+    public:
+      Motor(Link&);
+      ~Motor();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+      // Accessors
+      OMC_ACCESSOR(Velocity , Util::CustomChFunction,  velocity_);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+    
+    private:
+        Util::CustomChFunction velocity_;
+    };
+
+
+    template<class Archive>
+    inline void
+    Motor::serialize(Archive& ar, const unsigned int version)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+      if (version == 0)
+	{
+	  double fake = 0.;
+	  ar & BOOST_SERIALIZATION_NVP(fake);
+	  velocity_.SetExpressionFromValue(fake);
+	  return;
+	}
+      ar & BOOST_SERIALIZATION_NVP(velocity_);
+    }
+
+
+  }
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Motor> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Motor>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Motor> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Item::Motor, 1)
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Planar.cpp b/SRC/OpenMeca/Item/Link/Planar.cpp
new file mode 100644
index 0000000..90b4e3a
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Planar.cpp
@@ -0,0 +1,119 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Planar.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Planar::GetStrType()
+    {
+      return "Planar";
+    }
+
+    const QString 
+    Planar::GetQStrType()
+    {
+      return QObject::tr("Planar");
+    }
+
+    Planar::Planar(Link& link)
+      :LinkTypeBase(link)
+    {
+    }
+    
+    Planar::~Planar()
+    {
+    }
+
+    template<> 
+    void 
+    Planar::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      float Lx = 0.6f*scale;
+      float Ly = 0.6f*scale;
+      float Lz = 0.02f*scale;
+
+      glTranslatef(0.0f, 0.0f, -Lz/2.f);
+      Util::Draw::Box(Lx, Ly, Lz);
+      glTranslatef(0.0f, 0.0f, -Lz/2.f);
+    }
+
+    
+
+    template<>
+    void 
+    Planar::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+
+    template<> 
+    void 
+    Planar::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      float Lx = 0.6f*scale;
+      float Ly = 0.6f*scale;
+      float Lz = 0.02f*scale;
+
+      glTranslatef(0.0f, 0.0f,  Lz/2.f);
+      Util::Draw::Box(Lx, Ly, Lz);
+      glTranslatef(0.0f, 0.0f, -Lz/2.f);
+    }
+
+
+    template<>
+    void 
+    Planar::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Planar.hpp b/SRC/OpenMeca/Item/Link/Planar.hpp
new file mode 100644
index 0000000..9277a7d
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Planar.hpp
@@ -0,0 +1,96 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Planar_hpp
+#define OpenMeca_Item_Link_Planar_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+
+namespace OpenMeca
+{    
+  namespace Item
+  {
+
+    class Planar :  public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkLockPlanePlane ChLink; 
+      typedef Gui::DialogLinkT< LinkT<Planar > > Dialog;
+
+    public:
+      Planar(Link&);
+      ~Planar();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    };
+
+    template<class Archive>
+    inline void
+    Planar::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+    }
+
+   
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Planar> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Planar>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Planar> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/PointLine.cpp b/SRC/OpenMeca/Item/Link/PointLine.cpp
new file mode 100644
index 0000000..5ff653c
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/PointLine.cpp
@@ -0,0 +1,106 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/PointLine.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    PointLine::GetStrType()
+    {
+      return "PointLine";
+    }
+
+    const QString 
+    PointLine::GetQStrType()
+    {
+      return QObject::tr("PointLine");
+    }
+
+    PointLine::PointLine(Link& link)
+      :LinkTypeBase(link)
+    {
+    }
+
+    PointLine::~PointLine()
+    {
+    }
+
+    template<> 
+    void 
+    PointLine::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      Util::Draw::Sphere(0.15f*scale);
+    }
+
+    
+
+    template<>
+    void 
+    PointLine::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., -0.15, 0.);
+      set.AddItem(*p1);
+    }
+
+
+    template<> 
+    void 
+    PointLine::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      Util::Draw::Channel(0.2f*scale,0.15f*scale,0.6f*scale);
+    }
+
+
+    template<>
+    void 
+    PointLine::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0.2, 0.);
+      set.AddItem(*p1);
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/PointLine.hpp b/SRC/OpenMeca/Item/Link/PointLine.hpp
new file mode 100644
index 0000000..bcae45b
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/PointLine.hpp
@@ -0,0 +1,96 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_PointLine_hpp
+#define OpenMeca_Item_Link_PointLine_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+namespace OpenMeca
+{   
+  namespace Item
+  {
+   
+    class PointLine :  public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkLockPointLine ChLink; 
+      typedef Gui::DialogLinkT< LinkT<PointLine > > Dialog;
+    public:
+      PointLine(Link&);
+      ~PointLine();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    };
+
+
+    template<class Archive>
+    inline void
+    PointLine::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+    }
+   
+  }
+
+}
+
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::PointLine> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::PointLine>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::PointLine> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/PointPlane.cpp b/SRC/OpenMeca/Item/Link/PointPlane.cpp
new file mode 100644
index 0000000..191e0df
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/PointPlane.cpp
@@ -0,0 +1,112 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/PointPlane.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    PointPlane::GetStrType()
+    {
+      return "PointPlane";
+    }
+
+    const QString 
+    PointPlane::GetQStrType()
+    {
+      return QObject::tr("PointPlane");
+    }
+
+    template<> 
+    void 
+    PointPlane::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      Util::Draw::Cone(0.2f*scale,0.2f*scale);
+    }
+
+    PointPlane::PointPlane(Link& link)
+      :LinkTypeBase(link)
+    {
+    }
+
+    PointPlane::~PointPlane()
+    {
+    }    
+
+    template<>
+    void 
+    PointPlane::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.2);
+      set.AddItem(*p1);
+    }
+
+
+    template<> 
+    void 
+    PointPlane::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      glTranslatef(0.0f, 0.0f, -0.01f*scale);
+      Util::Draw::Box(0.6f*scale, 0.6f*scale, 0.02f*scale);
+      glTranslatef(0.0f, 0.0f, 0.01f*scale);
+    }
+
+
+    template<>
+    void 
+    PointPlane::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., -0.01);
+      set.AddItem(*p1);
+    }
+
+
+
+    
+  
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/PointPlane.hpp b/SRC/OpenMeca/Item/Link/PointPlane.hpp
new file mode 100644
index 0000000..b68d17c
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/PointPlane.hpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_PointPlane_hpp
+#define OpenMeca_Item_Link_PointPlane_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+
+namespace OpenMeca
+{    
+  namespace Item
+  {
+
+    class PointPlane :  public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkLockPointPlane ChLink; 
+      typedef Gui::DialogLinkT< LinkT<PointPlane > > Dialog;
+      
+    public:
+      PointPlane(Link&);
+      ~PointPlane();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    };
+
+
+    template<class Archive>
+    inline void
+    PointPlane::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+    }
+
+  }
+
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::PointPlane> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::PointPlane>::BuildIconSymbol(iconSymbol_);
+    }
+
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::PointPlane> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Pulley.cpp b/SRC/OpenMeca/Item/Link/Pulley.cpp
new file mode 100644
index 0000000..0e1269b
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Pulley.cpp
@@ -0,0 +1,227 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Pulley.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Pulley::GetStrType()
+    {
+      return "Pulley";
+    }
+
+    const QString 
+    Pulley::GetQStrType()
+    {
+      return QObject::tr("Pulley");
+    }
+
+    Pulley::Pulley(Link& link)
+      :LinkTypeBase(link),
+       radius1_(0.),
+       radius2_(0.),
+       interAxisLength_(0.),
+       modulus_(0.01)
+    {
+    }
+
+    Pulley::~Pulley()
+    {
+    }
+
+
+    template<> 
+    double 
+    Pulley::ComputePinionBeltAngle<1>()
+    {
+      return 2*acos((radius1_ - radius2_) /  interAxisLength_);
+    }
+
+    template<> 
+    double 
+    Pulley::ComputePinionBeltAngle<2>()
+    {
+      return M_PI - ComputePinionBeltAngle<1>();
+    }
+
+
+    template<> 
+    double 
+    Pulley::ComputeRotationAngle<1>()
+    {
+      const Geom::Point<_3D> O2(GetLink().GetPart2().GetCenter(), 
+				GetLink().GetPart1().GetFrameFct());
+      const Geom::Vector<_3D> dir = O2.GetPositionVector().Unit();
+      const Geom::Vector<_3D>& x = GetLink().GetPart1().GetFrame().GetYAxis();
+
+      Geom::Quaternion<_3D> Q(GetLink().GetPart1().GetFrameFct());
+      Q.SetVecFromTo(x, dir);
+      float angle = Q.GetAngle();
+      if (Q.GetAxis()[2] < 0)
+	angle = 2*M_PI - angle;
+      return  angle;
+    }
+
+    template<> 
+    double 
+    Pulley::ComputeRotationAngle<2>()
+    {
+      const Geom::Point<_3D> O1(GetLink().GetPart1().GetCenter(), 
+				GetLink().GetPart2().GetFrameFct());
+      const Geom::Vector<_3D> dir = O1.GetPositionVector().Unit();
+      const Geom::Vector<_3D>& x = GetLink().GetPart2().GetFrame().GetXAxis();
+      Geom::Quaternion<_3D> Q(GetLink().GetPart2().GetFrameFct());
+      Q.SetVecFromTo(x, dir);
+      float angle = Q.GetAngle();
+      if (Q.GetAxis()[2] < 0)
+	angle = 2*M_PI - angle;
+      return  angle;
+    }
+
+    double 
+    Pulley::ComputeRackLength()
+    {
+      const float e  = interAxisLength_;
+      const float d1 = radius1_*2.; 
+      const float d2 = radius2_*2.; 
+      return e*sqrt(1 - pow((d2-d1)/(2.*e), 2));
+    }
+
+    template<> 
+    void 
+    Pulley::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      const float beltThick = 0.01f*scale;
+
+      const float l  = 0.1f*scale;
+      const float L = ComputeRackLength();
+      const float e  = beltThick;
+      const float Ri = radius1_;
+      const float Re = Ri + e;
+      const float th = (2.*M_PI - ComputePinionBeltAngle<1>())/2.;
+      
+      
+      
+
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(Ri, l);
+      glLineWidth(1.);
+      Util::Draw::CylinderStripe(Ri, l);
+
+      Util::Color::Black.ApplyGLColor();
+      glLineWidth(2.5);
+      glBegin(GL_LINES);
+      glVertex3f(-l/2., Ri, 0.0f);
+      glVertex3f(-l/2.,-Ri, 0.0f);
+      glVertex3f( l/2., Ri, 0.0f);
+      glVertex3f( l/2.,-Ri, 0.0f);
+      glVertex3f(-l/2., 0.0f, Ri);
+      glVertex3f(-l/2., 0.0f,-Ri);
+      glVertex3f( l/2., 0.0f, Ri);
+      glVertex3f( l/2., 0.0f,-Ri);
+      glEnd();
+
+      const double rot = ComputeRotationAngle<1>()*180./M_PI;
+      glRotatef(rot, 1.0f, 0.0f, 0.0f);
+      glRotatef(180.f, 1.0f, 0.0f, 0.0f);
+      Util::Draw::Cylinder(Ri, Re, l, -th, th);
+
+      glRotatef(th*180./M_PI, 0.0f, 0.0f, 1.0f);
+      glTranslatef(-L/2., Ri + e/2, 0.0f);
+      Util::Draw::Box(L, e, l);
+      glTranslatef(L/2., -Ri - e/2, 0.0f);
+      
+      glRotatef(-2.*th*180./M_PI, 0.0f, 0.0f, 1.0f);
+      glTranslatef(L/2., Ri + e/2, 0.0f);
+      Util::Draw::Box(L, e, l);
+
+      
+    }
+
+
+    template<> 
+    void 
+    Pulley::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      const float beltThick = 0.01f*scale;
+
+      const float l  = 0.1f*scale;
+      const float e  = beltThick;
+      const float Ri = radius2_;
+      const float Re = Ri + e;
+      const float th = ComputePinionBeltAngle<1>()/2.;
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(Ri, l);
+      
+      glLineWidth(1.);
+      Util::Draw::CylinderStripe(Ri, l);
+
+      Util::Color::Black.ApplyGLColor();
+      glLineWidth(2.5);
+      glBegin(GL_LINES);
+      glVertex3f(-l/2., Ri, 0.0f);
+      glVertex3f(-l/2.,-Ri, 0.0f);
+      glVertex3f( l/2., Ri, 0.0f);
+      glVertex3f( l/2.,-Ri, 0.0f);
+      glVertex3f(-l/2., 0.0f, Ri);
+      glVertex3f(-l/2., 0.0f,-Ri);
+      glVertex3f( l/2., 0.0f, Ri);
+      glVertex3f( l/2., 0.0f,-Ri);
+      glEnd();
+
+      const double rot = ComputeRotationAngle<2>()*180./M_PI;
+      glRotatef(rot+90., 1.0f, 0.0f, 0.0f);
+      Util::Draw::Cylinder(Ri, Re, l, -th, th);
+    }
+
+
+    void 
+    Pulley::UpdatePart()
+    {
+      GetLink().GetPart2().GetCenter()[1] = interAxisLength_;
+    }
+
+
+    
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Pulley.hpp b/SRC/OpenMeca/Item/Link/Pulley.hpp
new file mode 100644
index 0000000..d8f9142
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Pulley.hpp
@@ -0,0 +1,148 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Pulley_hpp
+#define OpenMeca_Item_Link_Pulley_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkPulley.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+#include "ChronoEngine/physics/ChLinkLock.h"
+#include "ChronoEngine/physics/ChLinkLock.h"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    class Pulley : public LinkTypeBase
+    {
+
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkPulley ChLink; 
+      typedef Gui::DialogLinkPulley Dialog;
+
+
+    public:
+      Pulley(Link&);
+      ~Pulley();
+
+      void UpdatePart();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+      template <int N> chrono::ChFrame<> ComputeLocalShaft();
+      template <int N> double ComputePinionBeltAngle();
+      template <int N> double ComputeRotationAngle();
+
+      double ComputeRackLength();
+
+      // Accessors
+      OMC_ACCESSOR(Radius1        , double ,  radius1_        );
+      OMC_ACCESSOR(Radius2        , double ,  radius2_        );
+      OMC_ACCESSOR(InterAxisLength, double ,  interAxisLength_);
+
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      double radius1_;
+      double radius2_;
+      double interAxisLength_;
+      double modulus_;
+    };
+
+    template<class Archive>
+    inline void
+    Pulley::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+      ar & BOOST_SERIALIZATION_NVP(radius1_);
+      ar & BOOST_SERIALIZATION_NVP(radius2_);
+      ar & BOOST_SERIALIZATION_NVP(interAxisLength_);
+    }
+
+
+    template<int N>
+    void 
+    Pulley::BuildPoints(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "center";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+    template<int N>
+    chrono::ChFrame<>
+    Pulley::ComputeLocalShaft()
+    {
+      const Geom::Point<_3D> p(GetLink().GetPart<N>().GetCenter(), 
+			       GetLink().GetBody<N>().GetFrameFct());
+      
+      const Geom::Quaternion<_3D> q(GetLink().GetPart<N>().GetQuaternion(), 
+				    GetLink().GetBody<N>().GetFrameFct());
+      
+      const Geom::Frame<_3D> f(p, q);
+
+      return chrono::ChFrame<>(f.ToChCoordsys());
+    }
+
+  }
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Pulley> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Pulley>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Pulley> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/RackPinion.cpp b/SRC/OpenMeca/Item/Link/RackPinion.cpp
new file mode 100644
index 0000000..f3da6d7
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/RackPinion.cpp
@@ -0,0 +1,137 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/RackPinion.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    RackPinion::GetStrType()
+    {
+      return "RackPinion";
+    }
+
+    const QString 
+    RackPinion::GetQStrType()
+    {
+      return QObject::tr("RackPinion");
+    }
+
+
+    RackPinion::RackPinion(Link& link)
+      :LinkTypeBase(link),
+       ratio_(1.),
+       pinionRadius_(0.),
+       modulus_(0.001),
+       angleOfAction_(M_PI*20./180.)
+    {
+    }
+
+    RackPinion::~RackPinion()
+    {
+    }
+
+
+    template<>
+    void 
+    RackPinion::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "pinion center";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+    template<> 
+    void 
+    RackPinion::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      const float l = 0.1f*scale;
+      const float R0 = pinionRadius_;
+      const float Rb = R0*cos(angleOfAction_); 
+      
+      glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(Rb*1.01, l);
+      glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::OuterCylinderTeeth(R0, modulus_, angleOfAction_, l);
+
+    }
+
+    template<>
+    void 
+    RackPinion::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "pinion center";
+      p1->SetScaleCoordinate(0., 0.1f, 0.);
+      set.AddItem(*p1);
+    }
+
+ 
+
+    template<> 
+    void 
+    RackPinion::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      glTranslatef(.0f, -modulus_, .0f);
+      Util::Draw::StraightTeeth(modulus_, angleOfAction_, 0.1f*scale, 2.0f*scale);
+      
+      glTranslatef(.0f, 0.1f*scale/2., .0f);
+      Util::Draw::Box(2.0f*scale, 0.1f*scale, 0.1f*scale);
+
+    }
+
+
+    void 
+    RackPinion::UpdatePart()
+    {
+      GetLink().GetPart2().GetCenter()[1] = pinionRadius_ + modulus_;
+      
+    }
+
+
+    
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/RackPinion.hpp b/SRC/OpenMeca/Item/Link/RackPinion.hpp
new file mode 100644
index 0000000..fadc713
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/RackPinion.hpp
@@ -0,0 +1,139 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_RackPinion_hpp
+#define OpenMeca_Item_Link_RackPinion_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkRackPinion.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+#include "ChronoEngine/physics/ChLinkRackpinion.h"
+#include "ChronoEngine/physics/ChLinkLock.h"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    class RackPinion : public LinkTypeBase
+    {
+
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkRackpinion ChLink; 
+      typedef Gui::DialogLinkRackPinion Dialog;
+
+
+    public:
+      RackPinion(Link&);
+      ~RackPinion();
+
+      void UpdatePart();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+      template <int N> double ComputeRadius();
+      template <int N> chrono::ChFrame<> ComputeChFrame();
+
+      // Accessors
+      OMC_ACCESSOR(Ratio          , double ,  ratio_          );
+      OMC_ACCESSOR(PinionRadius   , double ,  pinionRadius_);
+      OMC_ACCESSOR(Modulus        , double ,  modulus_);
+      OMC_ACCESSOR(AngleOfAction  , double ,  angleOfAction_);
+
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      double ratio_;
+      double pinionRadius_;
+      double modulus_;
+      double angleOfAction_;
+    };
+
+    template<class Archive>
+    inline void
+    RackPinion::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+      ar & BOOST_SERIALIZATION_NVP(ratio_);
+      ar & BOOST_SERIALIZATION_NVP(pinionRadius_);
+      ar & BOOST_SERIALIZATION_NVP(modulus_);
+      ar & BOOST_SERIALIZATION_NVP(angleOfAction_);
+    }
+
+
+   
+
+    template<int N>
+    chrono::ChFrame<>
+    RackPinion::ComputeChFrame()
+    {
+      const Geom::Point<_3D> p(GetLink().GetPart<N>().GetCenter(), 
+			       GetLink().GetBody<N>().GetFrameFct());
+      
+      const Geom::Quaternion<_3D> q(GetLink().GetPart<N>().GetQuaternion(), 
+				    GetLink().GetBody<N>().GetFrameFct());
+      
+      const Geom::Frame<_3D> f(p, q);
+
+      return chrono::ChFrame<>(f.ToChCoordsys());
+    }
+
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::RackPinion> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::RackPinion>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::RackPinion> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Revolute.cpp b/SRC/OpenMeca/Item/Link/Revolute.cpp
new file mode 100644
index 0000000..40c4e31
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Revolute.cpp
@@ -0,0 +1,122 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Revolute.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Revolute::GetStrType()
+    {
+      return "Revolute";
+    }
+
+    const QString 
+    Revolute::GetQStrType()
+    {
+      return QObject::tr("Revolute");
+    }
+
+
+   Revolute::Revolute(Link& link)
+      :LinkTypeBase(link)
+    {
+    }
+
+    Revolute::~Revolute()
+    {
+    }
+
+    template<> 
+    void 
+    Revolute::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 1.0f*scale);
+
+      glRotatef(90.0f, 0.0f, 0.0f, 1.0f);
+      glTranslatef(0.0f, 0.35f*scale, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 0.1f*scale);
+      glTranslatef(0.0f, -2*0.35f*scale, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 0.1f*scale);
+    }
+
+    
+
+    template<>
+    void 
+    Revolute::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      PartPoint* p3 = new PartPoint(item);
+      p1->GetName() = "left";
+      p1->SetScaleCoordinate(0., 0., -0.5);
+      p2->GetName() = "middle";
+      p2->SetScaleCoordinate(0., 0., 0.);
+      p3->GetName() = "right";
+      p3->SetScaleCoordinate(0., 0., 0.5);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+      set.AddItem(*p3);
+    }
+
+
+    template<> 
+    void 
+    Revolute::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.1f*scale, 0.6f*scale);
+    }
+
+
+    template<>
+    void 
+    Revolute::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Revolute.hpp b/SRC/OpenMeca/Item/Link/Revolute.hpp
new file mode 100644
index 0000000..d1bc4f9
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Revolute.hpp
@@ -0,0 +1,96 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Revolute_hpp
+#define OpenMeca_Item_Link_Revolute_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+
+namespace OpenMeca
+{    
+  namespace Item
+  {
+
+    class Revolute : public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkLockRevolute ChLink; 
+      typedef Gui::DialogLinkT< LinkT<Revolute> > Dialog;
+
+    public:
+      Revolute(Link&);
+      ~Revolute();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    };
+
+    template<class Archive>
+    inline void
+    Revolute::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+    }
+
+   
+  }
+
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Revolute> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Revolute>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Revolute> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Screw.cpp b/SRC/OpenMeca/Item/Link/Screw.cpp
new file mode 100644
index 0000000..293233b
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Screw.cpp
@@ -0,0 +1,149 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Screw.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Screw::GetStrType()
+    {
+      return "Screw";
+    }
+
+    const QString
+    Screw::GetQStrType()
+    {
+      return QObject::tr("Screw");
+    }
+
+    Screw::Screw(Link& link)
+      :LinkTypeBase(link),
+       tau_(0.)
+    {
+    }
+    
+    Screw::~Screw()
+    {
+    }
+
+    template<> 
+    void 
+    Screw::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      const float r = 0.1f*scale;
+      const float l = 0.6f*scale;
+
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(r,l);
+
+    }
+
+    
+
+    template<>
+    void 
+    Screw::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+
+    }
+
+
+    template<> 
+    void 
+    Screw::DrawPart<2>()
+    {
+      const double tau = tau_;
+      const double scale = Part::GetScaleValue();
+      const GLfloat r = 0.01f*scale;
+      const GLfloat l = 1.0f*scale;
+
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(r, l);
+
+      // draw helical part
+      if (tau > 0.)
+	{
+	  glBegin(GL_TRIANGLE_STRIP);
+	  bool loop = true;
+	  float x = -l/2.;
+	  float a = 0.;
+	  do 
+	    {
+	      glVertex3f(x, r*cos(a)   , r*sin(a));
+	      glVertex3f(x, r*2.*cos(a), r*2.*sin(a));
+	      a += M_PI/100.; 
+	      x = (-l/2.) + (a * tau);
+	      if (x > l/2)
+		loop = false;
+	    }
+	  while(loop == true);
+	  glEnd();
+	}
+
+    }
+
+
+    template<>
+    void 
+    Screw::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      PartPoint* p3 = new PartPoint(item);
+      p1->GetName() = "left";
+      p1->SetScaleCoordinate(0., 0., -0.5);
+      p2->GetName() = "middle";
+      p2->SetScaleCoordinate(0., 0., 0.);
+      p3->GetName() = "right";
+      p3->SetScaleCoordinate(0., 0., 0.5);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+      set.AddItem(*p3);
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Screw.hpp b/SRC/OpenMeca/Item/Link/Screw.hpp
new file mode 100644
index 0000000..c245468
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Screw.hpp
@@ -0,0 +1,106 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Screw_hpp
+#define OpenMeca_Item_Link_Screw_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkScrew.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+namespace OpenMeca
+{    
+  namespace Item
+  {
+   
+
+    struct Screw : public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkScrew ChLink; 
+      typedef Gui::DialogLinkScrew Dialog;
+
+    public:
+      Screw(Link&);
+      ~Screw();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+      // Accessors
+      OMC_ACCESSOR(Tau , double,  tau_);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      double tau_;
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Screw::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+      ar & BOOST_SERIALIZATION_NVP(tau_);
+    }
+
+
+  }
+
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Screw> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Screw>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Screw> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Slider.cpp b/SRC/OpenMeca/Item/Link/Slider.cpp
new file mode 100644
index 0000000..6d6be45
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Slider.cpp
@@ -0,0 +1,141 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Slider.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Slider::GetStrType()
+    {
+      return "Slider";
+    }
+
+    const QString 
+    Slider::GetQStrType()
+    {
+      return QObject::tr("Slider");
+    }
+
+    Slider::Slider(Link& link)
+      :LinkTypeBase(link)
+    {
+    }
+
+    Slider::~Slider()
+    {
+    }
+
+
+    template<> 
+    void 
+    Slider::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      float Lx = 0.2f*scale;
+      float Ly = 0.2f*scale;
+      float Lz = 0.6f*scale;
+      Util::Draw::Box(Lx,Ly,Lz);
+      
+      Lx = Lx/2;
+      Ly = Ly/2;
+      Lz = Lz/2;
+      glColor3f(0.0f, 0.0f, 0.0f);
+      
+      glDisable(GL_LIGHTING);
+      glLineWidth(3.0f);
+      glBegin(GL_LINES);
+      glVertex3f(Lx,Ly,Lz);
+      glVertex3f(-Lx,-Ly,Lz);
+      glVertex3f(Lx,-Ly,Lz);
+      glVertex3f(-Lx,Ly,Lz);
+      glVertex3f(Lx,Ly,-Lz);
+      glVertex3f(-Lx,-Ly,-Lz);
+      glVertex3f(Lx,-Ly,-Lz);
+      glVertex3f(-Lx,Ly,-Lz);
+      
+      glEnd();
+      glEnable(GL_LIGHTING);
+      glLineWidth(1.0f);
+      
+    }
+
+    
+
+    template<>
+    void 
+    Slider::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "middle";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+
+    template<> 
+    void 
+    Slider::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+      Util::Draw::Cylinder(0.01f*scale, 1.0f*scale);
+    }
+
+
+    template<>
+    void 
+    Slider::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      PartPoint* p3 = new PartPoint(item);
+      p1->GetName() = "left";
+      p1->SetScaleCoordinate(0., 0., -0.5);
+      p2->GetName() = "middle";
+      p2->SetScaleCoordinate(0., 0., 0.);
+      p3->GetName() = "right";
+      p3->SetScaleCoordinate(0., 0., 0.5);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+      set.AddItem(*p3);
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Slider.hpp b/SRC/OpenMeca/Item/Link/Slider.hpp
new file mode 100644
index 0000000..19c2fa6
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Slider.hpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Slider_hpp
+#define OpenMeca_Item_Link_Slider_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+  
+    class Slider : public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkLockPrismatic ChLink; 
+      typedef Gui::DialogLinkT< LinkT<Slider> > Dialog;
+ 
+    public:
+      Slider(Link&);
+      ~Slider();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Slider::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+    }
+
+
+   
+  }
+
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Slider> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Slider>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Slider> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Spherical.cpp b/SRC/OpenMeca/Item/Link/Spherical.cpp
new file mode 100644
index 0000000..e4b12c1
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Spherical.cpp
@@ -0,0 +1,117 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Spherical.hpp" 
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    const std::string 
+    Spherical::GetStrType()
+    {
+      return "Spherical";
+    }
+
+    const QString 
+    Spherical::GetQStrType()
+    {
+      return QObject::tr("Spherical");
+    }
+
+    Spherical::Spherical(Link& link)
+      :LinkTypeBase(link)
+    {
+    }
+
+    Spherical::~Spherical()
+    {
+    }
+
+    template<> 
+    void 
+    Spherical::DrawPart<1>()
+    {
+      const double scale = Part::GetScaleValue();
+      static GLUquadric* quadric = gluNewQuadric();
+      glRotatef(90.0, 0.0f, 1.0f, 0.0f);
+      Util::Draw::PartialSphere(0.2f*scale, 30, 0, 0, M_PI, -M_PI/2., M_PI/2.);
+      glRotatef(180.0, 0.0f, 1.0f, 0.0f);
+      gluDisk(quadric, 0.0f, 0.2f*scale, 30, 1);
+    }
+
+    
+
+    template<>
+    void 
+    Spherical::BuildPoints<1>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      p1->GetName() = "center";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      p2->GetName() = "up";
+      p2->SetScaleCoordinate(0.2, 0., 0.);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+    }
+
+
+    template<> 
+    void 
+    Spherical::DrawPart<2>()
+    {
+      const double scale = Part::GetScaleValue();
+      Util::Draw::Sphere(0.15f*scale);
+    }
+
+
+    template<>
+    void 
+    Spherical::BuildPoints<2>(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      PartPoint* p2 = new PartPoint(item);
+      p1->GetName() = "center";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      p2->GetName() = "up";
+      p2->SetScaleCoordinate(-0.15, 0., 0.);
+      set.AddItem(*p1);
+      set.AddItem(*p2);
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Spherical.hpp b/SRC/OpenMeca/Item/Link/Spherical.hpp
new file mode 100644
index 0000000..dc97190
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Spherical.hpp
@@ -0,0 +1,97 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Spherical_hpp
+#define OpenMeca_Item_Link_Spherical_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    class Spherical : public LinkTypeBase
+    {
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkLockSpherical ChLink; 
+      typedef Gui::DialogLinkT< LinkT<Spherical > > Dialog;
+
+    public:
+      Spherical(Link&);
+      ~Spherical();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Spherical::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+    }
+
+   
+  }
+
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Spherical> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Spherical>::BuildIconSymbol(iconSymbol_);
+    }
+    
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Spherical> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+    
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link/Spring.cpp b/SRC/OpenMeca/Item/Link/Spring.cpp
new file mode 100644
index 0000000..0527604
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Spring.cpp
@@ -0,0 +1,133 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Link/Spring.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Drawable.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "OpenMeca/Core/Drawable.hpp" 
+#include "OpenMeca/Item/PartPoint.hpp" 
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Item/LinkT.hpp" 
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    const std::string 
+    Spring::GetStrType()
+    {
+      return "Spring";
+    }
+
+    const QString 
+    Spring::GetQStrType()
+    {
+      return QObject::tr("Spring");
+    }
+
+    Spring::Spring(Link& link)
+      :LinkTypeBase(link),
+       stiffness_(0.),
+       dampingFactor_(0.),
+       freeLength_(0.),
+       initialLength_(0.)
+    {
+    }
+
+    Spring::~Spring()
+    {
+    }
+
+    
+    void 
+    Spring::BeginDraw1()
+    {
+      const Geom::Vector<_3D> axis_glob(GetStartPoint<1>(), GetStartPoint<2>());
+      const Geom::Vector<_3D> axis_loc (axis_glob.Unit(), GetLink().GetFrameFctBody<1>());
+      const Geom::Vector<_3D>& z = GetLink().GetFrameBody<1>().GetZAxis();
+      GetLink().GetPart1().GetQuaternion().SetVecFromTo(z, axis_loc);
+      Geom::Point<_3D> p3(GetStartPoint<2>(), GetLink().GetPart1().GetFrameFct());
+    }
+    
+
+
+    template<> 
+    void 
+    Spring::DrawPart<1>()
+    {
+      
+      const double scale = Part::GetScaleValue();
+      
+      // Draw helicoid
+      const float length     = GetCurrentLength();
+      const int loopNumber   = 10;
+      const int step         = 200.0;
+      const float stepLength = length/float(step);
+      const float radius      = 0.2f*scale;
+
+      glDisable(GL_LIGHTING);
+      glColor3f(0.0, 0.0, 0.0);
+      glLineWidth(1.0f);
+      glBegin(GL_LINE_STRIP);
+      glVertex3f(0.f, 0.f, 0.f);
+      for (float l=0; l < length; l = l + stepLength)
+	{
+	  const float alpha = (2*M_PI*l/length)*float(loopNumber);
+	  glVertex3f(radius*cos(alpha), radius*sin(alpha), l);
+	}
+      glVertex3f(radius, 0.0f, length);
+      glVertex3f(0.f, 0.f, length);
+      glEnd();
+      glEnable(GL_LIGHTING);
+    }
+
+    template<> 
+    void 
+    Spring::DrawPart<2>()
+    {
+    }
+
+
+    void 
+    Spring::UpdatePart()
+    {
+      GetLink().GetPart1().GetCenter()[2] = -initialLength_/2.;
+      GetLink().GetPart2().GetCenter()[2] =  initialLength_/2.;
+
+    }
+
+    double 
+    Spring::GetCurrentLength()
+    {
+      return Geom::Vector<_3D>(GetStartPoint<1>(), GetStartPoint<2>()).GetNorm();
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Link/Spring.hpp b/SRC/OpenMeca/Item/Link/Spring.hpp
new file mode 100644
index 0000000..cdf5446
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link/Spring.hpp
@@ -0,0 +1,149 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Link_Spring_hpp
+#define OpenMeca_Item_Link_Spring_hpp
+
+#include <string>
+#include <QIcon>
+#include <QColor>
+
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Item/Link/LinkTypeBase.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkSpring.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link_CreateAction_SpecializedT.hpp"
+
+#include "ChronoEngine/physics/ChLinkLock.h"
+#include "ChronoEngine/physics/ChLinkLock.h"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    class Spring : public LinkTypeBase
+    {
+
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      typedef chrono::ChLinkSpring ChLink; 
+      typedef Gui::DialogLinkSpring Dialog;
+
+
+    public:
+      Spring(Link&);
+      ~Spring();
+
+      void UpdatePart();
+      double GetCurrentLength();
+
+      template <int N> void DrawPart();
+      template <int N> void BuildPoints(Core::SetOf<PartPoint>&, Core::DrawableUserItem&);
+      template <int N> Geom::Point<_3D> GetStartPoint() const;
+
+      void BeginDraw1();
+
+      // Accessors
+      OMC_ACCESSOR(Stiffness      , double ,  stiffness_    );
+      OMC_ACCESSOR(DampingFactor  , double ,  dampingFactor_);
+      OMC_ACCESSOR(FreeLength     , double ,  freeLength_   );
+      OMC_ACCESSOR(InitialLength  , double ,  initialLength_);
+
+      
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      double stiffness_;
+      double dampingFactor_;
+      double freeLength_;
+      double initialLength_;
+    };
+
+    template<class Archive>
+    inline void
+    Spring::serialize(Archive& ar, const unsigned int version)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(LinkTypeBase);
+      ar & BOOST_SERIALIZATION_NVP(stiffness_);
+      ar & BOOST_SERIALIZATION_NVP(dampingFactor_);
+      ar & BOOST_SERIALIZATION_NVP(freeLength_);
+      if (version > 0)
+	{
+	  ar & BOOST_SERIALIZATION_NVP(initialLength_);
+	}
+    }
+
+    template<int N>
+    Geom::Point<_3D>
+    Spring::GetStartPoint() const
+    {
+      const Geom::Point<_3D> p(0., 0., 0., GetLink().GetPart<N>().GetFrameFct());
+      return p.ToGlobalFrame();
+    }
+
+    template<int N>
+    void 
+    Spring::BuildPoints(Core::SetOf<PartPoint>& set, Core::DrawableUserItem& item)
+    {
+      OMC_ASSERT_MSG(set.GetTotItemNumber()==0, "The number of point is not null");
+      PartPoint* p1 = new PartPoint(item);
+      p1->GetName() = "center";
+      p1->SetScaleCoordinate(0., 0., 0.);
+      set.AddItem(*p1);
+    }
+
+
+  }
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<> 
+    inline void
+    ItemCommonProperty< OpenMeca::Item::LinkT<OpenMeca::Item::Spring> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::LinkT<OpenMeca::Item::Spring>::BuildIconSymbol(iconSymbol_);
+    }
+
+    template<>
+    inline void
+    UserItemCommonProperty<OpenMeca::Item::LinkT<OpenMeca::Item::Spring> >::CreateAction_Specialized() 
+    {
+      OpenMeca::Item::Link_CreateAction_SpecializedT(*this);
+    }
+
+
+  }
+}
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Item::Spring, 1)
+
+#endif
diff --git a/SRC/OpenMeca/Item/LinkT.cpp b/SRC/OpenMeca/Item/LinkT.cpp
new file mode 100644
index 0000000..f306586
--- /dev/null
+++ b/SRC/OpenMeca/Item/LinkT.cpp
@@ -0,0 +1,232 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/UserRootItemCommonProperty.hpp"
+
+#include "OpenMeca/Item/Link/All.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Cylindrical>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Gear>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Pulley>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::RackPinion>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Spring>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Motor>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::LinearMotor>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Planar>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::PointLine>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::PointPlane>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Revolute>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Screw>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Slider>)
+BOOST_CLASS_EXPORT(OpenMeca::Item::LinkT<OpenMeca::Item::Spherical>)
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    
+    template<>
+    void
+    LinkT<Cylindrical>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildDefaultChSystem(chSystem);
+    }
+
+    template<>
+    void
+    LinkT<Planar>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildDefaultChSystem(chSystem);
+    }
+
+    template<>
+    void
+    LinkT<PointLine>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildDefaultChSystem(chSystem);
+    }
+
+    template<>
+    void
+    LinkT<PointPlane>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildDefaultChSystem(chSystem);
+    }
+
+    template<>
+    void
+    LinkT<Revolute>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildDefaultChSystem(chSystem);
+    }
+
+    template<>
+    void
+    LinkT<Slider>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildDefaultChSystem(chSystem);
+    }
+
+    template<>
+    void
+    LinkT<Spherical>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildDefaultChSystem(chSystem);
+    }
+
+
+
+    template<>
+    void
+    LinkT<Motor>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, GetFrame().ToChCoordsys_Global());
+      chLinkPtr_->Set_eng_mode(chrono::ChLinkEngine::ENG_MODE_SPEED);
+      chLinkPtr_->Set_spe_funct(linkType_.GetVelocity().new_Duplicate());
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+    template<>
+    void
+    LinkT<LinearMotor>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, GetFrame().ToChCoordsys_Global());
+      chLinkPtr_->SetMotion_Z (linkType_.GetDisplacement().new_Duplicate());
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+    template<>
+    void
+    LinkT<Screw>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, GetFrame().ToChCoordsys_Global());
+      chLinkPtr_->Set_tau(linkType_.GetTau());
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+    template<>
+    void
+    LinkT<Gear>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, chrono::CSYSNORM);
+      chLinkPtr_->Set_local_shaft1(GetLinkType().ComputeLocalShaft<1>());
+      chLinkPtr_->Set_local_shaft2(GetLinkType().ComputeLocalShaft<2>());
+
+      chLinkPtr_->Set_alpha(linkType_.GetAngleOfAction());
+      chLinkPtr_->Set_beta(0.);
+      chLinkPtr_->Set_phase(0.);
+      chLinkPtr_->Set_tau(linkType_.GetRatio());
+      chLinkPtr_->Set_checkphase(false);
+      
+      if (linkType_.GetInternalTeeth())
+	chLinkPtr_->Set_epicyclic(1);
+      else
+	chLinkPtr_->Set_epicyclic(0);
+
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+
+    template<>
+    void
+    LinkT<Pulley>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, chrono::CSYSNORM);
+      chLinkPtr_->Set_local_shaft1(GetLinkType().ComputeLocalShaft<1>());
+      chLinkPtr_->Set_local_shaft2(GetLinkType().ComputeLocalShaft<2>());
+
+      chLinkPtr_->Set_r1(linkType_.GetRadius1());
+      chLinkPtr_->Set_r2(linkType_.GetRadius2());
+      chLinkPtr_->Set_phase(0.);
+      chLinkPtr_->Set_checkphase(false);
+      
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+
+    template<>
+    void
+    LinkT<RackPinion>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      chrono::ChFrame<> f1(GetBody1().GetFrame().ToChCoordsys());
+      chrono::ChFrame<> f2(GetBody2().GetFrame().ToChCoordsys());
+
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, true, f1, f2);
+      chLinkPtr_->SetPinionFrame(GetLinkType().ComputeChFrame<1>());
+      chLinkPtr_->SetRackFrame(GetLinkType().ComputeChFrame<2>());
+      chLinkPtr_->SetPinionRadius(GetLinkType().GetPinionRadius());
+      chLinkPtr_->SetAlpha(linkType_.GetAngleOfAction());
+      chLinkPtr_->SetBeta(0.);
+      chLinkPtr_->SetPhase(0.);
+      chLinkPtr_->SetCheckphase(false);
+      
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+    template<>
+    void
+    LinkT<Spring>::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      
+      const Geom::Point<_3D> p1 = GetLinkType().GetStartPoint<1>();
+      const Geom::Point<_3D> p2 = GetLinkType().GetStartPoint<2>();
+
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, false, p1.ToChVector(), p2.ToChVector());
+      chLinkPtr_->Set_SpringK (GetLinkType().GetStiffness());
+      chLinkPtr_->Set_SpringRestLenght (GetLinkType().GetFreeLength());
+      chLinkPtr_->Set_SpringR (GetLinkType().GetDampingFactor());
+      chLinkPtr_->Set_SpringF (0);
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+  
+
+
+  }
+
+}
+
diff --git a/SRC/OpenMeca/Item/LinkT.hpp b/SRC/OpenMeca/Item/LinkT.hpp
new file mode 100644
index 0000000..060cd35
--- /dev/null
+++ b/SRC/OpenMeca/Item/LinkT.hpp
@@ -0,0 +1,324 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_LinkT_hpp
+#define OpenMeca_Item_LinkT_hpp
+
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/Link.hpp"
+#include "OpenMeca/Item/PartLinkT.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLinkT.hpp"
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    class Body;
+
+    // The link class that model mechanical link.
+    // The 'T' type is used to define the link type, 'LinkT<Revolute>' for example.
+    template <class T>
+    class LinkT: public Link , public Core::AutoRegister< LinkT<T> >
+    {
+    
+    public:
+      static const std::string GetStrType() {return T::GetStrType();}; 
+      static const QString GetQStrType() {return T::GetQStrType();}; 
+
+      static void Init();
+      static void BuildIconSymbol(QIcon&);
+      static void DrawIcon(QIcon& icon, QColor color1, QColor color2);
+
+      typedef typename T::Dialog Dialog;
+
+    public:
+      LinkT<T>();
+      LinkT<T>(Body&, Body&);
+      ~LinkT<T>();
+
+      void BuildChSystem(chrono::ChSystem&);
+      template<int N> void UpdatePartIcon(QIcon& icon);
+
+      T& GetLinkType();
+      const T& GetLinkType() const;
+      virtual void Update();
+
+      Part& GetPart1();
+      const Part& GetPart1() const;
+
+      Part& GetPart2();
+      const Part& GetPart2() const;
+
+      chrono::ChLink& GetChLink();
+
+    private:
+      void UpdateIcon();
+      Core::SetOfBase<Core::UserItem> GetAssociatedSelectedItem();
+      void BuildChSystemInit();
+      void BuildDefaultChSystem(chrono::ChSystem&);
+
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    private:
+      chrono::ChSharedPtr<typename T::ChLink> chLinkPtr_;
+      PartLinkT<T,1>* partBody1_;
+      PartLinkT<T,2>* partBody2_;
+      T linkType_;
+    
+    };
+
+    template <class T>  
+    template<class Archive>
+    inline void
+    LinkT<T>::save(Archive& ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(Link);
+      ar << partBody1_;
+      ar << partBody2_;
+      ar << linkType_;
+    }
+
+
+    template <class T>  
+    template<class Archive>
+    inline void
+    LinkT<T>::load(Archive& ar, const unsigned int)
+    {
+      delete partBody1_;
+      delete partBody2_;
+      partBody1_ = 0;
+      partBody2_ = 0;
+
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(Link);
+      ar >> partBody1_;
+      ar >> partBody2_;
+      ar >> linkType_;
+    }
+    
+
+    template <class T>  
+    inline void 
+    LinkT<T>::DrawIcon(QIcon& icon, QColor color1, QColor color2)
+    {
+      const QString iconFile = ":/Rsc/Img/Link/" + QString(T::GetStrType().c_str()) + ".svg";
+      QSvgRenderer svgRenderer(Util::Icon::ChangeColorInSvgFile(iconFile,
+			       Qt::red, color1, Qt::blue, color2));
+      
+      // render it on pixmap and translate to icon
+      const int size = Gui::MainWindow::Get().GetIconSize();
+      QPixmap pixmap(QSize(size,size));
+      pixmap.fill(QColor (0, 0, 0, 0));
+      QPainter painter(&pixmap);
+      svgRenderer.render( &painter);
+      icon =  QIcon(pixmap);
+    }
+
+
+    
+
+    template <class T> 
+    inline void 
+    LinkT<T>::Init()
+    {
+      Core::Singleton< Core::UserItemCommonProperty< LinkT<T> > >::Get().CreateAction_All();
+    }
+     
+
+      
+    template <class T> 
+    inline
+    LinkT<T>::LinkT()
+      :Link(LinkT<T>::GetStrType()),
+       chLinkPtr_(0),
+       partBody1_(new PartLinkT<T,1>(*this)),
+       partBody2_(new PartLinkT<T,2>(*this)),
+       linkType_(*this)
+    {
+    }
+
+    template <class T> 
+    inline
+    LinkT<T>::LinkT(Body& body1, Body& body2)
+    :Link(LinkT<T>::GetStrType(), body1, body2),
+     chLinkPtr_(0),
+     partBody1_(new PartLinkT<T,1>(*this)),
+     partBody2_(new PartLinkT<T,2>(*this)),
+     linkType_(*this)
+    {
+    }
+
+    template <class T> 
+    inline
+    LinkT<T>::~LinkT()
+    {
+      // When deleting the chLinkPtr_ attribute, 
+      // chronoengine automatically delete the chLinkType_ attribute
+    }
+
+    
+  template <class T> 
+  inline void 
+  LinkT<T>::UpdateIcon()
+  {
+    const QColor color1 = GetBody1().GetColor().GetQColor();
+    const QColor color2 = GetBody2().GetColor().GetQColor();
+    LinkT<T>::DrawIcon(GetIcon(), color1, color2);
+  }
+
+  template <class T> 
+  template <int N> 
+  inline void 
+  LinkT<T>::UpdatePartIcon(QIcon& icon)
+  {
+    const QColor color1 = GetBody1().GetColor().GetQColor();
+    const QColor color2 = GetBody2().GetColor().GetQColor();
+    if (N==1)
+      LinkT<T>::DrawIcon(icon, color1, Qt::white);
+    else if (N==2)
+      LinkT<T>::DrawIcon(icon, Qt::white, color2);
+    else
+      OMC_ASSERT_MSG(0, "This case is forbidden");
+  }
+
+
+
+
+    template <class T> 
+    inline Core::SetOfBase<Core::UserItem> 
+    LinkT<T>::GetAssociatedSelectedItem()
+    {
+      Core::SetOfBase<Core::UserItem> set;
+      set.AddItem(*partBody1_);
+      set.AddItem(*partBody2_);
+      return set;
+    }
+
+    template <class T> 
+    inline T& LinkT<T>::GetLinkType()
+    {
+      return linkType_;
+    }
+
+    template <class T> 
+    inline const T& LinkT<T>::GetLinkType() const
+    {
+      return linkType_;
+    }
+
+    template <class T> 
+    inline void
+    LinkT<T>::BuildChSystemInit()
+    {
+      chLinkPtr_ = chrono::ChSharedPtr<typename T::ChLink>(new typename T::ChLink());
+    }
+
+    template <class T> 
+    inline void
+    LinkT<T>::Update()
+    {
+      Link::Update();
+      partBody1_->ChangeParentTreeItem(Link::GetBody<1>().GetMainTreeItem());
+      partBody2_->ChangeParentTreeItem(Link::GetBody<2>().GetMainTreeItem());
+      
+    }
+
+    template<class T>
+    inline void
+    LinkT<T>::BuildDefaultChSystem(chrono::ChSystem& chSystem)
+    {
+      BuildChSystemInit();
+      chrono::ChSharedBodyPtr& b1Ptr = GetBody1().GetChBodyPtr();
+      chrono::ChSharedBodyPtr& b2Ptr = GetBody2().GetChBodyPtr();
+      chLinkPtr_->Initialize(b1Ptr, b2Ptr, GetFrame().ToChCoordsys_Global());
+      chSystem.AddLink(chLinkPtr_);
+    }
+
+    template<class T>
+    inline chrono::ChLink&
+    LinkT<T>::GetChLink()
+    {
+      return *chLinkPtr_.get();
+    }
+
+
+    template<class T>
+    inline  void 
+    LinkT<T>::BuildIconSymbol(QIcon& icon)
+    {
+      const QString file = QString(":/Rsc/Img/Link/") + QString(T::GetStrType().c_str()) + QString(".svg");
+      QSvgRenderer svgRenderer(file);
+      const int size = Gui::MainWindow::Get().GetIconSize();
+      QPixmap pixmap(QSize(size,size));
+      pixmap.fill(QColor (0, 0, 0, 0));
+      QPainter painter(&pixmap);
+      svgRenderer.render( &painter);
+      icon =  QIcon(pixmap);
+    }
+
+    template<class T>
+    inline Part& 
+    LinkT<T>::GetPart1()
+    {
+      OMC_ASSERT_MSG(partBody1_ != 0, "The required pointer is null");
+      return *partBody1_;
+    }
+
+    template<class T>
+    inline const Part& 
+    LinkT<T>::GetPart1() const
+    {
+      OMC_ASSERT_MSG(partBody1_ != 0, "The required pointer is null");
+      return *partBody1_;
+    }
+
+    template<class T>
+    inline Part& 
+    LinkT<T>::GetPart2()
+    {
+      OMC_ASSERT_MSG(partBody2_ != 0, "The required pointer is null");
+      return *partBody2_;
+    }
+    
+    template<class T>
+    inline const Part& 
+    LinkT<T>::GetPart2() const
+    {
+      OMC_ASSERT_MSG(partBody2_ != 0, "The required pointer is null");
+      return *partBody2_;
+    }
+
+    
+  }
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Link_CreateAction_SpecializedT.hpp b/SRC/OpenMeca/Item/Link_CreateAction_SpecializedT.hpp
new file mode 100644
index 0000000..f542069
--- /dev/null
+++ b/SRC/OpenMeca/Item/Link_CreateAction_SpecializedT.hpp
@@ -0,0 +1,57 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Item_Link_CreateAction_SpecializedT_hpp
+#define OpenMeca_Item_Link_CreateAction_SpecializedT_hpp
+
+
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Item/How/GetReacForce.hpp"
+#include "OpenMeca/Item/How/GetReacTorque.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    template<class T>
+    inline void
+    Link_CreateAction_SpecializedT(OpenMeca::Core::UserItemCommonProperty<T>& t)
+    {
+      t.AddPopUpSeparator();
+      const QIcon emptyIcon;
+      const std::string sensorTitle = "Sensor";
+
+      typedef OpenMeca::Item::How::GetReacForce::MySensor SensorReacForce;
+      typedef OpenMeca::Item::How::GetReacTorque::MySensor SensorReacTorque;
+      Core::Singleton<Core::UserItemCommonProperty<SensorReacForce> >::Instanciate();
+      Core::Singleton<Core::UserItemCommonProperty<SensorReacTorque> >::Instanciate();
+      t.template CreateAction_NewWithSelection<SensorReacForce>();
+      t.template CreateAction_NewWithSelection<SensorReacTorque>();
+
+    
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Load.cpp b/SRC/OpenMeca/Item/Load.cpp
new file mode 100644
index 0000000..f2e952a
--- /dev/null
+++ b/SRC/OpenMeca/Item/Load.cpp
@@ -0,0 +1,79 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include "OpenMeca/Item/Load.hpp"
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/RootTreeItemT.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::Load)
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {    
+
+    const std::string 
+    Load::GetStrType()
+    {
+      return std::string("Load");
+    }
+
+    const QString 
+    Load::GetQStrType()
+    {
+      return QObject::tr("Load");
+    }
+
+       
+    Load::Load(const std::string strType, QTreeWidgetItem& parentTreeItem)
+      :Physical(strType, parentTreeItem),
+       treeItem_(0)
+    {
+      QTreeWidgetItem& rootItem = Gui::RootTreeItemT<Load>::Get();
+      Core::Item& me = *this;
+      treeItem_ = new Gui::SecondaryTreeItem(rootItem, me);
+      AddSecondaryTreeItem(*treeItem_);
+    }
+    
+    Load::~Load()
+    {      
+      delete treeItem_;
+    }
+
+
+    bool 
+    Load::IsLoad() const
+    {
+      return true;
+    }
+    
+    bool 
+    Load::IsSensor() const
+    {
+      return false;
+    }
+
+
+  } 
+}
diff --git a/SRC/OpenMeca/Item/Load.hpp b/SRC/OpenMeca/Item/Load.hpp
new file mode 100644
index 0000000..e7f118d
--- /dev/null
+++ b/SRC/OpenMeca/Item/Load.hpp
@@ -0,0 +1,68 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_Load_hpp_
+#define _OpenMeca_Item_Load_hpp_
+
+
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+
+
+    class Load : public Physical, public Core::AutoRegister<Load>
+    {
+
+    public:
+      static const std::string GetStrType(); 
+      static const QString GetQStrType(); 
+   
+    public:
+      Load(const std::string strType, QTreeWidgetItem& parentTreeItem);
+      virtual ~Load();
+
+      virtual void Apply() = 0;
+      bool IsLoad() const;
+      bool IsSensor() const;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    protected:
+      Gui::SecondaryTreeItem* treeItem_;
+
+    };
+    
+
+    template<class Archive>
+    inline void
+    Load::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Physical);
+    }
+
+  }
+} 
+
+#endif
diff --git a/SRC/OpenMeca/Item/LoadT.cpp b/SRC/OpenMeca/Item/LoadT.cpp
new file mode 100644
index 0000000..c77bcd5
--- /dev/null
+++ b/SRC/OpenMeca/Item/LoadT.cpp
@@ -0,0 +1,33 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include "OpenMeca/Item/LoadT.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+
+
+  }
+} 
+
+
diff --git a/SRC/OpenMeca/Item/LoadT.hpp b/SRC/OpenMeca/Item/LoadT.hpp
new file mode 100644
index 0000000..00e5a7f
--- /dev/null
+++ b/SRC/OpenMeca/Item/LoadT.hpp
@@ -0,0 +1,304 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_LoadT_hpp_
+#define _OpenMeca_Item_LoadT_hpp_
+
+
+#include "OpenMeca/Item/Load.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+#include "OpenMeca/Gui/Dialog/DialogLoadT.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+
+   
+
+    template<class Parent, class Quantity, class How>
+    class LoadT : public Load, 
+		  public Core::AutoRegister<LoadT<Parent, Quantity, How> >
+    {
+    public:  
+      static const std::string GetStrType(); 
+      static const QString GetQStrType(); 
+      static void Init();
+      static void DrawIcon(QIcon&, QColor);
+      typedef Gui::DialogLoadT<Parent, Quantity, How> Dialog;
+
+    public:      
+      LoadT(Parent&);
+      ~LoadT();
+
+      void UpdateIcon();
+      void DrawShape();
+      void BeginDraw();
+      void EndDraw();
+      Quantity& GetQuantity();
+      const Quantity& GetQuantity() const;
+
+      void Apply();
+      void BuildChSystem(chrono::ChSystem&);
+
+
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+      
+      virtual const Geom::Frame<_3D>& GetFrame() const;     
+
+      const Core::AutoRegisteredPtr<Parent, LoadT >& GetParentItemPtr() const;
+      Core::AutoRegisteredPtr<Parent, LoadT >& GetParentItemPtr();
+
+      Parent& GetParent();
+      const Parent& GetParent() const;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      Core::AutoRegisteredPtr<Parent, LoadT > parentItem_;
+      Quantity quantity_;
+    };
+
+    template<class Parent, class Quantity, class How>
+    template<class Archive>
+    inline void
+    LoadT<Parent, Quantity, How>::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Load);
+      ar & BOOST_SERIALIZATION_NVP(quantity_);
+    }
+
+    
+    template<class Parent, class Quantity, class How>
+    inline const std::string 
+    LoadT<Parent, Quantity, How>::GetStrType()
+    {
+      return Load::GetStrType() + "@" + Quantity::GetStrType();
+    }
+
+
+    template<class Parent, class Quantity, class How>
+    inline const QString
+    LoadT<Parent, Quantity, How>::GetQStrType()
+    {
+      return Load::GetQStrType() + "@" + Quantity::GetQStrType();
+    }
+
+
+    template<class Parent, class Quantity, class How>
+    inline void
+    LoadT<Parent, Quantity, How>::Init()
+    {
+      Core::UserItemCommonProperty< LoadT<Parent, Quantity, How> > & prop = 
+	Core::Singleton< Core::UserItemCommonProperty< LoadT<Parent, Quantity, How> > >::Get();
+
+      prop.CreateAction_Edit();
+      prop.CreateAction_Delete();
+
+      // don't forget to instanciate UserRootItemCommonProperty<Body> before calling
+      // create action
+      Core::Singleton< Core::UserItemCommonProperty<Parent> >::Instanciate();
+      prop.template CreateAction_NewWithAutomaticSelection<Parent>();
+    }
+    
+    template <class Parent, class Quantity, class How>
+    inline void 
+    LoadT<Parent, Quantity, How>::DrawIcon(QIcon& icon, QColor color)
+    {
+      // Read svg icon file
+      QString svgFileName = ":/Rsc/Img/Load/" + QString(Quantity::GetStrType().c_str()) + ".svg";
+      Util::Icon::DrawIconFromSvgFile(svgFileName, icon, color);
+    }
+
+
+    template<class Parent, class Quantity, class How> 
+    inline 
+    LoadT<Parent, Quantity, How>::LoadT(Parent& parent)
+      :Load(GetStrType(), parent.GetMainTreeItem()), 
+       parentItem_(*this, parent),
+       quantity_(*this)
+    {
+      UpdateIcon();
+      Load::treeItem_->Update();
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline 
+    LoadT<Parent, Quantity, How>::~LoadT()
+    {
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    LoadT<Parent, Quantity, How>::UpdateIcon()
+    {
+      DrawIcon(GetIcon(), GetColor().GetQColor());
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline Quantity& 
+    LoadT<Parent, Quantity, How>::GetQuantity()
+    {
+      return quantity_;
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline const Quantity& 
+    LoadT<Parent, Quantity, How>::GetQuantity() const
+    {
+      return quantity_;
+    }
+
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    LoadT<Parent, Quantity, How>::DrawShape()
+    {
+      quantity_.Draw();
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    LoadT<Parent, Quantity, How>::BeginDraw()
+    {
+      quantity_.BeginDraw();
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    LoadT<Parent, Quantity, How>::EndDraw()
+    {
+      quantity_.EndDraw();
+    }
+
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    LoadT<Parent, Quantity, How>::Apply() 
+    { 
+      How::Apply(*this);
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    LoadT<Parent, Quantity, How>::BuildChSystem(chrono::ChSystem&)
+    {
+      Apply();
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    LoadT<Parent, Quantity, How>::SaveState()
+    {
+      quantity_.GetDataType().SaveState();
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    LoadT<Parent, Quantity, How>::ResetState()
+    {
+      quantity_.GetDataType().ResetState();
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    LoadT<Parent, Quantity, How>::RecoveryState(unsigned int i)
+    {
+      quantity_.GetDataType().RecoveryState(i);
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline const Geom::Frame<_3D>& 
+    LoadT<Parent, Quantity, How>::GetFrame() const
+    {
+      return GetParent().GetFrame();
+    }
+
+  
+
+    template<class Parent, class Quantity, class How>
+    inline const Core::AutoRegisteredPtr<Parent, LoadT<Parent, Quantity, How> >& 
+    LoadT<Parent, Quantity, How>::GetParentItemPtr() const
+    {
+      return parentItem_;
+    }
+
+    
+    template<class Parent, class Quantity, class How>
+    inline Core::AutoRegisteredPtr<Parent, LoadT<Parent, Quantity, How> >& 
+    LoadT<Parent, Quantity, How>::GetParentItemPtr()
+      {
+      return parentItem_;
+    }
+
+
+    template<class Parent, class Quantity, class How>
+    inline Parent& 
+    LoadT<Parent, Quantity, How>::GetParent()
+    {
+      return *GetParentItemPtr().GetPtr();
+    }
+    
+    template<class Parent, class Quantity, class How>
+    inline const Parent& 
+    LoadT<Parent, Quantity, How>::GetParent() const
+    {
+      return *GetParentItemPtr().GetPtr();      
+    }
+
+
+  }
+} 
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive, class Parent, class Quantity, class How>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::LoadT<Parent, Quantity, How> * t, 
+				    const unsigned int)
+    {
+      const Parent* parent = &t->GetParent();
+      ar << parent;
+    }
+    
+
+    template<class Archive, class Parent, class Quantity, class How>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::LoadT<Parent, Quantity, How> * t, 
+				    const unsigned int)
+    {
+      Parent* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Item::LoadT<Parent, Quantity, How>(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Part.cpp b/SRC/OpenMeca/Item/Part.cpp
new file mode 100644
index 0000000..3642eef
--- /dev/null
+++ b/SRC/OpenMeca/Item/Part.cpp
@@ -0,0 +1,93 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Item::Part)
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    const std::string Part::GetStrType() 
+    {
+      return "Part";
+    } 
+
+    const QString Part::GetQStrType() 
+    {
+      return  QObject::tr("Part");
+    } 
+
+    double 
+    Part::GetScaleValue()
+    {
+      return Core::System::Get().GetScales().GetScaleValue(Part::GetStrType());
+    }
+
+    Part::~Part()
+    {
+    }
+
+    Part::Part(const std::string strType, QTreeWidgetItem& parent, bool isSelectable)
+    :Core::DrawableUserItem(strType, parent, isSelectable)
+    {
+    }
+
+
+    Geom::Point<_3D>& 
+    Part::GetCenter() 
+    {
+      OMC_ASSERT_MSG(0, "This method is not allowed with base class");
+      return *(Geom::Point<_3D>*)(0);
+    }
+
+    const Geom::Point<_3D>& 
+    Part::GetCenter() const 
+    {
+      OMC_ASSERT_MSG(0, "This method is not allowed with base class");
+      return *(Geom::Point<_3D>*)(0);
+    }
+
+    Geom::Quaternion<_3D>& 
+    Part::GetQuaternion()
+    {
+      OMC_ASSERT_MSG(0, "This method is not allowed with base class");
+      return *(Geom::Quaternion<_3D>*)(0);
+    }
+
+    const Geom::Quaternion<_3D>& 
+    Part::GetQuaternion() const 
+    {
+      OMC_ASSERT_MSG(0, "This method is not allowed with base class");
+      return *(Geom::Quaternion<_3D>*)(0);
+    }
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/Part.hpp b/SRC/OpenMeca/Item/Part.hpp
new file mode 100644
index 0000000..41b9071
--- /dev/null
+++ b/SRC/OpenMeca/Item/Part.hpp
@@ -0,0 +1,80 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Part_hpp
+#define OpenMeca_Item_Part_hpp
+
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/DrawableUserItem.hpp"
+
+
+
+namespace OpenMeca
+{  
+
+  namespace Item
+  {
+
+    class Body;
+    
+    // Base class for all parts. A part is a drawable entity registered
+    // in the treeview.
+    class Part: public Core::DrawableUserItem, public Core::AutoRegister<Part>
+    {
+    
+    public:
+      static const std::string GetStrType(); 
+      static const QString GetQStrType(); 
+      static double GetScaleValue();
+
+    public:
+      Part(const std::string strType, QTreeWidgetItem& parent, bool isSelectable);
+      virtual ~Part();
+      
+      virtual Geom::Point<_3D>& GetCenter(); // forbidden
+      virtual const Geom::Point<_3D>& GetCenter() const; // forbidden 
+      virtual Geom::Quaternion<_3D>& GetQuaternion(); // forbidden
+      virtual const Geom::Quaternion<_3D>& GetQuaternion() const ; // forbidden
+
+    private:
+      Part(); //Not allowed, just for serialization
+      Part(const Part&);             //Not Allowed
+      Part& operator=(const Part&);  //Not Allowed
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive& ar, const unsigned int);
+    };
+
+    template<class Archive>
+    void Part::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Core::DrawableUserItem);
+    }
+    
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartLinkT.cpp b/SRC/OpenMeca/Item/PartLinkT.cpp
new file mode 100644
index 0000000..aaa184c
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartLinkT.cpp
@@ -0,0 +1,101 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/PartLinkT.hpp"
+#include "OpenMeca/Item/LinkT.hpp"
+#include "OpenMeca/Item/Link/All.hpp"
+
+
+
+#include "Serialization/export.hpp"
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Revolute,1> PartLinkTRevolute1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Revolute,2> PartLinkTRevolute2;
+BOOST_CLASS_EXPORT(PartLinkTRevolute1)
+BOOST_CLASS_EXPORT(PartLinkTRevolute2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Motor,1> PartLinkTMotor1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Motor,2> PartLinkTMotor2;
+BOOST_CLASS_EXPORT(PartLinkTMotor1)
+BOOST_CLASS_EXPORT(PartLinkTMotor2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Slider,1> PartLinkTSlider1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Slider,2> PartLinkTSlider2;
+BOOST_CLASS_EXPORT(PartLinkTSlider1)
+BOOST_CLASS_EXPORT(PartLinkTSlider2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Cylindrical,1> PartLinkTCylindrical1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Cylindrical,2> PartLinkTCylindrical2;
+BOOST_CLASS_EXPORT(PartLinkTCylindrical1)
+BOOST_CLASS_EXPORT(PartLinkTCylindrical2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Planar,1> PartLinkTPlanar1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Planar,2> PartLinkTPlanar2;
+BOOST_CLASS_EXPORT(PartLinkTPlanar1)
+BOOST_CLASS_EXPORT(PartLinkTPlanar2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::PointLine,1> PartLinkTPointLine1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::PointLine,2> PartLinkTPointLine2;
+BOOST_CLASS_EXPORT(PartLinkTPointLine1)
+BOOST_CLASS_EXPORT(PartLinkTPointLine2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::PointPlane,1> PartLinkTPointPlane1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::PointPlane,2> PartLinkTPointPlane2;
+BOOST_CLASS_EXPORT(PartLinkTPointPlane1)
+BOOST_CLASS_EXPORT(PartLinkTPointPlane2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Spherical,1> PartLinkTSpherical1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Spherical,2> PartLinkTSpherical2;
+BOOST_CLASS_EXPORT(PartLinkTSpherical1)
+BOOST_CLASS_EXPORT(PartLinkTSpherical2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Screw,1> PartLinkTScrew1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Screw,2> PartLinkTScrew2;
+BOOST_CLASS_EXPORT(PartLinkTScrew1)
+BOOST_CLASS_EXPORT(PartLinkTScrew2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Gear,1> PartLinkTGear1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Gear,2> PartLinkTGear2;
+BOOST_CLASS_EXPORT(PartLinkTGear1)
+BOOST_CLASS_EXPORT(PartLinkTGear2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Pulley,1> PartLinkTPulley1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::Pulley,2> PartLinkTPulley2;
+BOOST_CLASS_EXPORT(PartLinkTPulley1)
+BOOST_CLASS_EXPORT(PartLinkTPulley2)
+
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::RackPinion,1> PartLinkTRackPinion1;
+typedef OpenMeca::Item::PartLinkT<OpenMeca::Item::RackPinion,2> PartLinkTRackPinion2;
+BOOST_CLASS_EXPORT(PartLinkTRackPinion1)
+BOOST_CLASS_EXPORT(PartLinkTRackPinion2)
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/PartLinkT.hpp b/SRC/OpenMeca/Item/PartLinkT.hpp
new file mode 100644
index 0000000..90a139e
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartLinkT.hpp
@@ -0,0 +1,396 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Item_PartLinkT_hpp
+#define OpenMeca_Item_PartLinkT_hpp
+
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Item/PartUserPoint.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Core/None.hpp"
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    template <class T> class LinkT;
+    // The PartLinkT is a part that belong to a link. A link
+    // is drawn by two parts that belong to the two linked bodies.
+    // N correspond to body (1 or 2)
+    template <class T, int N>
+    class PartLinkT: public Part
+    {
+    
+    public:
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+      static void Init();
+
+      typedef Core::None Dialog;
+
+    public:
+      PartLinkT(LinkT<T>& link);
+      virtual ~PartLinkT();
+
+      LinkT<T>& GetLinkT();
+      const LinkT<T>& GetLinkT() const;
+
+      void UpdateIcon();
+      void DrawShape();
+      void BeginDraw();
+
+      Body& GetBody();
+      const Body& GetBody() const;
+
+      void Update();
+
+      const Geom::Frame<_3D>& GetFrame() const;
+      Geom::Frame<_3D>& GetFrame();
+
+      Geom::Point<_3D>& GetCenter();
+      const Geom::Point<_3D>& GetCenter() const;
+
+      Geom::Quaternion<_3D>& GetQuaternion();
+      const Geom::Quaternion<_3D>& GetQuaternion() const;
+
+      const Geom::Frame<_3D>& GetReferenceFrame() const;
+
+      
+      const Util::Color& GetColor() const;
+      Util::Color& GetColor();
+
+      const Core::AutoRegisteredPtr<LinkT<T>, PartLinkT<T,N> >& GetLinkTPtr() const;
+      Core::AutoRegisteredPtr<LinkT<T>, PartLinkT<T,N> >& GetLinkTPtr();
+
+    private:
+      PartLinkT(); //Not allowed, just for serialization
+      PartLinkT(const PartLinkT<T,N>&);             //Not Allowed
+      PartLinkT& operator=(const PartLinkT<T,N>&);  //Not Allowed
+
+      QTreeWidgetItem& GetParentTreeItem();
+      Core::SetOfBase<Core::UserItem> GetAssociatedSelectedItem();
+
+      void UpdateName();
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+
+    private:
+      Core::AutoRegisteredPtr<LinkT<T>, PartLinkT<T,N> > link_;
+      Geom::Point<_3D> center_;
+      Geom::Quaternion<_3D> quaternion_;
+      Geom::Frame<_3D> frame_;
+      Core::SetOf<PartPoint> points_;
+    };
+
+
+    template <class T, int N>  
+    template<class Archive>
+    inline void
+    PartLinkT<T,N>::save(Archive& ar, const unsigned int) const
+    {
+
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(Part);
+      ar << BOOST_SERIALIZATION_NVP(points_);
+    }
+
+
+    template <class T, int N>  
+    template<class Archive>
+    inline void
+    PartLinkT<T,N>::load(Archive& ar, const unsigned int) 
+    {
+      points_.ClearAndDelete();
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(Part);
+      ar >> BOOST_SERIALIZATION_NVP(points_);
+    }
+
+    
+    template<class T, int N> 
+    inline const std::string 
+    PartLinkT<T,N>::GetStrType()
+    {
+      return std::string(Part::GetStrType() + '_' + T::GetStrType() + '_' 
+			 + std::to_string(N));
+    }
+
+    template<class T, int N> 
+    inline const QString 
+    PartLinkT<T,N>::GetQStrType()
+    {
+      return QString(Part::GetQStrType() + '_' + T::GetQStrType() + '_' 
+		     + std::to_string(N).c_str());
+    }
+
+
+    template<class T, int N> 
+    inline void 
+    PartLinkT<T,N>::Init()
+    {
+      Core::Singleton< Core::UserItemCommonProperty< PartLinkT<T,N> > >::Get().CreateAction_Nothing();
+    }
+
+
+    template<class T, int N>
+    inline
+    PartLinkT<T,N>::PartLinkT(LinkT<T>& link)
+      :Part(GetStrType(), link.template GetBody<N>().GetMainTreeItem(), true),
+       link_(*this, link),
+       center_(std::bind(&PartLinkT<T,N>::GetReferenceFrame, std::ref(*this))),
+       quaternion_(std::bind(&PartLinkT<T,N>::GetReferenceFrame, std::ref(*this))),
+       frame_(center_, quaternion_),
+       points_()
+    {      
+      UpdateName();
+      GetLinkT().GetLinkType().template BuildPoints<N>(points_, *this);
+    }
+
+ 
+    template<class T, int N>
+    inline
+    PartLinkT<T,N>::~PartLinkT()
+    {
+    }
+
+
+    template<class T, int N>
+    inline LinkT<T>&
+    PartLinkT<T,N>::GetLinkT()
+    {
+      return *link_.GetPtr();
+    }
+
+    template<class T, int N>
+    inline const LinkT<T>& 
+    PartLinkT<T,N>::GetLinkT() const
+    {
+      return *link_.GetPtr();
+    }
+
+    template<class T, int N>
+    inline void
+    PartLinkT<T,N>::Update()
+    {
+      GetLinkT().GetLinkType().UpdatePart();
+      UpdateName();
+      Core::UserItem::Update();
+      
+    }
+
+
+  
+
+
+    template<class T, int N>
+    inline const Geom::Frame<_3D>&
+    PartLinkT<T,N>::GetReferenceFrame() const
+    {
+      return GetLinkT().template GetFrameBody<N>(); 
+    }
+
+
+    
+
+    template<class T, int N>
+    inline void
+    PartLinkT<T,N>::UpdateName()
+    {
+      UserItem::GetName() = std::string(Part::GetStrType() + '_' + GetLinkT().GetName());
+    }
+
+
+    template<class T, int N>
+    inline void
+    PartLinkT<T,N>::UpdateIcon()
+    {
+      GetLinkT().template UpdatePartIcon<N>(Core::UserItem::GetIcon());
+    }
+    
+
+    template<class T, int N>
+    inline void
+    PartLinkT<T,N>::DrawShape()
+    {
+      GetLinkT().GetLinkType().template DrawPart<N>();
+    }
+
+    template<class T, int N>
+    inline void
+    PartLinkT<T,N>::BeginDraw()
+    {
+      if (N==1)
+	GetLinkT().GetLinkType().BeginDraw1();
+      else
+	GetLinkT().GetLinkType().BeginDraw2();
+    }
+
+
+    template<class T, int N>
+    inline Body& 
+    PartLinkT<T,N>::GetBody()
+    {
+      return GetLinkT().template GetBody<N>();
+    }
+    
+    template<class T, int N>
+    inline const Body& 
+    PartLinkT<T,N>::GetBody() const
+    {
+      return GetLinkT().template GetBody<N>();
+    }
+
+    template<class T, int N>
+    inline QTreeWidgetItem& 
+    PartLinkT<T,N>::GetParentTreeItem()
+    {
+      return GetLinkT().template GetBody<N>().GetMainTreeItem();
+    }
+
+
+    template<class T, int N>
+    inline const Geom::Frame<_3D>& 
+    PartLinkT<T,N>::GetFrame() const
+    {
+      return frame_;
+    }
+
+    template<class T, int N>
+    inline Geom::Frame<_3D>& 
+    PartLinkT<T,N>::GetFrame()
+     {
+      return frame_;
+    } 
+
+    template<class T, int N>
+    inline const Util::Color& 
+    PartLinkT<T,N>::GetColor() const
+    {
+      return GetLinkT().template GetBody<N>().GetColor();
+    }
+    
+    template<class T, int N>
+    inline Util::Color& 
+    PartLinkT<T,N>::GetColor()
+    {
+      return GetLinkT().template GetBody<N>().GetColor();
+    }
+
+
+    template<class T, int N>
+    inline const Core::AutoRegisteredPtr<LinkT<T>, PartLinkT<T,N> >& 
+    PartLinkT<T,N>::GetLinkTPtr() const
+    {
+      return link_;
+    }
+
+
+    template<class T, int N>
+    inline Core::AutoRegisteredPtr<LinkT<T>, PartLinkT<T,N> >& 
+    PartLinkT<T,N>::GetLinkTPtr()
+    {
+      return link_;
+    }
+
+
+    template <class T, int N> 
+    inline Core::SetOfBase<Core::UserItem> 
+    PartLinkT<T,N>::GetAssociatedSelectedItem()
+    {
+      Core::SetOfBase<Core::UserItem> set;
+
+      Core::SetOfBase<PartPoint>::it it;
+      for (it = points_.Begin() ; it != points_.End(); it++ )
+	set.AddItem(**it);
+
+      return set;
+    }
+
+
+    template <class T, int N> 
+    inline Geom::Point<_3D>& 
+    PartLinkT<T,N>::GetCenter()
+    {
+      return center_;
+    }
+
+    template <class T, int N> 
+    inline const Geom::Point<_3D>& 
+    PartLinkT<T,N>::GetCenter() const
+    {
+      return center_;
+    }
+
+
+     template <class T, int N> 
+    inline Geom::Quaternion<_3D>&
+    PartLinkT<T,N>::GetQuaternion()
+    {
+      return quaternion_;
+    }
+
+    template <class T, int N> 
+    inline const Geom::Quaternion<_3D>&
+    PartLinkT<T,N>::GetQuaternion() const
+    {
+      return quaternion_;
+    }
+
+
+  }
+
+}
+
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    template<class Archive, class T, int N>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::PartLinkT<T,N> * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::LinkT<T>* linkPtr = t->GetLinkTPtr().GetPtr();
+      ar << linkPtr;
+    }
+    
+    template<class Archive, class T, int N>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::PartLinkT<T,N> * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::LinkT<T>* linkPtr = 0;
+      ar >> linkPtr;
+      ::new(t)OpenMeca::Item::PartLinkT<T,N>(*linkPtr);
+    }
+  }
+} // namespace ...
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartPoint.cpp b/SRC/OpenMeca/Item/PartPoint.cpp
new file mode 100644
index 0000000..9489cfc
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartPoint.cpp
@@ -0,0 +1,143 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+
+
+
+#include "OpenMeca/Item/PartPoint_CreateAction_SpecializedT.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartPoint)
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    template<>
+    void
+    ItemCommonProperty<OpenMeca::Item::PartPoint>::BuildIconSymbol()
+    {
+      QIcon icon;
+      OpenMeca::Item::PartPoint::DrawIcon(iconSymbol_, Qt::gray);
+    }
+
+    template<>
+    void 
+    UserItemCommonProperty<OpenMeca::Item::PartPoint>::CreateAction_Specialized() 
+    {
+      // We call PartPoint_CreateAction_SpecializedT because it is needed by other class
+      UserItemCommonProperty<OpenMeca::Item::PartPoint>& me = *this;
+      OpenMeca::Item::PartPoint_CreateAction_SpecializedT(me);
+    }
+
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+    
+
+    void
+    PartPoint::Init()
+    {
+      Core::Singleton< Core::UserItemCommonProperty< PartPoint > >::Get().CreateAction_Specialized();
+    }
+
+
+    void 
+    PartPoint::DrawIcon(QIcon& icon, QColor color)
+    {
+      Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Part/Point.svg", icon, color);
+    }
+
+
+    PartPoint::PartPoint(Core::UserItem& parent)
+      :PartUser(GetStrType(), parent),
+       mustBeScaled_(false),
+       scaleCoordinate_(std::bind(&PartUser::GetReferenceFrame, std::ref(*this)))
+    {
+    }
+
+  
+    PartPoint::PartPoint(const std::string& childStrType, Core::UserItem& parent)
+      :PartUser(childStrType, parent),
+       mustBeScaled_(false),
+       scaleCoordinate_(std::bind(&PartUser::GetReferenceFrame, std::ref(*this)))
+    {
+    }  
+    
+    PartPoint::~PartPoint()
+    {
+    }
+
+    void 
+    PartPoint::BeginDraw()
+    {
+      if (mustBeScaled_)
+	{
+	  const double scale = Part::GetScaleValue();
+	  PartUser::GetPoint() = (scaleCoordinate_*scale).GetPoint();
+	}
+    }
+
+    void 
+    PartPoint::DrawShape()
+    {
+      const double scale = Part::GetScaleValue();
+      Util::Draw::Sphere(.02f*scale);
+    }
+
+    void 
+    PartPoint::UpdateIcon()
+    {
+      PartPoint::DrawIcon(GetIcon(), GetColor().GetQColor());
+    }
+    
+    void
+    PartPoint::SetScaleCoordinate(double x, double y, double z)
+    {
+      mustBeScaled_ = true;
+      scaleCoordinate_[0] = x;
+      scaleCoordinate_[1] = y;
+      scaleCoordinate_[2] = z;
+    }
+
+    void
+    PartPoint::SetAbsoluteCoordinate(double x, double y, double z)
+    {
+      mustBeScaled_ = false;
+      PartUser::GetPoint()[0] = x;
+      PartUser::GetPoint()[1] = y;
+      PartUser::GetPoint()[2] = z;
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/PartPoint.hpp b/SRC/OpenMeca/Item/PartPoint.hpp
new file mode 100644
index 0000000..29d42d1
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartPoint.hpp
@@ -0,0 +1,121 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Item_PartPoint_hpp
+#define OpenMeca_Item_PartPoint_hpp
+
+
+// This class is used for automatic point that don't support user edit
+
+#include "OpenMeca/Item/PartUser.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/None.hpp"
+
+
+
+namespace OpenMeca
+{  
+
+  namespace Item
+  {
+
+    // A part that represent a point. This is a little 3D sphere.
+    class PartPoint: public PartUser, public Core::AutoRegister<PartPoint> 
+    {    
+    public:
+      static const std::string GetStrType() {return std::string("AutomaticPoint");};
+      static const QString GetQStrType() {return QObject::tr("AutomaticPoint");}; 
+
+      static void Init();
+      static void DrawIcon(QIcon&, QColor);
+      typedef Core::None Dialog;
+
+
+    public:
+      PartPoint(Core::UserItem& parent);
+      PartPoint(const std::string& childStrType, Core::UserItem& parent);
+      virtual ~PartPoint();
+      void DrawShape();
+      void UpdateIcon();
+      void BeginDraw();
+
+      void SetScaleCoordinate(double x, double y, double z);
+      void SetAbsoluteCoordinate(double x, double y, double z);
+
+    private:
+      PartPoint(); //Not allowed, just for serialization
+      PartPoint(const PartPoint&);             //Not Allowed
+      PartPoint& operator=(const PartPoint&);  //Not Allowed
+
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive& ar, const unsigned int);
+
+
+    private:
+      bool mustBeScaled_;
+      Geom::Vector<_3D> scaleCoordinate_;
+    };
+
+    
+    template<class Archive>
+    inline void 
+    PartPoint::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUser);
+      ar & BOOST_SERIALIZATION_NVP(mustBeScaled_);
+      ar & BOOST_SERIALIZATION_NVP(scaleCoordinate_);
+    }
+    
+    
+
+    
+  }
+
+}
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::PartPoint * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Core::UserItem* parent = &t->GetParentItem();
+      ar << parent;
+    }
+    
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::PartPoint * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Core::UserItem* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Item::PartPoint(*parent);
+    }
+  }
+} // namespace ...
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartPoint_CreateAction_SpecializedT.hpp b/SRC/OpenMeca/Item/PartPoint_CreateAction_SpecializedT.hpp
new file mode 100644
index 0000000..c4378fb
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartPoint_CreateAction_SpecializedT.hpp
@@ -0,0 +1,111 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Item_PartPoint_CreateAction_SpecializedT_hpp
+#define OpenMeca_Item_PartPoint_CreateAction_SpecializedT_hpp
+
+
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+
+
+#include "OpenMeca/Item/PartUserPipe.hpp"
+#include "OpenMeca/Item/PartUserJunction.hpp"
+
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+#include "OpenMeca/Item/Shape/Sphere.hpp"
+#include "OpenMeca/Item/Shape/Cylinder.hpp"
+#include "OpenMeca/Item/Shape/Box.hpp"
+#include "OpenMeca/Item/Shape/Ground.hpp"
+
+#include "OpenMeca/Item/How/GetLinVel.hpp"
+#include "OpenMeca/Item/How/GetLinAcc.hpp"
+#include "OpenMeca/Item/How/GetAngPos.hpp"
+#include "OpenMeca/Item/How/GetAngVel.hpp"
+#include "OpenMeca/Item/How/GetAngAcc.hpp"
+#include "OpenMeca/Item/How/GetLinPos.hpp"
+#include "OpenMeca/Item/How/SetForce.hpp"
+#include "OpenMeca/Item/How/SetTorque.hpp"
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    template<class T>
+    inline void
+    PartPoint_CreateAction_SpecializedT(OpenMeca::Core::UserItemCommonProperty<T>& t)
+    {
+      const QIcon emptyIcon;
+
+      const std::string geomTitle = "Geometry";
+      t.AddPopUpSubMenu(geomTitle, emptyIcon);
+
+      t.template CreateAction_NewWithSelection<OpenMeca::Item::PartUserPipe>(geomTitle);
+      t.template CreateAction_NewWithSelection<OpenMeca::Item::PartUserJunction>(geomTitle);
+
+      typedef OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Sphere>    PartSphere;
+      typedef OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Box>       PartBox;
+      typedef OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder>  PartCylinder;
+      typedef OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground>  PartGround;
+      Core::Singleton< Core::UserItemCommonProperty<PartSphere> >  ::Instanciate();
+      Core::Singleton< Core::UserItemCommonProperty<PartBox> >     ::Instanciate();
+      Core::Singleton< Core::UserItemCommonProperty<PartCylinder> >::Instanciate();
+      Core::Singleton< Core::UserItemCommonProperty<PartGround> >  ::Instanciate();
+      t.template CreateAction_NewWithSelection<PartSphere>(geomTitle);
+      t.template CreateAction_NewWithSelection<PartBox>(geomTitle);
+      t.template CreateAction_NewWithSelection<PartCylinder>(geomTitle);
+      t.template CreateAction_NewWithSelection<PartGround>(geomTitle);
+
+      const std::string loadTitle = "Loading";
+      t.AddPopUpSubMenu(loadTitle, emptyIcon);
+      typedef OpenMeca::Item::How::SetForce::MyLoad LoadForce;
+      typedef OpenMeca::Item::How::SetTorque::MyLoad LoadTorque;
+      Core::Singleton<Core::UserItemCommonProperty<LoadForce> >::Instanciate();
+      Core::Singleton<Core::UserItemCommonProperty<LoadTorque> >::Instanciate();
+      t.template CreateAction_NewWithSelection<LoadForce>(loadTitle);
+      t.template CreateAction_NewWithSelection<LoadTorque>(loadTitle);
+
+      const std::string sensorTitle = "Sensor";
+      t.AddPopUpSubMenu(sensorTitle, emptyIcon);
+      typedef OpenMeca::Item::How::GetLinPos::MySensor SensorLinPos;
+      typedef OpenMeca::Item::How::GetLinVel::MySensor SensorLinVel;
+      typedef OpenMeca::Item::How::GetLinAcc::MySensor SensorLinAcc;
+      typedef OpenMeca::Item::How::GetAngPos::MySensor SensorAngPos;
+      typedef OpenMeca::Item::How::GetAngVel::MySensor SensorAngVel;
+      typedef OpenMeca::Item::How::GetAngAcc::MySensor SensorAngAcc;
+      Core::Singleton<Core::UserItemCommonProperty<SensorLinPos> >::Instanciate();
+      Core::Singleton<Core::UserItemCommonProperty<SensorLinVel> >::Instanciate();
+      Core::Singleton<Core::UserItemCommonProperty<SensorLinAcc> >::Instanciate();
+      Core::Singleton<Core::UserItemCommonProperty<SensorAngPos> >::Instanciate();
+      Core::Singleton<Core::UserItemCommonProperty<SensorAngVel> >::Instanciate();
+      Core::Singleton<Core::UserItemCommonProperty<SensorAngAcc> >::Instanciate();
+      t.template CreateAction_NewWithSelection<SensorLinPos>(sensorTitle);
+      t.template CreateAction_NewWithSelection<SensorLinVel>(sensorTitle);
+      t.template CreateAction_NewWithSelection<SensorLinAcc>(sensorTitle);
+      t.template CreateAction_NewWithSelection<SensorAngPos>(sensorTitle);
+      t.template CreateAction_NewWithSelection<SensorAngVel>(sensorTitle);
+      t.template CreateAction_NewWithSelection<SensorAngAcc>(sensorTitle);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartUser.cpp b/SRC/OpenMeca/Item/PartUser.cpp
new file mode 100644
index 0000000..7160b4a
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUser.cpp
@@ -0,0 +1,147 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/PartUser.hpp"
+#include "OpenMeca/Item/Body.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUser)
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+     
+    const std::string 
+    PartUser::GetStrType()
+    {
+      return std::string("PartUser");
+    }
+
+
+
+    
+    PartUser::PartUser(const std::string strType, Core::UserItem& parent)
+      :Part(strType, parent.GetMainTreeItem(), true),
+       parentItem_(*this, parent),
+       center_(std::bind(&PartUser::GetReferenceFrame, std::ref(*this))),
+       quaternion_(std::bind(&PartUser::GetReferenceFrame, std::ref(*this))),
+       frame_(center_, quaternion_),
+       bodyIsDeleted_(false)
+    {
+    }
+
+  
+    
+    
+    PartUser::~PartUser()
+    {
+    }
+
+
+
+    
+    Core::UserItem&
+    PartUser::GetParentItem()
+    {
+      return *parentItem_.GetPtr();
+    }
+
+
+    const Core::UserItem&
+    PartUser::GetParentItem() const
+    {
+      return *parentItem_.GetPtr();
+    }
+  
+
+
+    
+     const Geom::Frame<_3D>&
+    PartUser::GetReferenceFrame() const
+    {
+      return GetParentItem().GetFrame();
+    }
+
+    
+    QTreeWidgetItem& 
+    PartUser::GetParentTreeItem()
+    {
+      return GetParentItem().GetMainTreeItem();
+    }
+
+
+    
+     const Util::Color& 
+    PartUser::GetColor() const
+    {
+      return GetParentItem().GetColor();
+    }
+    
+    
+     Util::Color& 
+    PartUser::GetColor()
+    {
+      return GetParentItem().GetColor();
+    }
+
+
+    
+    const Core::AutoRegisteredPtr<Core::UserItem, PartUser >& 
+    PartUser::GetParentItemPtr() const
+    {
+      return parentItem_;
+    }
+
+    
+    
+    Core::AutoRegisteredPtr<Core::UserItem, PartUser >& 
+    PartUser::GetParentItemPtr()
+    {
+      return parentItem_;
+    }
+
+
+    const Body& 
+    PartUser::GetBody() const
+    {
+      return GetParentItem().GetBody();
+    }
+
+    Body& 
+    PartUser::GetBody()
+    {
+      return GetParentItem().GetBody();
+    }
+
+    void 
+    PartUser::BodyIsDeleted()
+    {
+      bodyIsDeleted_ = true;
+    }
+
+
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/PartUser.hpp b/SRC/OpenMeca/Item/PartUser.hpp
new file mode 100644
index 0000000..5d5e3f4
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUser.hpp
@@ -0,0 +1,104 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Item_PartUser_hpp_11
+#define OpenMeca_Item_PartUser_hpp_11
+
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+    // A partUser is a part that is managed by the user.
+    class PartUser: public Part
+    {
+    public:
+      static const std::string GetStrType(); 
+
+    public:
+      PartUser(const std::string strType, Core::UserItem& parent);
+      virtual ~PartUser();
+
+      void BodyIsDeleted();
+
+      // Accessor
+      OMC_ACCESSOR(Frame      , Geom::Frame<_3D>      ,  frame_     );
+      OMC_ACCESSOR(Point      , Geom::Point<_3D>      ,  center_    );
+      OMC_ACCESSOR(Center     , Geom::Point<_3D>      ,  center_    );
+      OMC_ACCESSOR(Quaternion , Geom::Quaternion<_3D> ,  quaternion_);
+
+      Core::UserItem& GetParentItem();
+      const Core::UserItem& GetParentItem() const;
+
+      virtual const Geom::Frame<_3D>& GetReferenceFrame() const;
+
+      Body& GetBody();
+      const Body& GetBody() const;
+      
+      const Util::Color& GetColor() const;
+      Util::Color& GetColor();
+
+      const Core::AutoRegisteredPtr<Core::UserItem, PartUser >& GetParentItemPtr() const;
+      Core::AutoRegisteredPtr<Core::UserItem, PartUser >& GetParentItemPtr();
+
+
+    private:
+      PartUser(); //Not allowed, just for serialization
+      PartUser(const PartUser&);             //Not Allowed
+      PartUser& operator=(const PartUser&);  //Not Allowed
+
+      QTreeWidgetItem& GetParentTreeItem();
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive& ar, const unsigned int);
+
+
+    private:
+      Core::AutoRegisteredPtr<Core::UserItem, PartUser > parentItem_;
+      Geom::Point<_3D> center_;
+      Geom::Quaternion<_3D> quaternion_;
+      Geom::Frame<_3D> frame_;
+      bool bodyIsDeleted_;
+    };
+
+
+    template<class Archive>
+    inline void 
+    PartUser::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Part);
+      ar & BOOST_SERIALIZATION_NVP(parentItem_);
+      ar & BOOST_SERIALIZATION_NVP(center_);
+      ar & BOOST_SERIALIZATION_NVP(quaternion_);
+      }
+    
+
+
+  }
+
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartUserJunction.cpp b/SRC/OpenMeca/Item/PartUserJunction.cpp
new file mode 100644
index 0000000..4ae7bd9
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserJunction.cpp
@@ -0,0 +1,169 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/PartUserJunction.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserJunction)
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    void
+    PartUserJunction::Init()
+    {
+      Core::Singleton< Core::UserItemCommonProperty< PartUserJunction > >::Get().CreateAction_Edit();
+      Core::Singleton< Core::UserItemCommonProperty< PartUserJunction > >::Get().CreateAction_Delete();
+    }
+
+
+
+    void 
+    PartUserJunction::DrawIcon(QIcon& icon, QColor color)
+    {
+      Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Part/Junction.svg", icon, color);
+    }
+
+
+    
+    PartUserJunction::PartUserJunction(PartPoint& parent)
+      :PartUser(GetStrType(), parent),
+       startPoint_(parent),
+       length_(0),
+       endPoint_(*this)
+    {
+
+      // find the end points, must be different from the start points
+      Core::SetOfBase<PartPoint> set = GetBody().GetChildSet<PartPoint>();
+      for (unsigned int i = 0; i < set.GetTotItemNumber();++i)
+	{
+	if (&set(i) != & startPoint_)
+	  {
+	    endPoint_ = &set(i);
+	    break;
+	  }
+	}
+    }
+
+  
+    
+    
+    PartUserJunction::~PartUserJunction()
+    {
+    }
+
+	     
+    void 
+    PartUserJunction::BeginDraw()
+    {
+      if (endPoint_.GetPtr() == 0)
+	return;
+
+      //Translate
+      Geom::Point<_3D>& p1 = PartUser::GetPoint();
+      p1 = Geom::Point<_3D>(GetStartPoint().GetPoint(),
+			   std::bind(&PartUser::GetReferenceFrame, std::ref(*this)));
+
+      //Rotate
+      Geom::Point<_3D> p2(GetEndPoint().GetPoint(), 
+			   std::bind(&PartUser::GetReferenceFrame, std::ref(*this)));
+      Geom::Vector<_3D> axis(p1, p2);
+      Geom::Quaternion<_3D>& q = PartUser::GetQuaternion();
+      const Geom::Vector<_3D>& X = GetReferenceFrame().GetXAxis();
+      q.SetVecFromTo(X,axis);
+      length_ = axis.GetNorm();
+    }
+
+    void 
+    PartUserJunction::DrawShape()
+    {
+      const double scale = Part::GetScaleValue();
+      Util::Draw::Cylinder(.01f*scale, length_, false);
+    }
+
+    void 
+    PartUserJunction::UpdateIcon()
+    {
+      PartUserJunction::DrawIcon(GetIcon(), GetColor().GetQColor());
+    }
+    
+    PartPoint& 
+    PartUserJunction::GetEndPoint()
+    {
+      OMC_ASSERT_MSG(endPoint_.GetPtr() != 0, "The end point is null");
+      return *endPoint_.GetPtr();
+    }
+
+    const PartPoint& 
+    PartUserJunction::GetEndPoint() const
+    {
+      OMC_ASSERT_MSG(endPoint_.GetPtr() != 0, "The end point is null");
+      return *endPoint_.GetPtr();
+    } 
+
+
+    Core::AutoRegisteredPtr<PartPoint, PartUserJunction >& 
+    PartUserJunction::GetEndPointPtr()
+    {
+      return endPoint_;
+    }
+    
+    const Core::AutoRegisteredPtr<PartPoint, PartUserJunction >& 
+    PartUserJunction::GetEndPointPtr() const
+    {
+      return endPoint_;      
+    }
+    
+
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    template<>
+    void
+    ItemCommonProperty<OpenMeca::Item::PartUserJunction>::BuildIconSymbol()
+    {
+      QIcon icon;
+      OpenMeca::Item::PartUserJunction::DrawIcon(iconSymbol_, Qt::gray);
+    }
+
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Item/PartUserJunction.hpp b/SRC/OpenMeca/Item/PartUserJunction.hpp
new file mode 100644
index 0000000..0b3f2c1
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserJunction.hpp
@@ -0,0 +1,135 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_PartUserJunction_hpp
+#define OpenMeca_Item_PartUserJunction_hpp
+
+
+#include "OpenMeca/Item/PartUser.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Gui/Dialog/DialogPartUserJunction.hpp"
+#include "OpenMeca/Item/PartUser.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+
+namespace OpenMeca
+{  
+
+  namespace Item
+  {
+
+    class PartPoint;
+
+    // A junction is a pipe between two points
+    class PartUserJunction: public PartUser, public Core::AutoRegister<PartUserJunction> 
+    {
+    public:
+      static const std::string GetStrType() { return std::string("Junction");};
+      static const QString GetQStrType() { return QObject::tr("Junction");};
+
+      static void Init();
+      static void DrawIcon(QIcon&, QColor);
+      typedef Gui::DialogPartUserJunction Dialog;
+
+
+    public:
+      PartUserJunction(PartPoint& point);
+      virtual ~PartUserJunction();
+      void DrawShape();
+      void UpdateIcon();
+      void BeginDraw();
+
+
+      // Accessor 
+      OMC_ACCESSOR(StartPoint , PartPoint,  startPoint_);
+
+      PartPoint& GetEndPoint();
+      const PartPoint& GetEndPoint() const ;
+
+      Core::AutoRegisteredPtr<PartPoint, PartUserJunction >& GetEndPointPtr();
+      const Core::AutoRegisteredPtr<PartPoint, PartUserJunction >& GetEndPointPtr() const;
+
+
+    private:
+      PartUserJunction(); //Not allowed, just for serialization
+      PartUserJunction(const PartUserJunction&);             //Not Allowed
+      PartUserJunction& operator=(const PartUserJunction&);  //Not Allowed
+
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    private:
+      PartPoint& startPoint_;
+      double length_;
+      Core::AutoRegisteredPtr<PartPoint, PartUserJunction > endPoint_;
+    };
+
+    
+    template<class Archive>
+    inline void 
+    PartUserJunction::save(Archive& ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUser);
+      ar << BOOST_SERIALIZATION_NVP(endPoint_);
+    }
+    
+    template<class Archive>
+    inline void 
+    PartUserJunction::load(Archive& ar, const unsigned int)
+    {
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUser);
+      ar >> BOOST_SERIALIZATION_NVP(endPoint_);
+    }
+
+
+  }
+
+}
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::PartUserJunction * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::PartPoint* parent = &t->GetStartPoint();
+      ar << parent;
+    }
+    
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::PartUserJunction * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::PartPoint* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Item::PartUserJunction(*parent);
+    }
+  }
+} // namespace ...
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartUserPipe.cpp b/SRC/OpenMeca/Item/PartUserPipe.cpp
new file mode 100644
index 0000000..aee97d1
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserPipe.cpp
@@ -0,0 +1,159 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/PartUserPipe.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserPipe)
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    void
+    PartUserPipe::Init()
+    {
+      Core::UserItemCommonProperty< PartUserPipe > & prop = 
+	Core::Singleton< Core::UserItemCommonProperty< PartUserPipe > >::Get();
+
+      prop.CreateAction_Edit();
+      prop.CreateAction_Delete();
+
+      // don't forget to instanciate UserRootItemCommonProperty<Body> before calling
+      // create action
+      Core::Singleton< Core::UserItemCommonProperty<PartPoint> >::Instanciate();
+      prop.CreateAction_NewWithAutomaticSelection<PartPoint>();
+    }
+
+
+
+    void 
+    PartUserPipe::DrawIcon(QIcon& icon, QColor color)
+    {
+      Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Part/Pipe.svg", icon, color);
+    }
+
+
+    
+    PartUserPipe::PartUserPipe(PartPoint& parent)
+      :PartUser(GetStrType(), parent),
+       axis_(1.,0.,0.,std::bind(&PartUserPipe::GetReferenceFrame, std::ref(*this))),
+       length_(0.5*Part::GetScaleValue()),
+       endPoint_(new PartPoint(*this))
+    {
+    }
+
+  
+    
+    
+    PartUserPipe::~PartUserPipe()
+    {
+    }
+
+    const Geom::Frame<_3D>& 
+    PartUserPipe::GetReferenceFrame() const
+    {
+      return GetBody().GetFrame();
+    }
+	     
+
+    PartPoint& 
+    PartUserPipe::GetStartPoint()
+    {
+      PartPoint& startPoint = dynamic_cast<PartPoint&>(GetParentItem());
+      return startPoint;
+    }
+
+    const PartPoint& 
+    PartUserPipe::GetStartPoint() const
+    {
+      const PartPoint& startPoint = dynamic_cast<const PartPoint&>(GetParentItem());
+      return startPoint;
+    }
+	     
+
+    Core::SetOfBase<Core::UserItem> 
+    PartUserPipe::GetAssociatedSelectedItem()
+    {
+      Core::SetOfBase<Core::UserItem> set;
+      set.AddItem(GetEndPoint());
+      return set;
+    }
+
+    void 
+    PartUserPipe::BeginDraw()
+    {
+      Geom::Point<_3D>& p = PartUser::GetPoint();
+      p = Geom::Point<_3D>(GetStartPoint().GetPoint(),
+			   std::bind(&PartUserPipe::GetReferenceFrame, std::ref(*this)));
+
+      Geom::Quaternion<_3D>& q = PartUser::GetQuaternion();
+      const Geom::Vector<_3D>& X = GetReferenceFrame().GetXAxis();
+      q.SetVecFromTo(X,axis_);
+
+      GetEndPoint().GetPoint()[0] = length_;
+    }
+
+    void 
+    PartUserPipe::DrawShape()
+    {
+      const double scale = Part::GetScaleValue();
+      Util::Draw::Cylinder(.01f*scale, length_, false);
+    }
+
+    void 
+    PartUserPipe::UpdateIcon()
+    {
+      PartUserPipe::DrawIcon(GetIcon(), GetColor().GetQColor());
+    }
+    
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    template<>
+    void
+    ItemCommonProperty<OpenMeca::Item::PartUserPipe>::BuildIconSymbol()
+    {
+      QIcon icon;
+      OpenMeca::Item::PartUserPipe::DrawIcon(iconSymbol_, Qt::gray);
+    }
+
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Item/PartUserPipe.hpp b/SRC/OpenMeca/Item/PartUserPipe.hpp
new file mode 100644
index 0000000..2d703c6
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserPipe.hpp
@@ -0,0 +1,141 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_PartUserPipe_hpp
+#define OpenMeca_Item_PartUserPipe_hpp
+
+
+#include "OpenMeca/Item/PartUser.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Gui/Dialog/DialogPartUserPipe.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+
+namespace OpenMeca
+{  
+
+  namespace Item
+  {
+
+    class PartPoint;
+
+    // A pipe is defined by a start point, a length and an axis.
+    class PartUserPipe: public PartUser, public Core::AutoRegister<PartUserPipe> 
+    {
+    
+    public:
+      static const std::string GetStrType() {return std::string("Pipe");};
+      static const QString GetQStrType() {return QObject::tr("Pipe");};
+
+
+      static void Init();
+      static void DrawIcon(QIcon&, QColor);
+      typedef Gui::DialogPartUserPipe Dialog;
+
+
+    public:
+      PartUserPipe(PartPoint& point);
+      virtual ~PartUserPipe();
+      void DrawShape();
+      void UpdateIcon();
+      void BeginDraw();
+
+      Core::SetOfBase<Core::UserItem> GetAssociatedSelectedItem();
+      const Geom::Frame<_3D>& GetReferenceFrame() const;
+
+      // Accessors
+      OMC_ACCESSOR     (Axis     , Geom::Vector<_3D>,  axis_    );
+      OMC_ACCESSOR     (Length   , double           ,  length_  );
+      OMC_ACCESSOR_PTR (EndPoint , PartPoint        ,  endPoint_);
+
+      PartPoint& GetStartPoint();
+      const PartPoint& GetStartPoint() const ;
+
+    private:
+      PartUserPipe(); //Not allowed, just for serialization
+      PartUserPipe(const PartUserPipe&);             //Not Allowed
+      PartUserPipe& operator=(const PartUserPipe&);  //Not Allowed
+
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    private:
+      Geom::Vector<_3D> axis_;
+      double length_;
+      PartPoint* endPoint_;
+    };
+
+    
+    template<class Archive>
+    inline void 
+    PartUserPipe::save(Archive& ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUser);
+      ar << BOOST_SERIALIZATION_NVP(axis_);
+      ar << BOOST_SERIALIZATION_NVP(length_);
+      ar << BOOST_SERIALIZATION_NVP(endPoint_);
+    }
+    
+    template<class Archive>
+    inline void 
+    PartUserPipe::load(Archive& ar, const unsigned int)
+    {
+      delete endPoint_;
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUser);
+      ar >> BOOST_SERIALIZATION_NVP(axis_);
+      ar >> BOOST_SERIALIZATION_NVP(length_);
+      ar >> BOOST_SERIALIZATION_NVP(endPoint_);
+    }
+
+
+  }
+
+}
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::PartUserPipe * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::PartPoint* parent = &t->GetStartPoint();
+      ar << parent;
+    }
+    
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::PartUserPipe * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::PartPoint* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Item::PartUserPipe(*parent);
+    }
+  }
+} // namespace ...
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartUserPoint.cpp b/SRC/OpenMeca/Item/PartUserPoint.cpp
new file mode 100644
index 0000000..2699150
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserPoint.cpp
@@ -0,0 +1,102 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "OpenMeca/Item/PartUserPoint.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/UserRootItemCommonProperty.hpp"
+
+#include "OpenMeca/Item/PartPoint_CreateAction_SpecializedT.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserPoint)
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    template<>
+    void 
+    UserItemCommonProperty<OpenMeca::Item::PartUserPoint>::CreateAction_Specialized() 
+    {
+      AddPopUpSeparator();
+      
+      // We call PartPoint_CreateAction_SpecializedT because it is needed by other class
+      UserItemCommonProperty<OpenMeca::Item::PartUserPoint>& me = *this;
+      OpenMeca::Item::PartPoint_CreateAction_SpecializedT(me);
+    }
+
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    void
+    PartUserPoint::Init()
+    {
+      Core::UserItemCommonProperty< PartUserPoint >& prop = 
+	Core::Singleton< Core::UserItemCommonProperty< PartUserPoint > >::Get();
+
+      prop.CreateAction_Edit();
+      prop.CreateAction_Delete();
+      
+      // don't forget to instanciate UserRootItemCommonProperty<Body> before calling
+      // create action
+      Core::Singleton< Core::UserRootItemCommonProperty<OpenMeca::Item::Body> >::Instanciate();
+      prop.CreateAction_NewWithAutomaticSelection<OpenMeca::Item::Body>();
+     
+      prop.CreateAction_Specialized();
+    }
+
+
+    void 
+    PartUserPoint::DrawIcon(QIcon& icon, QColor color)
+    {
+      PartPoint::DrawIcon(icon, color);
+    }
+
+    
+    PartUserPoint::PartUserPoint(Core::UserItem& parent)
+      :PartPoint(GetStrType(), parent),
+       centerExpr_(std::bind(&PartUser::GetReferenceFrame, std::ref(*this)))
+    {
+    }
+
+    PartUserPoint::~PartUserPoint()
+    {
+    }
+
+    void 
+    PartUserPoint::Update()
+    {
+      PartPoint::Update();
+      GetPoint() = centerExpr_;
+    }
+
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Item/PartUserPoint.hpp b/SRC/OpenMeca/Item/PartUserPoint.hpp
new file mode 100644
index 0000000..346c645
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserPoint.hpp
@@ -0,0 +1,134 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef OpenMeca_Item_PartUserPoint_hpp
+#define OpenMeca_Item_PartUserPoint_hpp
+
+
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Gui/Dialog/DialogPartUserPoint.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+
+
+namespace OpenMeca
+{  
+
+  namespace Item
+  {
+
+    // An user defined point that is drawn by a little sphere.
+    class PartUserPoint: public PartPoint, public Core::AutoRegister<PartUserPoint> 
+    {
+    public:
+      static const std::string GetStrType() {return std::string("Point");};
+      static const QString GetQStrType() {return QObject::tr("Point");};
+
+      static void Init();
+      static void DrawIcon(QIcon&, QColor);
+      typedef Gui::DialogPartUserPoint Dialog;
+
+
+    public:
+      PartUserPoint(Core::UserItem& parent);
+      virtual ~PartUserPoint();
+
+      virtual void Update();
+
+      OMC_ACCESSOR (CenterExpr, Util::ExprPoint,  centerExpr_);
+
+    private:
+      PartUserPoint();                                 //Just for serialization
+      PartUserPoint(const PartUserPoint&);             //Not Allowed
+      PartUserPoint& operator=(const PartUserPoint&);  //Not Allowed
+
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive& ar, const unsigned int);
+
+    private:
+      Util::ExprPoint centerExpr_;
+
+    };
+
+    
+    template<class Archive>
+    void PartUserPoint::serialize(Archive& ar, const unsigned int version)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartPoint);
+      if (version == 0)
+	const_cast<Util::ExprPoint&>(centerExpr_) = GetPoint();
+
+      if (version > 0)
+	  ar & BOOST_SERIALIZATION_NVP(centerExpr_);
+      
+    }
+  }
+}
+
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::PartUserPoint>::BuildIconSymbol()
+    {
+      QIcon icon;
+      OpenMeca::Item::PartUserPoint::DrawIcon(iconSymbol_, Qt::gray);
+    }
+
+  }
+}
+
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::PartUserPoint * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Core::UserItem* parent = &t->GetParentItem();
+      ar << parent;
+    }
+    
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::PartUserPoint * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Core::UserItem* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Item::PartUserPoint(*parent);
+    }
+  }
+} // namespace ...
+
+
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Item::PartUserPoint, 1)
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartUserShape.cpp b/SRC/OpenMeca/Item/PartUserShape.cpp
new file mode 100644
index 0000000..b7cba42
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserShape.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Item/PartUserShape.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserShape)
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    PartUserShape::PartUserShape(const std::string& strType, PartPoint& parent)
+      :PartUser(strType, parent)
+    {
+    }
+
+  
+    
+    
+    PartUserShape::~PartUserShape()
+    {
+    }
+
+    const Geom::Frame<_3D>& 
+    PartUserShape::GetReferenceFrame() const
+    {
+      return GetBody().GetFrame();
+    }
+	     
+    PartPoint& 
+    PartUserShape::GetStartPoint()
+    {
+      PartPoint& startPoint = dynamic_cast<PartPoint&>(GetParentItem());
+      return startPoint;
+    }
+
+    const PartPoint& 
+    PartUserShape::GetStartPoint() const
+    {
+      const PartPoint& startPoint = dynamic_cast<const PartPoint&>(GetParentItem());
+      return startPoint;
+    }
+	     
+
+
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Item/PartUserShape.hpp b/SRC/OpenMeca/Item/PartUserShape.hpp
new file mode 100644
index 0000000..d0bef79
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserShape.hpp
@@ -0,0 +1,89 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_PartUserShape_hpp
+#define OpenMeca_Item_PartUserShape_hpp
+
+
+#include "OpenMeca/Item/PartUser.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+namespace OpenMeca
+{  
+
+  namespace Item
+  {
+
+    class PartPoint;
+
+    // PartUserShape is a virtual base class that defines a geometry.
+    // A PartUserShape must have a PartPoint as parent.
+    //
+
+    class PartUserShape: public PartUser, public Core::AutoRegister<PartUserShape> 
+    {
+    
+    public:
+      PartUserShape(const std::string& strType, PartPoint& point);
+      virtual ~PartUserShape();
+
+      const Geom::Frame<_3D>& GetReferenceFrame() const;
+
+      PartPoint& GetStartPoint();
+      const PartPoint& GetStartPoint() const ;
+
+    private:
+      PartUserShape(); //Not allowed, just for serialization
+      PartUserShape(const PartUserShape&);             //Not Allowed
+      PartUserShape& operator=(const PartUserShape&);  //Not Allowed
+
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    };
+
+    
+    template<class Archive>
+    inline void 
+    PartUserShape::save(Archive& ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUser);
+    }
+    
+    template<class Archive>
+    inline void 
+    PartUserShape::load(Archive& ar, const unsigned int)
+    {
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUser);
+    }
+
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/PartUserShapeT.hpp b/SRC/OpenMeca/Item/PartUserShapeT.hpp
new file mode 100644
index 0000000..5a6598c
--- /dev/null
+++ b/SRC/OpenMeca/Item/PartUserShapeT.hpp
@@ -0,0 +1,249 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_PartUserGeometryT_hpp
+#define OpenMeca_Item_PartUserGeometryT_hpp
+
+
+#include "OpenMeca/Item/PartUserShape.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Gui/Dialog/DialogPartUserShapeT.hpp"
+#include "OpenMeca/Item/PartPoint.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+
+namespace OpenMeca
+{  
+
+  namespace Item
+  {
+
+    template <class T>
+    class PartUserShapeT: public PartUserShape, 
+			  public Core::AutoRegister<PartUserShapeT<T> > 
+    {
+    
+    public:
+      static const std::string GetStrType() {return T::GetStrType();};
+      static const QString GetQStrType() {return T::GetQStrType();};
+
+
+      static void Init();
+      static void DrawIcon(QIcon&, QColor);
+      typedef Gui::DialogPartUserShapeT<T> Dialog;
+
+
+    public:
+      PartUserShapeT(PartPoint& point);
+      virtual ~PartUserShapeT();
+      void DrawShape();
+      void UpdateIcon();
+      void BeginDraw();
+
+      T& GetShape();
+      const T& GetShape() const;
+
+      bool& GetCollisionState();
+      const bool& GetCollisionState() const;
+
+
+      void BuildChSystem(chrono::ChSystem&);
+
+    private:
+      PartUserShapeT(); //Not allowed, just for serialization
+      PartUserShapeT(const PartUserShapeT<T>&);             //Not Allowed
+      PartUserShapeT& operator=(const PartUserShapeT<T>&);  //Not Allowed
+
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    private:
+      T shape_;
+      bool collisionEnabled_;
+    };
+
+    template <class T>
+    template<class Archive>
+    inline void 
+    PartUserShapeT<T>::save(Archive& ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUserShape);
+      ar << BOOST_SERIALIZATION_NVP(shape_);
+      ar << BOOST_SERIALIZATION_NVP(collisionEnabled_);
+    }
+    
+    template <class T>
+    template<class Archive>
+    inline void 
+    PartUserShapeT<T>::load(Archive& ar, const unsigned int)
+    {
+      ar >> BOOST_SERIALIZATION_BASE_OBJECT_NVP(PartUserShape);
+      ar >> BOOST_SERIALIZATION_NVP(shape_);
+      ar >> BOOST_SERIALIZATION_NVP(collisionEnabled_);
+    }
+
+
+
+    template <class T>
+    inline void
+    PartUserShapeT<T>::Init()
+    {
+      Core::UserItemCommonProperty< PartUserShapeT<T> > & prop = 
+	Core::Singleton< Core::UserItemCommonProperty< PartUserShapeT<T> > >::Get();
+
+      prop.CreateAction_Edit();
+      prop.CreateAction_Delete();
+
+      // don't forget to instanciate UserRootItemCommonProperty<Body> before calling
+      // create action
+      Core::Singleton< Core::UserItemCommonProperty<PartPoint> >::Instanciate();
+      prop.template CreateAction_NewWithAutomaticSelection<PartPoint>();
+    }
+    
+    template <class T>
+    inline void 
+    PartUserShapeT<T>::DrawIcon(QIcon& icon, QColor color)
+    {
+      // Read svg icon file
+      QString svgFileName = ":/Rsc/Img/Shape/" + QString(T::GetStrType().c_str()) + ".svg";
+      Util::Icon::DrawIconFromSvgFile(svgFileName, icon, color);
+    }
+    
+    template <class T>
+    inline
+    PartUserShapeT<T>::PartUserShapeT(PartPoint& parent)
+      :PartUserShape(GetStrType(), parent),
+       shape_(*this),
+       collisionEnabled_(false)
+    {
+    }
+
+    template <class T>
+    inline
+    PartUserShapeT<T>::~PartUserShapeT()
+    {
+    }
+
+    template <class T>
+    inline void 
+    PartUserShapeT<T>::BeginDraw()
+    {
+      Geom::Point<_3D>& p = PartUser::GetPoint();
+      p = Geom::Point<_3D>(GetStartPoint().GetPoint(),
+			   std::bind(&PartUserShapeT<T>::GetReferenceFrame, std::ref(*this)));
+      shape_.BeginDraw();
+    }
+
+    template <class T>
+    inline void 
+    PartUserShapeT<T>::DrawShape()
+    {
+      shape_.Draw();
+    }
+
+    template <class T>
+    inline void 
+    PartUserShapeT<T>::UpdateIcon()
+    {
+      DrawIcon(GetIcon(), GetColor().GetQColor());
+    }
+
+    template <class T>
+    inline T& 
+    PartUserShapeT<T>::GetShape()
+    {
+      return shape_;
+    }
+
+    template <class T>
+    inline const T& 
+    PartUserShapeT<T>::GetShape() const
+    {
+      return shape_;
+    }
+
+    template <class T>
+    inline void 
+    PartUserShapeT<T>::BuildChSystem(chrono::ChSystem& chsystem)
+    {
+      if (GetCollisionState())
+	shape_.BuildChSystem(chsystem);
+    }
+
+
+    template <class T>
+    inline bool& 
+    PartUserShapeT<T>::GetCollisionState()
+    {
+      return collisionEnabled_;
+    }
+    
+    template <class T>
+    inline const bool& 
+    PartUserShapeT<T>::GetCollisionState() const
+    {
+      return collisionEnabled_;
+    }   
+
+  }
+
+}
+
+
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+
+    template<class Archive, class T>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::PartUserShapeT<T> * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::PartPoint* parent = &t->GetStartPoint();
+      ar << parent;
+    }
+    
+
+    template<class Archive, class T>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::PartUserShapeT<T> * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::PartPoint* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Item::PartUserShapeT<T>(*parent);
+    }
+  }
+} // namespace ...
+
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Physical.cpp b/SRC/OpenMeca/Item/Physical.cpp
new file mode 100644
index 0000000..ae5c903
--- /dev/null
+++ b/SRC/OpenMeca/Item/Physical.cpp
@@ -0,0 +1,142 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired from the "libItem" from 
+// the GranOO workbench : http://www.granoo.org and
+
+
+#include "OpenMeca/Item/Physical.hpp"
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/RootTreeItemT.hpp"
+#include "OpenMeca/Physic/Type.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::Physical)
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {    
+
+    const std::string 
+    Physical::GetStrType()
+    {
+      return std::string("Physical");
+    }
+
+    void
+    Physical::DumpAllDataToFile(const std::string& fileName)
+    {
+      std::ofstream dataFile;
+      dataFile.open (fileName.c_str());
+      OMC_ASSERT_MSG(dataFile.is_open(), "can't open data file");
+      dataFile.precision(10);
+      dataFile << std::scientific;
+
+      const std::vector<double>& time = 
+	Core::SystemSettingT<Setting::Simulation>::Get().GetTimeArray();
+      const unsigned int totIter = time.size();
+
+      Core::SetOfBase<Physical>& phys = 
+	Core::System::Get().GetSetOf<Physical>();
+      
+      dataFile << "Time (s)";
+      for (unsigned int i = 0; i < phys.GetTotItemNumber(); ++i)
+	{
+	  dataFile << '\t';
+	  phys(i).WriteHeaderDataFile(dataFile);
+	}
+      dataFile << '\n';
+      for (unsigned int iter = 0; iter < totIter; ++iter)
+	{
+	  dataFile << time[iter];
+	  for (unsigned int i = 0; i < phys.GetTotItemNumber(); ++i)
+	    {
+	      dataFile << '\t';
+	      phys(i).WriteDataFile(dataFile, iter);
+	    }
+	  dataFile << '\n';
+	}
+      dataFile.close();
+    }
+
+
+       
+    Physical::Physical(const std::string strType, QTreeWidgetItem& parentTreeItem)
+      :Core::DrawableUserItem(strType, parentTreeItem, false)
+    {
+    }
+    
+    Physical::~Physical()
+    {      
+    }
+
+    void 
+    Physical::FillDataMenu(QMenu* menu)
+    {
+      GetQuantity().GetDataType().FillDataMenu(menu);
+    }
+
+    const Util::Unit& 
+    Physical::GetUnit() const
+    {
+      return GetQuantity().GetUnit();
+    }
+
+    void 
+    Physical::WriteHeaderDataFile(std::ofstream& ofs)
+    {
+      return GetQuantity().GetDataType().WriteHeaderDataFile(ofs);
+    }
+
+    void 
+    Physical::WriteDataFile(std::ofstream& ofs, unsigned int i)
+    {
+      return GetQuantity().GetDataType().WriteDataFile(ofs, i);
+    }
+
+    const Util::Color& 
+    Physical::GetColor() const
+    {
+      return GetQuantity().GetColor();
+    }
+
+    Util::Color& 
+    Physical::GetColor()
+    {
+      return GetQuantity().GetColor();
+    }
+
+    const Body& 
+    Physical::GetBody() const
+    {
+      return GetParent().GetBody();
+    }
+
+    Body& 
+    Physical::GetBody()
+    {
+      return GetParent().GetBody();
+    }
+
+  } 
+}
diff --git a/SRC/OpenMeca/Item/Physical.hpp b/SRC/OpenMeca/Item/Physical.hpp
new file mode 100644
index 0000000..f7b24c2
--- /dev/null
+++ b/SRC/OpenMeca/Item/Physical.hpp
@@ -0,0 +1,90 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired from the "libUtil" from 
+// the GranOO workbench : http://www.granoo.org and
+
+#ifndef _OpenMeca_Item_Physical_hpp_
+#define _OpenMeca_Item_Physical_hpp_
+
+#include <string>
+#include <QMenu>
+#include "OpenMeca/Core/DrawableUserItem.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/AutoRegisteredPtr.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Physic/Quantity.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    class Physical : public Core::DrawableUserItem, 
+		     public Core::AutoRegister<Physical>
+    {
+
+    public:
+      static const std::string GetStrType(); 
+      static void DumpAllDataToFile(const std::string&);
+   
+    public:
+      Physical(const std::string, QTreeWidgetItem&);
+      virtual ~Physical();
+      
+      void FillDataMenu(QMenu*);
+      const Util::Unit& GetUnit() const; 
+      void WriteHeaderDataFile(std::ofstream&) ;
+      void WriteDataFile(std::ofstream&, unsigned int);
+
+      virtual Physic::Quantity& GetQuantity() = 0;
+      virtual const Physic::Quantity& GetQuantity() const = 0;
+
+      virtual const UserItem& GetParent() const = 0;
+      virtual UserItem& GetParent() = 0;
+
+      virtual const Util::Color& GetColor() const;
+      virtual Util::Color& GetColor();
+
+      virtual const Body& GetBody() const;
+      virtual Body& GetBody();
+
+      virtual bool IsLoad() const = 0;
+      virtual bool IsSensor() const = 0;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+
+    };
+    
+
+    template<class Archive>
+    inline void
+    Physical::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Core::DrawableUserItem);
+    }
+
+  }
+} 
+
+#endif
diff --git a/SRC/OpenMeca/Item/Sensor.cpp b/SRC/OpenMeca/Item/Sensor.cpp
new file mode 100644
index 0000000..0c7e5d7
--- /dev/null
+++ b/SRC/OpenMeca/Item/Sensor.cpp
@@ -0,0 +1,86 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include "OpenMeca/Item/Sensor.hpp"
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/RootTreeItemT.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::Sensor)
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {    
+
+    const std::string 
+    Sensor::GetStrType()
+    {
+      return std::string("Sensor");
+    }
+
+    const QString 
+    Sensor::GetQStrType()
+    {
+      return QObject::tr("Sensor");
+    }
+
+    void 
+    Sensor::AcquireAll()
+    {
+      Core::SetOfBase<Sensor>& sensor = Core::System::Get().GetSetOf<Sensor>();
+      for (unsigned int i = 0; i < sensor.GetTotItemNumber(); ++i)
+	sensor(i).Acquire();
+	  
+    }
+
+       
+    Sensor::Sensor(const std::string strType, QTreeWidgetItem& parentTreeItem)
+      :Physical(strType, parentTreeItem),
+       treeItem_(0)
+    {
+      QTreeWidgetItem& rootItem = Gui::RootTreeItemT<Sensor>::Get();
+      Core::Item& me = *this;
+      treeItem_ = new Gui::SecondaryTreeItem(rootItem, me);
+      AddSecondaryTreeItem(*treeItem_);
+    }
+    
+    Sensor::~Sensor()
+    {      
+      delete treeItem_;
+    }
+
+    bool 
+    Sensor::IsLoad() const
+    {
+      return false;
+    }
+    
+    bool 
+    Sensor::IsSensor() const
+    {
+      return true;
+    }
+
+  } 
+}
diff --git a/SRC/OpenMeca/Item/Sensor.hpp b/SRC/OpenMeca/Item/Sensor.hpp
new file mode 100644
index 0000000..fe7c939
--- /dev/null
+++ b/SRC/OpenMeca/Item/Sensor.hpp
@@ -0,0 +1,70 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_Sensor_hpp_
+#define _OpenMeca_Item_Sensor_hpp_
+
+
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+
+
+    class Sensor : public Physical, public Core::AutoRegister<Sensor>
+    {
+
+    public:
+      static const std::string GetStrType(); 
+      static const QString GetQStrType(); 
+      static void AcquireAll(); 
+   
+    public:
+      Sensor(const std::string strType, QTreeWidgetItem& parentTreeItem);
+      virtual ~Sensor();
+
+      virtual void Acquire() = 0;
+
+      bool IsLoad() const;
+      bool IsSensor() const;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    protected:
+      Gui::SecondaryTreeItem* treeItem_;
+
+    };
+    
+
+    template<class Archive>
+    inline void
+    Sensor::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Physical);
+    }
+
+  }
+} 
+
+#endif
diff --git a/SRC/OpenMeca/Item/SensorT.cpp b/SRC/OpenMeca/Item/SensorT.cpp
new file mode 100644
index 0000000..0b6d459
--- /dev/null
+++ b/SRC/OpenMeca/Item/SensorT.cpp
@@ -0,0 +1,35 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+// This source file was inspired from the "libItem" from 
+// the GranOO workbench : http://www.granoo.org and
+
+
+
+#include "OpenMeca/Item/SensorT.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+  
+  }
+} 
+
diff --git a/SRC/OpenMeca/Item/SensorT.hpp b/SRC/OpenMeca/Item/SensorT.hpp
new file mode 100644
index 0000000..a99857d
--- /dev/null
+++ b/SRC/OpenMeca/Item/SensorT.hpp
@@ -0,0 +1,293 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Item_SensorT_hpp_
+#define _OpenMeca_Item_SensorT_hpp_
+
+
+#include "OpenMeca/Item/Sensor.hpp"
+#include "OpenMeca/Core/UserItemCommonProperty.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+#include "OpenMeca/Gui/Dialog/DialogSensorT.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+
+   
+
+    template<class Parent, class Quantity, class How>
+    class SensorT : public Sensor, 
+                    public Core::AutoRegister<SensorT<Parent, Quantity, How> >
+    {
+    public:  
+      static const std::string GetStrType(); 
+      static const QString GetQStrType(); 
+      static void Init();
+      static void DrawIcon(QIcon&, QColor);
+      typedef Gui::DialogSensorT<Parent, Quantity, How> Dialog;
+
+    public:      
+      SensorT(Parent&);
+      ~SensorT();
+
+      void UpdateIcon();
+      void DrawShape();
+      void BeginDraw();
+      void EndDraw();
+      Physic::Quantity& GetQuantity();
+      const Physic::Quantity& GetQuantity() const;
+
+      void Acquire();
+
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+      
+      virtual const Geom::Frame<_3D>& GetFrame() const;     
+
+      const Core::AutoRegisteredPtr<Parent, SensorT >& GetParentItemPtr() const;
+      Core::AutoRegisteredPtr<Parent, SensorT >& GetParentItemPtr();
+
+      Parent& GetParent();
+      const Parent& GetParent() const;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      Core::AutoRegisteredPtr<Parent, SensorT > parentItem_;
+      Quantity quantity_;
+    };
+
+    template<class Parent, class Quantity, class How>
+    template<class Archive>
+    inline void
+    SensorT<Parent, Quantity, How>::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Sensor);
+    }
+
+    
+    template<class Parent, class Quantity, class How>
+    inline const std::string 
+    SensorT<Parent, Quantity, How>::GetStrType()
+    {
+      return Sensor::GetStrType()+ "@" + Quantity::GetStrType();
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline const QString
+    SensorT<Parent, Quantity, How>::GetQStrType()
+    {
+      return Sensor::GetQStrType()+ "@" + Quantity::GetQStrType();
+    }
+
+
+    template<class Parent, class Quantity, class How>
+    inline void
+    SensorT<Parent, Quantity, How>::Init()
+    {
+      Core::UserItemCommonProperty< SensorT<Parent, Quantity, How> > & prop = 
+	Core::Singleton< Core::UserItemCommonProperty< SensorT<Parent, Quantity, How> > >::Get();
+
+      prop.CreateAction_Edit();
+      prop.CreateAction_Delete();
+
+      // don't forget to instanciate UserRootItemCommonProperty<Body> before calling
+      // create action
+      Core::Singleton< Core::UserItemCommonProperty<Parent> >::Instanciate();
+      prop.template CreateAction_NewWithAutomaticSelection<Parent>();
+    }
+    
+    template <class Parent, class Quantity, class How>
+    inline void 
+    SensorT<Parent, Quantity, How>::DrawIcon(QIcon& icon, QColor color)
+    {
+      // Read svg icon file
+      QString svgFileName = ":/Rsc/Img/Sensor/" + QString(Quantity::GetStrType().c_str()) + ".svg";
+      Util::Icon::DrawIconFromSvgFile(svgFileName, icon, color);
+    }
+
+
+    template<class Parent, class Quantity, class How> 
+    inline 
+    SensorT<Parent, Quantity, How>::SensorT(Parent& parent)
+      :Sensor(GetStrType(), parent.GetMainTreeItem()), 
+       parentItem_(*this, parent),
+       quantity_(*this)
+    {
+      UpdateIcon();
+      Sensor::treeItem_->Update();
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline 
+    SensorT<Parent, Quantity, How>::~SensorT()
+    {
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    SensorT<Parent, Quantity, How>::UpdateIcon()
+    {
+      DrawIcon(GetIcon(), GetColor().GetQColor());
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline Physic::Quantity& 
+    SensorT<Parent, Quantity, How>::GetQuantity()
+    {
+      return quantity_;
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline const Physic::Quantity& 
+    SensorT<Parent, Quantity, How>::GetQuantity() const
+    {
+      return quantity_;
+    }
+
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    SensorT<Parent, Quantity, How>::DrawShape()
+    {
+      quantity_.Draw();
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    SensorT<Parent, Quantity, How>::BeginDraw()
+    {
+      quantity_.BeginDraw();
+    }
+
+    template<class Parent, class Quantity, class How> 
+    inline void 
+    SensorT<Parent, Quantity, How>::EndDraw()
+    {
+      quantity_.EndDraw();
+    }
+
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    SensorT<Parent, Quantity, How>::Acquire() 
+    { 
+      quantity_.GetRealDataType().Update(How::Acquire(*this));
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    SensorT<Parent, Quantity, How>::SaveState()
+    {
+      Acquire();
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    SensorT<Parent, Quantity, How>::ResetState()
+    {
+      quantity_.GetDataType().ResetState();
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline void 
+    SensorT<Parent, Quantity, How>::RecoveryState(unsigned int i)
+    {
+      quantity_.GetDataType().RecoveryState(i);
+    }
+
+    template<class Parent, class Quantity, class How>
+    inline const Geom::Frame<_3D>& 
+    SensorT<Parent, Quantity, How>::GetFrame() const
+    {
+      return GetParent().GetFrame();
+    }
+
+  
+
+    template<class Parent, class Quantity, class How>
+    inline const Core::AutoRegisteredPtr<Parent, SensorT<Parent, Quantity, How> >& 
+    SensorT<Parent, Quantity, How>::GetParentItemPtr() const
+    {
+      return parentItem_;
+    }
+
+    
+    template<class Parent, class Quantity, class How>
+    inline Core::AutoRegisteredPtr<Parent, SensorT<Parent, Quantity, How> >& 
+    SensorT<Parent, Quantity, How>::GetParentItemPtr()
+      {
+      return parentItem_;
+    }
+
+
+    template<class Parent, class Quantity, class How>
+    inline Parent& 
+    SensorT<Parent, Quantity, How>::GetParent()
+    {
+      return *GetParentItemPtr().GetPtr();
+    }
+    
+    template<class Parent, class Quantity, class How>
+    inline const Parent& 
+    SensorT<Parent, Quantity, How>::GetParent() const
+    {
+      return *GetParentItemPtr().GetPtr();      
+    }
+
+
+  }
+} 
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive, class Parent, class Quantity, class How>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Item::SensorT<Parent, Quantity, How> * t, 
+				    const unsigned int)
+    {
+      const Parent* parent = &t->GetParent();
+      ar << parent;
+    }
+    
+
+    template<class Archive, class Parent, class Quantity, class How>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Item::SensorT<Parent, Quantity, How> * t, 
+				    const unsigned int)
+    {
+      Parent* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Item::SensorT<Parent, Quantity, How>(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Shape/Box.cpp b/SRC/OpenMeca/Item/Shape/Box.cpp
new file mode 100644
index 0000000..068b053
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Box.cpp
@@ -0,0 +1,100 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Item/Shape/Box.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Box>)
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+    
+      const std::string
+      Box::GetStrType()
+      {
+	return "Box";
+      }
+
+      const QString
+      Box::GetQStrType()
+      {
+	return QObject::tr("Box");
+      }
+      
+
+      Box::Box(PartUser& part)
+	:ShapeBase(part),
+	 lx_(0.),
+	 ly_(0.),
+	 lz_(0.),
+	 attitude_()
+      {
+      }
+   
+      Box::~Box()
+      {
+      }
+    
+
+      void 
+      Box::BeginDraw()
+      {
+	Geom::Quaternion<_3D>& q = GetPart().GetQuaternion();
+	q[0] = attitude_[0];
+	q[1] = attitude_[1];
+	q[2] = attitude_[2];
+	q.GetReal() = attitude_.GetReal();
+      }
+
+      void 
+      Box::Draw() const
+      {
+	Util::Draw::Box(lx_, ly_, lz_);
+      }
+
+      void 
+      Box::BuildChSystem(chrono::ChSystem&)
+      {
+	
+	Body& body = GetPart().GetBody();
+	Geom::Frame<_3D>&(Body::*fnptr)() = &Body::GetFrame;
+	std::function<const Geom::Frame<_3D>& ()> f = std::bind(fnptr, std::ref(body));
+
+	Geom::Point<_3D> p(GetPart().GetPoint(), f);
+	chrono::ChVector<> chp = body.ExpressPointInLocalChFrame(p);
+	chrono::ChMatrix33<> chm = attitude_.ToRotationMatrix().ToChMatrix();
+
+	chrono::ChSharedBodyPtr& chbody = body.GetChBodyPtr();
+	chbody->GetCollisionModel()->AddBox(lx_/2., ly_/2., lz_/2., &chp, &chm);
+	chbody->SetCollide(true);
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Item/Shape/Box.hpp b/SRC/OpenMeca/Item/Shape/Box.hpp
new file mode 100644
index 0000000..09ffc66
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Box.hpp
@@ -0,0 +1,111 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Shape_Box_hpp
+#define OpenMeca_Item_Shape_Box_hpp
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Item/Shape/ShapeBase.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/ShapeDialogBox.hpp"
+
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+    
+      
+      class GuiBox;
+
+      class Box : public ShapeBase
+      {
+      public:  
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	typedef OpenMeca::Gui::Shape::ShapeDialogBox GuiManager;
+	static const bool CollisionDetectionAllowed = true;
+	
+      public:
+	Box(PartUser&);
+	~Box();
+	
+	void Draw() const;
+	void BeginDraw();
+
+	void BuildChSystem(chrono::ChSystem&);
+	
+	// Accessors
+	OMC_ACCESSOR(LengthX    , double                ,  lx_      );
+	OMC_ACCESSOR(LengthY    , double                ,  ly_      );
+	OMC_ACCESSOR(LengthZ    , double                ,  lz_      );
+	OMC_ACCESSOR(Attitude   , Geom::Quaternion<_3D> ,  attitude_);
+	OMC_ACCESSOR(Quaternion , Geom::Quaternion<_3D> ,  attitude_);
+
+	
+      private:
+	friend class boost::serialization::access;
+	template<class Archive> void serialize(Archive& ar, const unsigned int version);
+	
+      private:
+	double lx_;
+	double ly_;
+	double lz_;
+	Geom::Quaternion<_3D> attitude_;
+      }; 
+      
+      template<class Archive>
+      inline void
+      Box::serialize(Archive& ar, const unsigned int)
+      {
+	ar & BOOST_SERIALIZATION_NVP(lx_);
+	ar & BOOST_SERIALIZATION_NVP(ly_);
+	ar & BOOST_SERIALIZATION_NVP(lz_);
+	ar & BOOST_SERIALIZATION_NVP(attitude_);
+      }
+      
+    }
+  }
+}
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Box> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Box>::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Shape/Cylinder.cpp b/SRC/OpenMeca/Item/Shape/Cylinder.cpp
new file mode 100644
index 0000000..3724537
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Cylinder.cpp
@@ -0,0 +1,103 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Item/Shape/Cylinder.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder>)
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+    
+      const std::string
+      Cylinder::GetStrType()
+      {
+	return "Cylinder";
+      }
+
+      const QString
+      Cylinder::GetQStrType()
+      {
+	return QObject::tr("Cylinder");
+      }
+      
+
+      Cylinder::Cylinder(PartUser& part)
+	:ShapeBase(part),
+	 radius_(0.),
+	 length_(0.),
+	 axis_(1., 0., 0., std::bind(&PartUser::GetReferenceFrame, std::ref(part)))
+      {
+      }
+   
+      Cylinder::~Cylinder()
+      {
+      }
+    
+
+      void 
+      Cylinder::BeginDraw()
+      {
+	Geom::Quaternion<_3D>& q = GetPart().GetQuaternion();
+	const Geom::Vector<_3D>& X = GetPart().GetReferenceFrame().GetXAxis();
+	q.SetVecFromTo(X,axis_);
+      }
+
+      void 
+      Cylinder::Draw() const
+      {
+	Util::Draw::Cylinder(radius_, length_);
+      }
+
+
+      void 
+      Cylinder::BuildChSystem(chrono::ChSystem&)
+      {
+	Body& body = GetPart().GetBody();
+	Geom::Frame<_3D>&(Body::*fnptr)() = &Body::GetFrame;
+	std::function<const Geom::Frame<_3D>& ()> f = std::bind(fnptr, std::ref(body));
+
+	Geom::Point<_3D> p(GetPart().GetPoint(), f);
+	chrono::ChVector<> chp = body.ExpressPointInLocalChFrame(p);
+	
+	//
+	Geom::Quaternion<_3D> q(GetPart().GetQuaternion());
+	const Geom::Vector<_3D>& Y = GetPart().GetReferenceFrame().GetYAxis();
+	q.SetVecFromTo(Y,axis_);
+	chrono::ChMatrix33<> chm = q.ToRotationMatrix().ToChMatrix();
+
+	chrono::ChSharedBodyPtr& chbody = body.GetChBodyPtr();
+	chbody->GetCollisionModel()->AddCylinder(radius_, radius_, length_, &chp, &chm);
+	chbody->SetCollide(true);
+      }
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Item/Shape/Cylinder.hpp b/SRC/OpenMeca/Item/Shape/Cylinder.hpp
new file mode 100644
index 0000000..94c7ed2
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Cylinder.hpp
@@ -0,0 +1,105 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Shape_Cylinder_hpp
+#define OpenMeca_Item_Shape_Cylinder_hpp
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "OpenMeca/Item/Shape/ShapeBase.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/DialogCylinder.hpp"
+
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+    
+      
+      class GuiCylinder;
+
+      class Cylinder : public ShapeBase
+      {
+      public:  
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	typedef OpenMeca::Gui::Shape::DialogCylinder GuiManager;
+	static const bool CollisionDetectionAllowed = true;
+
+      public:
+	Cylinder(PartUser&);
+	~Cylinder();
+	
+	void Draw() const;
+	void BeginDraw();
+	void BuildChSystem(chrono::ChSystem&);
+
+	// Accessors
+	OMC_ACCESSOR(Radius , double            ,  radius_);
+	OMC_ACCESSOR(Length , double            ,  length_);
+	OMC_ACCESSOR(Axis   , Geom::Vector<_3D> ,  axis_);
+
+	
+      private:
+	friend class boost::serialization::access;
+	template<class Archive> void serialize(Archive& ar, const unsigned int version);
+	
+      private:
+	double radius_;
+	double length_;
+	Geom::Vector<_3D> axis_;
+      }; 
+      
+      template<class Archive>
+      inline void
+      Cylinder::serialize(Archive& ar, const unsigned int)
+      {
+	ar & BOOST_SERIALIZATION_NVP(radius_);
+	ar & BOOST_SERIALIZATION_NVP(length_);
+	ar & BOOST_SERIALIZATION_NVP(axis_);
+      }
+      
+    }
+  }
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder>::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Shape/Ground.cpp b/SRC/OpenMeca/Item/Shape/Ground.cpp
new file mode 100644
index 0000000..a86b6ab
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Ground.cpp
@@ -0,0 +1,91 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Item/Shape/Ground.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground>)
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+    
+      const std::string
+      Ground::GetStrType()
+      {
+	return "Ground";
+      }
+
+      const QString
+      Ground::GetQStrType()
+      {
+	return QObject::tr("Ground");
+      }
+      
+
+      Ground::Ground(PartUser& part)
+	: ShapeBase(part),
+	  axis_(1., 0., 0., std::bind(&PartUser::GetReferenceFrame, std::ref(part)))
+      {
+      }
+   
+      Ground::~Ground()
+      {
+      }
+    
+
+      void 
+      Ground::BeginDraw()
+      {
+	Geom::Quaternion<_3D>& q = GetPart().GetQuaternion();
+	const Geom::Vector<_3D>& X = GetPart().GetReferenceFrame().GetXAxis();
+	q.SetVecFromTo(X,axis_);
+      }
+
+      void 
+      Ground::Draw() const
+      {
+	static GLUquadric* quadric = gluNewQuadric();
+	const double scale = Part::GetScaleValue();
+	glTranslatef(0.01f*scale, 0.0f, 0.0f);
+	Util::Draw::Box(0.01f*scale, 0.15f*scale, 0.35f*scale);
+	glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+	glTranslatef(-0.2f*scale, 0.0f, 0.0f);
+	for (unsigned int i=0; i<4; i++)
+	  {
+            glTranslatef(0.08*scale, 0.0f, 0.0f);
+            glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
+            gluCylinder(quadric, 0.01*scale, 0.01*scale, 0.15*scale, 30, 1);
+            glRotatef(-45.0f, 0.0f, 1.0f, 0.0f);
+	  }
+      }
+
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Item/Shape/Ground.hpp b/SRC/OpenMeca/Item/Shape/Ground.hpp
new file mode 100644
index 0000000..492e0ee
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Ground.hpp
@@ -0,0 +1,93 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Shape_Ground_hpp
+#define OpenMeca_Item_Shape_Ground_hpp
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "OpenMeca/Item/Shape/ShapeBase.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/DialogGround.hpp"
+
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+
+      class Ground : public ShapeBase
+      {
+      public:  
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	typedef OpenMeca::Gui::Shape::DialogGround GuiManager;
+	static const bool CollisionDetectionAllowed = false;
+
+      public:
+	Ground(PartUser& part);
+	~Ground();
+      
+	void Draw() const;
+	void BeginDraw();
+	
+	// Accessors
+	OMC_ACCESSOR(Axis, Geom::Vector<_3D>,  axis_);
+
+      private:
+	friend class boost::serialization::access;
+	template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+      private:
+	Geom::Vector<_3D> axis_;
+
+      }; 
+    
+
+      template<class Archive>
+      inline void
+      Ground::serialize(Archive& ar, const unsigned int)
+      {
+	ar & BOOST_SERIALIZATION_NVP(axis_);
+      }
+
+    }
+  }
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground>::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Shape/Shape.pro b/SRC/OpenMeca/Item/Shape/Shape.pro
new file mode 100644
index 0000000..bd03974
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Shape.pro
@@ -0,0 +1,31 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Item/Shape/ShapeBase.hpp \
+           Item/Shape/Box.hpp \
+           Item/Shape/Sphere.hpp \
+           Item/Shape/Cylinder.hpp \
+           Item/Shape/Ground.hpp
+
+SOURCES += Item/Shape/ShapeBase.cpp \
+           Item/Shape/Box.cpp \
+           Item/Shape/Sphere.cpp \
+           Item/Shape/Cylinder.cpp \
+           Item/Shape/Ground.cpp
diff --git a/SRC/OpenMeca/Item/Shape/ShapeBase.cpp b/SRC/OpenMeca/Item/Shape/ShapeBase.cpp
new file mode 100644
index 0000000..6207197
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/ShapeBase.cpp
@@ -0,0 +1,49 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Item/Shape/ShapeBase.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+    
+      ShapeBase::ShapeBase(PartUser& part)
+	:part_(part)
+       
+      {
+      }
+   
+      ShapeBase::~ShapeBase()
+      {
+      }
+
+      void 
+      ShapeBase::BuildChSystem(chrono::ChSystem&)
+      {
+      }
+    
+    
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Item/Shape/ShapeBase.hpp b/SRC/OpenMeca/Item/Shape/ShapeBase.hpp
new file mode 100644
index 0000000..8f520f2
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/ShapeBase.hpp
@@ -0,0 +1,74 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Shape_ShapeBase_hpp
+#define OpenMeca_Item_Shape_ShapeBase_hpp
+
+#include <QString>
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "OpenMeca/Item/PartUser.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+
+
+      class ShapeBase
+      {
+      public:
+	ShapeBase(PartUser& part);
+	virtual ~ShapeBase();
+	
+	virtual void Draw() const = 0;
+	virtual void BeginDraw() = 0;
+
+
+	virtual void BuildChSystem(chrono::ChSystem&);
+
+	// Accessors
+	OMC_ACCESSOR(Part, PartUser,  part_);
+	
+      private:
+	friend class boost::serialization::access;
+	template<class Archive> void serialize(Archive& ar, const unsigned int version);
+	
+      private:
+	PartUser& part_;
+      }; 
+    
+
+      template<class Archive>
+      inline void
+      ShapeBase::serialize(Archive& ar, const unsigned int)
+      {
+      }
+
+      
+
+    }
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Shape/Sphere.cpp b/SRC/OpenMeca/Item/Shape/Sphere.cpp
new file mode 100644
index 0000000..528575a
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Sphere.cpp
@@ -0,0 +1,92 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Item/Shape/Sphere.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Util/Draw.hpp"
+#include "OpenMeca/Gui/Prop/PropTree.hpp"
+
+#include "Serialization/export.hpp"
+BOOST_CLASS_EXPORT(OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Sphere>)
+
+
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+    
+      const std::string
+      Sphere::GetStrType()
+      {
+	return "Sphere";
+      }
+
+      const QString
+      Sphere::GetQStrType()
+      {
+	return QObject::tr("Sphere");
+      }
+      
+
+      Sphere::Sphere(PartUser& part)
+	:ShapeBase(part),
+	 radius_(0.)
+       
+      {
+      }
+   
+      Sphere::~Sphere()
+      {
+      }
+    
+      void 
+      Sphere::BeginDraw()
+      {
+      }
+
+      void 
+      Sphere::Draw() const
+      {
+	Util::Draw::Sphere(radius_);
+      }
+
+      void 
+      Sphere::BuildChSystem(chrono::ChSystem&)
+      {
+	Body& body = GetPart().GetBody();
+	Geom::Frame<_3D>&(Body::*fnptr)() = &Body::GetFrame;
+	std::function<const Geom::Frame<_3D>& ()> f = std::bind(fnptr, std::ref(body));
+
+	Geom::Point<_3D> p(GetPart().GetPoint(), f);
+	chrono::ChVector<> chp = body.ExpressPointInLocalChFrame(p);
+
+	chrono::ChSharedBodyPtr& chbody = body.GetChBodyPtr();
+	chbody->GetCollisionModel()->AddSphere(radius_, &chp);
+	chbody->SetCollide(true);
+      }
+
+    }
+  }
+}
diff --git a/SRC/OpenMeca/Item/Shape/Sphere.hpp b/SRC/OpenMeca/Item/Shape/Sphere.hpp
new file mode 100644
index 0000000..e00c93c
--- /dev/null
+++ b/SRC/OpenMeca/Item/Shape/Sphere.hpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Shape_Sphere_hpp
+#define OpenMeca_Item_Shape_Sphere_hpp
+
+#include <QString>
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+#include "OpenMeca/Item/Shape/ShapeBase.hpp"
+#include "OpenMeca/Gui/Dialog/Shape/DialogSphere.hpp"
+
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Item/PartUserShapeT.hpp"
+
+namespace OpenMeca
+{
+  namespace Item
+  {
+    namespace Shape
+    {
+      class GuiSphere;
+
+      class Sphere : public ShapeBase
+      {
+      public:  
+	static const std::string GetStrType(); 
+	static const QString GetQStrType(); 
+	typedef OpenMeca::Gui::Shape::DialogSphere GuiManager;
+	static const bool CollisionDetectionAllowed = true;
+
+      public:
+	Sphere(PartUser&);
+	~Sphere();
+	
+	void Draw() const;
+	void BeginDraw();
+
+	void BuildChSystem(chrono::ChSystem&);
+
+	// Accessors
+	OMC_ACCESSOR(Radius, double,  radius_);
+
+	
+      private:
+	friend class boost::serialization::access;
+	template<class Archive> void serialize(Archive& ar, const unsigned int version);
+	
+      private:
+	double radius_;
+	
+      }; 
+
+    template<class Archive>
+    inline void
+    Sphere::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(radius_);
+    }
+
+    }
+  }
+}
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+    
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Sphere> >::BuildIconSymbol()
+    {
+      OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Sphere>::DrawIcon(iconSymbol_, Qt::gray);
+    }
+  }
+}
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Item/Variable.cpp b/SRC/OpenMeca/Item/Variable.cpp
new file mode 100644
index 0000000..c925030
--- /dev/null
+++ b/SRC/OpenMeca/Item/Variable.cpp
@@ -0,0 +1,67 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QSvgRenderer>
+
+#include "OpenMeca/Item/Variable.hpp"
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Core/UserRootItemCommonProperty.hpp"
+
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Item::Variable)
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    void
+    Variable::Init()
+    {
+      Core::Singleton< Core::UserRootItemCommonProperty<Variable> >::Get().CreateAction_All();
+    }
+     
+  
+
+      
+    Variable::Variable()
+      :Core::UserRootItem(Variable::GetStrType(), Core::Singleton< Core::UserRootItemCommonProperty<Variable> >::Get().GetRootTreeWidgetItem()),
+       Util::Var()
+    {
+    }
+
+    Variable::~Variable()
+    {
+    }
+
+    void 
+    Variable::UpdateIcon()
+    {
+      GetIcon() = Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Equation.svg");
+    }
+
+
+  }
+
+}
+
+
diff --git a/SRC/OpenMeca/Item/Variable.hpp b/SRC/OpenMeca/Item/Variable.hpp
new file mode 100644
index 0000000..1611fe2
--- /dev/null
+++ b/SRC/OpenMeca/Item/Variable.hpp
@@ -0,0 +1,102 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Variable_hpp
+#define OpenMeca_Item_Variable_hpp
+
+#include "OpenMeca/Core/UserRootItem.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Gui/Dialog/DialogVariable.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+#include "OpenMeca/Core/ItemCommonProperty.hpp"
+#include "OpenMeca/Util/Var.hpp"
+
+
+
+namespace OpenMeca
+{  
+  namespace Item
+  {
+
+
+    // The physical rigid body
+    class Variable: public Core::UserRootItem, public Core::AutoRegister<Variable>,
+		    public Util::Var
+    {
+    
+    public:
+      static const std::string GetStrType() {return "Variable";}; 
+      static const QString GetQStrType() {return QObject::tr("Variable");}; 
+      static void Init();
+
+      friend class  Gui::DialogVariable;
+      typedef Gui::DialogVariable Dialog;
+
+    public:
+      Variable();
+      virtual ~Variable();
+
+      void UpdateIcon();
+
+
+    private:
+      Variable(const Variable&);             //Not Allowed
+      Variable& operator=(const Variable&);  //Not Allowed
+      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Variable::serialize(Archive & ar, const unsigned int)
+      {
+	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Core::UserRootItem);
+	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Util::Var);
+      }
+
+
+  }
+
+}
+
+
+namespace OpenMeca
+{  
+  namespace Core
+  {
+
+    template<>
+    inline void
+    ItemCommonProperty<OpenMeca::Item::Variable>::BuildIconSymbol()
+    {
+      iconSymbol_ = Util::Icon::DrawIconFromSvgFile(":/Rsc/Img/Equation.svg");
+    }
+
+  }
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Main.cpp b/SRC/OpenMeca/Main.cpp
new file mode 100644
index 0000000..56280aa
--- /dev/null
+++ b/SRC/OpenMeca/Main.cpp
@@ -0,0 +1,62 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <cstdlib>
+
+#include <QApplication>
+#include <QSplashScreen>
+#include <QBitmap>
+#include <QThread>
+
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Core/Software.hpp"
+#include "OpenMeca/Setting/LangManager.hpp"
+#include "ChronoEngine/physics/ChApidll.h"
+
+
+
+int main(int argc, char *argv[])
+{
+  chrono::DLL_CreateGlobals();
+  
+  
+
+  QApplication app(argc, argv);
+  OpenMeca::Core::Singleton<OpenMeca::Setting::LangManager>::Get().ReadXmlFile();
+  OpenMeca::Core::Singleton<OpenMeca::Setting::LangManager>::Get().Apply(app);
+
+  QString welcome_msg = QObject::tr("Welcome to openmeca") + " version";
+  welcome_msg += OpenMeca::Core::Software::Get().Version().ToString().c_str();
+  OpenMeca::Core::DisplayInfoMsg(welcome_msg);
+
+  std::string fileName = "";
+  if (argc == 2) 
+    fileName = argv[1];
+
+  OpenMeca::Gui::MainWindow*  window = new OpenMeca::Gui::MainWindow(fileName);
+  window->show();
+  int res = app.exec();
+
+  chrono::DLL_DeleteGlobals();
+  delete window;
+
+  OpenMeca::Core::DisplayInfoMsg(QObject::tr("Good bye, see you soon !"));
+  return res;
+} 
diff --git a/SRC/OpenMeca/Note.txt b/SRC/OpenMeca/Note.txt
new file mode 100644
index 0000000..ee2bcc8
--- /dev/null
+++ b/SRC/OpenMeca/Note.txt
@@ -0,0 +1,153 @@
+***********************************
+* Welcome to openmeca's sources ! *
+***********************************
+The source code openmeca is quit complicated. It suffers of "the spaghetti syndrome". 
+You need to jump from one class to another class to understand the execution of the software.
+If you discover this code, you will quickly feel loose in this labyrinth.
+This minimal text will help you to find your way !
+
+
+--------------------------
+Updating french traduction
+--------------------------
+In the current directory, run the following commands :
+lupdate ./OpenMeca.pro
+linguist Rsc/Lang/openmeca_fr.ts
+lrelease ./OpenMeca.pro
+
+To force adding some keyword please use the
+Software::FakeTranslate() method of the Core/Software.cpp source file
+
+---------------------------------------
+Explanation of the general architecture
+---------------------------------------
+The sources are divided in :
+ - "Core"  -> the core of openmeca software. be carefull, if you touch it, it will explode !
+ - "Geom"  -> the geometrical part : vector, quaternion, frame, etc.
+ - "Gui"   -> all the graphical interfaces are here
+ - "Icons" -> contains the images and icons used in openmeca
+ - "Item"  -> you will find here all the items that can be created on-the-fly by the users : 
+              bodies, links, points, etc.
+ - "SystemSetting" -> the classes that contains the user setting of a session
+
+
+--------------------------------
+The openmeca file format (*.omc)
+--------------------------------
+The openmeca file format uses the boost serialization. To avoid version problems of boost 
+serialization (that conducts to save/load problem between different users that uses different
+version of the boost library), openmeca embeds it's own version of the boost library.
+
+
+--------------------
+undo/redo management
+--------------------
+Each time the user change its system, openmeca stores a complete backup of the system as (*.omc) file inside the memory. It's a little bit "brute force" way but it works well !
+
+
+---------------------------
+About the core architecture
+---------------------------
+The developed architecture is quiet complex. The aim of this architecture is to avoid 
+data corruption and code replication. All these fastidious task are coded here. I build the 
+code in a paranoid way and a lot of assertion were put inside the source code. 
+
+If you want to code a new user item feature. This item probably needs to appear with 
+an icon in the treeview, to color itself with the right colors, to be removed if it's 
+parent is removed, to be automatically saved and loaded in *.omc file, etc.
+All these features are common to all items so the "core" part of openmeca is in charge 
+of these common tasks. The next sections will detail this architecture.
+
+----------------
+RootItem Vs Item
+----------------
+A RootItem does not need parent. For example, the bodies and the links are RootItem. All 
+the other items are Items that need a parent. 
+
+----------------------------------
+the .....CommonProperty<T> classes
+----------------------------------
+The .....CommonProperty<T> classes are template singleton classes. Only one 
+.....CommonProperty<T> is allowed per class. This class is used to concatenate 
+the common behavior of classes such as icons management, action (new, edit, delete) 
+managements, etc.
+
+
+-----------------------------------------------------------------------------------------
+Where are defined the icons, the menus, the pop-up menus and actions for each user item ?
+-----------------------------------------------------------------------------------------
+
+1/ The icon
+You must specialize the Core::ItemCommonProperty<T>::BuildIconSymbol() to customize 
+the icon of an user item. Generally, it calls a method of the UserItem class T that draws
+the icon with the right colors.
+
+2/ The menu (generally new, edit, delete)
+These menus are built by the static method Init() of the UserItem class T.
+Don't forget to call this static method of the Gui::MainWindow constructors !
+Generally, the Init() method calls the CreateAction_...() methods 
+of the singleton Core::UserItemCommonProperty<T>(). Be careful with the "new" feature.
+Some items need a parent at their construction. For these items you need to call the 
+CreateAction_NewWithAutomaticSelection<T>() method instead of the CreateAction_New().
+of the Core::UserItemCommonProperty class.
+
+3/ Adding the menu to the Gui
+You need to edit "Xml/MenuManager.xml" file. It contains the description of how the menu 
+appears on the top of the openmeca windows. If you don't specify here the location of the
+menu, it won't appear. If you edit this file, you must recompile openmeca and erase the 
+default user file located in the $HOME/openmeca directory. If openmeca does not find this 
+file, it pastes the default file in $HOME/openmeca.
+
+4/ Adding right-click pop-up menus (used to edit, remove, add an user item)
+In addition, you may want the popup menu appears when right clicking of some given 
+parent items. It's usefull to allow fast creation of item that required a parent 
+at construction. It can be done with UserItemCommonProperty<T>::CreateAction_Specialized()
+method. See for example the Item/PartUserPoint.cpp file as example. 
+You can see also the Item/Body.cpp file for example of root item management.
+This popup menu are generally created with the CreateAction_NewWithSelection() method of the 
+Core::UserItemCommonProperty class.
+
+
+-------------------------
+To Add a new type of Link
+-------------------------
+
+1/ Add it to the "OpenMeca/Item/Link/xxxx.hpp" && "OpenMeca/Item/Link/xxxx.cpp" file
+     - don't forget to specify the ChLink typedef !
+     - don't forget to specify the Dialog typedef !
+     - add the file to the "OpenMeca/Item/Link/Link.pro"
+     - add the header to the "OpenMeca/Item/Link/All.hpp"
+ 
+2/ Add the specialization in the "OpenMeca/Item/LinkT.cpp". Don't forget :
+     - BOOST_CLASS_EXPORT macro
+     - BuildChSystem() method if it needs specialization
+     - BuildIconSymbol() method
+
+4/ Add to the "OpenMeca/Gui/MainWindow.cpp" file the initialization :
+     - Item::LinkT<MyLink>::Init() static method
+     - Item::PartLinkT<MyLink,1>::Init() static method
+     - Item::PartLinkT<MyLink,2>::Init() static method
+
+5/ Add it to the menu interface inside the "OpenMeca/Xml/MenuManager.xml" like this :
+     <Menu Title="Slider">
+       <Class Type="Slider">
+	 <Action Id="New"/>
+	 <Action Id="Edit"/>
+	 <Action Id="Delete"/>
+       </Class>
+     </Menu>
+   don't forget to remove the default user config file with the command : "rm -rf ~/openmeca"
+
+6/ Add the required svg icons (with blue and red color )
+   -> don't forget to add the svg file to the Resources.qrc
+
+7/ Add BOOST_CLASS_EXPORT macro in "OpenMeca/Item/PartLinkT.cpp" file
+
+
+--------------------------------------------------
+To Add a new type of Link with additional features
+--------------------------------------------------
+1/ add the additional feature in the "OpenMeca/Item/LinkT.cpp" struct 
+2/ specify the dialog with the typedef inside the struct
+3/ implement the new dialog 
+(See the Motor link as example)
diff --git a/SRC/OpenMeca/OpenMeca.pro b/SRC/OpenMeca/OpenMeca.pro
new file mode 100644
index 0000000..81f3883
--- /dev/null
+++ b/SRC/OpenMeca/OpenMeca.pro
@@ -0,0 +1,83 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+TEMPLATE  = app
+TARGET    = ./BUILD/openmeca
+DESTDIR   = ./
+CONFIG   += qt silent
+
+
+QMAKE_CXXFLAGS += -Wno-unused-local-typedefs
+
+QT +=  help svg xml opengl sql
+
+TRANSLATIONS = ./Rsc/Lang/openmeca_fr.ts
+
+MOC_DIR     = ./BUILD/moc
+UI_DIR      = ./BUILD/ui
+OBJECTS_DIR = ./BUILD/obj
+RCC_DIR     = ./BUILD/rcc
+
+
+DEPENDPATH += ../../
+ 
+INCLUDEPATH = ./ ../../ ../ \
+              ./BUILD/ui \
+              ../ChronoEngine/ \
+              ../ChronoEngine/collision/bullet \
+              ../ChronoEngine/collision/gimpact \
+              ../QGLViewer/BUILD/include
+
+LIBS      +=  ../ChronoEngine/BUILD/libchronoengine.a \
+              ../Serialization/BUILD/libserialization.a \
+              -lqwt-qt5 -lQGLViewer
+
+CONFIG += c++11
+              
+win32 {
+LIBS   += -lglu32
+CONFIG += release
+}
+
+unix:!macx {
+LIBS   += -lGL -lGLU
+CONFIG += release
+}
+
+macx {
+       QMAKE_CXXFLAGS += -DOSX
+       QMAKE_CXXFLAGS += -ftemplate-depth=1024
+               CONFIG += release
+                 ICON  = ./Rsc/Img/OpenMeca.icns
+             TARGET    = ./BUILD/OpenMeca
+
+}
+
+RESOURCES += ./Resources.qrc
+SOURCES += Main.cpp
+
+include(./Core/Core.pro)
+include(./Physic/Physic.pro)
+include(./Util/Util.pro)
+include(./Geom/Geom.pro)
+include(./Gui/Gui.pro)
+include(./Item/Item.pro)
+include(./Setting/Setting.pro)
diff --git a/SRC/OpenMeca/Physic/AngularAcceleration.cpp b/SRC/OpenMeca/Physic/AngularAcceleration.cpp
new file mode 100644
index 0000000..9cce70d
--- /dev/null
+++ b/SRC/OpenMeca/Physic/AngularAcceleration.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/AngularAcceleration.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::AngularAcceleration)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const Util::Color AngularAcceleration::color = Util::Color::Green;
+    
+    const std::string
+    AngularAcceleration::GetStrType()
+    {
+      return "AngularAcceleration";
+    }
+
+    const QString
+    AngularAcceleration::GetQStrType()
+    {
+      return QObject::tr("AngularAcceleration");
+    }
+      
+
+    AngularAcceleration::AngularAcceleration(Item::Physical& item)
+      :QuantityT<Vector3D>(item, color),
+       unit_(Util::Dimension::Get("AngularAcceleration").GetUnit("RadianPerSecondSquared"))
+    {
+      
+    }
+   
+    AngularAcceleration::~AngularAcceleration()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    AngularAcceleration::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    AngularAcceleration::GetScale() const
+    {
+      return Core::System::Get().GetScales().GetScaleValue(AngularAcceleration::GetStrType());
+    }
+
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/AngularAcceleration.hpp b/SRC/OpenMeca/Physic/AngularAcceleration.hpp
new file mode 100644
index 0000000..dc1242c
--- /dev/null
+++ b/SRC/OpenMeca/Physic/AngularAcceleration.hpp
@@ -0,0 +1,94 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_AngularAcceleration_hpp
+#define OpenMeca_Physic_AngularAcceleration_hpp
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    
+    class AngularAcceleration : public QuantityT<Vector3D>
+    {
+    public:  
+      static const Util::Color color;
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:
+      AngularAcceleration(Item::Physical& item);
+      ~AngularAcceleration();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    template<class Archive>
+    inline void
+    AngularAcceleration::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(QuantityT<Vector3D>);
+    }
+ 
+  }
+}
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::AngularAcceleration * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::AngularAcceleration * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::AngularAcceleration(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/AngularPosition.cpp b/SRC/OpenMeca/Physic/AngularPosition.cpp
new file mode 100644
index 0000000..dfaafaa
--- /dev/null
+++ b/SRC/OpenMeca/Physic/AngularPosition.cpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/AngularPosition.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::AngularPosition)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const Util::Color AngularPosition::color = Util::Color::Green;
+    
+    const std::string
+    AngularPosition::GetStrType()
+    {
+      return "AngularPosition";
+    }
+
+    const QString
+    AngularPosition::GetQStrType()
+    {
+      return QObject::tr("AngularPosition");
+    }
+      
+
+    AngularPosition::AngularPosition(Item::Physical& item)
+      :QuantityT<Double>(item, color),
+       unit_(Util::Dimension::Get("Angle").GetUnit("Radian"))
+    {
+      
+    }
+   
+    AngularPosition::~AngularPosition()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    AngularPosition::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    AngularPosition::GetScale() const
+    {
+      OMC_ASSERT_MSG(0, "Can't call this method");
+      return Core::System::Get().GetScales().GetScaleValue(AngularPosition::GetStrType());
+    }
+
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/AngularPosition.hpp b/SRC/OpenMeca/Physic/AngularPosition.hpp
new file mode 100644
index 0000000..8f58fd2
--- /dev/null
+++ b/SRC/OpenMeca/Physic/AngularPosition.hpp
@@ -0,0 +1,94 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_AngularPosition_hpp
+#define OpenMeca_Physic_AngularPosition_hpp
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Double.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    
+    class AngularPosition : public QuantityT<Double>
+    {
+    public:  
+      static const Util::Color color;
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:
+      AngularPosition(Item::Physical& item);
+      ~AngularPosition();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    template<class Archive>
+    inline void
+    AngularPosition::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(QuantityT<Double>);
+    }
+ 
+  }
+}
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::AngularPosition * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::AngularPosition * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::AngularPosition(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/AngularVelocity.cpp b/SRC/OpenMeca/Physic/AngularVelocity.cpp
new file mode 100644
index 0000000..2dd1b81
--- /dev/null
+++ b/SRC/OpenMeca/Physic/AngularVelocity.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/AngularVelocity.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::AngularVelocity)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const Util::Color AngularVelocity::color = Util::Color::Green;
+    
+    const std::string
+    AngularVelocity::GetStrType()
+    {
+      return "AngularVelocity";
+    }
+
+    const QString
+    AngularVelocity::GetQStrType()
+    {
+      return QObject::tr("AngularVelocity");
+    }
+      
+
+    AngularVelocity::AngularVelocity(Item::Physical& item)
+      :QuantityT<Vector3D>(item, color),
+       unit_(Util::Dimension::Get("AngularVelocity").GetUnit("RadianPerSecond"))
+    {
+      
+    }
+   
+    AngularVelocity::~AngularVelocity()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    AngularVelocity::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    AngularVelocity::GetScale() const
+    {
+      return Core::System::Get().GetScales().GetScaleValue(AngularVelocity::GetStrType());
+    }
+
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/AngularVelocity.hpp b/SRC/OpenMeca/Physic/AngularVelocity.hpp
new file mode 100644
index 0000000..32c7b67
--- /dev/null
+++ b/SRC/OpenMeca/Physic/AngularVelocity.hpp
@@ -0,0 +1,94 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_AngularVelocity_hpp
+#define OpenMeca_Physic_AngularVelocity_hpp
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    
+    class AngularVelocity : public QuantityT<Vector3D>
+    {
+    public:  
+      static const Util::Color color;
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:
+      AngularVelocity(Item::Physical& item);
+      ~AngularVelocity();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    template<class Archive>
+    inline void
+    AngularVelocity::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(QuantityT<Vector3D>);
+    }
+ 
+  }
+}
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::AngularVelocity * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::AngularVelocity * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::AngularVelocity(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/Double.cpp b/SRC/OpenMeca/Physic/Double.cpp
new file mode 100644
index 0000000..bcd0811
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Double.cpp
@@ -0,0 +1,128 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <functional>
+
+#include "OpenMeca/Physic/Double.hpp"
+#include "OpenMeca/Gui/MainPlotWindow.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::Double)
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    Double::Double(Quantity& q)
+      :TypeT<double>(q),
+       val_(0.), 
+       storedVal_()
+    {
+    }
+
+    Double::~Double()
+    {
+    }
+
+    double& 
+    Double::GetRealType()
+    {
+      return val_;
+    }
+    
+    const double& 
+    Double::GetRealType() const
+    {
+      return val_;
+    }
+    
+    void
+    Double::SaveState()
+    {
+      Update(val_);
+    }
+
+    void
+    Double::Update()
+    {
+      storedVal_.push_back(0.);
+    }
+
+
+    void
+    Double::Update(const double& v)
+    {
+      val_ = v;
+      storedVal_.push_back(v);
+    }
+
+    void
+    Double::ResetState()
+    {
+      storedVal_.clear();
+    }
+
+    void
+    Double::RecoveryState(unsigned int i)
+    {
+      val_ = storedVal_[i];
+    }
+
+    void 
+    Double::FillDataMenu(QMenu* menu)
+    {
+      QAction* Val = menu->addAction(Gui::MainPlotWindow::tr("Value"));
+      QObject::connect(Val, SIGNAL(triggered()), this, SLOT(Val()));
+    }
+
+    void 
+    Double::Val()
+    {
+      std::string label = GetLabel();
+      Gui::MainPlotWindow::Get().AddData(storedVal_, label.c_str(), GetUnit(), *this);
+    }
+
+   
+    void 
+    Double::WriteHeaderDataFile(std::ofstream& file)
+    {
+      file << GetLabel() << "(" <<  GetUnit().GetSymbol() << ")";
+    }
+
+    void 
+    Double::WriteDataFile(std::ofstream& file, unsigned int iter)
+    {
+      OMC_ASSERT_MSG(iter < storedVal_.size(), "The data are not coherent");
+      file << storedVal_[iter];
+    }
+
+    void 
+    Double::Draw() const
+    {
+      //Nothing
+    }
+
+
+  
+
+  }
+} 
+
diff --git a/SRC/OpenMeca/Physic/Double.hpp b/SRC/OpenMeca/Physic/Double.hpp
new file mode 100644
index 0000000..b5b3398
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Double.hpp
@@ -0,0 +1,115 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Physic_Double_hpp_
+#define _OpenMeca_Physic_Double_hpp_
+
+#include <QObject>
+#include <QMenu>
+#include "OpenMeca/Physic/TypeT.hpp"
+#include "OpenMeca/Physic/Quantity.hpp"
+#include "OpenMeca/Geom/Vector.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    class Double : public QObject, public TypeT <double >
+    {
+      Q_OBJECT
+      
+    public:
+      Double(Quantity&);
+      ~Double();
+
+      void Update(const double&);
+      void Update();
+
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+      double& GetRealType();
+      const double& GetRealType() const;
+			       
+      void FillDataMenu(QMenu* menu);
+      void WriteHeaderDataFile(std::ofstream&);
+      void WriteDataFile(std::ofstream&, unsigned int);	
+
+      void Draw() const;
+
+						      
+    private slots:
+      void Val();
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+    
+    private:
+      double val_;
+      std::vector<double> storedVal_;
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Double::serialize(Archive & ar, const unsigned int)
+    {
+	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(TypeT<double>);
+	ar & BOOST_SERIALIZATION_NVP(val_);
+    }
+
+  }
+} 
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::Double * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Physic::Quantity* parent = &t->GetQuantity();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::Double * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Physic::Quantity* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::Double(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/Enum.hpp b/SRC/OpenMeca/Physic/Enum.hpp
new file mode 100644
index 0000000..8989206
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Enum.hpp
@@ -0,0 +1,43 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_Enum_hpp
+#define OpenMeca_Physic_Enum_hpp
+
+
+namespace OpenMeca
+{
+
+  namespace Physic
+  {    
+
+    class ForceEnum
+    {
+    public:
+      enum DirectionMode {ABSOLUTE_DIR = FDIR_WORLD, BODY_COORDINATE_DIR=FDIR_BODY};
+      enum StartPointMode{ABSOLUTE_POS = FPOS_WORLD, BODY_COORDINATE_POS=FPOS_BODY};
+    }; 
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/Force.cpp b/SRC/OpenMeca/Physic/Force.cpp
new file mode 100644
index 0000000..aadb292
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Force.cpp
@@ -0,0 +1,79 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/Force.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::Force)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const std::string
+    Force::GetStrType()
+    {
+      return "Force";
+    }
+
+    const QString
+    Force::GetQStrType()
+    {
+      return QObject::tr("Force");
+    }
+      
+
+    Force::Force(Item::Physical& item)
+      :MechanicalAction(item, Util::Color::Red),
+       unit_(Util::Dimension::Get("Force").GetUnit("Newton"))
+    {
+    }
+   
+    Force::~Force()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    Force::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    Force::GetScale() const
+    {
+      return Core::System::Get().GetScales().GetScaleValue(Force::GetStrType());
+    }
+
+
+    void 
+    Force::CompleteChForce(chrono::ChSharedForcePtr& chForce)
+    {
+      chForce->SetMode(FTYPE_FORCE);
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/Force.hpp b/SRC/OpenMeca/Physic/Force.hpp
new file mode 100644
index 0000000..879e2ff
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Force.hpp
@@ -0,0 +1,100 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_Force_hpp
+#define OpenMeca_Physic_Force_hpp
+
+#include "OpenMeca/Physic/MechanicalAction.hpp"
+#include "OpenMeca/Gui/Dialog/Physic/DialogForce.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+    
+    class Force : public MechanicalAction
+    {
+    public:  
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+      typedef OpenMeca::Gui::Physic::DialogForce GuiManager;
+
+    public:
+      Force(Item::Physical& item);
+      ~Force();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+
+    protected:
+      void CompleteChForce(chrono::ChSharedForcePtr&);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+      
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    
+    template<class Archive>
+    inline void
+    Force::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(MechanicalAction);
+    }
+
+
+ 
+  }
+}
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::Force * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::Force * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::Force(*parent);
+    }
+  }
+} // namespace ...
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/LinearAcceleration.cpp b/SRC/OpenMeca/Physic/LinearAcceleration.cpp
new file mode 100644
index 0000000..ae9ce1d
--- /dev/null
+++ b/SRC/OpenMeca/Physic/LinearAcceleration.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/LinearAcceleration.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::LinearAcceleration)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const Util::Color LinearAcceleration::color = Util::Color::Green;
+    
+    const std::string
+    LinearAcceleration::GetStrType()
+    {
+      return "LinearAcceleration";
+    }
+
+    const QString
+    LinearAcceleration::GetQStrType()
+    {
+      return QObject::tr("LinearAcceleration");
+    }
+      
+
+    LinearAcceleration::LinearAcceleration(Item::Physical& item)
+      :QuantityT<Vector3D>(item, color),
+       unit_(Util::Dimension::Get("LinearAcceleration").GetUnit("MeterPerSecondSquared"))
+    {
+      
+    }
+   
+    LinearAcceleration::~LinearAcceleration()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    LinearAcceleration::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    LinearAcceleration::GetScale() const
+    {
+      return Core::System::Get().GetScales().GetScaleValue(LinearAcceleration::GetStrType());
+    }
+
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/LinearAcceleration.hpp b/SRC/OpenMeca/Physic/LinearAcceleration.hpp
new file mode 100644
index 0000000..873445b
--- /dev/null
+++ b/SRC/OpenMeca/Physic/LinearAcceleration.hpp
@@ -0,0 +1,94 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_LinearAcceleration_hpp
+#define OpenMeca_Physic_LinearAcceleration_hpp
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    
+    class LinearAcceleration : public QuantityT<Vector3D>
+    {
+    public:  
+      static const Util::Color color;
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:
+      LinearAcceleration(Item::Physical& item);
+      ~LinearAcceleration();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    template<class Archive>
+    inline void
+    LinearAcceleration::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(QuantityT<Vector3D>);
+    }
+ 
+  }
+}
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::LinearAcceleration * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::LinearAcceleration * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::LinearAcceleration(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/LinearPosition.cpp b/SRC/OpenMeca/Physic/LinearPosition.cpp
new file mode 100644
index 0000000..db8a819
--- /dev/null
+++ b/SRC/OpenMeca/Physic/LinearPosition.cpp
@@ -0,0 +1,100 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/LinearPosition.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::LinearPosition)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const Util::Color LinearPosition::color = Util::Color::Blue;
+    
+    const std::string
+    LinearPosition::GetStrType()
+    {
+      return "LinearPosition";
+    }
+
+    const QString
+    LinearPosition::GetQStrType()
+    {
+      return QObject::tr("LinearPosition");
+    }
+      
+
+    LinearPosition::LinearPosition(Item::Physical& item)
+      :QuantityT<Vector3D>(item, color),
+       unit_(Util::Dimension::Get("Length").GetUnit("Meter"))
+    {
+      
+    }
+   
+    LinearPosition::~LinearPosition()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    LinearPosition::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    LinearPosition::GetScale() const
+    {
+      return Core::System::Get().GetScales().GetScaleValue(LinearPosition::GetStrType());
+    }
+
+    void
+    LinearPosition::BeginDraw()
+    {
+      const std::vector< std::array<double, 3> >& array = 
+	GetRealDataType().GetRealType().GetRecordedState();
+	
+	if (array.size() > 2)
+	  {
+	    glDisable(GL_LIGHTING);
+	    glLineWidth(1);
+	    glColor4f(1.0, 1.0, 1.0, 1.0);
+	    glBegin(GL_LINE_STRIP);
+	    for (unsigned int i = 0; i < array.size(); ++i)
+	      glVertex3f(array[i][0], array[i][1], array[i][2]);
+
+	    glEnd();
+	    glEnable(GL_LIGHTING);
+	  }
+    }
+
+    void
+    LinearPosition::Draw()
+    {
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/LinearPosition.hpp b/SRC/OpenMeca/Physic/LinearPosition.hpp
new file mode 100644
index 0000000..997623a
--- /dev/null
+++ b/SRC/OpenMeca/Physic/LinearPosition.hpp
@@ -0,0 +1,97 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_LinearPosition_hpp
+#define OpenMeca_Physic_LinearPosition_hpp
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    
+    class LinearPosition : public QuantityT<Vector3D>
+    {
+    public:  
+      static const Util::Color color;
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:
+      LinearPosition(Item::Physical& item);
+      ~LinearPosition();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+      
+      void BeginDraw();
+      void Draw();
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    template<class Archive>
+    inline void
+    LinearPosition::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(QuantityT<Vector3D>);
+    }
+ 
+  }
+}
+
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::LinearPosition * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::LinearPosition * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::LinearPosition(*parent);
+    }
+  }
+} // namespace ...
+
+#endif
diff --git a/SRC/OpenMeca/Physic/LinearVelocity.cpp b/SRC/OpenMeca/Physic/LinearVelocity.cpp
new file mode 100644
index 0000000..9353226
--- /dev/null
+++ b/SRC/OpenMeca/Physic/LinearVelocity.cpp
@@ -0,0 +1,77 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/LinearVelocity.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::LinearVelocity)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const Util::Color LinearVelocity::color = Util::Color::Green;
+    
+    const std::string
+    LinearVelocity::GetStrType()
+    {
+      return "LinearVelocity";
+    }
+
+    const QString
+    LinearVelocity::GetQStrType()
+    {
+      return QObject::tr("LinearVelocity");
+    }
+      
+
+    LinearVelocity::LinearVelocity(Item::Physical& item)
+      :QuantityT<Vector3D>(item, color),
+       unit_(Util::Dimension::Get("LinearVelocity").GetUnit("MeterPerSecond"))
+    {
+      
+    }
+   
+    LinearVelocity::~LinearVelocity()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    LinearVelocity::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    LinearVelocity::GetScale() const
+    {
+      return Core::System::Get().GetScales().GetScaleValue(LinearVelocity::GetStrType());
+    }
+
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/LinearVelocity.hpp b/SRC/OpenMeca/Physic/LinearVelocity.hpp
new file mode 100644
index 0000000..640a706
--- /dev/null
+++ b/SRC/OpenMeca/Physic/LinearVelocity.hpp
@@ -0,0 +1,94 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_LinearVelocity_hpp
+#define OpenMeca_Physic_LinearVelocity_hpp
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    
+    class LinearVelocity : public QuantityT<Vector3D>
+    {
+    public:  
+      static const Util::Color color;
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:
+      LinearVelocity(Item::Physical& item);
+      ~LinearVelocity();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    template<class Archive>
+    inline void
+    LinearVelocity::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(QuantityT<Vector3D>);
+    }
+ 
+  }
+}
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::LinearVelocity * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::LinearVelocity * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::LinearVelocity(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/MechanicalAction.cpp b/SRC/OpenMeca/Physic/MechanicalAction.cpp
new file mode 100644
index 0000000..06e317a
--- /dev/null
+++ b/SRC/OpenMeca/Physic/MechanicalAction.cpp
@@ -0,0 +1,198 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/MechanicalAction.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Item/Link.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::MechanicalAction)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const std::string
+    MechanicalAction::GetStrType()
+    {
+      return "MechanicalAction";
+    }
+
+    const QString
+    MechanicalAction::GetQStrType()
+    {
+      return QObject::tr("MechanicalAction");
+    }
+      
+
+    MechanicalAction::MechanicalAction(Item::Physical& item, const Util::Color& color)
+      :QuantityT<Vector3D>(item, color),
+       value_(std::bind(&MechanicalAction::GetFrame, std::ref(*this))),
+       chForcePtr_(0),
+       directionMode_(MechActionEnum::ABSOLUTE_DIR),
+       startPointMode_(MechActionEnum::BODY_COORDINATE_POS)
+    {
+      
+    }
+    
+    MechanicalAction::~MechanicalAction()
+    {
+
+    }
+    
+    
+    Geom::Vector<_3D>& 
+    MechanicalAction::GetValue()
+    {
+      return value_; 
+    }
+    
+    const Geom::Vector<_3D>& 
+    MechanicalAction::GetValue() const
+    {
+      return value_;
+    }
+    
+
+    Geom::Point<_3D>
+    MechanicalAction::GetStartPoint()
+    {
+      const Geom::Point<_3D>& p = GetPhysicalItem().GetFrame().GetCenter();
+      Item::Body& body = GetBody();
+      Geom::Frame<_3D>&(Item::Body::*fnpt)() = &Item::Body::GetFrame;
+      std::function<const Geom::Frame<_3D>& ()> f_body = std::bind(fnpt, std::ref(body));
+      return Geom::Point<_3D> (p, f_body);
+    }
+
+
+    MechActionEnum::DirectionMode& 
+    MechanicalAction::GetDirectionMode()
+    {
+      return directionMode_;
+    }
+    
+
+    const MechActionEnum::DirectionMode& 
+    MechanicalAction::GetDirectionMode() const
+    {
+      return directionMode_;
+    }
+
+    const Geom::Frame<_3D>& 
+    MechanicalAction::GetFrame() const
+    {
+      if (directionMode_ == MechActionEnum::BODY_COORDINATE_DIR)
+	return GetBody().GetFrame();
+      
+      return Geom::Frame<_3D>::Global;	  
+    }
+
+    Item::Body& 
+    MechanicalAction::GetBody()
+    {
+      return GetPhysicalItem().GetBody();
+    }
+
+    const Item::Body& 
+    MechanicalAction::GetBody() const
+    {
+      return GetPhysicalItem().GetBody();
+    }
+
+
+    void 
+    MechanicalAction::Apply()
+    {
+      Geom::Vector<_3D> v = value_;
+      
+      chForcePtr_ = chrono::ChSharedForcePtr(new chrono::ChForce);
+      GetBody().GetChBodyPtr()->AddForce(chForcePtr_);
+      
+      Geom::Point<_3D> p(GetStartPoint(), &Geom::Frame<_3D>::GetGlobal);
+      chForcePtr_->SetVpoint(p.ToChVector());
+      chForcePtr_->SetFrame(startPointMode_);
+
+      chForcePtr_->SetMforce(value_.GetNorm());
+      chForcePtr_->SetAlign(directionMode_);
+
+      if (directionMode_ == MechActionEnum::BODY_COORDINATE_DIR)
+	chForcePtr_->SetRelDir(value_.Unit().ToChVector());
+      else
+      chForcePtr_->SetDir(value_.Unit().ToChVector());
+
+      CompleteChForce(chForcePtr_);
+
+      GetRealDataType().GetRealType().ResetState();
+      GetRealDataType().GetRealType() = value_;
+    }
+    
+    void 
+    MechanicalAction::Draw()
+    {
+      
+    }
+
+    void 
+    MechanicalAction::BeginDraw()
+    {
+      if (GetPhysicalItem().IsLoad())
+	{
+	  GetColor().ApplyGLColor();
+	  const Geom::Point<_3D> p(GetPhysicalItem().GetFrame().GetCenter(), &Geom::Frame<_3D>::GetGlobal);
+	  const Geom::Vector<_3D> v(value_, &Geom::Frame<_3D>::GetGlobal);
+	  glTranslated(p[0], p[1], p[2]);
+	  v.Draw(GetScale());
+	  glTranslated(-p[0], -p[1], -p[2]);  
+	  return;
+	}
+	  
+      if (GetPhysicalItem().IsSensor())
+	{
+	  Core::UserItem& item = GetPhysicalItem().GetParent();
+
+	  Item::Link* link = 0;
+	  link = dynamic_cast<Item::Link*>(&item);
+	  OMC_ASSERT_MSG(link != 0,
+			 "If the mechanical load come form a sensor the parent must be a link");
+
+	  Item::Body& body = link->GetBody1();
+
+	  Geom::Frame<_3D>&(Item::Body::*fnptr)() = &Item::Body::GetFrame;
+	  std::function<const Geom::Frame<_3D>& ()> f = 
+	  std::bind(fnptr, std::ref(body));
+	  
+
+	  const Geom::Point<_3D>& p_link  = GetPhysicalItem().GetFrame().GetCenter();
+	  const Geom::Point<_3D> p_loc(p_link[0], p_link[1], p_link[2], f);
+          const Geom::Point<_3D> p(p_loc, Geom::Frame<_3D>::GetGlobal);
+	  glTranslatef(p[0], p[1], p[2]);
+	  data_.Draw();
+          glTranslatef(-p[0], -p[1], -p[2]);
+	}
+      
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/MechanicalAction.hpp b/SRC/OpenMeca/Physic/MechanicalAction.hpp
new file mode 100644
index 0000000..ac584dc
--- /dev/null
+++ b/SRC/OpenMeca/Physic/MechanicalAction.hpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_MechanicalAction_hpp
+#define OpenMeca_Physic_MechanicalAction_hpp
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+#include "OpenMeca/Geom/Point.hpp"
+
+#include "OpenMeca/Item/Physical.hpp"
+#include "OpenMeca/Item/Body.hpp"
+#include "OpenMeca/Physic/PhysEnum.hpp"
+
+#include "OpenMeca/Gui/Dialog/Physic/DialogMechanicalAction.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+    
+    class MechanicalAction : public QuantityT<Vector3D>
+    {
+    public:  
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+      typedef OpenMeca::Gui::Physic::DialogMechanicalAction GuiManager;
+
+    public:
+      MechanicalAction(Item::Physical& item, const Util::Color& color);
+      ~MechanicalAction();
+
+      virtual void Apply();
+      
+      Geom::Vector<_3D>& GetValue();
+      const Geom::Vector<_3D>& GetValue() const;
+
+      MechActionEnum::DirectionMode& GetDirectionMode();
+      const MechActionEnum::DirectionMode& GetDirectionMode() const;
+
+      virtual void Draw();
+      virtual void BeginDraw();
+
+    protected:
+      virtual void CompleteChForce(chrono::ChSharedForcePtr&) = 0;
+      const Geom::Frame<_3D>& GetFrame() const;
+      Geom::Point<_3D> GetStartPoint();
+      Item::Body& GetBody();
+      const Item::Body& GetBody() const;
+
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+      
+    private:
+      Geom::Vector<_3D> value_;
+      chrono::ChSharedForcePtr chForcePtr_;
+      MechActionEnum::DirectionMode directionMode_;
+      const MechActionEnum::StartPointMode startPointMode_;
+    }; 
+
+    
+    template<class Archive>
+    inline void
+    MechanicalAction::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(QuantityT<Vector3D>);
+      ar & BOOST_SERIALIZATION_NVP(value_);
+      ar & BOOST_SERIALIZATION_NVP(directionMode_);
+    }
+
+
+ 
+  }
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/PhysEnum.hpp b/SRC/OpenMeca/Physic/PhysEnum.hpp
new file mode 100644
index 0000000..4d66703
--- /dev/null
+++ b/SRC/OpenMeca/Physic/PhysEnum.hpp
@@ -0,0 +1,42 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_PhysEnum_hpp
+#define OpenMeca_Physic_PhysEnum_hpp
+
+
+namespace OpenMeca
+{
+  namespace Physic
+  {    
+
+    class MechActionEnum
+    {
+    public:
+      enum DirectionMode {ABSOLUTE_DIR = FDIR_WORLD, BODY_COORDINATE_DIR=FDIR_BODY};
+      enum StartPointMode{ABSOLUTE_POS = FPOS_WORLD, BODY_COORDINATE_POS=FPOS_BODY};
+    }; 
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/Physic.pro b/SRC/OpenMeca/Physic/Physic.pro
new file mode 100644
index 0000000..a9ac5f0
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Physic.pro
@@ -0,0 +1,54 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Physic/PhysEnum.hpp \
+           Physic/Type.hpp \
+           Physic/TypeT.hpp \
+           Physic/Vector3D.hpp \
+           Physic/Double.hpp \
+           Physic/Quantity.hpp \
+           Physic/QuantityT.hpp \
+           Physic/LinearPosition.hpp \
+           Physic/LinearVelocity.hpp \
+           Physic/LinearAcceleration.hpp \
+           Physic/AngularPosition.hpp \
+           Physic/AngularVelocity.hpp \
+           Physic/AngularAcceleration.hpp \
+           Physic/MechanicalAction.hpp \
+           Physic/Force.hpp \
+           Physic/Torque.hpp
+
+
+SOURCES += Physic/Type.cpp \
+           Physic/TypeT.cpp \
+           Physic/Vector3D.cpp \
+           Physic/Double.cpp \
+           Physic/Quantity.cpp \
+           Physic/QuantityT.cpp \
+           Physic/LinearPosition.cpp \
+           Physic/LinearVelocity.cpp \
+           Physic/LinearAcceleration.cpp \
+           Physic/AngularPosition.cpp \
+           Physic/AngularVelocity.cpp \
+           Physic/AngularAcceleration.cpp \
+           Physic/MechanicalAction.cpp \
+           Physic/Force.cpp \
+           Physic/Torque.cpp
+
diff --git a/SRC/OpenMeca/Physic/Quantity.cpp b/SRC/OpenMeca/Physic/Quantity.cpp
new file mode 100644
index 0000000..7dcfbd8
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Quantity.cpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/Quantity.hpp"
+#include "OpenMeca/Physic/Type.hpp"
+#include "OpenMeca/Item/Physical.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::Quantity)
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    Quantity::Quantity(Item::Physical& item, const Util::Color& color)
+      :item_(item),
+       color_(color)
+    {
+    }
+    
+    Quantity::~Quantity()
+    {
+    }
+    
+    void
+    Quantity::Draw()
+    {
+      GetDataType().Draw();
+    }
+
+    void
+    Quantity::BeginDraw()
+    {
+    }
+
+    void
+    Quantity::EndDraw()
+    {
+    }
+
+    const Geom::Frame<_3D>& 
+    Quantity::GetFrame() const
+    {
+      return Geom::Frame<_3D>::Global;
+    }
+
+    const std::string& 
+    Quantity::GetLabel()
+    {
+      return item_.GetName();
+    }
+
+    const Util::Color& 
+    Quantity::GetColor() const
+    {
+      return color_;
+    }
+      
+    Util::Color& 
+    Quantity::GetColor()
+    {
+      return color_;
+    }
+      
+    const Item::Physical& 
+    Quantity::GetPhysicalItem() const
+    {
+      return item_;
+    }
+
+    Item::Physical& 
+    Quantity::GetPhysicalItem()
+    {
+      return item_;
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/Quantity.hpp b/SRC/OpenMeca/Physic/Quantity.hpp
new file mode 100644
index 0000000..a9d7431
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Quantity.hpp
@@ -0,0 +1,86 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_Quantity_hpp
+#define OpenMeca_Physic_Quantity_hpp
+
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+namespace OpenMeca
+{
+
+  namespace Item
+  {
+    class Physical;
+  }
+
+  namespace Physic
+  {    
+
+    class Type;
+
+    class Quantity
+    {
+    public:
+      Quantity(Item::Physical&, const Util::Color& color);
+      virtual ~Quantity();	
+      
+      const std::string& GetLabel();
+      
+      virtual void Draw();
+      virtual void BeginDraw();
+      virtual void EndDraw();
+      virtual const Geom::Frame<_3D>& GetFrame() const;
+      virtual const Util::Unit& GetUnit() const = 0;
+      virtual double GetScale() const = 0;
+      virtual Type& GetDataType() = 0;
+      virtual const Type& GetDataType() const = 0;
+
+      const Util::Color& GetColor() const;
+      Util::Color& GetColor();
+
+      const Item::Physical& GetPhysicalItem() const;
+      Item::Physical& GetPhysicalItem();
+
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      Item::Physical& item_;
+      Util::Color color_;
+    }; 
+
+    template<class Archive>
+    inline void
+    Quantity::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(item_);
+      ar & BOOST_SERIALIZATION_NVP(color_);
+    }
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/QuantityT.cpp b/SRC/OpenMeca/Physic/QuantityT.cpp
new file mode 100644
index 0000000..6508274
--- /dev/null
+++ b/SRC/OpenMeca/Physic/QuantityT.cpp
@@ -0,0 +1,74 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Physic/QuantityT.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+
+#include "OpenMeca/Item/Physical.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::QuantityT<OpenMeca::Physic::Vector3D>)
+
+
+namespace OpenMeca
+{
+  namespace Physic
+  {    
+
+    template<>
+    void 
+    QuantityT<Vector3D>::Draw()
+    {
+      if (data_.GetRealType().GetFrame() == GetPhysicalItem().GetFrame())
+	data_.Draw();
+      else
+	OMC_ASSERT_MSG(data_.GetRealType().GetFrame() == Geom::Frame<_3D>::Global,
+		       "The vector must be expression in global frame");
+    }
+
+    template<>
+    void 
+    QuantityT<Vector3D>::BeginDraw()
+    {
+      // if the vector is expressed in the global frame use begin draw
+      if (data_.GetRealType().GetFrame() == Geom::Frame<_3D>::Global)
+	{
+	  const Geom::Point<_3D>& p_loc  = GetPhysicalItem().GetFrame().GetCenter();
+          const Geom::Point<_3D> p(p_loc, Geom::Frame<_3D>::GetGlobal);
+	  glTranslatef(p[0], p[1], p[2]);
+	  data_.Draw();
+          glTranslatef(-p[0], -p[1], -p[2]);
+	}
+    }
+
+    template<>
+    void 
+    QuantityT<Vector3D>::EndDraw()
+    {
+      Quantity::EndDraw();
+    }
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Physic/QuantityT.hpp b/SRC/OpenMeca/Physic/QuantityT.hpp
new file mode 100644
index 0000000..8e3649d
--- /dev/null
+++ b/SRC/OpenMeca/Physic/QuantityT.hpp
@@ -0,0 +1,146 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_QuantityT_hpp
+#define OpenMeca_Physic_QuantityT_hpp
+
+#include "OpenMeca/Physic/Quantity.hpp"
+#include "OpenMeca/Physic/Vector3D.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {    
+
+    template<class T>
+    class QuantityT : public Quantity
+    {
+    public:
+      QuantityT(Item::Physical&, const Util::Color& color);
+      virtual ~QuantityT();	
+
+      Type& GetDataType();
+      const Type& GetDataType() const;
+
+      T& GetRealDataType();
+      const T& GetRealDataType() const;
+
+      virtual void Draw();
+      virtual void BeginDraw();
+      virtual void EndDraw();
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    protected:
+      T data_;     
+
+    }; 
+
+    template<class T>
+    template<class Archive>
+    inline void
+    QuantityT<T>::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Quantity);
+      ar & BOOST_SERIALIZATION_NVP(data_);
+    }
+
+    template<class T>
+    inline 
+    QuantityT<T>::QuantityT(Item::Physical& item, const Util::Color& color)
+      :Quantity(item, color), data_(*this)
+    {
+    }
+
+    template<class T>
+    inline 
+    QuantityT<T>::~QuantityT()
+    {
+    }
+
+    template<class T>
+    inline Type&
+    QuantityT<T>::GetDataType()
+    {
+      return data_;
+    }
+
+    template<class T>
+    inline const Type&
+    QuantityT<T>::GetDataType() const
+    {
+      return data_;
+    }
+
+    template<class T>
+    inline T&
+    QuantityT<T>::GetRealDataType()
+    {
+      return data_;
+    }
+
+    template<class T>
+    inline const T&
+    QuantityT<T>::GetRealDataType() const
+    {
+      return data_;
+    }
+
+    template<class T>
+    inline void 
+    QuantityT<T>::Draw()
+    {
+      Quantity::Draw();
+    }
+
+    template<class T>
+    inline void 
+    QuantityT<T>::BeginDraw()
+    {
+      Quantity::BeginDraw();
+    }
+
+    template<class T>
+    inline void 
+    QuantityT<T>::EndDraw()
+    {
+      Quantity::EndDraw();
+    }
+
+    
+
+
+
+
+
+    template<> void QuantityT<Vector3D>::Draw();
+    template<> void QuantityT<Vector3D>::BeginDraw();
+    template<> void QuantityT<Vector3D>::EndDraw();
+
+
+
+
+  }
+}
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/Torque.cpp b/SRC/OpenMeca/Physic/Torque.cpp
new file mode 100644
index 0000000..483e5e4
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Torque.cpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QWidget>
+
+#include "OpenMeca/Physic/Torque.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::Torque)
+
+namespace OpenMeca
+{  
+  namespace Physic
+  {
+
+    const std::string
+    Torque::GetStrType()
+    {
+      return "Torque";
+    }
+
+    const QString
+    Torque::GetQStrType()
+    {
+      return QObject::tr("Torque");
+    }
+      
+
+    Torque::Torque(Item::Physical& item)
+      :MechanicalAction(item, Util::Color::Red),
+       unit_(Util::Dimension::Get("Torque").GetUnit("NewtonPerMeter"))
+    {
+    }
+   
+    Torque::~Torque()
+    {
+    }
+
+ 
+    const Util::Unit& 
+    Torque::GetUnit() const
+    {
+      return unit_;
+    }
+    
+    double
+    Torque::GetScale() const
+    {
+      return Core::System::Get().GetScales().GetScaleValue(Torque::GetStrType());
+    }
+
+    void
+    Torque::CompleteChForce(chrono::ChSharedForcePtr& chTorque)
+    {
+      chTorque->SetMode(FTYPE_TORQUE);
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Physic/Torque.hpp b/SRC/OpenMeca/Physic/Torque.hpp
new file mode 100644
index 0000000..e339fe3
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Torque.hpp
@@ -0,0 +1,100 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Physic_Torque_hpp
+#define OpenMeca_Physic_Torque_hpp
+
+#include "OpenMeca/Physic/MechanicalAction.hpp"
+#include "OpenMeca/Gui/Dialog/Physic/DialogTorque.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+    
+    class Torque : public MechanicalAction
+    {
+    public:  
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+      typedef OpenMeca::Gui::Physic::DialogTorque GuiManager;
+
+    public:
+      Torque(Item::Physical& item);
+      ~Torque();
+      
+      const Util::Unit& GetUnit() const;
+      double GetScale() const;
+
+    protected:
+      void CompleteChForce(chrono::ChSharedForcePtr&);
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+      
+    private:
+      const Util::Unit& unit_;
+    }; 
+
+    
+    template<class Archive>
+    inline void
+    Torque::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(MechanicalAction);
+    }
+
+
+ 
+  }
+}
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::Torque * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Item::Physical* parent = &t->GetPhysicalItem();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::Torque * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Item::Physical* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::Torque(*parent);
+    }
+  }
+} // namespace ...
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/Type.cpp b/SRC/OpenMeca/Physic/Type.cpp
new file mode 100644
index 0000000..f11b3d5
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Type.cpp
@@ -0,0 +1,76 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Physic/Type.hpp"
+#include "OpenMeca/Physic/Quantity.hpp"
+#include "OpenMeca/Gui/MainPlotWindow.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::Type)
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    Type::Type(Quantity& q)
+      :quantity_(q)
+    {
+    }
+
+    Type::~Type()
+    {
+      Gui::MainPlotWindow::Get().DataDeleted(*this);
+    }
+
+    const std::string& 
+    Type::GetLabel() const
+    {
+      return quantity_.GetLabel();
+    }
+
+     double 
+     Type::GetScale() const
+     {
+       return quantity_.GetScale();
+     }
+    
+    const Util::Unit&
+    Type::GetUnit() const
+    {
+      return quantity_.GetUnit();
+    }
+
+    Quantity& 
+    Type::GetQuantity()
+    {
+      return quantity_;
+    }
+
+    const Quantity& 
+    Type::GetQuantity() const
+    {
+      return quantity_;
+    }
+
+  }
+} 
+
diff --git a/SRC/OpenMeca/Physic/Type.hpp b/SRC/OpenMeca/Physic/Type.hpp
new file mode 100644
index 0000000..58dbd67
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Type.hpp
@@ -0,0 +1,83 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Physic_Type_hpp_
+#define _OpenMeca_Physic_Type_hpp_
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include <QObject>
+#include <QMenu>
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Geom/Frame.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    class Quantity;
+
+    class Type
+    {
+    public:
+      Type(Quantity&);
+      virtual ~Type();
+
+      const std::string& GetLabel() const;
+      double GetScale() const;
+      const Util::Unit& GetUnit() const;
+
+      Quantity& GetQuantity();
+      const Quantity& GetQuantity() const;
+
+      virtual void SaveState() = 0;
+      virtual void ResetState() = 0;
+      virtual void RecoveryState(unsigned int) = 0;
+      virtual void FillDataMenu(QMenu* menu) = 0;
+      virtual void WriteHeaderDataFile(std::ofstream&) = 0;
+      virtual void WriteDataFile(std::ofstream&, unsigned int) = 0;
+
+      virtual void Draw() const = 0;
+    
+    private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      Quantity& quantity_;
+    };
+
+    template<class Archive>
+    inline void
+    Type::serialize(Archive &, const unsigned int)
+    {
+    }
+
+
+  }
+} 
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Physic/TypeT.cpp b/SRC/OpenMeca/Physic/TypeT.cpp
new file mode 100644
index 0000000..a12d855
--- /dev/null
+++ b/SRC/OpenMeca/Physic/TypeT.cpp
@@ -0,0 +1,39 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Physic/TypeT.hpp"
+#include "OpenMeca/Geom/Vector.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::TypeT<OpenMeca::Geom::Vector<_3D> >)
+
+
+namespace OpenMeca
+{
+  namespace Physic
+  {    
+
+  }
+}
+
+
diff --git a/SRC/OpenMeca/Physic/TypeT.hpp b/SRC/OpenMeca/Physic/TypeT.hpp
new file mode 100644
index 0000000..e789c0d
--- /dev/null
+++ b/SRC/OpenMeca/Physic/TypeT.hpp
@@ -0,0 +1,78 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Physic_TypeT_hpp_
+#define _OpenMeca_Physic_TypeT_hpp_
+
+#include "OpenMeca/Physic/Type.hpp"
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    template<class T>
+    class TypeT : public Type
+    {
+    public:
+      TypeT(Quantity&);
+      virtual ~TypeT();
+
+      virtual T& GetRealType() = 0;
+      virtual const T& GetRealType() const = 0;
+      
+      virtual void Update(const T&) = 0;
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+      
+    };
+
+    
+    template<class T>
+    template<class Archive>
+    inline void
+    TypeT<T>::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Type);
+    }
+
+
+    template<class T>
+    inline 
+    TypeT<T>::TypeT(Quantity& quantity)
+      :Type(quantity)
+    {
+    }
+
+
+    template<class T>
+    inline 
+    TypeT<T>::~TypeT()
+    {
+    }
+
+
+  }
+} 
+
+#endif
diff --git a/SRC/OpenMeca/Physic/Vector3D.cpp b/SRC/OpenMeca/Physic/Vector3D.cpp
new file mode 100644
index 0000000..f9217ff
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Vector3D.cpp
@@ -0,0 +1,180 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <functional>
+
+#include "OpenMeca/Physic/Vector3D.hpp"
+#include "OpenMeca/Gui/MainPlotWindow.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Physic::Vector3D)
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    Vector3D::Vector3D(Quantity& q)
+      :TypeT<Geom::Vector<_3D> >(q),
+       vec_(std::bind(&Quantity::GetFrame, std::ref(q))), 
+       x_(), y_(), z_(), norm_()
+    {
+      const Geom::Frame<_3D>&(Quantity::*fnpt)() const= &Quantity::GetFrame;
+      std::function<const Geom::Frame<_3D>& ()> f_body = std::bind(fnpt, std::ref(q));
+      
+
+    }
+
+    Vector3D::~Vector3D()
+    {
+    }
+
+    Geom::Vector<_3D>& 
+    Vector3D::GetRealType()
+    {
+      return vec_;
+    }
+    
+    const Geom::Vector<_3D>& 
+    Vector3D::GetRealType() const
+    {
+      return vec_;
+    }
+    
+    void
+    Vector3D::SaveState()
+    {
+      Update(vec_);
+    }
+
+    void
+    Vector3D::Update()
+    {
+      x_.push_back(0);
+      y_.push_back(0);
+      z_.push_back(0);
+      norm_.push_back(0);
+      vec_.SaveState();
+    }
+
+
+    void
+    Vector3D::Update(const Geom::Vector<_3D>& v)
+    {
+      vec_ = v;
+      x_.push_back(v[0]);
+      y_.push_back(v[1]);
+      z_.push_back(v[2]);
+      norm_.push_back(v.GetNorm());
+      vec_.SaveState();
+    }
+
+    void
+    Vector3D::ResetState()
+    {
+      vec_.ResetState();
+      x_.clear();
+      y_.clear();
+      z_.clear();
+      norm_.clear();
+    }
+
+    void
+    Vector3D::RecoveryState(unsigned int i)
+    {
+      vec_.RecoveryState(i);
+    }
+
+    void 
+    Vector3D::FillDataMenu(QMenu* menu)
+    {
+      QAction* X = menu->addAction(Gui::MainPlotWindow::tr("X"));
+      QAction* Y = menu->addAction(Gui::MainPlotWindow::tr("Y"));
+      QAction* Z = menu->addAction(Gui::MainPlotWindow::tr("Z"));
+      QAction* N = menu->addAction(Gui::MainPlotWindow::tr("Norm"));
+      QObject::connect(X, SIGNAL(triggered()), this, SLOT(X()));
+      QObject::connect(Y, SIGNAL(triggered()), this, SLOT(Y()));
+      QObject::connect(Z, SIGNAL(triggered()), this, SLOT(Z()));
+      QObject::connect(N, SIGNAL(triggered()), this, SLOT(Norm()));
+    }
+
+    void 
+    Vector3D::X()
+    {
+      std::string label = GetLabel();
+      label += " along X";
+      Gui::MainPlotWindow::Get().AddData(x_, label.c_str(), GetUnit(), *this);
+    }
+
+    void 
+    Vector3D::Y()
+    {
+      std::string label =  GetLabel();
+      label += " along Y";
+      Gui::MainPlotWindow::Get().AddData(y_, label.c_str(), GetUnit(), *this);
+    }
+
+    void 
+    Vector3D::Z()
+    {
+      std::string label =  GetLabel();
+      label += " along Z";
+      Gui::MainPlotWindow::Get().AddData(z_, label.c_str(), GetUnit(), *this);
+    }
+
+    void 
+    Vector3D::Norm()
+    {
+      std::string label =  GetLabel();
+      label = "Norm of " + label;
+      Gui::MainPlotWindow::Get().AddData(norm_, label.c_str(), GetUnit(), *this);
+    }
+
+    void 
+    Vector3D::WriteHeaderDataFile(std::ofstream& file)
+    {
+      file << GetLabel() << " /X (" <<  GetUnit().GetSymbol() << ")\t"
+	   << GetLabel() << " /Y (" <<  GetUnit().GetSymbol() << ")\t"
+	   << GetLabel() << " /Z (" <<  GetUnit().GetSymbol() << ")";
+    }
+
+    void 
+    Vector3D::WriteDataFile(std::ofstream& file, unsigned int iter)
+    {
+      OMC_ASSERT_MSG(iter < x_.size(), "The data are not coherent");
+      OMC_ASSERT_MSG(iter < y_.size(), "The data are not coherent");
+      OMC_ASSERT_MSG(iter < z_.size(), "The data are not coherent");
+      file << x_[iter] << '\t'
+	   << y_[iter] << '\t'
+	   << z_[iter];
+    }
+
+    void 
+    Vector3D::Draw() const
+    {
+      vec_.Draw(GetScale());
+    }
+
+
+  
+
+  }
+} 
+
diff --git a/SRC/OpenMeca/Physic/Vector3D.hpp b/SRC/OpenMeca/Physic/Vector3D.hpp
new file mode 100644
index 0000000..b2b0ac0
--- /dev/null
+++ b/SRC/OpenMeca/Physic/Vector3D.hpp
@@ -0,0 +1,121 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef _OpenMeca_Physic_Vector3D_hpp_
+#define _OpenMeca_Physic_Vector3D_hpp_
+
+#include <QObject>
+#include <QMenu>
+#include "OpenMeca/Physic/TypeT.hpp"
+#include "OpenMeca/Physic/Quantity.hpp"
+#include "OpenMeca/Geom/Vector.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Physic
+  {
+
+    class Vector3D : public QObject, public TypeT <Geom::Vector<_3D> >
+    {
+      Q_OBJECT
+      
+    public:
+      Vector3D(Quantity&);
+      ~Vector3D();
+
+      void Update(const Geom::Vector<_3D>&);
+      void Update();
+
+      void SaveState();
+      void ResetState();
+      void RecoveryState(unsigned int);
+      Geom::Vector<_3D>& GetRealType();
+      const Geom::Vector<_3D>& GetRealType() const;
+			       
+      void FillDataMenu(QMenu* menu);
+      void WriteHeaderDataFile(std::ofstream&);
+      void WriteDataFile(std::ofstream&, unsigned int);	
+
+      void Draw() const;
+
+						      
+    private slots:
+      void X();
+      void Y();
+      void Z();
+      void Norm();
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+    
+    private:
+      Geom::Vector<_3D> vec_;
+      std::vector<double> x_;
+      std::vector<double> y_;
+      std::vector<double> z_;
+      std::vector<double> norm_;
+
+    };
+
+
+    template<class Archive>
+    inline void
+    Vector3D::serialize(Archive & ar, const unsigned int)
+    {
+	ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(TypeT <Geom::Vector<_3D> >);
+	//ar & BOOST_SERIALIZATION_NVP(vec_);
+    }
+
+  }
+} 
+
+namespace boost 
+{ 
+  namespace serialization 
+  {
+    
+    template<class Archive>
+    inline void save_construct_data(Archive & ar, 
+				    const OpenMeca::Physic::Vector3D * t, 
+				    const unsigned int)
+    {
+      const OpenMeca::Physic::Quantity* parent = &t->GetQuantity();
+      ar << parent;
+    }
+    
+
+    template<class Archive>
+    inline void load_construct_data(Archive & ar, 
+				    OpenMeca::Physic::Vector3D * t, 
+				    const unsigned int)
+    {
+      OpenMeca::Physic::Quantity* parent = 0;
+      ar >> parent;
+      ::new(t)OpenMeca::Physic::Vector3D(*parent);
+    }
+  }
+} // namespace ...
+
+
+#endif
diff --git a/SRC/OpenMeca/Resources.qrc b/SRC/OpenMeca/Resources.qrc
new file mode 100644
index 0000000..b28b486
--- /dev/null
+++ b/SRC/OpenMeca/Resources.qrc
@@ -0,0 +1,111 @@
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<RCC>
+  <qresource>
+    <file>Info.txt</file>
+
+    <file>Rsc/Img/Logo.svg</file>
+    <file>Rsc/Img/Mini-Logo.svg</file>
+    <file>Rsc/Img/Logo.png</file>
+    <file>Rsc/Img/Body.svg</file>
+    <file>Rsc/Img/Body-ground.svg</file>
+    <file>Rsc/Img/Link.svg</file>
+    <file>Rsc/Img/Flower.svg</file>	
+    <file>Rsc/Img/System.svg</file>
+    <file>Rsc/Img/Sensor.svg</file>
+    <file>Rsc/Img/Frame.svg</file>
+    <file>Rsc/Img/Geometry.svg</file>
+    <file>Rsc/Img/Cosmetic.svg</file>
+    <file>Rsc/Img/Collision.svg</file>
+    <file>Rsc/Img/Equation.svg</file>
+
+    <file>Rsc/Img/Part/Point.svg</file>
+    <file>Rsc/Img/Part/Junction.svg</file>
+    <file>Rsc/Img/Part/Pipe.svg</file>
+
+    <file>Rsc/Img/Shape/Sphere.svg</file>
+    <file>Rsc/Img/Shape/Box.svg</file>
+    <file>Rsc/Img/Shape/Cylinder.svg</file>
+    <file>Rsc/Img/Shape/Ground.svg</file>
+
+    <file>Rsc/Img/Link/Revolute.svg</file>
+    <file>Rsc/Img/Link/Motor.svg</file>
+    <file>Rsc/Img/Link/LinearMotor.svg</file>
+    <file>Rsc/Img/Link/Slider.svg</file>
+    <file>Rsc/Img/Link/Cylindrical.svg</file>
+    <file>Rsc/Img/Link/Planar.svg</file>
+    <file>Rsc/Img/Link/PointLine.svg</file>
+    <file>Rsc/Img/Link/PointPlane.svg</file>
+    <file>Rsc/Img/Link/Spherical.svg</file>
+    <file>Rsc/Img/Link/Screw.svg</file>
+    <file>Rsc/Img/Link/Gear.svg</file>
+    <file>Rsc/Img/Link/Pulley.svg</file>
+    <file>Rsc/Img/Link/RackPinion.svg</file>
+    <file>Rsc/Img/Link/Spring.svg</file>
+
+    <file>Rsc/Img/MainWindow/New.svg</file>
+    <file>Rsc/Img/MainWindow/Redo.svg</file>
+    <file>Rsc/Img/MainWindow/Undo.svg</file>
+    <file>Rsc/Img/MainWindow/Open.svg</file>
+    <file>Rsc/Img/MainWindow/Preference.svg</file>
+    <file>Rsc/Img/MainWindow/Quit.svg</file>
+    <file>Rsc/Img/MainWindow/Save-as.svg</file>
+    <file>Rsc/Img/MainWindow/Save.svg</file>
+
+    <file>Rsc/Img/Player/Play.svg</file>
+    <file>Rsc/Img/Player/Stop.svg</file>
+    <file>Rsc/Img/Player/Record.svg</file>
+
+    <file>Rsc/Img/Sensor/LinearPosition.svg</file>
+    <file>Rsc/Img/Sensor/LinearVelocity.svg</file>
+    <file>Rsc/Img/Sensor/LinearAcceleration.svg</file>
+    <file>Rsc/Img/Sensor/AngularPosition.svg</file>
+    <file>Rsc/Img/Sensor/AngularVelocity.svg</file>
+    <file>Rsc/Img/Sensor/AngularAcceleration.svg</file>
+    <file>Rsc/Img/Sensor/Force.svg</file>
+    <file>Rsc/Img/Sensor/Torque.svg</file>
+
+    <file>Rsc/Img/Load.svg</file>
+    <file>Rsc/Img/Load/Force.svg</file>
+    <file>Rsc/Img/Load/Torque.svg</file>
+    <file>Rsc/Img/SystemSetting/Scales.svg</file>
+    <file>Rsc/Img/SystemSetting/Gravity.svg</file>
+    <file>Rsc/Img/SystemSetting/Simulation.svg</file>
+    <file>Rsc/Img/SystemSetting/Scene.svg</file>
+
+    <file>Rsc/Xml/MenuManager.xml</file>
+    <file>Rsc/Xml/UnitManager.xml</file>
+    <file>Rsc/Xml/LangManager.xml</file>
+
+    <file>Rsc/Help/Help.qhc</file>    
+    <file>Rsc/Help/Help.qch</file>
+
+    <file>Rsc/Lang/openmeca_fr.qm</file>
+
+    <file>Rsc/Example/gears.omc</file>
+    <file>Rsc/Example/gyroscope.omc</file>
+    <file>Rsc/Example/reprap.omc</file>
+    <file>Rsc/Example/robot.omc</file>
+    <file>Rsc/Example/screw.omc</file>
+    <file>Rsc/Example/steering.omc</file>
+    <file>Rsc/Example/cranck-shaft.omc</file>
+
+  </qresource>
+</RCC>
diff --git a/SRC/OpenMeca/Rsc/Example/cranck-shaft.omc b/SRC/OpenMeca/Rsc/Example/cranck-shaft.omc
new file mode 100644
index 0000000..702c78e
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Example/cranck-shaft.omc
@@ -0,0 +1,46 @@
+22 serialization::archive 9 0 2 0 0 6  2.1.4 2 1 4 0 0 45 3 20 OpenMeca::Item::Body 1 3
+0 0 0 0 0 0 0 4 Body 6 ground 0 0 27 27 27 255 1 0 0 0 0 0 0 0 0 3 0 0 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 3 1 0 0 3 0 1 0 3 0 0 1 1 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+1 4 Body 5 crank 255 0 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+2 4 Body 3 rod 0 85 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+3 4 Body 6 piston 0 85 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 44 OpenMeca::Item::LinkT<OpenMeca::Item::Motor> 1 0
+4 0 2 5 Motor 7 Motor_1 0 0 3 0 15 4 3 1 15 4 3 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 0 0 3 1 0 0 1 1 1 0 1 0 0 0 0 1 0 22 1 0
+5 15 4 0 0 0 0 12 Part_Motor_1 12 Part_Motor_1 0 0 0 3 26 1 0
+6 22 5 0 0 14 AutomaticPoint 4 left 0 0 0 22 5 26 6 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+7 22 5 14 AutomaticPoint 6 middle 0 22 5 26 7 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+8 22 5 14 AutomaticPoint 5 right 0 22 5 26 8 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 29 1 0
+9 15 4 12 Part_Motor_2 12 Part_Motor_1 0 1 26
+10 29 9 14 AutomaticPoint 6 middle 0 29 9 26 10 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 1 0 0 0 1 1 1 1 22 5 26 6 26 7 26 8 29 9 26 10 33 47 OpenMeca::Item::LinkT<OpenMeca::Item::Revolute> 1 0
+11 8 Revolute 10 Revolute_1 3 2 33 11 3 1 33 11 3 0 0.5 0 1 0 1 R 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34 1 0
+12 33 11 15 Part_Revolute_1 15 Part_Revolute_1 0 3 26
+13 34 12 14 AutomaticPoint 4 left 0 34 12 26 13 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+14 34 12 14 AutomaticPoint 6 middle 0 34 12 26 14 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+15 34 12 14 AutomaticPoint 5 right 0 34 12 26 15 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35 1 0
+16 33 11 15 Part_Revolute_2 15 Part_Revolute_1 0 1 26
+17 35 16 14 AutomaticPoint 6 middle 0 35 16 26 17 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 34 12 26 13 26 14 26 15 35 16 26 17 33
+18 8 Revolute 10 Revolute_2 3 2 33 18 3 3 33 18 3 0 1 0 1 0 3 R+B 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+19 33 18 15 Part_Revolute_1 15 Part_Revolute_2 0 3 26
+20 34 19 14 AutomaticPoint 4 left 0 34 19 26 20 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+21 34 19 14 AutomaticPoint 6 middle 0 34 19 26 21 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+22 34 19 14 AutomaticPoint 5 right 0 34 19 26 22 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+23 33 18 15 Part_Revolute_2 15 Part_Revolute_2 0 1 26
+24 35 23 14 AutomaticPoint 6 middle 0 35 23 26 24 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 19 26 20 26 21 26 22 35 23 26 24 37 45 OpenMeca::Item::LinkT<OpenMeca::Item::Slider> 1 0
+25 6 Slider 8 Slider_1 3 0 37 25 3 3 37 25 3 0 2 0 1 0 5 R+B+1 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 38 1 0
+26 37 25 13 Part_Slider_1 13 Part_Slider_1 0 1 26
+27 38 26 14 AutomaticPoint 6 middle 0 38 26 26 27 3 0 0 0 3 0 0 0 1 1 3 0 0 0 39 1 0
+28 37 25 13 Part_Slider_2 13 Part_Slider_1 0 3 26
+29 39 28 14 AutomaticPoint 4 left 0 39 28 26 29 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+30 39 28 14 AutomaticPoint 6 middle 0 39 28 26 30 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+31 39 28 14 AutomaticPoint 5 right 0 39 28 26 31 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 0 0 38 26 26 27 39 28 26 29 26 30 26 31 41 32 OpenMeca::Item::PartUserJunction 1 0
+32 26 15 8 Junction 10 Junction_1 0 26 15 41 32 3 0 0 0 3 0 0 0.70710678118654746 0.70710678118654757 0 0 26 22 41 32 41
+33 26 13 8 Junction 10 Junction_2 0 26 13 41 33 3 0 0 0 3 0 0 0.70710678118654746 0.70710678118654757 26 20 41 33 41
+34 26 31 8 Junction 10 Junction_3 0 26 31 41 34 3 0 0 0 3 0 -0.70710678118654746 -3.1401849173675498e-16 0.70710678118654757 26 24 41 34 41
+35 26 10 8 Junction 10 Junction_4 0 26 10 41 35 3 0 0 0 3 0 0 0.70710678118654746 0.70710678118654757 26 17 41 35 43 28 OpenMeca::Item::PartUserPipe 1 0
+36 26 29 4 Pipe 6 Pipe_1 0 26 29 43 36 3 0 2.5 -1.1102230246251565e-16 3 0 0 0.70710678118654746 0.70710678118654757 3 0 1 0 0.5 26
+37 43 36 14 AutomaticPoint 16 AutomaticPoint_1 0 43 36 26 37 3 0.5 0 0 3 0 0 0 1 0 3 0 0 0 26 37 44 63 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder> 1 0
+38 26 37 0 0 8 Cylinder 10 Cylinder_1 0 26 37 44 38 3 1.1102230246251565e-16 3 -1.1102230246251565e-16 3 0 0 0.70710678118654746 0.70710678118654757 0 0 0.5 0.10000000000000001 3 0 1 0 0 47 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground> 1 0
+39 26 8 6 Ground 8 Ground_1 0 26 8 47 39 3 0 0 0.5 3 0 -0.70710678118654746 0 0.70710678118654757 0 0 3 0 0 1 0 43
+40 26 27 4 Pipe 6 Pipe_2 0 26 27 43 40 3 0 2 0 3 0 -0.70710678118654746 0 0.70710678118654757 3 0 0 1 0.5 26
+41 43 40 14 AutomaticPoint 16 AutomaticPoint_2 0 43 40 26 41 3 0.5 0 0 3 0 0 0 1 0 3 0 0 0 26 41 47
+42 26 41 6 Ground 8 Ground_2 0 26 41 47 42 3 1.1102230246251565e-16 2 0.5 3 0 -0.70710678118654746 0 0.70710678118654757 3 0 0 1 0 49 24 OpenMeca::Item::Variable 1 0
+43 8 Variable 7 R = 0.5 0 0 1 R 0.5 49
+44 8 Variable 7 B = 0.5 1 B 0.5 4 7 Gravity 3 0 -9.8100000000000005 0 6 Scales 8 19 AngularAcceleration 1 15 AngularVelocity 1 5 Force 1 5 Frame 1 18 LinearAcceleration 1 14 LinearVelocity 1 4 Part 1 6 Torque 1 5 Scene 0 128 128 128 255 3 0 0 0 2 0 10 Simulation 0.001 60 0.10000000000000001
diff --git a/SRC/OpenMeca/Rsc/Example/gears.omc b/SRC/OpenMeca/Rsc/Example/gears.omc
new file mode 100644
index 0000000..90e6d6d
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Example/gears.omc
@@ -0,0 +1,43 @@
+22 serialization::archive 9 0 2 0 0 6  2.1.4 2 1 4 0 0 41 3 20 OpenMeca::Item::Body 1 3
+0 0 0 0 0 0 0 4 Body 6 Body_1 0 0 85 170 0 255 1 0 0 0 0 0 0 0 0 3 0 0 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+1 4 Body 6 Body_2 255 0 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 43 OpenMeca::Item::LinkT<OpenMeca::Item::Gear> 1 0
+2 0 2 4 Gear 6 Gear_1 0 0 3 0 15 2 3 1 15 2 3 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 0 0 3 1 0 0 1 1 1 0 1 0 0 0 0 1 0 22 1 0
+3 15 2 0 0 0 0 11 Part_Gear_1 11 Part_Gear_1 0 0 0 1 26 1 0
+4 22 3 0 0 14 AutomaticPoint 6 center 0 0 0 22 3 26 4 3 0 0 0 3 0 0 0 1 1 3 0 0 0 29 1 0
+5 15 2 11 Part_Gear_2 11 Part_Gear_1 0 1 26
+6 29 5 14 AutomaticPoint 6 center 0 29 5 26 6 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 0 0 2 1 0.10000000000000001 0.3490658503988659 0 22 3 26 4 29 5 26 6 3
+7 4 Body 6 Body_3 85 0 127 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 32 44 OpenMeca::Item::LinkT<OpenMeca::Item::Motor> 1 0
+8 5 Motor 7 Motor_1 3 0 32 8 3
+9 4 Body 6 Body_4 0 0 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 1 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 32 8 3 0 0 -1 1 0 1 0 2 -1 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 33 1 0
+10 32 8 12 Part_Motor_1 12 Part_Motor_1 0 3 26
+11 33 10 14 AutomaticPoint 4 left 0 33 10 26 11 3 0 0 -0.75 3 0 0 0 1 1 3 0 0 -0.5 26
+12 33 10 14 AutomaticPoint 6 middle 0 33 10 26 12 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+13 33 10 14 AutomaticPoint 5 right 0 33 10 26 13 3 0 0 0.75 3 0 0 0 1 1 3 0 0 0.5 34 1 0
+14 32 8 12 Part_Motor_2 12 Part_Motor_1 0 1 26
+15 34 14 14 AutomaticPoint 6 middle 0 34 14 26 15 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 1 0 1 1 5 5 3 9 33 10 26 11 26 12 26 13 34 14 26 15 37 47 OpenMeca::Item::LinkT<OpenMeca::Item::Revolute> 1 0
+16 8 Revolute 10 Revolute_1 3 1 37 16 3 7 37 16 3 0 1 -1 1 0 1 1 2 -1 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 38 1 0
+17 37 16 15 Part_Revolute_1 15 Part_Revolute_1 0 3 26
+18 38 17 14 AutomaticPoint 4 left 0 38 17 26 18 3 0 0 -0.75 3 0 0 0 1 1 3 0 0 -0.5 26
+19 38 17 14 AutomaticPoint 6 middle 0 38 17 26 19 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+20 38 17 14 AutomaticPoint 5 right 0 38 17 26 20 3 0 0 0.75 3 0 0 0 1 1 3 0 0 0.5 39 1 0
+21 37 16 15 Part_Revolute_2 15 Part_Revolute_1 0 1 26
+22 39 21 14 AutomaticPoint 6 middle 0 39 21 26 22 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 38 17 26 18 26 19 26 20 39 21 26 22 41 32 OpenMeca::Item::PartUserJunction 1 0
+23 26 6 8 Junction 10 Junction_1 0 26 6 41 23 3 0 0 0 3 -0 0.70710678118654746 0 0.70710678118654757 0 0 26 20 41 23 41
+24 26 4 8 Junction 10 Junction_2 0 26 4 41 24 3 0 0 0 3 -0 0.70710678118654746 0 0.70710678118654757 26 13 41 24 15
+25 4 Gear 6 Gear_2 3 9 15 25 3 1 15 25 3 0 0 0.80000000000000004 1 0 1 0 3 0.8 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 22
+26 15 25 11 Part_Gear_1 11 Part_Gear_2 0 1 26
+27 22 26 14 AutomaticPoint 6 center 0 22 26 26 27 3 0 0 0 3 0 0 0 1 1 3 0 0 0 29
+28 15 25 11 Part_Gear_2 11 Part_Gear_2 0 1 26
+29 29 28 14 AutomaticPoint 6 center 0 29 28 26 29 3 0 0 0 3 0 0 0 1 1 3 0 0 0 1.5 1 0.10000000000000001 0.3490658503988659 1 22 26 26 27 29 28 26 29 37
+30 8 Revolute 10 Revolute_2 3 7 37 30 3 9 37 30 3 0 0 -2.2000000000000002 1 0 1 0 4 -2.2 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 38
+31 37 30 15 Part_Revolute_1 15 Part_Revolute_2 0 3 26
+32 38 31 14 AutomaticPoint 4 left 0 38 31 26 32 3 0 0 -0.75 3 0 0 0 1 1 3 0 0 -0.5 26
+33 38 31 14 AutomaticPoint 6 middle 0 38 31 26 33 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+34 38 31 14 AutomaticPoint 5 right 0 38 31 26 34 3 0 0 0.75 3 0 0 0 1 1 3 0 0 0.5 39
+35 37 30 15 Part_Revolute_2 15 Part_Revolute_2 0 1 26
+36 39 35 14 AutomaticPoint 6 middle 0 39 35 26 36 3 0 0 0 3 0 0 0 1 1 3 0 0 0 38 31 26 32 26 33 26 34 39 35 26 36 41
+37 26 34 8 Junction 10 Junction_3 0 26 34 41 37 3 0 0 0 3 0 -0.2901716460986225 0.64482588021916087 0.70710678118654757 26 22 41 37 41
+38 26 6 8 Junction 10 Junction_4 0 26 6 41 38 3 0 0 0 3 0 -0.70710678118654746 0 0.70710678118654757 26 29 41 38 43 29 OpenMeca::Item::PartUserPoint 1 1
+39 3 1
+40 5 Point 7 Point_1 0 3 1 43 39 3 0 1.8 0.90000000000000002 3 0 0 0 1 0 3 0 0 0 3 0 1.8 0.90000000000000002 1 0 3 1.8 3 0.9 44 40 OpenMeca::Item::How::GetLinPos::MySensor 1 0
+41 43 39 0 0 0 0 21 Sensor at LinearPosition 23 Sensor at LinearPosition_1 0 4 7 Gravity 3 0 -9.8100000000000005 0 6 Scales 8 19 AngularAcceleration 1 15 AngularVelocity 1 5 Force 1 5 Frame 1 18 LinearAcceleration 1 14 LinearVelocity 1 4 Part 1.5 6 Torque 1 5 Scene 0 128 128 128 255 3 0 0 0 2 1 10 Simulation 0.00020000000000000001 60 0.10000000000000001
diff --git a/SRC/OpenMeca/Rsc/Example/gyroscope.omc b/SRC/OpenMeca/Rsc/Example/gyroscope.omc
new file mode 100644
index 0000000..5fad413
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Example/gyroscope.omc
@@ -0,0 +1,49 @@
+22 serialization::archive 9 0 2 0 0 6  2.1.0 2 1 0 0 0 44 3 20 OpenMeca::Item::Body 1 3
+0 0 0 0 0 0 0 4 Body 6 Body_1 0 0 34 250 57 255 1 0 0 0 0 0 0 0 0 3 0 0 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+1 4 Body 6 Body_2 53 15 85 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 10 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 44 OpenMeca::Item::LinkT<OpenMeca::Item::Motor> 1 0
+2 0 2 5 Motor 7 Motor_1 0 0 3 0 15 2 3 1 15 2 3 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 0 0 3 1 0 0 1 1 1 0 1 0 0 0 0 1 0 22 1 0
+3 15 2 0 0 0 0 12 Part_Motor_1 12 Part_Motor_1 0 0 0 3 26 1 0
+4 22 3 0 0 14 AutomaticPoint 4 left 0 0 0 22 3 26 4 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+5 22 3 14 AutomaticPoint 6 middle 0 22 3 26 5 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+6 22 3 14 AutomaticPoint 5 right 0 22 3 26 6 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 29 1 0
+7 15 2 12 Part_Motor_2 12 Part_Motor_1 0 1 26
+8 29 7 14 AutomaticPoint 6 middle 0 29 7 26 8 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 1 0 0 0 1 1 2 2 22 3 26 4 26 5 26 6 29 7 26 8 33 63 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder> 1 0
+9 26 8 0 0 8 Cylinder 10 Cylinder_1 0 26 8 33 9 3 0 0 0 3 0 -0.70710678118654746 0 0.70710678118654757 0 0 0.80000000000000004 0.10000000000000001 3 0 0 1 0 15
+10 5 Motor 7 Motor_2 3 0 15 10 3
+11 4 Body 6 Body_3 212 147 75 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 10 3 -1.5 0 0 4 -1.5 1 0 1 0 3 0 0.70710678118654746 0 0.70710678118654757 3 0 1 0 1 0 1 1 1 0 1.5707963267948966 2 90 22
+12 15 10 12 Part_Motor_1 12 Part_Motor_2 0 3 26
+13 22 12 14 AutomaticPoint 4 left 0 22 12 26 13 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+14 22 12 14 AutomaticPoint 6 middle 0 22 12 26 14 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+15 22 12 14 AutomaticPoint 5 right 0 22 12 26 15 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 29
+16 15 10 12 Part_Motor_2 12 Part_Motor_2 0 1 26
+17 29 16 14 AutomaticPoint 6 middle 0 29 16 26 17 3 0 0 0 3 0 0 0 1 1 3 0 0 0 6 sin(t) 0 3 11 22 12 26 13 26 14 26 15 29 16 26 17 3
+18 4 Body 6 Body_4 129 129 129 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 1 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 36 47 OpenMeca::Item::LinkT<OpenMeca::Item::Revolute> 1 0
+19 8 Revolute 10 Revolute_1 3 11 36 19 3 18 36 19 3 -1.5 -0.80000000000000004 0 4 -1.5 4 -0.8 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 37 1 0
+20 36 19 15 Part_Revolute_1 15 Part_Revolute_1 0 3 26
+21 37 20 14 AutomaticPoint 4 left 0 37 20 26 21 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+22 37 20 14 AutomaticPoint 6 middle 0 37 20 26 22 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+23 37 20 14 AutomaticPoint 5 right 0 37 20 26 23 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 38 1 0
+24 36 19 15 Part_Revolute_2 15 Part_Revolute_1 0 1 26
+25 38 24 14 AutomaticPoint 6 middle 0 38 24 26 25 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 37 20 26 21 26 22 26 23 38 24 26 25 40 29 OpenMeca::Item::PartUserPoint 1 1
+26 3 1
+27 5 Point 7 Point_1 0 3 1 40 26 3 0.5 0 0 3 0 0 0 1 0 3 0 0 0 3 0.5 0 0 3 0.5 1 0 1 0 40
+28 3 1
+29 5 Point 7 Point_2 0 3 1 40 28 3 -0.5 0 0 3 0 0 0 1 0 3 0 0 0 3 -0.5 0 0 4 -0.5 1 0 1 0 40
+30 3 1
+31 5 Point 7 Point_3 0 3 1 40 30 3 0 0.5 0 3 0 0 0 1 0 3 0 0 0 3 0 0.5 0 1 0 3 0.5 1 0 40
+32 3 1
+33 5 Point 7 Point_4 0 3 1 40 32 3 0 -0.5 0 3 0 0 0 1 0 3 0 0 0 3 0 -0.5 0 1 0 4 -0.5 1 0 41 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Sphere> 1 0
+34 40 26 6 Sphere 8 Sphere_1 0 40 26 41 34 3 0.5 0 0 3 0 0 0 1 0 0 0.10000000000000001 0 41
+35 40 28 6 Sphere 8 Sphere_2 0 40 28 41 35 3 -0.5 0 0 3 0 0 0 1 0.10000000000000001 0 41
+36 40 30 6 Sphere 8 Sphere_3 0 40 30 41 36 3 0 0.5 0 3 0 0 0 1 0.10000000000000001 0 41
+37 40 32 6 Sphere 8 Sphere_4 0 40 32 41 37 3 0 -0.5 0 3 0 0 0 1 0.10000000000000001 0 43 28 OpenMeca::Item::PartUserPipe 1 0
+38 26 6 4 Pipe 6 Pipe_1 0 26 6 43 38 3 0 0 0.5 3 -0 0 1 6.123233995736766e-17 3 -1 0 0 0.80000000000000004 26
+39 43 38 14 AutomaticPoint 16 AutomaticPoint_1 0 43 38 26 39 3 0.80000000000000004 0 0 3 0 0 0 1 0 3 0 0 0 26 39 43
+40 26 4 4 Pipe 6 Pipe_2 0 26 4 43 40 3 0 0 -0.5 3 -0 0 1 6.123233995736766e-17 3 -1 0 0 0.80000000000000004 26
+41 43 40 14 AutomaticPoint 16 AutomaticPoint_2 0 43 40 26 41 3 0.80000000000000004 0 0 3 0 0 0 1 0 3 0 0 0 26 41 44 32 OpenMeca::Item::PartUserJunction 1 0
+42 26 41 8 Junction 10 Junction_1 0 26 41 44 42 3 0 0 0 3 0 -0.56062883645134454 1.3731446201396876e-16 0.82806721209042655 0 0 26 15 44 42 44
+43 26 39 8 Junction 10 Junction_2 0 26 39 44 43 3 0 0 0 3 -0 0.56062883645134454 1.3731446201396881e-16 0.82806721209042655 26 15 44 43 44
+44 26 21 8 Junction 10 Junction_3 0 26 21 44 44 3 0 0 0 3 -0 0.70710678118654746 4.186913223156733e-16 0.70710678118654757 26 17 44 44 43
+45 26 25 4 Pipe 6 Pipe_3 0 26 25 43 45 3 -1.5 -0.80000000000000004 0 3 0 -0.70710678118654746 0 0.70710678118654757 3 0 0 1 0.5 26
+46 43 45 14 AutomaticPoint 16 AutomaticPoint_3 0 43 45 26 46 3 0.5 0 0 3 0 0 0 1 0 3 0 0 0 26 46 46 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground> 1 0
+47 26 46 6 Ground 8 Ground_1 0 26 46 46 47 3 -1.5 -0.80000000000000004 0.5 3 0 -0.70710678118654746 0 0.70710678118654757 0 0 3 0 0 1 0 4 7 Gravity 3 0 -9.8100000000000005 0 6 Scales 8 19 AngularAcceleration 1 15 AngularVelocity 1 5 Force 1 5 Frame 1 18 LinearAcceleration 1 14 LinearVelocity 1 4 Part 1 6 Torque 1 5 Scene 0 128 128 128 255 3 0 0 0 3 0 10 Simulation 0.001 60 0.10000000000000001
diff --git a/SRC/OpenMeca/Rsc/Example/reprap.omc b/SRC/OpenMeca/Rsc/Example/reprap.omc
new file mode 100644
index 0000000..bd9e2fd
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Example/reprap.omc
@@ -0,0 +1,158 @@
+22 serialization::archive 9 0 2 0 0 6  2.1.0 2 1 0 0 0 153 3 20 OpenMeca::Item::Body 1 3
+0 0 0 0 0 0 0 4 Body 4 bati 0 0 0 0 0 255 1 0 0 0 0 0 0 0 0 3 0 0 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 3 1 0 0 3 0 1 0 3 0 0 1 1 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+1 4 Body 9 Traverse1 0 0 127 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+2 4 Body 9 Traverse2 255 170 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+3 4 Body 9 Traverse3 0 170 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+4 4 Body 13 biellette1(1) 170 255 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 48 OpenMeca::Item::LinkT<OpenMeca::Item::Spherical> 1 0
+5 0 2 9 Spherical 11 Spherical_1 0 0 3 1 15 5 3 4 15 5 3 0.20000000000000001 0 1 3 0.2 1 0 1 1 0 0 3 0 1 0 6.123233995736766e-17 0 0 0 0 3 0 1 0 1 0 1 1 1 0 0 0 3.1415926535897931 3 180 22 1 0
+6 15 5 0 0 0 0 16 Part_Spherical_1 16 Part_Spherical_1 0 0 0 2 26 1 0
+7 22 6 0 0 14 AutomaticPoint 6 center 0 0 0 22 6 26 7 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+8 22 6 14 AutomaticPoint 2 up 0 22 6 26 8 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29 1 0
+9 15 5 16 Part_Spherical_2 16 Part_Spherical_1 0 2 26
+10 29 9 14 AutomaticPoint 6 center 0 29 9 26 10 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+11 29 9 14 AutomaticPoint 2 up 0 29 9 26 11 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 0 0 0 0 22 6 26 7 26 8 29 9 26 10 26 11 3
+12 4 Body 13 biellette1(2) 170 255 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+13 4 Body 13 biellette2(1) 170 255 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+14 4 Body 13 biellette2(2) 170 255 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+15 4 Body 13 biellette3(1) 170 255 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+16 4 Body 13 biellette3(2) 170 255 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15
+17 9 Spherical 11 Spherical_2 3 1 15 17 3 12 15 17 3 -0.20000000000000001 0 1 4 -0.2 1 0 1 1 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 22
+18 15 17 16 Part_Spherical_1 16 Part_Spherical_2 0 2 26
+19 22 18 14 AutomaticPoint 6 center 0 22 18 26 19 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+20 22 18 14 AutomaticPoint 2 up 0 22 18 26 20 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+21 15 17 16 Part_Spherical_2 16 Part_Spherical_2 0 2 26
+22 29 21 14 AutomaticPoint 6 center 0 29 21 26 22 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+23 29 21 14 AutomaticPoint 2 up 0 29 21 26 23 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 18 26 19 26 20 29 21 26 22 26 23 15
+24 9 Spherical 11 Spherical_3 3 2 15 24 3 13 15 24 3 -1.2 0 -1 4 -1.2 1 0 2 -1 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 22
+25 15 24 16 Part_Spherical_1 16 Part_Spherical_3 0 2 26
+26 22 25 14 AutomaticPoint 6 center 0 22 25 26 26 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+27 22 25 14 AutomaticPoint 2 up 0 22 25 26 27 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+28 15 24 16 Part_Spherical_2 16 Part_Spherical_3 0 2 26
+29 29 28 14 AutomaticPoint 6 center 0 29 28 26 29 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+30 29 28 14 AutomaticPoint 2 up 0 29 28 26 30 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 25 26 26 26 27 29 28 26 29 26 30 15
+31 9 Spherical 11 Spherical_4 3 2 15 31 3 14 15 31 3 -0.80000000000000004 0 -1 4 -0.8 1 0 2 -1 3 0 1 0 6.123233995736766e-17 3 0 1 0 1 0 1 1 1 0 3.1415926535897931 3 180 22
+32 15 31 16 Part_Spherical_1 16 Part_Spherical_4 0 2 26
+33 22 32 14 AutomaticPoint 6 center 0 22 32 26 33 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+34 22 32 14 AutomaticPoint 2 up 0 22 32 26 34 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+35 15 31 16 Part_Spherical_2 16 Part_Spherical_4 0 2 26
+36 29 35 14 AutomaticPoint 6 center 0 29 35 26 36 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+37 29 35 14 AutomaticPoint 2 up 0 29 35 26 37 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 32 26 33 26 34 29 35 26 36 26 37 15
+38 9 Spherical 11 Spherical_5 3 3 15 38 3 15 15 38 3 1.2 0 -1 3 1.2 1 0 2 -1 3 0 1 0 6.123233995736766e-17 3 0 1 0 1 0 1 1 1 0 3.1415926535897931 3 180 22
+39 15 38 16 Part_Spherical_1 16 Part_Spherical_5 0 2 26
+40 22 39 14 AutomaticPoint 6 center 0 22 39 26 40 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+41 22 39 14 AutomaticPoint 2 up 0 22 39 26 41 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+42 15 38 16 Part_Spherical_2 16 Part_Spherical_5 0 2 26
+43 29 42 14 AutomaticPoint 6 center 0 29 42 26 43 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+44 29 42 14 AutomaticPoint 2 up 0 29 42 26 44 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 39 26 40 26 41 29 42 26 43 26 44 15
+45 9 Spherical 11 Spherical_6 3 3 15 45 3 16 15 45 3 0.80000000000000004 0 -1 3 0.8 1 0 2 -1 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 22
+46 15 45 16 Part_Spherical_1 16 Part_Spherical_6 0 2 26
+47 22 46 14 AutomaticPoint 6 center 0 22 46 26 47 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+48 22 46 14 AutomaticPoint 2 up 0 22 46 26 48 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+49 15 45 16 Part_Spherical_2 16 Part_Spherical_6 0 2 26
+50 29 49 14 AutomaticPoint 6 center 0 29 49 26 50 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+51 29 49 14 AutomaticPoint 2 up 0 29 49 26 51 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 46 26 47 26 48 29 49 26 50 26 51 3
+52 4 Body 7 plateau 82 28 12 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15
+53 9 Spherical 11 Spherical_7 3 52 15 53 3 4 15 53 3 0.20000000000000001 -2 0.5 3 0.2 1 Y 3 0.5 3 0 1 0 6.123233995736766e-17 3 0 1 0 1 0 1 1 1 0 3.1415926535897931 3 180 22
+54 15 53 16 Part_Spherical_1 16 Part_Spherical_7 0 2 26
+55 22 54 14 AutomaticPoint 6 center 0 22 54 26 55 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+56 22 54 14 AutomaticPoint 2 up 0 22 54 26 56 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+57 15 53 16 Part_Spherical_2 16 Part_Spherical_7 0 2 26
+58 29 57 14 AutomaticPoint 6 center 0 29 57 26 58 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+59 29 57 14 AutomaticPoint 2 up 0 29 57 26 59 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 54 26 55 26 56 29 57 26 58 26 59 32 24 OpenMeca::Item::Variable 1 0
+60 8 Variable 6 Y = -2 0 0 1 Y -2 15
+61 9 Spherical 11 Spherical_8 3 52 15 61 3 12 15 61 3 -0.20000000000000001 -2 0.5 4 -0.2 1 Y 3 0.5 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 22
+62 15 61 16 Part_Spherical_1 16 Part_Spherical_8 0 2 26
+63 22 62 14 AutomaticPoint 6 center 0 22 62 26 63 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+64 22 62 14 AutomaticPoint 2 up 0 22 62 26 64 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+65 15 61 16 Part_Spherical_2 16 Part_Spherical_8 0 2 26
+66 29 65 14 AutomaticPoint 6 center 0 29 65 26 66 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+67 29 65 14 AutomaticPoint 2 up 0 29 65 26 67 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 62 26 63 26 64 29 65 26 66 26 67 15
+68 9 Spherical 11 Spherical_9 3 52 15 68 3 13 15 68 3 -0.69999999999999996 -2 -0.5 4 -0.7 1 Y 4 -0.5 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 22
+69 15 68 16 Part_Spherical_1 16 Part_Spherical_9 0 2 26
+70 22 69 14 AutomaticPoint 6 center 0 22 69 26 70 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+71 22 69 14 AutomaticPoint 2 up 0 22 69 26 71 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+72 15 68 16 Part_Spherical_2 16 Part_Spherical_9 0 2 26
+73 29 72 14 AutomaticPoint 6 center 0 29 72 26 73 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+74 29 72 14 AutomaticPoint 2 up 0 29 72 26 74 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 69 26 70 26 71 29 72 26 73 26 74 15
+75 9 Spherical 12 Spherical_10 3 52 15 75 3 14 15 75 3 -0.29999999999999999 -2 -0.5 4 -0.3 1 Y 4 -0.5 3 0 1 0 6.123233995736766e-17 3 0 1 0 1 0 1 1 1 0 3.1415926535897931 3 180 22
+76 15 75 16 Part_Spherical_1 17 Part_Spherical_10 0 2 26
+77 22 76 14 AutomaticPoint 6 center 0 22 76 26 77 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+78 22 76 14 AutomaticPoint 2 up 0 22 76 26 78 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+79 15 75 16 Part_Spherical_2 17 Part_Spherical_10 0 2 26
+80 29 79 14 AutomaticPoint 6 center 0 29 79 26 80 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+81 29 79 14 AutomaticPoint 2 up 0 29 79 26 81 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 76 26 77 26 78 29 79 26 80 26 81 15
+82 9 Spherical 12 Spherical_11 3 52 15 82 3 16 15 82 3 0.29999999999999999 -2 -0.5 3 0.3 1 Y 4 -0.5 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 22
+83 15 82 16 Part_Spherical_1 17 Part_Spherical_11 0 2 26
+84 22 83 14 AutomaticPoint 6 center 0 22 83 26 84 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+85 22 83 14 AutomaticPoint 2 up 0 22 83 26 85 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+86 15 82 16 Part_Spherical_2 17 Part_Spherical_11 0 2 26
+87 29 86 14 AutomaticPoint 6 center 0 29 86 26 87 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+88 29 86 14 AutomaticPoint 2 up 0 29 86 26 88 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 83 26 84 26 85 29 86 26 87 26 88 15
+89 9 Spherical 12 Spherical_12 3 52 15 89 3 15 15 89 3 0.69999999999999996 -2 -0.5 3 0.7 1 Y 4 -0.5 3 0 1 0 6.123233995736766e-17 3 0 1 0 1 0 1 1 1 0 3.1415926535897931 3 180 22
+90 15 89 16 Part_Spherical_1 17 Part_Spherical_12 0 2 26
+91 22 90 14 AutomaticPoint 6 center 0 22 90 26 91 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+92 22 90 14 AutomaticPoint 2 up 0 22 90 26 92 3 0.20000000000000001 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 29
+93 15 89 16 Part_Spherical_2 17 Part_Spherical_12 0 2 26
+94 29 93 14 AutomaticPoint 6 center 0 29 93 26 94 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+95 29 93 14 AutomaticPoint 2 up 0 29 93 26 95 3 -0.14999999999999999 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 22 90 26 91 26 92 29 93 26 94 26 95 34 50 OpenMeca::Item::LinkT<OpenMeca::Item::LinearMotor> 1 0
+96 11 LinearMotor 13 LinearMotor_1 3 1 34 96 3 0 34 96 3 0 0 1 1 0 1 0 1 1 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 35 1 0
+97 34 96 18 Part_LinearMotor_1 18 Part_LinearMotor_1 0 1 26
+98 35 97 14 AutomaticPoint 6 middle 0 35 97 26 98 3 0 0 0 3 0 0 0 1 1 3 0 0 0 36 1 0
+99 34 96 18 Part_LinearMotor_2 18 Part_LinearMotor_1 0 3 26
+100 36 99 14 AutomaticPoint 4 left 0 36 99 26 100 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+101 36 99 14 AutomaticPoint 6 middle 0 36 99 26 101 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+102 36 99 14 AutomaticPoint 5 right 0 36 99 26 102 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 0 0 0 1 6 sin(t) 0 35 97 26 98 36 99 26 100 26 101 26 102 34
+103 11 LinearMotor 13 LinearMotor_2 3 2 34 103 3 0 34 103 3 -1 0 -1 2 -1 1 0 2 -1 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 35
+104 34 103 18 Part_LinearMotor_1 18 Part_LinearMotor_2 0 1 26
+105 35 104 14 AutomaticPoint 6 middle 0 35 104 26 105 3 0 0 0 3 0 0 0 1 1 3 0 0 0 36
+106 34 103 18 Part_LinearMotor_2 18 Part_LinearMotor_2 0 3 26
+107 36 106 14 AutomaticPoint 4 left 0 36 106 26 107 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+108 36 106 14 AutomaticPoint 6 middle 0 36 106 26 108 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+109 36 106 14 AutomaticPoint 5 right 0 36 106 26 109 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 10 sin(t)*0.6 0 35 104 26 105 36 106 26 107 26 108 26 109 39 45 OpenMeca::Item::LinkT<OpenMeca::Item::Slider> 1 0
+110 6 Slider 8 Slider_1 3 3 39 110 3 0 39 110 3 1 0 -1 1 1 1 0 2 -1 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 40 1 0
+111 39 110 13 Part_Slider_1 13 Part_Slider_1 0 1 26
+112 40 111 14 AutomaticPoint 6 middle 0 40 111 26 112 3 0 0 0 3 0 0 0 1 1 3 0 0 0 41 1 0
+113 39 110 13 Part_Slider_2 13 Part_Slider_1 0 3 26
+114 41 113 14 AutomaticPoint 4 left 0 41 113 26 114 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+115 41 113 14 AutomaticPoint 6 middle 0 41 113 26 115 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+116 41 113 14 AutomaticPoint 5 right 0 41 113 26 116 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 0 0 40 111 26 112 41 113 26 114 26 115 26 116 3
+117 4 Body 6 Body_1 44 220 98 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 39
+118 6 Slider 8 Slider_2 3 0 39 118 3 117 39 118 3 0 10 0 1 0 2 10 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 40
+119 39 118 13 Part_Slider_1 13 Part_Slider_2 0 1 26
+120 40 119 14 AutomaticPoint 6 middle 0 40 119 26 120 3 0 0 0 3 0 0 0 1 1 3 0 0 0 41
+121 39 118 13 Part_Slider_2 13 Part_Slider_2 0 3 26
+122 41 121 14 AutomaticPoint 4 left 0 41 121 26 122 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+123 41 121 14 AutomaticPoint 6 middle 0 41 121 26 123 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+124 41 121 14 AutomaticPoint 5 right 0 41 121 26 124 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 40 119 26 120 41 121 26 122 26 123 26 124 43 45 OpenMeca::Item::LinkT<OpenMeca::Item::Planar> 1 0
+125 6 Planar 8 Planar_1 3 117 43 125 3 52 43 125 3 0 9 0 1 0 1 9 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 44 1 0
+126 43 125 13 Part_Planar_1 13 Part_Planar_1 0 1 26
+127 44 126 14 AutomaticPoint 6 middle 0 44 126 26 127 3 0 0 0 3 0 0 0 1 1 3 0 0 0 45 1 0
+128 43 125 13 Part_Planar_2 13 Part_Planar_1 0 1 26
+129 45 128 14 AutomaticPoint 6 middle 0 45 128 26 129 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 44 126 26 127 45 128 26 129 47 32 OpenMeca::Item::PartUserJunction 1 0
+130 26 95 8 Junction 10 Junction_1 0 26 95 47 130 3 0 0 0 3 0 -0.19064151117240255 0.76256604468960998 0.61818188399883289 0 0 26 44 47 130 47
+131 26 88 8 Junction 10 Junction_2 0 26 88 47 131 3 0 0 0 3 -0 0.14993112962179481 0.59972451848717923 0.78603508719118487 26 51 47 131 47
+132 26 59 8 Junction 10 Junction_3 0 26 59 47 132 3 0 0 0 3 -0 0.17149858514250882 0.68599434057003528 0.70710678118654757 26 11 47 132 47
+133 26 67 8 Junction 10 Junction_4 0 26 67 47 133 3 0 0 0 3 0 -0.17149858514250882 0.68599434057003528 0.70710678118654757 26 23 47 133 47
+134 26 74 8 Junction 10 Junction_5 0 26 74 47 134 3 0 0 0 3 -0 0.19064151117240249 0.76256604468960998 0.61818188399883289 26 30 47 134 47
+135 26 37 8 Junction 10 Junction_6 0 26 37 47 135 3 0 0 0 3 0 0.19064151117240247 -0.76256604468960998 0.61818188399883289 26 81 47 135 49 29 OpenMeca::Item::PartUserPoint 1 1
+136 3 52
+137 5 Point 7 Point_1 0 3 52 49 136 3 0 -2 0.5 3 0 0 0 1 0 3 0 0 0 3 0 -2 0.5 1 0 1 Y 3 0.5 49
+138 3 52
+139 5 Point 7 Point_2 0 3 52 49 138 3 -0.5 -2 -0.5 3 0 0 0 1 0 3 0 0 0 3 -0.5 -2 -0.5 4 -0.5 1 Y 4 -0.5 49
+140 3 52
+141 5 Point 7 Point_3 0 3 52 49 140 3 0.5 -2 -0.5 3 0 0 0 1 0 3 0 0 0 3 0.5 -2 -0.5 3 0.5 1 Y 4 -0.5 47
+142 49 136 8 Junction 10 Junction_7 0 49 136 47 142 3 0 0 0 3 -0 0.85065080443503771 0 0.52573111845697618 49 138 47 142 47
+143 49 138 8 Junction 10 Junction_8 0 49 138 47 143 3 0 0 0 3 -0 0 0 1 49 140 47 143 47
+144 49 140 8 Junction 10 Junction_9 0 49 140 47 144 3 0 0 0 3 0 -0.85065080443503771 0 0.52573111845697618 49 136 47 144 49
+145 3 52
+146 5 Point 7 Point_4 0 3 52 49 145 3 0 -2 -0.10000000000000001 3 0 0 0 1 0 3 0 0 0 3 0 -2 -0.10000000000000001 1 0 1 Y 4 -0.1 50 63 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder> 1 0
+147 49 145 0 0 8 Cylinder 10 Cylinder_1 0 49 145 50 147 3 0 -2 -0.10000000000000001 3 0 0 0.70710678118654746 0.70710678118654757 0 0 0.40000000000000002 0.01 3 0 1 0 0 53 28 OpenMeca::Item::PartUserPipe 1 0
+148 26 114 4 Pipe 6 Pipe_1 0 26 114 53 148 3 1 0.5 -1 3 0 0 0.70710678118654746 0.70710678118654757 3 0 1 0 1 26
+149 53 148 14 AutomaticPoint 16 AutomaticPoint_1 0 53 148 26 149 3 1 0 0 3 0 0 0 1 0 3 0 0 0 26 149 53
+150 26 107 4 Pipe 6 Pipe_2 0 26 107 53 150 3 -1 0.5 -1 3 0 0 0.70710678118654746 0.70710678118654757 3 0 1 0 1 26
+151 53 150 14 AutomaticPoint 16 AutomaticPoint_2 0 53 150 26 151 3 1 0 0 3 0 0 0 1 0 3 0 0 0 26 151 53
+152 26 100 4 Pipe 6 Pipe_3 0 26 100 53 152 3 0 0.5 0.99999999999999989 3 0 0 0.70710678118654746 0.70710678118654757 3 0 1 0 1 26
+153 53 152 14 AutomaticPoint 16 AutomaticPoint_3 0 53 152 26 153 3 1 0 0 3 0 0 0 1 0 3 0 0 0 26 153 54 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground> 1 0
+154 26 151 6 Ground 8 Ground_1 0 26 151 54 154 3 -0.99999999999999978 1.5 -1 3 0 0 0.70710678118654746 0.70710678118654757 0 0 3 0 1 0 0 54
+155 26 149 6 Ground 8 Ground_2 0 26 149 54 155 3 1.0000000000000002 1.5 -1 3 0 0 0.70710678118654746 0.70710678118654757 3 0 1 0 0 54
+156 26 153 6 Ground 8 Ground_3 0 26 153 54 156 3 2.2204460492503131e-16 1.5 0.99999999999999989 3 0 0 0.70710678118654746 0.70710678118654757 3 0 1 0 0 4 7 Gravity 3 0 0 0 6 Scales 8 19 AngularAcceleration 1 15 AngularVelocity 1 5 Force 1 5 Frame 1 18 LinearAcceleration 1 14 LinearVelocity 1 4 Part 1 6 Torque 1 5 Scene 0 128 128 128 255 3 0 0 0 5 0 10 Simulation 0.00050000000000000001 60 0.10000000000000001
diff --git a/SRC/OpenMeca/Rsc/Example/robot.omc b/SRC/OpenMeca/Rsc/Example/robot.omc
new file mode 100644
index 0000000..d7b057d
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Example/robot.omc
@@ -0,0 +1,203 @@
+22 serialization::archive 9 0 2 0 0 6  2.1.0 2 1 0 0 0 199 3 20 OpenMeca::Item::Body 1 3
+0 0 0 0 0 0 0 4 Body 6 ground 0 0 0 0 0 255 1 0 0 0 0 0 0 0 0 3 0.20000000000000001 0 0 0 0 3 0.2 1 0 1 0 0 0 3 0 0 0 1 0 0 3 0.10000000000000001 0 0 3 0 0.10000000000000001 0 3 0 0 0.10000000000000001 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 1 3
+1 4 Body 5 wheel 169 222 193 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 1 3
+2 4 Body 7 Body_13 153 231 11 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+3 4 Body 7 Body_14 35 120 189 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 44 OpenMeca::Item::LinkT<OpenMeca::Item::Motor> 1 0
+4 0 2 5 Motor 1 A 0 0 3 0 15 4 3 1 15 4 3 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 0 0 3 1 0 0 1 1 1 0 1 0 0 0 0 1 0 22 1 0
+5 15 4 0 0 0 0 12 Part_Motor_1 6 Part_A 0 0 0 3 26 1 0
+6 22 5 0 0 14 AutomaticPoint 4 left 0 0 0 22 5 26 6 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+7 22 5 14 AutomaticPoint 6 middle 0 22 5 26 7 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+8 22 5 14 AutomaticPoint 5 right 0 22 5 26 8 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 29 1 0
+9 15 4 12 Part_Motor_2 6 Part_A 0 1 26
+10 29 9 14 AutomaticPoint 6 middle 0 29 9 26 10 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 1 0 0 0 1 2 10 10 22 5 26 6 26 7 26 8 29 9 26 10 33 47 OpenMeca::Item::LinkT<OpenMeca::Item::Revolute> 1 0
+11 8 Revolute 5 B1(0) 3 2 33 11 3 1 33 11 3 0 0.20000000000000001 0 1 0 1 R 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34 1 0
+12 33 11 15 Part_Revolute_1 10 Part_B1(0) 0 3 26
+13 34 12 14 AutomaticPoint 4 left 0 34 12 26 13 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+14 34 12 14 AutomaticPoint 6 middle 0 34 12 26 14 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+15 34 12 14 AutomaticPoint 5 right 0 34 12 26 15 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35 1 0
+16 33 11 15 Part_Revolute_2 10 Part_B1(0) 0 1 26
+17 35 16 14 AutomaticPoint 6 middle 0 35 16 26 17 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 34 12 26 13 26 14 26 15 35 16 26 17 33
+18 8 Revolute 5 D1(0) 3 0 33 18 3 3 33 18 3 -1 0 0 2 -L 1 0 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+19 33 18 15 Part_Revolute_1 10 Part_D1(0) 0 3 26
+20 34 19 14 AutomaticPoint 4 left 0 34 19 26 20 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+21 34 19 14 AutomaticPoint 6 middle 0 34 19 26 21 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+22 34 19 14 AutomaticPoint 5 right 0 34 19 26 22 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+23 33 18 15 Part_Revolute_2 10 Part_D1(0) 0 1 26
+24 35 23 14 AutomaticPoint 6 middle 0 35 23 26 24 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 19 26 20 26 21 26 22 35 23 26 24 33
+25 8 Revolute 2 C1 3 2 33 25 3 3 33 25 3 -1.1288444942955247 0.99166481045246857 0 16 -L + L1*cos(th1) 11 L1*sin(th1) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+26 33 25 15 Part_Revolute_1 7 Part_C1 0 3 26
+27 34 26 14 AutomaticPoint 4 left 0 34 26 26 27 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+28 34 26 14 AutomaticPoint 6 middle 0 34 26 26 28 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+29 34 26 14 AutomaticPoint 5 right 0 34 26 26 29 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+30 33 25 15 Part_Revolute_2 7 Part_C1 0 1 26
+31 35 30 14 AutomaticPoint 6 middle 0 35 30 26 31 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 26 26 27 26 28 26 29 35 30 26 31 37 32 OpenMeca::Item::PartUserJunction 1 0
+32 26 15 8 Junction 10 Junction_1 0 26 15 37 32 3 0 0 0 3 0 -0 0.95360617440350881 0.30105691179493732 0 0 26 29 37 32 37
+33 26 13 8 Junction 10 Junction_2 0 26 13 37 33 3 0 0 0 3 0 -0 0.95360617440350881 0.30105691179493732 26 27 37 33 37
+34 26 10 8 Junction 10 Junction_3 0 26 10 37 34 3 0 0 0 3 0 0 0.70710678118654746 0.70710678118654757 26 17 37 34 37
+35 26 8 8 Junction 10 Junction_4 0 26 8 37 35 3 0 0 0 3 -0 0 1 6.123233995736766e-17 26 22 37 35 37
+36 26 6 8 Junction 10 Junction_5 0 26 6 37 36 3 0 0 0 3 -0 0 1 6.123233995736766e-17 26 20 37 36 3
+37 4 Body 7 Body_15 6 166 186 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+38 4 Body 7 Body_16 133 206 152 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+39 4 Body 7 Body_17 99 135 5 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 33
+40 8 Revolute 2 G1 3 37 33 40 3 3 33 40 3 -1.3966659241809873 -0.051537797718209877 0 23 -L - L2*cos(th1-(pi/2)) 19 -L2*sin(th1-(pi/2)) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+41 33 40 15 Part_Revolute_1 7 Part_G1 0 3 26
+42 34 41 14 AutomaticPoint 4 left 0 34 41 26 42 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+43 34 41 14 AutomaticPoint 6 middle 0 34 41 26 43 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+44 34 41 14 AutomaticPoint 5 right 0 34 41 26 44 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+45 33 40 15 Part_Revolute_2 7 Part_G1 0 1 26
+46 35 45 14 AutomaticPoint 6 middle 0 35 45 26 46 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 41 26 42 26 43 26 44 35 45 26 46 33
+47 8 Revolute 2 F1 3 37 33 47 3 38 33 47 3 -1.2033991827377004 -1.5390350133969126 0 36 -L - L2*cos(th1-(pi/2))- L3*cos(th1) 32 -L2*sin(th1-(pi/2)) -L3*sin(th1) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+48 33 47 15 Part_Revolute_1 7 Part_F1 0 3 26
+49 34 48 14 AutomaticPoint 4 left 0 34 48 26 49 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+50 34 48 14 AutomaticPoint 6 middle 0 34 48 26 50 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+51 34 48 14 AutomaticPoint 5 right 0 34 48 26 51 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+52 33 47 15 Part_Revolute_2 7 Part_F1 0 1 26
+53 35 52 14 AutomaticPoint 6 middle 0 35 52 26 53 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 48 26 49 26 50 26 51 35 52 26 53 37
+54 26 24 8 Junction 10 Junction_6 0 26 24 37 54 3 0 0 0 3 0 -0 0.75128040919335504 0.65998314127124869 26 31 37 54 37
+55 26 24 8 Junction 10 Junction_7 0 26 24 37 55 3 0 0 0 3 0 -0 -0.9979140270454816 0.064556909977707813 26 46 37 55 37
+56 26 46 8 Junction 10 Junction_8 0 26 46 37 56 3 0 0 0 3 0 0 0.61291686798912237 0.79014739949860291 26 31 37 56 37
+57 26 44 8 Junction 10 Junction_9 0 26 44 37 57 3 0 0 0 3 0 0 -0.65998314127124857 0.75128040919335515 26 51 37 57 37
+58 26 42 8 Junction 11 Junction_10 0 26 42 37 58 3 0 0 0 3 0 0 -0.65998314127124857 0.75128040919335515 26 49 37 58 33
+59 8 Revolute 5 D1(1) 3 39 33 59 3 3 33 59 3 -1 0 0 2 -L 1 0 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+60 33 59 15 Part_Revolute_1 10 Part_D1(1) 0 3 26
+61 34 60 14 AutomaticPoint 4 left 0 34 60 26 61 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+62 34 60 14 AutomaticPoint 6 middle 0 34 60 26 62 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+63 34 60 14 AutomaticPoint 5 right 0 34 60 26 63 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+64 33 59 15 Part_Revolute_2 10 Part_D1(1) 0 1 26
+65 35 64 14 AutomaticPoint 6 middle 0 35 64 26 65 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 60 26 61 26 62 26 63 35 64 26 65 33
+66 8 Revolute 5 E1(0) 3 39 33 66 3 38 33 66 3 -0.80673325855671307 -1.4874972156787027 0 16 -L - L3*cos(th1) 12 -L3*sin(th1) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+67 33 66 15 Part_Revolute_1 10 Part_E1(0) 0 3 26
+68 34 67 14 AutomaticPoint 4 left 0 34 67 26 68 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+69 34 67 14 AutomaticPoint 6 middle 0 34 67 26 69 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+70 34 67 14 AutomaticPoint 5 right 0 34 67 26 70 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+71 33 66 15 Part_Revolute_2 10 Part_E1(0) 0 1 26
+72 35 71 14 AutomaticPoint 6 middle 0 35 71 26 72 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 67 26 68 26 69 26 70 35 71 26 72 37
+73 26 63 8 Junction 11 Junction_11 0 26 63 37 73 3 0 0 0 3 0 0 -0.65998314127124857 0.75128040919335515 26 70 37 73 37
+74 26 61 8 Junction 11 Junction_12 0 26 61 37 74 3 0 0 0 3 0 0 -0.65998314127124857 0.75128040919335515 26 68 37 74 37
+75 26 53 8 Junction 11 Junction_14 0 26 53 37 75 3 0 0 0 3 0 0 0.064556909977707827 0.9979140270454816 26 72 37 75 33
+76 8 Revolute 5 B4(0) 3
+77 4 Body 7 Body_43 28 169 162 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 33 76 3 1 33 76 3 0 -0.20000000000000001 0 1 0 2 -R 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+78 33 76 15 Part_Revolute_1 10 Part_B4(0) 0 3 26
+79 34 78 14 AutomaticPoint 4 left 0 34 78 26 79 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+80 34 78 14 AutomaticPoint 6 middle 0 34 78 26 80 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+81 34 78 14 AutomaticPoint 5 right 0 34 78 26 81 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+82 33 76 15 Part_Revolute_2 10 Part_B4(0) 0 1 26
+83 35 82 14 AutomaticPoint 6 middle 0 35 82 26 83 3 0 0 0 3 0 0 0 1 1 3 0 0 0 3 77 34 78 26 79 26 80 26 81 35 82 26 83 3
+84 4 Body 7 Body_44 138 140 39 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+85 4 Body 7 Body_45 89 95 52 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+86 4 Body 7 Body_46 167 136 86 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+87 4 Body 7 Body_47 199 175 226 255 0.01 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 0.01 0 0 3 0 0.01 0 3 0 0 0.01 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 33
+88 8 Revolute 5 D4(0) 3 0 33 88 3 84 33 88 3 1 0 0 1 L 1 0 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+89 33 88 15 Part_Revolute_1 10 Part_D4(0) 0 3 26
+90 34 89 14 AutomaticPoint 4 left 0 34 89 26 90 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+91 34 89 14 AutomaticPoint 6 middle 0 34 89 26 91 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+92 34 89 14 AutomaticPoint 5 right 0 34 89 26 92 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+93 33 88 15 Part_Revolute_2 10 Part_D4(0) 0 1 26
+94 35 93 14 AutomaticPoint 6 middle 0 35 93 26 94 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 89 26 90 26 91 26 92 35 93 26 94 33
+95 8 Revolute 2 C4 3 77 33 95 3 84 33 95 3 0.63764224552332638 0.99166481045246857 0 15 L - L1*cos(th2) 11 L1*sin(th1) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+96 33 95 15 Part_Revolute_1 7 Part_C4 0 3 26
+97 34 96 14 AutomaticPoint 4 left 0 34 96 26 97 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+98 34 96 14 AutomaticPoint 6 middle 0 34 96 26 98 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+99 34 96 14 AutomaticPoint 5 right 0 34 96 26 99 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+100 33 95 15 Part_Revolute_2 7 Part_C4 0 1 26
+101 35 100 14 AutomaticPoint 6 middle 0 35 100 26 101 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 96 26 97 26 98 26 99 35 100 26 101 33
+102 8 Revolute 2 G4 3 85 33 102 3 84 33 102 3 1.3728156343868907 0.14494310179066944 0 22 L + L2*cos(th2-(pi/2)) 19 -L2*sin(th2-(pi/2)) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+103 33 102 15 Part_Revolute_1 7 Part_G4 0 3 26
+104 34 103 14 AutomaticPoint 4 left 0 34 103 26 104 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+105 34 103 14 AutomaticPoint 6 middle 0 34 103 26 105 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+106 34 103 14 AutomaticPoint 5 right 0 34 103 26 106 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+107 33 102 15 Part_Revolute_2 7 Part_G4 0 1 26
+108 35 107 14 AutomaticPoint 6 middle 0 35 107 26 108 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 103 26 104 26 105 26 106 35 107 26 108 37
+109 26 79 8 Junction 11 Junction_43 0 26 79 37 109 3 0 0 0 3 0 0 0.51391129010003633 0.85784333412792591 26 97 37 109 37
+110 26 81 8 Junction 11 Junction_44 0 26 81 37 110 3 0 0 0 3 0 0 0.51391129010003633 0.85784333412792591 26 99 37 110 37
+111 26 94 8 Junction 11 Junction_45 0 26 94 37 111 3 0 0 0 3 0 -0 0.81951466740712597 0.57305820812949515 26 101 37 111 37
+112 26 101 8 Junction 11 Junction_46 0 26 101 37 112 3 0 0 0 3 0 0 -0.4149598009553358 0.90983974610428409 26 108 37 112 37
+113 26 108 8 Junction 11 Junction_47 0 26 108 37 113 3 0 0 0 3 0 -0 -0.98286293136076019 0.1843378912674592 26 94 37 113 33
+114 8 Revolute 2 F4 3 85 33 114 3 86 33 114 3 1.9163522661019012 -1.2531155271601699 0 35 L + L2*cos(th2-(pi/2))+ L3*cos(th2) 32 -L2*sin(th2-(pi/2)) -L3*sin(th2) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+115 33 114 15 Part_Revolute_1 7 Part_F4 0 3 26
+116 34 115 14 AutomaticPoint 4 left 0 34 115 26 116 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+117 34 115 14 AutomaticPoint 6 middle 0 34 115 26 117 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+118 34 115 14 AutomaticPoint 5 right 0 34 115 26 118 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+119 33 114 15 Part_Revolute_2 7 Part_F4 0 1 26
+120 35 119 14 AutomaticPoint 6 middle 0 35 119 26 120 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 115 26 116 26 117 26 118 35 119 26 120 37
+121 26 106 8 Junction 11 Junction_48 0 26 106 37 121 3 0 0 0 3 -0 0.70710678118654746 0 0.70710678118654757 26 104 37 121 37
+122 26 104 8 Junction 11 Junction_49 0 26 104 37 122 3 0 0 0 3 0 0 -0.56464247990095562 0.82533561045873871 26 116 37 122 37
+123 26 106 8 Junction 11 Junction_50 0 26 106 37 123 3 0 0 0 3 0 0 -0.56464247990095562 0.82533561045873871 26 118 37 123 33
+124 8 Revolute 5 D4(1) 3 87 33 124 3 84 33 124 3 1 0 0 1 L 1 0 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+125 33 124 15 Part_Revolute_1 10 Part_D4(1) 0 3 26
+126 34 125 14 AutomaticPoint 4 left 0 34 125 26 126 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+127 34 125 14 AutomaticPoint 6 middle 0 34 125 26 127 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+128 34 125 14 AutomaticPoint 5 right 0 34 125 26 128 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+129 33 124 15 Part_Revolute_2 10 Part_D4(1) 0 1 26
+130 35 129 14 AutomaticPoint 6 middle 0 35 129 26 130 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 125 26 126 26 127 26 128 35 129 26 130 33
+131 8 Revolute 5 E4(0) 3 87 33 131 3 86 33 131 3 1.5435366317150105 -1.3980586289508394 0 15 L + L3*cos(th2) 12 -L3*sin(th2) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+132 33 131 15 Part_Revolute_1 10 Part_E4(0) 0 3 26
+133 34 132 14 AutomaticPoint 4 left 0 34 132 26 133 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+134 34 132 14 AutomaticPoint 6 middle 0 34 132 26 134 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+135 34 132 14 AutomaticPoint 5 right 0 34 132 26 135 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+136 33 131 15 Part_Revolute_2 10 Part_E4(0) 0 1 26
+137 35 136 14 AutomaticPoint 6 middle 0 35 136 26 137 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 132 26 133 26 134 26 135 35 136 26 137 37
+138 26 133 8 Junction 11 Junction_51 0 26 133 37 138 3 0 0 0 3 0 -0 0.82533561045873882 0.56464247990095562 26 126 37 138 37
+139 26 128 8 Junction 11 Junction_52 0 26 128 37 139 3 0 0 0 3 0 0 -0.56464247990095562 0.82533561045873871 26 135 37 139 37
+140 26 120 8 Junction 11 Junction_53 0 26 120 37 140 3 0 0 0 3 0 -0 -0.98286293136076019 0.1843378912674592 26 137 37 140 39 24 OpenMeca::Item::Variable 1 0
+141 8 Variable 7 R = 0.2 0 0 1 R 0.20000000000000001 39
+142 8 Variable 5 L = 1 1 L 1 39
+143 8 Variable 6 L1 = 1 2 L1 1 39
+144 8 Variable 9 th1 = 1.7 3 th1 1.7 39
+145 8 Variable 8 L2 = 0.4 2 L2 0.40000000000000002 39
+146 8 Variable 8 L3 = 1.5 2 L3 1.5 39
+147 8 Variable 9 th2 = 1.2 3 th2 1.2 3
+148 4 Body 7 Body_18 133 243 98 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+149 4 Body 7 Body_48 130 177 36 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 33
+150 8 Revolute 5 B1(1) 3 148 33 150 3 1 33 150 3 0 0.20000000000000001 0 1 0 1 R 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+151 33 150 15 Part_Revolute_1 10 Part_B1(1) 0 3 26
+152 34 151 14 AutomaticPoint 4 left 0 34 151 26 152 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+153 34 151 14 AutomaticPoint 6 middle 0 34 151 26 153 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+154 34 151 14 AutomaticPoint 5 right 0 34 151 26 154 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+155 33 150 15 Part_Revolute_2 10 Part_B1(1) 0 1 26
+156 35 155 14 AutomaticPoint 6 middle 0 35 155 26 156 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 151 26 152 26 153 26 154 35 155 26 156 33
+157 8 Revolute 5 E1(1) 3 148 33 157 3 38 33 157 3 -0.80673325855671307 -1.4874972156787027 0 16 -L - L3*cos(th1) 12 -L3*sin(th1) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+158 33 157 15 Part_Revolute_1 10 Part_E1(1) 0 3 26
+159 34 158 14 AutomaticPoint 4 left 0 34 158 26 159 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+160 34 158 14 AutomaticPoint 6 middle 0 34 158 26 160 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+161 34 158 14 AutomaticPoint 5 right 0 34 158 26 161 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+162 33 157 15 Part_Revolute_2 10 Part_E1(1) 0 1 26
+163 35 162 14 AutomaticPoint 6 middle 0 35 162 26 163 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 158 26 159 26 160 26 161 35 162 26 163 37
+164 26 161 8 Junction 11 Junction_57 0 26 161 37 164 3 0 0 0 3 0 0 0.5332393587507106 0.8459644119459937 26 154 37 164 37
+165 26 159 8 Junction 11 Junction_58 0 26 159 37 165 3 0 0 0 3 0 0 0.5332393587507106 0.8459644119459937 26 152 37 165 33
+166 8 Revolute 5 B4(1) 3 149 33 166 3 1 33 166 3 0 -0.20000000000000001 0 1 0 2 -R 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+167 33 166 15 Part_Revolute_1 10 Part_B4(1) 0 3 26
+168 34 167 14 AutomaticPoint 4 left 0 34 167 26 168 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+169 34 167 14 AutomaticPoint 6 middle 0 34 167 26 169 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+170 34 167 14 AutomaticPoint 5 right 0 34 167 26 170 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+171 33 166 15 Part_Revolute_2 10 Part_B4(1) 0 1 26
+172 35 171 14 AutomaticPoint 6 middle 0 35 171 26 172 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 167 26 168 26 169 26 170 35 171 26 172 33
+173 8 Revolute 5 E4(1) 3 149 33 173 3 86 33 173 3 1.5435366317150105 -1.3980586289508394 0 15 L + L3*cos(th2) 12 -L3*sin(th2) 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34
+174 33 173 15 Part_Revolute_1 10 Part_E4(1) 0 3 26
+175 34 174 14 AutomaticPoint 4 left 0 34 174 26 175 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+176 34 174 14 AutomaticPoint 6 middle 0 34 174 26 176 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+177 34 174 14 AutomaticPoint 5 right 0 34 174 26 177 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 35
+178 33 173 15 Part_Revolute_2 10 Part_E4(1) 0 1 26
+179 35 178 14 AutomaticPoint 6 middle 0 35 178 26 179 3 0 0 0 3 0 0 0 1 1 3 0 0 0 34 174 26 175 26 176 26 177 35 178 26 179 37
+180 26 177 8 Junction 11 Junction_59 0 26 177 37 180 3 0 0 0 3 0 -0 0.94603499035714411 0.32406449515483488 26 170 37 180 37
+181 26 175 8 Junction 11 Junction_60 0 26 175 37 181 3 0 0 0 3 0 -0 0.94603499035714411 0.32406449515483488 26 168 37 181 3
+182 4 Body 4 wall 216 208 130 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 1 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 41 29 OpenMeca::Item::PartUserPoint 1 1
+183 3 182
+184 5 Point 7 Point_1 0 3 182 41 183 3 0 -2.1499999999999999 0 3 0 0 0 1 0 3 0 0 0 3 0 -2.1499999999999999 0 1 0 5 -2.15 1 0 42 58 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Box> 1 0
+185 41 183 0 0 3 Box 5 Box_1 0 41 183 42 185 3 0 -2.1499999999999999 0 3 0 0 0 1 0 0 100 0.10000000000000001 10 3 0 0 0 1 1 45 49 OpenMeca::Item::LinkT<OpenMeca::Item::PointPlane> 1 0
+186 10 PointPlane 12 PointPlane_1 3 0 45 186 3 182 45 186 3 0 8 0 1 0 1 8 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 46 1 0
+187 45 186 17 Part_PointPlane_1 17 Part_PointPlane_1 0 1 26
+188 46 187 14 AutomaticPoint 6 middle 0 46 187 26 188 3 0 0 0.20000000000000001 3 0 0 0 1 1 3 0 0 0.20000000000000001 47 1 0
+189 45 186 17 Part_PointPlane_2 17 Part_PointPlane_1 0 1 26
+190 47 189 14 AutomaticPoint 6 middle 0 47 189 26 190 3 0 0 -0.01 3 0 0 0 1 1 3 0 0 -0.01 0 0 46 187 26 188 47 189 26 190 41
+191 3 38
+192 5 Point 7 Point_2 0 3 38 41 191 3 -1.1389769355899382 -2.034867418623147 0 3 0 0 0 1 0 3 0 0 0 3 -1.1389769355899382 -2.034867418623147 0 49 -L - L2*cos(th1-(pi/2))- L3*cos(th1) - p*cos(th1) 45 -L2*sin(th1-(pi/2)) -L3*sin(th1) - p*sin(th1) 1 0 39
+193 8 Variable 7 p = 0.5 1 p 0.5 41
+194 3 86
+195 5 Point 7 Point_3 0 3 86 41 194 3 2.0975311433402379 -1.7191350701437831 0 3 0 0 0 1 0 3 0 0 0 3 2.0975311433402379 -1.7191350701437831 0 49 L + L2*cos(th2-(pi/2)) + L3*cos(th2) + p*cos(th2) 45 -L2*sin(th2-(pi/2)) -L3*sin(th2) - p*sin(th2) 1 0 37
+196 41 191 8 Junction 11 Junction_61 0 41 191 37 196 3 0 0 0 3 0 -0 0.75128040919335504 0.65998314127124869 26 53 37 196 37
+197 41 194 8 Junction 11 Junction_62 0 41 194 37 197 3 0 0 0 3 0 -0 0.82533561045873871 0.56464247990095562 26 120 37 197 49 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Sphere> 1 0
+198 41 191 6 Sphere 8 Sphere_1 0 41 191 49 198 3 -1.1389769355899382 -2.034867418623147 0 3 0 0 0 1 0 0 0.050000000000000003 1 49
+199 41 194 6 Sphere 8 Sphere_2 0 41 194 49 199 3 2.0975311433402379 -1.7191350701437831 0 3 0 0 0 1 0.050000000000000003 1 51 40 OpenMeca::Item::How::GetLinPos::MySensor 1 0
+200 41 194 0 0 0 0 21 Sensor at LinearPosition 23 Sensor at LinearPosition_1 0 51
+201 41 191 21 Sensor at LinearPosition 23 Sensor at LinearPosition_2 0 4 7 Gravity 3 0 -10 0 6 Scales 8 19 AngularAcceleration 1 15 AngularVelocity 1 5 Force 1 5 Frame 2.25 18 LinearAcceleration 1 14 LinearVelocity 1 4 Part 1 6 Torque 1 5 Scene 0 171 171 171 255 3 0 0 0 5 1 10 Simulation 0.0001 60 0.01
diff --git a/SRC/OpenMeca/Rsc/Example/screw.omc b/SRC/OpenMeca/Rsc/Example/screw.omc
new file mode 100644
index 0000000..d354229
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Example/screw.omc
@@ -0,0 +1,36 @@
+22 serialization::archive 9 0 2 0 0 6  2.1.1 2 1 1 0 0 35 3 20 OpenMeca::Item::Body 1 3
+0 0 0 0 0 0 0 4 Body 6 ground 0 0 93 93 93 255 1 0 0 0 0 0 0 0 0 3 0 0 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 3 1 0 0 3 0 1 0 3 0 0 1 1 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+1 4 Body 4 axis 122 90 144 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 44 OpenMeca::Item::LinkT<OpenMeca::Item::Motor> 1 0
+2 0 2 5 Motor 7 Motor_1 0 0 3 1 15 2 3 0 15 2 3 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 0 0 3 1 0 0 1 1 1 0 1 0 0 0 0 1 0 22 1 0
+3 15 2 0 0 0 0 12 Part_Motor_1 12 Part_Motor_1 0 0 0 3 26 1 0
+4 22 3 0 0 14 AutomaticPoint 4 left 0 0 0 22 3 26 4 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+5 22 3 14 AutomaticPoint 6 middle 0 22 3 26 5 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+6 22 3 14 AutomaticPoint 5 right 0 22 3 26 6 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 29 1 0
+7 15 2 12 Part_Motor_2 12 Part_Motor_1 0 1 26
+8 29 7 14 AutomaticPoint 6 middle 0 29 7 26 8 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 1 0 0 0 1 2 -1 -1 22 3 26 4 26 5 26 6 29 7 26 8 3
+9 4 Body 5 screw 155 92 38 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 33 44 OpenMeca::Item::LinkT<OpenMeca::Item::Screw> 1 0
+10 5 Screw 7 Screw_1 3 9 33 10 3 1 33 10 3 0 0 1 1 0 1 0 1 1 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 34 1 0
+11 33 10 12 Part_Screw_1 12 Part_Screw_1 0 1 26
+12 34 11 14 AutomaticPoint 6 middle 0 34 11 26 12 3 0 0 0 3 0 0 0 1 1 3 0 0 0 35 1 0
+13 33 10 12 Part_Screw_2 12 Part_Screw_1 0 3 26
+14 35 13 14 AutomaticPoint 4 left 0 35 13 26 14 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+15 35 13 14 AutomaticPoint 6 middle 0 35 13 26 15 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+16 35 13 14 AutomaticPoint 5 right 0 35 13 26 16 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 0 0 0.0079617834394904458 34 11 26 12 35 13 26 14 26 15 26 16 37 45 OpenMeca::Item::LinkT<OpenMeca::Item::Slider> 1 0
+17 6 Slider 8 Slider_1 3 9 37 17 3 0 37 17 3 0 0.5 1 1 0 3 0.5 1 1 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 38 1 0
+18 37 17 13 Part_Slider_1 13 Part_Slider_1 0 1 26
+19 38 18 14 AutomaticPoint 6 middle 0 38 18 26 19 3 0 0 0 3 0 0 0 1 1 3 0 0 0 39 1 0
+20 37 17 13 Part_Slider_2 13 Part_Slider_1 0 3 26
+21 39 20 14 AutomaticPoint 4 left 0 39 20 26 21 3 0 0 -0.5 3 0 0 0 1 1 3 0 0 -0.5 26
+22 39 20 14 AutomaticPoint 6 middle 0 39 20 26 22 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+23 39 20 14 AutomaticPoint 5 right 0 39 20 26 23 3 0 0 0.5 3 0 0 0 1 1 3 0 0 0.5 0 0 38 18 26 19 39 20 26 21 26 22 26 23 41 32 OpenMeca::Item::PartUserJunction 1 0
+24 26 12 8 Junction 10 Junction_1 0 26 12 41 24 3 0 0 0 3 0 0 0.70710678118654746 0.70710678118654757 0 0 26 19 41 24 43 28 OpenMeca::Item::PartUserPipe 1 0
+25 26 21 4 Pipe 6 Pipe_1 0 26 21 43 25 3 0 0.5 0.5 3 -0 0.70710678118654746 0 0.70710678118654757 3 0 0 -1 0.5 26
+26 43 25 14 AutomaticPoint 16 AutomaticPoint_1 0 43 25 26 26 3 0.5 0 0 3 0 0 0 1 0 3 0 0 0 26 26 41
+27 26 26 8 Junction 10 Junction_2 0 26 26 41 27 3 0 0 0 3 0 1.5700924586837749e-16 -0.70710678118654746 0.70710678118654757 26 8 41 27 43
+28 26 26 4 Pipe 6 Pipe_2 0 26 26 43 28 3 1.1102230246251565e-16 0.5 0 3 -0 0.70710678118654746 0 0.70710678118654757 3 0 0 -1 0.20000000000000001 26
+29 43 28 14 AutomaticPoint 16 AutomaticPoint_2 0 43 28 26 29 3 0.20000000000000001 0 0 3 0 0 0 1 0 3 0 0 0 26 29 44 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground> 1 0
+30 26 29 0 0 6 Ground 8 Ground_1 0 26 29 44 30 3 1.5543122344752191e-16 0.5 -0.20000000000000001 3 -0 0.70710678118654746 0 0.70710678118654757 0 0 3 0 0 -1 0 43
+31 26 23 4 Pipe 6 Pipe_3 0 26 23 43 31 3 0 0.5 1.5 3 0 -0.70710678118654746 0 0.70710678118654757 3 0 0 1 1 26
+32 43 31 14 AutomaticPoint 16 AutomaticPoint_3 0 43 31 26 32 3 1 0 0 3 0 0 0 1 0 3 0 0 0 26 32 43
+33 26 16 4 Pipe 6 Pipe_4 0 26 16 43 33 3 0 0 1.5 3 0 -0.70710678118654746 0 0.70710678118654757 3 0 0 1 1 26
+34 43 33 14 AutomaticPoint 16 AutomaticPoint_4 0 43 33 26 34 3 1 0 0 3 0 0 0 1 0 3 0 0 0 26 34 4 7 Gravity 3 0 -9.8100000000000005 0 6 Scales 8 19 AngularAcceleration 1 15 AngularVelocity 1 5 Force 1 5 Frame 1 18 LinearAcceleration 1 14 LinearVelocity 1 4 Part 1 6 Torque 1 5 Scene 0 128 128 128 255 3 0 0 0 3 1 10 Simulation 0.01 60 0.10000000000000001
diff --git a/SRC/OpenMeca/Rsc/Example/steering.omc b/SRC/OpenMeca/Rsc/Example/steering.omc
new file mode 100644
index 0000000..afc5342
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Example/steering.omc
@@ -0,0 +1,164 @@
+22 serialization::archive 9 0 2 0 0 6  2.1.0 2 1 0 0 0 158 3 20 OpenMeca::Item::Body 1 3
+0 0 0 0 0 0 0 4 Body 5 frame 0 0 72 72 72 255 1 0 0 0 0 0 0 0 0 3 0 0 0 0 0 1 0 1 0 1 0 0 0 3 0 0 0 1 0 0 3 1 0 0 3 0 1 0 3 0 0 1 1 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+1 4 Body 1 1 0 170 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 15 45 OpenMeca::Item::LinkT<OpenMeca::Item::Slider> 1 0
+2 0 2 6 Slider 8 Slider_1 0 0 3 1 15 2 3 0 15 2 3 0 0.20000000000000001 0 1 0 3 0.2 1 0 0 0 3 0.70710678118654746 0 0 0.70710678118654757 0 0 0 0 3 1 0 0 1 1 1 0 1 0 0 0 1.5707963267948966 2 90 22 1 0
+3 15 2 0 0 0 0 13 Part_Slider_1 13 Part_Slider_1 0 0 0 1 26 1 0
+4 22 3 0 0 14 AutomaticPoint 6 middle 0 0 0 22 3 26 4 3 0 0 0 3 0 0 0 1 1 3 0 0 0 29 1 0
+5 15 2 13 Part_Slider_2 13 Part_Slider_1 0 3 26
+6 29 5 14 AutomaticPoint 4 left 0 29 5 26 6 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+7 29 5 14 AutomaticPoint 6 middle 0 29 5 26 7 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+8 29 5 14 AutomaticPoint 5 right 0 29 5 26 8 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 0 0 0 0 22 3 26 4 29 5 26 6 26 7 26 8 3
+9 4 Body 1 2 0 255 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 32 47 OpenMeca::Item::LinkT<OpenMeca::Item::Revolute> 1 0
+10 8 Revolute 10 Revolute_1 3 9 32 10 3 1 32 10 3 1 0.20000000000000001 0 1 1 3 0.2 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 33 1 0
+11 32 10 15 Part_Revolute_1 15 Part_Revolute_1 0 3 26
+12 33 11 14 AutomaticPoint 4 left 0 33 11 26 12 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+13 33 11 14 AutomaticPoint 6 middle 0 33 11 26 13 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+14 33 11 14 AutomaticPoint 5 right 0 33 11 26 14 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 34 1 0
+15 32 10 15 Part_Revolute_2 15 Part_Revolute_1 0 1 26
+16 34 15 14 AutomaticPoint 6 middle 0 34 15 26 16 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 33 11 26 12 26 13 26 14 34 15 26 16 36 45 OpenMeca::Item::LinkT<OpenMeca::Item::Spring> 1 0
+17 6 Spring 8 Spring_1 3 1 36 17 3 0 36 17 3 0 0.14999999999999999 0 1 0 4 0.15 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 37 1 0
+18 36 17 13 Part_Spring_1 13 Part_Spring_1 0 1 26
+19 37 18 14 AutomaticPoint 6 center 0 37 18 26 19 3 0 0 0 3 0 0 0 1 1 3 0 0 0 38 1 0
+20 36 17 13 Part_Spring_2 13 Part_Spring_1 0 1 26
+21 38 20 14 AutomaticPoint 6 center 0 38 20 26 21 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 1 10000 1000 0.20000000000000001 0.20000000000000001 37 18 26 19 38 20 26 21 3
+22 4 Body 1 3 255 0 0 255 1 3 1.6000000000000001 0.20000000000000001 0 3 1.6 3 0.2 1 0 3 0 0 0 1 3 10 0 0 3 0 10 0 3 0 0 10 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+23 4 Body 1 4 255 255 0 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 32
+24 8 Revolute 10 Revolute_3 3 22 32 24 3 23 32 24 3 0.69999999999999996 0.5 0 3 0.7 3 0.5 1 0 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 33
+25 32 24 15 Part_Revolute_1 15 Part_Revolute_3 0 3 26
+26 33 25 14 AutomaticPoint 4 left 0 33 25 26 26 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+27 33 25 14 AutomaticPoint 6 middle 0 33 25 26 27 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+28 33 25 14 AutomaticPoint 5 right 0 33 25 26 28 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 34
+29 32 24 15 Part_Revolute_2 15 Part_Revolute_3 0 1 26
+30 34 29 14 AutomaticPoint 6 middle 0 34 29 26 30 3 0 0 0 3 0 0 0 1 1 3 0 0 0 33 25 26 26 26 27 26 28 34 29 26 30 3
+31 4 Body 1 5 211 58 135 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 32
+32 8 Revolute 10 Revolute_4 3 31 32 32 3 23 32 32 3 0.69999999999999996 0.5 0 3 0.7 3 0.5 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 33
+33 32 32 15 Part_Revolute_1 15 Part_Revolute_4 0 3 26
+34 33 33 14 AutomaticPoint 4 left 0 33 33 26 34 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+35 33 33 14 AutomaticPoint 6 middle 0 33 33 26 35 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+36 33 33 14 AutomaticPoint 5 right 0 33 33 26 36 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 34
+37 32 32 15 Part_Revolute_2 15 Part_Revolute_4 0 1 26
+38 34 37 14 AutomaticPoint 6 middle 0 34 37 26 38 3 0 0 0 3 0 0 0 1 1 3 0 0 0 33 33 26 34 26 35 26 36 34 37 26 38 3
+39 4 Body 1 6 14 140 157 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 32
+40 8 Revolute 10 Revolute_5 3 31 32 40 3 39 32 40 3 0.29999999999999999 0.5 0 3 0.3 3 0.5 1 0 3 0.70710678118654746 0 0 0.70710678118654757 3 1 0 0 1 1 1 0 1 0 1.5707963267948966 2 90 33
+41 32 40 15 Part_Revolute_1 15 Part_Revolute_5 0 3 26
+42 33 41 14 AutomaticPoint 4 left 0 33 41 26 42 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+43 33 41 14 AutomaticPoint 6 middle 0 33 41 26 43 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+44 33 41 14 AutomaticPoint 5 right 0 33 41 26 44 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 34
+45 32 40 15 Part_Revolute_2 15 Part_Revolute_5 0 1 26
+46 34 45 14 AutomaticPoint 6 middle 0 34 45 26 46 3 0 0 0 3 0 0 0 1 1 3 0 0 0 33 41 26 42 26 43 26 44 34 45 26 46 3
+47 4 Body 1 7 190 30 57 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 32
+48 8 Revolute 10 Revolute_6 3 47 32 48 3 39 32 48 3 0.29999999999999999 0.5 0 3 0.3 3 0.5 1 0 3 0 0 0.70710678118654746 0.70710678118654757 3 0 0 1 1 0 1 0 1 1 1.5707963267948966 2 90 33
+49 32 48 15 Part_Revolute_1 15 Part_Revolute_6 0 3 26
+50 33 49 14 AutomaticPoint 4 left 0 33 49 26 50 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+51 33 49 14 AutomaticPoint 6 middle 0 33 49 26 51 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+52 33 49 14 AutomaticPoint 5 right 0 33 49 26 52 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 34
+53 32 48 15 Part_Revolute_2 15 Part_Revolute_6 0 1 26
+54 34 53 14 AutomaticPoint 6 middle 0 34 53 26 54 3 0 0 0 3 0 0 0 1 1 3 0 0 0 33 49 26 50 26 51 26 52 34 53 26 54 40 44 OpenMeca::Item::LinkT<OpenMeca::Item::Motor> 1 0
+55 5 Motor 7 Motor_1 3 47 40 55 3 0 40 55 3 0 0.5 0 1 0 3 0.5 1 0 3 0 0.70710678118654746 0 0.70710678118654757 3 0 1 0 1 0 1 1 1 0 1.5707963267948966 2 90 41 1 0
+56 40 55 12 Part_Motor_1 12 Part_Motor_1 0 3 26
+57 41 56 14 AutomaticPoint 4 left 0 41 56 26 57 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+58 41 56 14 AutomaticPoint 6 middle 0 41 56 26 58 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+59 41 56 14 AutomaticPoint 5 right 0 41 56 26 59 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 42 1 0
+60 40 55 12 Part_Motor_2 12 Part_Motor_1 0 1 26
+61 42 60 14 AutomaticPoint 6 middle 0 42 60 26 61 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 1 0 1 1 2 2 41 56 26 57 26 58 26 59 42 60 26 61 45 32 OpenMeca::Item::PartUserJunction 1 0
+62 26 16 8 Junction 10 Junction_2 0 26 16 45 62 3 0 0 0 3 -0 0 1 6.123233995736766e-17 0 0 26 4 45 62 47 28 OpenMeca::Item::PartUserPipe 1 0
+63 26 28 4 Pipe 6 Pipe_2 0 26 28 47 63 3 0.69999999999999996 0.5 0.1875 3 -0 0 0 1 3 1 0 0 0.10000000000000001 26
+64 47 63 14 AutomaticPoint 16 AutomaticPoint_2 0 47 63 26 64 3 0.10000000000000001 0 0 3 0 0 0 1 0 3 0 0 0 26 64 47
+65 26 26 4 Pipe 6 Pipe_3 0 26 26 47 65 3 0.69999999999999996 0.5 -0.1875 3 -0 0 0 1 3 1 0 0 0.10000000000000001 26
+66 47 65 14 AutomaticPoint 16 AutomaticPoint_3 0 47 65 26 66 3 0.10000000000000001 0 0 3 0 0 0 1 0 3 0 0 0 26 66 47
+67 26 52 4 Pipe 6 Pipe_4 0 26 52 47 67 3 0.29999999999999999 0.5 0.1875 3 -0 0 1 6.123233995736766e-17 3 -1 0 0 0.10000000000000001 26
+68 47 67 14 AutomaticPoint 16 AutomaticPoint_4 0 47 67 26 68 3 0.10000000000000001 0 0 3 0 0 0 1 0 3 0 0 0 26 68 47
+69 26 50 4 Pipe 6 Pipe_5 0 26 50 47 69 3 0.29999999999999999 0.5 -0.1875 3 -0 0 1 6.123233995736766e-17 3 -1 0 0 0.10000000000000001 26
+70 47 69 14 AutomaticPoint 16 AutomaticPoint_5 0 47 69 26 70 3 0.10000000000000001 0 0 3 0 0 0 1 0 3 0 0 0 26 70 45
+71 26 68 8 Junction 10 Junction_5 0 26 68 45 71 3 0 0 0 3 -0 0.68318416243835145 0 0.73024612302524972 26 59 45 71 45
+72 26 70 8 Junction 10 Junction_6 0 26 70 45 72 3 0 0 0 3 0 -0.68318416243835156 0 0.73024612302524972 26 59 45 72 45
+73 26 42 8 Junction 10 Junction_7 0 26 42 45 73 3 0 0 0 3 -0 0 0 1 26 34 45 73 45
+74 26 44 8 Junction 10 Junction_8 0 26 44 45 74 3 0 0 0 3 -0 0 0 1 26 36 45 74 3
+75 4 Body 2 10 55 120 175 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+76 4 Body 2 11 170 170 255 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 10 0 0 3 0 10 0 3 0 0 10 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 3
+77 4 Body 2 12 241 130 84 255 1 3 0 0 0 1 0 1 0 1 0 3 0 0 0 1 3 1 0 0 3 0 1 0 3 0 0 1 0 0 3 0 0 0 0.59999999999999998 0.59999999999999998 0 40
+78 5 Motor 7 Motor_2 3 77 40 78 3 0 40 78 3 0.29999999999999999 0.69999999999999996 -0.69999999999999996 3 0.3 3 0.7 4 -0.7 3 0.38268343236508978 0 0 0.92387953251128674 3 1 0 0 1 1 1 0 1 0 0.78539816339744828 2 45 41
+79 40 78 12 Part_Motor_1 12 Part_Motor_2 0 3 26
+80 41 79 14 AutomaticPoint 4 left 0 41 79 26 80 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+81 41 79 14 AutomaticPoint 6 middle 0 41 79 26 81 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+82 41 79 14 AutomaticPoint 5 right 0 41 79 26 82 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 42
+83 40 78 12 Part_Motor_2 12 Part_Motor_2 0 1 26
+84 42 83 14 AutomaticPoint 6 middle 0 42 83 26 84 3 0 0 0 3 0 0 0 1 1 3 0 0 0 11 2*sin(t*10) 0 41 79 26 80 26 81 26 82 42 83 26 84 48 49 OpenMeca::Item::LinkT<OpenMeca::Item::RackPinion> 1 0
+85 10 RackPinion 12 RackPinion_1 3 77 48 85 3 75 48 85 3 0.29999999999999999 0.5 -0.5 3 0.3 3 0.5 4 -0.5 3 0.38268343236508978 0 0 0.92387953251128674 3 1 0 0 1 1 1 0 1 0 0.78539816339744828 2 45 49 1 0
+86 48 85 17 Part_RackPinion_1 17 Part_RackPinion_1 0 1 26
+87 49 86 14 AutomaticPoint 13 pinion center 0 49 86 26 87 3 0 0 0 3 0 0 0 1 1 3 0 0 0 50 1 0
+88 48 85 17 Part_RackPinion_2 17 Part_RackPinion_1 0 1 26
+89 50 88 14 AutomaticPoint 13 pinion center 0 50 88 26 89 3 0 0.037500000558793545 0 3 0 0 0 1 1 3 0 0.10000000149011612 0 0 0 2 0.10000000000000001 0.01 0.3490658503988659 49 86 26 87 50 88 26 89 15
+90 6 Slider 8 Slider_2 3 0 15 90 3 75 15 90 3 -0.10000000000000001 0.5 -0.5 4 -0.1 3 0.5 4 -0.5 3 0 0.70710678118654746 0 0.70710678118654757 3 0 1 0 1 0 1 1 1 0 1.5707963267948966 2 90 22
+91 15 90 13 Part_Slider_1 13 Part_Slider_2 0 1 26
+92 22 91 14 AutomaticPoint 6 middle 0 22 91 26 92 3 0 0 0 3 0 0 0 1 1 3 0 0 0 29
+93 15 90 13 Part_Slider_2 13 Part_Slider_2 0 3 26
+94 29 93 14 AutomaticPoint 4 left 0 29 93 26 94 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+95 29 93 14 AutomaticPoint 6 middle 0 29 93 26 95 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+96 29 93 14 AutomaticPoint 5 right 0 29 93 26 96 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 22 91 26 92 29 93 26 94 26 95 26 96 52 48 OpenMeca::Item::LinkT<OpenMeca::Item::PointLine> 1 0
+97 9 PointLine 11 PointLine_2 3 1 52 97 3 9 52 97 3 1 0.5 0 1 1 3 0.5 1 0 3 1 0 0 6.123233995736766e-17 3 1 0 0 1 1 1 0 1 0 3.1415926535897931 3 180 53 1 0
+98 52 97 16 Part_PointLine_1 16 Part_PointLine_2 0 1 26
+99 53 98 14 AutomaticPoint 6 middle 0 53 98 26 99 3 0 -0.056249999999999994 0 3 0 0 0 1 1 3 0 -0.14999999999999999 0 54 1 0
+100 52 97 16 Part_PointLine_2 16 Part_PointLine_2 0 1 26
+101 54 100 14 AutomaticPoint 6 middle 0 54 100 26 101 3 0 0.075000000000000011 0 3 0 0 0 1 1 3 0 0.20000000000000001 0 0 0 53 98 26 99 54 100 26 101 45
+102 26 12 8 Junction 10 Junction_9 0 26 12 45 102 3 0 0 0 3 -0 0.70710678118654746 9.4205547521026535e-16 0.70710678118654757 26 101 45 102 56 29 OpenMeca::Item::PartUserPoint 1 1
+103 3 22
+104 5 Point 7 Point_2 0 3 22 56 103 3 1.6000000000000001 0.5 0 3 0 0 0 1 0 3 0 0 0 3 1.6000000000000001 0.5 0 3 1.6 3 0.5 1 0 57 63 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Cylinder> 1 0
+105 56 103 0 0 8 Cylinder 10 Cylinder_1 0 56 103 57 105 3 1.6000000000000001 0.5 0 3 -0 0 0 1 0 0 0.5 0.040000000000000001 3 1 0 0 0 60 50 OpenMeca::Item::LinkT<OpenMeca::Item::Cylindrical> 1 0
+106 11 Cylindrical 13 Cylindrical_1 3 22 60 106 3 9 60 106 3 1.3 0.5 0 3 1.3 3 0.5 1 0 3 0 0.70710678118654746 0 0.70710678118654757 3 0 1 0 1 0 1 1 1 0 1.5707963267948966 2 90 61 1 0
+107 60 106 18 Part_Cylindrical_1 18 Part_Cylindrical_1 0 3 26
+108 61 107 14 AutomaticPoint 4 left 0 61 107 26 108 3 0 0 -0.1875 3 0 0 0 1 1 3 0 0 -0.5 26
+109 61 107 14 AutomaticPoint 6 middle 0 61 107 26 109 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+110 61 107 14 AutomaticPoint 5 right 0 61 107 26 110 3 0 0 0.1875 3 0 0 0 1 1 3 0 0 0.5 62 1 0
+111 60 106 18 Part_Cylindrical_2 18 Part_Cylindrical_1 0 1 26
+112 62 111 14 AutomaticPoint 6 middle 0 62 111 26 112 3 0 0 0 3 0 0 0 1 1 3 0 0 0 0 0 61 107 26 108 26 109 26 110 62 111 26 112 47
+113 26 108 4 Pipe 6 Pipe_6 0 26 108 47 113 3 1.1125 0.5 -4.163336342344337e-17 3 -0 0 1 6.123233995736766e-17 3 -1 0 0 0.29999999999999999 26
+114 47 113 14 AutomaticPoint 16 AutomaticPoint_6 0 47 113 26 114 3 0.29999999999999999 0 0 3 0 0 0 1 0 3 0 0 0 26 114 45
+115 26 64 8 Junction 11 Junction_10 0 26 64 45 115 3 0 0 0 3 -0 0.68318416243835156 0 0.73024612302524972 26 114 45 115 45
+116 26 66 8 Junction 11 Junction_11 0 26 66 45 116 3 0 0 0 3 0 -0.68318416243835145 0 0.73024612302524972 26 114 45 116 45
+117 56 103 8 Junction 11 Junction_12 0 56 103 45 117 3 0 0 0 3 -0 0 1 2.8327694488239898e-16 26 110 45 117 64 48 OpenMeca::Item::LinkT<OpenMeca::Item::Spherical> 1 0
+118 9 Spherical 11 Spherical_3 3 76 64 118 3 75 64 118 3 0.80000000000000004 0.5 -0.5 3 0.8 3 0.5 4 -0.5 3 0 0 0 1 3 1 0 0 1 1 1 0 1 0 0 1 0 65 1 0
+119 64 118 16 Part_Spherical_1 16 Part_Spherical_3 0 2 26
+120 65 119 14 AutomaticPoint 6 center 0 65 119 26 120 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+121 65 119 14 AutomaticPoint 2 up 0 65 119 26 121 3 0.075000000000000011 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 66 1 0
+122 64 118 16 Part_Spherical_2 16 Part_Spherical_3 0 2 26
+123 66 122 14 AutomaticPoint 6 center 0 66 122 26 123 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+124 66 122 14 AutomaticPoint 2 up 0 66 122 26 124 3 -0.056249999999999994 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 0 0 65 119 26 120 26 121 66 122 26 123 26 124 64
+125 9 Spherical 11 Spherical_4 3 76 64 125 3 9 64 125 3 1 0.5 -0.20000000000000001 1 1 2 .5 3 -.2 3 0 0 0.70710678118654746 0.70710678118654757 3 0 0 1 1 0 1 0 1 1 1.5707963267948966 2 90 65
+126 64 125 16 Part_Spherical_1 16 Part_Spherical_4 0 2 26
+127 65 126 14 AutomaticPoint 6 center 0 65 126 26 127 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+128 65 126 14 AutomaticPoint 2 up 0 65 126 26 128 3 0.075000000000000011 0 0 3 0 0 0 1 1 3 0.20000000000000001 0 0 66
+129 64 125 16 Part_Spherical_2 16 Part_Spherical_4 0 2 26
+130 66 129 14 AutomaticPoint 6 center 0 66 129 26 130 3 0 0 0 3 0 0 0 1 1 3 0 0 0 26
+131 66 129 14 AutomaticPoint 2 up 0 66 129 26 131 3 -0.056249999999999994 0 0 3 0 0 0 1 1 3 -0.14999999999999999 0 0 65 126 26 127 26 128 66 129 26 130 26 131 45
+132 26 120 8 Junction 11 Junction_13 0 26 120 45 132 3 0 0 0 3 0 -0.47185796275628855 0 0.8816745788461211 26 127 45 132 47
+133 26 12 4 Pipe 6 Pipe_7 0 26 12 47 133 3 1 0.38750000000000001 -4.163336342344337e-17 3 -0 0.70710678118654746 0 0.70710678118654757 3 0 0 -1 0.20000000000000001 26
+134 47 133 14 AutomaticPoint 16 AutomaticPoint_7 0 47 133 26 134 3 0.20000000000000001 0 0 3 0 0 0 1 0 3 0 0 0 26 134 45
+135 26 134 8 Junction 11 Junction_14 0 26 134 45 135 3 0 0 0 3 0 -0 0.70710678118654746 0.70710678118654757 26 131 45 135 45
+136 26 82 8 Junction 11 Junction_17 0 26 82 45 136 3 0 0 0 3 0 -0.70710678118654746 4.1169702904711939e-16 0.70710678118654757 26 87 45 136 47
+137 26 80 4 Pipe 6 Pipe_8 0 26 80 47 137 3 0.29999999999999999 0.83258252147247758 -0.83258252147247758 3 -0 0 0 1 3 1 0 0 0.1875 26
+138 47 137 14 AutomaticPoint 16 AutomaticPoint_8 0 47 137 26 138 3 0.1875 0 0 3 0 0 0 1 0 3 0 0 0 26 138 45
+139 26 6 8 Junction 11 Junction_18 0 26 6 45 139 3 0 0 0 3 -0 0.70710678118654746 4.1869132231567334e-16 0.70710678118654757 26 61 45 139 45
+140 26 61 8 Junction 11 Junction_19 0 26 61 45 140 3 0 0 0 3 -0 0.098537619820222411 0 0.99513332648452957 26 92 45 140 47
+141 26 84 4 Pipe 6 Pipe_9 0 26 84 47 141 3 0.29999999999999999 0.69999999999999996 -0.69999999999999996 3 -0 0 1 6.123233995736766e-17 3 -1 0 0 0.40000000000000002 26
+142 47 141 14 AutomaticPoint 16 AutomaticPoint_9 0 47 141 26 142 3 0.40000000000000002 0 0 3 0 0 0 1 0 3 0 0 0 26 142 45
+143 26 92 8 Junction 11 Junction_20 0 26 92 45 143 3 0 0 0 3 -0 1.5932398415786497e-16 0.38268343236508978 0.92387953251128674 26 142 45 143 47
+144 26 96 4 Pipe 7 Pipe_10 0 26 96 47 144 3 0.087499999999999994 0.5 -0.49999999999999994 3 0 -0.49999999999999994 0.49999999999999994 0.70710678118654757 3 0 1 1 0.13 26
+145 47 144 14 AutomaticPoint 17 AutomaticPoint_10 0 47 144 26 145 3 0.13 0 0 3 0 0 0 1 0 3 0 0 0 26 145 47
+146 26 124 4 Pipe 7 Pipe_11 0 26 124 47 146 3 0.74375000000000002 0.5 -0.5 3 0 -0.49999999999999994 0.49999999999999994 0.70710678118654757 3 0 1 1 0.12 26
+147 47 146 14 AutomaticPoint 17 AutomaticPoint_11 0 47 146 26 147 3 0.12 0 0 3 0 0 0 1 0 3 0 0 0 26 147 47
+148 26 147 4 Pipe 7 Pipe_12 0 26 147 47 148 3 0.74375000000000002 0.58485281374238574 -0.41514718625761432 3 -0 0 1 6.123233995736766e-17 3 -1 0 0 0.1875 26
+149 47 148 14 AutomaticPoint 17 AutomaticPoint_12 0 47 148 26 149 3 0.1875 0 0 3 0 0 0 1 0 3 0 0 0 26 149 68 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Ground> 1 0
+150 26 8 6 Ground 8 Ground_1 0 26 8 68 150 3 0 0.012500000000000011 4.163336342344337e-17 3 0 0 -0.70710678118654746 0.70710678118654757 0 0 3 0 -1 0 0 56
+151 3 22
+152 5 Point 7 Point_3 0 3 22 56 151 3 1.6000000000000001 0.80000000000000004 0 3 0 0 0 1 0 3 0 0 0 3 1.6000000000000001 0.80000000000000004 0 3 1.6 3 0.8 1 0 70 61 OpenMeca::Item::PartUserShapeT<OpenMeca::Item::Shape::Sphere> 1 0
+153 56 151 6 Sphere 8 Sphere_1 0 56 151 70 153 3 1.6000000000000001 0.80000000000000004 0 3 0 0 0 1 0 0 0.050000000000000003 0 56
+154 3 22
+155 5 Point 7 Point_4 0 3 22 56 154 3 1.6000000000000001 0.20000000000000001 0 3 0 0 0 1 0 3 0 0 0 3 1.6000000000000001 0.20000000000000001 0 3 1.6 3 0.2 1 0 70
+156 56 154 6 Sphere 8 Sphere_2 0 56 154 70 156 3 1.6000000000000001 0.20000000000000001 0 3 0 0 0 1 0.050000000000000003 0 56
+157 3 22
+158 5 Point 7 Point_5 0 3 22 56 157 3 1.6000000000000001 0.5 0.29999999999999999 3 0 0 0 1 0 3 0 0 0 3 1.6000000000000001 0.5 0.29999999999999999 3 1.6 3 0.5 3 0.3 70
+159 56 157 6 Sphere 8 Sphere_3 0 56 157 70 159 3 1.6000000000000001 0.5 0.29999999999999999 3 0 0 0 1 0.050000000000000003 0 56
+160 3 22
+161 5 Point 7 Point_6 0 3 22 56 160 3 1.6000000000000001 0.5 -0.29999999999999999 3 0 0 0 1 0 3 0 0 0 3 1.6000000000000001 0.5 -0.29999999999999999 3 1.6 3 0.5 4 -0.3 70
+162 56 160 6 Sphere 8 Sphere_4 0 56 160 70 162 3 1.6000000000000001 0.5 -0.29999999999999999 3 0 0 0 1 0.050000000000000003 0 4 7 Gravity 3 0 -9.8100000000000005 0 6 Scales 8 19 AngularAcceleration 1 15 AngularVelocity 1 5 Force 1 5 Frame 0.28125 18 LinearAcceleration 1 14 LinearVelocity 1 4 Part 0.375 6 Torque 1 5 Scene 1 128 128 128 255 3 0 0 0 1 1 10 Simulation 0.00020000000000000001 60 0.02
diff --git a/SRC/OpenMeca/Rsc/Help/Help.html b/SRC/OpenMeca/Rsc/Help/Help.html
new file mode 100644
index 0000000..e865009
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Help/Help.html
@@ -0,0 +1,168 @@
+<!doctype html>
+<html lang="en">
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+  
+  <head>
+    <meta charset="utf-8">
+    <title>openmeca help</title>
+    <!-- <link rel="stylesheet" href="style.css"> -->
+    <!-- <script src="script.js"></script> -->
+  </head>
+  <body>
+
+    <h1 id="intro">Introduction </h1>
+    <p>
+      The aim of openmeca is to provide a software for simulating mechanical systems easily. It allows to build a 3D scheme, where the bonds are represented by symbols and gives a simple way to apply loadings and boundary conditions. Thanks to numerical sensors, different kind of data (force, torque, displacement, velocity, etc.) could be extracted from the simulation and exploited with your favorite tool.
+    </p> 
+    
+    <h1 id="gui">Presentation of the graphical interface</h1>
+    <p>
+      The graphical interface is composed by :
+      <ul>
+	<li>the <i>3D viewer</i> where the mechanical system is displayed in 3D,</li>
+	<li>the <i>treeview</i> that shows all the created items,</li>
+	<li>the <i>scale tool</i> that adjust the size of the item displayed in the 3D viewer,</li>
+	<li>the <i>action menu</i> where all the possible actions are available and</li>
+	<li>the <i>undo/redo</i> arrows.</li>
+      </ul>
+    </p>
+    <img src="./img/gui.svg">
+
+    <h3>Few notes about graphical interface</h3>
+    <p>In the graphical interface, nothing is hidden ! 
+      It means that all the possible actions are available in the action menu. 
+      Note that some shortcuts are available (by right-clicking or pressing keyboard) but all these 
+      actions are also provided by the action menu.
+    </p> 
+    
+      
+    <h3>Selecting items</h3>
+    <p>
+      To select some items, you can pick them in the treeview or in the 3D viewer. 
+      To select them in the 3D viewer, simply left-click and press the SHIFT key. 
+      The selected item are highlighted in the treeview and in the 3D viewer.</p> 
+
+    <h1 id="step">The main steps to build a mechanical system</h1>
+    <p>
+      The main steps required to build a mechanical system and simulate it are : 
+      <ol>
+	<li>building the <a href="#body">bodies</a>,</li>
+	<li>building the <a href="#link">links</a> between the bodies,</li>
+	<li>building some <a href="#geom">geometries</a> and <a href="#shape">shapes</a>,</li>
+	<li>building some <a href="#sensor">sensors</a> and <a href="#load">loading</a>, </li>
+	<li>running a <a href="#simu">simulation</a> and</li>
+	<li> <a href="#postpro">post-processing</a> the results.</li>
+    </ol>
+    </p>
+    
+    <h1 id="body">The body</h1>
+    <p>
+      The bodies are kinematic subsets. All the elements that belong to a same body are locked together.
+      A body requires mass parameters : gravity center, mass value and inertia tensor.
+    </p>
+    
+    <p>
+      You can add a body by clicking <i>Body > New</i>. 
+      In the opened dialog box, you can choose the parameters of the body. 
+      Note that the color of a body is applied to all the sub-items that belong to this body.
+    </p>
+
+    <h1 id="link">The link</h1>
+    <p>
+      A link is a mechanical joint between two bodies. Several links are available in the <i>Link</i> menu. 
+      A link must be placed in the space at a given center and attitude. You can use the <i>Preview</i> button 
+      available in the link dialog box to help you and pre-visualize your link in the 3D viewer.  
+    </p>
+    
+    <p> 
+      A link build two new parts in the two selected bodies. 
+      In addition, some <a href="#point">anchor points</a> are available with these parts.  
+      T
+    </p>
+   
+    
+
+    <h1 id="geom">The geometries</h1>
+    <p>
+      Several class of geometries are available with some specific characters.
+    </p>
+
+    <h3 id="point">Points</h3>
+    <p>
+      The points are a special class of the geometry instance. They can 
+      be used as anchor to attach some shapes or to insert some sensors or loading. 
+      The points can be automatically created or defined by users.
+    </p>
+
+    <h3 id="cosmetic">The cosmetic geometries</h3>
+    <p>
+      The cosmetic geometries can be used to improve the 3D rendering of the system. 
+      They have no influence on the mechanical simulation of the system.
+    </p>
+
+    <h3 id="coll">The collision shapes</h3>
+    <p>
+      The collision shapes can be used as a cosmetic geometries or as collision shape that 
+      interact together during a simulation. 
+    </p>
+
+
+    <h1 id="sensor">The sensor</h1>
+    <p>
+      Several sensors can be inserted in the simulation. They can be used to measure and to store some 
+      interesting data during a simulation. Generally, a sensor must be inserted at an
+      <a href="#point">anchor points</a>. These data can be <a href="#postpro">post-processed</a>.
+    </p>
+
+    <h1 id="load">The loading</h1>
+    <p>
+      A loading is an external force or torque applied to the mechanical system. 
+    </p>
+
+    <h1 id="system">The system</h1>
+    <p>
+    In the <i>system</i> menu, you will find the general settings of 
+    the system (mechanical and cosmetic) : scales, gravity, simulation, etc. 
+    Note that the <i>scale tool</i> available in the menu bar is just a shortcut to the scales setting. 
+    </p>
+    
+    <h3 id="simu">Simulation</h3>
+    <p>
+      After choosing the general settings of the simulation, you can run a simulation 
+      by clicking on the <i>play</i> button. You can also <i>pause</i> or <i>reset</i> 
+      the simulation and navigate through the iteration steps with the navigation bar. 
+      Note that, during a simulation, you can a <a href="#postpro">post-process</a> the data.
+    </p>
+
+    <h1 id="postpro">The post-processing</h1>
+    <p>
+      The data provided by the sensors and the loading are stored during a simulation. 
+      You can plot them thanks to the <i>Sensors > Plot Data...</i> action. 
+      It shows a new window where you can plots the data versus the simulated time.
+    </p>
+    <p>
+      In addition, you can dump data into a file with <i>Sensors > Save Data...</i>. 
+      The created file is a comma separated text file (.csv) that you can post-process
+      with your favorite software. 
+    </p>
+
+
+  </body>
+</html>
diff --git a/SRC/OpenMeca/Rsc/Help/Help.qhcp b/SRC/OpenMeca/Rsc/Help/Help.qhcp
new file mode 100644
index 0000000..36d9706
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Help/Help.qhcp
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<QHelpCollectionProject version="1.0">
+    <docFiles>
+        <generate>
+            <file>
+                <input>Help.qhp</input>
+                <output>Help.qch</output>
+            </file>
+        </generate>
+        <register>
+            <file>Help.qch</file>
+        </register>
+    </docFiles>
+</QHelpCollectionProject>
diff --git a/SRC/OpenMeca/Rsc/Help/Help.qhp b/SRC/OpenMeca/Rsc/Help/Help.qhp
new file mode 100644
index 0000000..92a01a4
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Help/Help.qhp
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<QtHelpProject version="1.0">
+  <namespace>OpenMeca</namespace>
+  <virtualFolder>Help</virtualFolder>
+  <filterSection>
+    <toc>
+      <section title="Introduction"         ref="Help.html#intro"/>
+      <section title="Graphical interface"  ref="Help.html#gui"/>
+      <section title="Building a system"    ref="Help.html#step"/>
+      <section title="The body"             ref="Help.html#body"/>
+      <section title="The link"             ref="Help.html#link"/>
+      <section title="The geometry"         ref="Help.html#geom"/>
+      <section title="The sensor"           ref="Help.html#sensor"/>
+      <section title="The loading"          ref="Help.html#load"/>
+      <section title="The system"           ref="Help.html#system"/>
+      <section title="Post-processing"      ref="Help.html#postpro"/>
+
+    </toc>
+    <keywords>
+      <!-- <keyword name="Insert rectangle" ref="./Help.html"/> -->
+    </keywords>
+    <files>
+      <file>Help.html</file>
+      <file>./img/gui.svg</file>
+    </files>
+  </filterSection>
+</QtHelpProject>
diff --git a/SRC/OpenMeca/Rsc/Help/img/gui.svg b/SRC/OpenMeca/Rsc/Help/img/gui.svg
new file mode 100644
index 0000000..8b7ca50
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Help/img/gui.svg
@@ -0,0 +1,687 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="846"
+   height="578"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Nouveau document 1">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Lend"
+       style="overflow:visible;">
+      <path
+         id="path3861"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;"
+         transform="scale(0.8) rotate(180) translate(12.5,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-4"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3861-9"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-7"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3861-0"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-8"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3861-7"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend-79"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3861-74"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.7"
+     inkscape:cx="425.92666"
+     inkscape:cy="188.0338"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer2"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1598"
+     inkscape:window-height="867"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="img"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(40.142853,-131.93361)"
+     sodipodi:insensitive="true">
+    <image
+       y="131.93361"
+       x="-40.142853"
+       id="image3047"
+       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA04AAAJCCAIAAAB4dwAZAAAAA3NCSVQICAjb4U/gAAAgAElEQVR4
+nOzdd1hT1xsH8PdmEBL2FMGJoyiouHEgKqKIirgtzrq1Km5t60DrqKuuulpr67Yu3CLW0Vatbd2K
+2x+isqeMkEFyf39ciJFlgCAavp/Hx96c3Nx7Mp722/eccy9z//Y1AgAAAABDxCvvDgAAAABAWXl/
+1IuKjmneqgO3/c28b3/dsaeMu0RE1D9w+OUr14jo6PFTEyZN/wBnLKIP+qX9eRYoIiKyrVcXvZ8X
+OFJplpu7h1yuIKLOXQPCHzws7x6B/pXjvzcAAD42BUS9gD6Bbu4emj8xsbGzZgTp8ZRLlq3SPn7R
+uadRA7eB/XsT0ctXr4ves+hzuTdr699r4LnfL5a83yUS0Cfw5KlQ7RZLCwv9fp55nL9wafCw0c08
+2rfy9AkcMvLwkeNqtbrsTpdHx849yiI8LVm2av7CpXo/7MQJYxwrV9b7YTkJiYnTZ33j2d63mUf7
+Xn0H7T9wuIxOVGJ37t4fNmJci9YdWnn6DB42+vqNW8V6eRl91wXK8wNITExyc/dITEz6MGcHAPik
+CQps/XbhXD/fzty2kZGwWZPG+j1rgH+3ed/M5rYZhiliz5o1q9esWb005+oV0CN43hylUhl27sKs
+r+b/3viYjY11aQ5YSiYmkn59Asro4AcOhXy/5odpU75cufxbC3OLh48e7977W3uvtuX7lolIpVLx
++fzy7UN+/j38yu7gC4KXGouNDx/YZWZm+vTZ/6JjYsvuXNp0/KjlcsWXk6YPHzZo44bVqmzVnXv3
+P8IvCAAASq/gAVyhQCASGXF/omNiCyynnTh5xr/XwFaePqPHToqKjineWfl8zfGNjIRc47nfL/p2
+79O6nc+qNRs0e2oGYoKmzpbJZJ27BnTuGvAi8qXu52IYhs/nGxsb+/fw4/F4r15HERHLsr/s2N3F
+r1dbry4zZs9NTX1TWB+USmXrdj5Pnz7nHiYnpzRt6ZWSklqs96tNewDXy9vv5192DRw0wq9H32/m
+fatSqfLsfOBQSPee/XX8eOVy+Zp1m2bNCOrfr3dlBweJRNy0ifuaVcu4nKdUKteu39TJt6dnB9/g
+RctkMhn3qstXrvXuP9ijbachw8c8fvJU07H9Bw538+/XvFWHlavXxcbGDR85vnmrDl9OnpGVlcXt
+E/7g4ZDhYzzadurVb9C1f/4jom+XrkhMTJo4eWbnrgHHT5zmRqK3/Lg9oE/g3AWLJ0yctmffQU1v
+e/UbdP7CpRJ/jIX1POzchV59B7Vo3aGLX699vx3iGlmW3bBxq2cHXx/fgNOhYZojaAZwDxw8Mn7i
+1K/mLuzVb5B/r4Ga+tbTZ88HDhrh0cZ7wqTp8xcuXbNuo+7dC3/4qHeAv729nVgsbtjA1bezN9ee
+lJQ8feY3nh18O3cN2Ll7H9c4Y/bcZSu+HzV2Us/enw8bMS4+PoFr37j5p/adunm07dS9Z/979x8Q
+UWamdF7wknYdu3p38V//wxauZMv1f9ZX87v37H/o8DFduhcdHZP65s2QQQNNTUwsLMzbtW3d2L0h
+ERX4NUmlWdNmft3Gq3MrT58BgV/IZLI83zUV9Hsg3X5IpVTYD1vDy9tvy4/bBw0d1bP354sWL1cq
+lXo5LwDAp6KEyzKuXL22Zv2mFd8tunwptE1rj+kzv2FZtjT9eP066qu5Cxct+Pqvi6ESsfjRoyd5
+dli3ZrmxsXHYmaNhZ47WqF6tuMdXKpVnQs8JBYJazjWI6HRo2L79h7ZuWnsu9CjDMAsWLi2sD0Kh
+sKuvz4ncQdjTZ8I8Wja3srIszZvVdu9++O4dPx4P2f+/iIjQsN+1n/r5l137fjv068+bnRx1GmQM
+f/AoPT29S+dOBT67cfNP9+4/+G3PL2GnQ96kpf2w+SciioqKnjJ9zpTJEy5fCu3i4z1+4jTNfyl/
+P39p986fQg7uPnL05PRZc7+ePf2P86ffvHlz+MhxIkpOThkzPmjwoAFX/wz7Zs6MGbPmJiUlz/t6
+lq2tzQ/rV4adOcoVzFLfvCGio4f3Lv12vr9/t5OnznAHf/zkaXx8QjvPNiX81Arvuampyfcrl/5z
+5cKqFUvWrd/84MEjIjp5KvR0aNhve389dmTfxUt/FXjAq3//+/mAviEH90wJmsD9HlQq1eSps3y7
+dLr617kvhg06dfpssXrY2L3h+o1bQsPOx8S+reexLDt56uzKlSv9Hnr81+1bDhwM+fOvK9xTf/51
+ZcWyRceO7Ktfz2XTlm1E9ODBo2PHT4Uc3HPt8u9bN621t7MlopWr1yUkJJw6dmDPjp/OX/hjb24s
+u3L1n/59e508dqB/v166dM/RsbK9vd038xdduXotLS1d017g13TgUIhKpb547tSVP87OnzuLz+fn
++a4L/D1wByn6h1R6Bf6w87h79/7OX7YeObg7NjZu+6+79XJeAIBPRcFRb9GS5W29urT16jL0i7EF
+7nDgYMiQQQNcPqvL5/OHDQ2Mioou1vjUyVNnuOO39eoydsIUIgr7/UKbVi1bNG/K5/PHjBoukUhK
+8GYKdCTkuJu7R+PmnrO/XhA0ebyZmRkRnTp1dlDggBo1qovF4hlTJ52/+IdUmlVYH/y7+50ODeOy
+7PFTZ3p076qvvhHR4MABAoFAIBB4eLR4+PCxpn3t+k2/n7/467bNtrY2Oh4qJTVVLBabmOR0e+yE
+KV7efl7eftzikt8OhkwNmmBjYy0WiyeMHRUWdp6Iwn6/4NGyWbu2rQUCweBBA0Qio3/+vc69fOSI
+oVaWllWqODVt0qhli6Z169aWSMQ+nTo+fPSEiE6fCWvUwK2LjzePx2vWtHGzZo3/uvJ3/i7xeLwv
+hg0mIoZhOnh5voh8FfnyFRGdOHnGt0snoVBY4s+tsJ63btWyZs3qDMM0cKvv3bH9zVt3iOh0aNig
+gf0dKztIJOLxY0cUeMAmjRs1bOBKRJ5tWr189VoqzXrw8HFmpnTo4IE8Hq95syZtWrUsVg+XLV7g
+3cFr+y87u3bv26vfIK5S+OTps+fP/zdtykSRyMixssPnA/udDbvA7d+jW1draysiaufZ+sGjx0TE
+F/CzZLJHT54qlUonJ8dKleyJ6NSZsMkTx5uZmTk4VBo9ctjx3FjWwM21WdPG9L4ZERoikdGenT9Z
+WlgsWbbKs4Pv+IlTY2PjiKjAr0koECQnJ0e8eMHj8Vzr18v/xRXxeyj6h6Q77X9p9Ozzuaa9wB92
+Hp8P7Mfn8/l8/qDA/qfPhOXfAQDAgBU8Vy9o0oROHb2ISCAQyOTy/DtEx8TcC39wOOQE95DH5yUm
+JulYfCKiTt4dpk+ZyG0bGRkRUXxCopOTY06fBILKDpWK8y6K0ruX/6IFX6vV6qfPno//cmqlSvYd
+27eLT0h0rOzA7VCpkj2fz4+Pjy+sD40auhmLRP9dv2lna/vy5esOXp766hsRWViYcxvGItGb3HFk
+aZZ0/2+Hv104V/OsLiwtLLKysjIzpVzaW750YXZ29qCho+QKeUZmZnp6+uyvFjA8HhERy3Jfa3x8
+ova6BCdHx7jcoUPb3Ol9xsbGmrgpNhZJs6REFB0Te/vuve4BA7j2rKws90YN83fJzMxUJDLitkUi
+I9/O3idPhY4fO/L0mbA1q5fp/tbyK6znd+7e/2Hj1heRr4goLT3NwcGe21nzzVZxcirwgJaWFtyG
+UChkGEYqlcYnJNjb2fF4Of875FDM36RYLB47+ouxo7+QSrO2/rR98tRZF8JOREfHKpQK/945SUWp
+VLp8VjdPB0QikVSaRUSf1a0zLejLtes2RUa+bO/VdvbMqUKhICsrS/PTdXSsrBnqtbPT9X8JNCo7
+OMz9eiYRxSckzp3/7fyFS3/cvK7Ar6lvn4DEpKSgaXPkMnlAQPdJE8ZoPhZOEb+Hon9IutP+l0Zy
+Smq/gUOJqLAfdh6auaq2tjbxCYnFOi8AwKeu4KhnYW7GlRCIqMCJYg4Olfr07jmwf5+SndXY2Fhz
+fI69ne3jx880D5OSk/O8hKdbraIwPB7vs7p1mjZtfPny3x3bt7O3s9WUIePi4lUqlb29fRF96NnD
+78SpUFtbm84+HTXZpexIxJIf1q+aNGWmublZyxbNdHyVm2s9U1PTsHPnewX0oNzowOPziMjUxMTU
+1HT92hW1nGtqv8Te3vbGzduah9HRMZXs7XQ5l4ODfauWLVavXJKnPU8CYOidb62nf7ev5gY3adzI
+2Ni4UcMGOr6vAhXW86kzvpo2ZaKfrw+Px5u3YDFXi7W3t9V8m/l/WoWxs7WNT0hQq9Xcm4qNjSvZ
+CiGJRDx86KCff9kVGxvn4FDJzMzsRMh+HWtvvQJ69ArokZKaOnf+4i0/bf9q1jSxWBwdE8t9udHR
+Mfa535eOByyQvZ1tn97+y5Z/zz3M/zWJREZBk8YHTRofERE57sspbvVdvDu21/6uC/s96JH2vzQ0
+K0gK+2HnERUVXb/eZ0T0+nUUNw4OAFBxlHCuXv++vX/eviv8wUOWZTMyMs6eK2DQpAhqlUouV2j+
+EJGPd8fLV//mYuWpM2eTk1PyvMTKykoulyckFvv/yFmWValUCoXywYNH/12/WauWMxH5de28d9+B
+yJevZDLZ92s3dmzfTiIRF9GH7t19z1+4dPJkqH/xR2+V2dmad5qdna3jq9wbNVizatmM2XN1vwSG
+SCSaMnn88lXrDh4+Ghsbl5kpvX3nXkZ6JhcC+vft9d2KNXFx8UQUn5DIjer6eHe49s/1y1euqVSq
+vfsPymQyHZNlV1+ff/+7ERp2Pjs7W6FQXr9xi5uRZm1t9fLl6yLeFEPMitXrSjAIrv2bUSiUBfac
+ZdnMzMy6tWvxeLyo6BjNtDzfLp0OHzkml8uJaNfu/Tqe0bW+i0Qi2bl7v1qt/u/6zSt//1OsDq/6
+fv3de+FSaVZKaupPP++wsrJ0cnL8rG7tKk6O36/dKJVmqdXq5/+L4BZbFOjZ8//dvnNPpVKZmphI
+JGIBn09EXX19fti4NSMjIy4u/udfdvXo5lusXmlERUVv3PxTRESkXK54+er1gYMhDd1cuafyf03X
+/vkv8uUrlmUtrSyEQiGfL6B3v+vCfg8fQIE/7Dx+3bknJSU1NfXNj9t2+HYpeDIrAIChKriq916e
+bVtNm/Ll3AWLo6NjTE1NWzRv2sXHW/eXHz1+6ujxU5qHf/91rmpVp3nfzJ44eYZYbPxZ3Tqf1a2T
+5yUmJpKRXwzp3XewMjt7765tzjVr6HiukKMnQo6e4PF4dna23bv5fj6gDxF18+sSGxc/euykTKnU
+o0XzhQu+JqIi+lDZwaGey2evXr1u2sRd97fJmbdg8bwFi7ntnj26TRg/SscXNmvaeNXyxVNnfLVh
+7Ur3RjrVwAb272NtZbVj197vVqwhYmvVcp42daKXZxsimvTlmB+3/Tp0xLjU1FR7e7t+fQLatvGo
+UsXp+1VLV6/ZEBMTW6uW88YN3xsbG+tyIjtb262b1636fv2ixd/xeXw3t3pzv55FRGNGDl+24vtF
+S1ZMnzqxaeMCPiv/Hn4/bPpxw5oVOn4IGtq/GcfKDmFnjhbY8/lzZ0+f/Y2FubmNjU3LljmxtUe3
+ri9evBwQ+IWJiUmH9rqOv/P5/HXffzc/eOnmrduaNmns27kTN9lAR0ZGRvODl7yOijYyErrWc9m6
+cS03xW39mhUrV6/r2qOPQqGsWaPaxAljCjuCVJq1eOnKV69fGwmNmjdvMnb0CCKaNSPou+Xf+/n3
+EwgEPXv4BQ7sp3uXtJmYmERHx46dEJSQmGRhYd7Ko8XMaZM1z+b5mqKiYoK//S4lJcVEIunZs7tX
+uzb07nfdt3fPAn8PH0CBP+w8+3Tt4jNo6Kg3aWk+3h1GfjH0w3QMAOAjweAeuDqaF7zEztZm8sRx
+5d2RT9uJk2cOHArZ9euP5d2RYpsYNKO9l2ff3j3LuyMfwqf7NeXn5e23beuGOrVrlXdHAADKB+6B
+q5PomNhzv1/s08u/vDvyaZPJZPt+O1R2V5DWu5u37iQnp7As+9flv//590a7tq3Lu0cfwif3NQEA
+QBEQ9d5vw8atPXt/PmL4YM0qTiiBK1evtW3va2Nj3c3vk7nDb0REZK9+g1q367x6zYYVyxbZ67Zm
+5ZP2KX5NAABQBAzgAgAAABgsVPUAAAAADBYzYZyuC0IBAAAA4NPClPLetQAAAADw0RKE3ynehWEB
+AAAA4FOBuXoAAAAABgtRDwAAAMBg5UQ910YtXRu13LRlm2Yj/67csx+2ewAAAABQcm+reppJe5i9
+BwAAAGAYMIALAAAAYLAQ9QAAAAAMFqIeAAAAgMFC1AMAAAAwWGUW9Vh1WR0ZAAAAAHQjKIuDsqpU
+NnUrWYzkCWzL4vgaCoUiOiamqlMVvoBfykMVeH0ZKGsbN/+Uf8U3votiKfAzBAAA4Og/6rGKSDuL
+RwLLFtFJCr0fPA+1Wm1jY5OemSE2NhaJRKU8GhLGB3b/9rXCnsJ3oaMiPkMAAADSe9RjZXcc7ZIs
+Kzd+E/9cv0cujJAvtLK0TE5JUSqzTU1NSnk0lmX10quKqVi1JTd3j6J3qJjfhX4/QwAAAH1GPVZ6
+qVo1U1PLWqROZ1mW1Fl6PHiBVCo1n8dXKBSWFhYyWdabN2kWFuZlfVIogo73U/ly/Oiy7smnC58h
+AADokd6iHpN+xPmzeiKJEbGZRIyJubVd1kNF1j+KbGEW+xnPuKG+TkRE6enpMrmCWNbIyEhkYkRE
+arXa1NTMyEiUmJhka2ujx3NBcWHeWOnhMwQAAH3RzwpcoXRPLbdmIjGPWDkREbFCocy+avUqderX
+qFuthlOcRP4zK3tR+hNJpdLo2FiWyNTExNLSQiIRc8N8PB5PrVYLBAIHh0oJCYmlPxHAxwMDtQAA
+UGKljnqqdJF8W836rQW8RFaVwqqScv+8YZUxamUkqf4nNo6t4mzlYP0HyW6V5lRv3qRJM7NMTUyU
+SqVMJsuSyZRKJRGp1ersXETk5OQYF5+QrVKV5lxubm4MwzAMY2dnFxgYmJSUpMurtm3b1r1799Kc
+Fwq0bt26xo0bC4XCcePGabcfPXq0Vq1aYrG4S5cu0dHRmvbg4GBbW1sLC4sJEyZwv4o8dH9hRkZG
+t27dmjVrNmzYMM30wQkTJuzdu7dM3mo+XM5D2gMAgJIpbdRjlc8tLUmRuiErYXlW4pqsxB9y/iRt
+ykrZLU8LlWf8p5CGKzL/kBg/tRQeJtXLkp1IliXLlGapWbVUmqXKVskVivT0jJTUN4mJScnJKSmp
+qUnJyUnJyXHx8cnJKRKJWC6Xl/Kt7dixQ6lUXr169dGjR19//fV79y8wUoBeVKlSZdGiRQMGDNBu
+jIiICAwMXL58eUxMjJ2d3dChQ7n2PXv2bN269dKlS/fv3//zzz+/++67PEcr1gu3b99ev37969ev
+p6amhoaGEtH169efPn0aGBhY5m+biIju377G/fkwpwMAAANT2rl6jLF7TGKqtVmMieilWvm6sL0Y
+RsQSa2bZSBq7VSEJJkZYrLOoVOrklBSRsUgqzSIiVp1zfWa+QMDn87UvqicUCpVKJZ/PMzE1Ldk7
+0uDxeAKBoE6dOgMGDAgJCZk/f/6OHTuSk5Nr1669du1aLy8vItqyZcvx48ctLS1v3LgRGBi4YcMG
+qVRao0YNa2vrmzdvlrIDn7QCq1Alzit9+vQhorNnz2rn6X379nl4ePTt25eIli1bVr169devX1ep
+UmXHjh3jx493c3Mjojlz5gQHB8+dO1f7aMV6YUREROPGjYmoYcOGERERarU6KCjo559/Ltkb0QXW
+WwAAgB7pYVkGz6R9coY5m82amhqpFf/Lba3EE1YjNolVp7PZiSwrI6LsrH9t7PyiYo/zzPsU6xTJ
+KSlisTg9PV3TIhQKhUKhkchIla1S596ZQ2QkUiiVxiIjiURS+vfFycjICA0NrVu3br169f79919b
+W9vt27f379//xYsXYrGYiM6ePXvhwgUvLy+WZZ2cnI4ePXry5El9nf3Tdf/2tTxpT+91qfDwcHd3
+d267atWq1tbW4eHhVapUCQ8PnzhxItfu7u7+/PlzmUxmbGxcshe6ubldvXp1yJAhV69enTdv3tat
+W9u1a+fi4qLf96KBgVoAANAv/azA5UmapMrNVKl7LK2MVPJHPEGlzKwmaYn2AqHASCQ3N0tg5Wdz
+9mReGvMExb22slKp1FTyiMjc3CxbrWbVbJY0y1hkzOMx2SqVyEgkk8tMTEzEWv9RL42JEyfOmDEj
+NTW1VatWy5Ytc3Jy4tpHjx69ZMmSJ0+eNGrUiIhatmzJVfgYhtHLeQ2Gdtori/HHjIyMOnXqaB5a
+WFhw/zOQkZFhbm6uaeRatKNesV44ZMiQ69evt2nTxtvb29XVderUqX/++eeUKVNu3LjRrl27JUuW
+6PdNFeuDQi4EAID30t/FVkR10hVjshN+tLUXqZWv1WScbdxTJbCTq1LeRF2qUsWJZL8QsaR+IzBS
+yVXpDN9MxyNnZ2fz+Xx17ox4KxtrWVaWhbm5QCBUKORymYKIxMbGaekZNlZWQqPiDQ0XYcmSJX37
+9rWysjIyMiKinTt3btiwITY2ls/nR0dHJybmrPOtXLmyvs5oeLi0V0bzzExNTdPS0jQP37x5Y2Zm
+lqf9zZs3XEuJX2hkZLR582aucfjw4QsWLDh9+nRSUtJff/3VrVu3sLCwzp076/d94bp6AACgR/q8
+hDJj5JjFmxofs9ahij3JiIgYnpB49nzL/lGvd1Sp0p6VXWTVmQI+j1VLdY96KpWKxzCK7GwiMjMz
+y8qU2tvbae9gbGycnJJib2fH55f2TrjaLCwsKlWqxG0/ffo0KCjozz//bNCgARE5OztrFmNqF/N4
+PP1cvMaQlN16AldX1wsXLnDbr1+/Tk5OdnV15drv3r3r7+9PRHfu3KlVq5bxu4Xekr3w8uXLSUlJ
+AQEB8+bNa9WqFRG1bt36/v37eo96hOvqAQCA/ug5mjACC7nJ1zGvJCplinY7a9Q8W05EPIZnLs+S
+8YS2uh8zd6UFn+Hx8t/9TJmtTEl941Cpkn5zXh5paWkSiYQb9Ttx4kRERESBu9nb20dGRmIprt5l
+Z2fLZDKVSqVSqWQyGfcJDxw48O+//z5x4kRGRsa8efM6duxYpUoVIho6dOiWLVseP34cExOzYsWK
+4cOHcwdxcXHZtm1bCV7IdWD69Onr1q0joho1aoSHhxPR/fv3a9asWdbv3c3dg/tT1icCAACDpP8q
+FMMTKs2/epNqxfDero1g1I8ZJoNIzbJGSqYyUTFiGY/H46plrFpNxMoVb2f68fmCLJnMoZJ9Wc+T
+a9q06eeff+7u7t6uXbuwsDCuCJSfj49PlSpV7O3ta9WqVab9qWiCg4PFYvGWLVu2bdsmFou5FbXO
+zs67d+8OCgqys7OLjo7euXMnt/PgwYNHjhzZpk0bFxeXNm3azJkzh4hUKlVsbKyHh0dxX8hZv359
+9+7dnZ2diSgwMPD169fcobgSYJniyqK42AoAAJSMPgdw1Wq15m/WappSTaRQEpE667/KVk/47D3i
+W2ZkWKmEfsXNZeYWZqmpaXyBQJmdLRQK37xJ42Zf8Xg8x8oOarWaYYiIIf2tjbh//36ellWrVq1a
+tSpP47hx47Qv6isSic6cOaOXDoC2xYsXL168OH97r169evXqlb994cKFCxcu1G65detWx44duQup
+FOuFnGnTpmm2xWLxsWPHitX/UkLOAwCAEtND1FPnYFmW+wepWTXlTmXjyW9WtvxTLPiDZdUKRZ3k
+9MasqRNPpWIYRpeZbSzLErEiIxFDDF/AV6tUKpWKZdn09DTtK6pwCY/HMMTwGIa4G12U/q2BwWjW
+rNmRI0fKuxc6wXoLAADQo1JFvZxwl0ulVrNqtUqVE/pYliVVXDWLEBPJAyKhQlkzNrGuwrg/Lzub
+x+PzeAy9bx1D7nGIZdU2NtYJCQlCoZCbk6dQZjMymZAv0MQ6hsewDMMwLI9hWIbh8RgiBL4PDTGl
+lDAnDwAA9Ku0UY9lWZblMlluUY9lVSpVTqEvm9TKdKXCIUNqmpjRIduoM59VsyyfzfmbZVm2sDTG
+1fOIGCLuinqsjY3Nm7Q0hVIpEPCVCoVQIFAxaq6IRzwescTtzzLEEMOyhJj3gSGmlJ5mZbeOsFYX
+AACKVqqol7NaglUxDI/HY4n4DKMmIoZhcjKgUeU42ZjkrCcKXnOeyJHP44ZtNX8XVXVjGC6u5aRB
+liUejywtzLNkMrlMbmJiIhIZ5exIRG/LeETEELEMwytuSe/+7Wv4D2dp6HFKGb4LAAAAvSjtXD0u
+sqnVarWa4UZauasdc8UJlliG3FhyM2KY3GzH4/HeBr2iD87twOdzcY+IVbNEJhKJRMzN0mNzl2IQ
+5U7UI2K5AFrcnLdx80/Ff/dQJvBdAAAA6IselmUwDMPn87kpdKxmTFdrKCqn1Ma8p4xX2ME1f7Ms
+91ru4Jodcv5JpVt+ixrSxwPfBQAAgL7o82IrRGW79DX3yG8reQAAAABQBNzICwAAAMBgIeoBAAAA
+GCxEPQAAAACDhagHAAAAYLBylmVobnKAux0AAAAAGAwGd1IHAAAAMFQYwAUAAAAwWIh6AAAAAAaL
+mTBuVHn3AQAAAADKBObqAQAAABgsDOACAAAAGCxEPQAAAACDhagHAAAAYLAQ9QAAAAAMFqIeAAAA
+gMFC1AMAAAAwWIh6AAAAAAYLUQ8AAADAYAkKe+LQ0dAP2Q8AAIBi6Rvgq9l2bdSyHHsC8JH4cvzo
+/HdBKzTqAQAAfELC7/xT3l0A+BhhABcAAADAYCHqAQAAABgsRD0AAAAAg4WoBwAAAGCwEPUAAKAC
++Wbet7/u2FPYsxERkW29uuh4qKjomOatOujr1ABlBFEPAAAM0PkLlwYPG93Mo30rT5/AISMPHzmu
+Vqs/wHnHTpjyw6YftVsuXPrTy9tPpVL16O7r4dH8A/QBQBuiHgAAGIugngAAACAASURBVJoDh0K+
+mfetf/euJ47uP3/2+PSpky5f/TslJfUDnLpnD78Tp0JZltW0nDh5prtfFz6f79GyuctndT9AHwC0
+IeoBAIBBkcvla9ZtmjUjqH+/3pUdHCQScdMm7mtWLbOxsdbejWXZX3bs7uLXq61Xlxmz56amvtE8
+9evOvV7efh0799i7/yDX8vx/EUO/GNvK06ddx66LlqxQKJSFnd27o9eb1Dc3bt7mHqalpf/x52X/
+Hn707gDuiZNn/HsNbOXpM3rspKjoGCL6et6iX3fuJaL4+AQ3d499vx0iolevolq38/kw9UgwVIh6
+AABgUMIfPEpPT+/SuVPRu50ODdu3/9DWTWvPhR5lGGbBwqVce1p6+qvXr38PPbblhzUbN/9089Yd
+ImJZdtKXY/+6eObQb7vu3w/ncliBRCJRly7ex0+e4R6Ghv1es0aNz+rW0d7nytVra9ZvWvHdosuX
+Qtu09pg+8xuWZZs3bfzf9ZtE9N+Nm1WqOF2/cYuIrt+42bSJO4+H/1hDyeHXAwAABiUlNVUsFpuY
+SLiHYydM8fL28/L2u3zlmvZup06dHRQ4oEaN6mKxeMbUSecv/iGVZhGRWq0OmjheKBTWrVu7Z49u
+p8+EEVHtWs7NmzURCAT2draBn/e/mVu0K1DPHt3Czl2QyxVEdPzE6Z7+fnl2OHAwZMigAS6f1eXz
++cOGBkZFRUfHxDZr2uTmrTtqtfrGjdsjhg++dfsuEf1341azpk3099lARYQbowEAgEGxtLDIysrK
+zJRyaW/50oXZ2dmDho6SK+Tau8UnJDpWduC2K1Wy5/P58fHxRCSRiM3Nzbh2x8oOXKUtMTFp5er1
+d+7dz87OlsvlNWtUL6IDTRo3srKyuHDxDzfX+vfuP1j3/fI8O0THxNwLf3A45AT3kMfnJSYmNWro
+JhYbP3r89MbN2+PGjDgScuLFi8jr128O/ry/Hj4UqMAQ9QAAwKC4udYzNTUNO3e+V0APIrK0tCAi
+Hj/vKJa9nW10TCy3HRcXr1Kp7O3t4+LipdKs9PR0MzMzIoqJjbWzsyWiVd+vNzc3O3Z4r0gkOn7i
+9MHDR4vug393v+MnT0e8iGzT2iPPHEEicnCo1Kd3z4H9++Rpb960ybnfLyiVSnt7u2bNGh87cTot
+Ld3FBSs5oFQwgAsAAAZFJBJNmTx++ap1Bw8fjY2Ny8yU3r5zLyM9k2EY7d38unbeu+9A5MtXMpns
++7UbO7ZvJ5GIiYjH463/YatSqXz69Pmx46d9u3QiovSMzBrVq4lEIplMdjjk+Hv74N/D7+9r/x06
+ciz/6C0R9e/b++ftu8IfPGRZNiMj4+y581x7s2aN9+4/2LRpYyJq0azJ3v0HmzRuhIl6UEqo6gEA
+gKEZ2L+PtZXVjl17v1uxhoitVct52tSJXp5ttPfp5tclNi5+9NhJmVKpR4vmCxd8zbWbm5k5OTl2
+8u3J5/PHjx3ZrGljIpr05Zh5CxafOnPW2Ni4QQPXO3fuFd0BJ8fK7o0aPH7yrINXu/zPerZtNW3K
+l3MXLI6OjjE1NW3RvGkXH28iat60cWamtFlTdyJq0rhRVpaMi30ApcHcv32twCcOHQ39wF0BAADQ
+Xd8AX822a6OW4Xf+KcfOAHwMNm3ZNmHcqDyNKAsDAAAAGCxEPQAAAACDhagHAAAAYLAQ9QAAAAAM
+FqIeAAAAgMHCxVYAAOCT9+X40eXdBYCPFKIeAAB88vJfYAIAOBjABQAAADBYiHoAAAAABgtRDwAA
+AMBgIeoBAAAAGCxEPQAAAACDhagHAAAAYLAQ9QAAAAAMFqIeAAAAgMFC1AMAAAAwWIh6AAAAAAYL
+UQ8AAADAYCHqAQAAABgsRD0AAAAAg4WoBwAAAGCwBOXdAQAAgDK0acu28u4CgD5t3PxT+J1/dN8f
+UQ8AAAwc0h4YjPu3rxX3JYh6AABg+FiWLe8uAJQWwzAleBWiHgAAVAjFGvMC+NiUuDiNZRkAAAAA
+BgtRDwAAAMBgIeoBAAAAGCxEPQAAAACDhagHAABQQjNmz927/2BpjhAVHdO8VYfivqpz14DwBw9L
+c16oOBD1AACgwgnoE9igcavomFhNy9Avxrq5ezx6/OQD98TSwmLWjCC9HCohMXH6rG882/s282jf
+q++g/QcOF+vlHTv3QHw0SLjYCgAAVETVq1U9eSp0zKjhRPT6dVRcXLxQKPzw3TAxkfTrE6CXQy0I
+XmosNj58YJeZmenTZ//TDrJQkaGqBwAAFVH3br7HT57hto+fPNO9m6/m8rRKpXLt+k2dfHt6dvAN
+XrRMJpNx7cdOnOrZ+/MWrTt0Dxhw+849rjExMWnU2EnNPNoPGzEuPj6Be3nQ1NmeHXxbefqM+3JK
+TGxO5Joxe+6yFd+PGjupZ+/PNTtrD+DGJyROn/lNu45d23h1nrdgcRGHKlD4w0e9A/zt7e3EYnHD
+Bq6+nb2JaMLEaXv2vR1i7tVv0PkLl6TSrGkzv27j1bmVp8+AwC9kMtm3S1ckJiZNnDyzc9eA4ydO
+E1H4g4dDho/xaNupV79B1/75T/MW1m3YPHzk+KYtvUaPm5ySmjoveEmL1h169RsUERFZ2q8Eygai
+HgAAVETONWtIJOJ79x8Q0YlTZ/x7+Gme2rj5p3v3H/y255ew0yFv0tJ+2PwTEV364/L3azcuCv76
+nysXtm5cY2Ntze189PipaUFfXv3znL29HXeRW5alTt7tw06HXDx3ws7WdsmyVZoj//nXlRXLFh07
+sq9+PZc8V8RVq9WTgmZaWlmcOXH44rlTAT27F32o/Bq7N1y/cUto2HntROjv3+3kqZxE+/jJ0/j4
+hHaebQ4cClGp1BfPnbryx9n5c2fx+fx5X8+ytbX5Yf3KsDNH/Xv4JSenjBkfNHjQgKt/hn0zZ8aM
+WXOTkpK5g5w4Ffr17Ol/XQzNysr6fPBIzzatrvwR1qpli7XrN5X8y4CyhKgHAAAVVM/ufidOnrl5
+6461lVX1alU17b8dDJkaNMHGxlosFk8YOyos7DwRHQ45NnTw540aNmAYxsnJsWpVp5yD9PCrX9/F
+yEgY4N/twaPHRGRkJOzRvatYLDY2Nh43duSNm3c0R+7Rrau1tRURtfNsze2s8fjJs8iXr2bPmGpi
+IjEyEjZt4l70ofJbtniBdwev7b/s7Nq9b69+g67fuEVEHbw8X0S+inz5iohOnDzj26WTUCgUCgTJ
+yckRL17weDzX+vXyj1yfPhPWqIFbFx9vHo/XrGnjZs0a/3Xlb+4p/+5d69atLZGIfTp1tLO16ezT
+USgUdu/m+/DdtwMfD8zVAwCACqqrr0/v/oOlUql/97clvYzMzPT09NlfLWB4PCIilpXJ5UQUGxtX
+tZtT/oPY2dlyG2KxWCrNIiK1Wr3+hy3nL/4hlWYxDJOenq5Wq3k8HhFZWlpwO4tEIm5njdjYOIdK
+9kZG76SuIg6Vn1gsHjv6i7Gjv5BKs7b+tH3y1FkXwk4YGxv7dvY+eSp0/NiRp8+ErVm9jIj69glI
+TEoKmjZHLpMHBHSfNGFMnmNGx8Tevnuve8AA7mFWVpZ7o4bctq2tTc7pjEVa28Z53g58PBD1AACg
+grK2tqpfz+XM2XOzZkzRNJqamJiamq5fu6KWc03tnR0cKr16HaXLYUOOnvz3vxs7t2+1srKMiY31
+8Q1gWfa9r3JwqBQbF69UKrVrbCU7lEQiHj500M+/7IqNjatRo3pP/25fzQ1u0riRsbFxo4YNiEgk
+MgqaND5o0viIiMhxX05xq+/i3bG9dtpzcLBv1bLF6pVLdHm/8JHDAC4AAFRc33w145dtm83NzbQb
++/ft9d2KNXFx8UQUn5B4+co1IurTq+euPfvv3gtnWTYqOuZ14bEvPSPDzs7OysqSiPbsPaBjT1w+
+q1O9WtWVq9dLpVkKhfLGzdvFPdSq79ffvRculWalpKb+9PMOKytLJydHInJv1IAhZsXqdT26d+X2
+vPbPf5EvX7Esa2llIRQK+XwBEVlbW718+Zrboauvz7//3QgNO5+dna1QKK/fuFX0ihD4mCHqAQBA
+xeXkWLlhA9c8jZO+HOPeqMHQEeNatuk4csyX/4uIIKL2Xm2DJo77Zv6iFq07jvtySlJycmHH7Nvb
+X6GQ9+k/ZOgXY62srHTsCcMwG9auiE9I6Nw1oINPt2MnThf3UEZGRvODl7Tr2LWbf7+nT59t3bhW
+UyD07+H39OnzHt18uYdRUTFjJ0zxaOvdp99gH5+OXu3aENGYkcNXrdnQytPn0JFjdra2WzevO3Dw
+SLuOXb079/j5l51q9furifBxYu7fvlbgE4eOhn7grgAAAOiub4CvLrtt2rJt05ZtLMuG3/mnrLv0
+0Tpx8syBQyG7fv2xvDsCJcf9ku/fvubaqGWxfsyo6gEAABgymUy277dD+rpQM3xyEPUAAAAM1pWr
+19q297Wxse7m16W8+wLlAytwAQAADFab1h7Xr10q715AeUJVDwAAAMBgoaoHAAAVQp4bkQFUEIh6
+AABg+BiGKe8uAJQPRD0AADB8utxkorhu3bq1c+dOlmWbN2/eu3dvsVis91MA5FGCawZhrh4AAFR0
+X44fXdyXXL9+vUmTJo8fPxYIBNu2bXNxcbl582ZZ9A2glBD1AACgotu4+afivsTV1dXLyysxMbF/
+//7bt2+fO3duly5doqOjy6J7AKWBqAcAABVdCap6YrH43Llzzs7Oo0aNioqK6ty586BBg5YtW1YW
+3QMoDUQ9AACo6HSv6l2/fv3NmzfctlAo3LNnz8OHD1+9eqVSqbp27Xrq1Kky6yNACSHqAQBARadj
+Ve/KlStt2rRp3LhxQkIC18Lj8YyMjBQKhVgstrCwSEtLK8tuApQEoh4AAFR0Olb1QkJCPD09fXx8
+PD09z58/n5ycPH36dFtb25o1a0okkoSEBCsrq7LuKkBx4WIrAABQ0X05frQuac/R0TEyMnLmzJkM
+w4wcOVIulxPRrl27KleuHB8f//Lly+fPnz979qx27dpl32UAXSHqAQBARZRn0Fb7YWGxr2fPnsuW
+LZPL5YsWLZo7d25iYqKxsbGFhQXLsiqVys/P7/Xr1506dbpy5YqTk1Nx+3Pt2rVZs2bdunVLIBDU
+r19/6dKlXl5eOr722bNn7u7uGRkZxT0pVASIegAAUEEVGOmKmLdXq1at4cOHT548eefOnZaWlubm
+5gzDyGQyIsrMzGQYZuLEiZmZmT4+Pn/99ZeNjY3uPZHJZN27d58xY8bJkyezs7OvXbsmEOA/0KAf
+mKsHAAAVne63Tfvuu+/q1avn7e29bt26kJCQ1atXu7u7z5w509zc3NLSks/nz507t3Xr1r6+vunp
+6bp34MWLF0lJSVOmTDE3N7e2tvbz82vTpo1CobC2tr537x63T3x8PDcjMDw8vE2bNlZWVra2tqNG
+jSKiXr16SaXSGjVq1KhR48mTJ0S0a9eu+vXrW1lZ+fj4vHjxgjuCg4PDpk2b6tata2pqOn369Fev
+Xnl5eZmamvbo0SMzM1P33sKnBVEPAABAV3w+/4cfftizZ09qauqJEyfi4+ODg4MvX7787bffKpVK
+Pp+fnZ29cOFCZ2fnnj17cgU/XdSoUcPJyWn48OFnz55NSUnhGo2MjAYOHLh7927u4b59+7y9ve3s
+7ObMmdOrV6/k5OSoqKgxY8YQUUhIiEQiefHixYsXL+rWrXv27Nmvvvpq7969CQkJXbp06d+/v+a+
+cEeOHLl69erdu3e3b98+YMCADRs2xMbGJicnb9u2Td8fFXwsEPUAAKDiYhiGK+lpNih3DFf77zya
+Nm26cuXKQ4cObdq0afTo0RcvXjx9+vTKlSsVCoVAIFCr1d99951EIhkwYIBSqdSlG8bGxlevXrWx
+sZk4caK9vb2fn9+rV6+IaOjQofv27eOC2q5du4YMGUJEQqHw2bNnr1+/FolELVq0yH+0LVu2BAUF
+ubu7CwSC6dOnR0REREZGck/NmTPH1tbW2dnZ09OzY8eODRs2NDU17dOnz61bt4r/4cGnAVEPAAAq
+LpZluSCl2aDcOXzafxetatWqFy9ePHz48Pr16xUKhVAoZBhm5cqVaWlpI0eOVKvVuvSkWrVqGzdu
+fPr0aWRkpEql4kZmPTw8xGLxpUuXHj169OzZM39/fyJat25dVlZW48aN3dzc9u3bl/9QkZGR69at
+c3FxcXFxqVevHp/Pj42N5Z5ycHDgNiQSifY2lnQYMMz6BAAAKK3q1atfvHjRy8tLIBCMGjVKKBTy
++fxVq1ZNmDBhypQp69at0306oKOj46hRoyZPnsw9HDZs2O7dux0cHPr27WtsbExEVatW3bFjh1qt
+PnfuXI8ePTp16sTjvVO4qVq16qhRoyZMmKDf9wifKFT1AACgotPU80rD2dn5woUL27dv/+WXXzIy
+MgQCgUgkWrly5aVLl4KDg4t+bURExIIFCx49eiSTyZ49e7Zly5aWLVtyTw0ePDgkJGT37t1Dhw7l
+Wg4dOpSQkMDj8SpVqsQwjEAgsLOzy8rKiomJ4XYYN27c8uXLr1+/zrLsmzdvDh48WPp3B58uVPUA
+AKCC0vF+aLqrU6cOV9sTCoU9e/YUiURmZmbLli2bOnWqlZXVlClTCnuhubl5ZGSkr69vTEyMtbW1
+j4/PqlWruKeqVavWuHHj58+fe3p6ci0XLlyYOHGiTCZzcHDYsWMHd4uO2bNnN2zYUKlU/v333127
+dl2+fPmIESNevHhhYWHRoUOHfv366fedwieEuX/7WoFPHDoa+oG7AgAAoLu+Ab667LZpy7ZNW7YV
+XbfT8W4ZOgoPD2/fvn1QUJCvr69IJMrMzHz58uXMmTODg4O/+OKLEhxw5MiRlStXXrx4sb56CJ+u
+8Dv/uDZqGX7nH91fgqoeAABUdHrMeUTk6ur6+++/d+rUiYi8vb2FQqG9vf3ChQvnzp1rbm7ep0+f
+Yh0tMjLy8OHDWCELJYa5egAAUNHpfSS3UaNGZ8+eXb9+/fnz5+VyuUAgqF279pw5cyZPnpycnKz7
+cebNm+fq6jpz5syaNWvqt4dQcaCqBwAAFZ1+q3qcJk2anDp1qlu3bgzDdOrUyd7ensfjubu7//nn
+nwEBAToe5Ntvv/3222/13jeoUFDVAwCAik7vVT1O8+bNjx07tmbNmgsXLkRGRqanp9++fVtzNTuA
+DwNVPQAAqOjKoqrHadWq1ZEjR/r163f06NGnT5/27dtXcxUVgA8DUQ8AACo6/a7AzaNdu3YRERF3
+7961tbWtXbt2GZ0FoDAYwAUAgIquLHIed/fb/fv3P378WCKReHh4IOdBuUBVDwAAKjo9VvVu3brF
+smxmZubBg4fd3OonJaU8ffq8V6+e1tbWDx8+8vbuqJezAOgOUQ8AACo6feW8Fy9eHD4cIhZL4uJi
+3dwaxsXFpKen1anjcvTo8cTEBJFIXK1a1Tp16ujlXAA6wgAuAABUdPpagVu9enVraytbWzsHB4cn
+Tx7Y2VWysLB8+vSRvX0la2sba2sL5Dz48BD1AACgotNXVY9hmGnTpsrlUmtrWxsbu2fPHtvY2Fla
+Wj1//rRSJQe1mv7++2+9nAhAd4h6AABQ0en3unqTJ09Sq5WWlta2tvbPnj2xtLS2tLT+3/+eW1pa
+//HH5YsXL+nxXADvhagHAAAVnd5X4E6YMJ7HY83Nzezs7F+8eG5ubmFtbfPixf+SkhI++6yufs8F
+UDREPQAAqOj0freM6OiYBw8evnr1UiIxsbW1f/kywsREYmNj4+Hh4ejoqN9zZWRkMAwjk8n0e1gw
+GFiBCwAAFVGeeKf9sJRFvvj4+M2bt7i41E9LS7W0NCVibW3tX7166ehY9c8//+rduxfDMPlf5ebm
+Fh4eTkQSiaRp06YbN25s0KBBaboBwEHUAwCACqrASFfKCl9ycvL69RuqVq2RlpYya9YMhmH27dsf
+H59ob+/w8mXE/PlzC8x5nB07dgQGBqanp3/zzTdDhgy5fft2aXoCwMEALgAAVHRFxK9iSUtL+/77
+NdWq1UxOTpw+fRp32M8/H+joWInPFzg6Vil6TQaPxxMIBFZWVsOHD3/w4AHX+OzZMx8fHysrq3r1
+6h04cIBrZFl23rx59vb21atX37dvH9e4cuXKPn36aI42efLkoKAgvbwv+KQh6gEAABRDRkYGy7L5
+26VS6YoVK6tXd46Li5k1awaP9/a/sP369atZs1psbHTXrr66HH/Pnj2tWrUiIpVK5e/v36pVq7i4
+uB9//HHkyJFcqW/37t379u3777//wsPDjx8/zr1w8ODBoaGhqampRJSdnb1///6hQ4fq5S3DJw1R
+DwAAKi6GYbjam2aDcsdwtf/WiI+Pnz8/+IcfNuZJezKZbNmy5dWrO8fEvJ4zZxafz89zop49/Ves
+WG5iYlJEZ4YMGcIwjJmZ2e7du5ctW0ZEN2/ejI2NnT9/vpGRkaen54ABA3bv3k1E+/btmzRpUvXq
+1U1NTefPn8+9vHLlyp6engcPHiSi0NBQW1vbpk2blvyjAUOBqAcAABUXy7JcaNNsUO4cPu2/NR48
+eGBra8vnG61Zs1azv0KhWLbsu2rVarx+/XL27FlCobDAc713mHjXrl0sy8pksh9//NHPzy8qKio6
+OtrJyUkgyJlYX6NGjaioKCKKjo6uWbMm1+js7Kw5wrBhw7gsuHv37iFDhhTrowBDhagHAACgK2dn
+54SE+JSUJLHYdNWq1Wq1Ojs7e9myZVWqVH/1KnLOnFkikaiUpxCJRH369BGLxX/99Zejo2NUVFR2
+djb31IsXL5ycnIjI0dExLi6Oa9RsEFFAQMDdu3fv379/8uTJQYMGlbInYBgQ9QAAoKIrcO5dgbut
+Xr3GxcU1JSUlMTHB3NxqxYqVCxcuqly56suXL2bNmiEWi0vTDS44ZmZm/vbbb/Hx8fXq1WvSpIm9
+vf2SJUuUSuWVK1cOHDgQGBhIRAMGDNi2bVtWVhYRrV27VnMEsVjcp0+fwMDAFi1aVKtWrTSdAYOB
+i60AAEAFVdzrqjAM06FD+5s3b332Wb3Hjx+qVEpHx6pRUVEZGfeDgxeYmpqWsj/Dhg0bNmyYkZFR
+rVq1fv7550aNGhHR8ePHx48fv2bNGgcHh61btzZp0oSIhgwZ8vjx4+bNm5ubm/v7++c5yM8//7x9
++/ZSdgYMBqIeAABURNqT8L4cP1qXyyY/fPjw+vUbUmnm69cvXVzqP3wYHhX1qmHDxjExr0tZzyOi
++/fvF9het27d8+fP52nk8XhLly5dunQp93DOnDmap2rUqMHV9krZHzAYGMAFAICKTsfbY7AsKxAI
+XF0bZmRkvHz5on5918zMjFevIp2cqi5ZslQul5d1P99LrVavXr164MCB5ubm5d0X+Fgg6gEAQEWn
+40hu/fr1Bw8OjIyMcHVtkJmZGRHxv/r1G0ilmf/73/Nq1WouWbKUmzxXXjIzM83Nzc+dO7dw4cJy
+7AZ8bBD1AACgotP9pre1atXi8ejhw3A3t4ZyufzZsyf16zdQKOTPnj2pUaPW0qXLMjIyyrSrRTAx
+McnIyAgPD69atWp59QE+Qoh6AABQ0em+PiMqKkouVyqVyufPn7q6NlCpsp88eVi/foOMjLSIiOcM
+w4uJiS3TrgIUF5ZlAABARad7Va9KlSqDBwc6OjrK5fINGzZaW9vUrFnj77//Hj78i8qVHd68eVOn
+Tu2y7ClAsSHqAQBARafjClyOq6srtzF1atC///7r5+fXr19f7k4Yjo6OZdVFgJLCAC4AAFR0uuc8
+bba2tn5+fqTDHc8AyhGiHgAAVHTFvZYywCcEA7gAAFDRlayql6eYp+Pd1QA+MEQ9AACo6Io1V4/D
+MAw7ZAhxN0PLyKCEBIZhkPbgI4SoBwAAFV1Jct748eToSJaWRESpqWRqyvr6Iu3BRwhz9QAAoKIr
+1ly9nHqeoyM5O1O9elSvHjk7k6Mj2dmxzZtjiQZ8bFDVAwCAiq7Yc/VMTcnSkipVojp1clqSk8nU
+lCQSvfcNoJRQ1QMAgIru41yB++uvv3bv3r2IHbZs2dK3b98P1h/4RKGqBwAAFVGeeKf98P1FvowM
+Sk2luLich3FxlJpKGRkklZa4P25ubnPmzBk8eLCmxcPDw87OrsQHBOAg6gEAQAVVYKTTqcKXkJCz
+9jY5mYgoNZWioykhgVJS9Ng9FxcXFxcXPR4QKiYM4AIAQEVXrLUULMsyoaEUEUFPntCDB/TgAT15
+QhERFBXFPHumxxW42gO4Dg4Oy5cvb9GiRZ06dYYPH56dna29p0qlGj58eI8ePWQymb7ODgYDVT0A
+AIDiYVmWYRi2efOcdRhSKaWkMM+elelJ//333ytXrhBR27ZtDxw4EBgYyLXL5fKBAwcaGxuHhIQI
+BPjPOuSFqh4AAFRcDMNwJT3NBuWO4Wr/nR/Lssx//zF//MH88Qfz339cPY+LgNpH1ih9VydPniwU
+CoVCYadOnW7evMk1ZmZmdu/e3d7efs+ePch5UCD8LAAAoOLixlvzXPqYm8On/XcRr83fyAW7IUNY
+rVtp5D1FCdjY2HAbYrE4KSmJ275x44ZMJtu2bRuPh9oNFAxRDwAAQM/Gj2ffvZUG+fqyZXEvjXbt
+2rVr187b2/uPP/5wcnLS78HBMCDqAQBARafHBMYwzJAhLHcrjUqViCjnkiwZGdS8+XvSnlKp1Kyr
+4PP5Op5x8uTJCoWiY8eOly5dqly5cin7D4YHUQ8AACqoMrpycolvpTFixIgRI0Zw28OGDWvfvr2O
+Z5wxY4ZSqeTSXiUuYALkQtQDAICKqNg3Qytj9+/fz984fPhwbiM2NlbTOHfuXG5j3Lhx48aN47a/
++uqrr776qmy7CJ8mRD0AAAB9KoNbaQCUHKIeAACAPn2QW2kA6ApRDwAAQG+4i634+rIZGaR9sZWo
+KHr2TP8rcAHeC1EPAABAn7i017w5q3UrDeQ8KDeIegAAAHqmt4IGmAAAIABJREFUfdsMTUt5dQYq
+OEQ9AAAA/UO2g48E7qMCAAAAYLAQ9QAAAAAMFqIeAAAAgMFC1AMAAAAwWIh6AAAAAAYLUQ8AAADA
+YCHqAQAAABgsRD0AAAAAg4WoBwAAAGCwEPUAAAAADBaiHgAAAIDBQtQDAAAAMFiIegAAAAAGC1EP
+AAAAwGAh6gEAAAAYLEF5dwAqOouI4Gw1ZasoW0XcRpaCMmSUKac63sHl3TsAAIBPG6IelI/aScFq
+ltQsqSWUJ+qZGpOVCWWrSXk3WKqgTBllyKhup+Dy7jIAAMCnB1EPPqimWcFqllRqUhuRWk05aS93
+Q6WmbFXO31zsMzEma03sk1OGnDIR+wAAAHSGqAcfSDs2mGVJLSQ1SypNvMuX9tTqt89qSn0qFWWr
+yUREVmpSqUh5NzhTTpkyypQj9gEAABQFUQ8+hE78YJYlliU1j1giVjve5Ul7aq0sKMgNf+p3Sn0q
+NZmIKNuUsrViX4acPusUXN5vFAAA4OOCqAdlq7txMBfscqIe5W6wxPLebucZxs0f/t6mQPU7pb5s
+rdinuBvMlfoyZfSZT3B5v3UAAIDyh6gHZai3acE5r4jGIkJeEbFPM8PPRJQTARV33g7yIvYBAECF
+hagHZWWAZTBpUh29G++4jfc1Fja8m78EyLJ5S30qFZkYU7YpqdQk14p9Loh9AABQkSDqQZkYZB3M
+ssQyRCzx6G2G0z3n5bTzczcKG97N3RAKtPZ5t9SXrSZTTey7HZwpJ+4PYh8AABg8RD3Qv2G2wWxu
+vCNNyCNiWSIqTs7TbuTl7PPeUV01S2r+25Y8pb5sNZkYk0pN2WqS5cY+qYxcOgeX74cGAABQFhD1
+QM9GVAouIt5phz8eEemY87Qn9vHe2ec9me/dcmCe6/ap1GRqnPMwJ/bJKFNO9RD7AADAUCDqgT6N
+qRxcdLxjWSKGuLFd7m/eu7mwqCJf/lUd9G7m02Elh2YjJ/PllvpUKjI1pmwzUqko61ZwppykcsQ+
+AAD45CHqgT7xeEQFxTtu0l5OvKOiRnW1twss8r3TTgVnQZ0yX+5F+3IGebVKfdkqMhPnZEEu9nHJ
+D7EPAAA+OYh6oDcTqgQTEUvEEBHljXdFlfryb+cW/IhKWORjeTlBUJ27RFeXcd53BnlzC36mYlKp
+SKUm6a1grtSXKaP6XYLL5UMGAAAoFkQ90I+JVYMpN+exRMRtMMRwJb3CVmlojeTm3c7dregR3vcX
++fJcqLnIqJdnqe/b4V01ZatIoiYzcU5L5s2c2CeVI/YBAMDHC1EPcgQHB7+3pQg85m3Oe5v2WGKZ
+t41EeSNdEaO3hW2zRPwSFPnyPSxs9UaB+S9P5lOpSSUic3FOHETsAwCAjxaiHhAVkuq4Rl0CX1D1
+YNLkPK14R/nD3/tKfcUo+2kv6Sgo/BU2k6+oiX0sqdUFNAo1N+RlcwZz3wl/IjIX52xn3AyW5i7p
+cEXsAwCA8oaoB+8Jc8HBwUXvMLVmztVV6N1gV2ja06XUV5qyn25VvXce8guKfQUO77570T6V+p1S
+X7aaJEZkIc4Jghk3gqVyylSQFLEPAADKCaIelBZDRFplPE0jyxLDFBDvqHSlPl22+cWp6uV9WMR6
+jiLy37uZL2dun4jMJaRSk0pF6Tdyqn1SObn6Bn+g7wYAACo8RL2KTpfx2SIKe9OcgzURjyvRvY13
+Rdf2Cs+CBZb6Civ7Fb2wo6gR3oIevlPzK2I9B0tsvswnzLOSVzO8qyaVisQispDkNGpiX6ac3BD7
+AACgLCHqgU40US9P5uNKejlh793Mpyn1acp1eePde7NgbsGPdC7pafYs1gjve2t+mgJh0XW+/PlP
+zebNfCo1SbRj3/VgboRXitgHAABlAFEPiqfAzKfJdnkyH+Ub3n0b4FitLFhYqe/dmX9UZKnvvdtc
+97RHeAvLcwU81M6IBa3nKCz/sdy1mtXvDvKq367tkIjIIjcLpl0PlspJqkDsAwAAvUHUgxIKDg5O
+35m3kdH6R2GlPs0/3wZCrXhXwLP6LfVpRUDeu6U+HZdx5J/YV1TO025nSZi7vFeVL/O9rfZpxz45
+OXcMLulXBAAAgKhX4b13gW2JFVbq03V4V3slh15KfTrHwWIN6RY2sS9/znt7GZd342D+zKfiVvJK
+SKUm5d23pb5aiH0AAFBMiHpQwrSXsZPo3dpbYfQ5vKt9WO2M+G6pjwqbsaf7aC/pEO/yDelqP6Vm
+Cw52eaf3vftQlZv53sY+FYmNyFJNKjUp7gZnIfYBAEBxIOoBUeFpr4gUqEldzLsPi/CezEc6zN7T
+LvUVMs77/lKfzuU9HUd484bCwib25Vm3kafOp3koeHvRPu06H7eMQ6KJfXeCucyXpUDsAwCAQiHq
+QY78qS7P3TLyPMulIu05diXIfG/3L6zUl5vdNKU+zT5FZEF6b6lPx+u2UCETAXUZ0i1wN37ewp6O
+D/NnPm5un8qEstUkvxOcxS3jVVBtxD4AANCCqAdvvfe2GdobeSMa83ZP3TMfvbfUV9iFlwtfyVGM
+Up8u5b1C4iDlH+EtvOZXQArMvVCzTnW+d4uC+TOfSk0mIso2IZWK5HeCuVKfVE61vYN1+xIAAMBg
+IepBseVEPTY45zFXRWNzA1a+zEd6H97VLt0VVtLTsdRX2N3YirxWiyYOFjXCW/gEvneeKnA9R5F1
+PqH2RfvyrefIqfapSKUm2e3gLAVJFZSF2AcAUFEh6kFJBFUPfjuc+m5h723mowJin56HdwtZyaG9
+s55LfbpFQB0n8BUx1Ku9nuM9dT5B3ms1q7Tm+ZmIcrZzYp+cpAqqg9gHAFBhIOpBSbytlnGPC8p8
+2i0lm9JHWrGviFKf5p9vnyyopFdUuw6lvqLjYLFHeN+b9gpfz8HmX8PLteROBFSp8/7hLuZiIiKV
+SU7syxnkRewDADB0iHpQEmxhlTytHJeTvd5NdmWa+Qoc3i14Jce7R85TICR6Z2XG23l7VFS2K3Ax
+R2EjvIWlwELbi1zPkX8+n/ZF+1R5FvOqcub2cY1Zt94O8tbpFKzbtwEAAJ8MRD0oCTWbM5Ba6Oit
+diGtoMxX+mUcb1+iw/CuxTA29Vfm/ddnzl/qo5xUV1Spj3RbzKG1W9Fpr4BlHJoNnlapr/CElz8F
+svlu0aH5Y2qckwKzbgVLFTlLOup2CtbtCwEAgI8aoh6UBBf1mNzpcfkzX966GekQCou5jIO0Yt97
+h3eJiCmw1KddAnz3yEWX+vLO5HvfYg7KHwGJeLrN2yusKEhs3jCnS50v/7Wa35nbZ5yzLb2VM7cv
+S4HYBwDwCUPUg5JQq4lhcgJQgZlPM/WNKN/orQ6ZjwpKjEUoOvOZDWXTdzI8zdnfzXxvQ572w/+3
+d+8xkqXlYYffU92zOz07lyVRYqLIUuRIGMsYpGALc128XARWsJdlMWYTmyiAYmIciEjAsRCcIYj4
+okQmiYUjm8iBZLktsDaSLYFZLgsYRIxwQpQER4ks2+FiNsvuDjvd09118kdVnTr3rq6uvn3zPGqN
+T1dX99T0Sujn9/u+U6sd9e2ZgPtZ4Z1v45vEYmMXYM9Ir6MC16fb/jo29s2mfdPs+9J02if7AE4d
+qccyxsUs74pDaL4VbumLZva1l3fLp/XdtKVvt9+So77oT8DqT1i49vqGfwMjvYEHm2/RMfm4Ic5v
+TK+/86V80nyPXIvvfXa+2H8WAI6N1GMZk6neJI9W3nwdT6h8cX/NF3H+p4uH3928C0vz9G5P21Wf
+v8Sor6y95qHdgQRceIW37LnuJ1TOc1TbrnNht/Zg46Z9rY+NG+LCxnTxd5J9kyMd3/ucfLH/MgAc
+KanHMhpTvdU239ATZj82Fm6+qITdwJa+MuZqy7vRe9OWvt1+A6O+7tXegcMce63wFgOnNxrX9Rs1
+d7Zd+6vV4V+z+XZjdxwb4zh/Nsbj2BnHlS/lV7emi7yyD+DkkHosYzzJoFbhtZuv+bTYo/mqHVeO
+yjqeUL88+Ja+6F/eHV7GrV5UE7D6+oe365UPduzk67ld3yILuJ1LvY0x4fCJ3e7hX8/Gvo1xXJjt
+7bvyh9NFXtkHcOykHsvYHUcW9eld9DffrH9qX4ooJk+I2Y+YPaeoPxL127Xs6+ju+Z8qrry7tRxb
+X8AdGPXNf2jPqK/WdoNvxRZ7jfoW6rzWYY7RApE3Gf71rgWXC8Gd78YxOPzrXOGdL/KOY3ccD1ey
+77GyD+DIST2WsbsbWTb7iPlFLNV8tY10B2u+8rNDWd6tv9KBtqtZfNQX/Qm42Jf69vONhod/rezr
+3MnXbsEFs++i7AM4PlKPZeyMp3k3ikrz9W3UO4Tmqz5n+Oju4vZe3m28quqor/qXFZU63O+ob8ET
+G60vDazwjhaJvPaDoxjHvoNv3LXIW3687JbqbzQvr+56IA8ADofUYxk742nkjSfBV53tHUHzlUnX
+aL7Z4ubkCTfNVm+XnvPNv2tg1Ne/vLtnDlZ/5h6jvgU7b/EV3sE533xj32j+tIV28rXWfHeLuOX7
+9viF3/moPAQfwOGQeixjd7cSeVmMZ503qi/pjqr1Fj1ht0Tz1ZOu3Xwxe6Qouud8B1nendyQef7V
+/uXd9lzxUEd9vZv8Yo8V3nI/X/lIdyBGLfsWCb4f/J6Ff9GCD+BwSD2WsTOuRd5oNszr/LTWfANh
+t3jzRUe1dd6upbsCD9Z8s7+g/6vteV7XqG/6169w1DfQedUibK3wTi72tZ+vurGvL/ge990L/3Ir
+7nxUrvYAVkjqsYzf3cqfdyafT/Vmk7zOTxsJuILmi2bSlY9EY85X6aqVHOOYHOmdvIzaAK/+09rL
+u/NnduZgHHjUF7XCq23dG7xd394rvIus+cZ8xbYo4nu+a7HfZg+1B7BCUo8lbe/GKIvRKLKoJF39
+rEbHp0fVfDf/veLB/5DVnjD7lmrztdeH9z3ni9rybvMJ1eXdBbfuLTHqq3feHqO+aBVhLLTC2zvV
+K9d8I2IUf/0vLfwb7Kf2AFZF6rGk7Z0YjSIbxyibNV/WfVajfXSjkYCTBlp58xWNiIuIvtu1VBZY
+Y//NN/8bFju9W9bbwPLuHqO+2e2p2/W2+JJu7+QvauU3Hqi96rJvRFHEd13az29tkNoDWAmpx5I+
+PcqfspNPIm+UxWhcCb4FtvFlMQ2+VTZf1HbRzdOtvXTbaL5KFw4c4+i7IXNVs/miln2LL+82Px0Y
++y026uvdutdzmCP2ucL7qJuGfzEAHA+px/Kma7jVyJtdj6r79vrXcKvNV7tjy6z5JuGVVUdZA80X
+80eiHJhV5nx736Jvr+Zb3EGXd/tGfYM5uPeoL1pFWHlwj8lf/wrv+bP7/wUtwGAP4OCkHsu7tjNf
+va1FXn3CN8o6BnjNNdz22K/z7XQXbr6IGBez5d3B5psP2GaPTPWE3pEt786f2bnyG93Lu9Ufu99R
+X9+SbnPyF7UV3hvP7Od3AcDRGh33C+AU+6Ob8u3d2N6N7Z3Y3plfXNuNa7txrXxwN3Z2Y3c3dndj
+Zxw75dsnVD/dnT44fWT26e7srVdrf7bem6Hxpb/y8uKbv5nNn1CfRU0zZVZL5XQqYug553+qePjd
+WZQP1ieIC5p8S5aVV91fLXu3dlHJ4qzx6eCXyhxfq16MZmne+HT24CiLtVFtRlt+ulZ+4+jQO29y
+sz0Almaqx4FsXou1UayN6oO91oQvm+XC5PFltvF1zvlmu/Smi7zlVr9ypBe1VeCYLZsOzfnKldPW
+c2JFR3ej2nhHcpKj+mObo77Gp63F3+HJHwAnnKkeB/K//nK+uR2b27G1Hdd2eid825UJ3/ZO7Mzm
+eTsD87yesV/3nK8y0hvPUm/+4Ow5fXO+ojrDqzwY1TlfzJ82nwWWz4mI7lHd3pqjvp6v7j3AO9io
+rzmxa4z66p9O4v5oSs9gD+AgTPU4qD/5q/lf+7/5ZLa3Nor1csg3vIev8vh8pNd5RKMx9mvP+SIi
+anO+mE31pnO+yROiNhGszvmy2Zhq+vns/1aPaEQ5M9v/0d0FLbilb98nOWIVo77WJr/t3f382wA4
+JlKPFdi8FmtrUdZe7aMSfFk9+CbXWXVu1L+k23mSoznEioiYLeCOKxV4sOaLiJtfVnz7t7Ko9txi
+zVf+mAM1X+v793eSo++ZrW+c/jY613Dr53m3dvbz7wHg+FjAZQUe+Bv51Wtx9Vpstj9ma7vtZdzu
+68kZjn0t6VauOxZw62u7Rf3TvrXdqC/jxmyVtr3gO/xI+Y1xkLXdVS/vjmZlPD/2Uf3S7GLUs4a7
+duT/s2ENF2Bppnqsxnf+Zr7+P/Izk9ne2nwlt/0xMOFrHuCo3pZlwSXd2WLrdAE3IqJ5hiMG53xR
+HRBW5nxF0XOMo367lj2eM/ux0ZzT7W2Fy7tDs73Gp12jvitX9/nSATg+Uo+V2XlsfvW/5GfW4ob1
+WK+v57azrzYuGrwJc+eh3eEl3YjY3Z1Pp4p9Nl/tHTtm31wNrNU2X+wz+w60vDv8aX21t7nhLyKL
+ePCR/bxWAI6b1GOVzjw+f/CL+Q3rcWY9bliPM2vN5uvbzNeMvMZNmCsDv3bbtcd+EbE7ns3/ZgdO
+y215kynXos03+6cV49mnlaHc8s1X39J3oOaLhUd9lcFke9TXPsnRu+EPgNND6rFil34o//pn8zL1
+ptm3Z/CNKpFXjvQaE772od3qkm4l6aKSep3zvyibbxIwg8336FcU3/jNrOOrSzTf7LvK0op689V/
+6j4ML+9On7DYMK/jq7PrB67s82UBcNykHqv36Kfm//2j+YWNaepVm+/MIs3XOJY7ruVde0tfO+mi
+lXrNHX5l89VvwtzZfNF/65ZFm6++T26g+aISaatpvtaP2Ht5t/LV9houAKeL1ONQfN9z84j4zx/J
+bz4X526cDvaqo77a7r215pJuezNf454so3Gz9qrNF2XqtbbxTXJwvgTc03y9q7fDS719zdc5w+tv
+vs4tfUs2X+VlLLG8Wy3C+x/e5ytYqTsfld/1QH6crwDgdJJ6HKIffEEeEZ++O7/5XFy6KW5cbzbf
+mfVYG8X6bsdibrX8Oo7rdq3nltkXETvj7hMbfdv75hftk7kxvYHL8H6+VTVfdC4Bz7599h37sOeW
+vlhgefcvjrXzAFia1OPQPeOOfHLxB/fkN5+LcmF3nn1rsb6+x9GN2ma+6gJu13ru596aPeWNxRfe
+lnXeqKU63iu399WeUDSbb1wsHHkHa77m01bafPNvXHp5F4DTRupxdJ58Wx4RH39ffvO5uDRZ2K03
+35n13rvxVT867skybr7lRkTs7E4TcNw/3puu53aO92bNF7O9erGvyNt/81XXUptPW+nR3do3LrC8
++/Vv7/OnA3BiSD2O2rNekk8uPn13fvNNcencdGF3mn2z+FvkFi21Exv19dyI2N6tbelrj/f+1uuL
+L/9KNjTemx2VmL7N2nKRt3DzxSK3azmko7sxtLx7lB7zmvn1V99+fK8DIBVSj2NTLux+/p78UnVh
+t3Jcd/jE7qixma+ynhuT1Ms6aq88wBH10xvN8V4l9ebneVtru/ttvvkh357mi851271u1xKHsbxb
+RBzhSK8aedVHBB/AQUg9jt8P35ZHxL3vyy+1FnbPlJv5epqvrL35Zr4ssnFEmXqVAxzt0xtPfEPx
+xV/Mqrv3Og7ndt665QDN176xS3UjXm19tnOv3j6P7sZKtvQBcDpJPU6KW2cLu/d9cNp8tXvyrU3L
+b9p8Wc9x3dlmvg//0+yFv1J85Oezvhvy3fLm4jP/PBtlMTnAMXTvvc7UW2HzTR6cXGTd67MLNl/H
+EvDs58++Y38cyQA47aQeJ87TX5RPLtoLu/MDHGtds736Zr6I2N5pns8t13Njcm4ji/vekj39TcXn
+3pqNRvOAq473Yjj1qhfLbuBbpvmqjx/a7Vq+9sBizwPgpJJ6nFzThd33zxZ2b2jWXtl8o0rhlbUX
+EVs707ffqJ3PHU9Tb3t3OsD7ZJ49My/ue0tWnuqYjPf63mat+6K8nhVbUb+o9dxyzbfYLfpigaO7
+sewxDgBOF6nHSXfrT+STi898ML9YX9idZt9a94ndd74qe/k7inf9XNbYzDfJu5ht5pt8+vE3Zc96
+S/HJPKtOAcezZ+4v9VqjvojpOu9Bmy8OcIu+QzjGsULtMxkArITU49R42mxh9wv35JfOxfmN5ja+
+9sJuRGxtT+/M0tjMF63l3Y++MXvuW4uPvykbFbWzujH4NmudD7bPdhSraL7plxZrvljgdi3Dy7tW
+bwESIPU4fZ50Wx4Rn3h/fulcXKws7FbLb31tul1v81r3lr7ouhvL7/1C9vy3FR99Y222F/X5356p
+N5qUXM/TBppvejHYfMVKm2/PYxwAnHZSj9PqRyoLu5Pmu6G1je9f/J3sn/2n4l+9LGuc4XjFO4p3
+vTor4696++VoJeC9b85uvVx86nLlMG/WMckrr4s9T2/0N18cWvPNY67rFn3t5jtpI727HsiP+yUA
+nEpSj1NvvrD72/mljenCbrmNLyIe2aps5sumI73N7fq0b7aZb3KXlt95Q9Y4rju/S19Ze6PuWy4v
+mHpH3HzdA7yBo7sAJGF03C8AVuZJP54/9rn5H38t/vz/xQNX4qGr8dDV+Md/O3vje4uHrsaVzXhk
+Kza3Y3M7ImJre3q9uR1b29NPt7bj2k7c/brsx36p2N6N7d3Y2YntnYiInd2YPlJe7MT2TuyMY3df
+H0XzYlzEeBxFEePyo/FpMf20+eB49mD9+UURRUQRURRRFNPIKyp5V8yeEzF/ZrSfCcDpZ6pHasqF
+3c9+KL+4ERfPxc88N/v1jxave0FWLuxGZao3GnXckPk9r81e+qvF3a/Lau+oW1/Anb4DR1F/j92+
+qV42u9ny8KivMtibLL8udKSjnPC1nzB5UmvOFzF0W+bVesxrvLkZwLGReiTrqbfnEfGx9+SXzkVE
+PHR1+qa6Z9YjIq5sxvpanFmL9a6bMI9G8a5XZz/9b4v3vDZbG8Xdr8vu+JfFPa9vbtdrvANHIwQX
+uhXLYPN1Nlz0N190NWJn88XgW3F888HV/Ccob6FSXmg+gCMm9Ujcc16aR8Tly5d/4/eL234ou3gu
+3vWp4tXPy6anN8pjHGut4Mvina/KyvKLyc1ZRl2zvfFQ7Q0d2j2E5mtO+5ZrvkOj+QCOmNTjenH5
+8uV7vlhcvnw5Ir7+YFzcqL/B7uwWLWfWZsGX1ZZ0o77mO9pn7XUf2j2pzbcSw3dF3lfzOX4LsDSp
+x3Xk8uXLb37zmyPiB56X//57pzv5zp9tjvfat2Ke3425MvkbZdM/96y9efY1Du127uTru+hrvkbY
+Haz5IqZ7E4+M98kAOFRSj+tLWXvP/sl88sinPpBfPBcXN2Ljho7mW1+LtVH8k3cV//rvZ//o3xfv
+eOX8Fn2jbF5+o0VqbxSN9+FY9KxG9MTf7M/ue68s1XxZxLceOpb/MgAcCqnHdWeyhlu65cX55OKz
+H8ovnYuLG7WbME8+3nZn9gt3FdEa7JVvuVau+Q7VXtF8pLqTr/1easMX0Rj49dxvrzPphpsPgJS4
+rx5MPfX2/HHPy7/6tfjT++NbD8fDV2cfm/Hw1XjTHVlEvPa3iup9+Mrr+cdObO/M78C3U73Yad6c
+r/xzd3ff9+cb1z8mN+pr3m+vcWe+ce3+fH1POGke85rI8/y4XwXAaWWqBzUDC7uv//Hsl3+7uLI5
+nflVp3rtd93o2MyXRTauneHtG/J1LO/uuYGvfhFdc75YbM63Kl99+yr34VVrT/kBLE7qQbdyYfdz
+H84vbkwXdn/u+dm/+b3iDbdl5dru+lr3km6j/OYndovu5d2++Nv3Br7GE+pvrbZI861Qebp2tWcv
+ytTTfAB7knqwh6e8MI+Ij793OuSLiF+6p3jNj87vzLfeaL6svnuvXn4L3ZZlNN26NxrNvrTEbVka
+8dd3Yrfr1i0rp/kAjovUg4U8a7aw+6wfyD7+X4u3/27xD56TTTuvcoCjcSvmvvIbDd+WZXaAo/2u
+awe8J9/k0+HmO1SaD+CIST3Yn2fckU/u2PLvPla8+MnZ/MRupflqt2JuzPZam/k6aq9VeCvbyVd/
+Qrv5traP6NdYvXOyLX0Ah8cJXFjG5I4tj3te/sdfjz+7P+5/eHpQd35odzMe2YrNa7G1HZs780O7
+Wzu147pb290ndjsP6lY/dnc7zuE2j+UWsxO7Rc8x3tax3GNxSG+Sls8cyk8HOCVM9WBJ5d2YJz59
+d35xIy5sxMYN06leOedbX6u9/UbnQd35Zr6eqd7wkG/B5d3Ya+CXJMu7wPVM6sHyJrU3mfA94458
+8uAffDi/sBG1hd21WF+vndhtF17zFi2DRzf2vkvLYou5zfswJ5p6Jc0HXIekHhxItfYmnvzCPCLu
+fd90yHfT2doGvnLOt77We2Jjft21ma/26ai79roP7Q7GX8ymiSfNJMtWG2e29AHXD6kHB9V4p7WJ
+W1+STy7uuzu/0F7Yrcz5hmd7awNDvtFiBzj2c1uW0dqR/uoWd3gDOaM+IG1SDw7X08uF3Xvyi2fj
+wkbzoO6Z9flmvu5V3cbAb4HOm7+17vCh3Vb8nfz/RdB8APty8v+HHRLx5NvyiLj3/fnFjbhwtrWw
+O5vzrY+6VnXbA79lj240Rn1Rj79T5Hibr/NLGhE4gaQeHKlbfyKfXNz3wfzCRlw8G2crC7vV7Fsf
+OKu7wGa+9oOdj7TfPPfUObyNd50/ec/+E3zAiSL14Hg8/UX55OLz9+QXNuLC2dbCbuUuLaOBVd2u
+zXzNqhvVvxS9h3ZPuyMY9S3yTLUHnBxSD47ZD9+WR8Qn3j89vXHTjR21V3v7jYFV3epmvmrhFYuu
+6ibjeDfeqT3g5JB6cCL8yGxh9zMfnA75bryhcly3OuRb6z2r25zzLVZ41T/Tc1zNp/aAE0Lqwcny
+tBflEfGx90yHfOXCbnvON3RWt7KquzbqWdXt+vPr344r/zchAAAH40lEQVRH33zcv4LD4YAtcH2S
+enASPeel+eTiE++f3or5XM/C7rT5+u/APLCZrzMBk3dkzWewB5wEUg9OtObC7kbceKbj9Eb59hvD
+Z3UnIdgx3hulvIbbx5wPuB5IPTgdpgu7780vnO1Y2F2vn9jt28PXmPaVhTcqrsfUK2k+IGFSD06T
+5/xkPrn45AemzVdd2F1vbebrPbTRv5nveua9cYH0SD04lZ754nxy8ZkPTZuvsbA738zXt4evFYKT
+Vd2v/Gk87ruP9N9y1wN5RH6kf+UCjPqANIyO+wUAB/K02/Mn/Gj+v78Rf3Z/fOuhePhqXNmsfXxn
+Kx65FpvbsbUTWzuxVbm4Nvlze/7ptd3Y2T2Gf0VfTp2EzDoJrwFgaaZ6kIJnL7awO70V8+ChjdHR
+/j+Adz0wfeXpFVV6/yLgNDLVg6Q888X5E1+QP+bZ+Z/8RXzj2/HgI/FwdcK3GVc245FrsXltOt67
+1hrvXduOz/7PI3q1ZeedcKINOL2kHqTpqbfnjx9Y2N2KK1txdSs2rzVXdScXR+C0dN7EfmtPHQIn
+hAVcSFm5sPupD+QXNuL82Th3Y31Vd1S/FfNsGfewna7Om3BLZOA0knpwXbhldmL3sx+aNt/kxO48
++0aVWzGP4iN/GC944mG9mNPYeROL1J4cBE4UC7hwfXnq7fnjn5//n2/Gn98f33oorlytLel+ZzO+
+sxmPbMXW9nG/0JNquOR0HnDSmOrB9ehZL8knF5+6O79wtrWwO4r1tfiP98Xfffrq/+rTO9Ir6Tng
+FJF6cF275Y58cvG5D+XnGwu7o3jnvfHyW1f2dyUQeQCnjtQDIiKecnseEfe+Lz9/Ns6fjfMb0+Bb
+FZ0HcCykHjB362xh99N3T5vvl38nXv9jB/2xOg/guEg9oMMzyoXdD+c/f1f84p1L/hyRB3C8pB4w
+5CkvzCPiFb+en9+IX33Z/r5X5wEcO6kH7G2ysHvXA3Hno/I9n6zwAE4OqQfsQzXjGtmn8ABOIKkH
+LEnbAZx83i0DACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZ
+Ug8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIP
+ACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAg
+WVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlS
+DwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8A
+IFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZ
+Ug8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIP
+ACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAg
+WVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlS
+DwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8A
+IFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZ
+Ug8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIP
+ACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAg
+WVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlS
+DwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8A
+IFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZ
+Ug8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIP
+ACBZUg8AIFnrx/0CAOBwfeXLn/9vf/SF434VcDykHgAp+7V3/MZxvwQ4TlIPgJSZ53Gds1cPACBZ
+Ug8AIFlSDwAgWVIPACBZUg8AIFlSDwAgWVIPACBZUg8AIFnZV778+eN+DQAAHApTPQCAZEk9AIBk
+ST0AgGRJPQCAZEk9AIBkST0AgGRJPQCAZEk9AIBkST0AgGRJPQCAZEk9AIBkST0AgGRJPQCAZEk9
+AIBkST0AgGRJPQCAZEk9AIBkST0AgGRJPQCANH3/E54k9QAAEvT9T3jSz77qlVIPACA1k84LC7gA
+AIkpO+8f/swrpB4AQDqqnWevHgBAOhqdZ68eAEAi2p0X9uoBACSgs/Ps1QMAOPX6Os9ePQCA022g
+8372Va/8/6XuO/O4DlODAAAAAElFTkSuQmCC
+"
+       height="578"
+       width="846" />
+  </g>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="txt">
+    <text
+       xml:space="preserve"
+       style="font-size:32px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;text-anchor:middle;text-align:center"
+       x="116.00612"
+       y="521.43146"
+       id="text3059"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3061"
+         x="36.365494"
+         y="521.43146">3D viewer</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:32px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="710.77704"
+       y="405.07178"
+       id="text3059-0"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3061-4"
+         x="710.77704"
+         y="405.07178">Treeview</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
+       d="M 708.11694,372.93903 660.63977,204.24355"
+       id="path3084"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
+       d="M 118.72174,485.57104 266.20401,319.90602"
+       id="path3084-6"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:32px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="148.29944"
+       y="144.45241"
+       id="text3059-9"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3061-3"
+         x="148.29944"
+         y="144.45241">Scale tool</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
+       d="M 147.48228,113.32983 247.48738,52.720671"
+       id="path3084-6-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
+       d="M 146.9772,112.31968 121.72338,54.740979"
+       id="path3084-6-7-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:32px;font-style:normal;font-weight:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"
+       x="592.0069"
+       y="51.518387"
+       id="text3059-9-7"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3061-3-9"
+         x="592.0069"
+         y="51.518387">Action menu</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Lend)"
+       d="M 586.89863,36.558237 431.33514,11.304425"
+       id="path3084-6-1"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Body-ground.svg b/SRC/OpenMeca/Rsc/Img/Body-ground.svg
new file mode 100644
index 0000000..35ecd42
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Body-ground.svg
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Capa_1"
+   x="0px"
+   y="0px"
+   width="40"
+   height="40"
+   viewBox="0 0 40.000002 39.999999"
+   xml:space="preserve"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Body-ground.svg"><metadata
+     id="metadata41"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs39"><linearGradient
+       id="linearGradient3787"><stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3789" /><stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3791" /></linearGradient><radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3787-3"
+       id="radialGradient3793-5"
+       cx="268.84299"
+       cy="307.07483"
+       fx="268.84299"
+       fy="307.07483"
+       r="265.96835"
+       gradientTransform="matrix(0.12973005,0,0,0.12626552,5.3581411,5.282229)"
+       gradientUnits="userSpaceOnUse" /><linearGradient
+       id="linearGradient3787-3"><stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3789-7" /><stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3791-6" /></linearGradient><radialGradient
+       r="265.96835"
+       fy="307.07483"
+       fx="268.84299"
+       cy="307.07483"
+       cx="268.84299"
+       gradientTransform="matrix(0.12973005,0,0,0.12626552,101.77316,5.7161893)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient4339"
+       xlink:href="#linearGradient3787-3"
+       inkscape:collect="always" /><radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,-78.175131,-118.50883)" /><linearGradient
+       id="linearGradient3755"><stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" /><stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" /></linearGradient></defs><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="739"
+     id="namedview37"
+     showgrid="false"
+     inkscape:zoom="7.1119547"
+     inkscape:cx="14.439718"
+     inkscape:cy="23.820093"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="Capa_1" /><rect
+     transform="matrix(-0.78044407,0.62522561,0.62522561,0.78044407,0,0)"
+     y="11.992808"
+     x="-4.3709207"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-0-1"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     inkscape:transform-center-x="6.3273744"
+     inkscape:transform-center-y="-8.2958909" /><g
+     id="g7"
+     transform="translate(0,-490.93703)" /><g
+     id="g9"
+     transform="translate(0,-490.93703)" /><g
+     id="g11"
+     transform="translate(0,-490.93703)" /><g
+     id="g13"
+     transform="translate(0,-490.93703)" /><g
+     id="g15"
+     transform="translate(0,-490.93703)" /><g
+     id="g17"
+     transform="translate(0,-490.93703)" /><g
+     id="g19"
+     transform="translate(0,-490.93703)" /><g
+     id="g21"
+     transform="translate(0,-490.93703)" /><g
+     id="g23"
+     transform="translate(0,-490.93703)" /><g
+     id="g25"
+     transform="translate(0,-490.93703)" /><g
+     id="g27"
+     transform="translate(0,-490.93703)" /><g
+     id="g29"
+     transform="translate(0,-490.93703)" /><g
+     id="g31"
+     transform="translate(0,-490.93703)" /><g
+     id="g33"
+     transform="translate(0,-490.93703)" /><g
+     id="g35"
+     transform="translate(0,-490.93703)" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="27.639196"
+     x="0.088795602"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-9-5"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="20.447306"
+     x="-24.803482"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="22.245277"
+     x="-18.580416"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-2"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="24.043249"
+     x="-12.357342"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-0"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="25.841223"
+     x="-6.1342759"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-9"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.80000004;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.8000062;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="rect8109"
+     width="39.354187"
+     height="4.7975802"
+     x="-16.681509"
+     y="24.015621"
+     transform="matrix(0.78105395,-0.62446355,0.62011876,0.78450795,0,0)" /></svg>
\ No newline at end of file
diff --git a/SRC/OpenMeca/Rsc/Img/Body.svg b/SRC/OpenMeca/Rsc/Img/Body.svg
new file mode 100644
index 0000000..8293fc8
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Body.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="40"
+   height="40"
+   viewBox="0 0 39.999998 40.000001"
+   id="svg8164"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Body.svg">
+  <defs
+     id="defs8166" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="5.6"
+     inkscape:cx="-0.81081571"
+     inkscape:cy="-0.9691643"
+     inkscape:document-units="px"
+     inkscape:current-layer="g8135"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1598"
+     inkscape:window-height="755"
+     inkscape:window-x="0"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     width="40px" />
+  <metadata
+     id="metadata8169">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-604.30511,-450.37756)">
+    <g
+       id="g8135"
+       transform="matrix(0.09097306,-0.08134951,0.08134951,0.09097306,474.2654,530.44691)"
+       style="fill:#000000;fill-opacity:1">
+      <g
+         id="g3906"
+         transform="matrix(0.88323461,-0.90000013,0.90000013,0.88323461,-220.82459,1175.7144)"
+         style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:3.24903175;stroke-miterlimit:4;stroke-dasharray:none">
+        <rect
+           transform="matrix(0.74931667,0.66221184,-0.66221184,0.74931667,0,0)"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect8099"
+           width="17.5"
+           height="141.42857"
+           x="1112.9622"
+           y="-560.90308" />
+        <rect
+           transform="matrix(0.74931667,0.66221184,-0.66221184,0.74931667,0,0)"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect8103"
+           width="17.5"
+           height="112.14286"
+           x="1090.4271"
+           y="-546.39191" />
+        <rect
+           transform="matrix(0.74931667,0.66221184,-0.66221184,0.74931667,0,0)"
+           y="-532.05927"
+           x="1067.8921"
+           height="83.214287"
+           width="17.5"
+           id="rect8105"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <rect
+           transform="matrix(0.74931667,0.66221184,-0.66221184,0.74931667,0,0)"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect8107"
+           width="11.428571"
+           height="15.357144"
+           x="1051.8213"
+           y="-498.24237" />
+        <rect
+           transform="matrix(0.75156434,0.65965979,-0.66382111,0.74789139,0,0)"
+           y="-493.5997"
+           x="1134.1508"
+           height="15.896326"
+           width="130.39635"
+           id="rect8109"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24905678;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <rect
+           y="-559.98193"
+           x="-1288.1025"
+           height="141.42857"
+           width="17.5"
+           id="rect8119"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           transform="matrix(-0.74931667,-0.66221184,-0.66221184,0.74931667,0,0)" />
+        <rect
+           y="-545.2074"
+           x="-1310.6376"
+           height="112.14286"
+           width="17.5"
+           id="rect8121"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           transform="matrix(-0.74931667,-0.66221184,-0.66221184,0.74931667,0,0)" />
+        <rect
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect8123"
+           width="17.5"
+           height="83.214287"
+           x="-1333.1726"
+           y="-530.61145"
+           transform="matrix(-0.74931667,-0.66221184,-0.66221184,0.74931667,0,0)" />
+        <rect
+           y="-496.57123"
+           x="-1349.2434"
+           height="15.357144"
+           width="11.428571"
+           id="rect8125"
+           style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3.24903176;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           transform="matrix(-0.74931667,-0.66221184,-0.66221184,0.74931667,0,0)" />
+      </g>
+    </g>
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Collision.svg b/SRC/OpenMeca/Rsc/Img/Collision.svg
new file mode 100644
index 0000000..0fcbc83
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Collision.svg
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   viewBox="0 0 80 80"
+   version="1.0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"
+   sodipodi:docname="Collision.svg">
+  <defs
+     id="defs12" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="835"
+     id="namedview10"
+     showgrid="false"
+     inkscape:zoom="3.7083822"
+     inkscape:cx="25.901132"
+     inkscape:cy="71.509782"
+     inkscape:window-x="0"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2" />
+  <path
+     inkscape:connector-curvature="0"
+     d="m 42.682219,51.3502 a 18.366185,18.366235 0 0 1 -36.7323701,0 18.366185,18.366235 0 1 1 36.7323701,0 z"
+     style="fill:#646464;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path2490" />
+  <metadata
+     id="metadata8">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2011-02-02T23:50:45</dc:date>
+        <dc:description>This picture is meant to show people the supreme shapes. They were designed to be big enough to see clearly.
\nI made them in inkscape, which is currently the best free vector graphics program available for Linux.
\n
\nWhen dealing with the natural world we live in, we tend to not appreciate the most basic things around us.
\nMany colors, numbers, and shapes, make up the objects which we see and feel. Although there are endless variations of everything,I have noticed that almost everything man made tends to resemble one of 4 common shapes.
\n
\nAlso, look up the definition of supreme and you'll see why I like this word.
\nhttp://en.wiktionary.org/wiki/supreme
\n
\nregular quadrilateral(square)
\n
\nThe square is my favorite shape of all. All of it's four sides are the same length. Many people think that
\na square and rectangle are different things, however, a square is a type of rectangle. Other rectangles may have
\na different width/height ratio but all types of rectangles are useful for building things(brick houses,legos,chessboards,etc).
\nIt's also the only type of shape which can actually be represented accurately on a computer screen because pixels
\nare squares. If you look around you, you'll probably find that squares and other
\nrectangles(all of which can be divided into smaller squares), are the most commonly made shape of all man-made objects.
\nThe 3 dimensional version of a square is called a cube. Most furniture and storage containers are a rectangle on every side.
\n
\nregular triangle
\n
\nA triangle is a 3 sided shape.
\nAll triangles are interesting, however, the most commonly used triangle is a regular or equilateral triangle.
\nRegular triangles have something in common with squares in that both of them can tesselate. This means that it's
\npossible fit a bunch of them together with no gaps. Many times, the are useful in making other shapes.
\n
\nregular hexagon
\n
\nA hexagon has 6 sides, but a regular hexagon is the most useful because it is the regular polygon with the most sides
\nthat can still tesselate perfectly! A regular hexagon can be formed with 6 regular triangles.
\n
\ncircle
\n
\ncircles are totally different from the other 3 supreme shapes. They do not tesselate, they can't be described by a number of sides. However, there are two reason that I include them in my definition of supreme shapes. First, they occur in God's creation more than anything else. Almost all plants have circular parts. The stems of plants(and trunks of trees), many fruits, and maybe every living animal. Although not all things are perfect circles, many things on the human body are mostly r [...]
\nRound things move easy. This is the total opposite of rectangles which are useful when you need something to stay in one place.
\n</dc:description>
+        <dc:source>https://openclipart.org/detail/116905/supreme-shapes-by-10binary</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>10binary</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>10binary</rdf:li>
+            <rdf:li>Chandler</rdf:li>
+            <rdf:li>Isaac</rdf:li>
+            <rdf:li>Klebs</rdf:li>
+            <rdf:li>circle</rdf:li>
+            <rdf:li>hexagon</rdf:li>
+            <rdf:li>square</rdf:li>
+            <rdf:li>supreme</rdf:li>
+            <rdf:li>triangle</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     d="M 44.761306,6.5583215 40.316599,37.450541 69.29289,25.853036 44.761306,6.5583215 z"
+     style="fill:#646464;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path2462" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+     d="m 46.576639,41.22959 c 18.201408,3.814036 19.010833,4.526979 19.010833,4.526979"
+     id="path3809"
+     inkscape:connector-curvature="0"
+     inkscape:transform-center-x="-8.3523475"
+     inkscape:transform-center-y="-11.315571" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+     d="M 35.072462,28.462945 C 29.106466,11.808298 29.106466,11.808298 29.106466,11.808298"
+     id="path3813"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+     d="M 16.98854,15.281752 C 31.010827,30.382677 31.010827,30.382677 31.010827,30.382677"
+     id="path3815"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+     d="M 45.302774,45.213942 C 59.325061,60.314867 59.325061,60.314867 59.325061,60.314867"
+     id="path3815-9"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Cosmetic.svg b/SRC/OpenMeca/Rsc/Img/Cosmetic.svg
new file mode 100644
index 0000000..47dff4e
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Cosmetic.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   viewBox="0 0 80 80"
+   version="1.0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"
+   sodipodi:docname="Cosmetic.svg">
+  <defs
+     id="defs12" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="819"
+     id="namedview10"
+     showgrid="false"
+     inkscape:zoom="1.8541911"
+     inkscape:cx="-115.12233"
+     inkscape:cy="99.352686"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2" />
+  <path
+     inkscape:connector-curvature="0"
+     d="M 18.763969,21.555443 12.253621,50.226502 33.844185,70.220507 61.936393,61.515359 68.438037,32.816206 46.856177,12.850294 18.763969,21.555443 z"
+     style="fill:#646464;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path2480" />
+  <metadata
+     id="metadata8">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:date>2011-02-02T23:50:45</dc:date>
+        <dc:description>This picture is meant to show people the supreme shapes. They were designed to be big enough to see clearly.
+\nI made them in inkscape, which is currently the best free vector graphics program available for Linux.
+\n
+\nWhen dealing with the natural world we live in, we tend to not appreciate the most basic things around us.
+\nMany colors, numbers, and shapes, make up the objects which we see and feel. Although there are endless variations of everything,I have noticed that almost everything man made tends to resemble one of 4 common shapes.
+\n
+\nAlso, look up the definition of supreme and you'll see why I like this word.
+\nhttp://en.wiktionary.org/wiki/supreme
+\n
+\nregular quadrilateral(square)
+\n
+\nThe square is my favorite shape of all. All of it's four sides are the same length. Many people think that
+\na square and rectangle are different things, however, a square is a type of rectangle. Other rectangles may have
+\na different width/height ratio but all types of rectangles are useful for building things(brick houses,legos,chessboards,etc).
+\nIt's also the only type of shape which can actually be represented accurately on a computer screen because pixels
+\nare squares. If you look around you, you'll probably find that squares and other
+\nrectangles(all of which can be divided into smaller squares), are the most commonly made shape of all man-made objects.
+\nThe 3 dimensional version of a square is called a cube. Most furniture and storage containers are a rectangle on every side.
+\n
+\nregular triangle
+\n
+\nA triangle is a 3 sided shape.
+\nAll triangles are interesting, however, the most commonly used triangle is a regular or equilateral triangle.
+\nRegular triangles have something in common with squares in that both of them can tesselate. This means that it's
+\npossible fit a bunch of them together with no gaps. Many times, the are useful in making other shapes.
+\n
+\nregular hexagon
+\n
+\nA hexagon has 6 sides, but a regular hexagon is the most useful because it is the regular polygon with the most sides
+\nthat can still tesselate perfectly! A regular hexagon can be formed with 6 regular triangles.
+\n
+\ncircle
+\n
+\ncircles are totally different from the other 3 supreme shapes. They do not tesselate, they can't be described by a number of sides. However, there are two reason that I include them in my definition of supreme shapes. First, they occur in God's creation more than anything else. Almost all plants have circular parts. The stems of plants(and trunks of trees), many fruits, and maybe every living animal. Although not all things are perfect circles, many things on the human body are mostly  [...]
+\nRound things move easy. This is the total opposite of rectangles which are useful when you need something to stay in one place.
+\n</dc:description>
+        <dc:source>https://openclipart.org/detail/116905/supreme-shapes-by-10binary</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>10binary</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>10binary</rdf:li>
+            <rdf:li>Chandler</rdf:li>
+            <rdf:li>Isaac</rdf:li>
+            <rdf:li>Klebs</rdf:li>
+            <rdf:li>circle</rdf:li>
+            <rdf:li>hexagon</rdf:li>
+            <rdf:li>square</rdf:li>
+            <rdf:li>supreme</rdf:li>
+            <rdf:li>triangle</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Equation.svg b/SRC/OpenMeca/Rsc/Img/Equation.svg
new file mode 100644
index 0000000..4ef0306
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Equation.svg
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg3049"
+   sodipodi:docname="Equation.svg"
+   viewBox="0 0 80 80"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs8" />
+  <title
+     id="title3066">math pi symbol</title>
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:guide-bbox="true"
+     pagecolor="#ffffff"
+     inkscape:window-maximized="0"
+     inkscape:zoom="2.8"
+     inkscape:window-x="0"
+     inkscape:window-height="835"
+     showgrid="false"
+     borderopacity="1.0"
+     inkscape:current-layer="layer1"
+     inkscape:cx="47.865192"
+     inkscape:cy="1.5984996"
+     showguides="true"
+     inkscape:window-y="32"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0"
+     inkscape:document-units="px" />
+  <g
+     id="layer1"
+     inkscape:label="Camada 1"
+     inkscape:groupmode="layer"
+     transform="translate(-164.92,-418.29)">
+    <path
+       id="path15823"
+       style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:2.51977396;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 194.27524,437.89622 c -2.44774,12.81381 -1.56262,22.71061 -11.0647,39.3719 -2.45403,6.17701 4.67747,8.49401 7.59725,3.68639 3.5904,-7.52713 5.67773,-22.97855 6.88224,-43.08631 h 15.54665 l -2.13892,33.54152 c -0.38259,17.86013 18.29496,14.61897 22.79482,-2.0042 h -1.44364 c -8.74098,16.60158 -16.85421,7.17928 -15.99374,-5.38483 l 1.89074,-26.04072 15.71354,-0.22221 v -6.05223 H 195.3582 c -10.22751,0.36248 -12.90155,1.18013 -15.52063,6.17471 l -4.2457,8.20618 1.44364,0.1111 c [...]
+       inkscape:export-ydpi="200"
+       sodipodi:nodetypes="cccccccccccccccccc"
+       inkscape:export-filename="/home/professor/Imagens/png/formula.png"
+       inkscape:connector-curvature="0"
+       inkscape:export-xdpi="200" />
+  </g>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title>math pi symbol</dc:title>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Flower.svg b/SRC/OpenMeca/Rsc/Img/Flower.svg
new file mode 100644
index 0000000..0df9bef
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Flower.svg
@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg13670"
+   viewBox="0 0 623.13 607.53"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"
+   sodipodi:docname="Flower-a7.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="951"
+     id="namedview45"
+     showgrid="false"
+     inkscape:zoom="0.38845818"
+     inkscape:cx="311.565"
+     inkscape:cy="303.765"
+     inkscape:window-x="1600"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg13670" />
+  <defs
+     id="defs13672">
+    <linearGradient
+       id="linearGradient18014">
+      <stop
+         id="stop18016"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop18018"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <filter
+       id="filter18742-6"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur18744-7"
+         stdDeviation="1.5845507" />
+    </filter>
+    <clipPath
+       id="clipPath18010">
+      <path
+         id="path18012"
+         style="stroke:#000000;stroke-width:.27272px;fill:none"
+         d="m2538.1-695.19s-16.541 34.223 23.956 70.158c40.498 35.935 103.24 50.194 103.24 50.194l34.223-77.003-86.699-60.461z" />
+    </clipPath>
+    <filter
+       id="filter18582"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur18584"
+         stdDeviation="2.348116" />
+    </filter>
+    <linearGradient
+       id="linearGradient18603"
+       y2="-667.1"
+       gradientUnits="userSpaceOnUse"
+       x2="2673.2"
+       y1="-526.3"
+       x1="2528.8">
+      <stop
+         id="stop18044"
+         style="stop-color:#ffdd55"
+         offset="0" />
+      <stop
+         id="stop18046"
+         style="stop-color:#aa8800"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient18605"
+       y2="-547.32"
+       gradientUnits="userSpaceOnUse"
+       x2="2584.2"
+       y1="-645.51"
+       x1="2592.1">
+      <stop
+         id="stop18036"
+         style="stop-color:#d4aa00"
+         offset="0" />
+      <stop
+         id="stop18038"
+         style="stop-color:#ffdd55;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient18607"
+       y2="-572.56"
+       xlink:href="#linearGradient18014"
+       gradientUnits="userSpaceOnUse"
+       x2="2560.4"
+       y1="-690.63"
+       x1="2634" />
+    <linearGradient
+       id="linearGradient18611"
+       y2="-114.62"
+       gradientUnits="userSpaceOnUse"
+       x2="3004.4"
+       gradientTransform="matrix(-3.6668 0 0 3.6668 11530 807.63)"
+       y1="-184.94"
+       x1="3043.5">
+      <stop
+         id="stop19343-4"
+         style="stop-color:#ff9955"
+         offset="0" />
+      <stop
+         id="stop19345-1"
+         style="stop-color:#ff9955;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient18613"
+       y2="415.55"
+       gradientUnits="userSpaceOnUse"
+       x2="300.79"
+       y1="218.18"
+       x1="259.69">
+      <stop
+         id="stop18026"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop18028"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+  </defs>
+  <g
+     id="layer1"
+     transform="translate(-68.764 91.248)">
+    <g
+       id="g18586">
+      <g
+         id="g18050"
+         style="filter:url(#filter18582);fill:#000000"
+         transform="matrix(-3.6668 0 0 3.6668 9863.8 2341.8)">
+        <path
+           id="path18052"
+           style="fill:#000000"
+           d="m2599.3-657.85c-10.883 0.67071-20.867 8.1275-24.531 18.375-14.633-12.715-40.413-8.4956-49.406 8.7188-5.4376 9.7206-4.1241 22.964 3.25 31.312-17.74 6.059-27.248 29.227-18.031 45.844 5.6445 10.71 18.956 16.689 30.625 14.062-2.3134 18.04 13.029 35.949 31.281 36.031 10.678 0.26736 21.037-6.1451 25.469-15.75 14.451 12.362 39.909 8.6046 49.031-8.375 5.9134-9.7384 4.4106-23.209-2.875-31.75 17.218-5.9794 26.981-28.331 18.379-45.008-5.2475-10.739-18.216-17.515-29.973-14.93 3.7827-19 [...]
+      </g>
+      <g
+         id="g20470"
+         style="fill:#806600"
+         transform="matrix(-3.6668 0 0 3.6668 9873.8 2345.8)">
+        <path
+           id="path20472"
+           style="fill:#806600"
+           d="m2599.3-657.85c-10.883 0.67071-20.867 8.1275-24.531 18.375-14.633-12.715-40.413-8.4956-49.406 8.7188-5.4376 9.7206-4.1241 22.964 3.25 31.312-17.74 6.059-27.248 29.227-18.031 45.844 5.6445 10.71 18.956 16.689 30.625 14.062-2.3134 18.04 13.029 35.949 31.281 36.031 10.678 0.26736 21.037-6.1451 25.469-15.75 14.451 12.362 39.909 8.6046 49.031-8.375 5.9134-9.7384 4.4106-23.209-2.875-31.75 17.218-5.9794 26.981-28.331 18.379-45.008-5.2475-10.739-18.216-17.515-29.973-14.93 3.7827-19 [...]
+      </g>
+      <g
+         id="g20474"
+         style="fill:#ffcc00"
+         transform="matrix(-3.6668 0 0 3.6668 9863.1 2417.9)">
+        <path
+           id="path20476"
+           style="fill:#ffcc00"
+           d="m2605.6-687.79c0 15.577-13.621 28.205-30.423 28.205s-30.423-12.628-30.423-28.205 13.621-28.205 30.423-28.205 30.423 12.628 30.423 28.205zm-65.284-76.058c0 15.577-13.621 28.205-30.423 28.205s-30.423-12.628-30.423-28.205 13.621-28.205 30.423-28.205 30.423 12.628 30.423 28.205zm63.856 2.5977c13.49 7.7886 17.616 25.899 9.2146 40.45-8.4012 14.551-26.148 20.034-39.638 12.245-13.49-7.7886-17.616-25.899-9.2146-40.45 8.4012-14.551 26.148-20.033 39.638-12.245zm-95.681 18.338c13.49 7. [...]
+           transform="matrix(-.5 .86603 -.86603 -.5 3222.7 -3162)" />
+      </g>
+      <g
+         id="g20480"
+         style="fill:url(#linearGradient18605)"
+         transform="matrix(-3.6668 0 0 3.6668 9863.1 2414.6)">
+        <path
+           id="path20482"
+           style="fill:url(#linearGradient18603)"
+           d="m2593.9-670.62c-10.773 0.20733-19.395 9.0283-22.531 18.75-5.1926 2.3348-7.7831-4.1503-12.219-5.2812-14.773-7.1891-36.108 1.7729-38.281 18.719-1.3905 9.7138 4.0641 19.595 12.438 24.344-19.42-0.97127-33.74 22.612-25.094 39.719 4.9638 9.9999 17.632 14.9 28.25 11.656 4.3156 0.84213 3.4965 6.2838 3.0938 9.5312 0.1898 15.954 16.663 30.282 32.594 26.219 9.0721-2.3762 16.089-10.47 17.312-19.656 10.228 16.545 38.519 15.395 47.188-1.875 5.7318-10.684 1.1141-25.634-9.5-31.188 4.7553-1 [...]
+      </g>
+      <path
+         id="path20478"
+         style="filter:url(#filter18742-6);fill:#000000"
+         d="m2613.9-575.29a31.691 31.691 0 1 1 -63.382 0 31.691 31.691 0 1 1 63.382 0z"
+         transform="matrix(-3.6668 0 0 3.6668 9856.4 2339.8)" />
+      <g
+         id="g18004"
+         style="fill:url(#linearGradient18607)"
+         transform="matrix(-3.5967 0 0 3.4703 9685.5 2293.3)"
+         clip-path="url(#clipPath18010)">
+        <path
+           id="path18006"
+           style="fill:url(#linearGradient18607)"
+           d="m2593.9-670.62c-10.773 0.20733-19.395 9.0283-22.531 18.75-5.1926 2.3348-7.7831-4.1503-12.219-5.2812-14.773-7.1891-36.108 1.7729-38.281 18.719-1.3905 9.7138 4.0641 19.595 12.438 24.344-19.42-0.97127-33.74 22.612-25.094 39.719 4.9638 9.9999 17.632 14.9 28.25 11.656 4.3156 0.84213 3.4965 6.2838 3.0938 9.5312 0.1898 15.954 16.663 30.282 32.594 26.219 9.0721-2.3762 16.089-10.47 17.312-19.656 10.228 16.545 38.519 15.395 47.188-1.875 5.7318-10.684 1.1141-25.634-9.5-31.188 4.7553-1 [...]
+      </g>
+      <path
+         id="path20484"
+         style="fill:#803300"
+         d="m284.05 236.93a116.2 116.2 0 1 0 232.41 0 116.2 116.2 0 1 0 -232.41 0z" />
+      <path
+         id="path20486"
+         style="fill:#d45500"
+         d="m300.32 248.56a116.2 116.2 0 1 0 232.41 0 116.2 116.2 0 1 0 -232.41 0z" />
+      <path
+         id="path20488"
+         style="fill:url(#linearGradient18611)"
+         d="m419.08 146.11c67.087-1.2862 120.12 77.207 93.503 139.11-19.735 54.383-92.513 84.255-144.15 54.085-47.55-25.211-71.017-91.591-41.795-139.39 18.111-32.655 54.284-55.505 92.442-53.799z" />
+      <path
+         id="path18022"
+         style="opacity:.55;fill:url(#linearGradient18613)"
+         d="m372.29 316.36a87.843 56.471 0 1 1 -175.69 0 87.843 56.471 0 1 1 175.69 0z"
+         transform="matrix(.86303 -.42928 .33476 1.1067 54.369 .33163)" />
+    </g>
+  </g>
+  <metadata
+     id="metadata43">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2010-08-16T18:40:15</dc:date>
+        <dc:description>Glossy flowers</dc:description>
+        <dc:source>https://openclipart.org/detail/80911/flower-a7-by-inky2010</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>inky2010</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>3D</rdf:li>
+            <rdf:li>Flower</rdf:li>
+            <rdf:li>art</rdf:li>
+            <rdf:li>fall</rdf:li>
+            <rdf:li>fall2010</rdf:li>
+            <rdf:li>flowers</rdf:li>
+            <rdf:li>gloss</rdf:li>
+            <rdf:li>glossy</rdf:li>
+            <rdf:li>inkscape</rdf:li>
+            <rdf:li>inky2010</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Frame.svg b/SRC/OpenMeca/Rsc/Img/Frame.svg
new file mode 100644
index 0000000..1f3fd27
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Frame.svg
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Frame.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="983"
+     id="namedview3047"
+     showgrid="false"
+     inkscape:zoom="4.975"
+     inkscape:cx="-59.479679"
+     inkscape:cy="18.661554"
+     inkscape:window-x="1600"
+     inkscape:window-y="64"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="matrix(0.48753267,0.27391628,-0.24678841,0.46688166,68.313877,51.194358)"
+     id="g3000"
+     style="fill:#000000;fill-opacity:1;stroke:#505050;stroke-opacity:1" />
+  <g
+     id="g3909"
+     transform="matrix(1.1326023,0,0,1.1218401,-1.8322787,-4.3398481)">
+    <g
+       transform="translate(0.8040201,4.5226131)"
+       id="g3899">
+      <path
+         d="M 7.6563774,2.7819319 10.658375,6.5133777 4.215998,6.5398087 7.6563774,2.7819319 z"
+         id="path1317-4"
+         style="color:#000000;fill:#000000;fill-opacity:1;stroke:#505050;stroke-width:1.69794059;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+         inkscape:connector-curvature="0" />
+      <path
+         d="M 7.3769515,28.946785 7.4411093,5.0448369"
+         id="path1323-6"
+         style="fill:#000000;fill-opacity:1;stroke:#505050;stroke-width:2.71670485;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cc" />
+    </g>
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;fill:#000000;fill-opacity:1;stroke:#505050;stroke-width:1.69794059;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+       id="path1317"
+       d="m 34.406214,34.101343 -3.731446,3.001998 -0.02643,-6.442377 3.757877,3.440379 z" />
+    <path
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0"
+       style="fill:#000000;fill-opacity:1;stroke:#505050;stroke-width:2.71670485;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
+       id="path1323"
+       d="m 8.2413611,33.821918 23.9019479,0.06416" />
+    <g
+       transform="matrix(1.3883004,0,0,1.3439717,-2.9729843,-12.077957)"
+       id="g3906">
+      <path
+         d="m 6.961545,33.412332 c -0.189218,0.743737 0.230276,1.509099 0.936277,1.708431 0.7062231,0.199333 1.4327511,-0.242584 1.6219701,-0.98632 0.189219,-0.743736 -0.230276,-1.509239 -0.936499,-1.708525 C 7.877293,32.226609 7.150764,32.668526 6.961545,33.412332 z"
+         id="path2086"
+         style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:0.71569085;stroke-linecap:round;stroke-linejoin:round;display:block"
+         inkscape:connector-curvature="0" />
+    </g>
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Geometry.svg b/SRC/OpenMeca/Rsc/Img/Geometry.svg
new file mode 100644
index 0000000..e189415
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Geometry.svg
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="svg4039"
+   viewBox="0 0 79.999997 80.000002"
+   height="80"
+   width="80"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="cartabon.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="851"
+     id="namedview31"
+     showgrid="false"
+     inkscape:zoom="2.025864"
+     inkscape:cx="64.000008"
+     inkscape:cy="58.246754"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg4039" />
+  <defs
+     id="defs4041">
+    <linearGradient
+       id="linearGradient438"
+       spreadMethod="pad"
+       gradientTransform="matrix(12.47651,0.20009,-0.17071,10.64499,487.281,503.7661)"
+       gradientUnits="userSpaceOnUse"
+       y2="0"
+       x2="0.99000001"
+       y1="0"
+       x1="0.0099999998">
+      <stop
+         id="stop440"
+         offset="0"
+         style="stop-opacity:1;stop-color:#231f20" />
+      <stop
+         id="stop442"
+         offset="1"
+         style="stop-opacity:1;stop-color:#ffffff" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient416"
+       spreadMethod="pad"
+       gradientTransform="matrix(15.79338,-3.58641,3.37845,14.87757,492.1997,509.4309)"
+       gradientUnits="userSpaceOnUse"
+       y2="0"
+       x2="0.88"
+       y1="0"
+       x1="0.12">
+      <stop
+         id="stop418"
+         offset="0"
+         style="stop-opacity:1;stop-color:#231f20" />
+      <stop
+         id="stop420"
+         offset="1"
+         style="stop-opacity:1;stop-color:#ffffff" />
+    </linearGradient>
+  </defs>
+  <metadata
+     id="metadata4044">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     d="M 60.248981,7.3954108 76.197325,48.789015 6.3630019,69.329674 60.248981,7.3954108 z m -1.270362,17.8706532 6.634746,17.220353 c 0.260915,0.677197 -0.124388,1.405344 -0.857102,1.620862 L 35.704071,52.65252 c -0.600127,0.176519 -1.243473,-0.02557 -1.616296,-0.506292 -0.373297,-0.481996 -0.363389,-1.097364 0.02528,-1.545163 L 56.533041,24.835074 c 0.323042,-0.373042 0.815019,-0.534742 1.338394,-0.442499 0.522025,0.09226 0.929635,0.412657 1.107199,0.873518 z"
+     style="fill:#a7a5a6;fill-opacity:1;fill-rule:evenodd;stroke:#231f20;stroke-width:1.18701971;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:22.92558479;stroke-opacity:1;stroke-dasharray:none"
+     id="path402" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link.svg b/SRC/OpenMeca/Rsc/Img/Link.svg
new file mode 100644
index 0000000..c71b87d
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Junction.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="867"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="8.34386"
+     inkscape:cx="31.704941"
+     inkscape:cy="11.577654"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 20 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="40 : 20 : 1"
+       inkscape:persp3d-origin="20 : 13.333333 : 1"
+       id="perspective3048" />
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     style="fill:#ff0000;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+     d="m 12,2 15,0 1,17 10,0 0,4 -10,0 -1,15 -16,0 0,-4 12,0 0,-28 -11,0 z"
+     id="path3009"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccccccccccccc" />
+  <path
+     style="fill:#0000ff;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+     d="m 19,9 -4,0 -0.5,9.5 -12,0 0,4 12,0 0.5,8.5 4,0 z"
+     id="path3011"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccccccccc" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Cylindrical.svg b/SRC/OpenMeca/Rsc/Img/Link/Cylindrical.svg
new file mode 100644
index 0000000..6a6402c
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Cylindrical.svg
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Cylindrical.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="867"
+     id="namedview3043"
+     showgrid="true"
+     inkscape:zoom="10.775"
+     inkscape:cx="6.4053321"
+     inkscape:cy="22.124001"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3813"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3874" />
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="1"
+         id="stop3876" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="0"
+         id="stop3856" />
+      <stop
+         id="stop3862"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3858" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     sodipodi:nodetypes="ccccc"
+     inkscape:connector-curvature="0"
+     id="path3848"
+     d="m 2.19649,15.37014 35.44898,0 0,9.0601 -35.44898,0 z"
+     style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+  <path
+     sodipodi:nodetypes="ccccc"
+     inkscape:connector-curvature="0"
+     id="path3850"
+     d="m 9.38148,4.87852 0,6.73999 21.23703,0 0,-6.73999 z"
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+  <path
+     sodipodi:nodetypes="ccccc"
+     inkscape:connector-curvature="0"
+     id="path3852"
+     d="m 9.8825,28.43631 0,7.48141 20.68119,0 0,-7.48141 z"
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Gear.svg b/SRC/OpenMeca/Rsc/Img/Link/Gear.svg
new file mode 100644
index 0000000..37339cf
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Gear.svg
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Spherical.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="835"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="4.17193"
+     inkscape:cx="-35.422551"
+     inkscape:cy="30.654782"
+     inkscape:window-x="0"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028"
+     d="m 36.142857,14.932046 a 12.071429,12.071428 0 0 1 -24.142856,0 12.071429,12.071428 0 1 1 24.142856,0 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.92366421;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028-4"
+     d="m 18.038166,29.005454 a 8.0381679,8.0381679 0 0 1 -16.076332,0 8.0381679,8.0381679 0 1 1 16.076332,0 z" />
+  <path
+     sodipodi:type="arc"
+     style="fill:#ffffff;fill-opacity:1;stroke:none"
+     id="path3789"
+     sodipodi:cx="10"
+     sodipodi:cy="29"
+     sodipodi:rx="2"
+     sodipodi:ry="2"
+     d="m 12,29 a 2,2 0 1 1 -4,0 2,2 0 1 1 4,0 z" />
+  <path
+     transform="translate(14,-14)"
+     sodipodi:type="arc"
+     style="fill:#ffffff;fill-opacity:1;stroke:none"
+     id="path3789-5"
+     sodipodi:cx="10"
+     sodipodi:cy="29"
+     sodipodi:rx="2"
+     sodipodi:ry="2"
+     d="m 12,29 a 2,2 0 1 1 -4,0 2,2 0 1 1 4,0 z" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/LinearMotor.svg b/SRC/OpenMeca/Rsc/Img/Link/LinearMotor.svg
new file mode 100644
index 0000000..3e1b9e3
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/LinearMotor.svg
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Slider.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="851"
+     id="namedview3043"
+     showgrid="true"
+     inkscape:zoom="5.3875"
+     inkscape:cx="-18.660067"
+     inkscape:cy="25.20365"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3813"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3874" />
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="1"
+         id="stop3876" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="0"
+         id="stop3856" />
+      <stop
+         id="stop3862"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3858" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="translate(-230.10998,-496.49673)"
+     id="layer1">
+    <path
+       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:1.53318572;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 232.10998,513.49673 0,6 36,0 0,-6 z"
+       id="path3850-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 238.10998,504.49673 0,25 24,0 0,-25 z"
+       id="path3850"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Motor.svg b/SRC/OpenMeca/Rsc/Img/Link/Motor.svg
new file mode 100644
index 0000000..90b4405
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Motor.svg
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Motor.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="819"
+     id="namedview3043"
+     showgrid="true"
+     inkscape:zoom="10.775"
+     inkscape:cx="16.727414"
+     inkscape:cy="16.365481"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3813"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3874" />
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="1"
+         id="stop3876" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="0"
+         id="stop3856" />
+      <stop
+         id="stop3862"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3858" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="translate(-230.10998,-496.49673)"
+     id="layer1">
+    <path
+       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 232.10998,504.49673 5,0 0.14284,9 25.71432,0 0.14284,-9 5,0 0,25 -5,0 -0.14284,-10 -25.71432,0 -0.14284,10 -5,0 z"
+       id="path3848"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccc" />
+    <path
+       style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.69230759;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 239.95613,501.34288 0,9.3077 20.3077,0 0,-9.3077 z"
+       id="path3850"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.69230759;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 239.95613,522.34288 0,9.3077 20.3077,0 0,-9.3077 z"
+       id="path3850-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Planar.svg b/SRC/OpenMeca/Rsc/Img/Link/Planar.svg
new file mode 100644
index 0000000..c60d905
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Planar.svg
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Planar.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="803"
+     id="namedview4403"
+     showgrid="true"
+     showguides="false"
+     inkscape:snap-bbox="true"
+     inkscape:snap-grids="true"
+     inkscape:zoom="11.8"
+     inkscape:cx="22.712669"
+     inkscape:cy="15.380451"
+     inkscape:window-x="0"
+     inkscape:window-y="64"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid4413"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     d="m 22.567568,2.0270271 -5.135136,0 0,11.2972969 -13.405405,0 0,5.135135 31.945946,0 0,-5.135135 -13.405405,0 z"
+     id="path4425"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccccccccc" />
+  <path
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     d="m 17.432432,37.972973 5.135136,0 0,-11.297298 13.405405,0 0,-5.135134 -31.9459462,0 0,5.135134 13.4054052,0 z"
+     id="path4425-2"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccccccccc" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/PointLine.svg b/SRC/OpenMeca/Rsc/Img/Link/PointLine.svg
new file mode 100644
index 0000000..27833d0
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/PointLine.svg
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Spherical.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="723"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="8.34386"
+     inkscape:cx="42.990268"
+     inkscape:cy="20.029888"
+     inkscape:window-x="0"
+     inkscape:window-y="112"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1.85714304;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028"
+     d="m 32.071429,15.003108 a 12.071429,12.071428 0 0 1 -24.1428571,0 12.071429,12.071428 0 1 1 24.1428571,0 z" />
+  <path
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2.05180979;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     d="m 2.0259049,15.974005 2.9956826,0 C 5.0215875,15.974005 6,30 20,29.974079 34,29.948158 34.978412,15.974005 34.978412,15.974005 l 2.995683,0 C 37.974095,15.974005 37,32.94819 20,32.974095 3,33 2.0259049,15.974005 2.0259049,15.974005 z"
+     id="path6965"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cczcczc" />
+  <path
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     d="m 4,33 0,3 32,0 0,-3 z"
+     id="path8747"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccccc" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/PointPlane.svg b/SRC/OpenMeca/Rsc/Img/Link/PointPlane.svg
new file mode 100644
index 0000000..8811549
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/PointPlane.svg
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="PointPlane.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="787"
+     id="namedview6294"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="8.34386"
+     inkscape:cx="-2.4476752"
+     inkscape:cy="17.414123"
+     inkscape:window-x="0"
+     inkscape:window-y="80"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6969"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#0000ff;stroke-width:10;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3819"
+     d="m -182.48614,69.123621 74.80278,0" />
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path4619"
+     d="M 4.6363639,4 20,23 35,4 z"
+     sodipodi:nodetypes="cccc" />
+  <path
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     d="m 2.0000003,26 0,7 L 38,33 38,26 z"
+     id="path7479"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="ccccc" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Pulley.svg b/SRC/OpenMeca/Rsc/Img/Link/Pulley.svg
new file mode 100644
index 0000000..c9ac433
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Pulley.svg
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Gear.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="851"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="8.34386"
+     inkscape:cx="38.316958"
+     inkscape:cy="12.165225"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g3189"
+     transform="matrix(0.77451997,0,0,0.77451997,0.20899881,9.5847788)"
+     style="stroke-width:2.58224459;stroke-miterlimit:4;stroke-dasharray:none">
+    <path
+       d="m 18.038166,29.005454 a 8.0381679,8.0381679 0 0 1 -16.076332,0 8.0381679,8.0381679 0 1 1 16.076332,0 z"
+       id="path3028-4"
+       style="fill:#0000ff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.58224459;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 12,29 c 0,1.104569 -0.895431,2 -2,2 -1.1045695,0 -2,-0.895431 -2,-2 0,-1.104569 0.8954305,-2 2,-2 1.104569,0 2,0.895431 2,2 z"
+       sodipodi:ry="2"
+       sodipodi:rx="2"
+       sodipodi:cy="29"
+       sodipodi:cx="10"
+       id="path3789"
+       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.58224459;stroke-miterlimit:4;stroke-dasharray:none"
+       sodipodi:type="arc" />
+  </g>
+  <g
+     id="g3177"
+     transform="matrix(0.7650273,0,0,0.76502736,10.5847,-0.41966468)"
+     style="stroke-width:2.61428569;stroke-miterlimit:4;stroke-dasharray:none">
+    <path
+       d="m 36.142857,14.932046 a 12.071429,12.071428 0 0 1 -24.142856,0 12.071429,12.071428 0 1 1 24.142856,0 z"
+       id="path3028"
+       style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:2.61428569;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 12,29 c 0,1.104569 -0.895431,2 -2,2 -1.1045695,0 -2,-0.895431 -2,-2 0,-1.104569 0.8954305,-2 2,-2 1.104569,0 2,0.895431 2,2 z"
+       sodipodi:ry="2"
+       sodipodi:rx="2"
+       sodipodi:cy="29"
+       sodipodi:cx="10"
+       id="path3789-5"
+       style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2.61428569;stroke-miterlimit:4;stroke-dasharray:none"
+       sodipodi:type="arc"
+       transform="translate(14,-14)" />
+  </g>
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="M 21,6 3,29"
+     id="path3961"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="M 35,19 11,37"
+     id="path3963"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/RackPinion.svg b/SRC/OpenMeca/Rsc/Img/Link/RackPinion.svg
new file mode 100644
index 0000000..da61385
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/RackPinion.svg
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="RackPinion.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="803"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="5.9"
+     inkscape:cx="51.212066"
+     inkscape:cy="46.771197"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g3138"
+     transform="matrix(1.0327869,0,0,1.0327869,-4.3606554,-0.91654732)">
+    <path
+       d="m 36.142857,14.932046 a 12.071429,12.071428 0 0 1 -24.142856,0 12.071429,12.071428 0 1 1 24.142856,0 z"
+       id="path3028"
+       style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       inkscape:connector-curvature="0" />
+    <path
+       d="m 12,29 c 0,1.104569 -0.895431,2 -2,2 -1.1045695,0 -2,-0.895431 -2,-2 0,-1.104569 0.8954305,-2 2,-2 1.104569,0 2,0.895431 2,2 z"
+       sodipodi:ry="2"
+       sodipodi:rx="2"
+       sodipodi:cy="29"
+       sodipodi:cx="10"
+       id="path3789-5"
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       sodipodi:type="arc"
+       transform="translate(14,-14)" />
+  </g>
+  <path
+     sodipodi:nodetypes="ccccc"
+     inkscape:connector-curvature="0"
+     id="path3848-6"
+     d="M 2.55102,29 38,29 l 0,9.0601 -35.44898,0 z"
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Revolute.svg b/SRC/OpenMeca/Rsc/Img/Link/Revolute.svg
new file mode 100644
index 0000000..95eb461
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Revolute.svg
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Motor.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="819"
+     id="namedview3043"
+     showgrid="true"
+     inkscape:zoom="10.775"
+     inkscape:cx="16.727414"
+     inkscape:cy="16.365481"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3813"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3874" />
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="1"
+         id="stop3876" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="0"
+         id="stop3856" />
+      <stop
+         id="stop3862"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3858" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="translate(-230.10998,-496.49673)"
+     id="layer1">
+    <path
+       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 232.10998,504.49673 5,0 0.14284,9 25.71432,0 0.14284,-9 5,0 0,25 -5,0 -0.14284,-10 -25.71432,0 -0.14284,10 -5,0 z"
+       id="path3848"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccccccccccc" />
+    <path
+       style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.69230759;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 239.95613,501.34288 0,9.3077 20.3077,0 0,-9.3077 z"
+       id="path3850"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:1.69230759;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 239.95613,522.34288 0,9.3077 20.3077,0 0,-9.3077 z"
+       id="path3850-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Screw.svg b/SRC/OpenMeca/Rsc/Img/Link/Screw.svg
new file mode 100644
index 0000000..5189b11
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Screw.svg
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Screw.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="707"
+     id="namedview3043"
+     showgrid="true"
+     inkscape:zoom="5.3875"
+     inkscape:cx="24.615078"
+     inkscape:cy="25.840967"
+     inkscape:window-x="0"
+     inkscape:window-y="128"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3813"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3874" />
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="1"
+         id="stop3876" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="0"
+         id="stop3856" />
+      <stop
+         id="stop3862"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3858" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="translate(-230.10998,-496.49673)"
+     id="layer1">
+    <path
+       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:1.53318572;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 232.10998,513.49673 0,6 36,0 0,-6 z"
+       id="path3850-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 238.10998,504.49673 0,25 24,0 0,-25 z"
+       id="path3850"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 10,10 30,31"
+       id="path10091"
+       inkscape:connector-curvature="0"
+       transform="translate(230.10998,496.49673)"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Slider.svg b/SRC/OpenMeca/Rsc/Img/Link/Slider.svg
new file mode 100644
index 0000000..edee2e8
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Slider.svg
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Slider.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="707"
+     id="namedview3043"
+     showgrid="true"
+     inkscape:zoom="5.3875"
+     inkscape:cx="-18.660067"
+     inkscape:cy="25.20365"
+     inkscape:window-x="0"
+     inkscape:window-y="128"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3813"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3874" />
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="1"
+         id="stop3876" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="0"
+         id="stop3856" />
+      <stop
+         id="stop3862"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3858" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="translate(-230.10998,-496.49673)"
+     id="layer1">
+    <path
+       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:1.53318572;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 232.10998,513.49673 0,6 36,0 0,-6 z"
+       id="path3850-5"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 238.10998,504.49673 0,25 24,0 0,-25 z"
+       id="path3850"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Spherical.svg b/SRC/OpenMeca/Rsc/Img/Link/Spherical.svg
new file mode 100644
index 0000000..4781936
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Spherical.svg
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Spherical.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="755"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="8.34386"
+     inkscape:cx="48.047477"
+     inkscape:cy="13.217796"
+     inkscape:window-x="0"
+     inkscape:window-y="96"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-rule:evenodd;stroke:#000000;stroke-width:1.85714304;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028"
+     d="m 32.071429,15.003108 a 12.071429,12.071428 0 0 1 -24.1428571,0 12.071429,12.071428 0 1 1 24.1428571,0 z" />
+  <path
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2.05180979;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     d="m 2.0259049,15.974005 2.9956826,0 C 5.0215875,15.974005 6,30 20,29.974079 34,29.948158 34.978412,15.974005 34.978412,15.974005 l 2.995683,0 C 37.974095,15.974005 37,32.94819 20,32.974095 3,33 2.0259049,15.974005 2.0259049,15.974005 z"
+     id="path6965"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cczcczc" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Link/Spring.svg b/SRC/OpenMeca/Rsc/Img/Link/Spring.svg
new file mode 100644
index 0000000..a2251af
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Link/Spring.svg
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Cylindrical.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="819"
+     id="namedview3043"
+     showgrid="true"
+     inkscape:zoom="5.3875"
+     inkscape:cx="-5.8222076"
+     inkscape:cy="19.80706"
+     inkscape:window-x="0"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2"
+     inkscape:snap-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3813"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3874" />
+      <stop
+         style="stop-color:#0000ff;stop-opacity:1;"
+         offset="1"
+         id="stop3876" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="0"
+         id="stop3856" />
+      <stop
+         id="stop3862"
+         offset="0.5"
+         style="stop-color:#ffffff;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3858" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     sodipodi:nodetypes="ccccc"
+     inkscape:connector-curvature="0"
+     id="path3848"
+     d="m 2,2.9399 35.44898,0 0,9.0601 L 2,12 z"
+     style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+  <path
+     sodipodi:nodetypes="ccccc"
+     inkscape:connector-curvature="0"
+     id="path3848-6"
+     d="M 2.55102,28.9399 38,28.9399 38,38 2.55102,38 z"
+     style="fill:#0000ff;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+     d="m 5,13 30,2 -30,0 30,2 -30,0 30,2 -30,0 30,2 -30,0 30,2 -30,0 30,2 -30,0 30,2 -30,0 30,2 0,0"
+     id="path3886"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Load.svg b/SRC/OpenMeca/Rsc/Img/Load.svg
new file mode 100644
index 0000000..c7fc18f
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Load.svg
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg1890"
+   sodipodi:docname="bow-and-arrow-2.svg"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   version="1.0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs18" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     guidetolerance="10.0"
+     pagecolor="#ffffff"
+     gridtolerance="10.0"
+     inkscape:window-maximized="0"
+     inkscape:zoom="6.5281388"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     inkscape:current-layer="svg1890"
+     inkscape:cx="21.177261"
+     inkscape:cy="16.252164"
+     inkscape:window-y="16"
+     inkscape:window-x="0"
+     inkscape:window-height="787"
+     showgrid="false"
+     inkscape:pageopacity="0.0"
+     inkscape:window-width="1598">
+    <inkscape:grid
+       id="grid2820"
+       enabled="true"
+       visible="true"
+       snapvisiblegridlinesonly="true"
+       type="xygrid"
+       empspacing="5" />
+  </sodipodi:namedview>
+  <g
+     id="g3683"
+     style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+     transform="matrix(0.02992738,0.0489587,-0.0489587,0.02992738,28.833689,-3.3413875)">
+    <g
+       id="g3614"
+       style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none">
+      <path
+         id="path3596"
+         sodipodi:nodetypes="ccccc"
+         style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+         d="m 620,423.85 c -39.718,13.48 -63.523,-5.858 -85,-30 l 35,-20 c 12.547,5.9754 20.684,-1.2801 30,-5 21.406,22.018 21.249,38.646 20,55 z"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path3598"
+         sodipodi:nodetypes="cccccccc"
+         style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+         d="m 540,348.85 c -3.944,14.186 -14.249,19.89 -25,25 -40,-50 -105.51,-232.58 -195,-120 l -55,-10 v -45 l 35,5 c 61.111,-99.786 155,-10 170,10 22.475,45 37.264,90 70,135 z"
+         inkscape:connector-curvature="0" />
+    </g>
+    <g
+       id="g3614-6"
+       style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+       transform="matrix(-1,0,0,1,495,2.4609e-6)">
+      <path
+         id="path3596-3"
+         sodipodi:nodetypes="ccccc"
+         style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+         d="m 620,423.85 c -39.718,13.48 -63.523,-5.858 -85,-30 l 35,-20 c 12.547,5.9754 20.684,-1.2801 30,-5 21.406,22.018 21.249,38.646 20,55 z"
+         inkscape:connector-curvature="0" />
+      <path
+         id="path3598-2"
+         sodipodi:nodetypes="cccccccc"
+         style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+         d="m 540,348.85 c -3.944,14.186 -14.249,19.89 -25,25 -40,-50 -105.51,-232.58 -195,-120 l -55,-10 v -45 l 35,5 c 61.111,-99.786 155,-10 170,10 22.475,45 37.264,90 70,135 z"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       id="path3646"
+       sodipodi:nodetypes="ccccccc"
+       style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 520,378.85 c 15.039,-9.1377 24.286,-22.619 35,-35 14.641,1.9061 24.417,7.055 15,25 l -40,20 -280,155 c -8.2301,1.4603 -16.296,2.5922 -20,-5 l 290,-160 z"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path3646-0"
+       sodipodi:nodetypes="ccccccc"
+       style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m -25,378.85 c -15.039,-9.1377 -24.286,-22.619 -35,-35 -14.641,1.9061 -24.417,7.055 -15,25 l 40,20 235,135 v -15 l -225,-130 z"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path3670"
+       sodipodi:nodetypes="ccccccccccccc"
+       style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 248,59.848 c 21.427,40.757 37.127,82.087 47,124 l -35,-30 v 280 l 25,25 v 45 l -55,30 -25,30 v -105 l 30,-25 v -280 l -35,30 c 9.4979,-45.008 25.216,-86.501 48,-124 z"
+       inkscape:connector-curvature="0" />
+    <path
+       id="path3672"
+       sodipodi:nodetypes="cccc"
+       style="fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:17.42730998000000042;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 265,538.85 20,-10 v 35 l -20,-25 z"
+       inkscape:connector-curvature="0" />
+  </g>
+  <metadata
+     id="metadata16">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2010-05-29T15:12:35</dc:date>
+        <dc:description>A heraldic black bow and arrow, notched.</dc:description>
+        <dc:source>https://openclipart.org/detail/63619/bow-and-arrow-by-paxed</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>paxed</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>archery</rdf:li>
+            <rdf:li>arrow</rdf:li>
+            <rdf:li>bow</rdf:li>
+            <rdf:li>heraldic</rdf:li>
+            <rdf:li>heraldry</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Load/Force.svg b/SRC/OpenMeca/Rsc/Img/Load/Force.svg
new file mode 100644
index 0000000..ef0c480
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Load/Force.svg
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg1"
+   sodipodi:docname="Force.svg"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   _SVGFile__filename="oldscale/actions/circle.svg"
+   version="1.0"
+   y="0"
+   x="0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs21" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="32"
+     pagecolor="#ffffff"
+     inkscape:window-height="835"
+     inkscape:zoom="4.6034679"
+     inkscape:window-x="0"
+     borderopacity="1.0"
+     inkscape:current-layer="svg1"
+     inkscape:cx="-13.694889"
+     inkscape:cy="32.33556"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0000000"
+     showgrid="false"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g3013"
+     transform="translate(-6.9512812,-1.0861377)">
+    <path
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0"
+       id="path2992"
+       d="M 12.164743,36.19891 C 5.4419384,14.363664 19.8312,5.0887654 19.984934,5.1353724"
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m 15.468914,5.5609733 c -0.36081,1.346232 0.4391,2.731608 1.785332,3.092419 1.346657,0.36081 2.732033,-0.4391 3.092843,-1.785331 0.360811,-1.346232 -0.439099,-2.731863 -1.785756,-3.092589 -1.346232,-0.360768 -2.731608,0.439143 -3.092419,1.785501 z"
+       style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:1.32963777;stroke-linecap:round;stroke-linejoin:round;display:block"
+       id="path2086-1" />
+  </g>
+  <g
+     id="g3000-1"
+     transform="matrix(-0.16547702,-0.76683195,0.71991702,-0.1747779,-1.6807025,-45.625784)">
+    <path
+       inkscape:connector-curvature="0"
+       d="m -68.01036,3.028382 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round"
+       id="path1317-4" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m -109.52556,27.048382 37.779,-21.812"
+       style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round"
+       id="path1323-3" />
+  </g>
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.722754,5.0263663 c 6.299598,3.6928682 6.299598,3.6928682 6.299598,3.6928682"
+     id="path3017"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.288299,8.7192345 c 6.734053,4.5617785 6.734053,4.5617785 6.734053,4.5617785"
+     id="path3019"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 13.685335,15.236061 c -0.217228,6.516826 -0.217228,6.516826 -0.217228,6.516826"
+     id="path3021"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="M 10.426922,15.018833 C 8.2546465,25.228527 8.2546465,25.228527 8.2546465,25.228527"
+     id="path3023"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Load/Torque.svg b/SRC/OpenMeca/Rsc/Img/Load/Torque.svg
new file mode 100644
index 0000000..a5ce4ed
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Load/Torque.svg
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg1"
+   sodipodi:docname="Torque.svg"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   _SVGFile__filename="oldscale/actions/circle.svg"
+   version="1.0"
+   y="0"
+   x="0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs21" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="64"
+     pagecolor="#ffffff"
+     inkscape:window-height="755"
+     inkscape:zoom="4.6034679"
+     inkscape:window-x="0"
+     borderopacity="1.0"
+     inkscape:current-layer="g3000-1"
+     inkscape:cx="-13.694889"
+     inkscape:cy="32.33556"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0000000"
+     showgrid="false"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g3013"
+     transform="translate(-6.9512812,-1.0861377)">
+    <path
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0"
+       id="path2992"
+       d="M 12.164743,36.19891 C 5.4419384,14.363664 19.8312,5.0887654 19.984934,5.1353724"
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m 15.468914,5.5609733 c -0.36081,1.346232 0.4391,2.731608 1.785332,3.092419 1.346657,0.36081 2.732033,-0.4391 3.092843,-1.785331 0.360811,-1.346232 -0.439099,-2.731863 -1.785756,-3.092589 -1.346232,-0.360768 -2.731608,0.439143 -3.092419,1.785501 z"
+       style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:1.32963777;stroke-linecap:round;stroke-linejoin:round;display:block"
+       id="path2086-1" />
+  </g>
+  <g
+     id="g3000-1"
+     transform="matrix(-0.16547702,-0.76683195,0.71991702,-0.1747779,-1.6807025,-45.625784)">
+    <path
+       inkscape:connector-curvature="0"
+       d="m -68.01036,3.028382 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round"
+       id="path1317-4" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m -109.52556,27.048382 c 10.892776,1.815507 23.421902,-5.113809 37.779,-21.812"
+       style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round"
+       id="path1323-3"
+       sodipodi:nodetypes="cc" />
+  </g>
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.722754,5.0263663 c 6.299598,3.6928682 6.299598,3.6928682 6.299598,3.6928682"
+     id="path3017"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.288299,8.7192345 c 6.734053,4.5617785 6.734053,4.5617785 6.734053,4.5617785"
+     id="path3019"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 13.685335,15.236061 c -0.217228,6.516826 -0.217228,6.516826 -0.217228,6.516826"
+     id="path3021"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="M 10.426922,15.018833 C 8.2546465,25.228527 8.2546465,25.228527 8.2546465,25.228527"
+     id="path3023"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Logo.png b/SRC/OpenMeca/Rsc/Img/Logo.png
new file mode 100644
index 0000000..f75a323
Binary files /dev/null and b/SRC/OpenMeca/Rsc/Img/Logo.png differ
diff --git a/SRC/OpenMeca/Rsc/Img/Logo.svg b/SRC/OpenMeca/Rsc/Img/Logo.svg
new file mode 100644
index 0000000..0af5fe6
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Logo.svg
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="300"
+   height="240"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="Logo.svg"
+   inkscape:export-filename="/home/dada/work/dev/openmeca/SRC/OpenMeca/Rsc/Img/Logo.png"
+   inkscape:export-xdpi="90"
+   inkscape:export-ydpi="90">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="803"
+     id="namedview3004"
+     showgrid="false"
+     inkscape:zoom="1.0824173"
+     inkscape:cx="206.43706"
+     inkscape:cy="119.62733"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
+  <metadata
+     id="metadata8">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs6">
+    <linearGradient
+       id="linearGradient3885">
+      <stop
+         style="stop-color:#ffeccc;stop-opacity:1;"
+         offset="0"
+         id="stop3887" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop3889" />
+    </linearGradient>
+    <path
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0"
+       id="path5015"
+       d="m 112.28675,-43.294213 c 79.40698,6.895775 101.40672,50.2690736 106.22162,104.561901"
+       style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+  </defs>
+  <g
+     id="g5852"
+     transform="matrix(1.7260912,0,0,1.7260912,-24.334949,-150.38181)">
+    <g
+       id="g5847">
+      <path
+         inkscape:connector-curvature="0"
+         d="m 160.44809,201.54954 -4.32977,0.28875 -0.96409,-1.62086 -1.97306,-0.83571 -2.07197,-0.73681 -2.01262,-0.56373 -1.75549,-0.34121 -0.68241,-0.15329 -0.0841,-1.49835 -0.10381,-1.48845 0.66263,-0.24231 1.6912,-0.55879 1.92857,-0.81098 1.95822,-0.98901 1.85933,-1.08296 -0.36099,-2.87306 -2.07196,-0.58351 -2.1412,-0.46978 -2.07197,-0.31153 -1.7802,-0.11374 -0.69725,-0.0692 -0.26703,-1.47362 -0.29177,-1.46867 0.62309,-0.31649 1.61206,-0.77142 1.81484,-1.0434 1.81483,-1.22637 1.7060 [...]
+         style="fill:#ffffbd;fill-opacity:1;stroke:#000000;stroke-width:1.62714851;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         id="gear50"
+         sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 93.47089,119.51143 -0.652744,1.25604 -0.573623,1.33021 -0.425273,1.30549 -0.252197,1.15219 -0.08406,0.80109 0.0049,0.28681 0.222526,2.40823 -2.062078,0.26209 -2.042295,0.38571 -0.534065,-2.35878 -0.08406,-0.27197 -0.326372,-0.73681 -0.588458,-1.01373 -0.810986,-1.11758 -0.954391,-1.08791 -1.008785,-0.989 -2.472515,0.80109 -0.237361,1.39945 -0.128577,1.43405 -0.0049,1.37967 0.118684,1.17197 0.16813,0.78626 0.09395,0.27197 0.959334,2.22032 -1.884056,0.88516 -1.82966,1.00879 - [...]
+         style="fill:#f1a875;fill-opacity:1;stroke:#000000;stroke-width:1.62714851;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         id="gear20" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 45.467593,182.99463 -1.721415,1.30924 0.03778,1.22284 0.205101,1.16183 0.314558,1.13053 0.370813,0.9241 0.384812,0.60665 0.187694,0.18761 2.532242,2.41858 -1.275694,1.53589 -1.033273,1.70002 -3.126298,-1.6053 -0.276804,-0.0953 -0.664627,-0.14841 -0.960171,-0.11239 -1.20407,0.0941 -1.218119,0.22388 -1.125834,0.313 -0.664153,2.07211 0.753944,0.97875 0.835225,0.83174 0.924336,0.73945 0.905523,0.49552 0.64589,0.27977 0.200175,0.0531 3.554517,0.48243 -0.149698,1.95786 0.183396,2 [...]
+         style="fill:#50c67b;fill-opacity:1;stroke:#000000;stroke-width:1.62714851;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+         id="gear10" />
+    </g>
+    <g
+       transform="translate(47.252802,148.39111)"
+       id="g5020">
+      <text
+         transform="translate(-102.90219,-7.0537792)"
+         xml:space="preserve"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:35px;line-height:125%;font-family:'Liberation Mono';-inkscape-font-specification:'Liberation Mono';text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         id="text4986"
+         sodipodi:linespacing="125%"
+         x="26.112469"
+         y="-19.364304"><textPath
+           style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25px;font-family:'Arial Black';-inkscape-font-specification:'Arial Black, '"
+           xlink:href="#path5015"
+           startOffset="100%"
+           id="textPath5017">open<tspan
+   id="tspan5702"
+   style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:Arial;-inkscape-font-specification:Arial">meca  </tspan></textPath></text>
+      <path
+         style="fill:none;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 112.28675,-43.294213 c 79.40698,6.895775 101.40672,50.2690736 106.22162,104.561901"
+         id="path5813"
+         inkscape:connector-curvature="0"
+         sodipodi:nodetypes="cc" />
+    </g>
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/New.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/New.svg
new file mode 100644
index 0000000..3a052f0
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/New.svg
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:ns1="http://sozi.baierouge.fr"
+    id="svg249"
+    sodipodi:docname="document-new.svg"
+    inkscape:export-filename="/home/jimmac/gfx/novell/pdes/trunk/docs/BIGmime-text.png"
+    viewBox="0 0 48 48"
+    sodipodi:version="0.32"
+    inkscape:export-xdpi="240.00000"
+    inkscape:output_extension="org.inkscape.output.svg.inkscape"
+    inkscape:export-ydpi="240.00000"
+    inkscape:version="0.46"
+    sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
+  >
+  <defs
+      id="defs3"
+    >
+    <radialGradient
+        id="radialGradient5031"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(-2.7744 0 0 1.9697 112.76 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5060"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5062"
+          style="stop-color:black"
+          offset="0"
+      />
+      <stop
+          id="stop5064"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient5029"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1891.6 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5027"
+        y2="609.51"
+        gradientUnits="userSpaceOnUse"
+        x2="302.86"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1892.2 -872.89)"
+        y1="366.65"
+        x1="302.86"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5050"
+          style="stop-color:black;stop-opacity:0"
+          offset="0"
+      />
+      <stop
+          id="stop5056"
+          style="stop-color:black"
+          offset=".5"
+      />
+      <stop
+          id="stop5052"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient278"
+        gradientUnits="userSpaceOnUse"
+        cy="125"
+        cx="55"
+        r="14.375"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop12513"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop12517"
+          style="stop-color:#fff520;stop-opacity:.89109"
+          offset=".5"
+      />
+      <stop
+          id="stop12514"
+          style="stop-color:#fff300;stop-opacity:0"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <radialGradient
+        id="radialGradient15656"
+        gradientUnits="userSpaceOnUse"
+        cx="8.8244"
+        cy="3.7561"
+        r="37.752"
+        gradientTransform="matrix(.96827 0 0 1.0328 3.3536 .64645)"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop270"
+          style="stop-color:#a3a3a3"
+          offset="0"
+      />
+      <stop
+          id="stop271"
+          style="stop-color:#4c4c4c"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <radialGradient
+        id="radialGradient15658"
+        gradientUnits="userSpaceOnUse"
+        cx="33.967"
+        cy="35.737"
+        r="86.708"
+        gradientTransform="scale(.96049 1.0411)"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop260"
+          style="stop-color:#fafafa"
+          offset="0"
+      />
+      <stop
+          id="stop261"
+          style="stop-color:#bbbbbb"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <radialGradient
+        id="radialGradient15668"
+        gradientUnits="userSpaceOnUse"
+        cx="8.1436"
+        cy="7.2679"
+        r="38.159"
+        gradientTransform="matrix(.96827 0 0 1.0328 3.3536 .64645)"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop15664"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop15666"
+          style="stop-color:#f8f8f8"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <radialGradient
+        id="radialGradient2283"
+        gradientUnits="userSpaceOnUse"
+        cy="114.57"
+        cx="20.892"
+        gradientTransform="matrix(.22970 0 0 .22970 4.6135 3.9798)"
+        r="5.256"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop15566"
+          style="stop-color:#F0F0F0"
+          offset="0"
+      />
+      <stop
+          id="stop15568"
+          style="stop-color:#9a9a9a"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <radialGradient
+        id="radialGradient2285"
+        gradientUnits="userSpaceOnUse"
+        cy="64.568"
+        cx="20.892"
+        gradientTransform="matrix(.22970 0 0 .22970 4.6135 3.9798)"
+        r="5.257"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop15573"
+          style="stop-color:#F0F0F0"
+          offset="0"
+      />
+      <stop
+          id="stop15575"
+          style="stop-color:#9a9a9a"
+          offset="1"
+      />
+    </radialGradient
+    >
+  </defs
+  >
+  <sodipodi:namedview
+      id="base"
+      bordercolor="#666666"
+      inkscape:pageshadow="2"
+      inkscape:window-y="151"
+      pagecolor="#ffffff"
+      inkscape:window-height="688"
+      inkscape:grid-bbox="true"
+      inkscape:zoom="1"
+      inkscape:window-x="166"
+      showgrid="false"
+      borderopacity="0.32941176"
+      inkscape:current-layer="layer6"
+      inkscape:cx="-130.2425"
+      inkscape:cy="-6.4480487"
+      inkscape:showpageshadow="false"
+      inkscape:window-width="872"
+      inkscape:pageopacity="0.0"
+      inkscape:document-units="px"
+  />
+  <g
+      id="layer6"
+      inkscape:label="Shadow"
+      inkscape:groupmode="layer"
+    >
+    <g
+        id="g5022"
+        transform="matrix(.021652 0 0 .014857 43.008 42.685)"
+      >
+      <rect
+          id="rect4173"
+          style="opacity:.40206;color:black;fill:url(#linearGradient5027)"
+          height="478.36"
+          width="1339.6"
+          y="-150.7"
+          x="-1559.3"
+      />
+      <path
+          id="path5058"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5029)"
+          d="m-219.62-150.68v478.33c142.88 0.9 345.4-107.17 345.4-239.2 0-132.02-159.44-239.13-345.4-239.13z"
+      />
+      <path
+          id="path5018"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5031)"
+          d="m-1559.3-150.68v478.33c-142.8 0.9-345.4-107.17-345.4-239.2 0-132.02 159.5-239.13 345.4-239.13z"
+      />
+    </g
+    >
+  </g
+  >
+  <g
+      id="layer1"
+      inkscape:label="Base"
+      inkscape:groupmode="layer"
+    >
+    <rect
+        id="rect15391"
+        style="stroke-linejoin:round;color:#000000;display:block;stroke:url(#radialGradient15656);stroke-linecap:round;fill:url(#radialGradient15658)"
+        ry="1.149"
+        height="40.92"
+        width="34.875"
+        y="3.6464"
+        x="6.6036"
+    />
+    <rect
+        id="rect15660"
+        style="stroke-linejoin:round;color:#000000;display:block;stroke:url(#radialGradient15668);stroke-linecap:round;fill:none"
+        rx=".14905"
+        ry=".14905"
+        height="38.946"
+        width="32.776"
+        y="4.5839"
+        x="7.6661"
+    />
+    <g
+        id="g2270"
+        transform="translate(.64645 -.037989)"
+      >
+      <g
+          id="g1440"
+          style="stroke:#000000;fill:#ffffff"
+          transform="matrix(.22970 0 0 .22970 4.9671 4.245)"
+        >
+        <path
+            id="path1448"
+            d="m23.428 113.07c0 1.97-1.6 3.57-3.573 3.57-1.974 0-3.573-1.6-3.573-3.57s1.6-3.57 3.573-3.57 3.573 1.6 3.573 3.57z"
+        />
+        <path
+            id="path1456"
+            d="m23.428 63.07c0 1.973-1.6 3.573-3.573 3.573-1.974 0-3.573-1.6-3.573-3.573 0-1.974 1.6-3.573 3.573-3.573s3.573 1.6 3.573 3.573z"
+        />
+      </g
+      >
+      <path
+          id="path15570"
+          style="fill:url(#radialGradient2283)"
+          d="m9.995 29.952c0 0.454-0.3675 0.821-0.8207 0.821-0.4535 0-0.8207-0.368-0.8207-0.821s0.3675-0.82 0.8207-0.82 0.8207 0.367 0.8207 0.82z"
+      />
+      <path
+          id="path15577"
+          style="fill:url(#radialGradient2285)"
+          d="m9.995 18.467c0 0.453-0.3675 0.821-0.8207 0.821-0.4535 0-0.8207-0.368-0.8207-0.821s0.3675-0.821 0.8207-0.821 0.8207 0.368 0.8207 0.821z"
+      />
+    </g
+    >
+    <path
+        id="path15672"
+        sodipodi:nodetypes="cc"
+        style="stroke-opacity:.017544;stroke:#000000;stroke-width:.98855;fill:none"
+        d="m11.506 5.4943v37.907"
+    />
+    <path
+        id="path15674"
+        sodipodi:nodetypes="cc"
+        style="stroke-opacity:.20468;stroke:#ffffff;fill:none"
+        d="m12.5 5.0205v38.018"
+    />
+  </g
+  >
+  <g
+      id="layer4"
+      inkscape:label="new"
+      inkscape:groupmode="layer"
+    >
+    <path
+        id="path12511"
+        sodipodi:rx="14.375000"
+        sodipodi:ry="14.375000"
+        style="color:#000000;display:block;fill:url(#radialGradient278)"
+        sodipodi:type="arc"
+        d="m69.375 125a14.375 14.375 0 1 1 -28.75 0 14.375 14.375 0 1 1 28.75 0z"
+        inkscape:export-ydpi="33.852203"
+        inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/stock_new-16.png"
+        transform="matrix(.78329 0 0 .78329 -6.3409 -86.652)"
+        sodipodi:cy="125.00000"
+        sodipodi:cx="55.000000"
+        inkscape:export-xdpi="33.852203"
+    />
+  </g
+  >
+  <metadata
+    >
+    <rdf:RDF
+      >
+      <cc:Work
+        >
+        <dc:format
+          >image/svg+xml</dc:format
+        >
+        <dc:type
+            rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+        />
+        <cc:license
+            rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+        />
+        <dc:publisher
+          >
+          <cc:Agent
+              rdf:about="http://openclipart.org/"
+            >
+            <dc:title
+              >Openclipart</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:publisher
+        >
+        <dc:title
+          >tango document new</dc:title
+        >
+        <dc:date
+          >2010-03-18T14:57:14</dc:date
+        >
+        <dc:description
+          >New document icon from <a href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </a> 
\n<br><br>
\nSince version 0.8.90 Tango Project icons are Public Domain: <a href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </a></dc:description
+        >
+        <dc:source
+          >https://openclipart.org/detail/32137/tango-document-new-by-warszawianka</dc:source
+        >
+        <dc:creator
+          >
+          <cc:Agent
+            >
+            <dc:title
+              >warszawianka</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:creator
+        >
+        <dc:subject
+          >
+          <rdf:Bag
+            >
+            <rdf:li
+              >blank</rdf:li
+            >
+            <rdf:li
+              >document</rdf:li
+            >
+            <rdf:li
+              >externalsource</rdf:li
+            >
+            <rdf:li
+              >filesystem</rdf:li
+            >
+            <rdf:li
+              >icon</rdf:li
+            >
+            <rdf:li
+              >new</rdf:li
+            >
+            <rdf:li
+              >page</rdf:li
+            >
+            <rdf:li
+              >paper</rdf:li
+            >
+            <rdf:li
+              >tango</rdf:li
+            >
+            <rdf:li
+              >text</rdf:li
+            >
+          </rdf:Bag
+          >
+        </dc:subject
+        >
+      </cc:Work
+      >
+      <cc:License
+          rdf:about="http://creativecommons.org/licenses/publicdomain/"
+        >
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Reproduction"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Distribution"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+        />
+      </cc:License
+      >
+    </rdf:RDF
+    >
+  </metadata
+  >
+</svg
+>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/Open.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/Open.svg
new file mode 100644
index 0000000..3a29393
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/Open.svg
@@ -0,0 +1,627 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:ns1="http://sozi.baierouge.fr"
+    id="svg97"
+    sodipodi:docname="document-open.svg"
+    inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/snowdunes/gnome-fs-directory-accept.png"
+    viewBox="0 0 48 48"
+    sodipodi:version="0.32"
+    inkscape:export-xdpi="90.000000"
+    inkscape:output_extension="org.inkscape.output.svg.inkscape"
+    inkscape:export-ydpi="90.000000"
+    inkscape:version="0.46"
+    sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
+  >
+  <defs
+      id="defs3"
+    >
+    <radialGradient
+        id="radialGradient5031"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(-2.7744 0 0 1.9697 112.76 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5060"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5062"
+          style="stop-color:black"
+          offset="0"
+      />
+      <stop
+          id="stop5064"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient5029"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1891.6 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5027"
+        y2="609.51"
+        gradientUnits="userSpaceOnUse"
+        x2="302.86"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1892.2 -872.89)"
+        y1="366.65"
+        x1="302.86"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5050"
+          style="stop-color:black;stop-opacity:0"
+          offset="0"
+      />
+      <stop
+          id="stop5056"
+          style="stop-color:black"
+          offset=".5"
+      />
+      <stop
+          id="stop5052"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient8234"
+        gradientUnits="userSpaceOnUse"
+        cy="3.7561"
+        cx="8.8244"
+        gradientTransform="matrix(.96827 0 0 1.0467 44.365 -17.007)"
+        r="37.752"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop270"
+          style="stop-color:#a3a3a3"
+          offset="0"
+      />
+      <stop
+          id="stop271"
+          style="stop-color:#4c4c4c"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient8236"
+        y2="30.875"
+        gradientUnits="userSpaceOnUse"
+        x2="25.25"
+        gradientTransform="matrix(1 0 0 1.2388 0 -7.8806)"
+        y1="10.625"
+        x1="25.875"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop260"
+          style="stop-color:#fafafa"
+          offset="0"
+      />
+      <stop
+          id="stop8238"
+          style="stop-color:#a8a8a8"
+          offset=".5"
+      />
+      <stop
+          id="stop261"
+          style="stop-color:#cdcdcd"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient155"
+        y2="51.913"
+        gradientUnits="userSpaceOnUse"
+        x2="19.427"
+        gradientTransform="scale(1.4215 .70346)"
+        y1="28.946"
+        x1="19.116"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop336"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop337"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient156"
+        y2="41.837"
+        gradientUnits="userSpaceOnUse"
+        x2="22.715"
+        gradientTransform="matrix(1.5353 0 0 .65134 3.4514 2.448)"
+        y1="27.06"
+        x1="14.899"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop149"
+          style="stop-color:#ffffff;stop-opacity:.13402"
+          offset="0"
+      />
+      <stop
+          id="stop150"
+          style="stop-color:#ffffff;stop-opacity:.051546"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient158"
+        y2="52.626"
+        gradientUnits="userSpaceOnUse"
+        x2="8.2122"
+        gradientTransform="matrix(1.4627 0 .069079 .68367 0 0)"
+        y1="18.726"
+        x1="5.2658"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop138"
+          style="stop-color:#ffffff;stop-opacity:.70060"
+          offset="0"
+      />
+      <stop
+          id="stop139"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient159"
+        gradientUnits="userSpaceOnUse"
+        cy="38.195"
+        cx="26.107"
+        gradientTransform="matrix(1.0156 0 .10310 1.0005 0 -.083695)"
+        r="32.26"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop1790"
+          style="stop-color:#a0a0a0"
+          offset="0"
+      />
+      <stop
+          id="stop1791"
+          style="stop-color:#a8a8a8"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient13162"
+        y2="32.05"
+        gradientUnits="userSpaceOnUse"
+        x2="22.065"
+        gradientTransform="matrix(1 0 0 1.0221 52.057 -1.323)"
+        y1="36.988"
+        x1="22.176"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop9768"
+          style="stop-color:#6194cb"
+          offset="0"
+      />
+      <stop
+          id="stop9770"
+          style="stop-color:#729fcf"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient13848"
+        y2="14.875"
+        gradientUnits="userSpaceOnUse"
+        x2="19.75"
+        y1="37.625"
+        x1="22.25"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop13844"
+          style="stop-color:#000000"
+          offset="0"
+      />
+      <stop
+          id="stop13846"
+          style="stop-color:#000000;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+  </defs
+  >
+  <sodipodi:namedview
+      id="base"
+      bordercolor="#666666"
+      inkscape:pageshadow="2"
+      inkscape:window-y="30"
+      pagecolor="#ffffff"
+      inkscape:window-height="818"
+      inkscape:grid-bbox="true"
+      inkscape:zoom="1"
+      inkscape:window-x="407"
+      showgrid="false"
+      borderopacity="1.0"
+      inkscape:current-layer="layer3"
+      inkscape:cx="-123.73861"
+      inkscape:cy="37.388301"
+      inkscape:showpageshadow="false"
+      inkscape:window-width="1027"
+      inkscape:pageopacity="0.0"
+      inkscape:document-units="px"
+  />
+  <g
+      id="layer3"
+      inkscape:label="Open"
+      inkscape:groupmode="layer"
+    >
+    <path
+        id="path2375"
+        d="m4.62 38.651c0.0418 0.42 0.4974 0.841 0.9112 0.841h31.136c0.414 0 0.786-0.421 0.744-0.841l-2.696-27.119c-0.042-0.421-0.498-0.841-0.912-0.841h-12.723c-0.59 0-1.209-0.38-1.403-0.9605l-1.103-3.3059c-0.169-0.5073-0.547-0.7358-1.314-0.7358h-14.938c-0.4134 0-0.7853 0.4205-0.7435 0.8409l3.0415 32.121z"
+        sodipodi:nodetypes="ccccccssssccc"
+        style="stroke-linejoin:round;color:#000000;stroke:#5a5a5a;stroke-linecap:round;fill:url(#radialGradient159)"
+    />
+    <path
+        id="path13113"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m3.3386 17.533h31.149"
+    />
+    <path
+        id="path13160"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m5.3302 37.533h29.988"
+    />
+    <path
+        id="path13139"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m5.3302 35.533h29.988"
+    />
+    <g
+        id="g5022"
+        transform="matrix(.021652 0 0 .019038 42.415 36.934)"
+      >
+      <rect
+          id="rect4173"
+          style="opacity:.40206;color:black;fill:url(#linearGradient5027)"
+          height="478.36"
+          width="1339.6"
+          y="-150.7"
+          x="-1559.3"
+      />
+      <path
+          id="path5058"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5029)"
+          d="m-219.62-150.68v478.33c142.88 0.9 345.4-107.17 345.4-239.2 0-132.02-159.44-239.13-345.4-239.13z"
+      />
+      <path
+          id="path5018"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5031)"
+          d="m-1559.3-150.68v478.33c-142.8 0.9-345.4-107.17-345.4-239.2 0-132.02 159.5-239.13 345.4-239.13z"
+      />
+    </g
+    >
+    <path
+        id="path2380"
+        sodipodi:nodetypes="ccccccsscsscccc"
+        style="color:#000000;display:block;fill:url(#linearGradient158)"
+        d="m6.1718 38.419c0.0313 0.31-0.1547 0.517-0.4755 0.413-0.3207-0.103-0.5485-0.31-0.5799-0.62l-3.0295-31.367c-0.0314-0.3107 0.1566-0.4981 0.4669-0.4981l14.75-0.0915c0.531-0.0033 0.739 0.0533 0.879 0.5172 0 0 1.086 3.1128 1.247 3.6984l-1.556-2.9173c-0.265-0.4973-0.599-0.4138-0.973-0.4138h-13.129c-0.3105 0-0.4965 0.2069-0.4652 0.5172l2.9788 30.865-0.1138-0.103z"
+    />
+    <path
+        id="path13145"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m2.3052 7.5335h14.784"
+    />
+    <path
+        id="path13115"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m2.7573 11.533h30.739"
+    />
+    <g
+        id="g2381"
+        style="fill-opacity:.58031;stroke:#000000;display:block;fill:#ffffff"
+        inkscape:export-ydpi="74.800003"
+        inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+        transform="matrix(1.0344 0 .10452 1.0344 -10.032 2.6319)"
+        inkscape:export-xdpi="74.800003"
+      >
+      <path
+          id="path2382"
+          sodipodi:nodetypes="cscscs"
+          d="m41.786 9.0364c0.009-0.4746 0.015-0.7245-0.424-0.7242l-12.555 0.0086c-0.3 0-0.325-0.1432 0 0 0.324 0.1432 1.247 0.6583 2.182 0.701 0 0 10.797 0.0165 10.797 0.0146z"
+      />
+    </g
+    >
+    <path
+        id="path13123"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m3.1629 15.533h30.83"
+    />
+    <path
+        id="path13121"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m5.1595 33.533h29.988"
+    />
+    <path
+        id="path13119"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m4.8658 31.533h30.109"
+    />
+    <path
+        id="path13135"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m4.6336 29.533h30.169"
+    />
+    <path
+        id="path13137"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m4.463 27.533h30.169"
+    />
+    <path
+        id="path13143"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m4.2557 25.533h30.205"
+    />
+    <path
+        id="path13133"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m4.0235 23.533h30.266"
+    />
+    <path
+        id="path13117"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m3.8528 21.533h30.265"
+    />
+    <g
+        id="g1853"
+        style="fill-opacity:.58031;stroke:#000000;display:block;fill:#ffffff"
+        inkscape:export-ydpi="74.800003"
+        inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+        transform="matrix(1.0344 0 .10452 1.0344 -10.032 2.6319)"
+        inkscape:export-xdpi="74.800003"
+      >
+      <path
+          id="path1855"
+          sodipodi:nodetypes="cscscs"
+          d="m41.786 9.0364c0.009-0.4746 0.015-0.7245-0.424-0.7242l-12.555 0.0086c-0.3 0-0.325-0.1432 0 0 0.324 0.1432 1.247 0.6583 2.182 0.701 0 0 10.797 0.0165 10.797 0.0146z"
+      />
+    </g
+    >
+    <path
+        id="path13127"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m2.9642 13.533h31.027"
+    />
+    <path
+        id="path13125"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m3.6514 19.533h30.296"
+    />
+    <path
+        id="path13147"
+        sodipodi:nodetypes="cc"
+        style="opacity:.11364;stroke-linejoin:round;color:#000000;stroke:#000000;stroke-linecap:round;fill:#729fcf"
+        d="m2.5243 9.5335h15.281"
+    />
+    <path
+        id="path13840"
+        sodipodi:nodetypes="cccsc"
+        style="opacity:.39205;color:#000000;display:block;fill:url(#linearGradient13848)"
+        d="m34.375 14.125l2.625 24.625-31 0.125-1.875-24.75h30.25z"
+    />
+    <path
+        id="path8230"
+        sodipodi:nodetypes="ccccc"
+        style="color:#000000;display:block;stroke:url(#radialGradient8234);fill:url(#linearGradient8236)"
+        d="m43.375 2.4944c0.5 16.879-9.075 18.529-6.013 29.001 0 0-31.487 0.886-31.487 0.886-1.875-12.853 8.375-21.215 5.375-29.732l32.125-0.1546z"
+    />
+    <path
+        id="path8277"
+        sodipodi:nodetypes="cc"
+        style="color:#000000;display:block;stroke:#a1a1a1;fill:none"
+        d="m15.438 6.5625h23.562"
+    />
+    <path
+        id="path2401"
+        style="stroke-linejoin:round;color:#000000;display:block;stroke:#3465a4;fill:url(#linearGradient13162)"
+        d="m5.7786 39.066c0.1034 0.211 0.3103 0.423 0.6206 0.423h33.309c0.207 0 0.521-0.126 0.708-0.264 0.53-0.392 0.655-0.613 0.893-0.974 2.448-3.715 5.805-19.277 5.805-19.277 0.103-0.211-0.104-0.423-0.414-0.423h-34.924c-0.31 0-1.656 16.108-4.8626 19.287l-1.2383 1.228h0.1035z"
+        inkscape:export-ydpi="74.800003"
+        sodipodi:nodetypes="cccsscccscc"
+        inkscape:export-filename="/home/jimmac/ximian_art/icons/nautilus/suse93/gnome-fs-directory.png"
+        inkscape:export-xdpi="74.800003"
+    />
+    <path
+        id="path8279"
+        sodipodi:nodetypes="cc"
+        style="color:#000000;display:block;stroke:#a1a1a1;fill:none"
+        d="m15.356 8.5625h19.725"
+    />
+    <path
+        id="path323"
+        sodipodi:nodetypes="ccccc"
+        style="fill-rule:evenodd;fill:url(#linearGradient156)"
+        d="m13.134 20.139c-0.772 4.99-1.501 9.009-2.716 13.514 2.387-0.708 7.117-3.205 17.117-3.205s16.723-9.249 17.651-10.354l-32.052 0.045z"
+    />
+    <path
+        id="path8281"
+        sodipodi:nodetypes="cc"
+        style="color:#000000;display:block;stroke:#a1a1a1;fill:none"
+        d="m15.143 10.562h24.315"
+    />
+    <path
+        id="path324"
+        sodipodi:nodetypes="cccsc"
+        style="opacity:.52273;color:#000000;stroke:url(#linearGradient155);stroke-linecap:round;stroke-width:1px;fill:none"
+        d="m45.82 19.688h-33.158s-2.148 16.019-4.7227 18.24c8.1207 0 31.572-0.049 31.591-0.049 1.752 0 4.908-12.636 6.29-18.191z"
+    />
+    <path
+        id="path8283"
+        sodipodi:nodetypes="cc"
+        style="color:#000000;display:block;stroke:#a1a1a1;fill:none"
+        d="m14.399 12.562h23.853"
+    />
+    <path
+        id="path8285"
+        sodipodi:nodetypes="cc"
+        style="color:#000000;display:block;stroke:#a1a1a1;fill:none"
+        d="m13.629 14.562h23.346"
+    />
+    <path
+        id="path8287"
+        sodipodi:nodetypes="cc"
+        style="color:#000000;display:block;stroke:#a1a1a1;fill:none"
+        d="m12.521 16.562h18.646"
+    />
+    <path
+        id="path8289"
+        sodipodi:nodetypes="ccccc"
+        style="color:#000000;display:block;fill:#ffffff"
+        d="m6.375 31.75c-1.2414-12.238 7.187-19.062 5.625-28.75h30.875l-30 0.625c1.25 9.563-6.1964 14.646-6.5 28.125z"
+    />
+  </g
+  >
+  <metadata
+    >
+    <rdf:RDF
+      >
+      <cc:Work
+        >
+        <dc:format
+          >image/svg+xml</dc:format
+        >
+        <dc:type
+            rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+        />
+        <cc:license
+            rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+        />
+        <dc:publisher
+          >
+          <cc:Agent
+              rdf:about="http://openclipart.org/"
+            >
+            <dc:title
+              >Openclipart</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:publisher
+        >
+        <dc:title
+          >tango document open</dc:title
+        >
+        <dc:date
+          >2010-03-18T16:08:09</dc:date
+        >
+        <dc:description
+          >"Open document" icon from <A href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </A> 
\n<BR><BR>
\nSince version 0.8.90 Tango Project icons are Public Domain: <A href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </A></dc:description
+        >
+        <dc:source
+          >https://openclipart.org/detail/32215/tango-document-open-by-warszawianka</dc:source
+        >
+        <dc:creator
+          >
+          <cc:Agent
+            >
+            <dc:title
+              >warszawianka</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:creator
+        >
+        <dc:subject
+          >
+          <rdf:Bag
+            >
+            <rdf:li
+              >document</rdf:li
+            >
+            <rdf:li
+              >icon</rdf:li
+            >
+            <rdf:li
+              >open</rdf:li
+            >
+            <rdf:li
+              >tango</rdf:li
+            >
+          </rdf:Bag
+          >
+        </dc:subject
+        >
+      </cc:Work
+      >
+      <cc:License
+          rdf:about="http://creativecommons.org/licenses/publicdomain/"
+        >
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Reproduction"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Distribution"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+        />
+      </cc:License
+      >
+    </rdf:RDF
+    >
+  </metadata
+  >
+</svg
+>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/Preference.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/Preference.svg
new file mode 100644
index 0000000..a230fe0
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/Preference.svg
@@ -0,0 +1,488 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:ns1="http://sozi.baierouge.fr"
+    id="svg11300"
+    sodipodi:docname="preferences-system.svg"
+    inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+    viewBox="0 0 48 48"
+    sodipodi:version="0.32"
+    inkscape:export-xdpi="90.000000"
+    inkscape:output_extension="org.inkscape.output.svg.inkscape"
+    inkscape:export-ydpi="90.000000"
+    inkscape:version="0.46"
+    sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/categories"
+  >
+  <defs
+      id="defs3"
+    >
+    <linearGradient
+        id="linearGradient3041"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop3043"
+          style="stop-color:#000000"
+          offset="0"
+      />
+      <stop
+          id="stop3045"
+          style="stop-color:#000000;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient3047"
+        xlink:href="#linearGradient3041"
+        gradientUnits="userSpaceOnUse"
+        cy="39.125"
+        cx="24.812"
+        gradientTransform="matrix(1 0 0 .37456 7.1943e-15 24.47)"
+        r="17.688"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient3055"
+        y2="6.7758"
+        gradientUnits="userSpaceOnUse"
+        x2="20.631"
+        gradientTransform="matrix(.87827 0 0 .87827 2.537 4.9677)"
+        y1="42.254"
+        x1="19.648"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop3051"
+          style="stop-color:#b6b6b6"
+          offset="0"
+      />
+      <stop
+          id="stop2262"
+          style="stop-color:#f2f2f2"
+          offset=".5"
+      />
+      <stop
+          id="stop2264"
+          style="stop-color:#fafafa"
+          offset=".67613"
+      />
+      <stop
+          id="stop2268"
+          style="stop-color:#d8d8d8"
+          offset=".84052"
+      />
+      <stop
+          id="stop2266"
+          style="stop-color:#f2f2f2"
+          offset=".875"
+      />
+      <stop
+          id="stop3053"
+          style="stop-color:#dbdbdb"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient3067"
+        y2="-4.3003"
+        gradientUnits="userSpaceOnUse"
+        x2="25.291"
+        gradientTransform="matrix(.87827 -1.3759e-15 1.3759e-15 .87827 5.3283 1.6502)"
+        y1="-3.6324"
+        x1="50.153"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop3063"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop3065"
+          style="stop-color:#000000"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient3083"
+        y2="6.6286"
+        gradientUnits="userSpaceOnUse"
+        x2="37.535"
+        gradientTransform="matrix(.87827 0 0 .87827 2.8475 5.5887)"
+        y1="13.603"
+        x1="38.228"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop3079"
+          style="stop-color:#98a0a9"
+          offset="0"
+      />
+      <stop
+          id="stop3081"
+          style="stop-color:#c3d0dd"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient3093"
+        y2="39.443"
+        gradientUnits="userSpaceOnUse"
+        x2="16.915"
+        gradientTransform="matrix(.87827 0 0 .87827 2.537 4.9677)"
+        y1="32.284"
+        x1="9.7503"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop3089"
+          style="stop-color:#3465a4"
+          offset="0"
+      />
+      <stop
+          id="stop3095"
+          style="stop-color:#9fbce1"
+          offset="0"
+      />
+      <stop
+          id="stop2242"
+          style="stop-color:#6b95ca"
+          offset="0"
+      />
+      <stop
+          id="stop2244"
+          style="stop-color:#3d6aa5"
+          offset=".75"
+      />
+      <stop
+          id="stop3091"
+          style="stop-color:#386eb4"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient2263"
+        y2="33.195"
+        gradientUnits="userSpaceOnUse"
+        x2="10.651"
+        gradientTransform="matrix(1.0073 -.026365 .026365 1.0073 1.5934 .079191)"
+        y1="35.688"
+        x1="12.005"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop2259"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop2261"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient2271"
+        y2="38.268"
+        gradientUnits="userSpaceOnUse"
+        x2="15.416"
+        gradientTransform="matrix(.87810 -.017324 .017324 .87810 2.1637 4.0679)"
+        y1="36.943"
+        x1="14.018"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop2267"
+          style="stop-color:#000000"
+          offset="0"
+      />
+      <stop
+          id="stop2269"
+          style="stop-color:#000000;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient2256"
+        y2="9.6569"
+        gradientUnits="userSpaceOnUse"
+        x2="40.859"
+        y1="19.822"
+        x1="31.177"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop2252"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop2254"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient2260"
+        xlink:href="#linearGradient3041"
+        gradientUnits="userSpaceOnUse"
+        cy="39.125"
+        cx="24.812"
+        gradientTransform="matrix(1 0 0 .37456 7.2728e-15 24.47)"
+        r="17.688"
+        inkscape:collect="always"
+    />
+  </defs
+  >
+  <sodipodi:namedview
+      id="base"
+      bordercolor="#666666"
+      inkscape:pageshadow="2"
+      inkscape:window-y="30"
+      pagecolor="#ffffff"
+      inkscape:showpageshadow="false"
+      inkscape:grid-bbox="true"
+      inkscape:zoom="4"
+      inkscape:cx="19.425317"
+      inkscape:window-height="818"
+      showgrid="false"
+      borderopacity="0.25490196"
+      inkscape:current-layer="layer1"
+      stroke="#204a87"
+      inkscape:cy="26.37487"
+      inkscape:window-x="400"
+      inkscape:window-width="1034"
+      inkscape:pageopacity="0.0"
+      inkscape:document-units="px"
+      fill="#3465a4"
+  />
+  <g
+      id="layer1"
+      inkscape:label="Layer 1"
+      inkscape:groupmode="layer"
+    >
+    <path
+        id="path2258"
+        sodipodi:rx="17.6875"
+        sodipodi:ry="6.625"
+        style="opacity:.19886;color:#000000;fill:url(#radialGradient2260)"
+        sodipodi:type="arc"
+        d="m42.5 39.125a17.688 6.625 0 1 1 -35.375 0 17.688 6.625 0 1 1 35.375 0z"
+        transform="matrix(.75112 0 0 .57870 17.041 19.363)"
+        sodipodi:cy="39.125"
+        sodipodi:cx="24.8125"
+    />
+    <path
+        id="path3039"
+        sodipodi:rx="17.6875"
+        sodipodi:ry="6.625"
+        style="opacity:.3125;color:#000000;fill:url(#radialGradient3047)"
+        sodipodi:type="arc"
+        d="m42.5 39.125a17.688 6.625 0 1 1 -35.375 0 17.688 6.625 0 1 1 35.375 0z"
+        transform="matrix(.83607 0 0 .68544 -7.9596 15.718)"
+        sodipodi:cy="39.125"
+        sodipodi:cx="24.8125"
+    />
+    <path
+        id="path2140"
+        sodipodi:nodetypes="cczcccccccccsc"
+        style="color:#000000;stroke:#888a85;fill:url(#linearGradient3055)"
+        d="m17.907 21.216l18.992 19.431c0.769 0.879 3.204 1.557 4.831 0 1.571-1.503 1.207-3.622-0.33-5.159l-18.224-19.542c2.25-6.2499-2.304-11.5-8.179-10.374l-1.262 1.1522 3.952 3.7328 0.22 3.293-2.951 2.694-3.527-0.388-3.6224-3.403-1.2701 1.254c-0.5908 5.642 5.3075 10.684 11.37 7.309z"
+    />
+    <path
+        id="path3057"
+        sodipodi:nodetypes="cczccccccccccc"
+        style="opacity:.42614;color:#000000;stroke:#ffffff;fill:none"
+        d="m18.117 19.94l19.203 20.028c0.595 0.68 2.48 1.205 3.74 0 1.216-1.164 0.935-2.805-0.255-3.995l-18.492-19.621c1.5-6.4998-1.859-10.004-6.859-9.8795l-0.27 0.2734 3.603 3.2363 0.13 4.1818-3.614 3.298-4.242-0.458-3.1764-2.991-0.3527 0.43c-0.3125 5.969 6.4921 8.685 10.585 5.497z"
+    />
+    <rect
+        id="rect3059"
+        style="opacity:.17045;color:#000000;stroke:url(#linearGradient3067);fill:none"
+        transform="rotate(45.738)"
+        rx=".88388"
+        ry=".88388"
+        height="2.0555"
+        width="23.268"
+        y="-2.6184"
+        x="28.185"
+    />
+    <path
+        id="path2144"
+        sodipodi:nodetypes="ccccccccc"
+        style="color:#000000;stroke:#878f9d;fill:url(#linearGradient3083)"
+        d="m22.499 30.125c0.833-0.714 13.284-13.448 13.284-13.448l3.074-0.22 4.83-6.6965-4.024-3.5852-6.258 5.3797v3.074l-12.735 13.229c-0.604 0.603 1.06 2.926 1.829 2.267z"
+    />
+    <path
+        id="path3085"
+        sodipodi:nodetypes="ccccccccc"
+        style="opacity:.53977;color:#000000;stroke:url(#linearGradient2256);fill:none"
+        d="m22.402 29.085c0.647-0.554 13.024-13.229 13.024-13.229l2.929-0.248 4.214-5.6624-2.89-2.549-5.476 4.7174 0.155 2.851-12.676 13.292c-0.469 0.469 0.124 1.34 0.72 0.828z"
+    />
+    <path
+        id="path2142"
+        sodipodi:nodetypes="ccccccscc"
+        style="color:#000000;stroke:#204a87;fill:url(#linearGradient3093)"
+        d="m8.4653 43.612c1.3166 1.465 4.9737 2.128 6.5957-0.71 0.707-1.238 2.094-4.703 8.281-10.272 1.039-0.934 2.14-3.071 1.207-4.223l-2.416-2.416c-0.988-1.098-3.734-0.585-4.861 0.951-3.359 4.596-8.8459 8.255-10.083 8.697-2.3682 0.846-2.1017 4.336-0.5351 5.996l1.8114 1.977z"
+    />
+    <path
+        id="path2146"
+        sodipodi:rx="1.375"
+        sodipodi:ry="1.375"
+        style="color:#000000;stroke:#a1a1a1;stroke-width:1.1386;fill:#ffffff"
+        sodipodi:type="arc"
+        d="m43.25 37.5a1.375 1.375 0 1 1 -2.75 0 1.375 1.375 0 1 1 2.75 0z"
+        transform="matrix(.87827 0 0 .87827 2.4272 5.0775)"
+        sodipodi:cy="37.5"
+        sodipodi:cx="41.875"
+    />
+    <path
+        id="path3101"
+        sodipodi:rx="1.767767"
+        sodipodi:ry="1.767767"
+        style="opacity:.60227;color:#000000;fill:#ffffff"
+        sodipodi:type="arc"
+        d="m20.771 28.201a1.7678 1.7678 0 1 1 -3.535 0 1.7678 1.7678 0 1 1 3.535 0z"
+        transform="matrix(.57088 0 0 .57088 9.1548 11.251)"
+        sodipodi:cy="28.20101"
+        sodipodi:cx="19.003494"
+    />
+    <path
+        id="path3103"
+        sodipodi:nodetypes="cc"
+        style="stroke-linejoin:round;color:#000000;stroke:url(#linearGradient2263);stroke-linecap:round;stroke-width:2.2945;fill:none"
+        d="m18.679 29.625s-7.17 7.299-10.529 8.537"
+    />
+    <path
+        id="path2270"
+        sodipodi:nodetypes="csccccscc"
+        style="opacity:.19886;color:#000000;stroke:#ffffff;fill:none"
+        d="m8.806 42.487c1.441 1.745 4.6 2.161 5.591-0.371 0.681-1.739 3.334-5.666 8.198-10.043 0.817-0.735 1.682-2.415 0.948-3.321l-1.898-1.898c-0.777-0.864-2.936-0.461-3.822 0.747-2.64 3.613-8.4832 8.34-9.8956 8.806-2.1868 0.721-1.777 3.221-0.5454 4.526l1.424 1.554z"
+    />
+    <path
+        id="path2247"
+        sodipodi:nodetypes="cc"
+        style="opacity:.27841;stroke-linejoin:round;color:#000000;stroke:url(#linearGradient2271);stroke-linecap:round;stroke-width:2.2945;fill:none"
+        d="m20.825 31.261s-7.323 6.617-8.914 10.86"
+    />
+  </g
+  >
+  <metadata
+    >
+    <rdf:RDF
+      >
+      <cc:Work
+        >
+        <dc:format
+          >image/svg+xml</dc:format
+        >
+        <dc:type
+            rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+        />
+        <cc:license
+            rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+        />
+        <dc:publisher
+          >
+          <cc:Agent
+              rdf:about="http://openclipart.org/"
+            >
+            <dc:title
+              >Openclipart</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:publisher
+        >
+        <dc:title
+          >tango preferences system</dc:title
+        >
+        <dc:date
+          >2010-03-29T09:07:18</dc:date
+        >
+        <dc:description
+          >"System preferences" icon from <a href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </a> 
\n<br><br>
\nSince version 0.8.90 Tango Project icons are Public Domain: <a href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </a></dc:description
+        >
+        <dc:source
+          >https://openclipart.org/detail/35431/tango-preferences-system-by-warszawianka</dc:source
+        >
+        <dc:creator
+          >
+          <cc:Agent
+            >
+            <dc:title
+              >warszawianka</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:creator
+        >
+        <dc:subject
+          >
+          <rdf:Bag
+            >
+            <rdf:li
+              >externalsource</rdf:li
+            >
+            <rdf:li
+              >icon</rdf:li
+            >
+            <rdf:li
+              >preferences</rdf:li
+            >
+            <rdf:li
+              >screwdriver</rdf:li
+            >
+            <rdf:li
+              >settings</rdf:li
+            >
+            <rdf:li
+              >spanner</rdf:li
+            >
+            <rdf:li
+              >tango</rdf:li
+            >
+            <rdf:li
+              >tool</rdf:li
+            >
+          </rdf:Bag
+          >
+        </dc:subject
+        >
+      </cc:Work
+      >
+      <cc:License
+          rdf:about="http://creativecommons.org/licenses/publicdomain/"
+        >
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Reproduction"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Distribution"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+        />
+      </cc:License
+      >
+    </rdf:RDF
+    >
+  </metadata
+  >
+</svg
+>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/Quit.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/Quit.svg
new file mode 100644
index 0000000..31f4376
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/Quit.svg
@@ -0,0 +1,374 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg11300"
+   sodipodi:docname="system-log-out.svg"
+   sodipodi:modified="true"
+   inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+   viewBox="0 0 48 48"
+   sodipodi:version="0.32"
+   inkscape:export-xdpi="90.000000"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-ydpi="90.000000"
+   inkscape:version="0.48.4 r9939"
+   version="1.1"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient9864"
+       y2="27.759"
+       gradientUnits="userSpaceOnUse"
+       y1="19.804"
+       gradientTransform="translate(-12.021)"
+       x2="18.031"
+       x1="46.846"
+       inkscape:collect="always">
+      <stop
+         id="stop9856"
+         style="stop-color:#4e4e4e"
+         offset="0" />
+      <stop
+         id="stop9858"
+         style="stop-color:#ababab"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       id="radialGradient9876"
+       cx="27.884"
+       gradientUnits="userSpaceOnUse"
+       cy="7.1396"
+       r="9.7227"
+       gradientTransform="matrix(2.5658 0 0 1.4033 -49.804 -9.4833)"
+       inkscape:collect="always">
+      <stop
+         id="stop9870"
+         style="stop-color:#4e4e4e"
+         offset="0" />
+      <stop
+         id="stop9872"
+         style="stop-color:#616161;stop-opacity:0"
+         offset="1" />
+    </radialGradient>
+    <linearGradient
+       id="linearGradient9886"
+       y2="24.765"
+       gradientUnits="userSpaceOnUse"
+       y1="19.108"
+       gradientTransform="translate(-13.137)"
+       x2="34.007"
+       x1="31.853"
+       inkscape:collect="always">
+      <stop
+         id="stop9882"
+         style="stop-color:#525252"
+         offset="0" />
+      <stop
+         id="stop9884"
+         style="stop-color:#525252;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient9902"
+       y2="18.064"
+       gradientUnits="userSpaceOnUse"
+       y1="21.511"
+       gradientTransform="translate(-12.021)"
+       x2="33.711"
+       x1="31.079"
+       inkscape:collect="always">
+      <stop
+         id="stop9898"
+         style="stop-color:#cecece"
+         offset="0" />
+      <stop
+         id="stop9900"
+         style="stop-color:#9e9e9e"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient6371"
+       y2="43.25"
+       gradientUnits="userSpaceOnUse"
+       x2="40.25"
+       gradientTransform="translate(-12.021)"
+       y1="31.625"
+       x1="40.25"
+       inkscape:collect="always">
+      <stop
+         id="stop6367"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop6369"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <filter
+       id="filter6421"
+       height="1.2083"
+       width="1.2831"
+       y="-.10415"
+       x="-.14154"
+       inkscape:collect="always">
+      <feGaussianBlur
+         id="feGaussianBlur6423"
+         stdDeviation="2.07"
+         inkscape:collect="always" />
+    </filter>
+    <filter
+       id="filter6451"
+       height="1.2391"
+       width="1.1336"
+       y="-.11953"
+       x="-.066813"
+       inkscape:collect="always">
+      <feGaussianBlur
+         id="feGaussianBlur6453"
+         stdDeviation="0.76879489"
+         inkscape:collect="always" />
+    </filter>
+    <radialGradient
+       id="radialGradient6461"
+       gradientUnits="userSpaceOnUse"
+       cy="36.421"
+       cx="24.837"
+       gradientTransform="matrix(1 0 0 .53672 0 16.873)"
+       r="15.645"
+       inkscape:collect="always">
+      <stop
+         id="stop8664"
+         style="stop-color:#000000"
+         offset="0" />
+      <stop
+         id="stop8666"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </radialGradient>
+    <radialGradient
+       id="radialGradient6463"
+       gradientUnits="userSpaceOnUse"
+       cy="2.8969"
+       cx="19.701"
+       gradientTransform="matrix(1.2534 0 0 .9539 -15.479 11.277)"
+       r="17.171"
+       inkscape:collect="always">
+      <stop
+         id="stop8652"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop8654"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </radialGradient>
+    <linearGradient
+       id="linearGradient6465"
+       y2="43.45"
+       gradientUnits="userSpaceOnUse"
+       x2="19.756"
+       gradientTransform="matrix(.96872 0 0 .96892 .36168 .73782)"
+       y1="13.663"
+       x1="8.7601"
+       inkscape:collect="always">
+      <stop
+         id="stop9890"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop9892"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient6473"
+       y2="29.068"
+       gradientUnits="userSpaceOnUse"
+       x2="18.729"
+       y1="44"
+       x1="18.729"
+       inkscape:collect="always">
+      <stop
+         id="stop6469"
+         style="stop-color:#babdb6"
+         offset="0" />
+      <stop
+         id="stop6471"
+         style="stop-color:#babdb6;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="16"
+     pagecolor="#ffffff"
+     inkscape:showpageshadow="false"
+     inkscape:grid-bbox="true"
+     inkscape:zoom="1"
+     inkscape:cx="-103.37653"
+     inkscape:window-height="851"
+     showgrid="false"
+     borderopacity="0.25490196"
+     inkscape:current-layer="layer1"
+     stroke="#a40000"
+     inkscape:cy="5.4914491"
+     inkscape:window-x="0"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0"
+     inkscape:document-units="px"
+     fill="#727e0a"
+     inkscape:window-maximized="0" />
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <rect
+       id="rect9828"
+       style="fill-rule:evenodd;color:#000000;stroke:#555753;stroke-miterlimit:10;fill:#eeeeec"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       rx=".70711"
+       ry=".70710"
+       height="41.942"
+       width="31.996"
+       y="2.5692"
+       x="1.4809" />
+    <rect
+       id="rect9840"
+       style="fill-rule:evenodd;color:#000000;fill:url(#linearGradient6473)"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       height="26.759"
+       width="31"
+       y="17.241"
+       x="1.9792" />
+    <path
+       id="path6425"
+       sodipodi:nodetypes="cczcc"
+       style="opacity:.55429;filter:url(#filter6451);fill-rule:evenodd;fill:#000000"
+       d="m2.1042 43.875l21.375-8.875s3.514-2.22 0.25-3.5c-3.415-1.34-7 0.5-7 0.5l-14.625 11.875z" />
+    <path
+       id="path9852"
+       sodipodi:nodetypes="ccccc"
+       style="fill-rule:evenodd;color:#000000;fill:url(#linearGradient9864)"
+       d="m2.0168 43.945l-0.0388-40.89 19.942 0.0437 0.045 29.919-19.948 10.927z" />
+    <path
+       id="path1360"
+       style="opacity:.42222;color:#000000;display:block;fill:#ffffff"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       sodipodi:nodetypes="cccccc"
+       d="m1.949 43.945l20.148-10.883-18.562 8.928 0.0005-38.98-1.5704 0.0003-0.0161 40.935z" />
+    <path
+       id="path9866"
+       style="fill-rule:evenodd;color:#000000;fill:url(#radialGradient9876)"
+       inkscape:r_cy="true"
+       inkscape:r_cx="true"
+       sodipodi:nodetypes="ccccc"
+       d="m2.024 43.757l-0.0448-40.702 19.941-0.0005-0.179 30.626-19.717 10.077z" />
+    <path
+       id="path9878"
+       sodipodi:nodetypes="cccsscc"
+       style="fill-rule:evenodd;color:#000000;fill:url(#linearGradient9886)"
+       d="m17.622 18.456l1.923 2.453-1.459 4.817s0.265 1.503 1.039 0.486c0.773-1.016 2.972-3.582 2.585-5.458-0.287-1.392-1.083-2.055-1.083-2.055l-3.005-0.243z" />
+    <path
+       id="path9862"
+       sodipodi:nodetypes="csccscs"
+       style="fill-rule:evenodd;color:#000000;fill:url(#linearGradient9902)"
+       d="m19.456 17.351s2.164 1.002 2.232 1.879c0.102 1.301-4.243 5.435-4.243 5.435-0.508 0.619-1.347 0.067-0.883-0.53 0 0 3.466-4.118 3.248-4.441-0.274-0.406-1.967-1.039-1.967-1.039-1.016-0.751 0.268-2.305 1.613-1.304z" />
+    <path
+       id="path6355"
+       style="opacity:.87429;filter:url(#filter6421);fill-rule:evenodd;fill:url(#linearGradient6371)"
+       d="m22.229 3.5l-0.5 29.75-18 9.75 29.25 0.25-0.25-39.75h-10.5z" />
+    <g
+       id="g6455"
+       transform="matrix(-1 0 0 1 48.201 -.047335)">
+      <path
+         id="path8660"
+         sodipodi:rx="15.644737"
+         sodipodi:ry="8.3968935"
+         style="opacity:.29947;fill-rule:evenodd;color:#000000;fill:url(#radialGradient6461)"
+         sodipodi:type="arc"
+         d="m 40.481863,36.421127 c 0,4.637477 -7.004387,8.396894 -15.644737,8.396894 -8.64035,0 -15.6447375,-3.759417 -15.6447375,-8.396894 0,-4.637476 7.0043875,-8.396893 15.6447375,-8.396893 8.64035,0 15.644737,3.759417 15.644737,8.396893 z"
+         transform="matrix(.77849 0 0 .77849 -7.5798 1.5981)"
+         sodipodi:cy="36.421127"
+         sodipodi:cx="24.837126" />
+      <path
+         id="path8643"
+         sodipodi:nodetypes="cccccccc"
+         style="stroke-linejoin:round;fill-rule:evenodd;color:#000000;stroke:#a40000;stroke-linecap:round;stroke-miterlimit:10;fill:#cc0000"
+         d="m1.7318 17.594v12.761h7.9323v5.821l12.224-12.223-12.297-12.297 0.0003 5.941-7.8595-0.003z" />
+      <path
+         id="path8645"
+         sodipodi:nodetypes="cccccc"
+         style="opacity:.50802;fill-rule:evenodd;color:#000000;fill:url(#radialGradient6463)"
+         d="m9.924 12.478v5.638h-7.8494v6.415c10.258-3.827 9.8804 3.243 19.219-0.585l-11.37-11.468z" />
+      <path
+         id="path8658"
+         sodipodi:nodetypes="cccccccc"
+         style="opacity:.48128;color:#000000;stroke:url(#linearGradient6465);stroke-miterlimit:10;fill:none"
+         d="m2.6834 18.566v10.79h7.9016v4.125l9.543-9.539-9.606-9.945v4.572l-7.8386-0.003z" />
+    </g>
+  </g>
+  <metadata
+     id="metadata51">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2010-03-26T15:33:56</dc:date>
+        <dc:description>"Log out" icon from <a href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </a> 
\n<br><br>
\nSince version 0.8.90 Tango Project icons are Public Domain: <a href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </a></dc:description>
+        <dc:source>https://openclipart.org/detail/34279/tango-system-log-out-by-warszawianka</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>warszawianka</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>arrow</rdf:li>
+            <rdf:li>door</rdf:li>
+            <rdf:li>exit</rdf:li>
+            <rdf:li>externalsource</rdf:li>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>logout</rdf:li>
+            <rdf:li>open</rdf:li>
+            <rdf:li>quit</rdf:li>
+            <rdf:li>red</rdf:li>
+            <rdf:li>tango</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/Redo.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/Redo.svg
new file mode 100644
index 0000000..23f0209
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/Redo.svg
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="90.000000"
+   inkscape:export-xdpi="90.000000"
+   inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-icon-theme/22x22/actions/edit-undo.png"
+   width="48"
+   height="48"
+   id="svg11300"
+   sodipodi:version="0.32"
+   inkscape:version="0.45"
+   sodipodi:docbase="/home/dobey/Projects/gnome-icon-theme/scalable/actions"
+   sodipodi:docname="edit-redo.svg"
+   version="1.0"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient1913">
+      <stop
+         style="stop-color:#73d216;stop-opacity:1"
+         offset="0"
+         id="stop1915" />
+      <stop
+         style="stop-color:#8ae234;stop-opacity:1"
+         offset="1"
+         id="stop1917" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5891">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop5893" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop5895" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5132">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop5134" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop5136" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8662">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop8664" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop8666" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8662"
+       id="radialGradient8668"
+       cx="24.837126"
+       cy="36.421127"
+       fx="24.837126"
+       fy="36.421127"
+       r="15.644737"
+       gradientTransform="matrix(1,0,0,0.536723,0,16.87306)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5132"
+       id="linearGradient5138"
+       x1="21.55229"
+       y1="29.205048"
+       x2="18.072493"
+       y2="55.692348"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5891"
+       id="linearGradient5897"
+       x1="15.456784"
+       y1="8.734375"
+       x2="25.561066"
+       y2="13.526372"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1.4306351,0,0,1.4301566,50.645952,2.3547655)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient1913"
+       id="linearGradient1919"
+       x1="13.1875"
+       y1="35.9375"
+       x2="17.9375"
+       y2="38.875"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#c4a000"
+     fill="#edd400"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666"
+     borderopacity="1"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="42.402351"
+     inkscape:cy="4.5251669"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="1072"
+     inkscape:window-height="970"
+     inkscape:window-x="488"
+     inkscape:window-y="21"
+     width="48px"
+     height="48px"
+     showborder="false" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+        <dc:title>Edit Undo</dc:title>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>edit</rdf:li>
+            <rdf:li>undo</rdf:li>
+            <rdf:li>revert</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>Andreas Nilsson
+Lapo Calamandrei</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/SourceCode" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <path
+       transform="matrix(1.47967,0,0,-0.872353,-13.55145,72.5668)"
+       d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1  9.1923885,36.421127 A 15.644737 8.3968935 0 1 1  40.481863 36.421127 z"
+       sodipodi:ry="8.3968935"
+       sodipodi:rx="15.644737"
+       sodipodi:cy="36.421127"
+       sodipodi:cx="24.837126"
+       id="path8660"
+       style="opacity:0.13;color:black;fill:url(#radialGradient8668);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+       sodipodi:type="arc" />
+    <path
+       style="opacity:1;color:#000000;fill:url(#linearGradient1919);fill-opacity:1.0;fill-rule:nonzero;stroke:#4e9a06;stroke-width:0.99999887;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible"
+       d="M 17.424821,41.893434 C 0.283744,32.442251 9.935604,12.409146 26.422371,12.56649 L 26.422371,4.4999994 L 42.5,18.558177 L 26.422371,33.301549 C 26.422371,33.301549 26.422371,24.572517 26.422371,24.572517 C 16.187754,24.157353 11.680698,31.839537 20.650045,37.935965 C 23.217139,39.680812 21.438823,44.106661 17.424821,41.893434 z "
+       id="path1432"
+       sodipodi:nodetypes="ccccccss" />
+    <path
+       style="opacity:0.61797755;color:black;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient5138);stroke-width:0.99999893;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:block;overflow:visible"
+       d="M 27.4375,6.6875 L 27.4375,12.5625 C 27.429067,13.111254 26.986254,13.554067 26.4375,13.5625 C 18.60766,13.487775 12.455124,18.243926 10.28125,24 C 8.1073762,29.756074 9.7034903,36.491213 17.9375,41.03125 C 18.787678,41.500018 19.403324,41.546979 19.8125,41.46875 C 20.221676,41.390521 20.480107,41.171685 20.65625,40.875 C 21.008536,40.281629 20.95643,39.367611 20.09375,38.78125 C 17.736506,37.179041 16.184817,35.430234 15.40625,33.625 C 14.627683,31.819766 14.666426,29.952664 1 [...]
+       id="path4247" />
+    <path
+       style="opacity:0.45;fill:url(#linearGradient5897);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 41.660227,18.605336 C 23.110128,15.475328 12.765166,20.754837 8.865084,29.04107 C 8.711319,16.398198 21.828491,12.721185 26.954933,13.108518 L 26.939308,5.6020321 L 41.660227,18.605336 z "
+       id="path4920"
+       sodipodi:nodetypes="ccccc" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/Save-as.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/Save-as.svg
new file mode 100644
index 0000000..e6a993b
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/Save-as.svg
@@ -0,0 +1,737 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:ns1="http://sozi.baierouge.fr"
+    id="svg2913"
+    viewBox="0 0 48 48"
+    sodipodi:version="0.32"
+    inkscape:output_extension="org.inkscape.output.svg.inkscape"
+    inkscape:version="0.46"
+    sodipodi:docname="document-save-as.svg"
+    sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
+  >
+  <defs
+      id="defs3"
+    >
+    <radialGradient
+        id="radialGradient5031"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(-2.7744 0 0 1.9697 112.76 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5060"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5062"
+          style="stop-color:black"
+          offset="0"
+      />
+      <stop
+          id="stop5064"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient5029"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1891.6 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5027"
+        y2="609.51"
+        gradientUnits="userSpaceOnUse"
+        x2="302.86"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1892.2 -872.89)"
+        y1="366.65"
+        x1="302.86"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5050"
+          style="stop-color:black;stop-opacity:0"
+          offset="0"
+      />
+      <stop
+          id="stop5056"
+          style="stop-color:black"
+          offset=".5"
+      />
+      <stop
+          id="stop5052"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient4997"
+        gradientUnits="userSpaceOnUse"
+        cy="6.4577"
+        cx="23.447"
+        gradientTransform="matrix(-1.3145 -.010063 -.010230 1.3362 46.221 -4.9099)"
+        r="19.062"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4993"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop4995"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient1764"
+        y2="12.584"
+        gradientUnits="userSpaceOnUse"
+        x2="12.624"
+        gradientTransform="matrix(.91411 1.4128e-16 -1.4128e-16 .91411 -3.8687 -2.7069)"
+        y1="27.394"
+        x1="33.06"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop2189"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop2191"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient8668"
+        gradientUnits="userSpaceOnUse"
+        cy="36.421"
+        cx="24.837"
+        gradientTransform="matrix(1 -7.8165e-32 -1.1324e-32 .53672 -5.898e-14 16.873)"
+        r="15.645"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop8664"
+          style="stop-color:#000000"
+          offset="0"
+      />
+      <stop
+          id="stop8666"
+          style="stop-color:#000000;stop-opacity:0"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient4209"
+        y2="35.281"
+        gradientUnits="userSpaceOnUse"
+        y1="35.281"
+        gradientTransform="translate(.79549 3.7992)"
+        x2="24.688"
+        x1="7.0625"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4186"
+          style="stop-color:#838383"
+          offset="0"
+      />
+      <stop
+          id="stop4188"
+          style="stop-color:#bbbbbb;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient4234"
+        y2="40.944"
+        gradientUnits="userSpaceOnUse"
+        y1="28.481"
+        gradientTransform="translate(0 5.125)"
+        x2="36.183"
+        x1="7.6046"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4230"
+          style="stop-color:#bbbbbb"
+          offset="0"
+      />
+      <stop
+          id="stop4232"
+          style="stop-color:#9f9f9f"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient4242"
+        y2="33.759"
+        gradientUnits="userSpaceOnUse"
+        y1="37.206"
+        gradientTransform="translate(0 5.125)"
+        x2="12.222"
+        x1="12.277"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4238"
+          style="stop-color:#eeeeee"
+          offset="0"
+      />
+      <stop
+          id="stop4240"
+          style="stop-color:#eeeeee;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient4250"
+        cx="15.571"
+        gradientUnits="userSpaceOnUse"
+        cy="2.9585"
+        r="20.936"
+        gradientTransform="matrix(1.2862 .78170 -.71078 1.1696 -2.3543 .24814)"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4246"
+          style="stop-color:#e4e4e4"
+          offset="0"
+      />
+      <stop
+          id="stop4248"
+          style="stop-color:#d3d3d3"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient4260"
+        y2="47.621"
+        gradientUnits="userSpaceOnUse"
+        y1="4.4331"
+        gradientTransform="translate(0 5.125)"
+        x2="44.096"
+        x1="12.378"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4256"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop4258"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient4272"
+        y2="26.357"
+        gradientUnits="userSpaceOnUse"
+        y1="11.319"
+        gradientTransform="translate(0 5.125)"
+        x2="23.688"
+        x1="23.688"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4276"
+          style="stop-color:#ffffff;stop-opacity:.25490"
+          offset="0"
+      />
+      <stop
+          id="stop4278"
+          style="stop-color:#ffffff"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient2553"
+        y2="11.781"
+        gradientUnits="userSpaceOnUse"
+        x2="21.748"
+        y1="31.965"
+        x1="33.431"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop2557"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop2561"
+          style="stop-color:#e6e6e6"
+          offset=".5"
+      />
+      <stop
+          id="stop2563"
+          style="stop-color:#ffffff"
+          offset=".75"
+      />
+      <stop
+          id="stop2565"
+          style="stop-color:#e1e1e1"
+          offset=".84167"
+      />
+      <stop
+          id="stop2559"
+          style="stop-color:#ffffff"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient6907"
+        y2="16.743"
+        gradientUnits="userSpaceOnUse"
+        x2="8.8953"
+        y1="15.868"
+        x1="14.752"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop6903"
+          style="stop-color:#3465a4"
+          offset="0"
+      />
+      <stop
+          id="stop6905"
+          style="stop-color:#3465a4;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient6931"
+        y2="21.118"
+        gradientUnits="userSpaceOnUse"
+        x2="7"
+        y1="18.25"
+        x1="12.25"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop6927"
+          style="stop-color:#204a87"
+          offset="0"
+      />
+      <stop
+          id="stop6929"
+          style="stop-color:#204a87;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient6971"
+        y2="36.437"
+        gradientUnits="userSpaceOnUse"
+        x2="28.061"
+        y1="31.431"
+        x1="28.061"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop6967"
+          style="stop-color:#dddddd"
+          offset="0"
+      />
+      <stop
+          id="stop6969"
+          style="stop-color:#fdfdfd"
+          offset="1"
+      />
+    </linearGradient
+    >
+  </defs
+  >
+  <sodipodi:namedview
+      id="base"
+      bordercolor="#666666"
+      inkscape:window-x="0"
+      inkscape:window-y="30"
+      pagecolor="#ffffff"
+      inkscape:showpageshadow="false"
+      inkscape:grid-bbox="true"
+      inkscape:zoom="2.8284271"
+      inkscape:pageshadow="2"
+      stroke="#204a87"
+      showgrid="false"
+      borderopacity="0.22745098"
+      inkscape:current-layer="layer2"
+      inkscape:cx="-21.21754"
+      inkscape:cy="15.12998"
+      inkscape:window-width="999"
+      inkscape:pageopacity="0.0"
+      inkscape:window-height="818"
+      inkscape:document-units="px"
+      fill="#3465a4"
+  />
+  <g
+      id="layer2"
+      inkscape:label="pix"
+      inkscape:groupmode="layer"
+    >
+    <g
+        id="g5022"
+        transform="matrix(.024114 0 0 .019292 45.49 41.752)"
+      >
+      <rect
+          id="rect4173"
+          style="opacity:.40206;color:black;fill:url(#linearGradient5027)"
+          height="478.36"
+          width="1339.6"
+          y="-150.7"
+          x="-1559.3"
+      />
+      <path
+          id="path5058"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5029)"
+          d="m-219.62-150.68v478.33c142.88 0.9 345.4-107.17 345.4-239.2 0-132.02-159.44-239.13-345.4-239.13z"
+      />
+      <path
+          id="path5018"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5031)"
+          d="m-1559.3-150.68v478.33c-142.8 0.9-345.4-107.17-345.4-239.2 0-132.02 159.5-239.13 345.4-239.13z"
+      />
+    </g
+    >
+    <path
+        id="path4196"
+        sodipodi:nodetypes="cccsccccccccc"
+        style="stroke-linejoin:round;stroke:#535353;stroke-linecap:round;stroke-width:2;fill:none"
+        d="m11.286 13.088c-0.625 0-1.032 0.29-1.282 0.843l-6.4683 17.104s-0.25 0.671-0.25 1.781v9.65c0 1.083 0.6578 1.625 1.6562 1.625h38.562c0.985 0 1.594-0.718 1.594-1.844v-9.65s0.106-0.77-0.094-1.312l-6.718-17.197c-0.185-0.512-0.637-0.988-1.125-1h-25.875z"
+    />
+    <path
+        id="path4170"
+        sodipodi:nodetypes="ccccccccc"
+        style="fill-rule:evenodd;fill:url(#linearGradient4234)"
+        d="m3.2736 32.122l0.7646-0.692 37.61 0.062 3.462 0.317v10.439c0 1.125-0.607 1.843-1.592 1.843h-38.583c-0.998 0-1.6614-0.542-1.6614-1.624v-10.345z"
+    />
+    <path
+        id="path3093"
+        sodipodi:nodetypes="csccccccs"
+        style="fill-rule:evenodd;fill:url(#radialGradient4250)"
+        d="m3.5491 31.039c-0.7143 1.465-0.0006 2.393 1.0357 2.393h39c1.119-0.024 1.845-1.012 1.428-2.143l-6.714-17.21c-0.184-0.512-0.655-0.988-1.143-1h-25.857c-0.625 0-1.036 0.303-1.286 0.857l-6.4639 17.103z"
+    />
+    <rect
+        id="rect4174"
+        style="fill-rule:evenodd;color:#000000;fill:url(#linearGradient4209)"
+        height="5.5625"
+        width="17.625"
+        y="36.299"
+        x="7.858"
+    />
+    <path
+        id="path4194"
+        sodipodi:nodetypes="cscc"
+        style="opacity:.81143;fill-rule:evenodd;fill:url(#linearGradient4242)"
+        d="m7.858 41.862v-4.012c1.8355 3.179 8.296 4.012 12.937 4.012h-12.937z"
+    />
+    <path
+        id="path4201"
+        sodipodi:nodetypes="cccccccc"
+        style="fill-rule:evenodd;fill:#ffffff"
+        d="m44.796 30.754c0.064 1.25-0.414 2.316-1.322 2.343h-38.119c-1.2889 0-1.8674-0.325-2.0837-0.868 0.0917 0.945 0.8258 1.65 2.084 1.65h38.119c1.076-0.033 1.753-1.424 1.352-2.995l-0.03-0.13z"
+    />
+    <path
+        id="path4211"
+        style="opacity:.69143;fill-rule:evenodd;color:#000000;fill:url(#linearGradient4272)"
+        d="m10.969 15.281c-0.046 0.201-0.188 0.387-0.188 0.594 0 0.949 0.591 1.789 1.344 2.594 0.24-0.154 0.365-0.355 0.625-0.5-0.94-0.816-1.553-1.717-1.781-2.688zm26.656 0c-0.229 0.97-0.842 1.873-1.781 2.688 0.274 0.153 0.404 0.368 0.656 0.531 0.757-0.807 1.312-1.673 1.312-2.625 0-0.207-0.141-0.393-0.187-0.594zm2.187 8.438c-0.613 4.04-7.298 7.25-15.531 7.25-8.212 0-14.86-3.193-15.5-7.219-0.0321 0.197-0.1248 0.392-0.1248 0.594 0.0001 4.318 6.9888 7.844 15.625 7.844 8.636 0 15.656-3.526 1 [...]
+    />
+    <path
+        id="path4224"
+        sodipodi:rx="1.3700194"
+        sodipodi:ry="1.016466"
+        style="fill-rule:evenodd;color:#000000;fill-opacity:.45763;fill:#ffffff"
+        sodipodi:type="arc"
+        d="m8.5737 25.594a1.37 1.0165 0 1 1 -2.7401 0 1.37 1.0165 0 1 1 2.7401 0z"
+        transform="translate(.088388 5.3018)"
+        sodipodi:cy="25.593554"
+        sodipodi:cx="7.2036505"
+    />
+    <path
+        id="path4226"
+        sodipodi:rx="1.3700194"
+        sodipodi:ry="1.016466"
+        style="fill-rule:evenodd;color:#000000;fill-opacity:.45763;fill:#ffffff"
+        sodipodi:type="arc"
+        d="m8.5737 25.594a1.37 1.0165 0 1 1 -2.7401 0 1.37 1.0165 0 1 1 2.7401 0z"
+        transform="translate(33.967 5.2134)"
+        sodipodi:cy="25.593554"
+        sodipodi:cx="7.2036505"
+    />
+    <path
+        id="path4252"
+        sodipodi:nodetypes="cccsccccccccc"
+        style="stroke-linejoin:round;stroke:url(#linearGradient4260);stroke-linecap:round;fill:none"
+        d="m11.643 13.541c-0.602 0-0.993 0.279-1.234 0.812l-6.415 16.591s-0.2406 0.646-0.2406 1.715v9.29c0 1.354 0.444 1.627 1.5944 1.627h37.687c1.323 0 1.534-0.317 1.534-1.838v-9.29s0.102-0.742-0.09-1.264l-6.593-16.806c-0.178-0.492-0.551-0.826-1.021-0.837h-25.222z"
+    />
+    <path
+        id="path4282"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m40.5 36.554v5.021"
+    />
+    <path
+        id="path4284"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m38.5 36.614v5.021"
+    />
+    <path
+        id="path4286"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m36.5 36.614v5.021"
+    />
+    <path
+        id="path4288"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m34.5 36.614v5.021"
+    />
+    <path
+        id="path4290"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m32.5 36.614v5.021"
+    />
+    <path
+        id="path4292"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m30.5 36.614v5.021"
+    />
+    <path
+        id="path4294"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m39.5 36.604v5.021"
+    />
+    <path
+        id="path4296"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m37.5 36.664v5.021"
+    />
+    <path
+        id="path4298"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m35.5 36.664v5.021"
+    />
+    <path
+        id="path4300"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m33.5 36.664v5.021"
+    />
+    <path
+        id="path4302"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m31.5 36.664v5.021"
+    />
+    <path
+        id="path4572"
+        style="opacity:0.44;fill-rule:evenodd;fill:#ffffff"
+        d="m7.875 36.312v5.532h12.563l-12.219-0.344-0.344-5.188z"
+    />
+    <path
+        id="path2545"
+        sodipodi:rx="14.875"
+        sodipodi:ry="6.6875"
+        style="opacity:.20571;fill-rule:evenodd;color:#000000;fill:url(#linearGradient2553)"
+        sodipodi:type="arc"
+        d="m39.875 19.562a14.875 6.6875 0 1 1 -29.75 0 14.875 6.6875 0 1 1 29.75 0z"
+        transform="matrix(1.0378 0 0 1.0607 -1.6329 3.0304)"
+        sodipodi:cy="19.5625"
+        sodipodi:cx="25"
+    />
+  </g
+  >
+  <g
+      id="layer1"
+      inkscape:label="down"
+      inkscape:groupmode="layer"
+    >
+    <path
+        id="path8660"
+        sodipodi:rx="15.644737"
+        sodipodi:ry="8.3968935"
+        style="opacity:.14118;fill-rule:evenodd;color:#000000;fill:url(#radialGradient8668)"
+        sodipodi:type="arc"
+        d="m40.482 36.421a15.645 8.3969 0 1 1 -31.29 0 15.645 8.3969 0 1 1 31.29 0z"
+        transform="matrix(1.1302 1.1782e-16 7.9185e-17 -.75960 -3.9097 53.666)"
+        sodipodi:cy="36.421127"
+        sodipodi:cx="24.837126"
+    />
+    <path
+        id="path1432"
+        sodipodi:nodetypes="ccccccc"
+        style="color:#000000;display:block;stroke:url(#linearGradient6931);fill:url(#linearGradient6907)"
+        d="m3.2035 25.835c-1.0306-31.22 25.538-26.286 25.378-10.046h7.313l-11.377 12.986-11.933-12.986h7.542c0.457-10.97-16.718-14.179-16.924 10.046z"
+    />
+    <path
+        id="path2177"
+        sodipodi:nodetypes="ccccccc"
+        style="opacity:.47159;color:#000000;display:block;stroke:url(#linearGradient1764);stroke-miterlimit:10;fill:none"
+        d="m7.6642 9.1041c4.7418-9.1441 20.458-6.3866 20.098 7.4749h6.317l-9.566 10.958-10.096-10.958h6.456c0.272-11.575-9.951-11.044-13.209-7.4749z"
+    />
+    <path
+        id="path4989"
+        sodipodi:nodetypes="cccccccc"
+        style="opacity:.49432;color:#000000;fill:url(#radialGradient4997)"
+        d="m34.767 16.212l-1.984 2.545c-5.41-1.516-7.886 2.73-15.674 1.732l-3.861-4.409 7.186 0.083c0.049-11.846-12.09-11.164-15.405-2.535 3.8082-14.889 22.864-12.822 23.254 2.486l6.484 0.098z"
+    />
+    <rect
+        id="rect6951"
+        style="color:#000000;display:block;stroke:#7d7d7d;stroke-linecap:round;fill:url(#linearGradient6971)"
+        rx="1.625"
+        ry="1.625"
+        height="12.278"
+        width="39.248"
+        y="30.298"
+        x="4.5635"
+    />
+    <rect
+        id="rect6953"
+        style="opacity:.59659;color:#000000;display:block;fill:#7d7d7d"
+        ry="0"
+        height="7"
+        width="16"
+        y="33"
+        x="7"
+    />
+    <rect
+        id="rect6957"
+        style="color:#000000;display:block;fill:#000000"
+        height="9"
+        width="1"
+        y="32"
+        x="24"
+    />
+  </g
+  >
+  <metadata
+    >
+    <rdf:RDF
+      >
+      <cc:Work
+        >
+        <dc:format
+          >image/svg+xml</dc:format
+        >
+        <dc:type
+            rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+        />
+        <cc:license
+            rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+        />
+        <dc:publisher
+          >
+          <cc:Agent
+              rdf:about="http://openclipart.org/"
+            >
+            <dc:title
+              >Openclipart</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:publisher
+        >
+        <dc:title
+          >tango document save as</dc:title
+        >
+        <dc:date
+          >2010-03-18T16:18:26</dc:date
+        >
+        <dc:description
+          >"Save as" icon from <A href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </A> 
\n<BR><BR>
\nSince version 0.8.90 Tango Project icons are Public Domain: <A href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </A></dc:description
+        >
+        <dc:source
+          >https://openclipart.org/detail/32251/tango-document-save-as-by-warszawianka</dc:source
+        >
+        <dc:creator
+          >
+          <cc:Agent
+            >
+            <dc:title
+              >warszawianka</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:creator
+        >
+        <dc:subject
+          >
+          <rdf:Bag
+            >
+            <rdf:li
+              >document</rdf:li
+            >
+            <rdf:li
+              >hard disk</rdf:li
+            >
+            <rdf:li
+              >icon</rdf:li
+            >
+            <rdf:li
+              >save</rdf:li
+            >
+            <rdf:li
+              >tango</rdf:li
+            >
+          </rdf:Bag
+          >
+        </dc:subject
+        >
+      </cc:Work
+      >
+      <cc:License
+          rdf:about="http://creativecommons.org/licenses/publicdomain/"
+        >
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Reproduction"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Distribution"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+        />
+      </cc:License
+      >
+    </rdf:RDF
+    >
+  </metadata
+  >
+</svg
+>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/Save.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/Save.svg
new file mode 100644
index 0000000..4a6dcfa
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/Save.svg
@@ -0,0 +1,695 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:cc="http://creativecommons.org/ns#"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:ns1="http://sozi.baierouge.fr"
+    id="svg2913"
+    viewBox="0 0 48 48"
+    sodipodi:version="0.32"
+    inkscape:output_extension="org.inkscape.output.svg.inkscape"
+    inkscape:version="0.46"
+    sodipodi:docname="document-save.svg"
+    sodipodi:docbase="/home/jimmac/src/cvs/tango-icon-theme/scalable/actions"
+  >
+  <defs
+      id="defs3"
+    >
+    <radialGradient
+        id="radialGradient5031"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(-2.7744 0 0 1.9697 112.76 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5060"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5062"
+          style="stop-color:black"
+          offset="0"
+      />
+      <stop
+          id="stop5064"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient5029"
+        xlink:href="#linearGradient5060"
+        gradientUnits="userSpaceOnUse"
+        cy="486.65"
+        cx="605.71"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1891.6 -872.89)"
+        r="117.14"
+        inkscape:collect="always"
+    />
+    <linearGradient
+        id="linearGradient5027"
+        y2="609.51"
+        gradientUnits="userSpaceOnUse"
+        x2="302.86"
+        gradientTransform="matrix(2.7744 0 0 1.9697 -1892.2 -872.89)"
+        y1="366.65"
+        x1="302.86"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5050"
+          style="stop-color:black;stop-opacity:0"
+          offset="0"
+      />
+      <stop
+          id="stop5056"
+          style="stop-color:black"
+          offset=".5"
+      />
+      <stop
+          id="stop5052"
+          style="stop-color:black;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient4997"
+        gradientUnits="userSpaceOnUse"
+        cy="6.4577"
+        cx="23.447"
+        gradientTransform="matrix(-1.3145 -.010063 -.010230 1.3362 46.221 -4.9099)"
+        r="19.062"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4993"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop4995"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient1764"
+        y2="12.584"
+        gradientUnits="userSpaceOnUse"
+        x2="12.624"
+        gradientTransform="matrix(.91411 1.4128e-16 -1.4128e-16 .91411 -3.8687 -2.7069)"
+        y1="27.394"
+        x1="33.06"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop2189"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop2191"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient8668"
+        gradientUnits="userSpaceOnUse"
+        cy="36.421"
+        cx="24.837"
+        gradientTransform="matrix(1 -7.8165e-32 -1.1324e-32 .53672 -5.898e-14 16.873)"
+        r="15.645"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop8664"
+          style="stop-color:#000000"
+          offset="0"
+      />
+      <stop
+          id="stop8666"
+          style="stop-color:#000000;stop-opacity:0"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient4209"
+        y2="35.281"
+        gradientUnits="userSpaceOnUse"
+        y1="35.281"
+        gradientTransform="translate(.79549 3.7992)"
+        x2="24.688"
+        x1="7.0625"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4186"
+          style="stop-color:#838383"
+          offset="0"
+      />
+      <stop
+          id="stop4188"
+          style="stop-color:#bbbbbb;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient4234"
+        y2="40.944"
+        gradientUnits="userSpaceOnUse"
+        y1="28.481"
+        gradientTransform="translate(0 5.125)"
+        x2="36.183"
+        x1="7.6046"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4230"
+          style="stop-color:#bbbbbb"
+          offset="0"
+      />
+      <stop
+          id="stop4232"
+          style="stop-color:#9f9f9f"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient4242"
+        y2="33.759"
+        gradientUnits="userSpaceOnUse"
+        y1="37.206"
+        gradientTransform="translate(0 5.125)"
+        x2="12.222"
+        x1="12.277"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4238"
+          style="stop-color:#eeeeee"
+          offset="0"
+      />
+      <stop
+          id="stop4240"
+          style="stop-color:#eeeeee;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <radialGradient
+        id="radialGradient4250"
+        cx="15.571"
+        gradientUnits="userSpaceOnUse"
+        cy="2.9585"
+        r="20.936"
+        gradientTransform="matrix(1.2862 .78170 -.71078 1.1696 -2.3543 .24814)"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4246"
+          style="stop-color:#e4e4e4"
+          offset="0"
+      />
+      <stop
+          id="stop4248"
+          style="stop-color:#d3d3d3"
+          offset="1"
+      />
+    </radialGradient
+    >
+    <linearGradient
+        id="linearGradient4260"
+        y2="47.621"
+        gradientUnits="userSpaceOnUse"
+        y1="4.4331"
+        gradientTransform="translate(0 5.125)"
+        x2="44.096"
+        x1="12.378"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4256"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop4258"
+          style="stop-color:#ffffff;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient4272"
+        y2="26.357"
+        gradientUnits="userSpaceOnUse"
+        y1="11.319"
+        gradientTransform="translate(0 5.125)"
+        x2="23.688"
+        x1="23.688"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop4276"
+          style="stop-color:#ffffff;stop-opacity:.25490"
+          offset="0"
+      />
+      <stop
+          id="stop4278"
+          style="stop-color:#ffffff"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient2553"
+        y2="11.781"
+        gradientUnits="userSpaceOnUse"
+        x2="21.748"
+        y1="31.965"
+        x1="33.431"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop2557"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop2561"
+          style="stop-color:#e6e6e6"
+          offset=".5"
+      />
+      <stop
+          id="stop2563"
+          style="stop-color:#ffffff"
+          offset=".75"
+      />
+      <stop
+          id="stop2565"
+          style="stop-color:#e1e1e1"
+          offset=".84167"
+      />
+      <stop
+          id="stop2559"
+          style="stop-color:#ffffff"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient6907"
+        y2="16.743"
+        gradientUnits="userSpaceOnUse"
+        x2="8.8953"
+        y1="15.868"
+        x1="14.752"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop6903"
+          style="stop-color:#3465a4"
+          offset="0"
+      />
+      <stop
+          id="stop6905"
+          style="stop-color:#3465a4;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient6931"
+        y2="21.118"
+        gradientUnits="userSpaceOnUse"
+        x2="7"
+        y1="18.25"
+        x1="12.25"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop6927"
+          style="stop-color:#204a87"
+          offset="0"
+      />
+      <stop
+          id="stop6929"
+          style="stop-color:#204a87;stop-opacity:0"
+          offset="1"
+      />
+    </linearGradient
+    >
+  </defs
+  >
+  <sodipodi:namedview
+      id="base"
+      bordercolor="#666666"
+      inkscape:window-x="0"
+      inkscape:window-y="30"
+      pagecolor="#ffffff"
+      inkscape:showpageshadow="false"
+      inkscape:grid-bbox="true"
+      inkscape:zoom="1"
+      inkscape:pageshadow="2"
+      stroke="#204a87"
+      showgrid="false"
+      borderopacity="0.22745098"
+      inkscape:current-layer="layer2"
+      inkscape:cx="-133.68151"
+      inkscape:cy="11.891468"
+      inkscape:window-width="999"
+      inkscape:pageopacity="0.0"
+      inkscape:window-height="818"
+      inkscape:document-units="px"
+      fill="#3465a4"
+  />
+  <g
+      id="layer2"
+      inkscape:label="pix"
+      inkscape:groupmode="layer"
+    >
+    <g
+        id="g5022"
+        transform="matrix(.024114 0 0 .019292 45.49 41.752)"
+      >
+      <rect
+          id="rect4173"
+          style="opacity:.40206;color:black;fill:url(#linearGradient5027)"
+          height="478.36"
+          width="1339.6"
+          y="-150.7"
+          x="-1559.3"
+      />
+      <path
+          id="path5058"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5029)"
+          d="m-219.62-150.68v478.33c142.88 0.9 345.4-107.17 345.4-239.2 0-132.02-159.44-239.13-345.4-239.13z"
+      />
+      <path
+          id="path5018"
+          sodipodi:nodetypes="cccc"
+          style="opacity:.40206;color:black;fill:url(#radialGradient5031)"
+          d="m-1559.3-150.68v478.33c-142.8 0.9-345.4-107.17-345.4-239.2 0-132.02 159.5-239.13 345.4-239.13z"
+      />
+    </g
+    >
+    <path
+        id="path4196"
+        sodipodi:nodetypes="cccsccccccccc"
+        style="stroke-linejoin:round;stroke:#535353;stroke-linecap:round;stroke-width:2;fill:none"
+        d="m11.286 13.088c-0.625 0-1.032 0.29-1.282 0.843l-6.4683 17.104s-0.25 0.671-0.25 1.781v9.65c0 1.083 0.6578 1.625 1.6562 1.625h38.562c0.985 0 1.594-0.718 1.594-1.844v-9.65s0.106-0.77-0.094-1.312l-6.718-17.197c-0.185-0.512-0.637-0.988-1.125-1h-25.875z"
+    />
+    <path
+        id="path4170"
+        sodipodi:nodetypes="ccccccccc"
+        style="fill-rule:evenodd;fill:url(#linearGradient4234)"
+        d="m3.2736 32.122l0.7646-0.692 37.61 0.062 3.462 0.317v10.439c0 1.125-0.607 1.843-1.592 1.843h-38.583c-0.998 0-1.6614-0.542-1.6614-1.624v-10.345z"
+    />
+    <path
+        id="path3093"
+        sodipodi:nodetypes="csccccccs"
+        style="fill-rule:evenodd;fill:url(#radialGradient4250)"
+        d="m3.5491 31.039c-0.7143 1.465-0.0006 2.393 1.0357 2.393h39c1.119-0.024 1.845-1.012 1.428-2.143l-6.714-17.21c-0.184-0.512-0.655-0.988-1.143-1h-25.857c-0.625 0-1.036 0.303-1.286 0.857l-6.4639 17.103z"
+    />
+    <rect
+        id="rect4174"
+        style="fill-rule:evenodd;color:#000000;fill:url(#linearGradient4209)"
+        height="5.5625"
+        width="17.625"
+        y="36.299"
+        x="7.858"
+    />
+    <path
+        id="path4194"
+        sodipodi:nodetypes="cscc"
+        style="opacity:.81143;fill-rule:evenodd;fill:url(#linearGradient4242)"
+        d="m7.858 41.862v-4.012c1.8355 3.179 8.296 4.012 12.937 4.012h-12.937z"
+    />
+    <path
+        id="path4201"
+        sodipodi:nodetypes="cccccccc"
+        style="fill-rule:evenodd;fill:#ffffff"
+        d="m44.796 30.754c0.064 1.25-0.414 2.316-1.322 2.343h-38.119c-1.2889 0-1.8674-0.325-2.0837-0.868 0.0917 0.945 0.8258 1.65 2.084 1.65h38.119c1.076-0.033 1.753-1.424 1.352-2.995l-0.03-0.13z"
+    />
+    <path
+        id="path4211"
+        style="opacity:.69143;fill-rule:evenodd;color:#000000;fill:url(#linearGradient4272)"
+        d="m10.969 15.281c-0.046 0.201-0.188 0.387-0.188 0.594 0 0.949 0.591 1.789 1.344 2.594 0.24-0.154 0.365-0.355 0.625-0.5-0.94-0.816-1.553-1.717-1.781-2.688zm26.656 0c-0.229 0.97-0.842 1.873-1.781 2.688 0.274 0.153 0.404 0.368 0.656 0.531 0.757-0.807 1.312-1.673 1.312-2.625 0-0.207-0.141-0.393-0.187-0.594zm2.187 8.438c-0.613 4.04-7.298 7.25-15.531 7.25-8.212 0-14.86-3.193-15.5-7.219-0.0321 0.197-0.1248 0.392-0.1248 0.594 0.0001 4.318 6.9888 7.844 15.625 7.844 8.636 0 15.656-3.526 1 [...]
+    />
+    <path
+        id="path4224"
+        sodipodi:rx="1.3700194"
+        sodipodi:ry="1.016466"
+        style="fill-rule:evenodd;color:#000000;fill-opacity:.45763;fill:#ffffff"
+        sodipodi:type="arc"
+        d="m8.5737 25.594a1.37 1.0165 0 1 1 -2.7401 0 1.37 1.0165 0 1 1 2.7401 0z"
+        transform="translate(.088388 5.3018)"
+        sodipodi:cy="25.593554"
+        sodipodi:cx="7.2036505"
+    />
+    <path
+        id="path4226"
+        sodipodi:rx="1.3700194"
+        sodipodi:ry="1.016466"
+        style="fill-rule:evenodd;color:#000000;fill-opacity:.45763;fill:#ffffff"
+        sodipodi:type="arc"
+        d="m8.5737 25.594a1.37 1.0165 0 1 1 -2.7401 0 1.37 1.0165 0 1 1 2.7401 0z"
+        transform="translate(33.967 5.2134)"
+        sodipodi:cy="25.593554"
+        sodipodi:cx="7.2036505"
+    />
+    <path
+        id="path4252"
+        sodipodi:nodetypes="cccsccccccccc"
+        style="stroke-linejoin:round;stroke:url(#linearGradient4260);stroke-linecap:round;fill:none"
+        d="m11.643 13.541c-0.602 0-0.993 0.279-1.234 0.812l-6.415 16.591s-0.2406 0.646-0.2406 1.715v9.29c0 1.354 0.444 1.627 1.5944 1.627h37.687c1.323 0 1.534-0.317 1.534-1.838v-9.29s0.102-0.742-0.09-1.264l-6.593-16.806c-0.178-0.492-0.551-0.826-1.021-0.837h-25.222z"
+    />
+    <path
+        id="path4282"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m40.5 36.554v5.021"
+    />
+    <path
+        id="path4284"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m38.5 36.614v5.021"
+    />
+    <path
+        id="path4286"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m36.5 36.614v5.021"
+    />
+    <path
+        id="path4288"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m34.5 36.614v5.021"
+    />
+    <path
+        id="path4290"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m32.5 36.614v5.021"
+    />
+    <path
+        id="path4292"
+        style="stroke-opacity:.42373;stroke:#ffffff;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m30.5 36.614v5.021"
+    />
+    <path
+        id="path4294"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m39.5 36.604v5.021"
+    />
+    <path
+        id="path4296"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m37.5 36.664v5.021"
+    />
+    <path
+        id="path4298"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m35.5 36.664v5.021"
+    />
+    <path
+        id="path4300"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m33.5 36.664v5.021"
+    />
+    <path
+        id="path4302"
+        style="opacity:.097143;stroke:#000000;stroke-linecap:square;stroke-width:1px;fill:none"
+        d="m31.5 36.664v5.021"
+    />
+    <path
+        id="path4572"
+        style="opacity:0.44;fill-rule:evenodd;fill:#ffffff"
+        d="m7.875 36.312v5.532h12.563l-12.219-0.344-0.344-5.188z"
+    />
+    <path
+        id="path2545"
+        sodipodi:rx="14.875"
+        sodipodi:ry="6.6875"
+        style="opacity:.20571;fill-rule:evenodd;color:#000000;fill:url(#linearGradient2553)"
+        sodipodi:type="arc"
+        d="m39.875 19.562a14.875 6.6875 0 1 1 -29.75 0 14.875 6.6875 0 1 1 29.75 0z"
+        transform="matrix(1.0378 0 0 1.0607 -1.6329 3.0304)"
+        sodipodi:cy="19.5625"
+        sodipodi:cx="25"
+    />
+  </g
+  >
+  <g
+      id="layer1"
+      inkscape:label="down"
+      inkscape:groupmode="layer"
+    >
+    <path
+        id="path8660"
+        sodipodi:rx="15.644737"
+        sodipodi:ry="8.3968935"
+        style="opacity:.14118;fill-rule:evenodd;color:#000000;fill:url(#radialGradient8668)"
+        sodipodi:type="arc"
+        d="m40.482 36.421a15.645 8.3969 0 1 1 -31.29 0 15.645 8.3969 0 1 1 31.29 0z"
+        transform="matrix(1.1302 1.1782e-16 7.9185e-17 -.75960 -3.9097 53.666)"
+        sodipodi:cy="36.421127"
+        sodipodi:cx="24.837126"
+    />
+    <path
+        id="path1432"
+        sodipodi:nodetypes="ccccccc"
+        style="color:#000000;display:block;stroke:url(#linearGradient6931);fill:url(#linearGradient6907)"
+        d="m3.2035 25.835c-1.0306-31.22 25.538-26.286 25.378-10.046h7.313l-11.377 12.986-11.933-12.986h7.542c0.457-10.97-16.718-14.179-16.924 10.046z"
+    />
+    <path
+        id="path2177"
+        sodipodi:nodetypes="ccccccc"
+        style="opacity:.47159;color:#000000;display:block;stroke:url(#linearGradient1764);stroke-miterlimit:10;fill:none"
+        d="m7.6642 9.1041c4.7418-9.1441 20.458-6.3866 20.098 7.4749h6.317l-9.566 10.958-10.096-10.958h6.456c0.272-11.575-9.951-11.044-13.209-7.4749z"
+    />
+    <path
+        id="path4989"
+        sodipodi:nodetypes="cccccccc"
+        style="opacity:.49432;color:#000000;fill:url(#radialGradient4997)"
+        d="m34.767 16.212l-1.984 2.545c-5.41-1.516-7.886 2.73-15.674 1.732l-3.861-4.409 7.186 0.083c0.049-11.846-12.09-11.164-15.405-2.535 3.8082-14.889 22.864-12.822 23.254 2.486l6.484 0.098z"
+    />
+  </g
+  >
+  <metadata
+    >
+    <rdf:RDF
+      >
+      <cc:Work
+        >
+        <dc:format
+          >image/svg+xml</dc:format
+        >
+        <dc:type
+            rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+        />
+        <cc:license
+            rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+        />
+        <dc:publisher
+          >
+          <cc:Agent
+              rdf:about="http://openclipart.org/"
+            >
+            <dc:title
+              >Openclipart</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:publisher
+        >
+        <dc:title
+          >tango documnet save</dc:title
+        >
+        <dc:date
+          >2010-03-18T16:16:36</dc:date
+        >
+        <dc:description
+          >"Save document" icon from <A href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </A> 
\n<BR><BR>
\nSince version 0.8.90 Tango Project icons are Public Domain: <A href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </A></dc:description
+        >
+        <dc:source
+          >https://openclipart.org/detail/32245/tango-documnet-save-by-warszawianka</dc:source
+        >
+        <dc:creator
+          >
+          <cc:Agent
+            >
+            <dc:title
+              >warszawianka</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:creator
+        >
+        <dc:subject
+          >
+          <rdf:Bag
+            >
+            <rdf:li
+              >arrow</rdf:li
+            >
+            <rdf:li
+              >document</rdf:li
+            >
+            <rdf:li
+              >externalsource</rdf:li
+            >
+            <rdf:li
+              >hard disk</rdf:li
+            >
+            <rdf:li
+              >icon</rdf:li
+            >
+            <rdf:li
+              >save</rdf:li
+            >
+            <rdf:li
+              >tango</rdf:li
+            >
+          </rdf:Bag
+          >
+        </dc:subject
+        >
+      </cc:Work
+      >
+      <cc:License
+          rdf:about="http://creativecommons.org/licenses/publicdomain/"
+        >
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Reproduction"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Distribution"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+        />
+      </cc:License
+      >
+    </rdf:RDF
+    >
+  </metadata
+  >
+</svg
+>
diff --git a/SRC/OpenMeca/Rsc/Img/MainWindow/Undo.svg b/SRC/OpenMeca/Rsc/Img/MainWindow/Undo.svg
new file mode 100644
index 0000000..310be02
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/MainWindow/Undo.svg
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://web.resource.org/cc/"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:export-ydpi="90.000000"
+   inkscape:export-xdpi="90.000000"
+   inkscape:export-filename="/home/jimmac/src/cvs/gnome/gnome-icon-theme/22x22/actions/edit-undo.png"
+   width="48"
+   height="48"
+   id="svg11300"
+   sodipodi:version="0.32"
+   inkscape:version="0.45"
+   sodipodi:docbase="/home/dobey/Projects/gnome-icon-theme/scalable/actions"
+   sodipodi:docname="edit-undo.svg"
+   version="1.0"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient2790">
+      <stop
+         id="stop2792"
+         offset="0"
+         style="stop-color:#edd400;stop-opacity:1" />
+      <stop
+         id="stop2794"
+         offset="1"
+         style="stop-color:#fce94f;stop-opacity:1" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5891">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop5893" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:0;"
+         offset="1"
+         id="stop5895" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient5132">
+      <stop
+         style="stop-color:white;stop-opacity:1;"
+         offset="0"
+         id="stop5134" />
+      <stop
+         style="stop-color:white;stop-opacity:0;"
+         offset="1"
+         id="stop5136" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient8662">
+      <stop
+         style="stop-color:#000000;stop-opacity:1;"
+         offset="0"
+         id="stop8664" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0;"
+         offset="1"
+         id="stop8666" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient8662"
+       id="radialGradient2782"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.536723,0,16.87306)"
+       cx="24.837126"
+       cy="36.421127"
+       fx="24.837126"
+       fy="36.421127"
+       r="15.644737" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2790"
+       id="linearGradient2784"
+       gradientUnits="userSpaceOnUse"
+       x1="25.445534"
+       y1="20.6875"
+       x2="25.445534"
+       y2="16.375" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5132"
+       id="linearGradient2786"
+       gradientUnits="userSpaceOnUse"
+       x1="21.67729"
+       y1="29.705048"
+       x2="18.072493"
+       y2="55.692348" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5891"
+       id="linearGradient2788"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-1.430635,0,0,1.430157,50.64595,2.354766)"
+       x1="15.456784"
+       y1="8.734375"
+       x2="25.561066"
+       y2="13.526372" />
+  </defs>
+  <sodipodi:namedview
+     stroke="#c4a000"
+     fill="#edd400"
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666"
+     borderopacity="1"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="-22.084221"
+     inkscape:cy="24.35648"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:grid-bbox="false"
+     inkscape:document-units="px"
+     inkscape:showpageshadow="false"
+     inkscape:window-width="1072"
+     inkscape:window-height="970"
+     inkscape:window-x="488"
+     inkscape:window-y="21"
+     width="48px"
+     height="48px"
+     showborder="false" />
+  <metadata
+     id="metadata4">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Jakub Steiner</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:source>http://jimmac.musichall.cz</dc:source>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
+        <dc:title>Edit Undo</dc:title>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>edit</rdf:li>
+            <rdf:li>undo</rdf:li>
+            <rdf:li>revert</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>Andreas Nilsson
+Lapo Calamandrei</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Reproduction" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/Distribution" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/Notice" />
+        <cc:permits
+           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/ShareAlike" />
+        <cc:requires
+           rdf:resource="http://web.resource.org/cc/SourceCode" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer">
+    <g
+       id="g2776"
+       transform="matrix(-1,0,0,1,45.9611,0)">
+      <path
+         sodipodi:type="arc"
+         style="opacity:0.12999998;color:black;fill:url(#radialGradient2782);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+         id="path8660"
+         sodipodi:cx="24.837126"
+         sodipodi:cy="36.421127"
+         sodipodi:rx="15.644737"
+         sodipodi:ry="8.3968935"
+         d="M 40.481863 36.421127 A 15.644737 8.3968935 0 1 1  9.1923885,36.421127 A 15.644737 8.3968935 0 1 1  40.481863 36.421127 z"
+         transform="matrix(1.47967,0,0,-0.872353,-13.55145,72.5668)" />
+      <path
+         sodipodi:nodetypes="ccccccss"
+         id="path1432"
+         d="M 17.424821,41.893434 C 0.283744,32.442251 9.935604,12.409146 26.422371,12.56649 L 26.422371,4.4999994 L 42.5,18.558177 L 26.422371,33.301549 C 26.422371,33.301549 26.422371,24.572517 26.422371,24.572517 C 16.187754,24.157353 11.680698,31.839537 20.650045,37.935965 C 23.217139,39.680812 21.438823,44.106661 17.424821,41.893434 z "
+         style="opacity:1;color:black;fill:url(#linearGradient2784);fill-opacity:1;fill-rule:nonzero;stroke:#c4a000;stroke-width:0.99999887;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+      <path
+         id="path4247"
+         d="M 27.4375,6.6875 L 27.4375,12.5625 C 27.429067,13.111254 26.986254,13.554067 26.4375,13.5625 C 18.60766,13.487775 12.455124,18.243926 10.28125,24 C 8.1073762,29.756074 9.7034903,36.491213 17.9375,41.03125 C 18.787678,41.500018 19.403324,41.546979 19.8125,41.46875 C 20.221676,41.390521 20.480107,41.171685 20.65625,40.875 C 21.008536,40.281629 20.95643,39.367611 20.09375,38.78125 C 17.736506,37.179041 16.184817,35.430234 15.40625,33.625 C 14.627683,31.819766 14.666426,29.952664 [...]
+         style="opacity:0.61797755;color:black;fill:none;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient2786);stroke-width:0.99999893;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:block;overflow:visible" />
+      <path
+         sodipodi:nodetypes="ccccc"
+         id="path4920"
+         d="M 41.660227,18.605336 C 23.110128,15.475328 12.765166,20.754837 8.865084,29.04107 C 8.711319,16.398198 21.828491,12.721185 26.954933,13.108518 L 26.939308,5.6020321 L 41.660227,18.605336 z "
+         style="opacity:0.45;fill:url(#linearGradient2788);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    </g>
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Mini-Logo.svg b/SRC/OpenMeca/Rsc/Img/Mini-Logo.svg
new file mode 100644
index 0000000..ad026b1
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Mini-Logo.svg
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   sodipodi:docname="Mini-Logo.svg"
+   viewBox="0 0 128 128"
+   sodipodi:version="0.32"
+   version="1.0"
+   inkscape:version="0.91 r13725"
+   width="128"
+   height="128"
+   inkscape:export-filename="/home/dada/work/dev/openmeca/SRC/OpenMeca/Rsc/Img/OpenMeca.png"
+   inkscape:export-xdpi="33.75"
+   inkscape:export-ydpi="33.75">
+  <defs
+     id="defs15" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="24"
+     pagecolor="#ffffff"
+     inkscape:window-height="824"
+     width="650px"
+     inkscape:zoom="2.4100556"
+     inkscape:window-x="0"
+     showgrid="false"
+     borderopacity="1.0"
+     inkscape:current-layer="svg2"
+     inkscape:cx="124.31402"
+     inkscape:cy="79.586022"
+     inkscape:window-width="1600"
+     height="650px"
+     inkscape:pageopacity="0.0"
+     inkscape:document-units="px"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-maximized="1">
+    <inkscape:grid
+       id="GridFromPre046Settings"
+       type="xygrid"
+       originx="0.65310699"
+       originy="0.65340852"
+       spacingx="1px"
+       spacingy="1px"
+       color="#3f3fff"
+       empcolor="#3f3fff"
+       opacity="0.15"
+       empopacity="0.38"
+       empspacing="5" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata13">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/publicdomain/zero/1.0/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:date>2006-10-10T11:21:25</dc:date>
+        <dc:description>Set of gears from 10 to 80 teeth</dc:description>
+        <dc:source>https://openclipart.org/detail/487/gears-by-technoargia</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>technoargia</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>gears</rdf:li>
+            <rdf:li>pignon</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/publicdomain/zero/1.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g4177"
+     transform="matrix(1.6271485,0,0,1.6271485,-79.976429,-0.39775282)">
+    <path
+       sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
+       id="gear50"
+       style="fill:#ffffbd;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 127.01241,63.928236 -2.66096,0.177459 -0.5925,-0.996138 -1.21259,-0.513604 -1.27337,-0.452822 -1.2369,-0.346455 -1.07888,-0.209696 -0.41939,-0.09421 -0.0517,-0.92084 -0.0638,-0.914762 0.40723,-0.148915 1.03937,-0.343416 1.18524,-0.498408 1.20347,-0.607816 1.14269,-0.665557 -0.22185,-1.765704 -1.27337,-0.358611 -1.31592,-0.288712 -1.27338,-0.191462 -1.09406,-0.0699 -0.42851,-0.04255 -0.16411,-0.905645 -0.17931,-0.902606 0.38293,-0.194501 0.99073,-0.474096 1.11535,-0.641245 1.1 [...]
+       inkscape:connector-curvature="0" />
+    <path
+       id="gear20"
+       style="fill:#f1a875;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 85.850093,13.509902 -0.401158,0.771925 -0.352533,0.817512 -0.261361,0.802316 -0.154993,0.708105 -0.05166,0.492331 0.003,0.176266 0.136758,1.480031 -1.267295,0.161071 -1.255138,0.237048 -0.328221,-1.44964 -0.05166,-0.167149 -0.200579,-0.452823 -0.36165,-0.62301 -0.498409,-0.686832 -0.586542,-0.668597 -0.619971,-0.607815 -1.519539,0.49233 -0.145875,0.860059 -0.07902,0.881332 -0.003,0.847903 0.07294,0.720261 0.103328,0.483213 0.05774,0.167149 0.58958,1.364546 -1.157888,0.543995  [...]
+       inkscape:connector-curvature="0" />
+    <path
+       id="gear10"
+       style="fill:#50c67b;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m 56.348608,52.524904 -1.057933,0.80462 0.02322,0.751528 0.126049,0.714028 0.193319,0.694787 0.227891,0.567928 0.236495,0.372834 0.115351,0.115299 1.556245,1.486394 -0.784006,0.94391 -0.635021,1.044789 -1.921335,-0.986575 -0.170116,-0.05859 -0.408461,-0.09121 -0.590094,-0.06907 -0.739988,0.05782 -0.748622,0.137591 -0.691906,0.192359 -0.40817,1.273464 0.463353,0.601512 0.513306,0.511164 0.568071,0.454448 0.556509,0.304531 0.396946,0.171942 0.123022,0.03265 2.184507,0.296489 -0.0 [...]
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/OpenMeca.icns b/SRC/OpenMeca/Rsc/Img/OpenMeca.icns
new file mode 100644
index 0000000..75ed8df
Binary files /dev/null and b/SRC/OpenMeca/Rsc/Img/OpenMeca.icns differ
diff --git a/SRC/OpenMeca/Rsc/Img/OpenMeca.png b/SRC/OpenMeca/Rsc/Img/OpenMeca.png
new file mode 100644
index 0000000..03b6706
Binary files /dev/null and b/SRC/OpenMeca/Rsc/Img/OpenMeca.png differ
diff --git a/SRC/OpenMeca/Rsc/Img/OpenMeca_1024.png b/SRC/OpenMeca/Rsc/Img/OpenMeca_1024.png
new file mode 100644
index 0000000..5eb1320
Binary files /dev/null and b/SRC/OpenMeca/Rsc/Img/OpenMeca_1024.png differ
diff --git a/SRC/OpenMeca/Rsc/Img/Part/Junction.svg b/SRC/OpenMeca/Rsc/Img/Part/Junction.svg
new file mode 100644
index 0000000..eb264de
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Part/Junction.svg
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Junction.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="835"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="11.8"
+     inkscape:cx="8.7009256"
+     inkscape:cy="19.161039"
+     inkscape:window-x="0"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 20 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="40 : 20 : 1"
+       inkscape:persp3d-origin="20 : 13.333333 : 1"
+       id="perspective3048" />
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028-4"
+     d="M 15.434252,24.457883 A 8.7203691,8.5974301 44.95372 0 1 3.3931958,36.732926 8.7203691,8.5974301 44.95372 1 1 15.434252,24.457883 z" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2.00002392;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+     id="rect5177"
+     width="9.0003977"
+     height="9.6252031"
+     x="-3.9164386"
+     y="23.370237"
+     transform="matrix(0.72800376,-0.68557314,0.69059165,0.72324489,0,0)" />
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028-4-8"
+     d="M 36.615747,3.4578136 A 8.7203691,8.5974301 44.95372 0 1 24.574691,15.732857 8.7203691,8.5974301 44.95372 1 1 36.615747,3.4578136 z" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Part/Pipe.svg b/SRC/OpenMeca/Rsc/Img/Part/Pipe.svg
new file mode 100644
index 0000000..430491e
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Part/Pipe.svg
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Pipe.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="819"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="5.9"
+     inkscape:cx="-41.845569"
+     inkscape:cy="10.821665"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 20 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="40 : 20 : 1"
+       inkscape:persp3d-origin="20 : 13.333333 : 1"
+       id="perspective3048" />
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028-4"
+     d="M 15.434252,24.457883 A 8.7203691,8.5974301 44.95372 0 1 3.3931958,36.732926 8.7203691,8.5974301 44.95372 1 1 15.434252,24.457883 z" />
+  <rect
+     style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2.00000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+     id="rect5177"
+     width="19.524855"
+     height="9.1721458"
+     x="-3.9356005"
+     y="23.95746"
+     transform="matrix(0.71814623,-0.69589222,0.69589222,0.71814623,0,0)" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Part/Point.svg b/SRC/OpenMeca/Rsc/Img/Part/Point.svg
new file mode 100644
index 0000000..8788905
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Part/Point.svg
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="40"
+   height="40"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Point.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="803"
+     id="namedview6409"
+     showgrid="true"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="4.17193"
+     inkscape:cx="-56.9953"
+     inkscape:cy="27.299021"
+     inkscape:window-x="0"
+     inkscape:window-y="64"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="path3028-4"
+     d="m 28.855757,20.045716 a 8.8956604,8.8956604 0 0 1 -17.791317,0 8.8956604,8.8956604 0 1 1 17.791317,0 z" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Player/Play.svg b/SRC/OpenMeca/Rsc/Img/Player/Play.svg
new file mode 100644
index 0000000..1b8b1a5
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Player/Play.svg
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2046"
+   sodipodi:docname="Stop.svg"
+   viewBox="0 0 159.61 159.61"
+   sodipodi:version="0.32"
+   version="1.0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs2048">
+    <linearGradient
+       id="linearGradient2109"
+       y2="553.74"
+       gradientUnits="userSpaceOnUse"
+       x2="380.68"
+       gradientTransform="matrix(0.31227,0,0,0.32049,127.55,434.38)"
+       y1="296.37"
+       x1="264.58">
+      <stop
+         id="stop5192"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop5194"
+         style="stop-color:#52ba00;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2109"
+       id="linearGradient5621"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.281043,0,0,0.288441,285.235,359.829)"
+       x1="264.58"
+       y1="296.37"
+       x2="380.68"
+       y2="553.74" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2109"
+       id="linearGradient5624"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.271467,0.0727398,-0.0746541,-0.278613,533.014,625.986)"
+       x1="249.48"
+       y1="262.87"
+       x2="272.03"
+       y2="427.54001" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     guidetolerance="10"
+     pagecolor="#ffffff"
+     gridtolerance="10000"
+     inkscape:window-height="803"
+     inkscape:zoom="1.979899"
+     objecttolerance="10"
+     borderopacity="1.0"
+     inkscape:current-layer="layer1"
+     inkscape:cx="53.19949"
+     inkscape:cy="80.248024"
+     inkscape:window-y="32"
+     inkscape:window-x="0"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0"
+     inkscape:document-units="px"
+     showgrid="false"
+     inkscape:window-maximized="0" />
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(-311.62 -429.7)">
+    <path
+       sodipodi:cx="384.28571"
+       sodipodi:cy="559.50507"
+       transform="matrix(0.276174,0,0,0.276174,285.298,354.987)"
+       d="m 634.28571,559.50507 a 250,250 0 1 1 -500,0 250,250 0 1 1 500,0 z"
+       sodipodi:type="arc"
+       style="fill:#6fa600;fill-rule:evenodd;stroke:#887d00;stroke-width:20.12800026000000031;fill-opacity:1;stroke-opacity:1"
+       sodipodi:ry="250"
+       sodipodi:rx="250"
+       id="path2174" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m 408.211,570.924 c 17.145,-4.59 30.753,-15.894 38.907,-30.438 13.239,-31.338 -36.153,42.03 -76.941,28.701 11.853,4.347 25.029,5.22 38.034,1.737 z"
+       style="fill:url(#linearGradient5624);fill-rule:evenodd;fill-opacity:1.0"
+       sodipodi:nodetypes="cccc"
+       id="path2540" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m 391.534,445.311 c -35.496,0 -64.296,29.565 -64.296,65.988 0,4.932 0.54,9.729 1.539,14.346 35.289,-67.923 73.305,-25.164 122.319,-39.195 -9.576,-24.12 -32.634,-41.139 -59.562,-41.139 z"
+       style="fill:url(#linearGradient5621);fill-rule:evenodd"
+       sodipodi:nodetypes="ccccc"
+       id="path2197" />
+    <path
+       style="fill:#ffffff;fill-opacity:1;stroke:#dfd6dd;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+       d="m 370.19143,472.88144 0,73.57142 57.14285,-36.07144 z"
+       id="path5819"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccc" />
+  </g>
+  <metadata
+     id="metadata5108">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2006-09-07T17:35:55</dc:date>
+        <dc:description>a red round error or warning icon</dc:description>
+        <dc:source>https://openclipart.org/detail/109/red-round-error-warning-icon-by-molumen</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>molumen</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>button</rdf:li>
+            <rdf:li>cancel</rdf:li>
+            <rdf:li>delete</rdf:li>
+            <rdf:li>error</rdf:li>
+            <rdf:li>glossy</rdf:li>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>negative</rdf:li>
+            <rdf:li>red</rdf:li>
+            <rdf:li>round</rdf:li>
+            <rdf:li>stop</rdf:li>
+            <rdf:li>warning</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Player/Record.svg b/SRC/OpenMeca/Rsc/Img/Player/Record.svg
new file mode 100644
index 0000000..e03a321
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Player/Record.svg
@@ -0,0 +1,501 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg1307"
+   sodipodi:docname="media-record.svg"
+   inkscape:export-filename="/home/lapo/Desktop/Grafica/Icone/media-actions-outlines.png"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   inkscape:export-xdpi="90"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-ydpi="90"
+   inkscape:version="0.48.4 r9939"
+   version="1.1"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs1309">
+    <linearGradient
+       id="linearGradient2257">
+      <stop
+         id="stop2259"
+         style="stop-color:#ef2929"
+         offset="0" />
+      <stop
+         id="stop2261"
+         style="stop-color:#cc0000"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       id="radialGradient2228"
+       gradientUnits="userSpaceOnUse"
+       cy="36.421001"
+       cx="24.837"
+       gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
+       r="15.645"
+       inkscape:collect="always">
+      <stop
+         id="stop8664"
+         style="stop-color:#000000"
+         offset="0" />
+      <stop
+         id="stop8666"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </radialGradient>
+    <radialGradient
+       id="radialGradient1368"
+       gradientUnits="userSpaceOnUse"
+       cy="-3.2183001"
+       cx="21.929001"
+       gradientTransform="matrix(3.6588,0,0,2.0808,-62.416,12.762)"
+       r="13"
+       inkscape:collect="always">
+      <stop
+         id="stop3342"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop3344"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </radialGradient>
+    <radialGradient
+       id="radialGradient2263"
+       xlink:href="#linearGradient2257"
+       gradientUnits="userSpaceOnUse"
+       cy="28.115999"
+       cx="22.5"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       r="14.538"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3843"
+       y2="35.546001"
+       gradientUnits="userSpaceOnUse"
+       x2="21.816"
+       y1="8.9115"
+       x1="21.702"
+       inkscape:collect="always">
+      <stop
+         id="stop3839"
+         style="stop-color:#000000"
+         offset="0" />
+      <stop
+         id="stop3841"
+         style="stop-color:#ffffff;stop-opacity:.78351"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3020"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3029"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3843"
+       id="linearGradient3031"
+       gradientUnits="userSpaceOnUse"
+       x1="21.702"
+       y1="8.9115"
+       x2="21.816"
+       y2="35.546001" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient2228"
+       id="radialGradient3033"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
+       cx="24.837"
+       cy="36.421001"
+       r="15.645" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3035"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient1368"
+       id="radialGradient3037"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.6588,0,0,2.0808,-62.416,12.762)"
+       cx="21.929001"
+       cy="-3.2183001"
+       r="13" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3047"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3843"
+       id="linearGradient3049"
+       gradientUnits="userSpaceOnUse"
+       x1="21.702"
+       y1="8.9115"
+       x2="21.816"
+       y2="35.546001" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient2228"
+       id="radialGradient3051"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
+       cx="24.837"
+       cy="36.421001"
+       r="15.645" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3053"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient1368"
+       id="radialGradient3055"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.6588,0,0,2.0808,-62.416,12.762)"
+       cx="21.929001"
+       cy="-3.2183001"
+       r="13" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3063"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3843"
+       id="linearGradient3065"
+       gradientUnits="userSpaceOnUse"
+       x1="21.702"
+       y1="8.9115"
+       x2="21.816"
+       y2="35.546001" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient2228"
+       id="radialGradient3067"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,0.53672,0,16.873)"
+       cx="24.837"
+       cy="36.421001"
+       r="15.645" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3069"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient1368"
+       id="radialGradient3071"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.6588,0,0,2.0808,-62.416,12.762)"
+       cx="21.929001"
+       cy="-3.2183001"
+       r="13" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient1368"
+       id="radialGradient3074"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.6588,0,0,2.0808,-66.481864,19.060097)"
+       cx="21.929001"
+       cy="-3.2183001"
+       r="13" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3086"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3843"
+       id="linearGradient3088"
+       gradientUnits="userSpaceOnUse"
+       x1="21.702"
+       y1="8.9115"
+       x2="21.816"
+       y2="35.546001" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2257"
+       id="radialGradient3090"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(2.3656,0,0,2.2028,-30.725,-34.24)"
+       cx="22.5"
+       cy="28.115999"
+       r="14.538" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#radialGradient1368"
+       id="radialGradient3092"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(3.6588,0,0,2.0808,-66.481864,19.060097)"
+       cx="21.929001"
+       cy="-3.2183001"
+       r="13" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     inkscape:showpageshadow="false"
+     inkscape:zoom="5.6568542"
+     borderopacity="0.11372549"
+     inkscape:current-layer="layer1"
+     stroke="#ef2929"
+     guidetolerance="1px"
+     fill="#ef2929"
+     inkscape:grid-points="true"
+     inkscape:grid-bbox="true"
+     showgrid="false"
+     showguides="false"
+     bordercolor="#666666"
+     inkscape:window-x="0"
+     inkscape:guide-bbox="true"
+     inkscape:window-y="48"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     pagecolor="#ffffff"
+     inkscape:cx="-6.2961543"
+     inkscape:cy="14.760392"
+     inkscape:document-units="px"
+     inkscape:window-height="803"
+     showborder="true"
+     inkscape:window-maximized="0">
+    <sodipodi:guide
+       id="guide2194"
+       position="38.996647"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide2196"
+       position="9.0140845"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide2198"
+       position="9.0140845"
+       orientation="vertical" />
+    <sodipodi:guide
+       id="guide2200"
+       position="38.975184"
+       orientation="vertical" />
+    <sodipodi:guide
+       id="guide2202"
+       position="22.988281"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide2204"
+       position="23.908786"
+       orientation="vertical" />
+    <sodipodi:guide
+       id="guide4332"
+       position="157.99417"
+       orientation="vertical" />
+    <sodipodi:guide
+       id="guide4334"
+       position="-36.062446"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide4336"
+       position="-58.02695"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide4338"
+       position="180.00287"
+       orientation="vertical" />
+    <sodipodi:guide
+       id="guide4417"
+       position="107.92217"
+       orientation="vertical" />
+    <sodipodi:guide
+       id="guide4419"
+       position="129.93087"
+       orientation="vertical" />
+    <sodipodi:guide
+       id="guide5106"
+       position="19.996875"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide5119"
+       position="63.039674"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide5121"
+       position="49.066305"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide5307"
+       position="-86.007168"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide5309"
+       position="-108.09009"
+       orientation="horizontal" />
+    <sodipodi:guide
+       id="guide3111"
+       position="-100.15429"
+       orientation="horizontal" />
+    <inkscape:grid
+       id="GridFromPre046Settings"
+       opacity=".2"
+       color="#0000ff"
+       originy="0px"
+       originx="0px"
+       empspacing="2"
+       spacingy="0.5px"
+       spacingx="0.5px"
+       empopacity="0.4"
+       type="xygrid"
+       empcolor="#0000ff"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,-8)">
+    <g
+       id="g3080"
+       transform="translate(0,-1.5909903)">
+      <path
+         inkscape:r_cx="true"
+         inkscape:r_cy="true"
+         sodipodi:cx="22.5"
+         sodipodi:cy="22"
+         transform="matrix(0.9207,0,0,0.99358,-0.386364,7.939297)"
+         d="m 36.5,22 c 0,7.179702 -6.268014,13 -14,13 -7.731986,0 -14,-5.820298 -14,-13 0,-7.179702 6.268014,-13 14,-13 7.731986,0 14,5.820298 14,13 z"
+         sodipodi:type="arc"
+         style="opacity:0.15;color:#000000;fill:url(#radialGradient3086);fill-rule:evenodd;stroke:url(#linearGradient3088);stroke-width:3.13660002;stroke-linecap:square;stroke-linejoin:round"
+         sodipodi:ry="13"
+         sodipodi:rx="14"
+         id="path3835" />
+      <path
+         sodipodi:cx="22.5"
+         sodipodi:cy="22"
+         transform="matrix(0.89486,0,0,0.9657,-0.210064,8.958397)"
+         d="m 36.5,22 c 0,7.179702 -6.268014,13 -14,13 -7.731986,0 -14,-5.820298 -14,-13 0,-7.179702 6.268014,-13 14,-13 7.731986,0 14,5.820298 14,13 z"
+         sodipodi:type="arc"
+         style="color:#000000;fill:url(#radialGradient3090);fill-rule:evenodd;stroke:#cc0000;stroke-width:1.07570004;stroke-linecap:square;stroke-linejoin:round"
+         sodipodi:ry="13"
+         sodipodi:rx="14"
+         id="path2525" />
+      <path
+         sodipodi:cx="24"
+         sodipodi:cy="24"
+         transform="matrix(0.82143,0,0,0.82143,0.219236,10.489597)"
+         d="m 38,24 c 0,7.731986 -6.268014,14 -14,14 -7.731986,0 -14,-6.268014 -14,-14 0,-7.731986 6.268014,-14 14,-14 7.731986,0 14,6.268014 14,14 z"
+         sodipodi:type="arc"
+         style="color:#000000;fill:none;stroke:#f77d7d;stroke-width:1.21739995;stroke-linecap:square;stroke-linejoin:round"
+         sodipodi:ry="14"
+         sodipodi:rx="14"
+         id="path2527" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 19.777136,18.204097 c -6.279,0.079 -11.404,4.992 -11.812,11.187 6.117,2.517 13.87,-1.451 23.142,-3.382 -0.689,-2.748 -4.555,-7.805 -11.174,-7.805 -0.051,0 -0.104,-0.001 -0.156,0 z"
+         style="opacity:0.6;fill:url(#radialGradient3092);fill-rule:evenodd"
+         sodipodi:nodetypes="cccsc"
+         id="path2529" />
+    </g>
+  </g>
+  <metadata
+     id="metadata43">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2010-03-10T21:04:47</dc:date>
+        <dc:description>Record icon from <A href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </A> 
\n<BR><BR>
\nSince version 0.8.90 Tango Project icons are Public Domain: <A href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </A></dc:description>
+        <dc:source>https://openclipart.org/detail/30955/tango-media-record-by-warszawianka</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>warszawianka</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>audio</rdf:li>
+            <rdf:li>button</rdf:li>
+            <rdf:li>circle</rdf:li>
+            <rdf:li>externalsource</rdf:li>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>record</rdf:li>
+            <rdf:li>red</rdf:li>
+            <rdf:li>sign</rdf:li>
+            <rdf:li>symbol</rdf:li>
+            <rdf:li>tango</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Player/Stop.svg b/SRC/OpenMeca/Rsc/Img/Player/Stop.svg
new file mode 100644
index 0000000..93f35ce
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Player/Stop.svg
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+    xmlns="http://www.w3.org/2000/svg"
+    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+    xmlns:cc="http://web.resource.org/cc/"
+    xmlns:xlink="http://www.w3.org/1999/xlink"
+    xmlns:dc="http://purl.org/dc/elements/1.1/"
+    xmlns:svg="http://www.w3.org/2000/svg"
+    xmlns:ns1="http://sozi.baierouge.fr"
+    id="svg2046"
+    sodipodi:docname="round_error_warning_icon.svg"
+    viewBox="0 0 159.61 159.61"
+    sodipodi:version="0.32"
+    version="1.0"
+    inkscape:version="0.44"
+    sodipodi:docbase="C:\Documents and Settings\Molumen\Desktop"
+  >
+  <defs
+      id="defs2048"
+    >
+    <linearGradient
+        id="linearGradient2109"
+        y2="553.74"
+        gradientUnits="userSpaceOnUse"
+        x2="380.68"
+        gradientTransform="matrix(.31227 0 0 .32049 127.55 434.38)"
+        y1="296.37"
+        x1="264.58"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5192"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop5194"
+          style="stop-color:#ff0000"
+          offset="1"
+      />
+    </linearGradient
+    >
+    <linearGradient
+        id="linearGradient2107"
+        y2="427.54"
+        gradientUnits="userSpaceOnUse"
+        x2="272.03"
+        gradientTransform="matrix(-.30163 .080822 -.082949 -.30957 402.86 730.11)"
+        y1="262.87"
+        x1="249.48"
+        inkscape:collect="always"
+      >
+      <stop
+          id="stop5199"
+          style="stop-color:#ffffff"
+          offset="0"
+      />
+      <stop
+          id="stop5201"
+          style="stop-color:#ff0000"
+          offset="1"
+      />
+    </linearGradient
+    >
+  </defs
+  >
+  <sodipodi:namedview
+      id="base"
+      bordercolor="#666666"
+      inkscape:pageshadow="2"
+      guidetolerance="10"
+      pagecolor="#ffffff"
+      gridtolerance="10000"
+      inkscape:window-height="569"
+      inkscape:zoom="1.4"
+      objecttolerance="10"
+      borderopacity="1.0"
+      inkscape:current-layer="layer1"
+      inkscape:cx="85.853793"
+      inkscape:cy="82.99359"
+      inkscape:window-y="124"
+      inkscape:window-x="606"
+      inkscape:window-width="853"
+      inkscape:pageopacity="0.0"
+      inkscape:document-units="px"
+  />
+  <g
+      id="layer1"
+      inkscape:label="Layer 1"
+      inkscape:groupmode="layer"
+      transform="translate(-311.62 -429.7)"
+    >
+    <g
+        id="g2100"
+        transform="matrix(.9 0 0 .9 170.44 -31.113)"
+      >
+      <path
+          id="path2174"
+          sodipodi:rx="250"
+          sodipodi:ry="250"
+          style="fill-rule:evenodd;stroke:#cb0000;stroke-width:20.128;fill:red"
+          sodipodi:type="arc"
+          d="m634.29 559.51a250 250 0 1 1 -500 0 250 250 0 1 1 500 0z"
+          transform="matrix(.30686 0 0 .30686 127.62 429)"
+          sodipodi:cy="559.50507"
+          sodipodi:cx="384.28571"
+      />
+      <path
+          id="path2540"
+          sodipodi:nodetypes="cccc"
+          style="fill-rule:evenodd;fill:url(#linearGradient2107)"
+          d="m264.19 668.93c19.05-5.1 34.17-17.66 43.23-33.82 14.71-34.82-40.17 46.7-85.49 31.89 13.17 4.83 27.81 5.8 42.26 1.93z"
+      />
+      <path
+          id="path2197"
+          sodipodi:nodetypes="ccccc"
+          style="fill-rule:evenodd;fill:url(#linearGradient2109)"
+          d="m245.66 529.36c-39.44 0-71.44 32.85-71.44 73.32 0 5.48 0.6 10.81 1.71 15.94 39.21-75.47 81.45-27.96 135.91-43.55-10.64-26.8-36.26-45.71-66.18-45.71z"
+      />
+      <path
+          id="text2705"
+          sodipodi:nodetypes="ccccccccccccc"
+          style="opacity:.73529;fill:white"
+          d="m267.42 640.04l-21.68-21.68-21.88 21.88-17.87-17.87 21.88-21.89-21.68-21.68 17.4-17.4 21.68 21.68 21.95-21.95 17.88 17.88-21.96 21.95 21.68 21.68-17.4 17.4"
+      />
+      <path
+          id="text2713"
+          style="fill:white"
+          d="m267.3 637.01l-21.59-21.59-21.76 21.76-14.9-14.91 21.76-21.75-21.59-21.59 14.51-14.51 21.58 21.59 21.82-21.81 14.9 14.9-21.81 21.81 21.58 21.59-14.5 14.51"
+      />
+    </g
+    >
+  </g
+  >
+  <metadata
+    >
+    <rdf:RDF
+      >
+      <cc:Work
+        >
+        <dc:format
+          >image/svg+xml</dc:format
+        >
+        <dc:type
+            rdf:resource="http://purl.org/dc/dcmitype/StillImage"
+        />
+        <cc:license
+            rdf:resource="http://creativecommons.org/licenses/publicdomain/"
+        />
+        <dc:publisher
+          >
+          <cc:Agent
+              rdf:about="http://openclipart.org/"
+            >
+            <dc:title
+              >Openclipart</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:publisher
+        >
+        <dc:title
+          >red round error warning icon</dc:title
+        >
+        <dc:date
+          >2006-09-07T17:35:55</dc:date
+        >
+        <dc:description
+          >a red round error or warning icon</dc:description
+        >
+        <dc:source
+          >https://openclipart.org/detail/109/red-round-error-warning-icon-by-molumen</dc:source
+        >
+        <dc:creator
+          >
+          <cc:Agent
+            >
+            <dc:title
+              >molumen</dc:title
+            >
+          </cc:Agent
+          >
+        </dc:creator
+        >
+        <dc:subject
+          >
+          <rdf:Bag
+            >
+            <rdf:li
+              >button</rdf:li
+            >
+            <rdf:li
+              >cancel</rdf:li
+            >
+            <rdf:li
+              >delete</rdf:li
+            >
+            <rdf:li
+              >error</rdf:li
+            >
+            <rdf:li
+              >glossy</rdf:li
+            >
+            <rdf:li
+              >icon</rdf:li
+            >
+            <rdf:li
+              >negative</rdf:li
+            >
+            <rdf:li
+              >red</rdf:li
+            >
+            <rdf:li
+              >round</rdf:li
+            >
+            <rdf:li
+              >stop</rdf:li
+            >
+            <rdf:li
+              >warning</rdf:li
+            >
+          </rdf:Bag
+          >
+        </dc:subject
+        >
+      </cc:Work
+      >
+      <cc:License
+          rdf:about="http://creativecommons.org/licenses/publicdomain/"
+        >
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Reproduction"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#Distribution"
+        />
+        <cc:permits
+            rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
+        />
+      </cc:License
+      >
+    </rdf:RDF
+    >
+  </metadata
+  >
+</svg
+>
diff --git a/SRC/OpenMeca/Rsc/Img/Screenshot.png b/SRC/OpenMeca/Rsc/Img/Screenshot.png
new file mode 100644
index 0000000..ba4d46b
Binary files /dev/null and b/SRC/OpenMeca/Rsc/Img/Screenshot.png differ
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor.svg b/SRC/OpenMeca/Rsc/Img/Sensor.svg
new file mode 100644
index 0000000..02d5323
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor.svg
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   viewBox="0 0 40 40"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"
+   sodipodi:docname="Sensor.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="819"
+     id="namedview29"
+     showgrid="false"
+     inkscape:zoom="5.6239683"
+     inkscape:cx="38.312615"
+     inkscape:cy="-8.2074632"
+     inkscape:window-x="0"
+     inkscape:window-y="16"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2" />
+  <title
+     id="title3006">Progress</title>
+  <defs
+     id="defs4">
+    <filter
+       id="filter3799"
+       width="1.2043999"
+       y="-0.14526001"
+       x="-0.10222"
+       height="1.2905"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur3801"
+         stdDeviation="11.5" />
+    </filter>
+    <filter
+       id="filter3944"
+       color-interpolation-filters="sRGB">
+      <feGaussianBlur
+         id="feGaussianBlur3946"
+         stdDeviation="7.76" />
+    </filter>
+  </defs>
+  <rect
+     style="opacity:0.29310004;fill:none;stroke:#393939;stroke-width:0.08210651"
+     x="2.8049877"
+     y="1.0623053"
+     width="38.898781"
+     height="38.898781"
+     id="rect2985" />
+  <g
+     style="stroke:#000000;stroke-width:24.35860443;stroke-miterlimit:4;stroke-dasharray:none"
+     id="g3862"
+     transform="matrix(0.08210651,0,0,0.08210651,-8.8065149,-19.986518)">
+    <path
+       id="path3755"
+       d="m 170,312.36 v 345"
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke-width:24.35860443;stroke-miterlimit:4;stroke-dasharray:none" />
+    <path
+       id="path3761"
+       d="m 170,287.36 -10,30 h 20 z"
+       inkscape:connector-curvature="0"
+       style="stroke-width:24.35860443;stroke-miterlimit:4;stroke-dasharray:none" />
+  </g>
+  <g
+     style="stroke:#000000;stroke-width:24.35860443;stroke-miterlimit:4;stroke-dasharray:none"
+     id="g3866"
+     transform="matrix(0.08210651,0,0,0.08210651,-8.8065149,-19.986518)">
+    <path
+       id="path3757"
+       d="M 533,655.36 157.87898,654.2772"
+       inkscape:connector-curvature="0"
+       style="fill:none;stroke-width:24.35860443;stroke-miterlimit:4;stroke-dasharray:none"
+       sodipodi:nodetypes="cc" />
+    <path
+       id="path3763"
+       d="m 558,655.36 -30,-10 v 20 z"
+       inkscape:connector-curvature="0"
+       style="stroke-width:24.35860443;stroke-miterlimit:4;stroke-dasharray:none" />
+  </g>
+  <path
+     style="fill:none;stroke:#fa0000;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+     inkscape:connector-curvature="0"
+     d="m 11.348805,24.053174 4.105326,-3.284261 6.56852,4.926391 11.494912,-15.600237"
+     id="path3767" />
+  <metadata
+     id="metadata27">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title>Progress</dc:title>
+        <dc:date>2013-05-17T18:08:54</dc:date>
+        <dc:description>A graph of progress</dc:description>
+        <dc:source>https://openclipart.org/detail/178279/progress-by-kamil_stepinski-178279</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>kamil_stepinski</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>chart</rdf:li>
+            <rdf:li>graph</rdf:li>
+            <rdf:li>progress</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/AngularAcceleration.svg b/SRC/OpenMeca/Rsc/Img/Sensor/AngularAcceleration.svg
new file mode 100644
index 0000000..9699655
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/AngularAcceleration.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="AngularVelocity.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="771"
+     id="namedview5630"
+     showgrid="false"
+     inkscape:zoom="8.34386"
+     inkscape:cx="-9.4651047"
+     inkscape:cy="15.682894"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="M 3.5890853,36.093384 C 2.7677037,5.3724769 26.672487,4.2913554 35.526365,5.1966353"
+     id="path2992"
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1,1;stroke-dashoffset:0"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     id="path2086-1-6"
+     style="color:#000000;fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:block"
+     d="m 32.638826,4.5202666 c -0.311676,1.162905 0.379304,2.359623 1.54221,2.671299 1.163272,0.311676 2.35999,-0.379304 2.671666,-1.542208 0.311677,-1.162905 -0.379303,-2.359844 -1.542576,-2.671447 -1.162904,-0.311639 -2.359623,0.379341 -2.6713,1.542356 z"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:8,2,1,2;stroke-dashoffset:0"
+     d="M 3.5954582,35.925147 34.636248,36.044996 34.875945,4.7645095"
+     id="path3109"
+     inkscape:connector-curvature="0" />
+  <g
+     id="g3904">
+    <path
+       d="M 5.7354506,3.2901512 12.111133,4.3043836 5.5797529,9.7111956 5.7354318,3.2901314 z"
+       id="path1317"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:2.21639967;stroke-linecap:round;stroke-linejoin:round"
+       inkscape:connector-curvature="0" />
+    <path
+       d="M 33.297414,34.612895 9.6073007,7.6918089"
+       id="path1323"
+       style="fill:none;stroke:#e71c02;stroke-width:3.55802894;stroke-linecap:round;stroke-linejoin:round"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/AngularPosition.svg b/SRC/OpenMeca/Rsc/Img/Sensor/AngularPosition.svg
new file mode 100644
index 0000000..5f8b012
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/AngularPosition.svg
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="AngularPosition.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="771"
+     id="namedview5630"
+     showgrid="false"
+     inkscape:zoom="8.34386"
+     inkscape:cx="-9.4651047"
+     inkscape:cy="15.682894"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="M 3.5890853,36.093384 C 2.7677037,5.3724769 26.672487,4.2913554 35.526365,5.1966353"
+     id="path2992"
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1,1;stroke-dashoffset:0"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     id="path2086-1-6"
+     style="color:#000000;fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:block"
+     d="m 32.638826,4.5202666 c -0.311676,1.162905 0.379304,2.359623 1.54221,2.671299 1.163272,0.311676 2.35999,-0.379304 2.671666,-1.542208 0.311677,-1.162905 -0.379303,-2.359844 -1.542576,-2.671447 -1.162904,-0.311639 -2.359623,0.379341 -2.6713,1.542356 z"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:8,2,1,2;stroke-dashoffset:0"
+     d="M 3.5954582,35.925147 34.636248,36.044996 34.875945,4.7645095"
+     id="path3109"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/AngularVelocity.svg b/SRC/OpenMeca/Rsc/Img/Sensor/AngularVelocity.svg
new file mode 100644
index 0000000..3b62939
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/AngularVelocity.svg
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="AngularVelocity.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="867"
+     id="namedview5630"
+     showgrid="false"
+     inkscape:zoom="8.34386"
+     inkscape:cx="-9.4651047"
+     inkscape:cy="15.682894"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="M 3.5890853,36.093384 C 2.7677037,5.3724769 26.672487,4.2913554 35.526365,5.1966353"
+     id="path2992"
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1,1;stroke-dashoffset:0"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     id="path2086-1-6"
+     style="color:#000000;fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:block"
+     d="m 32.638826,4.5202666 c -0.311676,1.162905 0.379304,2.359623 1.54221,2.671299 1.163272,0.311676 2.35999,-0.379304 2.671666,-1.542208 0.311677,-1.162905 -0.379303,-2.359844 -1.542576,-2.671447 -1.162904,-0.311639 -2.359623,0.379341 -2.6713,1.542356 z"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:8,2,1,2;stroke-dashoffset:0"
+     d="M 3.5954582,35.925147 34.636248,36.044996 34.875945,4.7645095"
+     id="path3109"
+     inkscape:connector-curvature="0" />
+  <g
+     id="g3904">
+    <path
+       d="M 5.7354506,3.2901512 12.111133,4.3043836 5.5797529,9.7111956 5.7354318,3.2901314 z"
+       id="path1317"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:2.21639967;stroke-linecap:round;stroke-linejoin:round"
+       inkscape:connector-curvature="0" />
+    <path
+       d="M 33.297414,34.612895 9.6073007,7.6918089"
+       id="path1323"
+       style="fill:none;stroke:#e71c02;stroke-width:3.55802894;stroke-linecap:round;stroke-linejoin:round"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/Force.svg b/SRC/OpenMeca/Rsc/Img/Sensor/Force.svg
new file mode 100644
index 0000000..c48e468
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/Force.svg
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg1"
+   sodipodi:docname="Force.svg"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   _SVGFile__filename="oldscale/actions/circle.svg"
+   version="1.0"
+   y="0"
+   x="0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs21" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="32"
+     pagecolor="#ffffff"
+     inkscape:window-height="803"
+     inkscape:zoom="4.6034679"
+     inkscape:window-x="0"
+     borderopacity="1.0"
+     inkscape:current-layer="svg1"
+     inkscape:cx="-13.694889"
+     inkscape:cy="32.33556"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0000000"
+     showgrid="false"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g3013"
+     transform="translate(-6.9512812,-1.0861377)">
+    <path
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0"
+       id="path2992"
+       d="M 12.164743,36.19891 C 5.4419384,14.363664 19.8312,5.0887654 19.984934,5.1353724"
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m 15.468914,5.5609733 c -0.36081,1.346232 0.4391,2.731608 1.785332,3.092419 1.346657,0.36081 2.732033,-0.4391 3.092843,-1.785331 0.360811,-1.346232 -0.439099,-2.731863 -1.785756,-3.092589 -1.346232,-0.360768 -2.731608,0.439143 -3.092419,1.785501 z"
+       style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:1.32963777;stroke-linecap:round;stroke-linejoin:round;display:block"
+       id="path2086-1" />
+  </g>
+  <g
+     id="g3000-1"
+     transform="matrix(-0.16547702,-0.76683195,0.71991702,-0.1747779,-1.6807025,-45.625784)">
+    <path
+       inkscape:connector-curvature="0"
+       d="m -68.01036,3.028382 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round"
+       id="path1317-4" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m -109.52556,27.048382 37.779,-21.812"
+       style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round"
+       id="path1323-3" />
+  </g>
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.722754,5.0263663 c 6.299598,3.6928682 6.299598,3.6928682 6.299598,3.6928682"
+     id="path3017"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.288299,8.7192345 c 6.734053,4.5617785 6.734053,4.5617785 6.734053,4.5617785"
+     id="path3019"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 13.685335,15.236061 c -0.217228,6.516826 -0.217228,6.516826 -0.217228,6.516826"
+     id="path3021"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="M 10.426922,15.018833 C 8.2546465,25.228527 8.2546465,25.228527 8.2546465,25.228527"
+     id="path3023"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/LinearAcceleration.svg b/SRC/OpenMeca/Rsc/Img/Sensor/LinearAcceleration.svg
new file mode 100644
index 0000000..069582d
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/LinearAcceleration.svg
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="LinearAcceleration.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="691"
+     id="namedview6244"
+     showgrid="false"
+     inkscape:zoom="8.34386"
+     inkscape:cx="42.441015"
+     inkscape:cy="11.246313"
+     inkscape:window-x="0"
+     inkscape:window-y="96"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:1.69794059;stroke-linecap:round;stroke-linejoin:round"
+     id="path1317-5"
+     d="m 34.466021,36.718248 -3.242149,-3.73108 6.442374,-0.02719 -3.200224,3.758294 z"
+     sodipodi:nodetypes="ccccc" />
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#e71c02;stroke-width:2.72573662;stroke-linecap:round;stroke-linejoin:round"
+     id="path1323-9"
+     d="M 34.145164,6.4155088 34.332953,34.042975" />
+  <path
+     d="M 3.143146,37.602307 C 2.321764,6.8814 26.226547,5.800278 35.080425,6.705558"
+     id="path2992-5"
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:1, 1;stroke-dashoffset:0"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     id="path2086-1-6"
+     style="color:#000000;fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:block"
+     d="m 32.192886,6.029189 c -0.311676,1.162905 0.379304,2.359623 1.54221,2.671299 1.163272,0.311676 2.35999,-0.379304 2.671666,-1.542208 0.311677,-1.162905 -0.379303,-2.359844 -1.542576,-2.671447 -1.162904,-0.311639 -2.359623,0.379341 -2.6713,1.542356 z"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/LinearPosition.svg b/SRC/OpenMeca/Rsc/Img/Sensor/LinearPosition.svg
new file mode 100644
index 0000000..08e44ef
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/LinearPosition.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg1"
+   sodipodi:docname="LinearPosition.svg"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   _SVGFile__filename="oldscale/actions/circle.svg"
+   version="1.0"
+   y="0"
+   x="0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs21" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="64"
+     pagecolor="#ffffff"
+     inkscape:window-height="723"
+     inkscape:zoom="4.6034679"
+     inkscape:window-x="0"
+     borderopacity="1.0"
+     inkscape:current-layer="svg1"
+     inkscape:cx="2.9230177"
+     inkscape:cy="24.732596"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0000000"
+     showgrid="false"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1,1;stroke-dashoffset:0"
+     d="M 3.4756412,35.764455 C 25.492327,34.095686 19.724521,8.1435381 33.235813,5.3525996"
+     id="path2992"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     id="path2086-1"
+     style="color:#000000;fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:block"
+     d="m 31.358639,4.6537286 c -0.311676,1.162905 0.379304,2.359623 1.54221,2.671299 1.163272,0.311676 2.35999,-0.379304 2.671666,-1.542208 0.311677,-1.162905 -0.379303,-2.359844 -1.542576,-2.671447 -1.162904,-0.311639 -2.359623,0.379341 -2.6713,1.542356 z"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/LinearVelocity.svg b/SRC/OpenMeca/Rsc/Img/Sensor/LinearVelocity.svg
new file mode 100644
index 0000000..74b2fd0
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/LinearVelocity.svg
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="LinearVelocity.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="707"
+     id="namedview5630"
+     showgrid="false"
+     inkscape:zoom="4.17193"
+     inkscape:cx="-0.32474198"
+     inkscape:cy="32.117238"
+     inkscape:window-x="0"
+     inkscape:window-y="80"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:1.69794059;stroke-linecap:round;stroke-linejoin:round"
+     id="path1317"
+     d="M 2.8574464,4.8874291 6.6130471,1.9157057 6.5873569,8.3580855 2.8574254,4.887429 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#e71c02;stroke-width:2.72573662;stroke-linecap:round;stroke-linejoin:round"
+     id="path1323"
+     d="M 35.017423,5.0702628 7.3893458,5.0312635" />
+  <path
+     d="M 3.5890853,36.093384 C 2.7677037,5.3724769 26.672487,4.2913554 35.526365,5.1966353"
+     id="path2992"
+     style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:1,1;stroke-dashoffset:0"
+     inkscape:connector-curvature="0"
+     sodipodi:nodetypes="cc" />
+  <path
+     id="path2086-1-6"
+     style="color:#000000;fill:#c8c8c8;fill-opacity:1;stroke:#000000;stroke-width:1.20000005;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;display:block"
+     d="m 32.638826,4.5202666 c -0.311676,1.162905 0.379304,2.359623 1.54221,2.671299 1.163272,0.311676 2.35999,-0.379304 2.671666,-1.542208 0.311677,-1.162905 -0.379303,-2.359844 -1.542576,-2.671447 -1.162904,-0.311639 -2.359623,0.379341 -2.6713,1.542356 z"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/RotationAcceleration.svg b/SRC/OpenMeca/Rsc/Img/Sensor/RotationAcceleration.svg
new file mode 100644
index 0000000..3e401cc
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/RotationAcceleration.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="RotationAcceleration.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="983"
+     id="namedview3089"
+     showgrid="false"
+     inkscape:zoom="5.5625733"
+     inkscape:cx="5.792391"
+     inkscape:cy="20.722907"
+     inkscape:window-x="1600"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="M 20.097252,7.9697093 6.3735032,31.740621 H 33.821646"
+     id="path2097"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:6.42648125;stroke-linecap:round;stroke-linejoin:round"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 3.9943556,30.185413 c -0.5448371,2.033338 0.6633414,4.126443 2.6968086,4.670766 2.0337866,0.544966 4.1262488,-0.663213 4.6712148,-2.696551 0.544965,-2.033339 -0.663213,-4.125801 -2.6971945,-4.670767 -2.0333367,-0.544966 -4.1259276,0.663213 -4.6708289,2.696552 z"
+     id="path2085"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:5.22151613;stroke-linecap:round;stroke-linejoin:round;display:block"
+     inkscape:connector-curvature="0" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#f2f8ff;stroke-width:7.44817543;stroke-linecap:round;stroke-linejoin:round"
+     id="path2167"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#c5d8ef"
+     id="path2157"
+     d="M 14.080784,15.398502 3.2894413,34.277251 H 24.988472 c 0.0089,-0.247035 0.06966,-0.476853 0.06966,-0.725385 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#9da1a6;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path2165"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#000000;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path1322"
+     d="M 19.037005,6.7238132 3.2887022,34.278 H 34.785309" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path1333"
+     d="m 29.148052,32.394542 c -0.628421,2.368546 0.764776,4.806711 3.110236,5.440769 2.34472,0.634806 4.757617,-0.772547 5.386038,-3.141094 0.62842,-2.368546 -0.764776,-4.805962 -3.109496,-5.440769 -2.345461,-0.634806 -4.758358,0.772547 -5.386778,3.141094 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path2086"
+     d="m 14.645473,6.957374 c -0.62842,2.3685459 0.764775,4.805962 3.109495,5.440769 2.345461,0.634807 4.758358,-0.772547 5.386778,-3.1410932 C 23.770167,6.8885039 22.376971,4.4506382 20.03151,3.8159814 17.68679,3.18125 15.273893,4.5886032 14.645473,6.957374 z" />
+  <g
+     id="g3000"
+     transform="matrix(0.76765524,-0.19344076,0.29953124,0.46636835,79.206812,0.28675411)">
+    <path
+       inkscape:connector-curvature="0"
+       d="m -68.01036,3.028382 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round"
+       id="path1317" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m -109.52556,27.048382 37.779,-21.812"
+       style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round"
+       id="path1323" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/RotationAngle.svg b/SRC/OpenMeca/Rsc/Img/Sensor/RotationAngle.svg
new file mode 100644
index 0000000..e7412e0
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/RotationAngle.svg
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="RotationAngle.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="983"
+     id="namedview3089"
+     showgrid="false"
+     inkscape:zoom="5.5625733"
+     inkscape:cx="5.792391"
+     inkscape:cy="20.722907"
+     inkscape:window-x="1600"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="M 20.097252,7.9697093 6.3735032,31.740621 H 33.821646"
+     id="path2097"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:6.42648125;stroke-linecap:round;stroke-linejoin:round"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 3.9943556,30.185413 c -0.5448371,2.033338 0.6633414,4.126443 2.6968086,4.670766 2.0337866,0.544966 4.1262488,-0.663213 4.6712148,-2.696551 0.544965,-2.033339 -0.663213,-4.125801 -2.6971945,-4.670767 -2.0333367,-0.544966 -4.1259276,0.663213 -4.6708289,2.696552 z"
+     id="path2085"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:5.22151613;stroke-linecap:round;stroke-linejoin:round;display:block"
+     inkscape:connector-curvature="0" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#f2f8ff;stroke-width:7.44817543;stroke-linecap:round;stroke-linejoin:round"
+     id="path2167"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#c5d8ef"
+     id="path2157"
+     d="M 14.080784,15.398502 3.2894413,34.277251 H 24.988472 c 0.0089,-0.247035 0.06966,-0.476853 0.06966,-0.725385 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#9da1a6;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path2165"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#000000;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path1322"
+     d="M 19.037005,6.7238132 3.2887022,34.278 H 34.785309" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path1333"
+     d="m 29.148052,32.394542 c -0.628421,2.368546 0.764776,4.806711 3.110236,5.440769 2.34472,0.634806 4.757617,-0.772547 5.386038,-3.141094 0.62842,-2.368546 -0.764776,-4.805962 -3.109496,-5.440769 -2.345461,-0.634806 -4.758358,0.772547 -5.386778,3.141094 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path2086"
+     d="m 14.645473,6.957374 c -0.62842,2.3685459 0.764775,4.805962 3.109495,5.440769 2.345461,0.634807 4.758358,-0.772547 5.386778,-3.1410932 C 23.770167,6.8885039 22.376971,4.4506382 20.03151,3.8159814 17.68679,3.18125 15.273893,4.5886032 14.645473,6.957374 z" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/RotationAxis.svg b/SRC/OpenMeca/Rsc/Img/Sensor/RotationAxis.svg
new file mode 100644
index 0000000..2e3d18f
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/RotationAxis.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="RotationAcceleration.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="983"
+     id="namedview3089"
+     showgrid="false"
+     inkscape:zoom="5.5625733"
+     inkscape:cx="5.792391"
+     inkscape:cy="20.722907"
+     inkscape:window-x="1600"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="M 20.097252,7.9697093 6.3735032,31.740621 H 33.821646"
+     id="path2097"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:6.42648125;stroke-linecap:round;stroke-linejoin:round"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 3.9943556,30.185413 c -0.5448371,2.033338 0.6633414,4.126443 2.6968086,4.670766 2.0337866,0.544966 4.1262488,-0.663213 4.6712148,-2.696551 0.544965,-2.033339 -0.663213,-4.125801 -2.6971945,-4.670767 -2.0333367,-0.544966 -4.1259276,0.663213 -4.6708289,2.696552 z"
+     id="path2085"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:5.22151613;stroke-linecap:round;stroke-linejoin:round;display:block"
+     inkscape:connector-curvature="0" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#f2f8ff;stroke-width:7.44817543;stroke-linecap:round;stroke-linejoin:round"
+     id="path2167"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#c5d8ef"
+     id="path2157"
+     d="M 14.080784,15.398502 3.2894413,34.277251 H 24.988472 c 0.0089,-0.247035 0.06966,-0.476853 0.06966,-0.725385 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#9da1a6;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path2165"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#000000;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path1322"
+     d="M 19.037005,6.7238132 3.2887022,34.278 H 34.785309" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path1333"
+     d="m 29.148052,32.394542 c -0.628421,2.368546 0.764776,4.806711 3.110236,5.440769 2.34472,0.634806 4.757617,-0.772547 5.386038,-3.141094 0.62842,-2.368546 -0.764776,-4.805962 -3.109496,-5.440769 -2.345461,-0.634806 -4.758358,0.772547 -5.386778,3.141094 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path2086"
+     d="m 14.645473,6.957374 c -0.62842,2.3685459 0.764775,4.805962 3.109495,5.440769 2.345461,0.634807 4.758358,-0.772547 5.386778,-3.1410932 C 23.770167,6.8885039 22.376971,4.4506382 20.03151,3.8159814 17.68679,3.18125 15.273893,4.5886032 14.645473,6.957374 z" />
+  <g
+     id="g3000"
+     transform="matrix(0.76765524,-0.19344076,0.29953124,0.46636835,79.206812,0.28675411)">
+    <path
+       inkscape:connector-curvature="0"
+       d="m -68.01036,3.028382 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round"
+       id="path1317" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m -109.52556,27.048382 37.779,-21.812"
+       style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round"
+       id="path1323" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/RotationVelocity.svg b/SRC/OpenMeca/Rsc/Img/Sensor/RotationVelocity.svg
new file mode 100644
index 0000000..6a7676e
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/RotationVelocity.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 40 40"
+   id="svg1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="RotationAxis.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="983"
+     id="namedview3089"
+     showgrid="false"
+     inkscape:zoom="5.5625733"
+     inkscape:cx="5.792391"
+     inkscape:cy="20.722907"
+     inkscape:window-x="1600"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" />
+  <defs
+     id="defs21" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="M 20.097252,7.9697093 6.3735032,31.740621 H 33.821646"
+     id="path2097"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:6.42648125;stroke-linecap:round;stroke-linejoin:round"
+     inkscape:connector-curvature="0" />
+  <path
+     d="m 3.9943556,30.185413 c -0.5448371,2.033338 0.6633414,4.126443 2.6968086,4.670766 2.0337866,0.544966 4.1262488,-0.663213 4.6712148,-2.696551 0.544965,-2.033339 -0.663213,-4.125801 -2.6971945,-4.670767 -2.0333367,-0.544966 -4.1259276,0.663213 -4.6708289,2.696552 z"
+     id="path2085"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:5.22151613;stroke-linecap:round;stroke-linejoin:round;display:block"
+     inkscape:connector-curvature="0" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#f2f8ff;stroke-width:7.44817543;stroke-linecap:round;stroke-linejoin:round"
+     id="path2167"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#c5d8ef"
+     id="path2157"
+     d="M 14.080784,15.398502 3.2894413,34.277251 H 24.988472 c 0.0089,-0.247035 0.06966,-0.476853 0.06966,-0.725385 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#9da1a6;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path2165"
+     d="m 25.058132,33.551866 c 0,-7.914119 -4.48787,-14.709091 -10.977348,-18.153364" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:none;stroke:#000000;stroke-width:3.72408772;stroke-linecap:round;stroke-linejoin:round"
+     id="path1322"
+     d="M 19.037005,6.7238132 3.2887022,34.278 H 34.785309" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path1333"
+     d="m 29.148052,32.394542 c -0.628421,2.368546 0.764776,4.806711 3.110236,5.440769 2.34472,0.634806 4.757617,-0.772547 5.386038,-3.141094 0.62842,-2.368546 -0.764776,-4.805962 -3.109496,-5.440769 -2.345461,-0.634806 -4.758358,0.772547 -5.386778,3.141094 z" />
+  <path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:2.3275547;stroke-linecap:round;stroke-linejoin:round;display:block"
+     id="path2086"
+     d="m 14.645473,6.957374 c -0.62842,2.3685459 0.764775,4.805962 3.109495,5.440769 2.345461,0.634807 4.758358,-0.772547 5.386778,-3.1410932 C 23.770167,6.8885039 22.376971,4.4506382 20.03151,3.8159814 17.68679,3.18125 15.273893,4.5886032 14.645473,6.957374 z" />
+  <g
+     id="g3000"
+     transform="matrix(0.76765524,-0.19344076,0.29953124,0.46636835,79.206812,0.28675411)">
+    <path
+       inkscape:connector-curvature="0"
+       d="m -68.01036,3.028382 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round"
+       id="path1317" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m -109.52556,27.048382 37.779,-21.812"
+       style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round"
+       id="path1323" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/Torque.svg b/SRC/OpenMeca/Rsc/Img/Sensor/Torque.svg
new file mode 100644
index 0000000..f5584ee
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/Torque.svg
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg1"
+   sodipodi:docname="Torque.svg"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   _SVGFile__filename="oldscale/actions/circle.svg"
+   version="1.0"
+   y="0"
+   x="0"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs21" />
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="48"
+     pagecolor="#ffffff"
+     inkscape:window-height="819"
+     inkscape:zoom="4.6034679"
+     inkscape:window-x="0"
+     borderopacity="1.0"
+     inkscape:current-layer="g3000-1"
+     inkscape:cx="-13.694889"
+     inkscape:cy="32.33556"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0000000"
+     showgrid="false"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:title />
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="g3013"
+     transform="translate(-6.9512812,-1.0861377)">
+    <path
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0"
+       id="path2992"
+       d="M 12.164743,36.19891 C 5.4419384,14.363664 19.8312,5.0887654 19.984934,5.1353724"
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m 15.468914,5.5609733 c -0.36081,1.346232 0.4391,2.731608 1.785332,3.092419 1.346657,0.36081 2.732033,-0.4391 3.092843,-1.785331 0.360811,-1.346232 -0.439099,-2.731863 -1.785756,-3.092589 -1.346232,-0.360768 -2.731608,0.439143 -3.092419,1.785501 z"
+       style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:1.32963777;stroke-linecap:round;stroke-linejoin:round;display:block"
+       id="path2086-1" />
+  </g>
+  <g
+     id="g3000-1"
+     transform="matrix(-0.16547702,-0.76683195,0.71991702,-0.1747779,-1.6807025,-45.625784)">
+    <path
+       inkscape:connector-curvature="0"
+       d="m -68.01036,3.028382 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+       style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round"
+       id="path1317-4" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m -109.52556,27.048382 c 10.892776,1.815507 23.421902,-5.113809 37.779,-21.812"
+       style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round"
+       id="path1323-3"
+       sodipodi:nodetypes="cc" />
+  </g>
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.722754,5.0263663 c 6.299598,3.6928682 6.299598,3.6928682 6.299598,3.6928682"
+     id="path3017"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 21.288299,8.7192345 c 6.734053,4.5617785 6.734053,4.5617785 6.734053,4.5617785"
+     id="path3019"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="m 13.685335,15.236061 c -0.217228,6.516826 -0.217228,6.516826 -0.217228,6.516826"
+     id="path3021"
+     inkscape:connector-curvature="0" />
+  <path
+     style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     d="M 10.426922,15.018833 C 8.2546465,25.228527 8.2546465,25.228527 8.2546465,25.228527"
+     id="path3023"
+     inkscape:connector-curvature="0" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Sensor/save.svg b/SRC/OpenMeca/Rsc/Img/Sensor/save.svg
new file mode 100644
index 0000000..f5964f1
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Sensor/save.svg
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 60 60"
+   id="svg1">
+  <defs
+     id="defs21" />
+  <path
+     d="M 8.7488,47.97 46.5278,26.158"
+     id="path2999"
+     style="fill:none;stroke:#ffffff;stroke-width:10;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="m 50.264,23.95 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+     id="path2992"
+     style="color:#000000;fill:#000000;stroke:#ffffff;stroke-width:8.125;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="m 50.264,23.95 -2.9,8.612 -6.044,-10.223 8.944,1.611 z"
+     id="path1317"
+     style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="M 29.948,10.885 8.593,47.874 h 42.711"
+     id="path2097"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:10;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="m 24.074,11.474 c -0.848,3.164 1.032,6.42 4.196,7.268 3.165,0.848 6.421,-1.032 7.269,-4.196 0.848,-3.164 -1.032,-6.4206 -4.197,-7.2684 -3.164,-0.8479 -6.42,1.0321 -7.268,4.1964 z"
+     id="path2083"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:8.125;stroke-linecap:round;stroke-linejoin:round;display:block" />
+  <path
+     d="m 4.8909,45.454 c -0.8478,3.164 1.0322,6.421 4.1964,7.268 3.1647,0.848 6.4207,-1.032 7.2687,-4.196 0.848,-3.164 -1.032,-6.42 -4.197,-7.268 C 8.995,40.41 5.7388,42.29 4.8909,45.454 z"
+     id="path2085"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:8.125;stroke-linecap:round;stroke-linejoin:round;display:block" />
+  <path
+     d="m 43.644,45.454 c -0.848,3.164 1.032,6.421 4.197,7.268 3.164,0.848 6.42,-1.032 7.268,-4.196 0.848,-3.164 -1.032,-6.42 -4.196,-7.268 -3.165,-0.848 -6.421,1.032 -7.269,4.196 z"
+     id="path1331"
+     style="color:#000000;fill:none;stroke:#ffffff;stroke-width:8.125;stroke-linecap:round;stroke-linejoin:round;display:block" />
+  <path
+     d="m 38.125,47 c 0,-10.572 -6.056,-19.649 -14.813,-24.25"
+     id="path2167"
+     style="color:#000000;fill:none;stroke:#f2f8ff;stroke-width:10;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="M 23.312,22.75 8.75,47.969 h 29.281 c 0.012,-0.33 0.094,-0.637 0.094,-0.969 0,-10.572 -6.056,-19.649 -14.813,-24.25 z"
+     id="path2157"
+     style="color:#000000;fill:#c5d8ef" />
+  <path
+     d="m 38.125,47 c 0,-10.572 -6.056,-19.649 -14.813,-24.25"
+     id="path2165"
+     style="color:#000000;fill:none;stroke:#9da1a6;stroke-width:5;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="M 30,11.162 8.749,47.97 h 42.502"
+     id="path1322"
+     style="color:#000000;fill:none;stroke:#000000;stroke-width:5;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="m 43.644,45.454 c -0.848,3.164 1.032,6.421 4.197,7.268 3.164,0.848 6.42,-1.032 7.268,-4.196 0.848,-3.164 -1.032,-6.42 -4.196,-7.268 -3.165,-0.848 -6.421,1.032 -7.269,4.196 z"
+     id="path1333"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round;display:block" />
+  <path
+     d="M 8.7488,47.97 46.5278,26.158"
+     id="path1323"
+     style="fill:none;stroke:#e71c02;stroke-width:5;stroke-linecap:round;stroke-linejoin:round" />
+  <path
+     d="m 4.8909,45.454 c -0.8478,3.164 1.0322,6.421 4.1964,7.268 3.1647,0.848 6.4207,-1.032 7.2687,-4.196 0.848,-3.164 -1.032,-6.42 -4.197,-7.268 C 8.995,40.41 5.7388,42.29 4.8909,45.454 z"
+     id="path2087"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round;display:block" />
+  <path
+     d="m 24.074,11.474 c -0.848,3.164 1.032,6.42 4.196,7.268 3.165,0.848 6.421,-1.032 7.269,-4.196 0.848,-3.164 -1.032,-6.4206 -4.197,-7.2684 -3.164,-0.8479 -6.42,1.0321 -7.268,4.1964 z"
+     id="path2086"
+     style="color:#000000;fill:#ffe940;stroke:#000000;stroke-width:3.125;stroke-linecap:round;stroke-linejoin:round;display:block" />
+  <metadata
+     id="metadata19">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Shape/Box.svg b/SRC/OpenMeca/Rsc/Img/Shape/Box.svg
new file mode 100644
index 0000000..ffeb695
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Shape/Box.svg
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.0"
+   width="100%"
+   height="100%"
+   viewBox="0 0 80 80"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Box.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="819"
+     id="namedview4887"
+     showgrid="false"
+     inkscape:zoom="2.95"
+     inkscape:cx="19.454532"
+     inkscape:cy="-4.3965932"
+     inkscape:window-x="0"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="g4468" />
+  <defs
+     id="defs4">
+    <linearGradient
+       x1="10.269"
+       y1="18.593"
+       x2="20.639999"
+       y2="20"
+       id="linearGradient2402"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.6441,0,0,0.6441,4.0504,-2.3906)">
+      <stop
+         id="stop8344"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop8346"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="10.269"
+       y1="18.593"
+       x2="20.639999"
+       y2="20"
+       id="linearGradient3771"
+       xlink:href="#linearGradient2402"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.97203134,0,0,0.97203134,3.3631616,-16.698381)" />
+    <linearGradient
+       x1="17.865271"
+       y1="14.35662"
+       x2="33.912136"
+       y2="26.929482"
+       id="linearGradient3794"
+       xlink:href="#linearGradient2402"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.1602483,0,0,1.1602483,0.49743072,-22.932367)" />
+    <linearGradient
+       x1="14.88041"
+       y1="12.186972"
+       x2="17.360123"
+       y2="10.559556"
+       id="linearGradient3803"
+       xlink:href="#linearGradient2402"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       x1="31.033985"
+       y1="12.87951"
+       x2="24.958994"
+       y2="0.16422372"
+       id="linearGradient3811"
+       xlink:href="#linearGradient2402"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <g
+     id="g4468"
+     transform="matrix(1.9084653,0,0,1.9084653,1.8947772,-70.675855)">
+    <g
+       id="layer1"
+       transform="translate(0,50)"
+       style="stroke-width:2.09592493;stroke-miterlimit:4;stroke-dasharray:none">
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2.09592493;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         id="path9348"
+         d="M 5.1382438,0.27187905 19.061403,9.5542257 V 25.796981 L 5.1382438,16.516436 V 0.27187905 z" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2.09592493;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         id="path9350"
+         d="M 21.38154,-9.0093868 35.304159,0.27187905 19.061403,9.5542257 5.1382438,0.27187905 21.38154,-9.0093868 z" />
+      <path
+         inkscape:connector-curvature="0"
+         style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2.09592493;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         id="path9352"
+         d="M 35.304159,0.27187905 V 16.516436 L 19.061403,25.796981 V 9.5542257 L 35.304159,0.27187905 z" />
+    </g>
+  </g>
+  <metadata
+     id="metadata15">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:date>2008-05-26T15:29:22</dc:date>
+        <dc:description />
+        <dc:source>https://openclipart.org/detail/17062/icon_cube_red-by-jean_victor_balin</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>jean_victor_balin</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>cube</rdf:li>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>item</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Shape/Cylinder.svg b/SRC/OpenMeca/Rsc/Img/Shape/Cylinder.svg
new file mode 100644
index 0000000..f6f1abd
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Shape/Cylinder.svg
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="80"
+   height="80"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.48.4 r9939"
+   version="1.0"
+   sodipodi:docname="Cylinder.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3214">
+      <stop
+         style="stop-color:#bd0000;stop-opacity:1;"
+         offset="0"
+         id="stop3216" />
+      <stop
+         style="stop-color:#bd0000;stop-opacity:0;"
+         offset="1"
+         id="stop3218" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3194">
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3196" />
+      <stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3198" />
+    </linearGradient>
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective10" />
+    <inkscape:perspective
+       id="perspective2390"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       sodipodi:type="inkscape:persp3d" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3194"
+       id="linearGradient3200"
+       x1="258.35654"
+       y1="297.09784"
+       x2="487.58066"
+       y2="297.09784"
+       gradientUnits="userSpaceOnUse"
+       spreadMethod="reflect" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3194"
+       id="linearGradient3212"
+       x1="384.36478"
+       y1="634.45886"
+       x2="224.61728"
+       y2="634.45886"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3214"
+       id="linearGradient3220"
+       x1="223.0714"
+       y1="321.41309"
+       x2="489.16129"
+       y2="321.41309"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-245.62882,42.565317)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3194"
+       id="linearGradient3224"
+       gradientUnits="userSpaceOnUse"
+       x1="384.36478"
+       y1="634.45886"
+       x2="224.61728"
+       y2="634.45886"
+       gradientTransform="matrix(0.9980779,0,0,1,-195.57336,40.913305)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3194"
+       id="linearGradient3230"
+       gradientUnits="userSpaceOnUse"
+       spreadMethod="reflect"
+       x1="258.35654"
+       y1="297.09784"
+       x2="487.58066"
+       y2="297.09784" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3194"
+       id="linearGradient3232"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.9980779,0,0,1,-195.57336,40.913305)"
+       x1="384.36478"
+       y1="634.45886"
+       x2="224.61728"
+       y2="634.45886" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="3.959798"
+     inkscape:cx="44.19519"
+     inkscape:cy="44.61105"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1598"
+     inkscape:window-height="835"
+     inkscape:window-x="0"
+     inkscape:window-y="32"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(195.5,-610.00504)">
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;stroke-linejoin:round"
+       d="m -174.26087,680.80117 c 0.0764,-0.11765 0.17855,-0.66822 0.22698,-1.22349 0.23913,-2.7415 -1.42549,-6.30254 -5.25742,-11.24696 -4.76491,-6.14827 -9.24511,-9.57612 -12.37313,-9.46684 l -0.54576,0.0191 27.06045,-20.33098 c 19.18781,-14.41616 27.18458,-20.38123 27.4872,-20.50365 0.61864,-0.25027 2.10667,-0.029 3.16631,0.47072 2.62487,1.23799 5.23118,3.60667 8.82767,8.02282 2.26992,2.78724 3.17009,4.05816 4.32549,6.10706 1.70019,3.015 2.31324,5.67263 1.6327,7.07798 -0.19976,0.4125 [...]
+       id="path3192" />
+    <path
+       inkscape:connector-curvature="0"
+       style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:4;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="m -188.02472,671.12381 c -2.29898,-3.14425 -3.32383,-4.89424 -4.13643,-7.06317 -0.69771,-1.86227 -0.80911,-3.6858 -0.29015,-4.7496 0.24478,-0.50175 0.48253,-0.6836 1.02821,-0.78641 1.98559,-0.37411 4.87429,1.12088 8.12342,4.20413 1.89747,1.80061 4.83919,5.32292 6.46619,7.74241 1.97453,2.93629 3.11024,5.54422 3.28154,7.5354 0.0242,0.28118 0.007,0.8059 -0.0378,1.16606 -0.0642,0.51419 -0.1265,0.74051 -0.28993,1.05382 -0.30782,0.59013 -0.41019,0.67768 -0.90098,0.77056 -0.25063,0.04 [...]
+       id="path3204" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/Shape/Ground.svg b/SRC/OpenMeca/Rsc/Img/Shape/Ground.svg
new file mode 100644
index 0000000..6a08335
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Shape/Ground.svg
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   id="Capa_1"
+   x="0px"
+   y="0px"
+   width="40"
+   height="40"
+   viewBox="0 0 40.000002 39.999999"
+   xml:space="preserve"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Ground.svg"><metadata
+     id="metadata41"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
+     id="defs39"><linearGradient
+       id="linearGradient3787"><stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3789" /><stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3791" /></linearGradient><radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3787-3"
+       id="radialGradient3793-5"
+       cx="268.84299"
+       cy="307.07483"
+       fx="268.84299"
+       fy="307.07483"
+       r="265.96835"
+       gradientTransform="matrix(0.12973005,0,0,0.12626552,5.3581411,5.282229)"
+       gradientUnits="userSpaceOnUse" /><linearGradient
+       id="linearGradient3787-3"><stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="0"
+         id="stop3789-7" /><stop
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1"
+         id="stop3791-6" /></linearGradient><radialGradient
+       r="265.96835"
+       fy="307.07483"
+       fx="268.84299"
+       cy="307.07483"
+       cx="268.84299"
+       gradientTransform="matrix(0.12973005,0,0,0.12626552,101.77316,5.7161893)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient4339"
+       xlink:href="#linearGradient3787-3"
+       inkscape:collect="always" /><radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,-78.175131,-118.50883)" /><linearGradient
+       id="linearGradient3755"><stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" /><stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" /></linearGradient></defs><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="803"
+     id="namedview37"
+     showgrid="false"
+     inkscape:zoom="5.0289114"
+     inkscape:cx="-13.716496"
+     inkscape:cy="18.18591"
+     inkscape:window-x="0"
+     inkscape:window-y="64"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="Capa_1" /><rect
+     transform="matrix(-0.78044407,0.62522561,0.62522561,0.78044407,0,0)"
+     y="11.992808"
+     x="-4.3709207"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-0-1"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.00000009;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     inkscape:transform-center-x="6.3273744"
+     inkscape:transform-center-y="-8.2958909" /><g
+     id="g7"
+     transform="translate(0,-490.93703)" /><g
+     id="g9"
+     transform="translate(0,-490.93703)" /><g
+     id="g11"
+     transform="translate(0,-490.93703)" /><g
+     id="g13"
+     transform="translate(0,-490.93703)" /><g
+     id="g15"
+     transform="translate(0,-490.93703)" /><g
+     id="g17"
+     transform="translate(0,-490.93703)" /><g
+     id="g19"
+     transform="translate(0,-490.93703)" /><g
+     id="g21"
+     transform="translate(0,-490.93703)" /><g
+     id="g23"
+     transform="translate(0,-490.93703)" /><g
+     id="g25"
+     transform="translate(0,-490.93703)" /><g
+     id="g27"
+     transform="translate(0,-490.93703)" /><g
+     id="g29"
+     transform="translate(0,-490.93703)" /><g
+     id="g31"
+     transform="translate(0,-490.93703)" /><g
+     id="g33"
+     transform="translate(0,-490.93703)" /><g
+     id="g35"
+     transform="translate(0,-490.93703)" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="27.639196"
+     x="0.088795602"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-9-5"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.0000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="20.447306"
+     x="-24.803482"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.0000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="22.245277"
+     x="-18.580416"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-2"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.0000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="24.043249"
+     x="-12.357342"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-0"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.0000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     transform="matrix(-0.92052094,0.39069323,0.39069323,0.92052094,0,0)"
+     y="25.841223"
+     x="-6.1342759"
+     height="13.059066"
+     width="2.7463272"
+     id="rect8123-9"
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.0000001;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /><rect
+     style="fill:#ff0000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:2.0000155;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+     id="rect8109"
+     width="39.354187"
+     height="4.7975802"
+     x="-16.681509"
+     y="24.015621"
+     transform="matrix(0.78105395,-0.62446355,0.62011876,0.78450795,0,0)" /></svg>
\ No newline at end of file
diff --git a/SRC/OpenMeca/Rsc/Img/Shape/Sphere.svg b/SRC/OpenMeca/Rsc/Img/Shape/Sphere.svg
new file mode 100644
index 0000000..8e9225f
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/Shape/Sphere.svg
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="80"
+   height="80"
+   id="svg2"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Sphere.svg">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="787"
+     id="namedview3043"
+     showgrid="false"
+     inkscape:zoom="2.69375"
+     inkscape:cx="-78.943442"
+     inkscape:cy="17.671565"
+     inkscape:window-x="0"
+     inkscape:window-y="80"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="layer1" />
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1;"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1,0,0,1.0443159,0,-19.350428)" />
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     transform="translate(-230.10998,-456.49673)"
+     id="layer1">
+    <path
+       d="m 420.00001,436.64789 a 94.285713,98.571426 0 1 1 -188.57143,0 94.285713,98.571426 0 1 1 188.57143,0 z"
+       transform="matrix(0.36211236,0,0,0.34636835,152.16481,345.25572)"
+       id="path2985"
+       style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:11.29455739;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/System.svg b/SRC/OpenMeca/Rsc/Img/System.svg
new file mode 100644
index 0000000..9798358
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/System.svg
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg11300"
+   sodipodi:docname="System.svg"
+   inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   inkscape:export-xdpi="90.000000"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:export-ydpi="90.000000"
+   inkscape:version="0.48.4 r9939"
+   version="1.1"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs3">
+    <linearGradient
+       id="linearGradient3055"
+       y2="6.7758002"
+       gradientUnits="userSpaceOnUse"
+       x2="20.631001"
+       gradientTransform="matrix(0.87827,0,0,0.87827,2.537,4.9677)"
+       y1="42.254002"
+       x1="19.648001"
+       inkscape:collect="always">
+      <stop
+         id="stop3051"
+         style="stop-color:#b6b6b6"
+         offset="0" />
+      <stop
+         id="stop2262"
+         style="stop-color:#f2f2f2"
+         offset=".5" />
+      <stop
+         id="stop2264"
+         style="stop-color:#fafafa"
+         offset=".67613" />
+      <stop
+         id="stop2268"
+         style="stop-color:#d8d8d8"
+         offset=".84052" />
+      <stop
+         id="stop2266"
+         style="stop-color:#f2f2f2"
+         offset=".875" />
+      <stop
+         id="stop3053"
+         style="stop-color:#dbdbdb"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3067"
+       y2="-4.3003001"
+       gradientUnits="userSpaceOnUse"
+       x2="25.291"
+       gradientTransform="matrix(0.87827,0,0,0.87827,5.3283,1.6502)"
+       y1="-3.6324"
+       x1="50.153"
+       inkscape:collect="always">
+      <stop
+         id="stop3063"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop3065"
+         style="stop-color:#000000"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3083"
+       y2="6.6286001"
+       gradientUnits="userSpaceOnUse"
+       x2="37.535"
+       gradientTransform="matrix(0.87827,0,0,0.87827,2.8475,5.5887)"
+       y1="13.603"
+       x1="38.228001"
+       inkscape:collect="always">
+      <stop
+         id="stop3079"
+         style="stop-color:#98a0a9"
+         offset="0" />
+      <stop
+         id="stop3081"
+         style="stop-color:#c3d0dd"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3093"
+       y2="39.443001"
+       gradientUnits="userSpaceOnUse"
+       x2="16.915001"
+       gradientTransform="matrix(0.87827,0,0,0.87827,2.537,4.9677)"
+       y1="32.284"
+       x1="9.7503004"
+       inkscape:collect="always">
+      <stop
+         id="stop3089"
+         style="stop-color:#3465a4"
+         offset="0" />
+      <stop
+         id="stop3095"
+         style="stop-color:#9fbce1"
+         offset="0" />
+      <stop
+         id="stop2242"
+         style="stop-color:#6b95ca"
+         offset="0" />
+      <stop
+         id="stop2244"
+         style="stop-color:#3d6aa5"
+         offset=".75" />
+      <stop
+         id="stop3091"
+         style="stop-color:#386eb4"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2263"
+       y2="33.195"
+       gradientUnits="userSpaceOnUse"
+       x2="10.651"
+       gradientTransform="matrix(1.0073,-0.026365,0.026365,1.0073,1.5934,0.079191)"
+       y1="35.688"
+       x1="12.005"
+       inkscape:collect="always">
+      <stop
+         id="stop2259"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop2261"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2271"
+       y2="38.268002"
+       gradientUnits="userSpaceOnUse"
+       x2="15.416"
+       gradientTransform="matrix(0.8781,-0.017324,0.017324,0.8781,2.1637,4.0679)"
+       y1="36.943001"
+       x1="14.018"
+       inkscape:collect="always">
+      <stop
+         id="stop2267"
+         style="stop-color:#000000"
+         offset="0" />
+      <stop
+         id="stop2269"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2256"
+       y2="9.6569004"
+       gradientUnits="userSpaceOnUse"
+       x2="40.859001"
+       y1="19.822001"
+       x1="31.177"
+       inkscape:collect="always">
+      <stop
+         id="stop2252"
+         style="stop-color:#ffffff"
+         offset="0" />
+      <stop
+         id="stop2254"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3055"
+       id="linearGradient3058"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.87827,0,0,0.87827,2.537,4.9677)"
+       x1="19.648001"
+       y1="42.254002"
+       x2="20.631001"
+       y2="6.7758002" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3067"
+       id="linearGradient3060"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.87827,0,0,0.87827,5.3283,1.6502)"
+       x1="50.153"
+       y1="-3.6324"
+       x2="25.291"
+       y2="-4.3003001" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3055"
+       id="linearGradient3068"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.87827,0,0,0.87827,-2.213,9.2177)"
+       x1="19.648001"
+       y1="42.254002"
+       x2="20.631001"
+       y2="6.7758002" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="0"
+     pagecolor="#ffffff"
+     inkscape:showpageshadow="false"
+     inkscape:grid-bbox="true"
+     inkscape:zoom="8"
+     inkscape:cx="-2.2897361"
+     inkscape:window-height="867"
+     showgrid="false"
+     borderopacity="0.25490196"
+     inkscape:current-layer="layer1"
+     stroke="#204a87"
+     inkscape:cy="19.062697"
+     inkscape:window-x="0"
+     inkscape:window-width="1598"
+     inkscape:pageopacity="0.0"
+     inkscape:document-units="px"
+     fill="#3465a4"
+     inkscape:window-maximized="0" />
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,-8)">
+    <path
+       inkscape:connector-curvature="0"
+       id="path2140"
+       sodipodi:nodetypes="cczcccccccccsc"
+       style="color:#000000;fill:url(#linearGradient3068);stroke:#000000;stroke-opacity:1;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 13.157,25.466 18.992,19.431 c 0.769,0.879 3.204,1.557 4.831,0 1.571,-1.503 1.207,-3.622 -0.33,-5.159 L 18.426,20.196 C 20.676,13.9461 16.122,8.696 10.247,9.822 L 8.985,10.9742 12.937,14.707 13.157,18 10.206,20.694 6.679,20.306 3.0566,16.903 1.7865,18.157 c -0.5908,5.642 5.3075,10.684 11.37,7.309 z" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path3057"
+       sodipodi:nodetypes="cczccccccccccc"
+       style="opacity:0.42614004;color:#000000;fill:none;stroke:#ffffff"
+       d="M 13.367,24.19 32.57,44.218 c 0.595,0.68 2.48,1.205 3.74,0 1.216,-1.164 0.935,-2.805 -0.255,-3.995 L 17.563,20.602 c 1.5,-6.4998 -1.859,-10.004 -6.859,-9.8795 l -0.27,0.2734 3.603,3.2363 0.13,4.1818 -3.614,3.298 -4.242,-0.458 -3.1764,-2.991 -0.3527,0.43 c -0.3125,5.969 6.4921,8.685 10.585,5.497 z" />
+    <path
+       id="path2146"
+       sodipodi:rx="1.375"
+       sodipodi:ry="1.375"
+       style="color:#000000;fill:#ffffff;stroke:#a1a1a1;stroke-width:1.13859999"
+       sodipodi:type="arc"
+       d="m 43.25,37.5 a 1.375,1.375 0 1 1 -2.75,0 1.375,1.375 0 1 1 2.75,0 z"
+       transform="matrix(0.87827,0,0,0.87827,-2.3228,9.3275)"
+       sodipodi:cy="37.5"
+       sodipodi:cx="41.875" />
+    <rect
+       id="rect3059"
+       style="opacity:0.17045001000000001;color:#000000;fill:none;stroke:#000000;stroke-width:1;stroke-opacity:1"
+       transform="matrix(0.69794047,0.71615578,-0.71615578,0.69794047,0,0)"
+       rx="0.88388002"
+       ry="0.88388002"
+       height="2.0555"
+       width="23.268"
+       y="3.7495868"
+       x="27.913445" />
+  </g>
+  <metadata
+     id="metadata52">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title></dc:title>
+        <dc:date>2010-03-29T09:07:18</dc:date>
+        <dc:description>"System preferences" icon from <a href="http://tango.freedesktop.org/Tango_Desktop_Project"> Tango Project </a> 
\n<br><br>
\nSince version 0.8.90 Tango Project icons are Public Domain: <a href="http://tango.freedesktop.org/Frequently_Asked_Questions#Terms_of_Use.3F"> Tango Project FAQ </a></dc:description>
+        <dc:source>https://openclipart.org/detail/35431/tango-preferences-system-by-warszawianka</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>warszawianka</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>externalsource</rdf:li>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>preferences</rdf:li>
+            <rdf:li>screwdriver</rdf:li>
+            <rdf:li>settings</rdf:li>
+            <rdf:li>spanner</rdf:li>
+            <rdf:li>tango</rdf:li>
+            <rdf:li>tool</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/SystemSetting/Gravity.svg b/SRC/OpenMeca/Rsc/Img/SystemSetting/Gravity.svg
new file mode 100644
index 0000000..07ad575
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/SystemSetting/Gravity.svg
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg2"
+   viewBox="0 0 40 40"
+   inkscape:export-ydpi="90"
+   inkscape:export-xdpi="90"
+   version="1.0"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   sodipodi:docname="Gravity.svg"
+   inkscape:export-filename="C:\joanna\Gfx\drawings_vector\nature_plants\fruits\papapishu_pear_6thck.png"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:version="0.32"
+   inkscape:label="Pozadí"
+   width="100%"
+   height="100%">
+  <defs
+     id="defs1928">
+    <radialGradient
+       id="radialGradient2405"
+       gradientUnits="userSpaceOnUse"
+       cy="417.75"
+       cx="167.27"
+       gradientTransform="matrix(1.0114,0.98335,-0.87434,0.89926,356.17,-95.72)"
+       r="44.668999"
+       inkscape:collect="always">
+      <stop
+         id="stop7102"
+         style="stop-color:#ff6000"
+         offset="0" />
+      <stop
+         id="stop7104"
+         style="stop-color:#c00000"
+         offset="1" />
+    </radialGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     inkscape:window-y="32"
+     pagecolor="#ffffff"
+     inkscape:window-height="999"
+     inkscape:zoom="2.9775825"
+     inkscape:window-x="1600"
+     borderlayer="true"
+     showgrid="false"
+     borderopacity="1.0"
+     inkscape:current-layer="layer3"
+     inkscape:cx="0.20900547"
+     inkscape:cy="15.312985"
+     inkscape:window-width="1918"
+     showborder="true"
+     inkscape:pageopacity="0.0"
+     inkscape:document-units="px"
+     inkscape:window-maximized="0" />
+  <g
+     id="layer1"
+     inkscape:label="Vrstva 1"
+     inkscape:groupmode="layer"
+     transform="translate(-68.374,-444.09)">
+    <g
+       id="layer2"
+       style="display:none"
+       inkscape:groupmode="layer">
+      <rect
+         id="rect2679"
+         style="opacity:0.36207;fill:#d45500;fill-rule:evenodd;display:inline"
+         transform="translate(68.374,356.09)"
+         height="100.75"
+         width="162.55"
+         y="15.828"
+         x="-14.777" />
+    </g>
+    <g
+       id="layer3"
+       inkscape:label="naj"
+       inkscape:groupmode="layer">
+      <path
+         sodipodi:sides="9"
+         inkscape:flatsided="false"
+         inkscape:rounded="0.01"
+         sodipodi:cx="4.037106"
+         sodipodi:cy="91.666046"
+         inkscape:randomized="0"
+         sodipodi:arg1="0.29145679"
+         sodipodi:arg2="0.64052264"
+         transform="matrix(0.29325789,0.21508197,-0.21508197,0.29325789,100.10465,449.31446)"
+         inkscape:transform-center-y="-0.7647213"
+         inkscape:transform-center-x="-2.56372"
+         sodipodi:r1="7.4379921"
+         d="m 11.16141,93.803337 c -0.0133,0.04432 -4.5919123,-0.307471 -4.6195668,-0.270369 -0.027654,0.0371 1.6176487,4.324346 1.5789722,4.349753 -0.038676,0.02541 -3.3199703,-3.187162 -3.3650038,-3.176515 -0.045033,0.01065 -1.5404453,4.352445 -1.5864041,4.347047 -0.045959,-0.0054 -0.494577,-4.575543 -0.5359178,-4.596335 -0.041341,-0.02079 -3.9777479,2.343988 -4.0094844,2.310311 -0.031737,-0.03368 2.5622344,-3.822977 2.5439301,-3.865478 -0.018304,-0.0425 -4.5538179,-0.761248 -4.5564823 [...]
+         sodipodi:type="star"
+         style="fill:#000000;fill-rule:evenodd;stroke:#000000;stroke-linecap:round;stroke-linejoin:round"
+         sodipodi:r2="3.1239569"
+         id="path7172" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 93.776674,451.77292 c 2.509369,-3.73496 5.346046,-5.00783 8.360926,-4.98237"
+         style="fill:none;stroke:#000000;stroke-width:2.18205953;stroke-linecap:round"
+         sodipodi:nodetypes="cc"
+         id="path6371" />
+      <path
+         inkscape:connector-curvature="0"
+         d="m 92.827479,453.50766 c -6.09522,-11.67039 -15.492623,-4.42959 -18.211106,-0.14548 -6.279603,9.8811 -2.307891,23.79536 7.857233,22.12245 6.437076,9.32831 19.111204,1.48017 22.264284,-6.83712 2.54937,-6.7171 1.29469,-17.37647 -11.910411,-15.13985 z"
+         style="fill:#d55f53;fill-rule:evenodd;stroke:#000000;stroke-width:1.5;fill-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+         sodipodi:nodetypes="cscsc"
+         id="path6364" />
+    </g>
+  </g>
+  <metadata
+     id="metadata16">
+    <rdf:RDF>
+      <cc:Work>
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" />
+        <dc:publisher>
+          <cc:Agent
+             rdf:about="http://openclipart.org/">
+            <dc:title>Openclipart</dc:title>
+          </cc:Agent>
+        </dc:publisher>
+        <dc:title />
+        <dc:date>2009-03-15T15:12:54</dc:date>
+        <dc:description>Yummy red apple with thick black contour.</dc:description>
+        <dc:source>https://openclipart.org/detail/22309/apple-icon-by-pitr-22309</dc:source>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>pitr</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:subject>
+          <rdf:Bag>
+            <rdf:li>apple</rdf:li>
+            <rdf:li>contour</rdf:li>
+            <rdf:li>food</rdf:li>
+            <rdf:li>fruit</rdf:li>
+            <rdf:li>icon</rdf:li>
+            <rdf:li>minimalistic</rdf:li>
+            <rdf:li>red</rdf:li>
+          </rdf:Bag>
+        </dc:subject>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/SystemSetting/Scales.svg b/SRC/OpenMeca/Rsc/Img/SystemSetting/Scales.svg
new file mode 100644
index 0000000..c3ed5e7
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/SystemSetting/Scales.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="svg5722"
+   sodipodi:docname="Scale.svg"
+   xml:space="preserve"
+   viewBox="0 0 40 40"
+   sodipodi:version="0.32"
+   version="1.0"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"><defs
+     id="defs36" /><sodipodi:namedview
+     id="base"
+     bordercolor="#666666"
+     inkscape:pageshadow="2"
+     guidetolerance="10.0"
+     pagecolor="#ffffff"
+     gridtolerance="10.0"
+     inkscape:zoom="4.3160493"
+     objecttolerance="10.0"
+     borderopacity="1.0"
+     inkscape:current-layer="g5729"
+     inkscape:cx="-1.7979421"
+     inkscape:cy="2.3722535"
+     inkscape:window-y="16"
+     inkscape:window-x="0"
+     inkscape:window-height="851"
+     showgrid="false"
+     inkscape:pageopacity="0.0"
+     inkscape:window-width="1598"
+     inkscape:window-maximized="0" /><g
+     id="g5729"
+     inkscape:label="guide"
+     inkscape:groupmode="layer"
+     transform="matrix(1.25,0,0,-1.25,-10.688,712.86)"><path
+       inkscape:connector-curvature="0"
+       d="m -68.69723,1163.9941 h 0.11961 -0.11961"
+       style="fill:#f9a749"
+       id="path5755" /><text
+       transform="scale(1,-1)"
+       style="font-size:152.67552185px"
+       x="-204.51369"
+       y="-836.37433"
+       id="text6003"><tspan
+         x="-204.51369"
+         y="-836.37433"
+         inkscape:font-specification="ZapfDingbats"
+         style="font-size:139.95698547px;fill:#2857af;font-family:ZapfDingbats"
+         sodipodi:role="line"
+         id="tspan6005" /></text>
+<g
+       id="g3041"
+       transform="matrix(0.26665071,0,0,0.26665071,4.0712855,398.45022)"
+       style="stroke:#000000;stroke-opacity:1;stroke-width:0.99905978;stroke-miterlimit:4;stroke-dasharray:none"><path
+         id="path6129"
+         style="fill:#1f57af;stroke:#000000;stroke-opacity:1;stroke-width:0.99905978;stroke-miterlimit:4;stroke-dasharray:none"
+         d="m 132.89878,624.18092 -0.35883,-2.19285 -89.66763,-81.4677 -4.79769,-2.24601 c -5.38245,5.95392 -10.71174,11.86797 -16.09419,17.8086 1.1961,2.17956 1.71441,4.9173 3.14973,6.71145 l 34.51413,26.68632 c 0.17277,0.82398 1.18281,0.70437 1.63467,1.20939 l 32.66682,25.5168 27.15147,20.62608 1.62138,0.22593 c 3.37566,-4.30596 7.08357,-8.33283 10.18014,-12.87801"
+         inkscape:connector-curvature="0" /><path
+         id="path6155"
+         style="fill:#ffffff;stroke:#000000;stroke-opacity:1;stroke-width:0.99905978;stroke-miterlimit:4;stroke-dasharray:none"
+         d="m 79.85839,579.12782 -39.00615,-35.01915 -14.68545,16.6125 3.13644,2.43207 4.29267,-5.68812 c 0.59805,-0.0399 0.7974,0.69108 0.78411,1.08978 -1.28913,1.76757 -2.55168,3.5883 -3.97371,5.27613 0.71766,0.98346 2.03337,1.76757 3.0567,2.72445 3.4554,-4.19964 6.47223,-8.61192 10.31304,-12.41286 0.69108,0.5316 1.35558,0.99675 1.91376,1.67454 -3.56172,3.88068 -5.72799,8.79798 -9.48906,12.47931 0.45186,0.90372 1.82073,1.64796 2.77761,2.48523 1.48848,-1.71441 2.59155,-3.68133 4.47873,- [...]
+         inkscape:connector-curvature="0" /></g></g><metadata
+     id="metadata34"><rdf:RDF><cc:Work><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" /><dc:publisher><cc:Agent
+             rdf:about="http://openclipart.org/"><dc:title>Openclipart</dc:title></cc:Agent></dc:publisher><dc:title></dc:title><dc:date>2007-11-09T04:59:43</dc:date><dc:description>an image from the US government EPA "Sunwise" program. I converted it from PDF format, and removed all the "sunwise" logos. the source link is here - http://www.epa.gov/sunwise/doc/guide.pdf</dc:description><dc:source>https://openclipart.org/detail/8055/ruler-and-calculator-by-ryanlerch</d [...]
+         rdf:about="http://creativecommons.org/licenses/publicdomain/"><cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata></svg>
\ No newline at end of file
diff --git a/SRC/OpenMeca/Rsc/Img/SystemSetting/Scene.svg b/SRC/OpenMeca/Rsc/Img/SystemSetting/Scene.svg
new file mode 100644
index 0000000..7cfdcb5
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/SystemSetting/Scene.svg
@@ -0,0 +1,573 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="40"
+   height="40"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="Scene.svg">
+  <defs
+     id="defs4">
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4352">
+      <stop
+         style="stop-color:#925228;stop-opacity:1"
+         offset="0"
+         id="stop4354" />
+      <stop
+         style="stop-color:#deaa87;stop-opacity:0"
+         offset="1"
+         id="stop4356" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4340">
+      <stop
+         style="stop-color:#005c00;stop-opacity:1"
+         offset="0"
+         id="stop4342" />
+      <stop
+         style="stop-color:#003200;stop-opacity:1"
+         offset="1"
+         id="stop4344" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4332">
+      <stop
+         style="stop-color:#472e26;stop-opacity:1;"
+         offset="0"
+         id="stop4334" />
+      <stop
+         style="stop-color:#37241e;stop-opacity:1"
+         offset="1"
+         id="stop4336" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4324">
+      <stop
+         style="stop-color:#3a3a33;stop-opacity:1;"
+         offset="0"
+         id="stop4326" />
+      <stop
+         style="stop-color:#292924;stop-opacity:1"
+         offset="1"
+         id="stop4328" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4316">
+      <stop
+         style="stop-color:#cfbfae;stop-opacity:1;"
+         offset="0"
+         id="stop4318" />
+      <stop
+         style="stop-color:#604d39;stop-opacity:1"
+         offset="1"
+         id="stop4320" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4308">
+      <stop
+         style="stop-color:#ccb956;stop-opacity:1;"
+         offset="0"
+         id="stop4310" />
+      <stop
+         style="stop-color:#706322;stop-opacity:1"
+         offset="1"
+         id="stop4312" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4300">
+      <stop
+         style="stop-color:#c9584c;stop-opacity:1;"
+         offset="0"
+         id="stop4302" />
+      <stop
+         style="stop-color:#56201a;stop-opacity:1"
+         offset="1"
+         id="stop4304" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4292">
+      <stop
+         style="stop-color:#395ebd;stop-opacity:1"
+         offset="0"
+         id="stop4294" />
+      <stop
+         style="stop-color:#07233d;stop-opacity:1"
+         offset="1"
+         id="stop4296" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4284">
+      <stop
+         style="stop-color:#81513e;stop-opacity:1;"
+         offset="0"
+         id="stop4286" />
+      <stop
+         style="stop-color:#3f281e;stop-opacity:1"
+         offset="1"
+         id="stop4288" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4276">
+      <stop
+         style="stop-color:#c5574b;stop-opacity:1;"
+         offset="0"
+         id="stop4278" />
+      <stop
+         style="stop-color:#4f1f1a;stop-opacity:1"
+         offset="1"
+         id="stop4280" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4268">
+      <stop
+         style="stop-color:#342c29;stop-opacity:1;"
+         offset="0"
+         id="stop4270" />
+      <stop
+         style="stop-color:#211c1a;stop-opacity:1"
+         offset="1"
+         id="stop4272" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient4260">
+      <stop
+         style="stop-color:#4c7b57;stop-opacity:1;"
+         offset="0"
+         id="stop4262" />
+      <stop
+         style="stop-color:#27402d;stop-opacity:1"
+         offset="1"
+         id="stop4264" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       id="linearGradient3456">
+      <stop
+         style="stop-color:#aa7556;stop-opacity:1"
+         offset="0"
+         id="stop3458" />
+      <stop
+         style="stop-color:#7a4d3b;stop-opacity:1"
+         offset="1"
+         id="stop3460" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       y2="190.89999"
+       x2="375.04001"
+       gradientTransform="translate(-477.51,501.33)"
+       y1="188.02"
+       gradientUnits="userSpaceOnUse"
+       x1="372.26999"
+       id="linearGradient3562">
+      <stop
+         offset="0"
+         style="stop-color:#000000;stop-opacity:0"
+         id="stop4077" />
+      <stop
+         offset=".28701"
+         style="stop-color:#ffffff"
+         id="stop4153" />
+      <stop
+         offset="0.553"
+         style="stop-color:#b86e17;stop-opacity:.60209"
+         id="stop4083" />
+      <stop
+         offset=".80732"
+         style="stop-color:#e9a049"
+         id="stop4155" />
+      <stop
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0"
+         id="stop4079" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient16134">
+      <stop
+         offset="0"
+         style="stop-color:#9d9d9d"
+         id="stop16136" />
+      <stop
+         offset=".46938"
+         style="stop-color:#aeaeae"
+         id="stop16146" />
+      <stop
+         offset=".59982"
+         style="stop-color:#d3d3d3"
+         id="stop16142" />
+      <stop
+         offset=".76320"
+         style="stop-color:#999999"
+         id="stop16148" />
+      <stop
+         offset="1"
+         style="stop-color:#9e9e9e"
+         id="stop16138" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       y2="796.96997"
+       x2="252.92"
+       gradientTransform="matrix(0.4471,-0.43614,0.46038,0.4491,-584.29,451.84)"
+       y1="784.85999"
+       gradientUnits="userSpaceOnUse"
+       x1="252.92"
+       id="linearGradient3556">
+      <stop
+         offset="0"
+         style="stop-color:#e79637"
+         id="stop3719" />
+      <stop
+         offset=".46938"
+         style="stop-color:#eaa24f"
+         id="stop3721" />
+      <stop
+         offset=".59982"
+         style="stop-color:#f0ba7a"
+         id="stop3723" />
+      <stop
+         offset=".76320"
+         style="stop-color:#cb7919"
+         id="stop3725" />
+      <stop
+         offset="1"
+         style="stop-color:#e2871b"
+         id="stop3727" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3556"
+       id="linearGradient3298"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.4471,-0.43614,0.46038,0.4491,-584.29,451.84)"
+       x1="252.92"
+       y1="784.85999"
+       x2="252.92"
+       y2="796.96997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient16134"
+       id="linearGradient3300"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.44769,-0.43672,0.4613,0.44999,-567.68,885.41)"
+       x1="804.42999"
+       y1="286.01001"
+       x2="804.37"
+       y2="293.66" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient16134"
+       id="linearGradient3302"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.49526,-0.48312,0.46995,0.45843,-668.19,978.57)"
+       x1="804.42999"
+       y1="286.01001"
+       x2="804.37"
+       y2="293.66" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3562"
+       id="linearGradient3304"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-477.51,501.33)"
+       x1="372.26999"
+       y1="188.02"
+       x2="375.04001"
+       y2="190.89999" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3556"
+       id="linearGradient3348"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.4471,-0.43614,0.46038,0.4491,-584.29,451.84)"
+       x1="252.92"
+       y1="784.85999"
+       x2="252.92"
+       y2="796.96997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient16134"
+       id="linearGradient3350"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.44769,-0.43672,0.4613,0.44999,-567.68,885.41)"
+       x1="804.42999"
+       y1="286.01001"
+       x2="804.37"
+       y2="293.66" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient16134"
+       id="linearGradient3352"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.49526,-0.48312,0.46995,0.45843,-668.19,978.57)"
+       x1="804.42999"
+       y1="286.01001"
+       x2="804.37"
+       y2="293.66" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3562"
+       id="linearGradient3354"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-477.51,501.33)"
+       x1="372.26999"
+       y1="188.02"
+       x2="375.04001"
+       y2="190.89999" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3456"
+       id="linearGradient3462"
+       x1="739.43164"
+       y1="232.11832"
+       x2="268.70059"
+       y2="935.18451"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4260"
+       id="radialGradient4266"
+       cx="211.48114"
+       cy="812.67035"
+       fx="211.48114"
+       fy="812.67035"
+       r="73.212227"
+       gradientTransform="matrix(2.3514089,-1.6336732e-7,1.29505e-7,1.8640153,-253.47271,-694.07837)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4268"
+       id="radialGradient4274"
+       cx="91.080643"
+       cy="663.7984"
+       fx="91.080643"
+       fy="663.7984"
+       r="76.076988"
+       gradientTransform="matrix(2.0503083,-2.91776e-8,1.6388796e-8,1.1516398,-97.683065,-52.170912)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4276"
+       id="radialGradient4282"
+       cx="126.11601"
+       cy="537.59753"
+       fx="126.11601"
+       fy="537.59753"
+       r="50.867912"
+       gradientTransform="matrix(3.6214204,0,0,2.9022007,-336.664,-994.33403)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4284"
+       id="radialGradient4290"
+       cx="269.94815"
+       cy="366.50302"
+       fx="269.94815"
+       fy="366.50302"
+       r="45.434731"
+       gradientTransform="matrix(2.1337775,0.08139579,-0.0576646,1.511668,-284.92689,-209.50053)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4292"
+       id="radialGradient4298"
+       cx="376.35733"
+       cy="293.41122"
+       fx="376.35733"
+       fy="293.41122"
+       r="51.434158"
+       gradientTransform="matrix(3.160559,-0.01855801,0.00622322,1.0598602,-814.96815,-10.579208)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4300"
+       id="radialGradient4306"
+       cx="757.31006"
+       cy="580.68445"
+       fx="757.31006"
+       fy="580.68445"
+       r="71.499641"
+       gradientTransform="matrix(2.3648988,-5.7077621e-7,4.1123885e-7,1.7038872,-1033.6519,-408.73595)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4308"
+       id="radialGradient4314"
+       cx="877.12036"
+       cy="420.05679"
+       fx="877.12036"
+       fy="420.05679"
+       r="57.290901"
+       gradientTransform="matrix(2.1316059,-2.4490042e-7,1.8350401e-7,1.5972134,-998.61556,-222.57904)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4316"
+       id="radialGradient4322"
+       cx="928.06909"
+       cy="317.69482"
+       fx="928.06909"
+       fy="317.69482"
+       r="48.359505"
+       gradientTransform="matrix(2.5524679,0,0,2.1291157,-1437.7611,-356.54616)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4324"
+       id="radialGradient4330"
+       cx="872.1875"
+       cy="233.04945"
+       fx="872.1875"
+       fy="233.04945"
+       r="36.131989"
+       gradientTransform="matrix(2.3620592,-2.5319346e-7,2.0729837e-7,1.9339007,-1259.2139,-195.6245)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4332"
+       id="radialGradient4338"
+       cx="554.57544"
+       cy="737.61755"
+       fx="554.57544"
+       fy="737.61755"
+       r="76.257851"
+       gradientTransform="matrix(1.7711984,-3.0652706e-8,1.952624e-8,1.1282803,-427.68765,-94.621753)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4340"
+       id="radialGradient4348"
+       cx="189.88535"
+       cy="450.92615"
+       fx="189.88535"
+       fy="450.92615"
+       r="59.344151"
+       gradientTransform="matrix(1.240785,-9.8271365e-8,8.530174e-8,1.0770291,-45.721573,-34.734408)"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient4352"
+       id="radialGradient4358"
+       cx="351.26431"
+       cy="455.67578"
+       fx="351.26431"
+       fy="455.67578"
+       r="561.79431"
+       gradientTransform="matrix(0.78283252,-0.48413644,0.33400604,0.54007661,-17.19108,481.85992)"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3456"
+       id="linearGradient4209"
+       gradientUnits="userSpaceOnUse"
+       x1="739.43164"
+       y1="232.11832"
+       x2="268.70059"
+       y2="935.18451"
+       gradientTransform="matrix(0.03526053,-0.00809998,0.00809998,0.03526053,-2.5993681,1016.1156)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="3.959798"
+     inkscape:cx="-49.008851"
+     inkscape:cy="-14.240633"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1918"
+     inkscape:window-height="951"
+     inkscape:window-x="1600"
+     inkscape:window-y="64"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Calque 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(3.3621271e-7,-1012.3622)">
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;fill:url(#linearGradient4209);fill-opacity:1;stroke:none;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 27.894767,1015.768 c -2.360056,0.5603 -4.014615,2.1266 -4.352699,4.0288 -0.673848,3.7911 -5.216474,2.6235 -6.332592,1.9848 -1.680807,-0.9618 -3.558907,-0.7045 -5.539707,0.5835 -2.7047869,1.7588 -6.6986382,6.7109 -8.6297988,10.6793 -4.025304,8.2716 -2.0404681,13.2711 5.0321248,15.4418 8.960346,2.7502 21.72256,-4.5049 27.833088,-15.0372 4.266003,-7.353 3.229577,-15.3439 -2.764581,-17.342 -1.930467,-0.6436 -3.73298,-0.6982 -5.245835,-0.339 z m -7.396888,9.229 c 0.720512,-0.1693  [...]
+       id="path2996" />
+    <path
+       inkscape:connector-curvature="0"
+       id="path4350"
+       d="m 27.894767,1015.768 c -2.360056,0.5603 -4.014615,2.1266 -4.352699,4.0288 -0.673848,3.7911 -5.216474,2.6235 -6.332592,1.9848 -1.680807,-0.9618 -3.558907,-0.7045 -5.539707,0.5835 -2.7047869,1.7588 -6.6986382,6.7109 -8.6297988,10.6793 -4.025304,8.2716 -2.0404681,13.2711 5.0321248,15.4418 8.960346,2.7502 21.72256,-4.5049 27.833088,-15.0372 4.266003,-7.353 3.229577,-15.3439 -2.764581,-17.342 -1.930467,-0.6436 -3.73298,-0.6982 -5.245835,-0.339 z m -7.396888,9.229 c 0.720512,-0.1693  [...]
+       style="color:#000000;fill:#ceb99f;fill-opacity:1;stroke:#000000;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
+    <path
+       style="color:#000000;fill:#f346f7;fill-opacity:1;stroke:#000000;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 29.538092,1026.1052 c -0.670494,-0.734 0.08026,-1.6883 0.589488,-2.271 0.674153,-0.7319 1.798305,-1.253 2.742463,-0.7097 0.810455,0.3161 1.795695,1.1229 1.31733,2.0969 -0.327948,0.8673 -1.287137,1.0572 -2.038469,1.3942 -0.717558,0.428 -1.64106,0.469 -2.285505,-0.108 -0.136256,-0.107 -0.260233,-0.2389 -0.325307,-0.4024 z"
+       id="path3360"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:#26f4f7;fill-opacity:1;stroke:#000000;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 26.7216,1017.8741 c -0.135793,0.1229 -0.578041,0.2413 -0.677208,0.4296 -0.227088,0.4312 -0.02238,0.9975 0.404587,1.3882 0.657149,0.6437 1.833137,0.6541 2.522349,0.058 0.422079,-0.3794 0.547755,-1.0565 0.208016,-1.5304 -0.370157,-0.4971 -0.926363,-0.8896 -1.420755,-1.2262 -0.506323,0.038 -0.698238,0.5746 -1.036989,0.881 z"
+       id="path3364"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ssccccs" />
+    <path
+       style="color:#000000;fill:#f3f45e;fill-opacity:1;stroke:#000000;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 5.4069717,1038.4384 c 0.814789,-0.2981 1.7756215,-0.3854 2.4003227,0.3216 0.6520963,0.1358 1.7238768,-0.055 1.636426,0.9651 -0.030067,0.8302 -0.4833065,1.6827 -1.1877832,2.1337 -0.7894245,0.302 -1.5247788,0.715 -2.3091886,1.0361 -0.9867147,0.3394 -2.2088384,-0.1541 -2.7027917,-1.0611 -0.1208736,-0.7836 0.4243002,-1.5034 0.7347146,-2.1823 0.4200385,-0.4561 0.9142505,-0.8725 1.4283002,-1.2131 z"
+       id="path3370"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:#d74923;fill-opacity:1;stroke:#000000;stroke-width:1.5;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 20.355037,1037.8659 c 0.382967,-0.7313 -0.203651,-1.7167 0.330642,-2.3207 0.655727,-0.4481 1.546776,-0.7309 2.307376,-0.3728 0.834003,0.4047 1.70959,-0.541 2.520518,-0.01 0.90284,0.6356 -0.383143,1.6565 0.185228,2.4054 0.797218,0.2489 0.925034,1.5099 -0.100438,1.4741 -1.071248,0.4582 -1.953226,1.6986 -3.251651,1.3437 -0.933675,-0.3306 -2.124546,-0.6493 -2.521528,-1.6666 -0.165945,-0.3982 0.125291,-0.7912 0.529853,-0.8569 z"
+       id="path3372"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:#f3f4bf;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 30.534921,1029.704 c 0.833184,0.2419 1.659317,0.7403 1.744393,1.6799 0.445234,0.4954 1.422054,0.976 0.747798,1.7464 -0.515609,0.6514 -1.385502,1.0703 -2.220268,1.0168 -0.815047,-0.2238 -1.652209,-0.3261 -2.474519,-0.5316 -0.996205,-0.3104 -1.689188,-1.4315 -1.550504,-2.455 0.366363,-0.7031 1.23182,-0.9606 1.883845,-1.3241 0.608518,-0.119 1.253324,-0.1621 1.869255,-0.1324 z"
+       id="path3370-0"
+       inkscape:connector-curvature="0" />
+    <path
+       style="color:#000000;fill:#4946f7;fill-opacity:1;stroke:#000000;stroke-width:1.5;stroke-opacity:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 13.030047,1045.2932 c -0.960879,-0.255 -0.845206,-1.4637 -0.731827,-2.2292 0.171465,-0.9802 0.835462,-2.0263 1.92347,-2.0797 0.852699,-0.1722 2.117721,-0.026 2.24185,1.0519 0.192986,0.9069 -0.511286,1.5852 -0.961169,2.2749 -0.372274,0.748 -1.127022,1.2818 -1.981109,1.1448 -0.172474,-0.016 -0.34808,-0.06 -0.491215,-0.1627 z"
+       id="path3360-2"
+       inkscape:connector-curvature="0" />
+  </g>
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Img/SystemSetting/Simulation.svg b/SRC/OpenMeca/Rsc/Img/SystemSetting/Simulation.svg
new file mode 100644
index 0000000..80fb2a1
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/SystemSetting/Simulation.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   id="Layer_1"
+   xml:space="preserve"
+   viewBox="0 0 40 40"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   width="100%"
+   height="100%"
+   sodipodi:docname="Simulation.svg"><defs
+     id="defs17"><filter
+       inkscape:collect="always"
+       id="filter5640"><feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.69899998"
+         id="feGaussianBlur5642" /></filter></defs><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1918"
+     inkscape:window-height="967"
+     id="namedview15"
+     showgrid="false"
+     inkscape:zoom="3.4196148"
+     inkscape:cx="-52.6571"
+     inkscape:cy="41.874986"
+     inkscape:window-x="1600"
+     inkscape:window-y="48"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="Layer_1" /><g
+     id="g2993"
+     transform="matrix(0.54744096,0,0,0.54511481,2.0502467,-16.489962)"
+     style="stroke-width:2.74586148;stroke-miterlimit:4;stroke-dasharray:none"><path
+       style="fill:#83848f;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:2.74586148;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 40.8,33.6 c -0.4,-0.2 -0.7,-0.3 -1,-0.3 -1.2,-0.3 -2.4,-0.5 -3.6,-0.7 -1.1,2.7 -2,5.3 -2.9,7.9 h -1.4 -0.4 c -1.2,0.1 -2.3,0.2 -3.4,0.4 -0.9,0.1 -1.8,0.4 -2.7,0.7 -1.6,-2.3 -3.3,-4.6 -4.9,-6.8 l -0.1,-0.1 c -0.6,0.2 -1.2,0.4 -1.7,0.7 -1,0.4 -1.9,0.9 -2.8,1.5 -1.4,0.7 -2.7,1.6 -3.9,2.7 v 0.1 c 1.2,2.5 2.3,5 3.5,7.5 -0.7,0.7 -1.3,1.3 -1.9,2.1 -0.8,0.8 -1.5,1.8 -2.1,2.8 -0.3,0.4 -0.5,0.8 -0.7,1.3 C 8,52.9 5.2,52.4 2.4,52 c -0.5,1.2 -1,2.4 -1.4,3.7 -0.4,2 -0.8,3.9 -1,5.8 l 7.8,3  [...]
+       id="path9"
+       inkscape:connector-curvature="0" /><path
+       style="fill:#83848f;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:2.74586148;stroke-miterlimit:4;stroke-dasharray:none"
+       d="m 22.8,62.4 c -0.8,2.7 -0.5,5.3 0.9,7.7 h 0.1 c 1.4,2.5 3.5,4 6.2,4.8 2.7,0.7 5.3,0.4 7.8,-1 2.5,-1.5 4,-3.5 4.8,-6.2 v -0.1 c 0.7,-2.7 0.3,-5.3 -1.1,-7.7 -1.4,-2.5 -3.5,-4.1 -6.2,-4.8 -2.7,-0.8 -5.4,-0.4 -7.8,1 -2.5,1.4 -4,3.5 -4.7,6.3 z m 6,-4 c 1.9,-1.1 3.8,-1.4 5.8,-0.8 2,0.5 3.6,1.7 4.7,3.6 1.1,1.8 1.3,3.8 0.8,5.8 -0.6,2 -1.8,3.6 -3.6,4.6 v 0.1 c -1.9,1 -3.8,1.3 -5.8,0.7 C 28.6,71.9 27.1,70.7 26,68.8 25,67 24.7,65.1 25.2,63 25.8,61 27,59.5 28.8,58.4 z"
+       id="path11"
+       inkscape:connector-curvature="0" /></g><metadata
+     id="metadata13"><rdf:RDF><cc:Work><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><cc:license
+           rdf:resource="http://creativecommons.org/licenses/publicdomain/" /><dc:publisher><cc:Agent
+             rdf:about="http://openclipart.org/"><dc:title>Openclipart</dc:title></cc:Agent></dc:publisher><dc:title /></cc:Work><cc:License
+         rdf:about="http://creativecommons.org/licenses/publicdomain/"><cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" /><cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" /><cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" /></cc:License></rdf:RDF></metadata><path
+     inkscape:connector-curvature="0"
+     style="color:#000000;fill:#e71c02;stroke:#e71c02;stroke-width:1.69794059;stroke-linecap:round;stroke-linejoin:round"
+     id="path1317"
+     d="M 6.1592596,28.802037 10.889697,28.054624 7.7071484,33.65608 6.1592413,28.802027 z" /><path
+     inkscape:connector-curvature="0"
+     style="fill:none;stroke:#e71c02;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
+     id="path1323"
+     d="M 35.686385,22.900691 C 27.800118,35.344435 17.919479,35.262081 8.9714291,30.716821"
+     sodipodi:nodetypes="cc" /></svg>
\ No newline at end of file
diff --git a/SRC/OpenMeca/Rsc/Img/application-openmeca.svg b/SRC/OpenMeca/Rsc/Img/application-openmeca.svg
new file mode 100644
index 0000000..2f5ede7
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Img/application-openmeca.svg
@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="128"
+   height="128"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="application-openmeca.svg"
+   inkscape:export-filename="/home/dada/work/dev/openmeca/SRC/OpenMeca/Icons/Mini-Logo-48px.png"
+   inkscape:export-xdpi="109.63609"
+   inkscape:export-ydpi="109.63609">
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1598"
+     inkscape:window-height="823"
+     id="namedview6409"
+     showgrid="false"
+     inkscape:snap-bbox="true"
+     inkscape:zoom="1.2880859"
+     inkscape:cx="-31.753087"
+     inkscape:cy="-9.9935059"
+     inkscape:window-x="0"
+     inkscape:window-y="24"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2"
+     showguides="false">
+    <inkscape:grid
+       type="xygrid"
+       id="grid6411"
+       empspacing="1"
+       dotted="true"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3872">
+      <stop
+         id="stop3874"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3876"
+         style="stop-color:#0000ff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3854">
+      <stop
+         id="stop3856"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3862"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop3858"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3755">
+      <stop
+         id="stop3757"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3759"
+         style="stop-color:#ff0000;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       cx="325.71429"
+       cy="436.64789"
+       r="96.708328"
+       fx="325.71429"
+       fy="436.64789"
+       id="radialGradient3761"
+       xlink:href="#linearGradient3755"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.36211236,0,0,0.36171798,39.815222,321.2284)" />
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4163">
+      <circle
+         style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.5, 1;stroke-dashoffset:0;stroke-opacity:1"
+         id="circle4165"
+         cx="15"
+         cy="25"
+         r="15" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4197">
+      <circle
+         style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.61410201;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="circle4199"
+         cx="31.556349"
+         cy="17.713625"
+         r="19.419611" />
+    </clipPath>
+    <filter
+       id="6">
+      <feGaussianBlur
+         stdDeviation="2.58594"
+         id="M" />
+    </filter>
+    <radialGradient
+       xlink:href="#2"
+       r="44.419998"
+       cy="100.32"
+       cx="81.790001"
+       gradientTransform="matrix(2.0026052,-1.5970314,1.7773333,2.2286954,-279.23554,23.703826)"
+       gradientUnits="userSpaceOnUse"
+       id="7" />
+    <linearGradient
+       id="2">
+      <stop
+         id="F"
+         stop-color="#eee" />
+      <stop
+         offset="1"
+         id="G"
+         stop-color="#d2d2d2" />
+    </linearGradient>
+    <radialGradient
+       xlink:href="#3"
+       r="18.278999"
+       cy="22.254"
+       cx="89.510002"
+       gradientTransform="matrix(1,0,0,0.97467889,0,0.43910718)"
+       gradientUnits="userSpaceOnUse"
+       id="8" />
+    <linearGradient
+       id="3">
+      <stop
+         id="H" />
+      <stop
+         offset="1"
+         id="I"
+         stop-opacity="0.536" />
+    </linearGradient>
+    <filter
+       id="5"
+       x="-0.147"
+       width="1.294"
+       y="-0.145"
+       height="1.29">
+      <feGaussianBlur
+         stdDeviation="1.81881"
+         id="L" />
+    </filter>
+    <linearGradient
+       xlink:href="#4"
+       y2="25.1"
+       x2="86.82"
+       y1="14.793"
+       x1="98.330002"
+       gradientTransform="matrix(0.96714879,0,0,0.96714879,5.7242712,3.4943798)"
+       gradientUnits="userSpaceOnUse"
+       id="9" />
+    <linearGradient
+       id="4">
+      <stop
+         id="J" />
+      <stop
+         offset="1"
+         id="K"
+         stop-color="#ddd"
+         stop-opacity="0" />
+    </linearGradient>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4197-3">
+      <circle
+         style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.61410201;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="circle4199-6"
+         cx="31.556349"
+         cy="17.713625"
+         r="19.419611" />
+    </clipPath>
+    <clipPath
+       clipPathUnits="userSpaceOnUse"
+       id="clipPath4163-7">
+      <circle
+         style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.5, 1;stroke-dashoffset:0;stroke-opacity:1"
+         id="circle4165-5"
+         cx="15"
+         cy="25"
+         r="15" />
+    </clipPath>
+    <filter
+       id="6-3">
+      <feGaussianBlur
+         stdDeviation="2.58594"
+         id="M-6" />
+    </filter>
+    <radialGradient
+       xlink:href="#2"
+       r="44.419998"
+       cy="100.32"
+       cx="81.790001"
+       gradientTransform="matrix(2.0026052,-1.5970314,1.7773333,2.2286954,-273.96749,27.285009)"
+       gradientUnits="userSpaceOnUse"
+       id="7-7" />
+    <radialGradient
+       xlink:href="#3"
+       r="18.278999"
+       cy="22.254"
+       cx="89.510002"
+       gradientTransform="matrix(1,0,0,0.97467889,0,0.43910718)"
+       gradientUnits="userSpaceOnUse"
+       id="8-5" />
+    <filter
+       id="5-9"
+       x="-0.147"
+       width="1.294"
+       y="-0.145"
+       height="1.29">
+      <feGaussianBlur
+         stdDeviation="1.81881"
+         id="L-1" />
+    </filter>
+    <filter
+       inkscape:collect="always"
+       style="color-interpolation-filters:sRGB"
+       id="filter5398"
+       x="-0.054317041"
+       width="1.1086341"
+       y="-0.18521622"
+       height="1.3704324">
+      <feGaussianBlur
+         inkscape:collect="always"
+         stdDeviation="0.67969513"
+         id="feGaussianBlur5400" />
+    </filter>
+  </defs>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <path
+     d="m 20.09375,4.1185004 0,117.9999996 88.84375,0 0,-86.15625 -0.59375,-0.625 c 0.21045,0.144391 0.41688,0.302162 0.625,0.4375 L 78.09375,4.1497504 c 0.05654,0.079597 0.09993,0.1703021 0.15625,0.25 l -0.25,-0.28125 -57.90625,0 z"
+     id="A"
+     transform="matrix(0.96714879,0,0,0.97126149,5.7242712,2.9666149)"
+     inkscape:connector-curvature="0"
+     style="opacity:0.80899999;filter:url(#6-3)" />
+  <path
+     d="m 25.157917,6.1238156 0,114.1235544 85.925123,0 0,-83.32591 -29.921163,-30.7976444 -56.00396,0 z"
+     id="B"
+     inkscape:connector-curvature="0"
+     style="fill:url(#7-7)" />
+  <path
+     id="C"
+     d="m 81.698039,28.309502 0.135161,-8.351 C 81.901124,13.359407 80.956142,8.4107397 77.785779,3.9471419 L 80.362343,3.9159389 107.86271,29.53084 c -4.06802,-2.645393 -9.621189,-0.791242 -16.861906,-1.025606 l -9.302765,-0.195732 z"
+     transform="matrix(1.016085,0,0,1.112241,0.3433534,3.2359418)"
+     inkscape:connector-curvature="0"
+     style="opacity:0.50499998;fill:url(#8-5);filter:url(#5-9)" />
+  <path
+     d="m 86.883911,29.392864 0.130721,-8.07666 C 87.080324,14.933898 84.323055,10.480135 81.256842,6.1631716 L 111.12358,36.751338 c -3.93438,-2.558489 -8.23966,-6.942507 -15.242511,-7.169171 l -8.997158,-0.189303 z"
+     id="D"
+     inkscape:connector-curvature="0"
+     style="fill:#eeeeee" />
+  <path
+     id="E"
+     d="m 86.883911,29.392864 0.130721,-8.07666 C 87.080324,14.933898 84.323055,10.480135 81.256842,6.1631716 L 111.12358,36.751338 c -3.93438,-2.558489 -8.23966,-6.942507 -15.242511,-7.169171 l -8.997158,-0.189303 z"
+     inkscape:connector-curvature="0"
+     style="fill:url(#9)" />
+  <text
+     xml:space="preserve"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.25px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     x="107.64312"
+     y="116.34673"
+     id="text5352"
+     sodipodi:linespacing="125%"><tspan
+       sodipodi:role="line"
+       id="tspan5354"
+       x="107.64312"
+       y="116.34673">omc</tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16.25px;line-height:125%;font-family:Arial;-inkscape-font-specification:Arial;text-align:end;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5398)"
+     x="106.56867"
+     y="117.39135"
+     id="text5352-7"
+     sodipodi:linespacing="125%"><tspan
+       sodipodi:role="line"
+       id="tspan5354-3"
+       x="106.56867"
+       y="117.39135">omc</tspan></text>
+  <path
+     inkscape:connector-curvature="0"
+     d="m 112.1663,98.450038 -3.58199,0.238882 -0.79758,-1.340928 -1.6323,-0.691377 -1.71412,-0.609555 -1.66502,-0.466373 -1.45231,-0.282277 -0.56455,-0.126819 -0.0696,-1.239568 -0.0859,-1.231385 0.54818,-0.200459 1.39913,-0.462281 1.59548,-0.670921 1.62002,-0.818197 1.53821,-0.895925 -0.29864,-2.376862 -1.71412,-0.482735 -1.77139,-0.388644 -1.71413,-0.257732 -1.47275,-0.09409 -0.576826,-0.05728 -0.220913,-1.219113 -0.241374,-1.215022 0.515473,-0.261823 1.33365,-0.638194 1.5014,-0.863197 [...]
+     style="fill:#ffffbd;fill-opacity:1;stroke:#000000;stroke-width:1.34612703;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+     id="gear50"
+     sodipodi:nodetypes="ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" />
+  <path
+     inkscape:connector-curvature="0"
+     d="m 56.756595,30.580557 -0.540009,1.039109 -0.474555,1.100475 -0.351825,1.080019 -0.20864,0.953199 -0.06954,0.66274 0.004,0.237277 0.184094,1.99231 -1.70594,0.216822 -1.689575,0.319096 -0.441827,-1.951399 -0.06954,-0.225004 -0.270005,-0.609557 -0.486827,-0.838651 -0.670922,-0.924563 -0.78956,-0.900016 -0.834559,-0.818197 -2.045493,0.662739 -0.196366,1.157749 -0.106371,1.186385 -0.004,1.141385 0.09819,0.969562 0.139093,0.650466 0.07772,0.225004 0.79365,1.836852 -1.558665,0.732287 -1 [...]
+     style="fill:#f1a875;fill-opacity:1;stroke:#000000;stroke-width:1.34612703;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+     id="gear20" />
+  <path
+     inkscape:connector-curvature="0"
+     d="m 17.04385,83.099704 -1.424113,1.083121 0.03126,1.011652 0.169677,0.961173 0.260232,0.935271 0.306771,0.764503 0.318352,0.501882 0.155277,0.155207 2.094903,2.000876 -1.055371,1.270622 -0.854819,1.406419 -2.586361,-1.328055 -0.228998,-0.07887 -0.54984,-0.12278 -0.794342,-0.09298 -0.996117,0.07783 -1.007741,0.185215 -0.9313931,0.25894 -0.5494486,1.714244 0.6237317,0.809711 0.690975,0.688092 0.764696,0.611745 0.749132,0.409937 0.53434,0.231456 0.165603,0.04395 2.940624,0.399112 -0.1 [...]
+     style="fill:#50c67b;fill-opacity:1;stroke:#000000;stroke-width:1.34612703;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+     id="gear10" />
+</svg>
diff --git a/SRC/OpenMeca/Rsc/Lang/openmeca_fr.ts b/SRC/OpenMeca/Rsc/Lang/openmeca_fr.ts
new file mode 100644
index 0000000..a01c112
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Lang/openmeca_fr.ts
@@ -0,0 +1,1835 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.1" language="fr_FR">
+<context>
+    <name>Action</name>
+    <message>
+        <location filename="../../Core/Action/ActionDeleteUserItem.hpp" line="49"/>
+        <source>Delete</source>
+        <translation>Supprimer</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Action/ActionEditSystemSetting.hpp" line="44"/>
+        <source>Edit</source>
+        <translation>Éditer</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Action/ActionNewUserItem.hpp" line="47"/>
+        <source>New</source>
+        <translation>Nouveau</translation>
+    </message>
+</context>
+<context>
+    <name>DialogCheckDeleteItem</name>
+    <message>
+        <location filename="../../Gui/Dialog/DialogCheckDeleteItem.ui" line="33"/>
+        <source>Are you sure ?</source>
+        <translation>Ếtes-vous sûr ?</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogCheckDeleteItem.ui" line="49"/>
+        <source>Delete this item with all its child ?</source>
+        <translation>Voulez-vous détruire cet élément et tous ses enfants ?</translation>
+    </message>
+</context>
+<context>
+    <name>DialogSimulation</name>
+    <message>
+        <source>Form</source>
+        <translation type="obsolete">Fenêtre</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.ui" line="20"/>
+        <source>Close</source>
+        <translation>Fermer</translation>
+    </message>
+</context>
+<context>
+    <name>DialogUserItem</name>
+    <message>
+        <source>Form</source>
+        <translation type="obsolete">Fenêtre</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogUserItem.ui" line="77"/>
+        <source>Preview</source>
+        <translation>Aperçu</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogUserItem.ui" line="109"/>
+        <source>Cancel</source>
+        <translation>Annuler</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogUserItem.ui" line="128"/>
+        <source>OK</source>
+        <translation>OK</translation>
+    </message>
+</context>
+<context>
+    <name>GeneralSetting</name>
+    <message>
+        <location filename="../../Gui/GeneralSetting.ui" line="14"/>
+        <source>General setting</source>
+        <translation>Préférence d'openmeca</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/GeneralSetting.ui" line="24"/>
+        <source>Language</source>
+        <translation>Language</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/GeneralSetting.ui" line="30"/>
+        <source>Choose your language :</source>
+        <translation>Choix du language :</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/GeneralSetting.ui" line="59"/>
+        <source>Reset Setting</source>
+        <translation>Remise à zéro des préférences</translation>
+    </message>
+</context>
+<context>
+    <name>ImageDialog</name>
+    <message>
+        <location filename="../../Gui/ImageDialog.ui" line="26"/>
+        <source>Save image as...</source>
+        <translation>Sauver l'image comme...</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/ImageDialog.ui" line="36"/>
+        <source>Choose image parameter</source>
+        <translation>Choisissez les paramètres de l'image</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/ImageDialog.ui" line="56"/>
+        <source>Image quality </source>
+        <translation>Qualité de l'image</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/ImageDialog.ui" line="69"/>
+        <source>%</source>
+        <translation>%</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/ImageDialog.ui" line="98"/>
+        <source>Image format</source>
+        <translation>Format de l'image</translation>
+    </message>
+</context>
+<context>
+    <name>MainPlotWindow</name>
+    <message>
+        <location filename="../../Gui/MainPlotWindow.ui" line="14"/>
+        <source>openmeca (plot)</source>
+        <translation>openmeca (graph)</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainPlotWindow.ui" line="34"/>
+        <source>Plot</source>
+        <translation>Tracer</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainPlotWindow.ui" line="38"/>
+        <source>Add data</source>
+        <translation>Ajouter des données</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainPlotWindow.ui" line="49"/>
+        <source>Clear</source>
+        <translation>Effacer</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainPlotWindow.ui" line="54"/>
+        <source>sdqs</source>
+        <translation>ssds</translation>
+    </message>
+</context>
+<context>
+    <name>MainWindow</name>
+    <message>
+        <source>openMeca</source>
+        <translation type="obsolete">openmeca</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="58"/>
+        <source>Global View</source>
+        <translation>Global</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="74"/>
+        <source>1</source>
+        <translation>1</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="97"/>
+        <source>File</source>
+        <translation>Fichier</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="116"/>
+        <source>Edit</source>
+        <translation>Édition</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="14"/>
+        <source>openmeca</source>
+        <translation>openmeca</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="101"/>
+        <source>Example</source>
+        <translation type="unfinished"></translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="127"/>
+        <source>ToolBar</source>
+        <translation>Bar d'outils</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="148"/>
+        <source>Save</source>
+        <translation>Enregistrer</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="157"/>
+        <source>Save as...</source>
+        <translation>Enregistrer comme...</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="166"/>
+        <source>Open...</source>
+        <translation>Ouvrir...</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="175"/>
+        <source>Undo</source>
+        <translation>Annuler</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="187"/>
+        <source>Redo</source>
+        <translation>Refaire</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="199"/>
+        <source>Quit...</source>
+        <translation>Quitter....</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="204"/>
+        <source>Show...</source>
+        <translation>Montrer...</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="213"/>
+        <source>Settings...</source>
+        <translation>Préférences...</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="222"/>
+        <source>New system</source>
+        <translation>Nouveau systéme</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.ui" line="227"/>
+        <source>sdqs</source>
+        <translation type="unfinished">ssds</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Core::Action</name>
+    <message>
+        <location filename="../../Core/Action/ActionEditGlobalSetting.hpp" line="48"/>
+        <location filename="../../Core/Action/ActionEditItem.hpp" line="48"/>
+        <source>Edit</source>
+        <translation>Éditer</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Action/ActionNewUserItemWithAutomaticSelection.hpp" line="52"/>
+        <source>New</source>
+        <translation>Nouveau</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Action/ActionNewUserItemWithAutomaticSelection.hpp" line="83"/>
+        <source>You must build a </source>
+        <translation>Vous devez contruire un(e)</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Action/ActionNewUserItemWithAutomaticSelection.hpp" line="84"/>
+        <source> instance first</source>
+        <translation> d'abord</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Action/ActionNewUserItemWithAutomaticSelection.hpp" line="85"/>
+        <source>Warning</source>
+        <translation>Attention</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Action/ActionNewUserItemWithSelection.hpp" line="47"/>
+        <source>New </source>
+        <translation>Nouveau </translation>
+    </message>
+    <message>
+        <location filename="../../Item/Body.cpp" line="332"/>
+        <source>Fix/Unfix</source>
+        <translation>Fixer/Libre</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Body.cpp" line="361"/>
+        <source>Show/Unshow local frame</source>
+        <translation>Montrer/Cacher le repère local</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui</name>
+    <message>
+        <source>New </source>
+        <translation type="obsolete">Nouveau </translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogBody</name>
+    <message>
+        <source>Name</source>
+        <translation type="obsolete">Nom</translation>
+    </message>
+    <message>
+        <source>Color</source>
+        <translation type="obsolete">Couleur</translation>
+    </message>
+    <message>
+        <source>Clamped</source>
+        <translation type="obsolete">Bâti</translation>
+    </message>
+    <message>
+        <source>Show local frame</source>
+        <translation type="obsolete">Montrer le repère local</translation>
+    </message>
+    <message>
+        <source>Mass</source>
+        <translation type="obsolete">Masse</translation>
+    </message>
+    <message>
+        <source>Center</source>
+        <translation type="obsolete">Centre de masse</translation>
+    </message>
+    <message>
+        <source>Inertia</source>
+        <translation type="obsolete">Tenseur d'inertie</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogGravity</name>
+    <message>
+        <source>Gravity</source>
+        <translation type="obsolete">Gravité</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogLinkGear</name>
+    <message>
+        <source>Ratio</source>
+        <translation type="obsolete">Réduction</translation>
+    </message>
+    <message>
+        <source>Length between axes</source>
+        <translation type="obsolete">Longueur inter-axes</translation>
+    </message>
+    <message>
+        <source>Modulus</source>
+        <translation type="obsolete">Module</translation>
+    </message>
+    <message>
+        <source>Angle of action</source>
+        <translation type="obsolete">Angle d'action</translation>
+    </message>
+    <message>
+        <source>Internal teeth</source>
+        <translation type="obsolete">Denture intérieure</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogLinkMotor</name>
+    <message>
+        <source>Angular velocity</source>
+        <translation type="obsolete">Vitesse angulaire</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogLinkPulley</name>
+    <message>
+        <source>Pinion 1 radius</source>
+        <translation type="obsolete">Rayon du pignon 1</translation>
+    </message>
+    <message>
+        <source>Pinion 2 radius</source>
+        <translation type="obsolete">Rayon du pignon 2</translation>
+    </message>
+    <message>
+        <source>Length between axes</source>
+        <translation type="obsolete">Longueur inter-axes</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogLinkRackPinion</name>
+    <message>
+        <source>Ratio</source>
+        <translation type="obsolete">Réduction</translation>
+    </message>
+    <message>
+        <source>Pinion radius</source>
+        <translation type="obsolete">Rayon du pignon</translation>
+    </message>
+    <message>
+        <source>Modulus</source>
+        <translation type="obsolete">Module</translation>
+    </message>
+    <message>
+        <source>Angle of action</source>
+        <translation type="obsolete">Angle d'action</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogLinkScrew</name>
+    <message>
+        <source>Step</source>
+        <translation type="obsolete">Pas</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogLinkSpring</name>
+    <message>
+        <source>Stiffness</source>
+        <translation type="obsolete">Raideur</translation>
+    </message>
+    <message>
+        <source>Damping factor</source>
+        <translation type="obsolete">Amortissement</translation>
+    </message>
+    <message>
+        <source>Free length</source>
+        <translation type="obsolete">Longueur à vide</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogPartUserJunction</name>
+    <message>
+        <source>Name</source>
+        <translation type="obsolete">Nom</translation>
+    </message>
+    <message>
+        <source>End Point</source>
+        <translation type="obsolete">Point de fin</translation>
+    </message>
+    <message>
+        <source>Warning</source>
+        <translation type="obsolete">Attention</translation>
+    </message>
+    <message>
+        <source>Need two points to build a junction</source>
+        <translation type="obsolete">Deux points sont requis pour construire un jonction</translation>
+    </message>
+    <message>
+        <source>The end point is the same as the start point</source>
+        <translation type="obsolete">Le point de fin est le même que le point de début</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogPartUserPipe</name>
+    <message>
+        <source>Name</source>
+        <translation type="obsolete">Nom</translation>
+    </message>
+    <message>
+        <source>Attached to point</source>
+        <translation type="obsolete">Attaché au point</translation>
+    </message>
+    <message>
+        <source>Axis</source>
+        <translation type="obsolete">Axe</translation>
+    </message>
+    <message>
+        <source>Length</source>
+        <translation type="obsolete">Longueur</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogPartUserPoint</name>
+    <message>
+        <source>Name</source>
+        <translation type="obsolete">Nom</translation>
+    </message>
+    <message>
+        <source>Parent Item</source>
+        <translation type="obsolete">Élement parent</translation>
+    </message>
+    <message>
+        <source>Center</source>
+        <translation type="obsolete">Centre de masse</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogScene</name>
+    <message>
+        <source>Draw scene axis</source>
+        <translation type="obsolete">Montrer le repère global</translation>
+    </message>
+    <message>
+        <source>Background color</source>
+        <translation type="obsolete">Couleur de fond</translation>
+    </message>
+    <message>
+        <source>Scene center</source>
+        <translation type="obsolete">Centre de la scène 3D</translation>
+    </message>
+    <message>
+        <source>Scene radius</source>
+        <translation type="obsolete">Rayon de la scène 3D</translation>
+    </message>
+    <message>
+        <source>Camera</source>
+        <translation type="obsolete">Type de vue</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogSimulation</name>
+    <message>
+        <source>time step</source>
+        <translation type="obsolete">Pas de temps</translation>
+    </message>
+    <message>
+        <source>total simulation time</source>
+        <translation type="obsolete">Temps total à simuler</translation>
+    </message>
+    <message>
+        <source>Solver</source>
+        <translation type="obsolete">Solveur</translation>
+    </message>
+    <message>
+        <source>Integration</source>
+        <translation type="obsolete">Intégrateur</translation>
+    </message>
+    <message>
+        <source>Warning</source>
+        <translation type="vanished">Attention</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.cpp" line="103"/>
+        <source>The time step must be lower than the total simulation time</source>
+        <translation>Le pas de temps doit être plus petit que le temps total simulé</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.cpp" line="143"/>
+        <source>Please stop your simulation first</source>
+        <translation type="unfinished">Veuillez arrêter d'abord votre simulation</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::DialogUserItem</name>
+    <message>
+        <location filename="../../Gui/Dialog/DialogUserItem.cpp" line="119"/>
+        <source>OpenMeca</source>
+        <translation>openmeca</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogUserItem.cpp" line="119"/>
+        <source>The current edited item was deleted.
+The dialog will be closed</source>
+        <translation>L'élément courant a été détruit. L'action en cours va être annulée.</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="43"/>
+        <source>Name</source>
+        <translation>Nom</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="44"/>
+        <source>First body</source>
+        <translation>Solide 1</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="45"/>
+        <source>Second body</source>
+        <translation>Solide 2</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="47"/>
+        <source>Center</source>
+        <translation>Centre de masse</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="50"/>
+        <source>Rotation</source>
+        <translation>Rotation</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="52"/>
+        <source>Draw local frame</source>
+        <translation>Montrer le repère local</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::GeneralSetting</name>
+    <message>
+        <location filename="../../Gui/GeneralSetting.cpp" line="75"/>
+        <source>Information</source>
+        <translation>Information</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/GeneralSetting.cpp" line="76"/>
+        <source>You must restart openmeca to apply settings</source>
+        <translation>Vous devez redémarrer openmeca pour que vos changements soient pris en compte</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/GeneralSetting.cpp" line="91"/>
+        <source>Question</source>
+        <translation>Question</translation>
+    </message>
+    <message>
+        <source>please remove manually this directory</source>
+        <translation type="vanished">Veuillez supprimer manuellement ce répertoire</translation>
+    </message>
+    <message>
+        <source>You are going to reset the setting of openmeca, are you sure ?</source>
+        <translation type="vanished">Vous êtes sur le point de supprimer vos préférences, êtes-vous sûr ?</translation>
+    </message>
+    <message>
+        <source>Can't delete the config directory</source>
+        <translation type="vanished">Impossible de supprimer le repertoire de configuration</translation>
+    </message>
+    <message>
+        <source>please remove this directory by hand</source>
+        <translation type="vanished">vous devez supprimer ce répertoire à la main</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::MainPlotWindow</name>
+    <message>
+        <location filename="../../Gui/MainPlotWindow.cpp" line="96"/>
+        <source>openmeca (plot)</source>
+        <translation>openmeca (graphe)</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/Vector3D.cpp" line="109"/>
+        <source>X</source>
+        <translation>X</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/Vector3D.cpp" line="110"/>
+        <source>Y</source>
+        <translation>Y</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/Vector3D.cpp" line="111"/>
+        <source>Z</source>
+        <translation>Z</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/Vector3D.cpp" line="112"/>
+        <source>Norm</source>
+        <translation>Norme</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/Double.cpp" line="93"/>
+        <source>Value</source>
+        <translation>Valeur</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::MainWindow</name>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="128"/>
+        <source>Mechanical System</source>
+        <translation>Système mécanique</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="427"/>
+        <source>Save As</source>
+        <translation>Sauver comme</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="483"/>
+        <source>OpenMeca Files (*.omc)</source>
+        <translation>Fichier openmeca (*.omc)</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="455"/>
+        <source>The current action will clear your system, do you want to continue ?</source>
+        <translation>Vous allez effacer votre systéme, voulez-vous continuer ?</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="457"/>
+        <source>Are you sure ?</source>
+        <translation>Ếtes-vous sûr ?</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="483"/>
+        <source>Open File</source>
+        <translation>Ouvrir un fichier</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="531"/>
+        <source>The document has been modified.</source>
+        <translation>Le système a été modifié.</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="532"/>
+        <source>Do you want to save your changes?</source>
+        <translation>Voulez-vous sauvegarder les changements ?</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="569"/>
+        <source>Save data as</source>
+        <translation>Enregistrer les données</translation>
+    </message>
+    <message>
+        <source>Data file (*.txt)</source>
+        <translation type="vanished">Fichier de donnée (*.txt)</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="602"/>
+        <source>Welcome to openmeca !</source>
+        <translation>Bienvenue dans openmeca !</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="603"/>
+        <source>Openmeca is an easy to use software that helps you to build mechanical systems and simulate it</source>
+        <translation>Openmeca est un logiciel qui permet de construire et de simuler des systèmes mécaniques</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="606"/>
+        <source>OpenMeca is distributed under the free GPL v3 license</source>
+        <translation>Openmeca est distribué sous la licence libre GPLv3</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="608"/>
+        <source>It means that you are free to use and to distribute it !</source>
+        <translation>Cela signifie que vous êtes libre d'utiliser et de redistribuer ce logiciel !</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="611"/>
+        <source>Main informations</source>
+        <translation>Informations générales</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="615"/>
+        <source>About openmeca</source>
+        <translation>À propos d'openmeca</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainWindow.cpp" line="661"/>
+        <source>Help</source>
+        <translation>Aide</translation>
+    </message>
+    <message>
+        <source>You are loading a file created with an older version of openmeca 
+</source>
+        <translation type="vanished">Vous êtes en train de charger un fichier créé avec une ancienne version d'openmeca </translation>
+    </message>
+    <message>
+        <source>File version: </source>
+        <translation type="vanished">Version du fichier: </translation>
+    </message>
+    <message>
+        <source>Soft version: </source>
+        <translation type="vanished">Version d'openmeca: </translation>
+    </message>
+    <message>
+        <source>Warning</source>
+        <translation type="vanished">Attention</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::Physic::DialogMechanicalAction</name>
+    <message>
+        <source>Value</source>
+        <translation type="obsolete">Valeur</translation>
+    </message>
+    <message>
+        <source>Direction coordinate</source>
+        <translation type="obsolete">Coordonnées de la direction</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::Player</name>
+    <message>
+        <location filename="../../Gui/Player.cpp" line="35"/>
+        <source>Simulated time : </source>
+        <translation>Temps simulé</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.cpp" line="36"/>
+        <source>Iteration number : </source>
+        <translation>Nombre d'itération</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.cpp" line="161"/>
+        <source>Save files in directory</source>
+        <translation>Enregister les fichiers dans le répertoire</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::PropTree</name>
+    <message>
+        <source>Property</source>
+        <translation type="obsolete">Propriété</translation>
+    </message>
+    <message>
+        <source>Value</source>
+        <translation type="obsolete">Valeur</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::Shape::DialogBox</name>
+    <message>
+        <source>Length along X</source>
+        <translation type="obsolete">Longueur suivant X</translation>
+    </message>
+    <message>
+        <source>Length along Y</source>
+        <translation type="obsolete">Longueur suivant Y</translation>
+    </message>
+    <message>
+        <source>Length along Z</source>
+        <translation type="obsolete">Longueur suivant Z</translation>
+    </message>
+    <message>
+        <source>Rotation</source>
+        <translation type="obsolete">Rotation</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::Shape::DialogCylinder</name>
+    <message>
+        <source>Radius</source>
+        <translation type="obsolete">Rayon</translation>
+    </message>
+    <message>
+        <source>Length</source>
+        <translation type="obsolete">Longueur</translation>
+    </message>
+    <message>
+        <source>Axis</source>
+        <translation type="obsolete">Axe</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::Shape::DialogGround</name>
+    <message>
+        <source>Axis</source>
+        <translation type="obsolete">Axe</translation>
+    </message>
+</context>
+<context>
+    <name>OpenMeca::Gui::Shape::DialogSphere</name>
+    <message>
+        <source>Radius</source>
+        <translation type="obsolete">Rayon</translation>
+    </message>
+</context>
+<context>
+    <name>Player</name>
+    <message>
+        <source>Form</source>
+        <translation type="obsolete">Fenêtre</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.ui" line="17"/>
+        <source>Play/Pause</source>
+        <translation>Lecture/Pause</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.ui" line="72"/>
+        <source>Stop and reset</source>
+        <translation>Arrêt et mise à zéro</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.ui" line="107"/>
+        <source>Record image</source>
+        <translation>Enregistrer des images</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.ui" line="130"/>
+        <source>Current simulation step</source>
+        <translation>Pas courant de la simulation</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.ui" line="142"/>
+        <source>Iteration number : </source>
+        <translation>Nombre d'itération</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Player.ui" line="149"/>
+        <source>Simulated time : </source>
+        <translation>Temps simulé</translation>
+    </message>
+</context>
+<context>
+    <name>QObject</name>
+    <message>
+        <source>You must build a </source>
+        <translation type="obsolete">Vous devez contruire un(e)</translation>
+    </message>
+    <message>
+        <source> instance first</source>
+        <translation type="obsolete"> d'abord</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="92"/>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="91"/>
+        <location filename="../../Gui/Dialog/DialogLinkT.hpp" line="128"/>
+        <location filename="../../Gui/Dialog/DialogPartUserJunction.cpp" line="57"/>
+        <location filename="../../Gui/Dialog/DialogPartUserJunction.cpp" line="76"/>
+        <source>Warning</source>
+        <translation>Attention</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Condition.hpp" line="93"/>
+        <source>Must be superior to </source>
+        <translation>Doit être supérieur à </translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="45"/>
+        <location filename="../../Gui/Dialog/DialogLoadT.hpp" line="73"/>
+        <location filename="../../Gui/Dialog/DialogPartUserJunction.cpp" line="38"/>
+        <location filename="../../Gui/Dialog/DialogPartUserPipe.cpp" line="39"/>
+        <location filename="../../Gui/Dialog/DialogPartUserPoint.cpp" line="38"/>
+        <location filename="../../Gui/Dialog/DialogPartUserShapeT.hpp" line="79"/>
+        <location filename="../../Gui/Dialog/DialogSensorT.hpp" line="70"/>
+        <source>Name</source>
+        <translation>Nom</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="47"/>
+        <source>Color</source>
+        <translation>Couleur</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="49"/>
+        <source>Clamped</source>
+        <translation>Fixer</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="50"/>
+        <source>Show local frame</source>
+        <translation>Montrer le repère local</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="51"/>
+        <source>Show mass center</source>
+        <translation>Montrer le centre de masse</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="54"/>
+        <source>Mass</source>
+        <translation>Masse</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="57"/>
+        <location filename="../../Gui/Dialog/DialogPartUserPoint.cpp" line="40"/>
+        <source>Center</source>
+        <translation>Centre de masse</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="61"/>
+        <source>Inertia</source>
+        <translation>Tenseur d'inertie</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="64"/>
+        <source>Static friction coeficient</source>
+        <translation>Coef de friction statique</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogBody.cpp" line="67"/>
+        <source>Sliding friction coeficient</source>
+        <translation>Coef de friction en glissement</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogGravity.cpp" line="38"/>
+        <location filename="../../Setting/Gravity.cpp" line="41"/>
+        <source>Gravity</source>
+        <translation>Gravité</translation>
+    </message>
+    <message>
+        <source>First body</source>
+        <translation type="obsolete">Solide 1</translation>
+    </message>
+    <message>
+        <source>Second body</source>
+        <translation type="obsolete">Solide 2</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/Shape/ShapeDialogBox.cpp" line="52"/>
+        <source>Rotation</source>
+        <translation>Rotation</translation>
+    </message>
+    <message>
+        <source>Draw local frame</source>
+        <translation type="obsolete">Montrer le repère local</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLink.cpp" line="92"/>
+        <source>The bodys must be different</source>
+        <translation>Les deux solides doivent êtres différents</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkGear.cpp" line="40"/>
+        <location filename="../../Gui/Dialog/DialogLinkRackPinion.cpp" line="39"/>
+        <source>Ratio</source>
+        <translation>Réduction</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkGear.cpp" line="43"/>
+        <location filename="../../Gui/Dialog/DialogLinkPulley.cpp" line="44"/>
+        <source>Length between axes</source>
+        <translation>Longueur inter-axes</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkGear.cpp" line="46"/>
+        <location filename="../../Gui/Dialog/DialogLinkRackPinion.cpp" line="45"/>
+        <source>Modulus</source>
+        <translation>Module</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkGear.cpp" line="49"/>
+        <location filename="../../Gui/Dialog/DialogLinkRackPinion.cpp" line="48"/>
+        <source>Angle of action</source>
+        <translation>Angle d'action</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkGear.cpp" line="52"/>
+        <source>Internal teeth</source>
+        <translation>Denture intérieure</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkGear.cpp" line="84"/>
+        <source>You can't set a ratio of 100% with internal teeth gear</source>
+        <translation>Vous ne pouvez pas mettre un rapport de réduction de 100% avec une denture intérieure </translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkMotor.cpp" line="36"/>
+        <source>Angular velocity</source>
+        <translation>Vitesse angulaire</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkPulley.cpp" line="38"/>
+        <source>Pinion 1 radius</source>
+        <translation>Rayon du pignon 1</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkPulley.cpp" line="41"/>
+        <source>Pinion 2 radius</source>
+        <translation>Rayon du pignon 2</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkRackPinion.cpp" line="42"/>
+        <source>Pinion radius</source>
+        <translation>Rayon du pignon</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkScrew.cpp" line="36"/>
+        <source>Step</source>
+        <translation>Pas</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkSpring.cpp" line="41"/>
+        <source>Stiffness</source>
+        <translation>Raideur</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkSpring.cpp" line="44"/>
+        <location filename="../../Gui/Dialog/DialogLinkSpring.cpp" line="47"/>
+        <source>Damping factor</source>
+        <translation>Amortissement</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkSpring.cpp" line="50"/>
+        <source>Free length</source>
+        <translation>Longueur à vide</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkSpring.cpp" line="53"/>
+        <source>Initial length</source>
+        <translation>Longueur initiale</translation>
+    </message>
+    <message>
+        <source>openmeca</source>
+        <translation type="obsolete">openmeca</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLoadT.hpp" line="74"/>
+        <location filename="../../Gui/Dialog/DialogSensorT.hpp" line="71"/>
+        <source>Parent</source>
+        <translation>Parent</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserJunction.cpp" line="39"/>
+        <source>End Point</source>
+        <translation>Point de fin</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserJunction.cpp" line="58"/>
+        <source>Need two points to build a junction</source>
+        <translation>Deux points sont requis pour construire une jonction</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserJunction.cpp" line="77"/>
+        <source>The end point is the same as the start point</source>
+        <translation>Le point de fin est le même que le point de début</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserPipe.cpp" line="40"/>
+        <source>Attached to point</source>
+        <translation>Attaché au point</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserPipe.cpp" line="41"/>
+        <location filename="../../Gui/Dialog/Shape/DialogCylinder.cpp" line="49"/>
+        <location filename="../../Gui/Dialog/Shape/DialogGround.cpp" line="35"/>
+        <source>Axis</source>
+        <translation>Axe</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserPipe.cpp" line="44"/>
+        <location filename="../../Gui/Dialog/Shape/DialogCylinder.cpp" line="45"/>
+        <source>Length</source>
+        <translation>Longueur</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserPoint.cpp" line="39"/>
+        <source>Parent Item</source>
+        <translation>Élement parent</translation>
+    </message>
+    <message>
+        <location filename="../../Geom/Point.hpp" line="57"/>
+        <location filename="../../Gui/Dialog/DialogPartUserShapeT.hpp" line="80"/>
+        <location filename="../../Item/PartUserPoint.hpp" line="40"/>
+        <source>Point</source>
+        <translation>Point</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogPartUserShapeT.hpp" line="81"/>
+        <source>Enable collision detection</source>
+        <translation>Activer la collision de detection</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogScene.cpp" line="42"/>
+        <source>Draw scene axis</source>
+        <translation>Montrer le repère global</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogScene.cpp" line="44"/>
+        <source>Background color</source>
+        <translation>Couleur de fond</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogScene.cpp" line="46"/>
+        <source>Scene center</source>
+        <translation>Centre de la scène 3D</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogScene.cpp" line="49"/>
+        <source>Scene radius</source>
+        <translation>Rayon de la scène 3D</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogScene.cpp" line="52"/>
+        <source>Camera</source>
+        <translation>Type de vue</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.cpp" line="49"/>
+        <source>time step</source>
+        <translation>Pas de temps</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.cpp" line="53"/>
+        <source>total simulation time</source>
+        <translation>Temps total à simuler</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.cpp" line="56"/>
+        <source>Solver</source>
+        <translation>Solveur</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.cpp" line="57"/>
+        <source>Integration</source>
+        <translation>Intégrateur</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogSimulation.cpp" line="60"/>
+        <source>Animation period</source>
+        <translation>Période d'animation</translation>
+    </message>
+    <message>
+        <source>The time step must be lower than the total simulation time</source>
+        <translation type="obsolete">Le pas de temps doit être plus petit que le temps total simulé</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogVariable.cpp" line="38"/>
+        <source>Symbol</source>
+        <translation>Symbole</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogVariable.cpp" line="41"/>
+        <location filename="../../Gui/Dialog/Physic/DialogMechanicalAction.cpp" line="37"/>
+        <location filename="../../Gui/Prop/PropTree.cpp" line="36"/>
+        <location filename="../../Gui/Prop/PropTree.cpp" line="50"/>
+        <source>Value</source>
+        <translation>Valeur</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogVariable.cpp" line="94"/>
+        <source>The name of the variable is already used</source>
+        <translation>Le nom de la variable est déjà utilisée</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogVariable.cpp" line="101"/>
+        <source>It's not a valid variable name</source>
+        <translation>Nom de variable invalide</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/Physic/DialogMechanicalAction.cpp" line="38"/>
+        <source>Direction coordinate</source>
+        <translation>Direction</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/Shape/ShapeDialogBox.cpp" line="41"/>
+        <source>Length along X</source>
+        <translation>Longueur suivant X</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/Shape/ShapeDialogBox.cpp" line="45"/>
+        <source>Length along Y</source>
+        <translation>Longueur suivant Y</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/Shape/ShapeDialogBox.cpp" line="49"/>
+        <source>Length along Z</source>
+        <translation>Longueur suivant Z</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/Shape/DialogCylinder.cpp" line="41"/>
+        <location filename="../../Gui/Dialog/Shape/DialogSphere.cpp" line="38"/>
+        <source>Radius</source>
+        <translation>Rayon</translation>
+    </message>
+    <message>
+        <source>openmeca (plot)</source>
+        <translation type="obsolete">openmeca (graphe)</translation>
+    </message>
+    <message>
+        <source>Mechanical System</source>
+        <translation type="obsolete">Système mécanique</translation>
+    </message>
+    <message>
+        <source>About openmeca</source>
+        <translation type="obsolete">À propos d'openmeca</translation>
+    </message>
+    <message>
+        <source>You are loading a file created with an older version of openmeca 
+</source>
+        <translation type="obsolete">Vous êtes en train de charger un fichier créé avec une ancienne version d'openmeca </translation>
+    </message>
+    <message>
+        <source>File version: </source>
+        <translation type="obsolete">Version du fichier: </translation>
+    </message>
+    <message>
+        <source>Soft version: </source>
+        <translation type="obsolete">Version d'openmeca: </translation>
+    </message>
+    <message>
+        <source>Simulated time : </source>
+        <translation type="obsolete">Temps simulé</translation>
+    </message>
+    <message>
+        <source>Iteration number : </source>
+        <translation type="obsolete">Nombre d'itération</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Prop/PropAttitude.cpp" line="114"/>
+        <location filename="../../Gui/Prop/PropExprAttitude.cpp" line="115"/>
+        <source>The axis can't be null</source>
+        <translation>L'axe ne peut être nul</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Prop/PropAxis.cpp" line="105"/>
+        <source>The axis can not be null</source>
+        <translation>L'axe ne peut être nul</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Prop/PropTree.cpp" line="36"/>
+        <location filename="../../Gui/Prop/PropTree.cpp" line="50"/>
+        <source>Property</source>
+        <translation>Propriété</translation>
+    </message>
+    <message>
+        <source>Fix/Unfix</source>
+        <translation type="obsolete">Fixé/Défixé</translation>
+    </message>
+    <message>
+        <source>Show/Unshow local frame</source>
+        <translation type="obsolete">Montrer/Cacher le repère local</translation>
+    </message>
+    <message>
+        <source>X</source>
+        <translation type="obsolete">X</translation>
+    </message>
+    <message>
+        <source>Y</source>
+        <translation type="obsolete">Y</translation>
+    </message>
+    <message>
+        <source>Z</source>
+        <translation type="obsolete">Z</translation>
+    </message>
+    <message>
+        <source>Norm</source>
+        <translation type="obsolete">Norme</translation>
+    </message>
+    <message>
+        <source>Delete</source>
+        <translation type="obsolete">Supprimer</translation>
+    </message>
+    <message>
+        <source>Edit</source>
+        <translation type="obsolete">Éditer</translation>
+    </message>
+    <message>
+        <location filename="../../Core/SystemSetting.cpp" line="84"/>
+        <source>System</source>
+        <translation>Système</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogUserItemT.hpp" line="87"/>
+        <source>New </source>
+        <translation>Nouveau </translation>
+    </message>
+    <message>
+        <location filename="../../Item/Body.hpp" line="63"/>
+        <source>Body</source>
+        <translation>Solide</translation>
+    </message>
+    <message>
+        <location filename="../../Item/How/SetForce.cpp" line="47"/>
+        <source>AbsoluteForce</source>
+        <translation>ForceAbsolue</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link.cpp" line="50"/>
+        <source>Link</source>
+        <translation>Liaison</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Cylindrical.cpp" line="45"/>
+        <source>Cylindrical</source>
+        <translation>Pivot glissant</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Gear.cpp" line="48"/>
+        <source>Gear</source>
+        <translation>Engrenage</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Motor.cpp" line="45"/>
+        <source>Motor</source>
+        <translation>Moteur</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Planar.cpp" line="48"/>
+        <source>Planar</source>
+        <translation>AppuiPlan</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/PointLine.cpp" line="47"/>
+        <source>PointLine</source>
+        <translation>Linéaire annulaire</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/PointPlane.cpp" line="47"/>
+        <source>PointPlane</source>
+        <translation>Ponctuelle</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Pulley.cpp" line="48"/>
+        <source>Pulley</source>
+        <translation>Poulie courroie</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/RackPinion.cpp" line="48"/>
+        <source>RackPinion</source>
+        <translation>Pignon crémaillère</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Revolute.cpp" line="46"/>
+        <source>Revolute</source>
+        <translation>Pivot</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Screw.cpp" line="48"/>
+        <source>Screw</source>
+        <translation>Hélioidale</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Slider.cpp" line="46"/>
+        <source>Slider</source>
+        <translation>Glissière</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Spherical.cpp" line="45"/>
+        <source>Spherical</source>
+        <translation>Rotule</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/Spring.cpp" line="48"/>
+        <source>Spring</source>
+        <translation>Ressort</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Load.cpp" line="45"/>
+        <source>Load</source>
+        <translation>Chargement</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Part.cpp" line="40"/>
+        <source>Part</source>
+        <translation>Pièce</translation>
+    </message>
+    <message>
+        <location filename="../../Item/PartPoint.hpp" line="44"/>
+        <source>AutomaticPoint</source>
+        <translation>Point automatique</translation>
+    </message>
+    <message>
+        <location filename="../../Item/PartUserJunction.hpp" line="45"/>
+        <source>Junction</source>
+        <translation>Jonction</translation>
+    </message>
+    <message>
+        <location filename="../../Item/PartUserPipe.hpp" line="45"/>
+        <source>Pipe</source>
+        <translation>Tuyau</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Sensor.cpp" line="45"/>
+        <source>Sensor</source>
+        <translation>Capteur</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Shape/Box.cpp" line="47"/>
+        <source>Box</source>
+        <translation>Pavé</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Shape/Cylinder.cpp" line="48"/>
+        <source>Cylinder</source>
+        <translation>Cylindre</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Shape/Ground.cpp" line="47"/>
+        <source>Ground</source>
+        <translation>Bâti</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Shape/Sphere.cpp" line="49"/>
+        <source>Sphere</source>
+        <translation>Sphère</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/AngularVelocity.cpp" line="46"/>
+        <source>AngularVelocity</source>
+        <translation>Vitesse angulaire</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/Force.cpp" line="44"/>
+        <source>Force</source>
+        <translation>Force</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/LinearPosition.cpp" line="46"/>
+        <source>LinearPosition</source>
+        <translation>Position linéaire</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/LinearVelocity.cpp" line="46"/>
+        <source>LinearVelocity</source>
+        <translation>Vitesse linéaire</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/MechanicalAction.cpp" line="45"/>
+        <source>MechanicalAction</source>
+        <translation>Action mécanique</translation>
+    </message>
+    <message>
+        <source>New</source>
+        <translation type="obsolete">Nouveau</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="119"/>
+        <source>Geometry</source>
+        <translation>Géométrie</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="120"/>
+        <source>Cosmetic</source>
+        <translation>Habillage</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="121"/>
+        <source>Loading</source>
+        <translation>Chargement</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="122"/>
+        <source>Plot data...</source>
+        <translation>Tracer les données...</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="123"/>
+        <source>Save data...</source>
+        <translation>Sauver les données...</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="124"/>
+        <source>Help</source>
+        <translation>Aide</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="125"/>
+        <source>About...</source>
+        <translation>À propos...</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="126"/>
+        <source>Help...</source>
+        <translation>Aide...</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="127"/>
+        <source>3D viewer help...</source>
+        <translation>Aide du viewer 3D...</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="130"/>
+        <source>Author(s)</source>
+        <translation>Autheur(s)</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="131"/>
+        <source>Version</source>
+        <translation>Version</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="132"/>
+        <source>Licence</source>
+        <translation>Licence</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="133"/>
+        <source>Contact</source>
+        <translation>Contact</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="134"/>
+        <source>Project</source>
+        <translation>Projet</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="137"/>
+        <source>gears</source>
+        <translation type="unfinished">engrenage</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="138"/>
+        <source>gyroscope</source>
+        <translation type="unfinished">gyroscope</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="139"/>
+        <source>reprap</source>
+        <translation type="unfinished">reprap</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="140"/>
+        <source>robot</source>
+        <translation type="unfinished">robot</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="141"/>
+        <source>screw</source>
+        <translation type="unfinished">vis-écrou</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="142"/>
+        <source>steering</source>
+        <translation type="unfinished">direction</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Software.cpp" line="143"/>
+        <source>cranck-shaft</source>
+        <translation type="unfinished">bielle-manivelle</translation>
+    </message>
+    <message>
+        <location filename="../../Setting/Scales.cpp" line="47"/>
+        <source>Scales</source>
+        <translation>Échelles</translation>
+    </message>
+    <message>
+        <location filename="../../Setting/Scene.cpp" line="42"/>
+        <source>Scene</source>
+        <translation>Scène</translation>
+    </message>
+    <message>
+        <location filename="../../Setting/Simulation.cpp" line="49"/>
+        <source>Simulation</source>
+        <translation>Simulation</translation>
+    </message>
+    <message>
+        <location filename="../../Geom/Frame.hpp" line="73"/>
+        <source>Frame</source>
+        <translation>Repère</translation>
+    </message>
+    <message>
+        <location filename="../../Geom/Matrix.hpp" line="88"/>
+        <source>Matrix</source>
+        <translation>Matrice</translation>
+    </message>
+    <message>
+        <location filename="../../Geom/Quaternion.hpp" line="68"/>
+        <source>Quaternion</source>
+        <translation>Quaternion</translation>
+    </message>
+    <message>
+        <location filename="../../Geom/Vector.hpp" line="107"/>
+        <source>Vector</source>
+        <translation>Vecteur</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkT.hpp" line="125"/>
+        <source>You must build 2 bodys before adding a new link</source>
+        <translation>Vous devez construire deux solides avant de créer une nouvelle liaison</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="36"/>
+        <source>Sorry, openmeca encounters an error</source>
+        <translation>Désolé, openmeca rencontre une erreur fatale</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="38"/>
+        <source>Error details :</source>
+        <translation>Détail de l'erreur :</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="39"/>
+        <source>source file :</source>
+        <translation>fichier source :</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="40"/>
+        <source>line :</source>
+        <translation>ligne :</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="41"/>
+        <source>condition :</source>
+        <translation>condition :</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="44"/>
+        <source>message :</source>
+        <translation>message :</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="46"/>
+        <source>The program may be unstable now, do you really want to continue ?</source>
+        <translation>Le programme peut être instable maintenant, voulez vous continuer ?</translation>
+    </message>
+    <message>
+        <source>The program will stop, do you want to try to save your work ?</source>
+        <translation type="vanished">Le programme va s'arrêter, vous pouvez essayer de sauvegarder votre travail</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="49"/>
+        <source>Error</source>
+        <translation>Erreur</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="55"/>
+        <source>Do You want to save your work before quitting OpenMeca ?</source>
+        <translation>Voulez-vous sauvez votre travail avant de quitter OpenMeca ?</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="56"/>
+        <source>Question</source>
+        <translation>Question</translation>
+    </message>
+    <message>
+        <location filename="../../Core/Macro.cpp" line="83"/>
+        <source>Information</source>
+        <translation>Information</translation>
+    </message>
+    <message>
+        <location filename="../../Core/ConfigDirectory.cpp" line="46"/>
+        <source>The config file directory of openmeca does not exist, openmeca will build a new config directory "</source>
+        <translation>Le répértoire de configuration d'openmeca n'existe pas. Openmeca va construire un nouveau répertoire de configuration</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/MainPlotWindow.cpp" line="196"/>
+        <source>One of the data seems to be deleted, the plot will be cleared</source>
+        <translation>Une des données semble avoir été détruite. Le graphe va être éffacé.</translation>
+    </message>
+    <message>
+        <location filename="../../Core/System.cpp" line="177"/>
+        <source>Can't save file</source>
+        <translation>Impossible de sauver le fichier</translation>
+    </message>
+    <message>
+        <location filename="../../Core/System.cpp" line="195"/>
+        <source>Can't open file</source>
+        <translation>Impossible d'ouvrir un fichier</translation>
+    </message>
+    <message>
+        <source>You are loading a file created with an</source>
+        <translation type="vanished">Vous ouvrez un fichier créé avec une</translation>
+    </message>
+    <message>
+        <source>older version of openmeca</source>
+        <translation type="vanished">version plus ancienne d'OpenMeca</translation>
+    </message>
+    <message>
+        <source>Note that your file version is</source>
+        <translation type="vanished">La version du fichier est</translation>
+    </message>
+    <message>
+        <source>and the software version is</source>
+        <translation type="vanished">La version d'OpenMeca est</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Dialog/DialogLinkLinearMotor.cpp" line="36"/>
+        <source>Displacement</source>
+        <translation>Déplacement</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Prop/PropMotionLaw.cpp" line="57"/>
+        <source>Enabled</source>
+        <translation>Activé</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Prop/PropMotionLaw.cpp" line="61"/>
+        <source>Motion Law</source>
+        <translation>Loi de mouvement</translation>
+    </message>
+    <message>
+        <location filename="../../Item/How/SetTorque.cpp" line="47"/>
+        <source>AbsoluteTorque</source>
+        <translation>CoubleAbsolu</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Link/LinearMotor.cpp" line="45"/>
+        <source>LinearMotor</source>
+        <translation>MoteurLinéaire</translation>
+    </message>
+    <message>
+        <location filename="../../Item/Variable.hpp" line="46"/>
+        <source>Variable</source>
+        <translation>Variable</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/AngularAcceleration.cpp" line="46"/>
+        <source>AngularAcceleration</source>
+        <translation>AccélérationAngulaire</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/AngularPosition.cpp" line="46"/>
+        <source>AngularPosition</source>
+        <translation>PositionAngulaire</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/LinearAcceleration.cpp" line="46"/>
+        <source>LinearAcceleration</source>
+        <translation>AccélérationLinéaire</translation>
+    </message>
+    <message>
+        <location filename="../../Physic/Torque.cpp" line="44"/>
+        <source>Torque</source>
+        <translation>Couple</translation>
+    </message>
+    <message>
+        <location filename="../../Core/XmlConfigFile.cpp" line="67"/>
+        <source>The version of your local configuration file "</source>
+        <translation>La version de votre fichier de configuration local</translation>
+    </message>
+    <message>
+        <location filename="../../Core/XmlConfigFile.cpp" line="69"/>
+        <source>is obsolete</source>
+        <translation>est obsolète</translation>
+    </message>
+    <message>
+        <location filename="../../Core/XmlConfigFile.cpp" line="70"/>
+        <source>OpenMeca will replace it</source>
+        <translation>OpenMeca va le remplacer automatiquement</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/GeneralSetting.cpp" line="90"/>
+        <source>You are going to reset the setting of openmeca, are you sure ?</source>
+        <translation>Vous êtes sur le point de supprimer vos préférences, êtes-vous sûr ?</translation>
+    </message>
+    <message>
+        <source>It means that the config directory</source>
+        <translation type="vanished">Le repertoire de configuration</translation>
+    </message>
+    <message>
+        <source>will be removed</source>
+        <translation type="vanished">va être supprimer</translation>
+    </message>
+    <message>
+        <location filename="../../Main.cpp" line="45"/>
+        <source>Welcome to openmeca</source>
+        <translation>Bienvenu dans openmeca</translation>
+    </message>
+    <message>
+        <location filename="../../Main.cpp" line="60"/>
+        <source>Good bye, see you soon !</source>
+        <translation>Au revoir, a bientot !</translation>
+    </message>
+</context>
+<context>
+    <name>WidgetDouble</name>
+    <message>
+        <location filename="../../Gui/Widget/WidgetDouble.ui" line="14"/>
+        <source>Form</source>
+        <translation>Fenêtre</translation>
+    </message>
+</context>
+<context>
+    <name>WidgetExpr</name>
+    <message>
+        <location filename="../../Gui/Widget/WidgetExpr.ui" line="14"/>
+        <source>Form</source>
+        <translation>Fenêtre</translation>
+    </message>
+</context>
+<context>
+    <name>WidgetScales</name>
+    <message>
+        <source>Form</source>
+        <translation type="obsolete">Fenêtre</translation>
+    </message>
+    <message>
+        <location filename="../../Gui/Widget/WidgetScales.ui" line="25"/>
+        <source>%</source>
+        <translation>%</translation>
+    </message>
+</context>
+<context>
+    <name>WidgetSelectItem</name>
+    <message>
+        <source>Form</source>
+        <translation type="obsolete">Fenêtre</translation>
+    </message>
+</context>
+</TS>
diff --git a/SRC/OpenMeca/Rsc/Xml/LangManager.xml b/SRC/OpenMeca/Rsc/Xml/LangManager.xml
new file mode 100644
index 0000000..4374d23
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Xml/LangManager.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<LangManager Version="1.0.0">
+  <Lang ID="EN" Name="English"  File="" />
+  <Lang ID="FR" Name="French"   File="openmeca_fr.qm" />
+
+  <App UserChoice="EN"/>
+
+</LangManager>
+
diff --git a/SRC/OpenMeca/Rsc/Xml/MenuManager.xml b/SRC/OpenMeca/Rsc/Xml/MenuManager.xml
new file mode 100644
index 0000000..9e6adba
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Xml/MenuManager.xml
@@ -0,0 +1,331 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+<MenuManager Version="1.0.0">
+  
+  <Menu Title="Body">
+    <Class Type="Body">
+      <ActionClass Id="New"/>
+      <ActionClass Id="Edit"/>
+      <ActionClass Id="Delete"/>
+    </Class>
+  </Menu>
+
+  <Menu Title="Link">
+
+    <Menu Title="Motor" Icon="Link/Motor.svg" KeepIconColor="1">
+      <Class Type="Motor">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="LinearMotor" Icon="Link/LinearMotor.svg" KeepIconColor="1">
+      <Class Type="LinearMotor">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+
+    <Menu Title="Revolute" Icon="Link/Revolute.svg" KeepIconColor="1">
+      <Class Type="Revolute">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+    
+    <Menu Title="Slider" Icon="Link/Slider.svg" KeepIconColor="1">
+      <Class Type="Slider">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+    
+    <Menu Title="Cylindrical" Icon="Link/Cylindrical.svg" KeepIconColor="1">
+      <Class Type="Cylindrical">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="Planar" Icon="Link/Planar.svg" KeepIconColor="1">
+      <Class Type="Planar">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+     <Menu Title="PointLine" Icon="Link/PointLine.svg" KeepIconColor="1">
+      <Class Type="PointLine">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="PointPlane" Icon="Link/PointPlane.svg" KeepIconColor="1">
+      <Class Type="PointPlane">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="Spherical" Icon="Link/Spherical.svg" KeepIconColor="1">
+      <Class Type="Spherical">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+    
+    <Menu Title="Screw" Icon="Link/Screw.svg" KeepIconColor="1">
+      <Class Type="Screw">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="Gear" Icon="Link/Gear.svg" KeepIconColor="1">
+      <Class Type="Gear">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="Pulley" Icon="Link/Pulley.svg" KeepIconColor="1">
+      <Class Type="Pulley">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="RackPinion" Icon="Link/RackPinion.svg" KeepIconColor="1">
+      <Class Type="RackPinion">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+    
+    <Menu Title="Spring" Icon="Link/Spring.svg" KeepIconColor="1">
+      <Class Type="Spring">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+
+  </Menu>
+  <Menu Title="Geometry">
+    
+    <Menu Title="Point" Icon="Part/Point.svg">
+      <Class Type="Point">
+      	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+    
+     <Menu Title="Cosmetic" Icon="Cosmetic.svg">
+
+       <Menu Title="Pipe" Icon="Part/Pipe.svg">
+	 <Class Type="Pipe">
+      	   <ActionClass Id="New"/>
+	   <ActionClass Id="Edit"/>
+	   <ActionClass Id="Delete"/>
+	 </Class>
+       </Menu>
+       
+       <Menu Title="Ground" Icon="Shape/Ground.svg">
+	 <Class Type="Ground">
+      	   <ActionClass Id="New"/>
+	   <ActionClass Id="Edit"/>
+	   <ActionClass Id="Delete"/>
+	 </Class>
+       </Menu>
+       
+     </Menu>
+    
+     <Menu Title="Collision shape" Icon="Collision.svg">
+       
+       <Menu Title="Sphere" Icon="Shape/Sphere.svg">
+	 <Class Type="Sphere">
+      	   <ActionClass Id="New"/>
+	   <ActionClass Id="Edit"/>
+	   <ActionClass Id="Delete"/>
+	 </Class>
+       </Menu>
+       
+       <Menu Title="Box" Icon="Shape/Box.svg">
+	 <Class Type="Box">
+      	   <ActionClass Id="New"/>
+	   <ActionClass Id="Edit"/>
+	   <ActionClass Id="Delete"/>
+	 </Class>
+       </Menu>
+       
+       <Menu Title="Cylinder" Icon="Shape/Cylinder.svg">
+	 <Class Type="Cylinder">
+      	   <ActionClass Id="New"/>
+	   <ActionClass Id="Edit"/>
+	   <ActionClass Id="Delete"/>
+	 </Class>
+       </Menu>
+
+     </Menu>
+  </Menu>
+  
+  <Menu Title="Loading">
+
+    <Menu Title="Force" Icon="Load/Force.svg">
+      <Class Type="Load at Force">
+    	<ActionClass Id="New"/>
+    	<ActionClass Id="Edit"/>
+    	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="Torque" Icon="Load/Torque.svg">
+      <Class Type="Load at Torque">
+    	<ActionClass Id="New"/>
+    	<ActionClass Id="Edit"/>
+    	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+
+  </Menu>
+
+  <Menu Title="Sensor">
+    
+    <Menu Title="LinearPosition" Icon="Sensor/LinearPosition.svg">
+      <Class Type="Sensor at LinearPosition">
+    	<ActionClass Id="New"/>
+    	<ActionClass Id="Edit"/>
+    	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="LinearVelocity" Icon="Sensor/LinearVelocity.svg">
+      <Class Type="Sensor at LinearVelocity">
+    	<ActionClass Id="New"/>
+    	<ActionClass Id="Edit"/>
+    	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="LinearAcceleration" Icon="Sensor/LinearAcceleration.svg">
+      <Class Type="Sensor at LinearAcceleration">
+    	<ActionClass Id="New"/>
+    	<ActionClass Id="Edit"/>
+    	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+ <Menu Title="AngularPosition" Icon="Sensor/AngularPosition.svg">
+      <Class Type="Sensor at AngularPosition">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="AngularVelocity" Icon="Sensor/AngularVelocity.svg">
+      <Class Type="Sensor at AngularVelocity">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    <Menu Title="AngularAcceleration" Icon="Sensor/AngularAcceleration.svg">
+      <Class Type="Sensor at AngularAcceleration">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+     <Menu Title="ReactionForce" Icon="Sensor/Force.svg">
+      <Class Type="Sensor at Force">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+     <Menu Title="ReactionTorque" Icon="Sensor/Torque.svg">
+      <Class Type="Sensor at Torque">
+	<ActionClass Id="New"/>
+	<ActionClass Id="Edit"/>
+	<ActionClass Id="Delete"/>
+      </Class>
+    </Menu>
+
+    
+
+    <Separator/>
+    <Action Title="Plot data..." UniqueId="ShowData"/>
+    <Action Title="Save data..." UniqueId="SaveData"/>
+    
+  </Menu>
+
+  <Menu Title="Variable">
+    <Class Type="Variable">
+      <ActionClass Id="New"/>
+      <ActionClass Id="Edit"/>
+      <ActionClass Id="Delete"/>
+    </Class>
+  </Menu>
+
+  
+  <Menu Title="System">
+    <Class Type="Simulation">
+      <ActionClass Id="Edit" Title="Simulation" />
+    </Class>
+    <Class Type="Scales">
+      <ActionClass Id="Edit" Title="Scales" />
+    </Class>
+    <Class Type="Gravity">
+      <ActionClass Id="Edit" Title="Gravity" />
+    </Class>
+  </Menu>
+
+
+  <Menu Title="Help">
+    <Action Title="About..."  UniqueId="About"/>
+    <Action Title="Help..."   UniqueId="Help"/>
+    <Action Title="3D viewer help..." UniqueId="HelpViewer"/>
+    
+  </Menu>
+
+
+</MenuManager>
diff --git a/SRC/OpenMeca/Rsc/Xml/UnitManager.xml b/SRC/OpenMeca/Rsc/Xml/UnitManager.xml
new file mode 100644
index 0000000..bb5642b
--- /dev/null
+++ b/SRC/OpenMeca/Rsc/Xml/UnitManager.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="US-ASCII"?>
+<!-- This file is part of OpenMeca, an easy software to do mechanical simulation. -->
+
+<!-- Author(s)    :  - Damien ANDRE  openmeca at yakuru.fr -->
+
+<!-- Copyright (C) 2012-2017 Damien ANDRE -->
+
+<!-- This program is free software: you can redistribute it and/or modify -->
+<!-- it under the terms of the GNU General Public License as published by -->
+<!-- the Free Software Foundation, either version 3 of the License, or -->
+<!-- (at your option) any later version. -->
+
+<!-- This program is distributed in the hope that it will be useful, -->
+<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
+<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -->
+<!-- GNU General Public License for more details. -->
+
+<!-- You should have received a copy of the GNU General Public License -->
+<!-- along with this program.  If not, see http://www.gnu.org/licenses. -->
+
+<UnitManager Version="1.0.0">
+
+  <Dimension Name="Force" UserChoice="Newton">
+    <Unit Name="Newton"    Symbol="N"     Factor="1."/>
+  </Dimension>
+
+  <Dimension Name="Stiffness" UserChoice="NewtonPerMeter">
+    <Unit Name="NewtonPerMeter" Symbol="N/m" Factor="1."/>
+  </Dimension>
+
+  <Dimension Name="DampingFactor" UserChoice="NewtonPerMeterPerSecond">
+    <Unit Name="NewtonPerMeterPerSecond" Symbol="N/(m/s)" Factor="1."/>
+  </Dimension>
+
+
+  <Dimension Name="Torque" UserChoice="NewtonPerMeter">
+    <Unit Name="NewtonPerMeter" Symbol="N/m" Factor="1."/>
+  </Dimension>
+
+
+  <Dimension Name="Length" UserChoice="Meter">
+    <Unit Name="Meter"      Symbol="m" Factor="1."/>
+    <Unit Name="Millimeter" Symbol="mm" Factor="1.e-3"/> 
+  </Dimension>
+
+  <Dimension Name="Angle" UserChoice="Degree">
+    <Unit Name="Radian"      Symbol="rad" Factor="1."/>
+    <Unit Name="Degree"      Symbol="d" Factor="0.017453292519943295"/> 
+  </Dimension>
+
+  <Dimension Name="Step" UserChoice="MeterPerRevolution">
+    <Unit Name="MeterPerRadian" Symbol="m/rad" Factor="1."/>
+    <Unit Name="MeterPerRevolution" Symbol="m/rev" Factor="0.1592356687898089"/>
+  </Dimension>
+
+  <Dimension Name="AngularVelocity" UserChoice="RadianPerSecond">
+    <Unit Name="RadianPerSecond" Symbol="rad/s" Factor="1."/>
+  </Dimension>
+
+  <Dimension Name="AngularAcceleration" UserChoice="RadianPerSecondSquared">
+    <Unit Name="RadianPerSecondSquared" Symbol="rad/s^2" Factor="1."/>
+  </Dimension>
+  
+
+  <Dimension Name="LinearVelocity" UserChoice="MeterPerSecond">
+    <Unit Name="MeterPerSecond" Symbol="m/s" Factor="1."/>
+  </Dimension>
+
+  <Dimension Name="LinearAcceleration" UserChoice="MeterPerSecondSquared">
+    <Unit Name="MeterPerSecondSquared" Symbol="m/s^2" Factor="1."/>
+  </Dimension>
+
+  
+  <Dimension Name="Mass" UserChoice="Kilogramme">
+    <Unit Name="Kilogramme" Symbol="kg" Factor="1."/>
+    <Unit Name="Gramme"     Symbol="g" Factor="1.e-3"/> 
+  </Dimension>
+
+  <Dimension Name="Inertia" UserChoice="Kilogramme Square Meter">
+    <Unit Name="Kilogramme Square Meter"      Symbol="kg.m^2" Factor="1."/>
+    <Unit Name="Gramme Square Meter"          Symbol="g.m^2" Factor="1.e-3"/> 
+    <Unit Name="Kilogramme Square Millimeter" Symbol="kg.mm^2" Factor="1.e-6"/> 
+    <Unit Name="Gramme Square Millimeter"     Symbol="kg.mm^2" Factor="1.e-9"/> 
+  </Dimension>
+
+  <Dimension Name="Time" UserChoice="Second">
+    <Unit Name="Second"      Symbol="s" Factor="1."/>
+  </Dimension>
+
+  <!-- It's not really dimension -->
+  <Dimension Name="Percent" UserChoice="PercentUnit">
+    <Unit Name="PercentUnit" Symbol="%" Factor="0.01"/>
+    <Unit Name="Fake" Symbol="%" Factor="1"/>
+  </Dimension>
+
+  <Dimension Name="Null" UserChoice="NoUnit">
+    <Unit Name="NoUnit" Symbol="" Factor="1."/>
+  </Dimension>
+
+
+</UnitManager>
+
diff --git a/SRC/OpenMeca/Setting/Gravity.cpp b/SRC/OpenMeca/Setting/Gravity.cpp
new file mode 100644
index 0000000..2f1f04f
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Gravity.cpp
@@ -0,0 +1,84 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Setting/Gravity.hpp"
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Core/SystemSettingCommonProperty.hpp"
+#include "OpenMeca/Gui/Dialog/DialogGravity.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    const 
+    std::string Gravity::GetStrType()
+    {
+      return "Gravity";
+    }
+
+    const 
+    QString Gravity::GetQStrType()
+    {
+      return QObject::tr("Gravity");
+    }
+
+    void
+    Gravity::Init()
+    {
+      Core::SystemSettingT< Gravity>::Get();      
+      Core::Singleton< Core::SystemSettingCommonProperty<Gravity> >::Get().RegisterAction();
+    }
+
+
+    Gravity::Gravity()
+      :Core::SystemSettingT<Gravity>(),
+       g_(0., -9.81, 0.)
+    {
+    }
+
+    Gravity::~Gravity()
+    {
+    }
+
+
+    void 
+    Gravity::Save(boost::archive::text_oarchive& ar, const unsigned int )
+    {
+      ar << BOOST_SERIALIZATION_NVP(g_);
+    }
+
+    void 
+    Gravity::Load(boost::archive::text_iarchive& ar, const unsigned int ) 
+    {
+      ar >> BOOST_SERIALIZATION_NVP(g_);
+    }
+
+    void 
+    Gravity::BuildChSystem(chrono::ChSystem& chSystem)
+    {
+      chSystem.Set_G_acc(g_.ToChVector());
+    }
+
+  }
+}
+ 
+
diff --git a/SRC/OpenMeca/Setting/Gravity.hpp b/SRC/OpenMeca/Setting/Gravity.hpp
new file mode 100644
index 0000000..a5db908
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Gravity.hpp
@@ -0,0 +1,80 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Setting_Gravity_hpp
+#define OpenMeca_Setting_Gravity_hpp
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Core/SystemSettingT.hpp"
+#include "OpenMeca/Core/SetOf.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/None.hpp"
+
+#include "OpenMeca/Geom/Vector.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogGravity;
+  }
+
+  namespace Setting
+  {
+
+    class Gravity : public Core::SystemSettingT<Gravity>, public Core::AutoRegister<Gravity>
+    {
+    public:
+      typedef Gui::DialogGravity Dialog;
+
+    public:  
+      static void Init();
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:    
+      Gravity();
+      ~Gravity();
+
+
+      void Save(boost::archive::text_oarchive&, const unsigned int);
+      void Load(boost::archive::text_iarchive&, const unsigned int);
+
+      void BuildChSystem(chrono::ChSystem&);
+
+      // Accessors
+      OMC_ACCESSOR(Value, Geom::Vector<_3D>,  g_);
+
+
+    private:
+      Gravity(const Gravity&);            //Not Allowed    
+      Gravity& operator=(const Gravity&); //Not Allowed
+
+    private:
+      Geom::Vector<_3D> g_;
+    };
+
+   
+  }
+}
+ 
+#endif
diff --git a/SRC/OpenMeca/Setting/LangManager.cpp b/SRC/OpenMeca/Setting/LangManager.cpp
new file mode 100644
index 0000000..b34a3c5
--- /dev/null
+++ b/SRC/OpenMeca/Setting/LangManager.cpp
@@ -0,0 +1,176 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Setting/LangManager.hpp"
+#include "OpenMeca/Core/GlobalSettingCommonProperty.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+#include <QTranslator>
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    void
+    LangManager::Init()
+    {
+      Core::Singleton< Core::GlobalSettingCommonProperty<LangManager> >::Get();
+      Core::Singleton<LangManager>::Get().ReadXmlFile();
+    }
+
+    const std::string
+    LangManager::GetStrType()
+    {
+      return "LangManager";
+    }
+
+    
+
+    LangManager::LangManager()
+      :Core::GlobalSettingT<LangManager>(),
+       userChoice_(0)
+    {
+      
+    }
+    
+   
+    LangManager::~LangManager()
+    {
+    }
+
+    void LangManager::ReadXmlFile()
+    {
+      QDomDocument doc("");
+      QFile& file = OpenXmlConfigFile();
+      OMC_ASSERT_MSG(doc.setContent(&file), "Can't set content of the xml doc");
+      QDomNode n = doc.firstChild();
+      while (!n.isNull()) 
+	{
+	  if (n.isElement()) 
+	    {
+	      QDomElement e = n.toElement();
+	      if (e.tagName()==QString(GetStrType().c_str()))
+		{
+		  QDomNode n1 = e.firstChild ();
+		  while (!n1.isNull()) 
+		    {
+		      if (n1.isElement()) 
+			{
+			  QDomElement e1(n1.toElement());
+			  if (e1.tagName() == "Lang")
+			    AddLang(e1);
+			  else if (e1.tagName() == "App")
+			    SetUserChoice(e1);
+			  else
+			    OMC_ASSERT_MSG(0, "Unknown case");
+			}
+		      n1 = n1.nextSibling();
+		    }
+		}
+	    }
+	  n = n.nextSibling();
+	}
+    }
+    
+ 
+    void LangManager::AddLang(QDomElement& e)
+    {
+      const std::string id   = e.attribute ("ID").toStdString();
+      const std::string name = e.attribute ("Name").toStdString();
+      const std::string file = e.attribute ("File").toStdString();
+
+      OMC_ASSERT_MSG(!id.empty() && !name.empty(), "One of these attributes is empty");
+      new Util::Lang(id, name, file);
+      
+    }
+
+    void LangManager::SetUserChoice(QDomElement& e)
+    {
+      OMC_ASSERT_MSG(userChoice_ == 0, "User choice must be null before its initialization");
+      
+      userChoice_ = &Util::Lang::GetByID(e.attribute ("UserChoice").toStdString());
+    }
+
+    void LangManager::WriteXmlFile()
+    {
+      OMC_ASSERT_MSG(0, "TODO");
+    }
+
+    const Util::Lang& 
+    LangManager::GetUserChoice()
+    {
+      OMC_ASSERT_MSG(userChoice_ != 0, "The user choice is null");
+      return *userChoice_;
+    }
+
+    void 
+    LangManager::Apply(QApplication& app)
+    {
+      OMC_ASSERT_MSG(userChoice_ != 0, "The user choice is null");
+      const QString file = userChoice_->GetFile().c_str();      
+      if (file != "")
+	{
+	  QTranslator* tr = new QTranslator();
+	  tr->load(":/Rsc/Lang/" + file);
+	  app.installTranslator(tr);
+	}
+    }
+
+    void 
+    LangManager::SetUserChoice(const Util::Lang& lang)
+    {
+      QDomDocument doc("");
+      QFile& file = OpenXmlConfigFile();
+      OMC_ASSERT_MSG(doc.setContent(&file), "Can't set doc content");
+      QDomNode n = doc.firstChild();
+      while (!n.isNull()) 
+	{
+	  if (n.isElement()) 
+	    {
+	      QDomElement e = n.toElement();
+	      if (e.tagName()==QString(GetStrType().c_str()))
+		{
+		  QDomNode n1 = e.firstChild ();
+		  while (!n1.isNull()) 
+		    {
+		      if (n1.isElement()) 
+			{
+			  QDomElement e1(n1.toElement());
+			  if (e1.tagName() == "App")
+			    {
+			      e1.setAttribute("UserChoice", lang.GetID().c_str());
+			    }
+			}
+		      n1 = n1.nextSibling();
+		    }
+		}
+	    }
+	  n = n.nextSibling();
+	}
+      
+      SaveXmlConfigFile(doc);
+      
+
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Setting/LangManager.hpp b/SRC/OpenMeca/Setting/LangManager.hpp
new file mode 100644
index 0000000..d5ed9cc
--- /dev/null
+++ b/SRC/OpenMeca/Setting/LangManager.hpp
@@ -0,0 +1,75 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_LangManager_hpp
+#define OpenMeca_Core_LangManager_hpp
+
+#include <QDomDocument>
+#include <QMenu>
+
+#include "OpenMeca/Core/GlobalSettingT.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Util/Lang.hpp"
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    // The MenuManager manage the file that customize the openmeca's units
+    class LangManager : public Core::GlobalSettingT<LangManager>  
+    {
+      friend class Core::Singleton<LangManager> ;
+
+    public:  
+      static void Init();
+      static const std::string GetStrType(); 
+  
+      void ReadXmlFile();
+      void WriteXmlFile();
+
+      void AddLang(QDomElement& e);
+      void SetUserChoice(QDomElement& e);
+      void SetUserChoice(const Util::Lang& lang);
+      void Apply(QApplication& app);
+      const Util::Lang& GetUserChoice();
+      
+      typedef double Dialog; // fake, change this plz !
+
+    private:
+      LangManager();
+      ~LangManager();
+
+    private :
+      LangManager(const LangManager&);             //Not Allowed
+      LangManager& operator=(const LangManager&);  //Not Allowed
+
+
+    private:
+      Util::Lang* userChoice_;
+
+
+    }; 
+    
+    
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Setting/MenuManager.cpp b/SRC/OpenMeca/Setting/MenuManager.cpp
new file mode 100644
index 0000000..827732a
--- /dev/null
+++ b/SRC/OpenMeca/Setting/MenuManager.cpp
@@ -0,0 +1,241 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Setting/MenuManager.hpp"
+#include "OpenMeca/Core/GlobalSettingCommonProperty.hpp"
+#include "OpenMeca/Util/Icon.hpp"
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    void
+    MenuManager::Init()
+    {
+      Core::Singleton< Core::GlobalSettingCommonProperty<MenuManager> >::Get();
+      Core::Singleton<MenuManager>::Get().ReadXmlFile();
+    }
+
+    const std::string
+    MenuManager::GetStrType()
+    {
+      return "MenuManager";
+    }
+
+    
+
+    MenuManager::MenuManager()
+      :Core::GlobalSettingT<MenuManager>(),
+       menuKey_("Menu"),
+       classKey_("Class"),
+       actionClassKey_("ActionClass"),
+       actionKey_("Action"),
+       separatorKey_("Separator"),
+       actions_()
+    {
+    }
+    
+   
+    MenuManager::~MenuManager()
+    {
+    }
+
+    std::string 
+    MenuManager::GetClassId() const
+    {
+      return GetStrType();
+    }
+
+    void MenuManager::ReadXmlFile()
+    {
+      QDomDocument doc("mydocument");
+      QFile& file = OpenXmlConfigFile();
+      OMC_ASSERT_MSG(doc.setContent(&file), "Can't set content of the xml file");
+      QDomNode n = doc.firstChild();
+      std::map<const QDomElement*, QMenu* > menuNode;
+
+      while (!n.isNull()) 
+	{
+	  if (n.isElement()) 
+	    {
+	      QDomElement e = n.toElement();
+	      if (e.tagName()==QString(GetClassId().c_str()))
+		{
+		  QDomNode n1 = e.firstChild ();
+		  while (!n1.isNull()) 
+		    {
+		      if (n1.isElement()) 
+			{
+			  QDomElement e1 = n1.toElement();
+			  const QString title = QObject::tr(qPrintable(e1.attribute("Title")));
+			  OMC_ASSERT_MSG(title != QString(), "The title is empty");
+			  QMenu* menu = 0;
+			  if (e1.hasAttribute("Icon"))
+			    {
+			      QIcon icon = BuildIcon(e1);
+			      menu = Gui::MainWindow::Get().menuBar()->addMenu(icon, title);
+			    }
+			  else
+			    menu = Gui::MainWindow::Get().menuBar()->addMenu(title);
+			  ReadMenu(e1, menu);
+			}
+		      n1 = n1.nextSibling();
+		    }
+		}
+	    }
+	  n = n.nextSibling();
+	}
+    }
+    
+    void
+    MenuManager::ReadMenu(QDomElement& e, QMenu* menu)
+    {
+      OMC_ASSERT_MSG(e.tagName()==QString(menuKey_.c_str()),
+		 "The first tag name must be MenuManager");
+      QDomNode n = e.firstChild ();
+      while (!n.isNull()) 
+	{
+	  if (n.isElement()) 
+	    {
+	      
+	      QDomElement e = n.toElement();
+	      if (e.tagName()==QString(classKey_.c_str()))
+		{
+		  const QString type = e.attribute("Type");
+		  Core::CommonProperty& theClass = Core::CommonProperty::GetClass(type.toStdString());
+
+		  QDomNode n1 = e.firstChild ();
+		  while (!n1.isNull()) 
+		    {
+		      if (n1.isElement()) 
+			{
+			  
+			  QDomElement e1 = n1.toElement();
+			  if (e1.tagName()==QString(actionClassKey_.c_str()))
+			    {
+			      const QString Id = e1.attribute("Id");
+			      Core::Action& action = theClass.GetAction(Id.toStdString());
+			      if (e1.hasAttribute("Title"))
+				{
+				  const QString title = QObject::tr(qPrintable(e1.attribute("Title")));
+				  action.setText(title);
+				}
+			      menu->addAction(&action);
+			    }
+			  else if (e1.tagName()==QString(separatorKey_.c_str()))
+			    {
+			      menu->addSeparator();
+			    }
+			  else if(e.tagName()==QString(actionKey_.c_str()))
+			    {
+			      AddAction(e, menu);
+			    }
+			  else
+			    {
+			      OMC_ASSERT_MSG(0, "Unknown tag name");
+			    }
+			}
+		      n1 = n1.nextSibling();
+		    }
+		    
+		  
+		}
+	      else if(e.tagName()==QString(actionKey_.c_str()))
+		{
+		  AddAction(e, menu);
+		}
+	      
+	      else if (e.tagName()==QString(menuKey_.c_str()))
+		{
+		  const QString title = QObject::tr(qPrintable(e.attribute("Title")));
+		  OMC_ASSERT_MSG(title!=QString(), "The title is empty");
+
+		  QMenu* childmenu = 0;
+		  if (e.hasAttribute("Icon"))
+		    {
+		      QIcon icon = BuildIcon(e);
+		      childmenu = menu->addMenu(icon, title);
+		    }
+		  else
+		    childmenu = menu->addMenu(title);
+		  
+		  ReadMenu(e, childmenu);
+		}
+	      
+	      else if (e.tagName()==QString(separatorKey_.c_str()))
+		{
+		  menu->addSeparator();
+		}
+	      else
+		{
+		  OMC_ASSERT_MSG(0, "Unknown tag name");
+		}
+
+	      
+	    }
+	  n = n.nextSibling();
+	}
+    }
+
+    void MenuManager::AddAction(QDomElement& e, QMenu* menu)
+    {
+      OMC_ASSERT_MSG(e.tagName()==QString(actionKey_.c_str()), "Unknown tag name");
+      const QString title = QObject::tr(qPrintable(e.attribute("Title")));
+      const QString UniqueID = e.attribute("UniqueId");
+      OMC_ASSERT_MSG(actions_.count(UniqueID.toStdString()) == 0, "This action ID already exists");
+      QAction* action = new QAction(title, menu);
+      if (e.hasAttribute("Icon"))
+	action->setIcon(BuildIcon(e));
+      menu->addAction(action);
+      actions_[UniqueID.toStdString()] = action;
+    }
+
+    QAction* 
+    MenuManager::GetQAction(const std::string& actionID)
+    {
+      OMC_ASSERT_MSG(actions_.count(actionID) == 1, "Can't find this action");
+      return actions_[actionID];
+    }
+
+
+    void MenuManager::WriteXmlFile()
+    {
+      OMC_ASSERT_MSG(0, "Not implemented yet");//TODO
+      
+    }
+
+    QIcon 
+    MenuManager::BuildIcon(QDomElement& e)
+    {
+      OMC_ASSERT_MSG(e.hasAttribute("Icon"),
+		     "The element must have the Icon tag !");
+      const QString iconStr = ":/Rsc/Img/" + e.attribute("Icon");
+      QIcon icon;
+      if (e.hasAttribute("KeepIconColor"))
+	icon = Util::Icon::DrawIconFromSvgFile(iconStr);
+      else
+	Util::Icon::DrawIconFromSvgFile(iconStr, icon, Qt::gray);
+      return icon;
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Setting/MenuManager.hpp b/SRC/OpenMeca/Setting/MenuManager.hpp
new file mode 100644
index 0000000..6085189
--- /dev/null
+++ b/SRC/OpenMeca/Setting/MenuManager.hpp
@@ -0,0 +1,75 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_MenuManager_hpp
+#define OpenMeca_Core_MenuManager_hpp
+
+#include <QDomDocument>
+#include <QMenu>
+
+#include "OpenMeca/Core/GlobalSettingT.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    // The MenuManager manage the file that customize the openmeca's menus
+    class MenuManager : public Core::GlobalSettingT<MenuManager>  
+    {
+      friend class Core::Singleton<MenuManager> ;
+
+    public:  
+      static void Init();
+      static const std::string GetStrType(); 
+      typedef double Dialog; // fake, change this plz !
+  
+      std::string GetClassId() const;
+      void ReadXmlFile();
+      void WriteXmlFile();
+      QAction* GetQAction(const std::string& actionID);
+
+    private:
+      MenuManager();
+      ~MenuManager();
+      void ReadMenu(QDomElement& e, QMenu* menu);
+      void AddAction(QDomElement& e, QMenu* menu);
+      QIcon BuildIcon(QDomElement& e);
+
+    private:
+      const std::string menuKey_;
+      const std::string classKey_;
+      const std::string actionClassKey_;
+      const std::string actionKey_;
+      const std::string separatorKey_;
+      std::map<const std::string, QAction*> actions_;
+      
+    private :
+      MenuManager(const MenuManager&);             //Not Allowed
+      MenuManager& operator=(const MenuManager&);  //Not Allowed
+    }; 
+    
+    
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Setting/Scales.cpp b/SRC/OpenMeca/Setting/Scales.cpp
new file mode 100644
index 0000000..ada536b
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Scales.cpp
@@ -0,0 +1,149 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Setting/Scales.hpp"
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Core/SystemSettingCommonProperty.hpp"
+#include "OpenMeca/Gui/Dialog/DialogScales.hpp"
+
+#include "OpenMeca/Physic/LinearVelocity.hpp"
+#include "OpenMeca/Physic/LinearAcceleration.hpp"
+#include "OpenMeca/Physic/AngularVelocity.hpp"
+#include "OpenMeca/Physic/AngularAcceleration.hpp"
+#include "OpenMeca/Physic/Force.hpp"
+#include "OpenMeca/Physic/Torque.hpp"
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    const 
+    std::string Scales::GetStrType()
+    {
+      return "Scales";
+    }
+
+    const 
+    QString Scales::GetQStrType()
+    {
+      return QObject::tr("Scales");
+    }
+
+
+    void
+    Scales::Init()
+    {
+      Core::SystemSettingT< Scales>::Get();      
+      Core::Singleton< Core::SystemSettingCommonProperty<Scales> >::Get().RegisterAction();
+    }
+
+
+    Scales::Scales()
+      :Core::SystemSettingT<Scales>(),
+       scales_(),
+       widget_(0)
+    {
+
+      // set all the scales
+      AddScale(OpenMeca::Item::Part::GetStrType()); 
+      AddScale(OpenMeca::Geom::Frame<_3D>::GetStrType()); 
+      AddScale(OpenMeca::Physic::LinearVelocity::GetStrType()); 
+      AddScale(OpenMeca::Physic::LinearAcceleration::GetStrType()); 
+      AddScale(OpenMeca::Physic::AngularVelocity::GetStrType()); 
+      AddScale(OpenMeca::Physic::AngularAcceleration::GetStrType()); 
+      AddScale(OpenMeca::Physic::Force::GetStrType()); 
+      AddScale(OpenMeca::Physic::Torque::GetStrType()); 
+    }
+
+    Scales::~Scales()
+    {
+    }
+
+    void 
+    Scales::SetWidget(Gui::WidgetScales& widget)
+    {
+      widget_ = &widget;
+    }
+    
+     void 
+     Scales::AddScale(const std::string& scaleKey)
+     {
+       OMC_ASSERT_MSG(scales_.count(scaleKey) == 0, "This scale already exist");
+       scales_[scaleKey] = 1.;
+       scaleKeys_.push_back(scaleKey);
+     } 
+
+    double& 
+    Scales::GetScaleValue(const std::string& scaleKey)
+    {
+      OMC_ASSERT_MSG(scales_.count(scaleKey) == 1, "Can't find this scale");
+      return scales_[scaleKey];
+    }
+
+    const std::vector<std::string>& 
+    Scales::GetKeys() const 
+    {
+      return scaleKeys_;
+    }
+
+    void
+    Scales::Update()
+    {
+      OMC_ASSERT_MSG(widget_ != 0, "Widget is null");
+      widget_->Update();
+    }
+
+    void 
+    Scales::Save(boost::archive::text_oarchive& ar, const unsigned int )
+    {
+      const unsigned int size = scales_.size();
+      ar << BOOST_SERIALIZATION_NVP(size);
+
+      std::map<std::string, double>::const_iterator it;
+      for (it=scales_.begin(); it!=scales_.end(); ++it)
+	{
+	  const std::string key = it->first;
+	  const double value = it->second;
+	  ar << BOOST_SERIALIZATION_NVP(key);
+	  ar << BOOST_SERIALIZATION_NVP(value);
+	}
+    }
+
+    void 
+    Scales::Load(boost::archive::text_iarchive& ar, const unsigned int ) 
+    {
+      unsigned int size = 0;
+      ar >> BOOST_SERIALIZATION_NVP(size);
+      for (unsigned int i=0; i<size; i++)
+	{
+	  std::string key = "";
+	  double value = 0;
+	  ar >> BOOST_SERIALIZATION_NVP(key);
+	  ar >> BOOST_SERIALIZATION_NVP(value);
+	  OMC_ASSERT_MSG(key != "", "The key is empty");
+	  scales_[key] = value;
+	}
+    }
+
+  }
+}
+ 
+
diff --git a/SRC/OpenMeca/Setting/Scales.hpp b/SRC/OpenMeca/Setting/Scales.hpp
new file mode 100644
index 0000000..11f7be0
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Scales.hpp
@@ -0,0 +1,84 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Setting_Scales_hpp
+#define OpenMeca_Setting_Scales_hpp
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Core/SystemSettingT.hpp"
+#include "OpenMeca/Core/SetOf.hpp"
+#include "OpenMeca/Gui/Widget/WidgetScales.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/None.hpp"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogScales;
+  }
+
+  namespace Setting
+  {
+
+
+    // Class that models the different scales for the 3D view. All the 
+    // 3D object can be scaled by the user to adapt the sketch to the 
+    // system dimension.
+    class Scales : public Core::SystemSettingT<Scales>, public Core::AutoRegister<Scales>
+    {
+    public:
+      typedef Gui::DialogScales Dialog;
+
+    public:  
+      static void Init();
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:    
+      Scales();
+      ~Scales();
+
+      void SetWidget(Gui::WidgetScales&);
+      void AddScale(const std::string&);
+      double& GetScaleValue(const std::string&);
+      void Update();
+      const std::vector<std::string>& GetKeys() const;
+
+      void Save(boost::archive::text_oarchive&, const unsigned int);
+      void Load(boost::archive::text_iarchive&, const unsigned int);
+
+    private:
+      Scales(const Scales&);            //Not Allowed    
+      Scales& operator=(const Scales&); //Not Allowed
+
+    private:
+      std::map<std::string, double> scales_;
+      std::vector<std::string> scaleKeys_;
+      Gui::WidgetScales* widget_;
+    };
+
+   
+  }
+}
+ 
+#endif
diff --git a/SRC/OpenMeca/Setting/Scene.cpp b/SRC/OpenMeca/Setting/Scene.cpp
new file mode 100644
index 0000000..5c4ced8
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Scene.cpp
@@ -0,0 +1,128 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Setting/Scene.hpp"
+#include "OpenMeca/Item/Part.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Core/SystemSettingCommonProperty.hpp"
+#include "OpenMeca/Gui/Dialog/DialogScene.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    const 
+    std::string Scene::GetStrType()
+    {
+      return "Scene";
+    }
+
+    const 
+    QString Scene::GetQStrType()
+    {
+      return QObject::tr("Scene");
+    }
+
+    void
+    Scene::Init()
+    {
+      Core::SystemSettingT<Scene>::Get(); 
+      Core::Singleton< Core::SystemSettingCommonProperty<Scene> >::Get().RegisterAction();
+      
+    }
+
+
+    Scene::Scene()
+      :Core::SystemSettingT<Scene>(),
+       drawAxis_(true),
+       backgroundColor_(Qt::darkGray),
+       sceneCenter_(0.,0.,0.),
+       sceneRadius_(1.),
+       cameraType_(qglviewer::Camera::PERSPECTIVE)
+    {
+    }
+
+    Scene::~Scene()
+    {
+    }
+
+    void
+    Scene::Update()
+    {
+      Gui::Viewer& viewer = Gui::MainWindow::Get().GetViewer();
+      viewer.setBackgroundColor(backgroundColor_.GetQColor());
+      viewer.setSceneCenter(sceneCenter_.ToQGLVector());
+      viewer.setSceneRadius(sceneRadius_);
+      viewer.camera()->setType(cameraType_);
+      viewer.DrawAxis(drawAxis_);
+      viewer.updateGL();
+    }
+
+    
+    void
+    Scene::ComputeOptimalSceneRadius()
+    {
+      double rmax = 0;
+
+      Core::SetOf<OpenMeca::Item::Part>::it it;
+      Core::SetOf<OpenMeca::Item::Part>& set = 
+	Core::System::Get().GetSetOf<OpenMeca::Item::Part>();
+
+      for (it = set.Begin() ; it != set.End(); it++ )
+    	{
+    	  const Geom::Point<_3D>& p = (*it)->GetFrame().GetCenter();
+    	  const Geom::Point<_3D> pp(p, &Geom::Frame<_3D>::GetGlobal);
+    	  const double norm = pp.GetPositionVector().GetNorm();
+    	  if (norm > rmax)
+    	    rmax = norm;
+    	  (*it)->Update();
+    	}
+      sceneRadius_ = rmax;
+    }
+
+
+    void 
+    Scene::Save(boost::archive::text_oarchive& ar, const unsigned int )
+    {
+      ar << BOOST_SERIALIZATION_NVP(drawAxis_);
+      ar << BOOST_SERIALIZATION_NVP(backgroundColor_);
+      ar << BOOST_SERIALIZATION_NVP(sceneCenter_);
+      ar << BOOST_SERIALIZATION_NVP(sceneRadius_);
+      ar << BOOST_SERIALIZATION_NVP(cameraType_);
+
+    }
+
+    void 
+    Scene::Load(boost::archive::text_iarchive& ar, const unsigned int ) 
+    {
+      ar >> BOOST_SERIALIZATION_NVP(drawAxis_);
+      ar >> BOOST_SERIALIZATION_NVP(backgroundColor_);
+      ar >> BOOST_SERIALIZATION_NVP(sceneCenter_);
+      ar >> BOOST_SERIALIZATION_NVP(sceneRadius_);
+      ar >> BOOST_SERIALIZATION_NVP(cameraType_);
+    }
+
+
+  }
+}
+ 
+
diff --git a/SRC/OpenMeca/Setting/Scene.hpp b/SRC/OpenMeca/Setting/Scene.hpp
new file mode 100644
index 0000000..d909c58
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Scene.hpp
@@ -0,0 +1,98 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Setting_Scene_hpp
+#define OpenMeca_Setting_Scene_hpp
+
+#include <QGLViewer/camera.h>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Core/SystemSettingT.hpp"
+#include "OpenMeca/Core/SetOf.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+#include "OpenMeca/Core/None.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+#include "OpenMeca/Geom/Point.hpp"
+#include "OpenMeca/Util/Color.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogScene;
+  }
+
+  namespace Setting
+  {
+
+    class Scene : public Core::SystemSettingT<Scene>, public Core::AutoRegister<Scene>
+    {
+    public:
+      typedef Gui::DialogScene Dialog;
+
+    public:  
+      static void Init();
+      static const std::string GetStrType();
+      static const QString GetQStrType();
+
+    public:    
+      Scene();
+      ~Scene();
+
+
+
+
+      void Update();
+      void ComputeOptimalSceneRadius();
+
+      void Save(boost::archive::text_oarchive&, const unsigned int);
+      void Load(boost::archive::text_iarchive&, const unsigned int);
+
+      // Accessor
+      OMC_ACCESSOR(DrawAxis       , bool                  , drawAxis_       );
+      OMC_ACCESSOR(BackgroundColor, Util::Color           , backgroundColor_);
+      OMC_ACCESSOR(SceneCenter    , Geom::Vector<_3D>     , sceneCenter_    );
+      OMC_ACCESSOR(SceneRadius    , double                , sceneRadius_    );
+      OMC_ACCESSOR(CameraType    , qglviewer::Camera::Type, cameraType_    );
+
+
+    private:
+      Scene(const Scene&);            //Not Allowed    
+      Scene& operator=(const Scene&); //Not Allowed
+
+    private:
+      bool drawAxis_;
+      Util::Color backgroundColor_;
+      Geom::Vector<_3D> sceneCenter_;
+      double sceneRadius_;
+      qglviewer::Camera::Type cameraType_;
+      
+      
+    };
+
+   
+  }
+}
+ 
+#endif
diff --git a/SRC/OpenMeca/Setting/Setting.pro b/SRC/OpenMeca/Setting/Setting.pro
new file mode 100644
index 0000000..93f349c
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Setting.pro
@@ -0,0 +1,37 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+HEADERS += Setting/MenuManager.hpp \
+           Setting/UnitManager.hpp \
+           Setting/LangManager.hpp \
+           Setting/Scales.hpp \
+           Setting/Gravity.hpp \
+           Setting/Simulation.hpp \
+           Setting/Scene.hpp \
+
+
+SOURCES += Setting/MenuManager.cpp \
+           Setting/UnitManager.cpp \
+           Setting/LangManager.cpp \
+           Setting/Scales.cpp \
+           Setting/Gravity.cpp \
+           Setting/Simulation.cpp \
+           Setting/Scene.cpp \
+
diff --git a/SRC/OpenMeca/Setting/Simulation.cpp b/SRC/OpenMeca/Setting/Simulation.cpp
new file mode 100644
index 0000000..e02bfaf
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Simulation.cpp
@@ -0,0 +1,275 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QThread>
+
+#include "OpenMeca/Setting/Simulation.hpp"
+#include "OpenMeca/Core/SystemSettingCommonProperty.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+#include "OpenMeca/Gui/Dialog/DialogSimulation.hpp"
+#include "OpenMeca/Item/Sensor.hpp"
+
+#include "Serialization/export.hpp"
+//Don't forget to export for dynamic serialization of child class
+BOOST_CLASS_EXPORT(OpenMeca::Setting::Simulation)
+BOOST_CLASS_EXPORT(OpenMeca::Core::SystemSettingT<OpenMeca::Setting::Simulation>)
+
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+    
+    const std::string 
+    Simulation::GetStrType()
+    {
+      return "Simulation";
+    }
+
+    const QString 
+    Simulation::GetQStrType()
+    {
+      return QObject::tr("Simulation");
+    }
+
+    void
+    Simulation::Init()
+    {
+      Core::SystemSettingT< Simulation>::Get();      
+      Core::Singleton< Core::SystemSettingCommonProperty<Simulation> >::Get().RegisterAction();
+    }
+
+
+
+    Simulation::Simulation()
+      :QThread(),
+       Core::SystemSettingT<Simulation>(),
+       initialize_(false),
+       current_(),
+       recordTime_(),
+       timeArray_(),
+       timeStep_(0.1),
+       totalSimulationTime_(60.),
+       stopLoopRequired_(false),
+       pauseLoopRequired_(false),
+       animationPeriod_(.1),
+       isRunning_(false)
+    {
+      
+    }
+
+    Simulation::~Simulation()
+    {
+    }
+
+     void
+    Simulation::Start()
+    {
+      isRunning_ = true;
+      if (!initialize_)
+	Initialize();
+
+      stopLoopRequired_ = false;
+      pauseLoopRequired_ = false;
+      Gui::MainWindow::Get().GetViewer().setAnimationPeriod(int(animationPeriod_*1000.));
+      Gui::MainWindow::Get().GetViewer().startAnimation();
+      QThread::start();
+    }
+
+    
+    void
+    Simulation::run()
+    {
+      do
+	{
+	  NextStep();
+	}
+      while(pauseLoopRequired_ == false);
+
+      if (stopLoopRequired_ == true)
+	{
+	  OMC_ASSERT_MSG(Gui::MainWindow::Get().GetViewer().animationIsStarted() == false,
+			 "The animation is already started");
+	  Initialize();
+	}
+    }
+
+
+    void
+    Simulation::Pause()
+    {
+      Gui::MainWindow::Get().GetViewer().stopAnimation();
+      pauseLoopRequired_ = true;
+    }
+
+    void
+    Simulation::Stop()
+    {
+      stopLoopRequired_ = true;
+      Pause();
+      wait();
+      
+      Core::System::Get().ResetState();
+      Gui::MainWindow::Get().GetViewer().updateGL();
+      Initialize();
+      stopLoopRequired_ = false;
+      initialize_ = false;
+      pauseLoopRequired_ = true;
+      isRunning_ = false;
+    }
+    
+    void
+    Simulation::NextStep()
+    {
+      if (current_.time >= totalSimulationTime_)
+	{
+	  emit End();
+	  return;
+	}
+
+      if (current_.iterNumber < current_.totalIterNumber)
+	current_.iterNumber  = current_.totalIterNumber;
+
+      Core::System::Get().GetChSystem().DoStepDynamics(timeStep_);
+      OMC_ASSERT_MSG(recordTime_.count(current_.iterNumber) == 1, "the data are not coherent");
+      current_.time = recordTime_[current_.iterNumber];
+      current_.time += timeStep_;
+      current_.iterNumber ++;
+      current_.totalIterNumber = current_.iterNumber;
+      recordTime_[current_.iterNumber] = current_.time;
+      timeArray_.push_back(current_.time);
+      Core::System::Get().UpdateValueFromCh();
+      Core::System::Get().SaveState();
+      emit StepChanged(current_);
+    }
+
+    void
+    Simulation::Initialize()
+    {
+      Core::System::Get().ResetState();
+      Core::System::Get().BuildChSystem();
+      initialize_ = true;
+      pauseLoopRequired_ = false;
+      stopLoopRequired_ = false;
+      recordTime_.clear();
+      timeArray_.clear();
+      current_.Init();
+      recordTime_[current_.iterNumber] = current_.time;
+      timeArray_.push_back(current_.time);
+      Core::System::Get().SaveState();
+      emit StepChanged(current_);
+    }
+
+    void
+    Simulation::GoToStep(unsigned int iter)
+    {
+      Pause();
+      OMC_ASSERT_MSG(recordTime_.count(iter) == 1,
+		 "The data are not coherent");
+      current_.time = recordTime_[iter];
+      current_.iterNumber = iter;
+      Core::System::Get().RecoveryState(iter);
+      Gui::MainWindow::Get().GetViewer().updateGL();
+      emit StepChanged(current_);
+    }
+   
+    double& 
+    Simulation::GetTimeStep()
+    {
+      return timeStep_;
+    }
+
+    const double& 
+    Simulation::GetTimeStep() const
+    {
+      return timeStep_;
+    }
+    
+    double& 
+    Simulation::GetTotalSimulationTime()
+    {
+      return totalSimulationTime_;
+    }
+    
+    const double& 
+    Simulation::GetTotalSimulationTime() const
+    {
+      return totalSimulationTime_;
+    }
+    
+    chrono::ChSystem::eCh_lcpSolver& 
+    Simulation::GetSolver()
+    {
+      return solver_;
+    }
+    
+    const chrono::ChSystem::eCh_lcpSolver& 
+    Simulation::GetSolver() const
+    {
+      return solver_;
+    }
+
+    chrono::ChSystem::eCh_integrationType& 
+    Simulation::GetIntegrationType()
+    {
+      return integrationType_;
+    }
+
+
+    const chrono::ChSystem::eCh_integrationType& 
+    Simulation::GetIntegrationType() const
+    {
+      return integrationType_;
+    }
+
+    const std::vector<double>& 
+    Simulation::GetTimeArray()
+    {
+      return timeArray_;
+    }
+
+
+    bool
+    Simulation::IsRunning() const
+    {
+      return isRunning_;
+    }
+    
+    void
+    Simulation::Save(boost::archive::text_oarchive& ar, const unsigned int )
+    {
+      ar << BOOST_SERIALIZATION_NVP(timeStep_);
+      ar << BOOST_SERIALIZATION_NVP(totalSimulationTime_);
+      ar << BOOST_SERIALIZATION_NVP(animationPeriod_);
+    }
+
+    void
+    Simulation::Load(boost::archive::text_iarchive& ar, const unsigned int version)
+    {
+      ar >> BOOST_SERIALIZATION_NVP(timeStep_);
+      ar >> BOOST_SERIALIZATION_NVP(totalSimulationTime_);
+      if (version >= 2)
+	ar >> BOOST_SERIALIZATION_NVP(animationPeriod_);
+    }
+
+  }
+}
+ 
+
diff --git a/SRC/OpenMeca/Setting/Simulation.hpp b/SRC/OpenMeca/Setting/Simulation.hpp
new file mode 100644
index 0000000..df4bf17
--- /dev/null
+++ b/SRC/OpenMeca/Setting/Simulation.hpp
@@ -0,0 +1,160 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_Simulation_hpp
+#define OpenMeca_Core_Simulation_hpp
+
+#include <QThread>
+#include <map>
+
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Core/SystemSettingT.hpp"
+#include "OpenMeca/Core/SetOf.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+#include "ChronoEngine/physics/ChSystem.h"
+
+namespace OpenMeca
+{
+  namespace Gui
+  {
+    class DialogSimulation; // put the #include in .cpp
+  }
+
+  namespace Setting
+  {
+    
+
+
+    // The simulation settings
+    class Simulation : public QThread,
+		       public Core::SystemSettingT<Simulation>
+    {
+      Q_OBJECT
+    
+    public:
+      typedef Gui::DialogSimulation Dialog;
+
+    public:  
+      static void Init();
+      static const std::string GetStrType(); 
+      static const QString GetQStrType(); 
+      
+    public:
+      struct Step
+      {
+	
+	Step():
+	  time(0.), 
+	  iterNumber(0),
+	  totalIterNumber(0)
+	{
+	}
+
+	void Init() 
+	{
+	  time            = 0.;
+	  iterNumber      = 0 ;
+	  totalIterNumber = 0 ;
+	}
+
+	bool IsCleared()
+	{
+	  return (iterNumber == 0);
+	}
+
+	double time;
+	unsigned int iterNumber;
+	unsigned int totalIterNumber;
+      };
+
+    public:    
+      Simulation();
+      virtual ~Simulation();
+
+
+      void Start();
+      void Pause();
+      void Stop();
+      void NextStep();
+      void Initialize();
+
+      double& GetTimeStep();
+      const double& GetTimeStep() const ;
+
+      double& GetTotalSimulationTime();
+      const double& GetTotalSimulationTime() const ;
+
+      chrono::ChSystem::eCh_lcpSolver& GetSolver();
+      const chrono::ChSystem::eCh_lcpSolver& GetSolver() const;
+
+      chrono::ChSystem::eCh_integrationType& GetIntegrationType();
+      const chrono::ChSystem::eCh_integrationType& GetIntegrationType() const;
+
+      const std::vector<double>& GetTimeArray();
+
+      void Save(boost::archive::text_oarchive&, const unsigned int);
+      void Load(boost::archive::text_iarchive&, const unsigned int);
+
+      OMC_ACCESSOR(AnimationPeriod, double , animationPeriod_);
+
+      bool IsRunning() const;
+
+    public slots:
+      void GoToStep(unsigned int);
+
+    signals:
+      void StepChanged(OpenMeca::Setting::Simulation::Step);
+      void End();
+
+    private:
+      void WaitWhileStepIsRunning();
+      void run();
+
+      Simulation(const Simulation&);            //Not Allowed    
+      Simulation& operator=(const Simulation&); //Not Allowed
+      
+      
+ 
+
+    private:
+      bool initialize_;
+      Step current_;
+      std::map<unsigned int, double> recordTime_;
+      std::vector<double> timeArray_;
+      double timeStep_;
+      double totalSimulationTime_;
+      chrono::ChSystem::eCh_lcpSolver solver_;
+      chrono::ChSystem::eCh_integrationType integrationType_;
+      bool stopLoopRequired_;
+      bool pauseLoopRequired_;
+      double animationPeriod_;
+      bool isRunning_;
+    };
+
+   
+
+
+  }
+}
+ 
+#endif
diff --git a/SRC/OpenMeca/Setting/UnitManager.cpp b/SRC/OpenMeca/Setting/UnitManager.cpp
new file mode 100644
index 0000000..a578de3
--- /dev/null
+++ b/SRC/OpenMeca/Setting/UnitManager.cpp
@@ -0,0 +1,152 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+#include "OpenMeca/Setting/UnitManager.hpp"
+#include "OpenMeca/Core/GlobalSettingCommonProperty.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    void
+    UnitManager::Init()
+    {
+      Core::Singleton< Core::GlobalSettingCommonProperty<UnitManager> >::Get();
+      Core::Singleton<UnitManager>::Get().ReadXmlFile();
+    }
+
+    const std::string
+    UnitManager::GetStrType()
+    {
+      return "UnitManager";
+    }
+
+    
+
+    UnitManager::UnitManager()
+      :Core::GlobalSettingT<UnitManager>()
+    {
+      
+    }
+    
+   
+    UnitManager::~UnitManager()
+    {
+    }
+
+    std::string 
+    UnitManager::GetClassId() const
+    {
+      return GetStrType();
+    }
+
+    void UnitManager::ReadXmlFile()
+    {
+      QDomDocument doc("mydocument");
+      QFile& file = OpenXmlConfigFile();
+      OMC_ASSERT_MSG(doc.setContent(&file), "Can't set file content");
+      QDomNode n = doc.firstChild();
+      while (!n.isNull()) 
+	{
+	  if (n.isElement()) 
+	    {
+	      QDomElement e = n.toElement();
+	      if (e.tagName()==QString(GetClassId().c_str()))
+		{
+		  QDomNode n1 = e.firstChild ();
+		  while (!n1.isNull()) 
+		    {
+		      if (n1.isElement()) 
+			{
+			  QDomElement e1(n1.toElement());
+			  AddDimension(e1);
+			}
+		      n1 = n1.nextSibling();
+		    }
+		}
+	    }
+	  n = n.nextSibling();
+	}
+    }
+    
+ 
+    void UnitManager::AddDimension(QDomElement& e)
+    {
+      OMC_ASSERT_MSG(e.tagName().toStdString() ==  Util::Dimension::GetStrType(),
+		 "Wrong tag name");
+
+      //Read and check xml attributes
+      const std::string name       = e.attribute ("Name").toStdString();
+      const std::string userChoice = e.attribute ("UserChoice").toStdString();
+      OMC_ASSERT_MSG(!name.empty() && !userChoice.empty(),
+		 "One of the attribute is empty");
+      
+      Util::Dimension& dim = *new Util::Dimension(name);
+      
+      QDomNode n1 = e.firstChild ();
+      while (!n1.isNull()) 
+	{
+	  if (n1.isElement()) 
+	    {
+	      QDomElement e1(n1.toElement());
+	      AddUnit(e1, dim);
+	    }
+	  n1 = n1.nextSibling();
+	}
+      
+
+      dim.SetSiUnit();
+      dim.SetUserChoiceUnit(dim.GetUnit(userChoice));
+    }
+
+    void UnitManager::AddUnit(QDomElement& e, Util::Dimension& dim)
+    {
+      OMC_ASSERT_MSG(e.tagName().toStdString() ==  Util::Unit::GetStrType(),
+		 "Wrong tag name");
+      const std::string name = e.attribute("Name").toStdString();
+      const std::string symbol = e.attribute("Symbol").toStdString();
+      const QString factor = e.attribute("Factor");
+      OMC_ASSERT_MSG(!name.empty() && !factor.isEmpty(),
+		 "One of the attribute is empty");
+      
+      double factorValue = 0.;
+      bool conversionOk = false;
+      factorValue = factor.toDouble(&conversionOk);
+      if (conversionOk == false)
+	OMC_ASSERT_MSG(0, "Can't convert unit");
+
+      OMC_ASSERT_MSG(factorValue != 0., "The factor value can't be null");
+      
+      new Util::Unit(dim, name, symbol, factorValue);
+    }
+
+
+    void UnitManager::WriteXmlFile()
+    {
+      OMC_ASSERT_MSG(0, "Not implemented yet");
+    }
+
+  }
+}
diff --git a/SRC/OpenMeca/Setting/UnitManager.hpp b/SRC/OpenMeca/Setting/UnitManager.hpp
new file mode 100644
index 0000000..8c60fce
--- /dev/null
+++ b/SRC/OpenMeca/Setting/UnitManager.hpp
@@ -0,0 +1,69 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_UnitManager_hpp
+#define OpenMeca_Core_UnitManager_hpp
+
+#include <QDomDocument>
+#include <QMenu>
+
+#include "OpenMeca/Core/GlobalSettingT.hpp"
+#include "OpenMeca/Core/System.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+namespace OpenMeca
+{
+  namespace Setting
+  {
+
+    // The MenuManager manage the file that customize the openmeca's units
+    class UnitManager : public Core::GlobalSettingT<UnitManager>  
+    {
+      friend class Core::Singleton<UnitManager> ;
+
+    public:  
+      static void Init();
+      static const std::string GetStrType(); 
+  
+      std::string GetClassId() const;
+      void ReadXmlFile();
+      void WriteXmlFile();
+      
+      typedef double Dialog; // fake, change this plz !
+
+    private:
+      UnitManager();
+      ~UnitManager();
+
+      void AddDimension(QDomElement&);
+      void AddUnit(QDomElement&, Util::Dimension&);
+      
+    private:
+      
+    private :
+      UnitManager(const UnitManager&);             //Not Allowed
+      UnitManager& operator=(const UnitManager&);  //Not Allowed
+    }; 
+    
+    
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Todo.txt b/SRC/OpenMeca/Todo.txt
new file mode 100644
index 0000000..24f0d05
--- /dev/null
+++ b/SRC/OpenMeca/Todo.txt
@@ -0,0 +1,8 @@
+********************
+* TODO & WISH LIST *
+********************
+
+[OK  ] Use unit with widget related to mathematical expression
+[TODO] Create a "Label" user item class to display user defined text in the 3D scene
+[TODO] Create a boolean property to the sensor ad load to display their names in the 3D scene
+[NOTE] The MotionLaw class may be obsolete 
diff --git a/SRC/OpenMeca/Util/Color.cpp b/SRC/OpenMeca/Util/Color.cpp
new file mode 100644
index 0000000..2e40470
--- /dev/null
+++ b/SRC/OpenMeca/Util/Color.cpp
@@ -0,0 +1,161 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+#include <QFile>
+
+#ifndef OSX
+  #include <GL/gl.h>
+#else
+  #include <OpenGL/gl.h>
+#endif
+
+#include "OpenMeca/Util/Color.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+    const Color Color::White  = Color(Qt::white);
+    const Color Color::Black  = Color(Qt::black);
+    const Color Color::Red    = Color(Qt::red);
+    const Color Color::Green  = Color(Qt::green);
+    const Color Color::Blue   = Color(Qt::blue);
+    const Color Color::Yellow = Color(Qt::yellow);
+
+
+    std::ostream& 
+    operator<< (std::ostream& os, const Color & c)
+    {
+      os << "red: "   << c.red_ << '\t'
+	 << "green: " << c.green_ << '\t'
+	 << "blue: "  << c.blue_ << '\t'
+	 << "alpha: " << c.alpha_;
+      return os;
+    }
+
+
+    const QString
+    Color::GetStrType()
+    {
+      return "Color";
+    }
+
+    Color::Color()
+      :red_(0),
+       green_(0),
+       blue_(0),
+       alpha_(255)
+       
+    {
+      srand ( time(NULL) );
+      Randomize();
+    }
+
+    Color::Color(unsigned int r, unsigned int g, unsigned int b, unsigned int a)
+      :red_(r),
+       green_(g),
+       blue_(b),
+       alpha_(a)
+       
+    {
+    }
+
+    Color::Color(unsigned int r, unsigned int g, unsigned int b)
+      :red_(r),
+       green_(g),
+       blue_(b),
+       alpha_(255)
+       
+    {
+    }
+
+    Color::Color(const QColor& col)
+      :red_(col.red()),
+       green_(col.green()),
+       blue_(col.blue()),
+       alpha_(col.alpha())
+       
+    {
+    }
+    
+    Color::Color(const Color& col)
+      :red_(col.red_),
+       green_(col.green_),
+       blue_(col.blue_),
+       alpha_(col.alpha_)
+    {
+    }
+
+
+   
+    Color::~Color()
+    {
+    }
+
+    Color&  
+    Color::operator=(const Color& col)
+    {
+      red_ = col.red_;
+      green_ = col.green_;
+      blue_ = col.blue_;
+      alpha_ = col.alpha_;
+      return *this;
+    }
+
+    void
+    Color::Randomize()
+    {
+      red_   = GetRandomNumber();
+      green_ = GetRandomNumber();
+      blue_  = GetRandomNumber();
+    }
+
+    int
+    Color::GetRandomNumber()
+    {
+      int val = rand() % 256;
+      OMC_ASSERT_MSG( val >= 0 && val <= 255, "Wrong values");
+      return val;
+    }
+
+    QColor
+    Color:: GetQColor() const
+    {
+      return QColor(red_, green_, blue_, alpha_);
+    }
+   
+    void
+    Color::ApplyGLColor() const
+    {
+      float red   = float(red_)  /255.;
+      float green = float(green_)/255.;
+      float blue  = float(blue_) /255.;
+      float alpha = float(alpha_)/255.;
+      glColor4f(red, green, blue, alpha);
+    }
+    
+
+  }
+}
diff --git a/SRC/OpenMeca/Util/Color.hpp b/SRC/OpenMeca/Util/Color.hpp
new file mode 100644
index 0000000..fd76fa0
--- /dev/null
+++ b/SRC/OpenMeca/Util/Color.hpp
@@ -0,0 +1,93 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Color_hpp
+#define OpenMeca_Util_Color_hpp
+
+#include <QString>
+#include <QColor>
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+    class Color;
+
+    std::ostream& operator<< (std::ostream &, const Color &);
+
+    
+    // openmeca's color class
+    class Color
+    {
+    public:
+      friend std::ostream& operator<< (std::ostream &, const Color &);
+
+    public:
+      static const Color White;
+      static const Color Black;
+      static const Color Red;
+      static const Color Green;
+      static const Color Blue;
+      static const Color Yellow;
+
+    public:  
+      static const QString GetStrType(); 
+
+    public:
+      Color();
+      Color(unsigned int, unsigned int, unsigned int, unsigned int);    
+      Color(unsigned int, unsigned int, unsigned int);    
+      Color(const QColor&);
+      Color(const Color&);           
+      Color& operator=(const Color&);
+      ~Color();
+      QColor GetQColor() const;
+      void ApplyGLColor() const;
+      
+    private:
+      void Randomize();
+      int GetRandomNumber();
+
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+       int red_, green_, blue_, alpha_;
+      
+    private :
+      //Copy constructor and assignment operator are built by compiler
+    }; 
+    
+    template<class Archive>
+    inline void
+    Color::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(red_);
+      ar & BOOST_SERIALIZATION_NVP(green_);
+      ar & BOOST_SERIALIZATION_NVP(blue_);
+      ar & BOOST_SERIALIZATION_NVP(alpha_);
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/CustomChFunction.cpp b/SRC/OpenMeca/Util/CustomChFunction.cpp
new file mode 100644
index 0000000..ba63662
--- /dev/null
+++ b/SRC/OpenMeca/Util/CustomChFunction.cpp
@@ -0,0 +1,105 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Util/CustomChFunction.hpp"
+#include "OpenMeca/Util/Var.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    CustomChFunction::CustomChFunction(double& x, double y)
+      :Expr(),
+       chrono::ChFunction(),
+       x_(x), y_(y)
+       
+    {
+      Expr::SetVariable(y_);
+    }
+
+
+    CustomChFunction::~CustomChFunction()
+    {
+    }
+
+    void 
+    CustomChFunction::PostSerializationLoad()
+    {
+      // We manage unit here
+      if (IsExpressionNumber())
+	SetExpressionFromValue(y_/GetFactor());
+    }
+
+
+    double 
+    CustomChFunction::Get_y(double)
+    {
+      Expr::Update();
+      return y_;
+    }
+
+    double 
+    CustomChFunction::Get_y_dx(double)
+    {
+      OMC_ASSERT_MSG(Expr::var_ != 0,
+		     "The variable was not initialized");
+
+      exprtk::expression<double> expression;
+      expression.register_symbol_table(Var::GetSymbolTable());
+
+      exprtk::parser<double> parser;
+      OMC_ASSERT_MSG(parser.compile(Expr::expression_, expression),
+		     "Can't understand the expression \"" + expression_ + "\"");
+      
+      return exprtk::derivative(expression, x_)*GetFactor();
+    }
+
+    double 
+    CustomChFunction::Get_y_dxdx (double)
+    {
+      OMC_ASSERT_MSG(Expr::var_ != 0,
+		     "The variable was not initialized");
+
+      exprtk::expression<double> expression;
+      expression.register_symbol_table(Var::GetSymbolTable());
+
+      exprtk::parser<double> parser;
+      OMC_ASSERT_MSG(parser.compile(Expr::expression_, expression),
+		     "Can't understand the expression \"" + expression_ + "\"");
+      
+      return exprtk::second_derivative(expression, x_)*GetFactor();
+    }
+
+    chrono::ChFunction* 
+    CustomChFunction::new_Duplicate ()
+    {
+      CustomChFunction& f = *new CustomChFunction(x_, y_);
+      f.expression_ = expression_;
+      f.SetDimension(GetDimension());
+      return &f;
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Util/CustomChFunction.hpp b/SRC/OpenMeca/Util/CustomChFunction.hpp
new file mode 100644
index 0000000..1f6e144
--- /dev/null
+++ b/SRC/OpenMeca/Util/CustomChFunction.hpp
@@ -0,0 +1,89 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_CustomChFunction_hpp
+#define OpenMeca_Util_CustomChFunction_hpp
+
+#include "OpenMeca/Util/Expr.hpp"
+#include "ChronoEngine/motion_functions/ChFunction_Base.h"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+
+    class CustomChFunction : public Expr,
+			     public chrono::ChFunction
+    {
+
+
+    public:
+      
+      CustomChFunction(double&, double);
+      virtual ~CustomChFunction();
+      
+      double Get_y      (double);
+      double Get_y_dx   (double);
+      double Get_y_dxdx (double);
+
+      virtual ChFunction* new_Duplicate ();
+
+    private:
+      void PostSerializationLoad();
+
+      friend class boost::serialization::access;
+      template<class Archive> void save(Archive& ar, const unsigned int) const;
+      template<class Archive> void load(Archive& ar, const unsigned int);
+      BOOST_SERIALIZATION_SPLIT_MEMBER()
+
+    private:
+      double& x_;
+      double  y_;
+    };
+
+    template<class Archive>
+    inline void
+    CustomChFunction::save(Archive& ar, const unsigned int) const
+    {
+      ar << BOOST_SERIALIZATION_BASE_OBJECT_NVP(Expr);
+      ar << BOOST_SERIALIZATION_NVP(y_);
+    }
+
+    template<class Archive>
+    inline void
+    CustomChFunction::load(Archive& ar, const unsigned int version)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Expr);
+      if (version >= 1)
+	{
+	  ar & BOOST_SERIALIZATION_NVP(y_);
+	  PostSerializationLoad();
+	}
+    }
+
+  }
+}
+
+#include "Serialization/version.hpp"
+BOOST_CLASS_VERSION(OpenMeca::Util::CustomChFunction, 1)
+
+#endif
diff --git a/SRC/OpenMeca/Util/Dimension.cpp b/SRC/OpenMeca/Util/Dimension.cpp
new file mode 100644
index 0000000..fa54034
--- /dev/null
+++ b/SRC/OpenMeca/Util/Dimension.cpp
@@ -0,0 +1,159 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <iostream>
+
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    std::map<std::string, Dimension*> Dimension::all_ = std::map<std::string, Dimension*>();
+
+    std::string Dimension::GetStrType(){return "Dimension";}
+
+    Dimension& 
+    Dimension::Get(const std::string str)
+    {
+      OMC_ASSERT_MSG(all_.count(str) == 1, "Can't find this dimension");
+      return *all_[str];
+    }
+    
+    bool 
+    Dimension::Exist(const std::string str)
+    {
+      OMC_ASSERT_MSG(all_.count(str) < 2, "Wrong number of dimension");
+      return (all_.count(str)==1);
+    }
+
+
+
+    Dimension::Dimension(std::string name)
+      :name_(name),
+       units_(),
+       siUnit_(0),
+       userChoice_(0)
+    {
+      OMC_ASSERT_MSG(all_.count(name_)==0, "The name is already taken");
+      all_[name_] = this;
+    }
+    
+
+    Dimension::~Dimension()
+    {
+      OMC_ASSERT_MSG(all_.count(name_)==1, "Can't find the required dimension");
+      all_.erase(all_.find(name_));
+    }
+    
+    void 
+    Dimension::AddUnit(Unit& unit)
+    {
+      OMC_ASSERT_MSG(units_.count(unit.GetName())==0, "The unit already exist");
+      units_[unit.GetName()] = &unit;
+    }
+
+    void 
+    Dimension::RemoveUnit(Unit& unit)
+    {
+      OMC_ASSERT_MSG(units_.count(unit.GetName())==1, "Can't find this unit");
+      units_.erase(units_.find(unit.GetName()));
+    }
+      
+    void 
+    Dimension::SetSiUnit(Unit& unit)
+    {
+      OMC_ASSERT_MSG(units_.count(unit.GetName())==1, "Can't foind this unit");
+      siUnit_ = &unit;
+      
+    }
+
+    
+    void 
+    Dimension::SetSiUnit()
+    {
+      //Automactic detection of SiUnits (factor = 1.)
+      std::map<std::string, Unit*>::iterator it;
+      unsigned int count = 0;
+
+      for ( it=units_.begin() ; it != units_.end(); it++ )
+	{
+	  if ((*it).second->GetFactor()==1.)
+	    {
+	      siUnit_ = (*it).second;
+	      count ++;
+	    }
+	}
+
+      OMC_ASSERT_MSG(count == 1, "The Si unit must be unique !");
+    }
+    
+    void 
+    Dimension::SetUserChoiceUnit(Unit& unit)
+    {
+      OMC_ASSERT_MSG(units_.count(unit.GetName())==1, "Can't find this unit");
+      userChoice_ = &unit;
+    }
+
+
+    Unit&  
+    Dimension::GetUnit(const std::string& name)
+    {
+      OMC_ASSERT_MSG(units_.count(name)==1, "Can't find this name");
+      return *units_[name];
+    }
+    
+    const Unit&  
+    Dimension::GetUnit(const std::string& name) const
+    {
+      OMC_ASSERT_MSG(units_.count(name)==1, "Can't find this name");
+      return *units_.find(name)->second;
+    }
+      
+    const std::string& 
+    Dimension::GetName() const
+    {
+      return name_;
+    }
+
+    const std::map<std::string, Unit*>&
+    Dimension::GetUnits() const
+    {
+      return units_;
+    }
+
+    const Unit& 
+    Dimension::GetSiUnit() const
+    {
+      return *siUnit_;
+    }
+
+    const Unit& 
+    Dimension::GetUserChoice() const
+    {
+      return *userChoice_;
+    }
+      
+  }
+}
diff --git a/SRC/OpenMeca/Util/Dimension.hpp b/SRC/OpenMeca/Util/Dimension.hpp
new file mode 100644
index 0000000..ed9ccf7
--- /dev/null
+++ b/SRC/OpenMeca/Util/Dimension.hpp
@@ -0,0 +1,69 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Dimension_hpp
+#define OpenMeca_Util_Dimension_hpp
+
+#include <string>
+#include <map>
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+    class Unit;
+
+    // A dimension (time, length) can be associated to many units
+    class Dimension
+    {
+    public: 
+      static Dimension& Get(const std::string);
+      static bool Exist(const std::string);
+      static std::string GetStrType();
+
+      Dimension(std::string name);
+      ~Dimension();
+      void AddUnit(Unit&);
+      void RemoveUnit(Unit&);
+
+      void SetSiUnit(Unit&);
+      void SetSiUnit();
+      void SetUserChoiceUnit(Unit&);
+
+      Unit& GetUnit(const std::string&);
+      const Unit& GetUnit(const std::string&) const;
+
+      const std::string& GetName() const;
+      const std::map<std::string, Unit*>& GetUnits() const;
+      const Unit& GetSiUnit() const;
+      const Unit& GetUserChoice() const;
+      
+    private :
+      static std::map<std::string, Dimension*> all_;
+
+      const std::string name_;
+      std::map<std::string, Unit*> units_;
+      Unit* siUnit_;
+      Unit* userChoice_;
+    };
+      
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/Draw.cpp b/SRC/OpenMeca/Util/Draw.cpp
new file mode 100644
index 0000000..e7ac6f5
--- /dev/null
+++ b/SRC/OpenMeca/Util/Draw.cpp
@@ -0,0 +1,582 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OSX
+  #include <GL/glu.h>
+#else
+  #include <OpenGL/glu.h>
+#endif
+
+#include <cmath>
+#include <iostream>
+#include "OpenMeca/Util/Draw.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+    struct XYZ
+    {
+      float x, y, z;
+    };
+
+
+     //Static methods that draw misceallous shape
+    void
+    Draw::Cylinder(float radius, float length, bool middlePositinning)
+    {
+      //Draw a cylinder along the x axis with given radius and length
+      glRotatef(90., 0.0, 1.0, 0.0);
+      static GLUquadric* quadric = gluNewQuadric();
+      if (middlePositinning)
+	glTranslatef(0.0f, 0.0f, -length/2);
+      gluCylinder(quadric, radius, radius, length, 30, 1);
+      glTranslatef(0.0f, 0.0f, length);
+      gluDisk(quadric, 0.0, radius, 30, 1);
+      glRotatef(180.0, 0.0, 1.0, 0.0);
+      glTranslatef(0.0f, 0.0f, length);
+      gluDisk(quadric, 0.0, radius, 30, 1);
+      glTranslatef(0.0f, 0.0f, -length/2);
+      glRotatef(-90.0, 0.0, 1.0, 0.0);
+    }
+
+    void
+    Draw::CylinderStripe(float Re, float l)
+    {
+      glRotatef(90., 0.0, 1.0, 0.0);
+      glBegin(GL_LINES);
+      for (float i=0;i<=6.28;i=i+0.05)
+	{
+	  glVertex3f(Re*sin(i),Re*cos(i),-l/2.);
+	  glVertex3f(Re*sin(i),Re*cos(i), l/2.);
+	}
+      glEnd();
+      glRotatef(-90., 0.0, 1.0, 0.0);
+    }
+
+    void Draw::Cylinder(float externRadius, float internRadius, float length)
+    {
+      glRotatef(90., 0.0, 1.0, 0.0);
+      const float Re = externRadius;
+      const float Ri = internRadius;
+      const float l  = length;
+      static GLUquadric* quadric = gluNewQuadric();
+      glTranslatef(0.0f, 0.0f, l/2);
+      gluDisk(quadric, Ri, Re, 30, 1);
+      glRotatef(180, 0.0, 1.0, 0.0);
+      glTranslatef(0.0f, 0.0f, l);
+      gluDisk(quadric, Ri, Re, 30, 1);
+      
+      double i;
+      glBegin(GL_QUAD_STRIP);
+      for (i=0;i<=6.28;i=i+0.2)
+	{
+	  glNormal3f(sin(i),cos(i),0.0f);
+	  glVertex3f(Re*sin(i),Re*cos(i),0.0f);
+	  glVertex3f(Re*sin(i),Re*cos(i),-l);
+	}
+      glNormal3f(0.0f,Re,0.0f);
+      glVertex3f(0.0f,Re,0.0f);
+      glVertex3f(0.0f,Re,-l);
+      glEnd();
+      
+      glBegin(GL_QUAD_STRIP);
+      for (i=0;i<=6.28;i=i+0.2)
+	{
+	  glNormal3f(-sin(i),-cos(i),0.0f);
+	  glVertex3f(Ri*sin(i),Ri*cos(i),0.0f);
+	  glVertex3f(Ri*sin(i),Ri*cos(i),-l);
+	}
+      glNormal3f(0.0f,-Ri,0.0f);
+      glVertex3f(0.0f,Ri,0.0f);
+      glVertex3f(0.0f,Ri,-l);
+      glEnd();
+    }
+
+
+ void Draw::Cylinder(float externRadius, float internRadius, float length, float startAngle, float stopAngle)
+    {
+      glRotatef(90., 0.0, 1.0, 0.0);
+      const float Re = externRadius;
+      const float Ri = internRadius;
+      const float l  = length;
+      
+      double i;
+      glBegin(GL_QUAD_STRIP);
+      for (i=startAngle;i<=stopAngle+0.1;i=i+0.1)
+	{
+	  glNormal3f(sin(i),cos(i),0.0f);
+	  glVertex3f(Re*sin(i),Re*cos(i), -l/2.);
+	  glVertex3f(Re*sin(i),Re*cos(i), l/2.);
+	}
+      
+      glEnd();
+      
+      glBegin(GL_QUAD_STRIP);
+      for (i=startAngle;i<=stopAngle+0.1;i=i+0.1)
+	{
+	  glNormal3f(-sin(i),-cos(i),0.0f);
+	  glVertex3f(Ri*sin(i),Ri*cos(i), -l/2.);
+	  glVertex3f(Ri*sin(i),Ri*cos(i),  l/2.);
+	}
+      glEnd();
+
+
+      glBegin(GL_QUAD_STRIP);
+      for (i=startAngle;i<=stopAngle+0.1;i=i+0.1)
+	{
+	  glNormal3f(0.0f, 0.0f, 1.f);
+	  glVertex3f(Ri*sin(i),Ri*cos(i), -l/2.);
+	  glVertex3f(Re*sin(i),Re*cos(i), -l/2.);
+	  glNormal3f(0.0f, 0.0f, 1.f);
+	}
+      glEnd();
+
+      glBegin(GL_QUAD_STRIP);
+      for (i=startAngle;i<=stopAngle+0.1;i=i+0.1)
+	{
+	  glNormal3f(0.0f, 0.0f, -1.f);
+	  glVertex3f(Ri*sin(i),Ri*cos(i), l/2.);
+	  glVertex3f(Re*sin(i),Re*cos(i), l/2.);
+	  glNormal3f(0.0f, 0.0f, -1.f);
+	}
+      glEnd();
+    }
+
+    void
+    Draw::Sphere(float radius)
+    {
+      //Draw a cylinder along the x axis with given radius and length
+      static GLUquadric* quadric = gluNewQuadric();
+      gluSphere(quadric, radius, 30, 30);
+    }
+
+    void 
+    Draw::Box(float lx, float ly, float lz)
+    {
+      const float Lx = lx/2;
+      const float Ly = ly/2;
+      const float Lz = lz/2;
+      glBegin(GL_QUADS);
+      glNormal3f(1.0f,0.0f,0.0f);
+      glVertex3f(Lx,-Ly,-Lz);
+      glVertex3f(Lx,Ly,-Lz);
+      glVertex3f(Lx,Ly,Lz);
+      glVertex3f(Lx,-Ly,Lz);
+      glEnd();
+      glBegin(GL_QUADS);
+      glNormal3f(-1.0f,0.0f,0.0f);
+      glVertex3f(-Lx,-Ly,-Lz);
+      glVertex3f(-Lx,Ly,-Lz);
+      glVertex3f(-Lx,Ly,Lz);
+      glVertex3f(-Lx,-Ly,Lz);
+      glEnd();
+      glBegin(GL_QUADS);
+      glNormal3f(0.0f,1.0f,0.0f);
+      glVertex3f(Lx,Ly,Lz);
+      glVertex3f(Lx,Ly,-Lz);
+      glVertex3f(-Lx,Ly,-Lz);
+      glVertex3f(-Lx,Ly,Lz);
+      glEnd();
+      glBegin(GL_QUADS);
+      glNormal3f(0.0f,-1.0f,0.0f);
+      glVertex3f(Lx,-Ly,Lz);
+      glVertex3f(Lx,-Ly,-Lz);
+      glVertex3f(-Lx,-Ly,-Lz);
+      glVertex3f(-Lx,-Ly,Lz);
+      glEnd();
+      glBegin(GL_QUADS);
+      glNormal3f(0.0f,0.0f,1.0f);
+      glVertex3f(Lx,Ly,Lz);
+      glVertex3f(Lx,-Ly,Lz);
+      glVertex3f(-Lx,-Ly,Lz);
+      glVertex3f(-Lx,Ly,Lz);
+      glEnd();
+      glBegin(GL_QUADS);
+      glNormal3f(0.0f,0.0f,-1.0f);
+      glVertex3f(Lx,Ly,-Lz);
+      glVertex3f(Lx,-Ly,-Lz);
+      glVertex3f(-Lx,-Ly,-Lz);
+      glVertex3f(-Lx,Ly,-Lz);
+      glEnd();
+    }
+
+    void 
+    Draw::Channel(double Re,double Ri,double l)
+    {
+      static GLUquadric* quadric = gluNewQuadric();
+      glTranslatef(-l/2, 0.0f, 0.0f );
+      glBegin(GL_QUAD_STRIP);
+      for (double i=0; i<=3.14; i=i+0.1)
+	{
+	  glNormal3f(0.0f,sin(i),cos(i));
+	  glVertex3f(0.0f,Re*sin(i),Re*cos(i));
+	  glVertex3f(l,Re*sin(i),Re*cos(i));
+	}
+      glNormal3f(0.0f,0.0f,-Re);
+      glVertex3f(0.0f,0.0f,-Re);
+      glVertex3f(l,0.0f,-Re);
+      glEnd();
+      
+      glBegin(GL_QUAD_STRIP);
+      for (double i=0; i<=3.14; i=i+0.1)
+	{
+	  glNormal3f(0.0f,-sin(i),-cos(i));
+	  glVertex3f(0.0f,Ri*sin(i),Ri*cos(i));
+	  glVertex3f(l,Ri*sin(i),Ri*cos(i));
+	}
+
+      glNormal3f(0.0f,0.0f,Ri);
+      glVertex3f(0.0f,0.0f,-Ri);
+      glVertex3f(l,0.0f,-Ri);
+      glEnd();
+      glTranslatef(l/2, 0.0f, 0.0f);
+      
+      //Plane that attach the semi-cylinder
+      glBegin(GL_QUADS);
+      glNormal3f(0.0f,-1.0f,0.0);
+      glVertex3f(l/2,0.0f,Re);
+      glVertex3f(l/2,0.0f,Ri);
+      glVertex3f(-l/2,0.0f,Ri);
+      glVertex3f(-l/2,0.0f,Re);
+      glEnd();
+      glBegin(GL_QUADS);
+      glNormal3f(0.0f,-1.0f,0.0);
+      glVertex3f(l/2,0.0f,-Re);
+      glVertex3f(l/2,0.0f,-Ri);
+      glVertex3f(-l/2,0.0f,-Ri);
+      glVertex3f(-l/2,0.0f,-Re);
+      glEnd();
+      
+      // Close the surface with partial disk
+      glTranslatef(l/2, 0.0f, 0.0f);
+      glRotatef(90.0, 0.0f, 1.0f, 0.0f);
+      gluPartialDisk(quadric,Ri,Re,30,1,-90,180);
+      glTranslatef(0.0f, 0.0f, -l);
+      glRotatef(180.0, 0.0f, 1.0f, 0.0f);
+      gluPartialDisk(quadric,Ri,Re,30,1,-90,180);
+    }
+
+    void 
+    Draw::Cone(float r, float l)
+    {
+      static GLUquadric* quadric = gluNewQuadric();
+      gluCylinder(quadric, 0.0f, r, l, 30, 1);
+      glTranslatef(0.0f, 0.0f, l);
+      gluDisk(quadric, 0.0, r, 30, 1);
+    }
+
+    void Draw::PartialSphere(double r,int n,int method,
+			     double theta1,double theta2,double phi1,double phi2)
+    {
+      int i,j;
+      double t1,t2,t3;
+      XYZ e,p;
+      
+      for (j=0;j<n/2;j++) {
+	t1 = phi1 + j * (phi2 - phi1) / (n/2);
+	t2 = phi1 + (j + 1) * (phi2 - phi1) / (n/2);
+	if (method == 0)
+	  glBegin(GL_QUAD_STRIP);
+	else
+	  glBegin(GL_TRIANGLE_STRIP);
+	for (i=0;i<=n;i++) {
+	  t3 = theta1 + i * (theta2 - theta1) / n;
+	  e.x = cos(t1) * cos(t3);
+	  e.y = sin(t1);
+	  e.z = cos(t1) * sin(t3);
+	  p.x = r * e.x;
+	  p.y = r * e.y;
+	  p.z = r * e.z;
+	  glNormal3f(e.x,e.y,e.z);
+	  glTexCoord2f(i/(double)n,2*j/(double)n);
+	  glVertex3f(p.x,p.y,p.z);
+	  e.x = cos(t2) * cos(t3);
+	  e.y = sin(t2);
+	  e.z = cos(t2) * sin(t3);
+	  p.x = r * e.x;
+	  p.y = r * e.y;
+	  p.z = r * e.z;
+	  glNormal3f(e.x,e.y,e.z);
+	  glTexCoord2f(i/(double)n,2*(j+1)/(double)n);
+	  glVertex3f(p.x,p.y,p.z);
+	}
+	glEnd();
+      }
+    }
+
+    void 
+    Draw::OuterCylinderTeeth(float Ro, float mo, float alphao, float e)
+    {
+      const float Rb = Ro*cos(alphao);
+      const float RTeethMax = Ro + mo;
+
+      //Decalage pour que les dents soit aligné en degre
+      float theta1 = (tan(alphao)-alphao)*180.0/M_PI;
+      glRotatef(-theta1, 0.0f, 0.0f, 1.0f);
+
+      //Decalage en degre pour le pas
+      float theta2 = 2.0*(M_PI*mo/(4*Ro) + (tan(alphao)-alphao))*180.0/M_PI;
+      float a = theta2*M_PI/(180.0);
+      float Z = Ro*2.0/mo;
+      float i,j,alt;
+
+      for (j=0;j<Z;j=j+1)
+	{
+	  i=0;
+	  glBegin(GL_QUAD_STRIP);
+	  for (alt=0;alt<=RTeethMax;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), -e/2.0);
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), e/2.0);
+	      i=i+0.01;
+	      glNormal3f(sin(i),-cos(i),0.0f);
+	    }
+	  //i = iMax;
+	  glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), -e/2.0);
+	  glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), e/2.0);
+	  glNormal3f(sin(i),-cos(i),0.0f);
+	  glEnd();
+	  float recallPoint1X = Rb*(cos(i)+i*sin(i));
+	  float recallPoint1Y = Rb*(sin(i)-i*cos(i));
+	  glRotatef(theta2, 0.0, 0.0, 1.0);
+	  glBegin(GL_QUAD_STRIP);
+	  i=0.0;
+	  for (alt=0;alt<=RTeethMax;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), -e/2.0);
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), e/2.0);
+	      i = i-0.01;
+	      glNormal3f(-sin(i),cos(i),0.0f);
+	    }
+	  //i = iMax;
+	  glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), -e/2.0);
+	  glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), e/2.0);
+	  glNormal3f(-sin(i),cos(i),0.0f);
+	  glEnd();
+	  glRotatef(-theta2, 0.0, 0.0, 1.0);
+	  float recallPoint2X = Rb*(cos(i)+i*sin(i));
+	  float recallPoint2Y = Rb*(sin(i)-i*cos(i));
+	  float X2 = recallPoint2X*cos(a) - recallPoint2Y*sin(a);
+	  float Y2 = recallPoint2X*sin(a) + recallPoint2Y*cos(a);
+	  glBegin(GL_QUADS);
+	  glVertex3f(recallPoint1X,recallPoint1Y, -e/2.0);
+	  glVertex3f(recallPoint1X,recallPoint1Y, e/2.0);
+	  glVertex3f(X2,Y2, e/2.0);
+	  glVertex3f(X2,Y2, -e/2.0);
+	  glNormal3f(cos(a/2.0),sin(a/2.0),0.0f);
+	  glEnd();
+
+	  glBegin(GL_QUAD_STRIP);
+	  i=0.0;
+	  for (alt=0;alt<=RTeethMax;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+	      float recallPoint2X = Rb*(cos(-i)-i*sin(-i));
+	      float recallPoint2Y = Rb*(sin(-i)+i*cos(-i));
+	      float X2 = recallPoint2X*cos(a) - recallPoint2Y*sin(a);
+	      float Y2 = recallPoint2X*sin(a) + recallPoint2Y*cos(a);
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), e/2.0);
+	      glVertex3f(X2,Y2, e/2.0);
+	      i = i+0.01;
+	      glNormal3f(0.0f,0.0f,1.0f);
+	    }
+	  glVertex3f(recallPoint1X,recallPoint1Y, e/2.0);
+	  glVertex3f(X2,Y2, e/2.0);
+	  glEnd();
+
+	  glBegin(GL_QUAD_STRIP);
+	  i=0.0;
+	  for (alt=0;alt<=RTeethMax;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+	      float recallPoint2X = Rb*(cos(-i)-i*sin(-i));
+	      float recallPoint2Y = Rb*(sin(-i)+i*cos(-i));
+	      float X2 = recallPoint2X*cos(a) - recallPoint2Y*sin(a);
+	      float Y2 = recallPoint2X*sin(a) + recallPoint2Y*cos(a);
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), -e/2.0);
+	      glVertex3f(X2,Y2, -e/2.0);
+	      i = i+0.01;
+	      glNormal3f(0.0f,0.0f,-1.0f);
+	    }
+	  glVertex3f(recallPoint1X,recallPoint1Y, -e/2.0);
+	  glVertex3f(X2,Y2, -e/2.0);
+	  glEnd();
+
+	  glRotatef(360.0/Z, 0.0, 0.0, 1.0);
+	}
+    }
+
+
+
+    void Draw::InnerCylinderTeeth(float Ro, float mo,float alphao, float e)
+    {
+      const float Rb = Ro*cos(alphao);
+      const float ITeethMin = mo;
+
+      //Decalage pour que les dents soit aligné en degre
+      float theta1 = (tan(alphao)-alphao)*180.0/M_PI;
+      glRotatef(-theta1+180.0, 0.0, 0.0, 1.0);
+
+      //Decalage en degre pour le pas
+      float theta2 = 2.0*(M_PI*mo/(4*Ro) + (tan(alphao)-alphao))*180.0/M_PI;
+      float Z = Ro*2.0/mo;
+      float a = (theta2-360.0/Z)*M_PI/(180.0);
+
+      const float rot = (360./Z)/2.;
+      glRotatef(rot, 0.0f, 0.0f, 1.0f);
+      
+
+      float i,j,alt;
+
+      for (j=0;j<Z;j=j+1)
+	{
+	  i=ITeethMin;
+	  glBegin(GL_QUAD_STRIP);
+
+	  for (alt=0;alt<=Ro+mo;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), -e/2.0);
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), e/2.0);
+	      i=i+0.01;
+	      glNormal3f(-sin(i),cos(i),0.0f);
+	    }
+
+	  i=ITeethMin;
+	  glBegin(GL_QUAD_STRIP);
+	  for (alt=0;alt<=Ro+mo;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+
+	      float recallPoint2X = Rb*(cos(-i)-i*sin(-i));
+	      float recallPoint2Y = Rb*(sin(-i)+i*cos(-i));
+	      float X2 = recallPoint2X*cos(a) - recallPoint2Y*sin(a);
+	      float Y2 = recallPoint2X*sin(a) + recallPoint2Y*cos(a);
+	      glVertex3f(X2,Y2, -e/2.0);
+	      glVertex3f(X2,Y2, e/2.0);
+	      i=i+0.01;
+	      glNormal3f(sin(i),-cos(i),0.0f);
+	    }
+
+	  glBegin(GL_QUAD_STRIP);
+	  i=ITeethMin;
+	  for (alt=0;alt<=Ro+mo;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+	      float recallPoint2X = Rb*(cos(-i)-i*sin(-i));
+	      float recallPoint2Y = Rb*(sin(-i)+i*cos(-i));
+	      float X2 = recallPoint2X*cos(a) - recallPoint2Y*sin(a);
+	      float Y2 = recallPoint2X*sin(a) + recallPoint2Y*cos(a);
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), e/2.0);
+	      glVertex3f(X2,Y2, e/2.0);
+	      i = i+0.01;
+	      glNormal3f(0.0f,0.0f,1.0f);
+	    }
+	  glEnd();
+
+	  glBegin(GL_QUAD_STRIP);
+	  i=ITeethMin;
+	  for (alt=0;alt<=Ro+mo;alt=Rb*(cos(i)+i*sin(i)))
+	    {
+	      float recallPoint2X = Rb*(cos(-i)-i*sin(-i));
+	      float recallPoint2Y = Rb*(sin(-i)+i*cos(-i));
+	      float X2 = recallPoint2X*cos(a) - recallPoint2Y*sin(a);
+	      float Y2 = recallPoint2X*sin(a) + recallPoint2Y*cos(a);
+	      glVertex3f(Rb*(cos(i)+i*sin(i)),Rb*(sin(i)-i*cos(i)), -e/2.0);
+	      glVertex3f(X2,Y2, -e/2.0);
+	      i = i+0.01;
+	      glNormal3f(0.0f,0.0f,-1.0f);
+	    }
+
+	  glEnd();
+	  glRotatef(360.0/Z, 0.0, 0.0, 1.0);
+	}
+    }
+
+    void Draw::StraightTeeth(float mo, float alphao, float thickness, float length)
+    {      
+      const float step = M_PI*mo;
+      const float hs = step/2.;
+      const float c = 1.*mo*cos(alphao)/cos(alphao);
+      const float s = 1.*mo*sin(alphao)/cos(alphao);
+      const float e = thickness;
+
+      const float start = int(int(length/2.)/step)*step - hs;
+
+      glBegin(GL_QUAD_STRIP);
+      for (float x = -start; x < length/2.; x += step)
+	{
+
+	  glVertex3f(x - s,  c, -e/2.0);
+	  glVertex3f(x - s,  c,  e/2.0);
+	  glNormal3f(-c, -s, .0f);
+
+	  glVertex3f(x + s, -c, -e/2.0);
+	  glVertex3f(x + s, -c,  e/2.0);
+	  glNormal3f(-c, -s, .0f);
+
+	  glVertex3f(x + hs - s, -c, -e/2.0);
+	  glVertex3f(x + hs - s, -c,  e/2.0);
+	  glNormal3f(.0f, -1.f, .0f);
+
+	  glVertex3f(x + hs + s,  c, -e/2.0);
+	  glVertex3f(x + hs + s,  c,  e/2.0);
+	  glNormal3f(c, -s, .0f);
+
+	  glVertex3f(x + 2.*hs - s,  c, -e/2.0);
+	  glVertex3f(x + 2.*hs - s,  c,  e/2.0);
+	  glNormal3f(.0f, -1.f, .0f);
+	}
+      glEnd();
+
+      glBegin(GL_QUADS);
+
+      for (float x = -start; x < length/2.; x += step)
+      	{
+      	  glNormal3f(0.f, 0.f, -1.f);
+      	  glVertex3f(x - s,  c, -e/2.0);
+      	  glVertex3f(x + s, -c, -e/2.0);
+      	  glVertex3f(x + hs - s, -c, -e/2.0);
+      	  glVertex3f(x + hs + s,  c, -e/2.0);
+      	  glNormal3f(0.f, 0.f, -1.f);
+      	}
+      glEnd();
+
+      glBegin(GL_QUADS);
+      for (float x = -start; x < length/2.; x += step)
+      	{
+      	  glNormal3f(0.f, 0.f, 1.f);
+      	  glVertex3f(x - s,  c, e/2.0);
+      	  glVertex3f(x + s, -c, e/2.0);
+      	  glVertex3f(x + hs - s, -c, e/2.0);
+      	  glVertex3f(x + hs + s,  c, e/2.0);
+      	  glNormal3f(0.f, 0.f, 1.f);
+      	}
+      glEnd();
+
+      glTranslatef(.0f, c, .0f);
+    }
+
+
+
+    
+  }
+}
+
+
+
+
diff --git a/SRC/OpenMeca/Util/Draw.hpp b/SRC/OpenMeca/Util/Draw.hpp
new file mode 100644
index 0000000..474f61b
--- /dev/null
+++ b/SRC/OpenMeca/Util/Draw.hpp
@@ -0,0 +1,63 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Draw_hpp
+#define OpenMeca_Util_Draw_hpp
+
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    // Base class for all 3D drawable items.
+    class Draw
+    {
+    
+    public:
+      static void Cylinder(float radius, float length, bool middlePositionning=true);
+      static void CylinderStripe(float radius, float length);
+      static void Cylinder(float externRadius, float interRadius, float length);
+      static void Cylinder(float externRadius, float interRadius, float length, float startAngle, float stopAngle);
+
+      static void Sphere(float radius);
+      static void PartialSphere(double r,int n,int method,
+				double theta1,double theta2,double phi1,double phi2);
+      static void Box(float lx, float ly, float lz);
+      static void Channel(double Re,double Ri,double l);
+
+      static void Cone(float r, float l);
+
+      static void OuterCylinderTeeth(float Ro, float mo, float alphao, float thickness);
+      static void InnerCylinderTeeth(float Ro, float mo, float alphao, float thickness);
+      static void StraightTeeth(float mo, float alphao, float thickness, float length);
+    };
+
+
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Util/Enum.cpp b/SRC/OpenMeca/Util/Enum.cpp
new file mode 100644
index 0000000..98a7b7f
--- /dev/null
+++ b/SRC/OpenMeca/Util/Enum.cpp
@@ -0,0 +1,76 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QGLViewer/camera.h>
+
+#include "ChronoEngine/physics/ChSystem.h"
+
+#include "OpenMeca/Util/Enum.hpp"
+#include "OpenMeca/Physic/PhysEnum.hpp"
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    template<>
+    Enum<chrono::ChSystem::eCh_lcpSolver>::Map 
+    Enum<chrono::ChSystem::eCh_lcpSolver>::map_ { 
+      {"SOR"     , chrono::ChSystem::LCP_ITERATIVE_SOR},
+      {"SYMMSOR" , chrono::ChSystem::LCP_ITERATIVE_SYMMSOR},
+      {"SIMPLEX" , chrono::ChSystem::LCP_SIMPLEX},
+      {"JACOBI"  , chrono::ChSystem::LCP_ITERATIVE_JACOBI},
+      {"SOR_MULTITHREAD", chrono::ChSystem::LCP_ITERATIVE_SOR_MULTITHREAD},
+      {"PMINRES"        , chrono::ChSystem::LCP_ITERATIVE_PMINRES},
+      {"BARZILAIBORWEIN", chrono::ChSystem::LCP_ITERATIVE_BARZILAIBORWEIN},
+      {"PCG"            , chrono::ChSystem::LCP_ITERATIVE_PCG},
+      {"APGD"           , chrono::ChSystem::LCP_ITERATIVE_APGD},
+      {"DEM"            , chrono::ChSystem::LCP_DEM}
+    };
+
+    template<>
+    Enum<chrono::ChSystem::eCh_integrationType>::Map 
+    Enum<chrono::ChSystem::eCh_integrationType>::map_ = {
+      {"ANITESCU", chrono::ChSystem::INT_ANITESCU},
+      {"TASORA"  , chrono::ChSystem::INT_TASORA}
+    };
+
+    template<>
+    Enum<OpenMeca::Physic::MechActionEnum::DirectionMode>::Map 
+    Enum<OpenMeca::Physic::MechActionEnum::DirectionMode>::map_ = {
+      {"ABSOLUTE", OpenMeca::Physic::MechActionEnum::ABSOLUTE_DIR},
+      {"BODY"  , OpenMeca::Physic::MechActionEnum::BODY_COORDINATE_DIR}
+    };
+
+    template<>
+    Enum<OpenMeca::Physic::MechActionEnum::StartPointMode>::Map 
+    Enum<OpenMeca::Physic::MechActionEnum::StartPointMode>::map_ = {
+      {"ABSOLUTE", OpenMeca::Physic::MechActionEnum::ABSOLUTE_POS},
+      {"BODY"  , OpenMeca::Physic::MechActionEnum::BODY_COORDINATE_POS}
+      };
+
+    template<>
+    Enum<qglviewer::Camera::Type>::Map 
+    Enum<qglviewer::Camera::Type>::map_ = {
+      {"PERSPECTIVE" , qglviewer::Camera::PERSPECTIVE},
+      {"ORTHOGRAPHIC", qglviewer::Camera::ORTHOGRAPHIC}
+    };
+
+  }
+}
diff --git a/SRC/OpenMeca/Util/Enum.hpp b/SRC/OpenMeca/Util/Enum.hpp
new file mode 100644
index 0000000..1287975
--- /dev/null
+++ b/SRC/OpenMeca/Util/Enum.hpp
@@ -0,0 +1,85 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Enum_hpp
+#define OpenMeca_Util_Enum_hpp
+
+#include <map>
+#include <vector>
+#include <string>
+#include "OpenMeca/Core/Macro.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+    
+    // Util class to manage enum
+    template<typename T> 
+    class Enum
+    {
+    public:
+      typedef std::map<std::string, T> Map;
+
+      static std::string ToString(const T& val);      
+      static T ToEnum(const std::string& str);
+      static std::vector<std::string> List();
+
+      static Map map_;
+    };
+
+    
+        
+    template<typename T> 
+    std::string 
+    Enum<T>::ToString(const T& val)
+    {
+      for (typename Map::iterator it=map_.begin(); it!=map_.end(); ++it)
+	{
+	  if (it->second == val)
+	    return it->first;
+	}
+      OMC_ASSERT_MSG(0, "The val was not fond in the map");
+      return "";
+    }
+    
+    template<typename T> 
+    T 
+    Enum<T>::ToEnum(const std::string& str)
+    {
+      OMC_ASSERT_MSG(map_.count(str) == 1, "The key was not fond in the map");
+      return map_[str];
+    }
+
+    template<typename T> 
+    std::vector<std::string>
+    Enum<T>::List()
+    {
+      std::vector<std::string> vec;
+      for (typename Map::iterator it=map_.begin(); it!=map_.end(); ++it)
+	vec.push_back(it->first);
+      return vec;
+    }
+
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/Expr.cpp b/SRC/OpenMeca/Util/Expr.cpp
new file mode 100644
index 0000000..5f99b66
--- /dev/null
+++ b/SRC/OpenMeca/Util/Expr.cpp
@@ -0,0 +1,225 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <sstream>
+
+#include "OpenMeca/Util/Expr.hpp"
+#include "OpenMeca/Util/Var.hpp"
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+
+
+    Core::SetOfBase<Expr> Expr::all_ = Core::SetOfBase<Expr>();
+
+
+    bool 
+    Expr::IsValid(const std::string & exp_str)
+    {
+      double x = 0.;
+      Expr exp(exp_str, x);
+      return exp.Check();
+    }
+
+    double 
+    Expr::Compute(const std::string &exp_str)
+    {
+      double x = 0.;
+      Expr exp(exp_str, x);
+      return exp();
+    }
+
+    void
+    Expr::UpdateAll()
+    {
+      Var::UpdateTable();
+
+      for (unsigned int i =0; i < all_.GetTotItemNumber(); ++i)
+	if (!all_(i).IsNull())
+	  all_(i).Update();
+    }
+
+    
+
+    Expr::Expr()
+      :dim_(0), var_(0),
+       expression_("0"),
+       isCopy_(false)
+    {
+      all_.AddItem(*this);
+    }
+
+    Expr::Expr(double& var)
+      :dim_(0), var_(0),
+       expression_(""),
+       isCopy_(false)
+    {
+      SetVariable(var);
+      all_.AddItem(*this);
+    }
+
+    Expr::Expr(const std::string& exp, double& var)
+      :dim_(0), var_(&var),
+       expression_(exp),
+       isCopy_(false)
+    {
+      all_.AddItem(*this);
+    }
+
+    Expr::Expr(const Expr& exp)
+      :dim_(exp.dim_), var_(0),
+       expression_(exp.expression_),
+       isCopy_(true)
+    {
+    }
+
+
+
+    Expr::~Expr()
+    {
+      if (!isCopy_)
+	all_.RemoveItem(*this);
+    }
+
+    bool 
+    Expr::IsNull() const
+    {
+      return expression_.empty();
+    }
+
+    void 
+    Expr::SetVariable(double& var)
+    {
+      OMC_ASSERT_MSG(var_==0, "The variable is already defined");
+      SetExpressionFromValue(var);
+      var_ = &var;
+    }
+
+    Expr& 
+    Expr::operator=(const Expr& exp)
+    {
+      expression_ = exp.expression_;
+      return *this;
+    }
+
+    bool
+    Expr::Check()
+    {
+      OMC_ASSERT_MSG(var_ != 0,
+		     "The variable was not initialized");
+
+      exprtk::expression<double> expression;
+      expression.register_symbol_table(Var::GetSymbolTable());
+
+      exprtk::parser<double> parser;
+      return parser.compile(expression_,expression);
+    }
+
+
+    double 
+    Expr::operator()(void)
+    {
+      exprtk::expression<double> expression;
+      expression.register_symbol_table(Var::GetSymbolTable());
+
+      exprtk::parser<double> parser;
+      OMC_ASSERT_MSG(parser.compile(expression_,expression),
+		     "Can't understand the expression \"" + expression_ + "\"");
+      return expression.value();
+    }
+
+    void 
+    Expr::Update()
+    {
+      OMC_ASSERT_MSG(var_ != 0      , "The variable was not initialized");
+      OMC_ASSERT_MSG(expression_!="", "The expression is empty");
+      
+      Expr& me = *this;
+      double& var = *var_;
+      var = me()*GetFactor();
+    }
+
+    const std::string& 
+    Expr::ToString() const
+    {
+      return expression_;
+    }
+    
+    void 
+    Expr::SetString(std::string str)
+    {
+      expression_ = std::string(str);
+    }
+
+    void
+    Expr::SetExpressionFromValue(double val)
+    {
+      std::ostringstream strs;
+      strs << val;
+      expression_ = strs.str();
+    }
+
+    double 
+    Expr::GetVariableValue() const
+    {
+      OMC_ASSERT_MSG(var_ != 0, "The variable was not initialized");
+      return *var_;
+    }
+
+    void 
+    Expr::SetDimension(const Dimension& dim)
+    {
+      OMC_ASSERT_MSG(dim_==0, "The expression is already defined");
+      dim_ = &dim;
+    }
+    
+    const Dimension& 
+    Expr::GetDimension() const
+    {
+      OMC_ASSERT_MSG(dim_!=0, "The expression has no dimension");
+      return *dim_;
+    }
+    
+    double 
+    Expr::GetFactor() const
+    {
+      return GetDimension().GetUserChoice().GetFactor();
+    }
+
+    bool 
+    Expr::IsExpressionNumber() const
+    {
+      const QString str =  ToString().c_str();
+      bool isNumber = false;
+      str.toDouble(&isNumber);
+      return isNumber;
+    }
+    
+
+  }
+
+}
+
+
diff --git a/SRC/OpenMeca/Util/Expr.hpp b/SRC/OpenMeca/Util/Expr.hpp
new file mode 100644
index 0000000..28308ab
--- /dev/null
+++ b/SRC/OpenMeca/Util/Expr.hpp
@@ -0,0 +1,107 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Expr_hpp
+#define OpenMeca_Util_Expr_hpp
+
+
+#include <string>
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Core/SetOfBase.hpp"
+#include "OpenMeca/Util/exprtk.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+#include "OpenMeca/Util/Unit.hpp"
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    class Expr
+    {
+    public:
+      static bool IsValid(const std::string &);
+      static double Compute(const std::string &);
+      static void UpdateAll();
+
+    public:
+      Expr();
+      Expr(double& var);
+      Expr(const std::string & exp, double& var);
+      Expr(const Expr&);
+
+      virtual ~Expr();
+
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+      double GetFactor() const;
+
+      void Update();
+      double operator()(void);
+      bool IsNull() const;
+      bool IsExpressionNumber() const;
+
+      void SetVariable(double&);
+      void SetExpressionFromValue(double);
+
+      bool Check();
+
+      double GetVariableValue() const;
+
+      Expr& operator=(const Expr&);
+
+      const std::string& ToString() const;
+      void SetString(std::string);
+
+    private:      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      static Core::SetOfBase<Expr> all_;
+
+    protected:
+      const Util::Dimension* dim_;
+      double* var_;
+      std::string expression_;
+      bool isCopy_;
+    };
+
+
+    template<class Archive>
+    inline void
+    Expr::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(expression_);
+    }
+    
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Util/ExprAttitude.cpp b/SRC/OpenMeca/Util/ExprAttitude.cpp
new file mode 100644
index 0000000..56f8dc4
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprAttitude.cpp
@@ -0,0 +1,87 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <sstream>
+
+#include "OpenMeca/Util/ExprAttitude.hpp"
+#include "OpenMeca/Util/Var.hpp"
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+      
+    ExprAttitude::ExprAttitude(std::function<const Geom::Frame<_3D>& ()> f)
+      :Geom::Quaternion<_3D>(f),
+       axis_(1., 0., 0., f), angle_(0)
+    {
+      axis_.SetDimension(Util::Dimension::Get("Length"));
+      angle_.SetDimension(Util::Dimension::Get("Angle"));
+    }
+
+
+
+    ExprAttitude::~ExprAttitude()
+    {
+    }
+
+
+    ExprAttitude& 
+    ExprAttitude::operator=(const Geom::Quaternion<_3D>& q)
+    {
+      Geom::Vector<_3D> axis = q.GetAxis();
+      if (axis.GetNorm() == 0.)
+	axis[0] = 1.;
+      const double angle = q.GetAngle();
+      axis_  = axis;
+      angle_ = angle;
+      return (*this);
+    }
+
+    ExprAttitude& 
+    ExprAttitude::operator=(const ExprAttitude& q)
+    {
+      axis_ = q.axis_;
+      angle_ = q.angle_;
+      return (*this);
+    }
+
+    
+
+    void
+    ExprAttitude::Update()
+    {
+      axis_.GetExpressionX().Update();
+      axis_.GetExpressionY().Update();
+      axis_.GetExpressionZ().Update();
+      angle_.Update();
+      
+      Geom::Quaternion<_3D>::SetAxisAngle(axis_,  angle_.GetValue());
+    }
+
+  
+
+  }
+
+}
+
+
diff --git a/SRC/OpenMeca/Util/ExprAttitude.hpp b/SRC/OpenMeca/Util/ExprAttitude.hpp
new file mode 100644
index 0000000..4b49c0e
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprAttitude.hpp
@@ -0,0 +1,82 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_ExprAttitude_hpp
+#define OpenMeca_Item_ExprAttitude_hpp
+
+
+#include <string>
+
+
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Util/Expr.hpp"
+#include "OpenMeca/Geom/Quaternion.hpp"
+#include "OpenMeca/Util/ExprVector.hpp"
+#include "OpenMeca/Util/ExprDouble.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    class ExprAttitude : public Geom::Quaternion<_3D>
+    {
+
+    public:
+      ExprAttitude(std::function<const Geom::Frame<_3D>& ()> = &Geom::Frame<_3D>::GetGlobal);
+      virtual ~ExprAttitude();
+
+      ExprAttitude& operator=(const Geom::Quaternion<_3D>&); 
+      ExprAttitude& operator=(const ExprAttitude&); 
+      void Update();
+
+      OMC_ACCESSOR(Axis , ExprVector, axis_ );
+      OMC_ACCESSOR(Angle, ExprDouble, angle_);
+
+    private:      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      ExprVector axis_;
+      ExprDouble angle_;
+    };
+
+
+    template<class Archive>
+    inline void
+    ExprAttitude::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Geom::Quaternion<_3D>);
+      ar & BOOST_SERIALIZATION_NVP(axis_);
+      ar & BOOST_SERIALIZATION_NVP(angle_);
+    }
+    
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Util/ExprDouble.cpp b/SRC/OpenMeca/Util/ExprDouble.cpp
new file mode 100644
index 0000000..623f604
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprDouble.cpp
@@ -0,0 +1,89 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <sstream>
+
+#include "OpenMeca/Util/ExprDouble.hpp"
+#include "OpenMeca/Util/Var.hpp"
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+      
+    ExprDouble::ExprDouble()
+      :val_(0.), exp_(val_)
+    {
+    }
+
+    ExprDouble::ExprDouble(double val)
+      :val_(val), exp_(val_)
+    {
+    }
+
+
+    ExprDouble::~ExprDouble()
+    {
+    }
+
+
+    ExprDouble& 
+    ExprDouble::operator=(const double& val)
+    {
+      val_ = val;
+      exp_.SetExpressionFromValue(val);
+      return (*this);
+    }
+
+    ExprDouble& 
+    ExprDouble::operator=(const ExprDouble& val)
+    {
+      exp_ = val.exp_;
+      val_ = val_;
+      return (*this);
+    }
+
+    void
+    ExprDouble::Update()
+    {
+      exp_.Update();
+    }
+  
+    
+    void 
+    ExprDouble::SetDimension(const Dimension& dim)
+    {
+      exp_.SetDimension(dim);
+    }
+    
+    const Dimension& 
+    ExprDouble::GetDimension() const
+    {
+      return exp_.GetDimension();
+    }
+
+
+  }
+
+}
+
+
diff --git a/SRC/OpenMeca/Util/ExprDouble.hpp b/SRC/OpenMeca/Util/ExprDouble.hpp
new file mode 100644
index 0000000..645ea6c
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprDouble.hpp
@@ -0,0 +1,82 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_ExprDouble_hpp
+#define OpenMeca_Item_ExprDouble_hpp
+
+
+#include <string>
+
+
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Util/Expr.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    class ExprDouble
+    {
+
+    public:
+      ExprDouble();
+      ExprDouble(double);
+      virtual ~ExprDouble();
+
+      ExprDouble& operator=(const double&); 
+      ExprDouble& operator=(const ExprDouble&); 
+      void Update();
+
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+
+      OMC_ACCESSOR(Expression, Util::Expr, exp_);
+      OMC_ACCESSOR(Value     , double    , val_);
+
+    private:      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      double val_;
+      Util::Expr exp_;
+    };
+
+
+    template<class Archive>
+    inline void
+    ExprDouble::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(val_);
+      ar & BOOST_SERIALIZATION_NVP(exp_);
+    }
+    
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Util/ExprPoint.cpp b/SRC/OpenMeca/Util/ExprPoint.cpp
new file mode 100644
index 0000000..68a4ab7
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprPoint.cpp
@@ -0,0 +1,88 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <sstream>
+
+#include "OpenMeca/Util/ExprPoint.hpp"
+#include "OpenMeca/Util/Var.hpp"
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+      
+    ExprPoint::ExprPoint(std::function<const Geom::Frame<_3D>& ()> f)
+      :Geom::Point<_3D>(f),
+       expX_(Geom::Point<_3D>::operator[](0)),
+       expY_(Geom::Point<_3D>::operator[](1)),
+       expZ_(Geom::Point<_3D>::operator[](2))
+    {
+      expX_.SetDimension(Util::Dimension::Get("Length"));
+      expY_.SetDimension(Util::Dimension::Get("Length"));
+      expZ_.SetDimension(Util::Dimension::Get("Length"));
+      
+    }
+
+    ExprPoint::ExprPoint(double x, double y, double z, std::function<const Geom::Frame<_3D>& ()> f)
+      :Geom::Point<_3D>(x, y, z, f),
+       expX_(Geom::Point<_3D>::operator[](0)),
+       expY_(Geom::Point<_3D>::operator[](1)),
+       expZ_(Geom::Point<_3D>::operator[](2))
+    {
+      expX_.SetDimension(Util::Dimension::Get("Length"));
+      expY_.SetDimension(Util::Dimension::Get("Length"));
+      expZ_.SetDimension(Util::Dimension::Get("Length"));
+    }
+
+
+    ExprPoint::~ExprPoint()
+    {
+    }
+
+
+    ExprPoint& 
+    ExprPoint::operator=(const Geom::Point<_3D>& p)
+    {
+      Geom::Point<_3D>& me = *this;
+      me = p;
+      expX_.SetExpressionFromValue(me[0]);
+      expY_.SetExpressionFromValue(me[1]);
+      expZ_.SetExpressionFromValue(me[2]);
+      return (*this);
+    }
+
+    ExprPoint& 
+    ExprPoint::operator=(const ExprPoint& p)
+    {
+      expX_ = p.expX_;
+      expY_ = p.expY_;
+      expZ_ = p.expZ_;
+      return (*this);
+    }
+
+  
+
+  }
+
+}
+
+
diff --git a/SRC/OpenMeca/Util/ExprPoint.hpp b/SRC/OpenMeca/Util/ExprPoint.hpp
new file mode 100644
index 0000000..be01150
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprPoint.hpp
@@ -0,0 +1,83 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_ExprPoint_hpp
+#define OpenMeca_Item_ExprPoint_hpp
+
+
+#include <string>
+
+
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Util/Expr.hpp"
+#include "OpenMeca/Geom/Point.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    class ExprPoint : public Geom::Point<_3D>
+    {
+
+    public:
+      ExprPoint(std::function<const Geom::Frame<_3D>& ()> = &Geom::Frame<_3D>::GetGlobal);
+      ExprPoint(double, double, double, std::function<const Geom::Frame<_3D>& ()> = &Geom::Frame<_3D>::GetGlobal);
+      virtual ~ExprPoint();
+
+      ExprPoint& operator=(const Geom::Point<_3D>&); 
+      ExprPoint& operator=(const ExprPoint&); 
+
+      OMC_ACCESSOR(ExpressionX, Util::Expr, expX_);
+      OMC_ACCESSOR(ExpressionY, Util::Expr, expY_);
+      OMC_ACCESSOR(ExpressionZ, Util::Expr, expZ_);
+
+    private:      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      Util::Expr expX_;
+      Util::Expr expY_;
+      Util::Expr expZ_;
+    };
+
+
+    template<class Archive>
+    inline void
+    ExprPoint::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Geom::Point<_3D>);
+      ar & BOOST_SERIALIZATION_NVP(expX_);
+      ar & BOOST_SERIALIZATION_NVP(expY_);
+      ar & BOOST_SERIALIZATION_NVP(expZ_);
+    }
+    
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Util/ExprVector.cpp b/SRC/OpenMeca/Util/ExprVector.cpp
new file mode 100644
index 0000000..d30d324
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprVector.cpp
@@ -0,0 +1,97 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <sstream>
+
+#include "OpenMeca/Util/ExprVector.hpp"
+#include "OpenMeca/Util/Var.hpp"
+
+
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+      
+    ExprVector::ExprVector(std::function<const Geom::Frame<_3D>& ()> f)
+      :Geom::Vector<_3D>(f),
+       expX_(Geom::Vector<_3D>::operator[](0)),
+       expY_(Geom::Vector<_3D>::operator[](1)),
+       expZ_(Geom::Vector<_3D>::operator[](2))
+    {
+      
+    }
+
+    ExprVector::ExprVector(double x, double y, double z, std::function<const Geom::Frame<_3D>& ()> f)
+      :Geom::Vector<_3D>(x, y, z, f),
+       expX_(Geom::Vector<_3D>::operator[](0)),
+       expY_(Geom::Vector<_3D>::operator[](1)),
+       expZ_(Geom::Vector<_3D>::operator[](2))
+    {
+      
+    }
+
+
+    ExprVector::~ExprVector()
+    {
+    }
+
+
+    ExprVector& 
+    ExprVector::operator=(const Geom::Vector<_3D>& p)
+    {
+      Geom::Vector<_3D>& me = *this;
+      me = p;
+      expX_.SetExpressionFromValue(me[0]);
+      expY_.SetExpressionFromValue(me[1]);
+      expZ_.SetExpressionFromValue(me[2]);
+      return (*this);
+    }
+
+    ExprVector& 
+    ExprVector::operator=(const ExprVector& v)
+    {
+      expX_ = v.expX_;
+      expY_ = v.expY_;
+      expZ_ = v.expZ_;
+      return (*this);
+    }
+
+    void 
+    ExprVector::SetDimension(const Dimension& dim)
+    {
+      expX_.SetDimension(dim);
+      expY_.SetDimension(dim);
+      expZ_.SetDimension(dim);
+    }
+    
+    const Dimension& 
+    ExprVector::GetDimension() const
+    {
+      return expX_.GetDimension();
+    }
+
+  
+
+  }
+
+}
+
+
diff --git a/SRC/OpenMeca/Util/ExprVector.hpp b/SRC/OpenMeca/Util/ExprVector.hpp
new file mode 100644
index 0000000..c6607e3
--- /dev/null
+++ b/SRC/OpenMeca/Util/ExprVector.hpp
@@ -0,0 +1,86 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_ExprVector_hpp
+#define OpenMeca_Item_ExprVector_hpp
+
+
+#include <string>
+
+
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Util/Expr.hpp"
+#include "OpenMeca/Geom/Vector.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    class ExprVector : public Geom::Vector<_3D>
+    {
+
+    public:
+      ExprVector(std::function<const Geom::Frame<_3D>& ()> = &Geom::Frame<_3D>::GetGlobal);
+      ExprVector(double, double, double, std::function<const Geom::Frame<_3D>& ()> = &Geom::Frame<_3D>::GetGlobal);
+      virtual ~ExprVector();
+
+      ExprVector& operator=(const Geom::Vector<_3D>&); 
+      ExprVector& operator=(const ExprVector&); 
+
+      void SetDimension(const Util::Dimension& dim);
+      const Util::Dimension& GetDimension() const;
+
+      OMC_ACCESSOR(ExpressionX, Util::Expr, expX_);
+      OMC_ACCESSOR(ExpressionY, Util::Expr, expY_);
+      OMC_ACCESSOR(ExpressionZ, Util::Expr, expZ_);
+
+    private:      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      Util::Expr expX_;
+      Util::Expr expY_;
+      Util::Expr expZ_;
+    };
+
+
+    template<class Archive>
+    inline void
+    ExprVector::serialize(Archive & ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Geom::Vector<_3D>);
+      ar & BOOST_SERIALIZATION_NVP(expX_);
+      ar & BOOST_SERIALIZATION_NVP(expY_);
+      ar & BOOST_SERIALIZATION_NVP(expZ_);
+    }
+    
+
+  }
+
+}
+
+
+
+
+#endif
diff --git a/SRC/OpenMeca/Util/Icon.cpp b/SRC/OpenMeca/Util/Icon.cpp
new file mode 100644
index 0000000..71aa1d3
--- /dev/null
+++ b/SRC/OpenMeca/Util/Icon.cpp
@@ -0,0 +1,91 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QFile>
+
+#include "OpenMeca/Util/Icon.hpp"
+#include "OpenMeca/Gui/MainWindow.hpp"
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    QByteArray
+    Icon::ChangeColorInSvgFile(const QString& fileName, const QColor& from, const QColor& to)
+    {
+      QFile file(fileName);
+      OMC_ASSERT_MSG(file.open(QFile::ReadOnly | QFile::Text), "Can't open svg file");
+      QByteArray fileData;
+      fileData = file.readAll();
+      QString text(fileData);
+      text.replace(from.name(), to.name());
+      file.close();
+      return text.toLatin1();
+      
+    }
+
+    QByteArray
+    Icon::ChangeColorInSvgFile(const QString& fileName, const QColor& from1, const QColor& to1,const QColor& from2, const QColor& to2)
+    {
+      QFile file(fileName);
+      OMC_ASSERT_MSG(file.open(QFile::ReadOnly | QFile::Text), "Can't open svg file");
+      QByteArray fileData;
+      fileData = file.readAll();
+      QString text(fileData);
+      text.replace(from1.name(), to1.name());
+      text.replace(from2.name(), to2.name());
+      file.close();
+      return text.toLatin1();
+      
+    }
+
+    
+
+    QIcon
+    Icon::DrawIconFromSvgFile(const QString& fileName)
+    {
+      QSvgRenderer svgRenderer(fileName);
+      // render it on pixmap and translate to icon
+      const int size = Gui::MainWindow::Get().GetIconSize();
+      QPixmap pixmap(QSize(size,size));
+      pixmap.fill(QColor (0, 0, 0, 0));
+      QPainter painter(&pixmap);
+      svgRenderer.render( &painter);
+      return QIcon(pixmap);
+    }
+    
+
+    void
+    Icon::DrawIconFromSvgFile(const QString& fileName, QIcon& icon, QColor color)
+    {
+      QSvgRenderer svgRenderer(Util::Icon::ChangeColorInSvgFile(fileName, Qt::red, color));
+
+      // render it on pixmap and translate to icon
+      const int size = Gui::MainWindow::Get().GetIconSize();
+      QPixmap pixmap(QSize(size,size));
+      pixmap.fill(QColor (0, 0, 0, 0));
+      QPainter painter(&pixmap);
+      svgRenderer.render( &painter);
+      icon =  QIcon(pixmap);
+    }
+
+   
+  }
+}
diff --git a/SRC/OpenMeca/Util/Icon.hpp b/SRC/OpenMeca/Util/Icon.hpp
new file mode 100644
index 0000000..acd809d
--- /dev/null
+++ b/SRC/OpenMeca/Util/Icon.hpp
@@ -0,0 +1,52 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Icon_hpp
+#define OpenMeca_Util_Icon_hpp
+
+#include <QString>
+#include <QIcon>
+#include <QColor>
+#include <QSvgRenderer>
+
+#include "OpenMeca/Util/Color.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    class Icon
+    {
+    public:  
+      static QByteArray ChangeColorInSvgFile(const QString& fileName, const QColor& from, const QColor& to);
+
+      static QByteArray ChangeColorInSvgFile(const QString& fileName, const QColor& from1, const QColor& to1, const QColor& from2, const QColor& to2);
+
+      static void DrawIconFromSvgFile(const QString& fileName, QIcon& icon, QColor color);
+
+      static QIcon DrawIconFromSvgFile(const QString& fileName);
+    }; 
+    
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/Lang.cpp b/SRC/OpenMeca/Util/Lang.cpp
new file mode 100644
index 0000000..defeb15
--- /dev/null
+++ b/SRC/OpenMeca/Util/Lang.cpp
@@ -0,0 +1,96 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Util/Lang.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    std::string Lang::GetStrType(){return "Lang";}
+
+    std::map<const std::string, Lang*> Lang::all_ = std::map<const std::string, Lang*>();
+
+    Lang& 
+    Lang::GetByID(const std::string& id)
+    {
+      OMC_ASSERT_MSG(all_.count(id) == 1, "Can't find this id");
+      return *all_[id];
+    }
+
+    Lang& 
+    Lang::GetByIndex(const int index)
+    {
+      int i = 0;
+      std::map<const std::string, Lang*>::iterator it;
+      for (it = all_.begin(); it != all_.end(); ++it)
+	{
+	  if (i == index)
+	    return *it->second;
+	  i ++;
+	}
+      OMC_ASSERT_MSG(0, "Can't find this index");
+      return *it->second;
+    }
+
+    std::map<const std::string, Lang*>& 
+    Lang::GetAll()
+    {
+      return all_;
+    }
+
+
+    Lang::Lang(const std::string& id, const std::string& name, const std::string& file)
+      :id_(id),
+       name_(name), 
+       file_(file)
+    {
+      OMC_ASSERT_MSG(all_.count(id_) == 0, "The id is already taken");
+      all_[id_] = this;
+    }
+    
+
+    Lang::~Lang()
+    {
+      OMC_ASSERT_MSG(all_.count(id_) == 1, "Can't find this id");
+      all_.erase(id_); 
+    }
+
+
+    int
+    Lang::GetIndex() const
+    {
+      int i = 0;
+      std::map<const std::string, Lang*>::iterator it;
+      for (it = all_.begin(); it != all_.end(); ++it)
+	{
+	  if (it->second == this)
+	    return i;
+	  i ++;
+	}
+      OMC_ASSERT_MSG(0, "Can't find this index");
+      return i;
+    }
+      
+  }
+}
diff --git a/SRC/OpenMeca/Util/Lang.hpp b/SRC/OpenMeca/Util/Lang.hpp
new file mode 100644
index 0000000..d23f3e8
--- /dev/null
+++ b/SRC/OpenMeca/Util/Lang.hpp
@@ -0,0 +1,64 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Lang_hpp
+#define OpenMeca_Util_Lang_hpp
+
+#include <string>
+#include <map>
+
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    class Lang
+    {
+    public: 
+      static std::string GetStrType();
+      static Lang& GetByID(const std::string&);
+      static Lang& GetByIndex(const int);
+      static std::map<const std::string, Lang*>& GetAll();
+
+    private:
+      static std::map<const std::string, Lang*> all_;
+
+
+    public:
+      Lang(const std::string& id, const std::string& name, const std::string& file);
+      ~Lang();
+      void Load();
+      int GetIndex() const;
+      
+      OMC_ACCESS_CST(ID  , std::string, id_);
+      OMC_ACCESS_CST(Name, std::string, name_);
+      OMC_ACCESS_CST(File, std::string, file_);
+
+    private:
+      const std::string id_; 
+      const std::string name_;
+      const std::string file_;
+    };
+      
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/MotionLaw.cpp b/SRC/OpenMeca/Util/MotionLaw.cpp
new file mode 100644
index 0000000..2fe6027
--- /dev/null
+++ b/SRC/OpenMeca/Util/MotionLaw.cpp
@@ -0,0 +1,71 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+
+
+#include "OpenMeca/Util/MotionLaw.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    MotionLaw::MotionLaw()
+      :enabled_(false),
+       law_(Core::System::Get().GetTime(), 0.)
+    {
+    }
+
+    MotionLaw::~MotionLaw()
+    {
+    }
+
+    MotionLaw::MotionLaw(const MotionLaw& l):
+      enabled_(l.enabled_),
+      law_(Core::System::Get().GetTime(), 0.)
+    {
+      Expr& exp1 = law_;
+      const Expr& exp2 = l.law_;
+      exp1 = exp2;
+    }
+    
+
+    MotionLaw& 
+    MotionLaw::operator=(const MotionLaw& l)
+    {
+      enabled_ = l.enabled_;
+      Expr& exp1 = law_;
+      const Expr& exp2 = l.law_;
+      exp1 = exp2;
+      return *this;
+    }
+
+
+    bool 
+    MotionLaw::IsEnabled() const
+    {
+      return enabled_;
+    }
+
+
+  }
+}
diff --git a/SRC/OpenMeca/Util/MotionLaw.hpp b/SRC/OpenMeca/Util/MotionLaw.hpp
new file mode 100644
index 0000000..9cb04bb
--- /dev/null
+++ b/SRC/OpenMeca/Util/MotionLaw.hpp
@@ -0,0 +1,69 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_MotionLaw_hpp
+#define OpenMeca_Util_MotionLaw_hpp
+
+#include "OpenMeca/Util/CustomChFunction.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+
+    class MotionLaw 
+    {
+    public:
+      
+      MotionLaw();
+      virtual ~MotionLaw();
+      
+      MotionLaw(const MotionLaw&);           
+      MotionLaw& operator=(const MotionLaw&);
+
+      bool IsEnabled() const;
+
+      // Accessors
+      OMC_ACCESSOR(Enabled, bool            ,  enabled_);
+      OMC_ACCESSOR(Law    , CustomChFunction,  law_    );
+
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      bool enabled_;
+      CustomChFunction law_;
+    };
+
+    template<class Archive>
+    inline void
+    MotionLaw::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(enabled_);
+      ar & BOOST_SERIALIZATION_NVP(law_);
+    }
+
+  }
+}
+
+#endif
diff --git a/SRC/OpenMeca/Util/Unit.cpp b/SRC/OpenMeca/Util/Unit.cpp
new file mode 100644
index 0000000..1032c6d
--- /dev/null
+++ b/SRC/OpenMeca/Util/Unit.cpp
@@ -0,0 +1,73 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "OpenMeca/Util/Unit.hpp"
+#include "OpenMeca/Util/Dimension.hpp"
+
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    std::string Unit::GetStrType(){return "Unit";}
+
+    Unit::Unit(Dimension& dimension, const std::string name, const std::string symbol, const double factor)
+      :dimension_(dimension),
+       name_(name), 
+       symbol_(symbol), 
+       factor_(factor)
+    {
+      dimension_.AddUnit(*this);
+    }
+    
+
+    Unit::~Unit()
+    {
+      dimension_.RemoveUnit(*this);
+    }
+
+
+    const std::string& 
+    Unit::GetName() const
+    {
+      return name_;
+    }
+
+    const std::string& 
+    Unit::GetSymbol() const
+    {
+      return symbol_;
+    }
+
+    double 
+    Unit::GetFactor() const
+    {
+      return factor_;
+    }
+
+    const Dimension&
+    Unit::GetDimension() const
+    {
+      return dimension_;
+    }
+    
+      
+  }
+}
diff --git a/SRC/OpenMeca/Util/Unit.hpp b/SRC/OpenMeca/Util/Unit.hpp
new file mode 100644
index 0000000..c68aa5f
--- /dev/null
+++ b/SRC/OpenMeca/Util/Unit.hpp
@@ -0,0 +1,58 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Unit_hpp
+#define OpenMeca_Util_Unit_hpp
+
+#include <string>
+#include <map>
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+    class Dimension;
+      
+    // A unit must be associated to a given dimension, for example 'second' unit
+    // must be associated to time dimension
+    class Unit
+    {
+    public: 
+      static std::string GetStrType();
+
+      Unit(Dimension& dimension, const std::string name, const std::string symbol, const double factor);
+      ~Unit();
+    
+      const std::string& GetName() const;
+      const std::string& GetSymbol() const;
+      double GetFactor() const;
+      const Dimension& GetDimension() const;
+
+      
+    private:
+      Dimension& dimension_;
+      const std::string name_; 
+      const std::string symbol_;
+      const double factor_;
+    };
+      
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/Util.pro b/SRC/OpenMeca/Util/Util.pro
new file mode 100644
index 0000000..27e3cb3
--- /dev/null
+++ b/SRC/OpenMeca/Util/Util.pro
@@ -0,0 +1,55 @@
+## This file is part of OpenMeca, an easy software to do mechanical simulation.
+##
+## Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+##
+## Copyright (C) 2012-2017 Damien ANDRE
+##
+## This program is free software: you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+HEADERS += Util/Color.hpp \
+           Util/Draw.hpp \
+           Util/Icon.hpp \
+           Util/Enum.hpp \
+           Util/Dimension.hpp \
+           Util/Unit.hpp \
+           Util/Lang.hpp \
+           Util/Version.hpp \
+           Util/Var.hpp \
+           Util/exprtk.hpp \
+           Util/Expr.hpp \
+           Util/ExprDouble.cpp \
+           Util/ExprPoint.cpp \
+           Util/ExprVector.cpp \
+           Util/ExprAttitude.cpp \
+           Util/MotionLaw.hpp \
+           Util/CustomChFunction.hpp 
+
+
+SOURCES += Util/Color.cpp \
+           Util/Draw.cpp \
+           Util/Icon.cpp \
+           Util/Dimension.cpp \
+           Util/Enum.cpp \
+           Util/Lang.cpp \
+           Util/Unit.cpp \
+           Util/Version.cpp \
+           Util/Var.cpp \
+           Util/Expr.cpp \
+           Util/ExprDouble.cpp \
+           Util/ExprPoint.cpp \
+           Util/ExprVector.cpp \
+           Util/ExprAttitude.cpp \
+           Util/MotionLaw.cpp \
+           Util/CustomChFunction.cpp 
+
diff --git a/SRC/OpenMeca/Util/Var.cpp b/SRC/OpenMeca/Util/Var.cpp
new file mode 100644
index 0000000..22fd37c
--- /dev/null
+++ b/SRC/OpenMeca/Util/Var.cpp
@@ -0,0 +1,103 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include "OpenMeca/Util/Var.hpp"
+#include "OpenMeca/Core/System.hpp"
+
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    exprtk::symbol_table<double> Var::symbolTable_ = exprtk::symbol_table<double>();
+      
+    
+    exprtk::symbol_table<double>&
+    Var::GetSymbolTable()
+    {
+      return symbolTable_;
+    }
+
+    void 
+    Var::UpdateTable()
+    {
+      symbolTable_.clear();
+
+      Core::SetOf<Var>& set = Core::SetOf<Var>::GetGlobalSet();
+      for (unsigned int i =0; i < set.GetTotItemNumber(); ++i)
+	set(i).AddToTable();
+
+      symbolTable_.add_variable("t", Core::System::Get().GetTime());
+      symbolTable_.add_constants();
+    }
+
+
+    Var::Var()
+      :symbol_("x"),
+       value_(0.)
+    {
+    }
+
+    Var::Var(const std::string& str, double& val)
+      :symbol_(str),
+       value_(val)
+    {
+    }
+
+    Var::~Var()
+    {
+    }
+
+    void 
+    Var::AddToTable()
+    {
+      OMC_ASSERT_MSG(symbolTable_.add_variable(symbol_, value_),
+		     "The symbol \"" + symbol_ + "\" is not valid");
+    }
+
+
+    bool
+    Var::IsDoublon()
+    {
+      Core::SetOf<Var>& set = Core::SetOf<Var>::GetGlobalSet();
+      for (unsigned int i =0; i < set.GetTotItemNumber(); ++i)
+	if (&set(i) != this)
+	  if (set(i).symbol_ == symbol_)
+	    return true;
+      
+      return false;
+    }
+
+
+    bool
+    Var::IsValid()
+    {
+      exprtk::symbol_table<double> table;
+      return table.add_variable(symbol_, value_);
+    }
+
+    
+
+  }
+
+}
+
+
diff --git a/SRC/OpenMeca/Util/Var.hpp b/SRC/OpenMeca/Util/Var.hpp
new file mode 100644
index 0000000..eeeefaf
--- /dev/null
+++ b/SRC/OpenMeca/Util/Var.hpp
@@ -0,0 +1,93 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Item_Var_hpp
+#define OpenMeca_Item_Var_hpp
+
+
+#include <string>
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+#include "OpenMeca/Util/exprtk.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+#include "OpenMeca/Core/AutoRegister.hpp"
+
+namespace OpenMeca
+{  
+  namespace Util
+  {
+
+    class Var : public Core::AutoRegister<Var>
+    {
+
+    public:
+      static void UpdateTable();
+      static exprtk::symbol_table<double>& GetSymbolTable();
+
+      
+
+    public:
+      Var();
+      Var(const std::string&, double&);
+
+      ~Var();
+
+      bool IsDoublon();
+      bool IsValid();
+
+
+      OMC_ACCESSOR(Symbol, std::string, symbol_);
+      OMC_ACCESSOR(Value , double     , value_ );
+
+    private:
+      Var(const Var&);             //Not Allowed
+      Var& operator=(const Var&);  //Not Allowed
+
+      void AddToTable();
+
+      
+      friend class boost::serialization::access;
+      template<class Archive>
+      void serialize(Archive & ar, const unsigned int);
+
+    private:
+      static exprtk::symbol_table<double> symbolTable_;
+
+    private:
+      std::string symbol_;
+      double value_;
+    };
+
+
+    template<class Archive>
+    inline void
+    Var::serialize(Archive & ar, const unsigned int)
+      {
+	ar & BOOST_SERIALIZATION_NVP(symbol_);
+	ar & BOOST_SERIALIZATION_NVP(value_);
+      }
+
+
+  }
+
+}
+
+#endif
diff --git a/SRC/OpenMeca/Util/Version.cpp b/SRC/OpenMeca/Util/Version.cpp
new file mode 100644
index 0000000..c9d603d
--- /dev/null
+++ b/SRC/OpenMeca/Util/Version.cpp
@@ -0,0 +1,127 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#include <QString>
+#include <QStringList>
+
+#include "OpenMeca/Util/Version.hpp"
+#include "OpenMeca/Core/Macro.hpp"
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    std::ostream& 
+    operator<< (std::ostream& os, const Version & v)
+    {
+      os << v.str_;
+      return os;
+    }
+
+
+    Version::Version(const std::string& vstr)
+      :str_(""),
+       omc_major_(0), omc_minor_(0), omc_revision_(0)
+    {
+      ReadString(vstr);
+    }
+
+
+    Version::Version()
+      :str_(""),
+       omc_major_(0), omc_minor_(0), omc_revision_(0)
+       
+    {
+    }
+   
+    Version::~Version()
+    {
+    }
+
+    void 
+    Version::ReadString(const std::string& vstr)
+    {
+      str_ = vstr;
+      QString str(vstr.c_str());
+      QStringList fields = str.split(".");
+      OMC_ASSERT_MSG(fields.count()==3, 
+		     "Problem while reading version, the version must contain tree number : major.minor.revision and I read \"" + vstr + "\"");
+      omc_major_    = fields[0].toInt();
+      omc_minor_    = fields[1].toInt();
+      omc_revision_ = fields[2].toInt();
+    }
+
+    const std::string& 
+    Version::ToString() const
+    {
+      OMC_ASSERT_MSG(str_ != "", "The required version is empty");
+      return str_;
+    }
+
+    
+    bool 
+    Version::operator<(const Version& otherVersion) const
+    {
+      OMC_ASSERT_MSG(str_ != "", "The required version is empty");
+      OMC_ASSERT_MSG(otherVersion.str_ != "", "The required version is empty");
+
+       if(omc_major_ < otherVersion.omc_major_)
+            return true;
+        if(omc_minor_ < otherVersion.omc_minor_)
+            return true;
+        if(omc_revision_ < otherVersion.omc_revision_)
+            return true;
+        return false;
+    }
+    bool 
+    Version::operator>(const Version& otherVersion) const
+    {
+
+      if(omc_major_ > otherVersion.omc_major_)
+	return true;
+      else if(omc_major_ < otherVersion.omc_major_)
+	return false;
+      
+      if(omc_minor_ > otherVersion.omc_minor_)
+	return true;
+      else if(omc_minor_ < otherVersion.omc_minor_)
+	return false;
+      
+      if(omc_revision_ > otherVersion.omc_revision_)
+	return true;
+      else if(omc_revision_ < otherVersion.omc_revision_)
+	return false;
+
+        return false;
+    }
+
+     bool 
+    Version::operator==(const Version& otherVersion) const
+    {
+      OMC_ASSERT_MSG(str_ != "", "The required version is empty");
+      OMC_ASSERT_MSG(otherVersion.str_ != "", "The required version is empty");
+      return (omc_major_    == otherVersion.omc_major_ &&
+	      omc_minor_    == otherVersion.omc_minor_ && 
+	      omc_revision_ == otherVersion.omc_revision_);
+    }
+      
+
+  }
+}
diff --git a/SRC/OpenMeca/Util/Version.hpp b/SRC/OpenMeca/Util/Version.hpp
new file mode 100644
index 0000000..cb5fd5e
--- /dev/null
+++ b/SRC/OpenMeca/Util/Version.hpp
@@ -0,0 +1,79 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Util_Version_hpp
+#define OpenMeca_Util_Version_hpp
+
+#include <string>
+#include "Serialization/archive/text_oarchive.hpp"
+#include "Serialization/archive/text_iarchive.hpp"
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+    class Version;
+
+    std::ostream& operator<< (std::ostream &, const Version &);
+
+    
+    // openmeca's color class
+    class Version
+    {
+    public:
+      friend std::ostream& operator<< (std::ostream &, const Version &);
+
+    public:
+      Version(const std::string&);
+      Version();
+      ~Version();
+
+      void ReadString(const std::string&);
+      const std::string& ToString() const;
+
+      bool operator<(const Version& otherVersion)  const;
+      bool operator>(const Version& otherVersion) const;
+      bool operator==(const Version& otherVersion ) const;
+      
+    private:
+      friend class boost::serialization::access;
+      template<class Archive> void serialize(Archive& ar, const unsigned int version);
+
+    private:
+      std::string str_;
+      unsigned int omc_major_, omc_minor_, omc_revision_;
+      
+    private :
+      //Copy constructor and assignment operator are built by compiler
+    }; 
+    
+    template<class Archive>
+    inline void
+    Version::serialize(Archive& ar, const unsigned int)
+    {
+      ar & BOOST_SERIALIZATION_NVP(str_);
+      ar & BOOST_SERIALIZATION_NVP(omc_major_);
+      ar & BOOST_SERIALIZATION_NVP(omc_minor_);
+      ar & BOOST_SERIALIZATION_NVP(omc_revision_);
+    }
+
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/exprtk.hpp b/SRC/OpenMeca/Util/exprtk.hpp
new file mode 100644
index 0000000..17bb65b
--- /dev/null
+++ b/SRC/OpenMeca/Util/exprtk.hpp
@@ -0,0 +1,33740 @@
+/*
+ ******************************************************************
+ *           C++ Mathematical Expression Toolkit Library          *
+ *                                                                *
+ * Author: Arash Partow (1999-2016)                               *
+ * URL: http://www.partow.net/programming/exprtk/index.html       *
+ *                                                                *
+ * Copyright notice:                                              *
+ * Free use of the C++ Mathematical Expression Toolkit Library is *
+ * permitted under the guidelines and in accordance with the most *
+ * current version of the Common Public License.                  *
+ * http://www.opensource.org/licenses/cpl1.0.php                  *
+ *                                                                *
+ * Example expressions:                                           *
+ * (00) (y + x / y) * (x - y / x)                                 *
+ * (01) (x^2 / sin(2 * pi / y)) - x / 2                           *
+ * (02) sqrt(1 - (x^2))                                           *
+ * (03) 1 - sin(2 * x) + cos(pi / y)                              *
+ * (04) a * exp(2 * t) + c                                        *
+ * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z)        *
+ * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x          *
+ * (07) z := x + sin(2 * pi / y)                                  *
+ * (08) u := 2 * (pi * z) / (w := x + cos(y / pi))                *
+ * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1)            *
+ * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0)     *
+ * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1)  *
+ * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)]                  *
+ *                                                                *
+ ******************************************************************
+*/
+
+
+#ifndef INCLUDE_EXPRTK_HPP
+#define INCLUDE_EXPRTK_HPP
+
+
+#include <algorithm>
+#include <cctype>
+#include <cmath>
+#include <complex>
+#include <cstdio>
+#include <cstdlib>
+#include <deque>
+#include <exception>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <list>
+#include <map>
+#include <set>
+#include <stack>
+#include <stdexcept>
+#include <string>
+#include <utility>
+#include <vector>
+
+
+namespace exprtk
+{
+   #ifdef exprtk_enable_debugging
+     #define exprtk_debug(params) printf params
+   #else
+     #define exprtk_debug(params) (void)0
+   #endif
+
+   namespace details
+   {
+      inline bool is_whitespace(const char c)
+      {
+         return (' '  == c) || ('\n' == c) ||
+                ('\r' == c) || ('\t' == c) ||
+                ('\b' == c) || ('\v' == c) ||
+                ('\f' == c) ;
+      }
+
+      inline bool is_operator_char(const char c)
+      {
+         return ('+' == c) || ('-' == c) ||
+                ('*' == c) || ('/' == c) ||
+                ('^' == c) || ('<' == c) ||
+                ('>' == c) || ('=' == c) ||
+                (',' == c) || ('!' == c) ||
+                ('(' == c) || (')' == c) ||
+                ('[' == c) || (']' == c) ||
+                ('{' == c) || ('}' == c) ||
+                ('%' == c) || (':' == c) ||
+                ('?' == c) || ('&' == c) ||
+                ('|' == c) || (';' == c) ;
+      }
+
+      inline bool is_letter(const char c)
+      {
+         return (('a' <= c) && (c <= 'z')) ||
+                (('A' <= c) && (c <= 'Z')) ;
+      }
+
+      inline bool is_digit(const char c)
+      {
+         return ('0' <= c) && (c <= '9');
+      }
+
+      inline bool is_letter_or_digit(const char c)
+      {
+         return is_letter(c) || is_digit(c);
+      }
+
+      inline bool is_left_bracket(const char c)
+      {
+         return ('(' == c) || ('[' == c) || ('{' == c);
+      }
+
+      inline bool is_right_bracket(const char c)
+      {
+         return (')' == c) || (']' == c) || ('}' == c);
+      }
+
+      inline bool is_bracket(const char c)
+      {
+         return is_left_bracket(c) || is_right_bracket(c);
+      }
+
+      inline bool is_sign(const char c)
+      {
+         return ('+' == c) || ('-' == c);
+      }
+
+      inline bool is_invalid(const char c)
+      {
+         return !is_whitespace   (c) &&
+                !is_operator_char(c) &&
+                !is_letter       (c) &&
+                !is_digit        (c) &&
+                ('.'  != c)          &&
+                ('_'  != c)          &&
+                ('$'  != c)          &&
+                ('~'  != c)          &&
+                ('\'' != c);
+      }
+
+      inline bool imatch(const char c1, const char c2)
+      {
+         return std::tolower(c1) == std::tolower(c2);
+      }
+
+      inline bool imatch(const std::string& s1, const std::string& s2)
+      {
+         if (s1.size() == s2.size())
+         {
+            for (std::size_t i = 0; i < s1.size(); ++i)
+            {
+               if (std::tolower(s1[i]) != std::tolower(s2[i]))
+               {
+                  return false;
+               }
+            }
+
+            return true;
+         }
+
+         return false;
+      }
+
+      inline bool is_valid_sf_symbol(const std::string& symbol)
+      {
+         // Special function: $f12 or $F34
+         return (4 == symbol.size())  &&
+                ('$' == symbol[0])    &&
+                imatch('f',symbol[1]) &&
+                is_digit(symbol[2])   &&
+                is_digit(symbol[3]);
+      }
+
+      inline const char& front(const std::string& s)
+      {
+         return s[0];
+      }
+
+      inline const char& back(const std::string& s)
+      {
+         return s[s.size() - 1];
+      }
+
+      inline std::string to_str(int i)
+      {
+         if (0 == i)
+            return std::string("0");
+
+         std::string result;
+
+         if (i < 0)
+         {
+            for ( ; i; i /= 10)
+            {
+               result += '0' + char(-(i % 10));
+            }
+
+            result += '-';
+         }
+         else
+         {
+            for ( ; i; i /= 10)
+            {
+               result += '0' + char(i % 10);
+            }
+         }
+
+         std::reverse(result.begin(), result.end());
+
+         return result;
+      }
+
+      inline bool is_hex_digit(const std::string::value_type digit)
+      {
+         return (('0' <= digit) && (digit <= '9')) ||
+                (('A' <= digit) && (digit <= 'F')) ||
+                (('a' <= digit) && (digit <= 'f')) ;
+      }
+
+      inline unsigned char hex_to_bin(unsigned char h)
+      {
+         if (('0' <= h) && (h <= '9'))
+            return (h - '0');
+         else
+            return static_cast<unsigned char>(std::toupper(h) - 'A');
+      }
+
+      template <typename Iterator>
+      inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
+      {
+         if (
+              (end !=  (itr    )) &&
+              (end !=  (itr + 1)) &&
+              (end !=  (itr + 2)) &&
+              (end !=  (itr + 3)) &&
+              ('0' == *(itr    )) &&
+              (
+                ('x' == *(itr + 1)) ||
+                ('X' == *(itr + 1))
+              ) &&
+              (is_hex_digit(*(itr + 2))) &&
+              (is_hex_digit(*(itr + 3)))
+            )
+         {
+            result = hex_to_bin(*(itr + 2)) << 4 | hex_to_bin(*(itr + 3));
+            itr += 3;
+         }
+         else
+            result = '\0';
+      }
+
+      inline void cleanup_escapes(std::string& s)
+      {
+         typedef std::string::iterator str_itr_t;
+
+         str_itr_t itr1 = s.begin();
+         str_itr_t itr2 = s.begin();
+         str_itr_t end  = s.end  ();
+
+         std::size_t removal_count  = 0;
+
+         while (end != itr1)
+         {
+            if ('\\' == (*itr1))
+            {
+               ++removal_count;
+
+               if (end == ++itr1)
+                  break;
+               else if ('\\' != (*itr1))
+               {
+                  switch (*itr1)
+                  {
+                     case 'n' : (*itr1) = '\n'; break;
+                     case 'r' : (*itr1) = '\r'; break;
+                     case 't' : (*itr1) = '\t'; break;
+                     case '0' : parse_hex(itr1, end, (*itr1));
+                                removal_count += 3;
+                                break;
+                  }
+
+                  continue;
+               }
+            }
+
+            if (itr1 != itr2)
+            {
+               (*itr2) = (*itr1);
+            }
+
+            ++itr1;
+            ++itr2;
+         }
+
+         s.resize(s.size() - removal_count);
+      }
+
+      class build_string
+      {
+      public:
+
+         build_string(const std::size_t& initial_size = 64)
+         {
+            data_.reserve(initial_size);
+         }
+
+         inline build_string& operator << (const std::string& s)
+         {
+            data_ += s;
+            return (*this);
+         }
+
+         inline build_string& operator << (const char* s)
+         {
+            data_ += std::string(s);
+            return (*this);
+         }
+
+         inline operator std::string () const
+         {
+            return data_;
+         }
+
+         inline std::string as_string() const
+         {
+            return data_;
+         }
+
+      private:
+
+         std::string data_;
+      };
+
+      struct ilesscompare
+      {
+         inline bool operator()(const std::string& s1, const std::string& s2) const
+         {
+            const std::size_t length = std::min(s1.size(),s2.size());
+
+            for (std::size_t i = 0; i < length;  ++i)
+            {
+               const char c1 = static_cast<char>(std::tolower(s1[i]));
+               const char c2 = static_cast<char>(std::tolower(s2[i]));
+
+               if (c1 > c2)
+                  return false;
+               else if (c1 < c2)
+                  return true;
+            }
+
+            return s1.size() < s2.size();
+         }
+      };
+
+      static const std::string reserved_words[] =
+                                  {
+                                    "break",  "case",  "continue",  "default",  "false",  "for",
+                                    "if", "else", "ilike",  "in", "like", "and",  "nand", "nor",
+                                    "not",  "null",  "or",   "repeat", "return",  "shl",  "shr",
+                                    "swap", "switch", "true",  "until", "var",  "while", "xnor",
+                                    "xor", "&", "|"
+                                  };
+
+      static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
+
+      static const std::string reserved_symbols[] =
+                                  {
+                                    "abs",  "acos",  "acosh",  "and",  "asin",  "asinh", "atan",
+                                    "atanh", "atan2", "avg",  "break", "case", "ceil",  "clamp",
+                                    "continue",   "cos",   "cosh",   "cot",   "csc",  "default",
+                                    "deg2grad",  "deg2rad",   "equal",  "erf",   "erfc",  "exp",
+                                    "expm1",  "false",   "floor",  "for",   "frac",  "grad2deg",
+                                    "hypot", "iclamp", "if",  "else", "ilike", "in",  "inrange",
+                                    "like",  "log",  "log10", "log2",  "logn",  "log1p", "mand",
+                                    "max", "min",  "mod", "mor",  "mul", "ncdf",  "nand", "nor",
+                                    "not",   "not_equal",   "null",   "or",   "pow",  "rad2deg",
+                                    "repeat", "return", "root", "round", "roundn", "sec", "sgn",
+                                    "shl", "shr", "sin", "sinc", "sinh", "sqrt",  "sum", "swap",
+                                    "switch", "tan",  "tanh", "true",  "trunc", "until",  "var",
+                                    "while", "xnor", "xor", "&", "|"
+                                  };
+
+      static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
+
+      static const std::string base_function_list[] =
+                                  {
+                                    "abs", "acos",  "acosh", "asin",  "asinh", "atan",  "atanh",
+                                    "atan2",  "avg",  "ceil",  "clamp",  "cos",  "cosh",  "cot",
+                                    "csc",  "equal",  "erf",  "erfc",  "exp",  "expm1", "floor",
+                                    "frac", "hypot", "iclamp",  "like", "log", "log10",  "log2",
+                                    "logn", "log1p", "mand", "max", "min", "mod", "mor",  "mul",
+                                    "ncdf",  "pow",  "root",  "round",  "roundn",  "sec", "sgn",
+                                    "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
+                                    "trunc",  "not_equal",  "inrange",  "deg2grad",   "deg2rad",
+                                    "rad2deg", "grad2deg"
+                                  };
+
+      static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
+
+      static const std::string logic_ops_list[] =
+                                  {
+                                    "and", "nand", "nor", "not", "or",  "xnor", "xor", "&", "|"
+                                  };
+
+      static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
+
+      static const std::string cntrl_struct_list[] =
+                                  {
+                                     "if", "switch", "for", "while", "repeat"
+                                  };
+
+      static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
+
+      static const std::string arithmetic_ops_list[] =
+                                  {
+                                    "+", "-", "*", "/", "%", "^"
+                                  };
+
+      static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
+
+      static const std::string assignment_ops_list[] =
+                                  {
+                                    ":=", "+=", "-=",
+                                    "*=", "/=", "%="
+                                  };
+
+      static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
+
+      static const std::string inequality_ops_list[] =
+                                  {
+                                     "<",  "<=", "==",
+                                     "=",  "!=", "<>",
+                                    ">=",  ">"
+                                  };
+
+      static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
+
+      inline bool is_reserved_word(const std::string& symbol)
+      {
+         for (std::size_t i = 0; i < reserved_words_size; ++i)
+         {
+            if (imatch(symbol,reserved_words[i]))
+            {
+               return true;
+            }
+         }
+
+         return false;
+      }
+
+      inline bool is_reserved_symbol(const std::string& symbol)
+      {
+         for (std::size_t i = 0; i < reserved_symbols_size; ++i)
+         {
+            if (imatch(symbol,reserved_symbols[i]))
+            {
+               return true;
+            }
+         }
+
+         return false;
+      }
+
+      inline bool is_base_function(const std::string& function_name)
+      {
+         for (std::size_t i = 0; i < base_function_list_size; ++i)
+         {
+            if (imatch(function_name,base_function_list[i]))
+            {
+               return true;
+            }
+         }
+
+         return false;
+      }
+
+      inline bool is_control_struct(const std::string& cntrl_strct)
+      {
+         for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
+         {
+            if (imatch(cntrl_strct,cntrl_struct_list[i]))
+            {
+               return true;
+            }
+         }
+
+         return false;
+      }
+
+      inline bool is_logic_opr(const std::string& lgc_opr)
+      {
+         for (std::size_t i = 0; i < logic_ops_list_size; ++i)
+         {
+            if (imatch(lgc_opr,logic_ops_list[i]))
+            {
+               return true;
+            }
+         }
+
+         return false;
+      }
+
+      struct cs_match
+      {
+         static inline bool cmp(const char c0, const char c1)
+         {
+            return (c0 == c1);
+         }
+      };
+
+      struct cis_match
+      {
+         static inline bool cmp(const char c0, const char c1)
+         {
+            return (std::tolower(c0) == std::tolower(c1));
+         }
+      };
+
+      template <typename Iterator, typename Compare>
+      inline bool match_impl(const Iterator pattern_begin,
+                             const Iterator pattern_end,
+                             const Iterator data_begin,
+                             const Iterator data_end,
+                             const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
+                             const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
+      {
+         if (0 == std::distance(data_begin,data_end))
+         {
+            return false;
+         }
+
+         Iterator d_itr = data_begin;
+         Iterator p_itr = pattern_begin;
+         Iterator c_itr = data_begin;
+         Iterator m_itr = data_begin;
+
+         while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
+         {
+            if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
+            {
+               return false;
+            }
+
+            ++p_itr;
+            ++d_itr;
+         }
+
+         while (data_end != d_itr)
+         {
+            if (zero_or_more == (*p_itr))
+            {
+               if (pattern_end == (++p_itr))
+               {
+                  return true;
+               }
+
+               m_itr = p_itr;
+               c_itr = d_itr;
+               ++c_itr;
+            }
+            else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
+            {
+               ++p_itr;
+               ++d_itr;
+            }
+            else
+            {
+               p_itr = m_itr;
+               d_itr = c_itr++;
+            }
+         }
+
+         while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) { ++p_itr; }
+
+         return (p_itr == pattern_end);
+      }
+
+      inline bool wc_match(const std::string& wild_card,
+                           const std::string& str)
+      {
+         return match_impl<const char*,cs_match>(wild_card.data(),
+                                                 wild_card.data() + wild_card.size(),
+                                                 str.data(),
+                                                 str.data() + str.size(),
+                                                 '*',
+                                                 '?');
+      }
+
+      inline bool wc_imatch(const std::string& wild_card,
+                            const std::string& str)
+      {
+         return match_impl<const char*,cis_match>(wild_card.data(),
+                                                  wild_card.data() + wild_card.size(),
+                                                  str.data(),
+                                                  str.data() + str.size(),
+                                                  '*',
+                                                  '?');
+      }
+
+      inline bool sequence_match(const std::string& pattern,
+                                 const std::string& str,
+                                 std::size_t&       diff_index,
+                                 char&              diff_value)
+      {
+         if (str.empty() || pattern.empty())
+            return false;
+         else if ('*' == pattern[0])
+            return false;
+
+         typedef std::string::const_iterator itr_t;
+
+         itr_t p_itr = pattern.begin();
+         itr_t s_itr = str    .begin();
+
+         itr_t p_end = pattern.end();
+         itr_t s_end = str    .end();
+
+         while ((s_end != s_itr) && (p_end != p_itr))
+         {
+            if ('*' == (*p_itr))
+            {
+               const char target = static_cast<char>(std::toupper(*(p_itr - 1)));
+
+               if ('*' == target)
+               {
+                  diff_index = std::distance(str.begin(),s_itr);
+                  diff_value = static_cast<char>(std::toupper(*p_itr));
+
+                  return false;
+               }
+               else
+                  ++p_itr;
+
+               while (s_itr != s_end)
+               {
+                  if (target != std::toupper(*s_itr))
+                     break;
+                  else
+                     ++s_itr;
+               }
+
+               continue;
+            }
+            else if (
+                      ('?' != *p_itr) &&
+                      std::toupper(*p_itr) != std::toupper(*s_itr)
+                    )
+            {
+               diff_index = std::distance(str.begin(),s_itr);
+               diff_value = static_cast<char>(std::toupper(*p_itr));
+
+               return false;
+            }
+
+            ++p_itr;
+            ++s_itr;
+         }
+
+         return (
+                  (s_end == s_itr) &&
+                  (
+                    (p_end ==  p_itr) ||
+                    ('*'   == *p_itr)
+                  )
+                );
+      }
+
+      static const double pow10[] = {
+                                      1.0,
+                                      1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
+                                      1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
+                                      1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
+                                      1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
+                                    };
+
+     static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
+
+      namespace numeric
+      {
+         namespace constant
+         {
+            static const double e       =  2.71828182845904523536028747135266249775724709369996;
+            static const double pi      =  3.14159265358979323846264338327950288419716939937510;
+            static const double pi_2    =  1.57079632679489661923132169163975144209858469968755;
+            static const double pi_4    =  0.78539816339744830961566084581987572104929234984378;
+            static const double pi_180  =  0.01745329251994329576923690768488612713442871888542;
+            static const double _1_pi   =  0.31830988618379067153776752674502872406891929148091;
+            static const double _2_pi   =  0.63661977236758134307553505349005744813783858296183;
+            static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
+            static const double log2    =  0.69314718055994530941723212145817656807550013436026;
+            static const double sqrt2   =  1.41421356237309504880168872420969807856967187537695;
+         }
+
+         namespace details
+         {
+            struct unknown_type_tag {};
+            struct real_type_tag    {};
+            struct complex_type_tag {};
+            struct int_type_tag     {};
+
+            template <typename T>
+            struct number_type { typedef unknown_type_tag type; };
+
+            #define exprtk_register_real_type_tag(T)                          \
+            template<> struct number_type<T> { typedef real_type_tag type; }; \
+
+            #define exprtk_register_complex_type_tag(T)     \
+            template<> struct number_type<std::complex<T> > \
+            { typedef complex_type_tag type; };             \
+
+            #define exprtk_register_int_type_tag(T)                          \
+            template<> struct number_type<T> { typedef int_type_tag type; }; \
+
+            exprtk_register_real_type_tag(double     )
+            exprtk_register_real_type_tag(long double)
+            exprtk_register_real_type_tag(float      )
+
+            exprtk_register_complex_type_tag(double     )
+            exprtk_register_complex_type_tag(long double)
+            exprtk_register_complex_type_tag(float      )
+
+            exprtk_register_int_type_tag(short                 )
+            exprtk_register_int_type_tag(int                   )
+            exprtk_register_int_type_tag(long long int         )
+            exprtk_register_int_type_tag(unsigned short        )
+            exprtk_register_int_type_tag(unsigned int          )
+            exprtk_register_int_type_tag(unsigned long long int)
+
+            #undef exprtk_register_real_type_tag
+            #undef exprtk_register_int_type_tag
+
+            template <typename T>
+            struct epsilon_type
+            {
+               static inline T value()
+               {
+                  const T epsilon = T(0.0000000001);
+                  return epsilon;
+               }
+            };
+
+            template <>
+            struct epsilon_type <float>
+            {
+               static inline float value()
+               {
+                  const float epsilon = float(0.000001f);
+                  return epsilon;
+               }
+            };
+
+            template <>
+            struct epsilon_type <long double>
+            {
+               static inline long double value()
+               {
+                  const long double epsilon = (long double)(0.000000000001);
+                  return epsilon;
+               }
+            };
+
+            template <typename T>
+            inline bool is_nan_impl(const T v, real_type_tag)
+            {
+               return std::not_equal_to<T>()(v,v);
+            }
+
+            template <typename T>
+            inline int to_int32_impl(const T v, real_type_tag)
+            {
+               return static_cast<int>(v);
+            }
+
+            template <typename T>
+            inline long long int to_int64_impl(const T v, real_type_tag)
+            {
+               return static_cast<long long int>(v);
+            }
+
+            template <typename T>
+            inline bool is_true_impl(const T v)
+            {
+               return std::not_equal_to<T>()(T(0),v);
+            }
+
+            template <typename T>
+            inline bool is_false_impl(const T v)
+            {
+               return std::equal_to<T>()(T(0),v);
+            }
+
+            template <typename T>
+            inline T abs_impl(const T v, real_type_tag)
+            {
+               return ((v >= T(0)) ? v : -v);
+            }
+
+            template <typename T>
+            inline T min_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::min<T>(v0,v1);
+            }
+
+            template <typename T>
+            inline T max_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::max<T>(v0,v1);
+            }
+
+            template <typename T>
+            inline T equal_impl(const T v0, const T v1, real_type_tag)
+            {
+               const T epsilon = epsilon_type<T>::value();
+               return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
+            }
+
+            inline float equal_impl(const float v0, const float v1, real_type_tag)
+            {
+               const float epsilon = epsilon_type<float>::value();
+               return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
+            }
+
+            template <typename T>
+            inline T equal_impl(const T v0, const T v1, int_type_tag)
+            {
+               return (v0 == v1) ? 1 : 0;
+            }
+
+            template <typename T>
+            inline T expm1_impl(const T v, real_type_tag)
+            {
+               // return std::expm1<T>(v);
+               if (abs_impl(v,real_type_tag()) < T(0.00001))
+                  return v + (T(0.5) * v * v);
+               else
+                  return std::exp(v) - T(1);
+            }
+
+            template <typename T>
+            inline T expm1_impl(const T v, int_type_tag)
+            {
+               return T(std::exp<double>(v)) - T(1);
+            }
+
+            template <typename T>
+            inline T nequal_impl(const T v0, const T v1, real_type_tag)
+            {
+               typedef real_type_tag rtg;
+               const T epsilon = epsilon_type<T>::value();
+               return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
+            }
+
+            inline float nequal_impl(const float v0, const float v1, real_type_tag)
+            {
+               typedef real_type_tag rtg;
+               const float epsilon = epsilon_type<float>::value();
+               return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
+            }
+
+            template <typename T>
+            inline T nequal_impl(const T v0, const T v1, int_type_tag)
+            {
+               return (v0 != v1) ? 1 : 0;
+            }
+
+            template <typename T>
+            inline T modulus_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::fmod(v0,v1);
+            }
+
+            template <typename T>
+            inline T modulus_impl(const T v0, const T v1, int_type_tag)
+            {
+               return v0 % v1;
+            }
+
+            template <typename T>
+            inline T pow_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::pow(v0,v1);
+            }
+
+            template <typename T>
+            inline T pow_impl(const T v0, const T v1, int_type_tag)
+            {
+               return std::pow(static_cast<double>(v0),static_cast<double>(v1));
+            }
+
+            template <typename T>
+            inline T logn_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::log(v0) / std::log(v1);
+            }
+
+            template <typename T>
+            inline T logn_impl(const T v0, const T v1, int_type_tag)
+            {
+               return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
+            }
+
+            template <typename T>
+            inline T log1p_impl(const T v, real_type_tag)
+            {
+               if (v > T(-1))
+               {
+                  if (abs_impl(v,real_type_tag()) > T(0.0001))
+                  {
+                     return std::log(T(1) + v);
+                  }
+                  else
+                     return (T(-0.5) * v + T(1)) * v;
+               }
+               else
+                  return std::numeric_limits<T>::quiet_NaN();
+            }
+
+            template <typename T>
+            inline T log1p_impl(const T v, int_type_tag)
+            {
+               if (v > T(-1))
+               {
+                  return std::log(T(1) + v);
+               }
+               else
+                  return std::numeric_limits<T>::quiet_NaN();
+            }
+
+            template <typename T>
+            inline T root_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::pow(v0,T(1) / v1);
+            }
+
+            template <typename T>
+            inline T root_impl(const T v0, const T v1, int_type_tag)
+            {
+               return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
+            }
+
+            template <typename T>
+            inline T round_impl(const T v, real_type_tag)
+            {
+               return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
+            }
+
+            template <typename T>
+            inline T roundn_impl(const T v0, const T v1, real_type_tag)
+            {
+               const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
+               const T p10 = T(pow10[index]);
+               if (v0 < T(0))
+                  return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
+               else
+                  return T(std::floor((v0 * p10) + T(0.5)) / p10);
+            }
+
+            template <typename T>
+            inline T roundn_impl(const T v0, const T, int_type_tag)
+            {
+               return v0;
+            }
+
+            template <typename T>
+            inline T hypot_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::sqrt((v0 * v0) + (v1 * v1));
+            }
+
+            template <typename T>
+            inline T hypot_impl(const T v0, const T v1, int_type_tag)
+            {
+               return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
+            }
+
+            template <typename T>
+            inline T atan2_impl(const T v0, const T v1, real_type_tag)
+            {
+               return std::atan2(v0,v1);
+            }
+
+            template <typename T>
+            inline T atan2_impl(const T, const T, int_type_tag)
+            {
+               return 0;
+            }
+
+            template <typename T>
+            inline T shr_impl(const T v0, const T v1, real_type_tag)
+            {
+               return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
+            }
+
+            template <typename T>
+            inline T shr_impl(const T v0, const T v1, int_type_tag)
+            {
+               return v0 >> v1;
+            }
+
+            template <typename T>
+            inline T shl_impl(const T v0, const T v1, real_type_tag)
+            {
+               return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
+            }
+
+            template <typename T>
+            inline T shl_impl(const T v0, const T v1, int_type_tag)
+            {
+               return v0 << v1;
+            }
+
+            template <typename T>
+            inline T sgn_impl(const T v, real_type_tag)
+            {
+                    if (v > T(0)) return T(+1);
+               else if (v < T(0)) return T(-1);
+               else               return T( 0);
+            }
+
+            template <typename T>
+            inline T sgn_impl(const T v, int_type_tag)
+            {
+                    if (v > T(0)) return T(+1);
+               else if (v < T(0)) return T(-1);
+               else               return T( 0);
+            }
+
+            template <typename T>
+            inline T and_impl(const T v0, const T v1, real_type_tag)
+            {
+               return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
+            }
+
+            template <typename T>
+            inline T and_impl(const T v0, const T v1, int_type_tag)
+            {
+               return v0 && v1;
+            }
+
+            template <typename T>
+            inline T nand_impl(const T v0, const T v1, real_type_tag)
+            {
+               return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
+            }
+
+            template <typename T>
+            inline T nand_impl(const T v0, const T v1, int_type_tag)
+            {
+               return !(v0 && v1);
+            }
+
+            template <typename T>
+            inline T or_impl(const T v0, const T v1, real_type_tag)
+            {
+               return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
+            }
+
+            template <typename T>
+            inline T or_impl(const T v0, const T v1, int_type_tag)
+            {
+               return (v0 || v1);
+            }
+
+            template <typename T>
+            inline T nor_impl(const T v0, const T v1, real_type_tag)
+            {
+               return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
+            }
+
+            template <typename T>
+            inline T nor_impl(const T v0, const T v1, int_type_tag)
+            {
+               return !(v0 || v1);
+            }
+
+            template <typename T>
+            inline T xor_impl(const T v0, const T v1, real_type_tag)
+            {
+               return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
+            }
+
+            template <typename T>
+            inline T xor_impl(const T v0, const T v1, int_type_tag)
+            {
+               return v0 ^ v1;
+            }
+
+            template <typename T>
+            inline T xnor_impl(const T v0, const T v1, real_type_tag)
+            {
+               const bool v0_true = is_true_impl(v0);
+               const bool v1_true = is_true_impl(v1);
+               if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
+                  return T(1);
+               else
+                  return T(0);
+            }
+
+            template <typename T>
+            inline T xnor_impl(const T v0, const T v1, int_type_tag)
+            {
+               const bool v0_true = is_true_impl(v0);
+               const bool v1_true = is_true_impl(v1);
+               if ((v0_true &&  v1_true) || (!v0_true && !v1_true))
+                  return T(1);
+               else
+                  return T(0);
+            }
+
+            template <typename T>
+            inline T erf_impl(T v, real_type_tag)
+            {
+               #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+               // Credits: Abramowitz & Stegun Equations 7.1.25-28
+               const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
+               static const T c[] = {
+                                      T( 1.26551223), T(1.00002368),
+                                      T( 0.37409196), T(0.09678418),
+                                      T(-0.18628806), T(0.27886807),
+                                      T(-1.13520398), T(1.48851587),
+                                      T(-0.82215223), T(0.17087277)
+                                    };
+               T result = T(1) - t * std::exp((-v * v) -
+                                      c[0] + t * (c[1] + t *
+                                     (c[2] + t * (c[3] + t *
+                                     (c[4] + t * (c[5] + t *
+                                     (c[6] + t * (c[7] + t *
+                                     (c[8] + t * (c[9]))))))))));
+               return (v >= T(0)) ? result : -result;
+               #else
+               return ::erf(v);
+               #endif
+            }
+
+            template <typename T>
+            inline T erf_impl(T v, int_type_tag)
+            {
+               return erf_impl(static_cast<double>(v),real_type_tag());
+            }
+
+            template <typename T>
+            inline T erfc_impl(T v, real_type_tag)
+            {
+               #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+               return T(1) - erf_impl(v,real_type_tag());
+               #else
+               return ::erfc(v);
+               #endif
+            }
+
+            template <typename T>
+            inline T erfc_impl(T v, int_type_tag)
+            {
+               return erfc_impl(static_cast<double>(v),real_type_tag());
+            }
+
+            template <typename T>
+            inline T ncdf_impl(T v, real_type_tag)
+            {
+               T cnd = T(0.5) * (T(1) + erf_impl(
+                                           abs_impl(v,real_type_tag()) /
+                                           T(numeric::constant::sqrt2),real_type_tag()));
+               return  (v < T(0)) ? (T(1) - cnd) : cnd;
+            }
+
+            template <typename T>
+            inline T ncdf_impl(T v, int_type_tag)
+            {
+               return ncdf_impl(static_cast<double>(v),real_type_tag());
+            }
+
+            template <typename T>
+            inline T sinc_impl(T v, real_type_tag)
+            {
+               if (std::abs(v) >= std::numeric_limits<T>::epsilon())
+                   return(std::sin(v) / v);
+               else
+                  return T(1);
+            }
+
+            template <typename T>
+            inline T sinc_impl(T v, int_type_tag)
+            {
+               return sinc_impl(static_cast<double>(v),real_type_tag());
+            }
+
+            template <typename T> inline T  acos_impl(const T v, real_type_tag) { return std::acos (v); }
+            template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
+            template <typename T> inline T  asin_impl(const T v, real_type_tag) { return std::asin (v); }
+            template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
+            template <typename T> inline T  atan_impl(const T v, real_type_tag) { return std::atan (v); }
+            template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - log(T(1) - v)) / T(2); }
+            template <typename T> inline T  ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
+            template <typename T> inline T   cos_impl(const T v, real_type_tag) { return std::cos  (v); }
+            template <typename T> inline T  cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
+            template <typename T> inline T   exp_impl(const T v, real_type_tag) { return std::exp  (v); }
+            template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
+            template <typename T> inline T   log_impl(const T v, real_type_tag) { return std::log  (v); }
+            template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
+            template <typename T> inline T  log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
+            template <typename T> inline T   neg_impl(const T v, real_type_tag) { return -v;            }
+            template <typename T> inline T   pos_impl(const T v, real_type_tag) { return +v;            }
+            template <typename T> inline T   sin_impl(const T v, real_type_tag) { return std::sin  (v); }
+            template <typename T> inline T  sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
+            template <typename T> inline T  sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
+            template <typename T> inline T   tan_impl(const T v, real_type_tag) { return std::tan  (v); }
+            template <typename T> inline T  tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
+            template <typename T> inline T   cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
+            template <typename T> inline T   sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
+            template <typename T> inline T   csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
+            template <typename T> inline T   r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
+            template <typename T> inline T   d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180));  }
+            template <typename T> inline T   d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
+            template <typename T> inline T   g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
+            template <typename T> inline T  notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
+            template <typename T> inline T  frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
+            template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v));    }
+
+            template <typename T> inline T   abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
+            template <typename T> inline T   exp_impl(const T v, int_type_tag) { return std::exp  (v); }
+            template <typename T> inline T   log_impl(const T v, int_type_tag) { return std::log  (v); }
+            template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
+            template <typename T> inline T  log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
+            template <typename T> inline T   neg_impl(const T v, int_type_tag) { return -v;            }
+            template <typename T> inline T   pos_impl(const T v, int_type_tag) { return +v;            }
+            template <typename T> inline T  ceil_impl(const T v, int_type_tag) { return v;             }
+            template <typename T> inline T floor_impl(const T v, int_type_tag) { return v;             }
+            template <typename T> inline T round_impl(const T v, int_type_tag) { return v;             }
+            template <typename T> inline T  notl_impl(const T v, int_type_tag) { return !v;            }
+            template <typename T> inline T  sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
+            template <typename T> inline T  frac_impl(const T  , int_type_tag) { return T(0);          }
+            template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v;             }
+            template <typename T> inline T  acos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T acosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T  asin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T asinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T  atan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T atanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T   cos_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T  cosh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T   sin_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T  sinh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T   tan_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T  tanh_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T   cot_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T   sec_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+            template <typename T> inline T   csc_impl(const T  , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
+
+            template <typename T>
+            inline bool is_integer_impl(const T& v, real_type_tag)
+            {
+               return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
+            }
+
+            template <typename T>
+            inline bool is_integer_impl(const T&, int_type_tag)
+            {
+               return true;
+            }
+         }
+
+         template <typename Type>
+         struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
+
+         template<> struct numeric_info<int>         { enum { length = 10, size = 16, bound_length =  9}; };
+         template<> struct numeric_info<float>       { enum { min_exp =  -38, max_exp =  +38}; };
+         template<> struct numeric_info<double>      { enum { min_exp = -308, max_exp = +308}; };
+         template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
+
+         template <typename T>
+         inline int to_int32(const T v)
+         {
+            typename details::number_type<T>::type num_type;
+            return to_int32_impl(v,num_type);
+         }
+
+         template <typename T>
+         inline long long int to_int64(const T v)
+         {
+            typename details::number_type<T>::type num_type;
+            return to_int64_impl(v,num_type);
+         }
+
+         template <typename T>
+         inline bool is_nan(const T v)
+         {
+            typename details::number_type<T>::type num_type;
+            return is_nan_impl(v,num_type);
+         }
+
+         template <typename T>
+         inline T min(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return min_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T max(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return max_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T equal(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return equal_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T nequal(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return nequal_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T modulus(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return modulus_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T pow(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return pow_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T logn(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return logn_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T root(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return root_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T roundn(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return roundn_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T hypot(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return hypot_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T atan2(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return atan2_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T shr(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return shr_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T shl(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return shl_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T and_opr(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return and_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T nand_opr(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return nand_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T or_opr(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return or_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T nor_opr(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return nor_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T xor_opr(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return xor_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline T xnor_opr(const T v0, const T v1)
+         {
+            typename details::number_type<T>::type num_type;
+            return xnor_impl(v0,v1,num_type);
+         }
+
+         template <typename T>
+         inline bool is_integer(const T v)
+         {
+            typename details::number_type<T>::type num_type;
+            return is_integer_impl(v,num_type);
+         }
+
+         template <typename T, unsigned int N>
+         struct fast_exp
+         {
+            static inline T result(T v)
+            {
+               unsigned int k = N;
+               T l = T(1);
+
+               while (k)
+               {
+                  if (k & 1)
+                  {
+                     l *= v;
+                     --k;
+                  }
+
+                  v *= v;
+                  k >>= 1;
+               }
+
+               return l;
+            }
+         };
+
+         template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } };
+         template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
+         template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } };
+         template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
+         template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } };
+         template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
+         template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
+         template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
+         template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v;     } };
+         template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v;         } };
+         template <typename T> struct fast_exp<T, 0> { static inline T result(T  ) { return T(1);      } };
+
+         #define exprtk_define_unary_function(FunctionName)   \
+         template <typename T>                                \
+         inline T FunctionName (const T v)                    \
+         {                                                    \
+            typename details::number_type<T>::type num_type;  \
+            return  FunctionName##_impl(v,num_type);          \
+         }                                                    \
+
+         exprtk_define_unary_function(abs  )
+         exprtk_define_unary_function(acos )
+         exprtk_define_unary_function(acosh)
+         exprtk_define_unary_function(asin )
+         exprtk_define_unary_function(asinh)
+         exprtk_define_unary_function(atan )
+         exprtk_define_unary_function(atanh)
+         exprtk_define_unary_function(ceil )
+         exprtk_define_unary_function(cos  )
+         exprtk_define_unary_function(cosh )
+         exprtk_define_unary_function(exp  )
+         exprtk_define_unary_function(expm1)
+         exprtk_define_unary_function(floor)
+         exprtk_define_unary_function(log  )
+         exprtk_define_unary_function(log10)
+         exprtk_define_unary_function(log2 )
+         exprtk_define_unary_function(log1p)
+         exprtk_define_unary_function(neg  )
+         exprtk_define_unary_function(pos  )
+         exprtk_define_unary_function(round)
+         exprtk_define_unary_function(sin  )
+         exprtk_define_unary_function(sinc )
+         exprtk_define_unary_function(sinh )
+         exprtk_define_unary_function(sqrt )
+         exprtk_define_unary_function(tan  )
+         exprtk_define_unary_function(tanh )
+         exprtk_define_unary_function(cot  )
+         exprtk_define_unary_function(sec  )
+         exprtk_define_unary_function(csc  )
+         exprtk_define_unary_function(r2d  )
+         exprtk_define_unary_function(d2r  )
+         exprtk_define_unary_function(d2g  )
+         exprtk_define_unary_function(g2d  )
+         exprtk_define_unary_function(notl )
+         exprtk_define_unary_function(sgn  )
+         exprtk_define_unary_function(erf  )
+         exprtk_define_unary_function(erfc )
+         exprtk_define_unary_function(ncdf )
+         exprtk_define_unary_function(frac )
+         exprtk_define_unary_function(trunc)
+         #undef exprtk_define_unary_function
+      }
+
+      template <typename T>
+      inline T compute_pow10(T d, const int exponent)
+      {
+         static const double fract10[] =
+         {
+           0.0,
+           1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010,
+           1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020,
+           1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030,
+           1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040,
+           1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050,
+           1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060,
+           1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070,
+           1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080,
+           1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090,
+           1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100,
+           1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110,
+           1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120,
+           1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130,
+           1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140,
+           1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150,
+           1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160,
+           1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170,
+           1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180,
+           1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190,
+           1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200,
+           1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210,
+           1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220,
+           1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230,
+           1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240,
+           1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250,
+           1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260,
+           1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270,
+           1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280,
+           1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290,
+           1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300,
+           1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
+         };
+
+         static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
+
+         const int e = std::abs(exponent);
+
+         if (exponent >= std::numeric_limits<T>::min_exponent10)
+         {
+            if (e < fract10_size)
+            {
+               if (exponent > 0)
+                  return T(d * fract10[e]);
+               else
+                  return T(d / fract10[e]);
+            }
+            else
+               return T(d * std::pow(10.0, 10.0 * exponent));
+         }
+         else
+         {
+                     d /= T(fract10[           -std::numeric_limits<T>::min_exponent10]);
+            return T(d /    fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
+         }
+      }
+
+      template <typename Iterator, typename T>
+      inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
+      {
+         if (itr == end)
+            return false;
+
+         bool negative = ('-' == (*itr));
+
+         if (negative || ('+' == (*itr)))
+         {
+            if (end == ++itr)
+               return false;
+         }
+
+         while ((end != itr) && ('0' == (*itr))) ++itr;
+
+         bool return_result = true;
+         unsigned int digit = 0;
+         const std::size_t length = std::distance(itr,end);
+
+         if (length <= 4)
+         {
+            switch (length)
+            {
+               #ifdef exprtk_use_lut
+
+               #define exprtk_process_digit \
+               if ((digit = details::digit_table[(int)*itr++]) < 10) result = result * 10 + (digit); else { return_result = false; break; }
+
+               #else
+               #define exprtk_process_digit \
+               if ((digit = (*itr++ - '0')) < 10) result = result * 10 + (digit); else { return_result = false; break; }
+
+               #endif
+
+               case  4 : exprtk_process_digit
+               case  3 : exprtk_process_digit
+               case  2 : exprtk_process_digit
+               case  1 : if ((digit = (*itr - '0'))>= 10) { digit = 0; return_result = false; }
+
+               #undef exprtk_process_digit
+            }
+         }
+         else
+            return_result = false;
+
+         if (length && return_result)
+         {
+            result = result * 10 + static_cast<T>(digit);
+            ++itr;
+         }
+
+         result = negative ? -result : result;
+         return return_result;
+      }
+
+      template <typename Iterator, typename T>
+      static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
+      {
+         typedef typename std::iterator_traits<Iterator>::value_type type;
+         static const std::size_t nan_length = 3;
+         if (std::distance(itr,end) != static_cast<int>(nan_length))
+            return false;
+         if (static_cast<type>('n') == (*itr))
+         {
+            if (
+                 (static_cast<type>('a') != *(itr + 1)) ||
+                 (static_cast<type>('n') != *(itr + 2))
+               )
+            {
+               return false;
+            }
+         }
+         else if (
+                   (static_cast<type>('A') != *(itr + 1)) ||
+                   (static_cast<type>('N') != *(itr + 2))
+                 )
+         {
+            return false;
+         }
+         t = std::numeric_limits<T>::quiet_NaN();
+         return true;
+      }
+
+      template <typename Iterator, typename T>
+      static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
+      {
+         static const char inf_uc[] = "INFINITY";
+         static const char inf_lc[] = "infinity";
+         static const std::size_t inf_length = 8;
+         const std::size_t length = std::distance(itr,end);
+         if ((3 != length) && (inf_length != length))
+            return false;
+         const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
+         while (end != itr)
+         {
+            if (*inf_itr == static_cast<char>(*itr))
+            {
+               ++itr;
+               ++inf_itr;
+               continue;
+            }
+            else
+               return false;
+         }
+         if (negative)
+            t = -std::numeric_limits<T>::infinity();
+         else
+            t =  std::numeric_limits<T>::infinity();
+         return true;
+      }
+
+      template <typename Iterator, typename T>
+      inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
+      {
+         if (end == itr_external) return false;
+
+         Iterator itr = itr_external;
+
+         T d = T(0);
+
+         bool negative = ('-' == (*itr));
+
+         if (negative || '+' == (*itr))
+         {
+            if (end == ++itr)
+               return false;
+         }
+
+         bool instate = false;
+
+         #define parse_digit_1(d) \
+         if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; if (end == ++itr) break; \
+
+         #define parse_digit_2(d) \
+         if ((digit = (*itr - '0')) < 10) { d = d * T(10) + digit; } else break; ++itr; \
+
+         if ('.' != (*itr))
+         {
+            const Iterator curr = itr;
+            while ((end != itr) && ('0' == (*itr))) ++itr;
+            unsigned int digit;
+
+            while (end != itr)
+            {
+               // Note: For 'physical' superscalar architectures it
+               // is advised that the following loop be: 4xPD1 and 1xPD2
+               #ifdef exprtk_enable_superscalar
+               parse_digit_1(d)
+               parse_digit_1(d)
+               #endif
+               parse_digit_1(d)
+               parse_digit_1(d)
+               parse_digit_2(d)
+            }
+
+            if (curr != itr) instate = true;
+         }
+
+         int exponent = 0;
+
+         if (end != itr)
+         {
+            if ('.' == (*itr))
+            {
+               const Iterator curr = ++itr;
+               unsigned int digit;
+               T tmp_d = T(0);
+
+               while (end != itr)
+               {
+                  #ifdef exprtk_enable_superscalar
+                  parse_digit_1(tmp_d)
+                  parse_digit_1(tmp_d)
+                  parse_digit_1(tmp_d)
+                  #endif
+                  parse_digit_1(tmp_d)
+                  parse_digit_1(tmp_d)
+                  parse_digit_2(tmp_d)
+               }
+
+               if (curr != itr)
+               {
+                  instate = true;
+                  d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
+               }
+
+               #undef parse_digit_1
+               #undef parse_digit_2
+            }
+
+            if (end != itr)
+            {
+               typename std::iterator_traits<Iterator>::value_type c = (*itr);
+
+               if (('e' == c) || ('E' == c))
+               {
+                  int exp = 0;
+
+                  if (!details::string_to_type_converter_impl_ref(++itr,end,exp))
+                  {
+                     if (end == itr)
+                        return false;
+                     else
+                        c = (*itr);
+                  }
+
+                  exponent += exp;
+               }
+
+               if (end != itr)
+               {
+                  if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
+                     ++itr;
+                  else if ('#' == c)
+                  {
+                     if (end == ++itr)
+                        return false;
+                     else if (('I' <= (*itr)) && ((*itr) <= 'n'))
+                     {
+                        if (('i' == (*itr)) || ('I' == (*itr)))
+                        {
+                           return parse_inf(itr,end,t,negative);
+                        }
+                        else if (('n' == (*itr)) || ('N' == (*itr)))
+                        {
+                           return parse_nan(itr,end,t);
+                        }
+                        else
+                           return false;
+                     }
+                     else
+                        return false;
+                  }
+                  else if (('I' <= (*itr)) && ((*itr) <= 'n'))
+                  {
+                     if (('i' == (*itr)) || ('I' == (*itr)))
+                     {
+                        return parse_inf(itr,end,t,negative);
+                     }
+                     else if (('n' == (*itr)) || ('N' == (*itr)))
+                     {
+                        return parse_nan(itr,end,t);
+                     }
+                     else
+                        return false;
+                  }
+                  else
+                     return false;
+               }
+            }
+         }
+
+         if ((end != itr) || (!instate))
+            return false;
+         else if (exponent)
+            d = compute_pow10(d,exponent);
+
+         t = static_cast<T>((negative) ? -d : d);
+         return true;
+      }
+
+      template <typename T>
+      inline bool string_to_real(const std::string& s, T& t)
+      {
+         const char* begin = s.data();
+         const char* end   = s.data() + s.size();
+         typename numeric::details::number_type<T>::type num_type;
+         return string_to_real(begin,end,t,num_type);
+      }
+
+      template <typename T>
+      struct functor_t
+      {
+         /*
+            Note: The following definitions for Type, may require tweaking
+                  based on the compiler and target architecture. The benchmark
+                  should provide enough information to make the right choice.
+         */
+         //typedef T Type;
+         //typedef const T Type;
+         typedef const T& Type;
+         typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
+         typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
+         typedef T (*bfunc_t)(Type t0, Type t1);
+         typedef T (*ufunc_t)(Type t0);
+      };
+
+   } // namespace details
+
+   namespace lexer
+   {
+      struct token
+      {
+         enum token_type
+         {
+            e_none        =   0, e_error       =   1, e_err_symbol  =   2,
+            e_err_number  =   3, e_err_string  =   4, e_err_sfunc   =   5,
+            e_eof         =   6, e_number      =   7, e_symbol      =   8,
+            e_string      =   9, e_assign      =  10, e_addass      =  11,
+            e_subass      =  12, e_mulass      =  13, e_divass      =  14,
+            e_modass      =  15, e_shr         =  16, e_shl         =  17,
+            e_lte         =  18, e_ne          =  19, e_gte         =  20,
+            e_swap        =  21, e_lt          = '<', e_gt          = '>',
+            e_eq          = '=', e_rbracket    = ')', e_lbracket    = '(',
+            e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}',
+            e_lcrlbracket = '{', e_comma       = ',', e_add         = '+',
+            e_sub         = '-', e_div         = '/', e_mul         = '*',
+            e_mod         = '%', e_pow         = '^', e_colon       = ':',
+            e_ternary     = '?'
+         };
+
+         token()
+         : type(e_none),
+           value(""),
+           position(std::numeric_limits<std::size_t>::max())
+         {}
+
+         void clear()
+         {
+            type     = e_none;
+            value    = "";
+            position = std::numeric_limits<std::size_t>::max();
+         }
+
+         template <typename Iterator>
+         inline token& set_operator(const token_type tt, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+         {
+            type = tt;
+            value.assign(begin,end);
+            if (base_begin)
+               position = std::distance(base_begin,begin);
+            return *this;
+         }
+
+         template <typename Iterator>
+         inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+         {
+            type = e_symbol;
+            value.assign(begin,end);
+            if (base_begin)
+               position = std::distance(base_begin,begin);
+            return *this;
+         }
+
+         template <typename Iterator>
+         inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+         {
+            type = e_number;
+            value.assign(begin,end);
+            if (base_begin)
+               position = std::distance(base_begin,begin);
+            return *this;
+         }
+
+         template <typename Iterator>
+         inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+         {
+            type = e_string;
+            value.assign(begin,end);
+            if (base_begin)
+               position = std::distance(base_begin,begin);
+            return *this;
+         }
+
+         inline token& set_string(const std::string& s, const std::size_t p)
+         {
+            type     = e_string;
+            value    = s;
+            position = p;
+            return *this;
+         }
+
+         template <typename Iterator>
+         inline token& set_error(const token_type et, const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
+         {
+            if (
+                 (e_error      == et) ||
+                 (e_err_symbol == et) ||
+                 (e_err_number == et) ||
+                 (e_err_string == et) ||
+                 (e_err_sfunc  == et)
+               )
+            {
+               type = et;
+            }
+            else
+               type = e_error;
+
+            value.assign(begin,end);
+
+            if (base_begin)
+               position = std::distance(base_begin,begin);
+
+            return *this;
+         }
+
+         static inline std::string to_str(token_type t)
+         {
+            switch (t)
+            {
+               case e_none        : return "NONE";
+               case e_error       : return "ERROR";
+               case e_err_symbol  : return "ERROR_SYMBOL";
+               case e_err_number  : return "ERROR_NUMBER";
+               case e_err_string  : return "ERROR_STRING";
+               case e_eof         : return "EOF";
+               case e_number      : return "NUMBER";
+               case e_symbol      : return "SYMBOL";
+               case e_string      : return "STRING";
+               case e_assign      : return ":=";
+               case e_addass      : return "+=";
+               case e_subass      : return "-=";
+               case e_mulass      : return "*=";
+               case e_divass      : return "/=";
+               case e_modass      : return "%=";
+               case e_shr         : return ">>";
+               case e_shl         : return "<<";
+               case e_lte         : return "<=";
+               case e_ne          : return "!=";
+               case e_gte         : return ">=";
+               case e_lt          : return "<";
+               case e_gt          : return ">";
+               case e_eq          : return "=";
+               case e_rbracket    : return ")";
+               case e_lbracket    : return "(";
+               case e_rsqrbracket : return "]";
+               case e_lsqrbracket : return "[";
+               case e_rcrlbracket : return "}";
+               case e_lcrlbracket : return "{";
+               case e_comma       : return ",";
+               case e_add         : return "+";
+               case e_sub         : return "-";
+               case e_div         : return "/";
+               case e_mul         : return "*";
+               case e_mod         : return "%";
+               case e_pow         : return "^";
+               case e_colon       : return ":";
+               case e_ternary     : return "?";
+               case e_swap        : return "<=>";
+               default            : return "UNKNOWN";
+            }
+         }
+
+         inline bool is_error() const
+         {
+            return (
+                     (e_error      == type) ||
+                     (e_err_symbol == type) ||
+                     (e_err_number == type) ||
+                     (e_err_string == type) ||
+                     (e_err_sfunc  == type)
+                   );
+         }
+
+         token_type type;
+         std::string value;
+         std::size_t position;
+      };
+
+      class generator
+      {
+      public:
+
+         typedef token token_t;
+         typedef std::vector<token_t> token_list_t;
+         typedef std::vector<token_t>::iterator token_list_itr_t;
+
+         generator()
+         : base_itr_(0),
+           s_itr_   (0),
+           s_end_   (0)
+         {
+            clear();
+         }
+
+         inline void clear()
+         {
+            base_itr_ = 0;
+            s_itr_    = 0;
+            s_end_    = 0;
+            token_list_.clear();
+            token_itr_ = token_list_.end();
+            store_token_itr_ = token_list_.end();
+         }
+
+         inline bool process(const std::string& str)
+         {
+            base_itr_ = str.data();
+            s_itr_    = str.data();
+            s_end_    = str.data() + str.size();
+
+            eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_);
+            token_list_.clear();
+
+            while (!is_end(s_itr_))
+            {
+               scan_token();
+
+               if (token_list_.empty())
+                  return true;
+               else if (token_list_.back().is_error())
+               {
+                  return false;
+               }
+            }
+
+            return true;
+         }
+
+         inline bool empty() const
+         {
+            return token_list_.empty();
+         }
+
+         inline std::size_t size() const
+         {
+            return token_list_.size();
+         }
+
+         inline void begin()
+         {
+            token_itr_ = token_list_.begin();
+            store_token_itr_ = token_list_.begin();
+         }
+
+         inline void store()
+         {
+            store_token_itr_ = token_itr_;
+         }
+
+         inline void restore()
+         {
+            token_itr_ = store_token_itr_;
+         }
+
+         inline token_t& next_token()
+         {
+            if (token_list_.end() != token_itr_)
+            {
+               return *token_itr_++;
+            }
+            else
+               return eof_token_;
+         }
+
+         inline token_t& peek_next_token()
+         {
+            if (token_list_.end() != token_itr_)
+            {
+               return *token_itr_;
+            }
+            else
+               return eof_token_;
+         }
+
+         inline token_t& operator[](const std::size_t& index)
+         {
+            if (index < token_list_.size())
+               return token_list_[index];
+            else
+               return eof_token_;
+         }
+
+         inline token_t operator[](const std::size_t& index) const
+         {
+            if (index < token_list_.size())
+               return token_list_[index];
+            else
+               return eof_token_;
+         }
+
+         inline bool finished() const
+         {
+            return (token_list_.end() == token_itr_);
+         }
+
+         inline void insert_front(token_t::token_type tk_type)
+         {
+            if (
+                 !token_list_.empty() &&
+                 (token_list_.end() != token_itr_)
+               )
+            {
+               token_t t = *token_itr_;
+
+               t.type     = tk_type;
+               token_itr_ = token_list_.insert(token_itr_,t);
+            }
+         }
+
+         inline std::string substr(const std::size_t& begin, const std::size_t& end)
+         {
+            const char* begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
+            const char* end_itr   = ((base_itr_ +   end) < s_end_) ? (base_itr_ +   end) : s_end_;
+            return std::string(begin_itr,end_itr);
+         }
+
+         inline std::string remaining() const
+         {
+            if (finished())
+               return "";
+            else if (token_list_.begin() != token_itr_)
+               return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_);
+            else
+               return std::string(base_itr_ + token_itr_->position,s_end_);
+         }
+
+      private:
+
+         inline bool is_end(const char* itr)
+         {
+            return (s_end_ == itr);
+         }
+
+         inline void skip_whitespace()
+         {
+            while (!is_end(s_itr_) && details::is_whitespace(*s_itr_))
+            {
+               ++s_itr_;
+            }
+         }
+
+         inline void skip_comments()
+         {
+            #ifndef exprtk_disable_comments
+            // The following comment styles are supported:
+            // 1. // .... \n
+            // 2. #  .... \n
+            // 3. /* .... */
+            struct test
+            {
+               static inline bool comment_start(const char c0, const char c1, int& mode, int& incr)
+               {
+                  mode = 0;
+                       if ('#' == c0)    { mode = 1; incr = 1; }
+                  else if ('/' == c0)
+                  {
+                          if ('/' == c1) { mode = 1; incr = 2; }
+                     else if ('*' == c1) { mode = 2; incr = 2; }
+                  }
+                  return (0 != mode);
+               }
+
+               static inline bool comment_end(const char c0, const char c1, const int mode)
+               {
+                  return (
+                           ((1 == mode) && ('\n' == c0)) ||
+                           ((2 == mode) && ( '*' == c0) && ('/' == c1))
+                         );
+               }
+            };
+
+            int mode = 0;
+            int increment = 0;
+
+            if (is_end(s_itr_) || is_end((s_itr_ + 1)))
+               return;
+            else if (!test::comment_start(*s_itr_,*(s_itr_ + 1),mode,increment))
+               return;
+
+            s_itr_ += increment;
+
+            while (!is_end(s_itr_) && !test::comment_end(*s_itr_,*(s_itr_ + 1),mode))
+            {
+               ++s_itr_;
+            }
+
+            if (!is_end(s_itr_))
+            {
+               s_itr_ += mode;
+               skip_whitespace();
+               skip_comments();
+            }
+            #endif
+         }
+
+         inline void scan_token()
+         {
+            skip_whitespace();
+            skip_comments();
+            if (is_end(s_itr_))
+            {
+               return;
+            }
+            else if (details::is_operator_char(*s_itr_))
+            {
+               scan_operator();
+               return;
+            }
+            else if (details::is_letter(*s_itr_))
+            {
+               scan_symbol();
+               return;
+            }
+            else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
+            {
+               scan_number();
+               return;
+            }
+            else if ('$' == (*s_itr_))
+            {
+               scan_special_function();
+               return;
+            }
+            #ifndef exprtk_disable_string_capabilities
+            else if ('\'' == (*s_itr_))
+            {
+               scan_string();
+               return;
+            }
+            #endif
+            else if ('~' == (*s_itr_))
+            {
+               token_t t;
+               t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
+               token_list_.push_back(t);
+               ++s_itr_;
+               return;
+            }
+            else
+            {
+               token_t t;
+               t.set_error(token::e_error,s_itr_,s_itr_ + 2,base_itr_);
+               token_list_.push_back(t);
+               ++s_itr_;
+            }
+         }
+
+         inline void scan_operator()
+         {
+            token_t t;
+
+            const char c0 = s_itr_[0];
+
+            if (!is_end(s_itr_ + 1))
+            {
+               const char c1 = s_itr_[1];
+
+               if (!is_end(s_itr_ + 2))
+               {
+                  const char c2 = s_itr_[2];
+
+                  if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
+                  {
+                     t.set_operator(token_t::e_swap,s_itr_,s_itr_ + 3,base_itr_);
+                     token_list_.push_back(t);
+                     s_itr_ += 3;
+                     return;
+                  }
+               }
+
+               token_t::token_type ttype = token_t::e_none;
+
+                    if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
+               else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
+               else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
+               else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
+               else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
+               else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
+               else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
+               else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
+               else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
+               else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
+               else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
+               else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
+               else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
+
+               if (token_t::e_none != ttype)
+               {
+                  t.set_operator(ttype,s_itr_,s_itr_ + 2,base_itr_);
+                  token_list_.push_back(t);
+                  s_itr_ += 2;
+                  return;
+               }
+            }
+
+            if ('<' == c0)
+               t.set_operator(token_t::e_lt ,s_itr_,s_itr_ + 1,base_itr_);
+            else if ('>' == c0)
+               t.set_operator(token_t::e_gt ,s_itr_,s_itr_ + 1,base_itr_);
+            else if (';' == c0)
+               t.set_operator(token_t::e_eof,s_itr_,s_itr_ + 1,base_itr_);
+            else if ('&' == c0)
+               t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
+            else if ('|' == c0)
+               t.set_symbol(s_itr_,s_itr_ + 1,base_itr_);
+            else
+               t.set_operator(token_t::token_type(c0),s_itr_,s_itr_ + 1,base_itr_);
+
+            token_list_.push_back(t);
+            ++s_itr_;
+         }
+
+         inline void scan_symbol()
+         {
+            const char* initial_itr = s_itr_;
+
+            while (
+                    (!is_end(s_itr_)) &&
+                    (details::is_letter_or_digit(*s_itr_) || ((*s_itr_) == '_'))
+                  )
+            {
+               ++s_itr_;
+            }
+
+            token_t t;
+            t.set_symbol(initial_itr,s_itr_,base_itr_);
+            token_list_.push_back(t);
+         }
+
+         inline void scan_number()
+         {
+            /*
+               Attempt to match a valid numeric value in one of the following formats:
+               1. 123456
+               2. 123.456
+               3. 123.456e3
+               4. 123.456E3
+               5. 123.456e+3
+               6. 123.456E+3
+               7. 123.456e-3
+               8. 123.456E-3
+            */
+            const char* initial_itr = s_itr_;
+            bool dot_found          = false;
+            bool e_found            = false;
+            bool post_e_sign_found  = false;
+            bool post_e_digit_found = false;
+            token_t t;
+
+            while (!is_end(s_itr_))
+            {
+               if ('.' == (*s_itr_))
+               {
+                  if (dot_found)
+                  {
+                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                     token_list_.push_back(t);
+                     return;
+                  }
+
+                  dot_found = true;
+                  ++s_itr_;
+
+                  continue;
+               }
+               else if (details::imatch('e',(*s_itr_)))
+               {
+                  const char& c = *(s_itr_ + 1);
+
+                  if (is_end(s_itr_ + 1))
+                  {
+                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                     token_list_.push_back(t);
+
+                     return;
+                  }
+                  else if (
+                            ('+' != c) &&
+                            ('-' != c) &&
+                            !details::is_digit(c)
+                          )
+                  {
+                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                     token_list_.push_back(t);
+
+                     return;
+                  }
+
+                  e_found = true;
+                  ++s_itr_;
+
+                  continue;
+               }
+               else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
+               {
+                  if (post_e_sign_found)
+                  {
+                     t.set_error(token::e_err_number,initial_itr,s_itr_,base_itr_);
+                     token_list_.push_back(t);
+
+                     return;
+                  }
+
+                  post_e_sign_found = true;
+                  ++s_itr_;
+
+                  continue;
+               }
+               else if (e_found && details::is_digit(*s_itr_))
+               {
+                  post_e_digit_found = true;
+                  ++s_itr_;
+
+                  continue;
+               }
+               else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
+                  break;
+               else
+                  ++s_itr_;
+            }
+
+            t.set_numeric(initial_itr,s_itr_,base_itr_);
+            token_list_.push_back(t);
+
+            return;
+         }
+
+         inline void scan_special_function()
+         {
+            const char* initial_itr = s_itr_;
+            token_t t;
+
+            // $fdd(x,x,x) = at least 11 chars
+            if (std::distance(s_itr_,s_end_) < 11)
+            {
+               t.set_error(token::e_err_sfunc,initial_itr,s_itr_,base_itr_);
+               token_list_.push_back(t);
+
+               return;
+            }
+
+            if (
+                 !(('$' == *s_itr_)                       &&
+                   (details::imatch  ('f',*(s_itr_ + 1))) &&
+                   (details::is_digit(*(s_itr_ + 2)))     &&
+                   (details::is_digit(*(s_itr_ + 3))))
+               )
+            {
+               t.set_error(token::e_err_sfunc,initial_itr,s_itr_,base_itr_);
+               token_list_.push_back(t);
+
+               return;
+            }
+
+            s_itr_ += 4; // $fdd = 4chars
+
+            t.set_symbol(initial_itr,s_itr_,base_itr_);
+            token_list_.push_back(t);
+
+            return;
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline void scan_string()
+         {
+            const char* initial_itr = s_itr_ + 1;
+            token_t t;
+
+            if (std::distance(s_itr_,s_end_) < 2)
+            {
+               t.set_error(token::e_err_string,s_itr_,s_end_,base_itr_);
+               token_list_.push_back(t);
+               return;
+            }
+
+            ++s_itr_;
+
+            bool escaped_found = false;
+            bool escaped = false;
+
+            while (!is_end(s_itr_))
+            {
+               if (!escaped && ('\\' == *s_itr_))
+               {
+                  escaped_found = true;
+                  escaped = true;
+                  ++s_itr_;
+
+                  continue;
+               }
+               else if (!escaped)
+               {
+                  if ('\'' == *s_itr_)
+                     break;
+               }
+               else if (escaped)
+               {
+                  if (!is_end(s_itr_) && ('0' == *(s_itr_)))
+                  {
+                     /*
+                        Note: The following 'awkward' conditional is
+                              due to various broken msvc compilers.
+                     */
+                     #if _MSC_VER == 1600
+                     const bool within_range = !is_end(s_itr_ + 2) &&
+                                               !is_end(s_itr_ + 3) ;
+                     #else
+                     const bool within_range = !is_end(s_itr_ + 1) &&
+                                               !is_end(s_itr_ + 2) &&
+                                               !is_end(s_itr_ + 3) ;
+                     #endif
+
+                     const bool x_seperator  = ('x' == *(s_itr_ + 1)) ||
+                                               ('X' == *(s_itr_ + 1)) ;
+
+                     const bool both_digits  = details::is_hex_digit(*(s_itr_ + 2)) &&
+                                               details::is_hex_digit(*(s_itr_ + 3)) ;
+
+                     if (!within_range || !x_seperator || !both_digits)
+                     {
+                        t.set_error(token::e_err_string,initial_itr,s_itr_,base_itr_);
+                        token_list_.push_back(t);
+
+                        return;
+                     }
+                     else
+                        s_itr_ += 3;
+                  }
+
+                  escaped = false;
+               }
+
+               ++s_itr_;
+            }
+
+            if (is_end(s_itr_))
+            {
+               t.set_error(token::e_err_string,initial_itr,s_itr_,base_itr_);
+               token_list_.push_back(t);
+
+               return;
+            }
+
+            if (!escaped_found)
+               t.set_string(initial_itr,s_itr_,base_itr_);
+            else
+            {
+               std::string parsed_string(initial_itr,s_itr_);
+               details::cleanup_escapes(parsed_string);
+               t.set_string(parsed_string, std::distance(base_itr_,initial_itr));
+            }
+
+            token_list_.push_back(t);
+            ++s_itr_;
+
+            return;
+         }
+         #endif
+
+      private:
+
+         token_list_t     token_list_;
+         token_list_itr_t token_itr_;
+         token_list_itr_t store_token_itr_;
+         token_t eof_token_;
+         const char* base_itr_;
+         const char* s_itr_;
+         const char* s_end_;
+
+         friend class token_scanner;
+         friend class token_modifier;
+         friend class token_inserter;
+         friend class token_joiner;
+      };
+
+      class helper_interface
+      {
+      public:
+
+         virtual void init()                     {              }
+         virtual void reset()                    {              }
+         virtual bool result()                   { return true; }
+         virtual std::size_t process(generator&) { return 0;    }
+         virtual ~helper_interface()             {              }
+      };
+
+      class token_scanner : public helper_interface
+      {
+      public:
+
+         virtual ~token_scanner()
+         {}
+
+         explicit token_scanner(const std::size_t& stride)
+         : stride_(stride)
+         {
+            if (stride > 4)
+            {
+               throw std::invalid_argument("token_scanner() - Invalid stride value");
+            }
+         }
+
+         inline std::size_t process(generator& g)
+         {
+            if (g.token_list_.size() >= stride_)
+            {
+               for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
+               {
+                  token t;
+
+                  switch (stride_)
+                  {
+                     case 1 :
+                              {
+                                 const token& t0 = g.token_list_[i];
+
+                                 if (!operator()(t0))
+                                 {
+                                    return i;
+                                 }
+                              }
+                              break;
+
+                     case 2 :
+                              {
+                                 const token& t0 = g.token_list_[i    ];
+                                 const token& t1 = g.token_list_[i + 1];
+
+                                 if (!operator()(t0,t1))
+                                 {
+                                    return i;
+                                 }
+                              }
+                              break;
+
+                     case 3 :
+                              {
+                                 const token& t0 = g.token_list_[i    ];
+                                 const token& t1 = g.token_list_[i + 1];
+                                 const token& t2 = g.token_list_[i + 2];
+
+                                 if (!operator()(t0,t1,t2))
+                                 {
+                                    return i;
+                                 }
+                              }
+                              break;
+
+                     case 4 :
+                              {
+                                 const token& t0 = g.token_list_[i    ];
+                                 const token& t1 = g.token_list_[i + 1];
+                                 const token& t2 = g.token_list_[i + 2];
+                                 const token& t3 = g.token_list_[i + 3];
+
+                                 if (!operator()(t0,t1,t2,t3))
+                                 {
+                                    return i;
+                                 }
+                              }
+                              break;
+                  }
+               }
+            }
+
+            return (g.token_list_.size() - stride_ + 1);
+         }
+
+         virtual bool operator()(const token&)
+         {
+            return false;
+         }
+
+         virtual bool operator()(const token&, const token&)
+         {
+            return false;
+         }
+
+         virtual bool operator()(const token&, const token&, const token&)
+         {
+            return false;
+         }
+
+         virtual bool operator()(const token&, const token&, const token&, const token&)
+         {
+            return false;
+         }
+
+      private:
+
+         std::size_t stride_;
+      };
+
+      class token_modifier : public helper_interface
+      {
+      public:
+
+         inline std::size_t process(generator& g)
+         {
+            std::size_t changes = 0;
+
+            for (std::size_t i = 0; i < g.token_list_.size(); ++i)
+            {
+               if (modify(g.token_list_[i])) changes++;
+            }
+
+            return changes;
+         }
+
+         virtual bool modify(token& t) = 0;
+      };
+
+      class token_inserter : public helper_interface
+      {
+      public:
+
+         explicit token_inserter(const std::size_t& stride)
+         : stride_(stride)
+         {
+            if (stride > 5)
+            {
+               throw std::invalid_argument("token_inserter() - Invalid stride value");
+            }
+         }
+
+         inline std::size_t process(generator& g)
+         {
+            if (g.token_list_.empty())
+               return 0;
+            else if (g.token_list_.size() < stride_)
+               return 0;
+
+            std::size_t changes = 0;
+
+            for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
+            {
+               int insert_index = -1;
+               token t;
+
+               switch (stride_)
+               {
+                  case 1 : insert_index = insert(g.token_list_[i],t);
+                           break;
+
+                  case 2 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],t);
+                           break;
+
+                  case 3 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t);
+                           break;
+
+                  case 4 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],t);
+                           break;
+
+                  case 5 : insert_index = insert(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],g.token_list_[i + 3],g.token_list_[i + 4],t);
+                           break;
+               }
+
+               if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
+               {
+                  g.token_list_.insert(g.token_list_.begin() + (i + insert_index),t);
+                  changes++;
+               }
+            }
+
+            return changes;
+         }
+
+         inline virtual int insert(const token&, token& )
+         {
+            return -1;
+         }
+
+         inline virtual int insert(const token&, const token&, token&)
+         {
+            return -1;
+         }
+
+         inline virtual int insert(const token&, const token&, const token&, token&)
+         {
+            return -1;
+         }
+
+         inline virtual int insert(const token&, const token&, const token&, const token&, token&)
+         {
+            return -1;
+         }
+
+         inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
+         {
+            return -1;
+         }
+
+      private:
+
+         std::size_t stride_;
+      };
+
+      class token_joiner : public helper_interface
+      {
+      public:
+
+         token_joiner(const std::size_t& stride)
+         : stride_(stride)
+         {}
+
+         inline std::size_t process(generator& g)
+         {
+            if (g.token_list_.empty())
+               return 0;
+
+            switch (stride_)
+            {
+               case 2  : return process_stride_2(g);
+               case 3  : return process_stride_3(g);
+               default : return 0;
+            }
+         }
+
+         virtual bool join(const token&, const token&, token&) { return false; }
+         virtual bool join(const token&, const token&, const token&, token&) { return false; }
+
+      private:
+
+         inline std::size_t process_stride_2(generator& g)
+         {
+            if (g.token_list_.size() < 2)
+               return 0;
+
+            std::size_t changes = 0;
+
+            for (std::size_t i = 0; i < g.token_list_.size() - 1; ++i)
+            {
+               token t;
+
+               while (join(g.token_list_[i],g.token_list_[i + 1],t))
+               {
+                  g.token_list_[i] = t;
+                  g.token_list_.erase(g.token_list_.begin() + (i + 1));
+                  ++changes;
+               }
+            }
+
+            return changes;
+         }
+
+         inline std::size_t process_stride_3(generator& g)
+         {
+            if (g.token_list_.size() < 3)
+               return 0;
+
+            std::size_t changes = 0;
+
+            for (std::size_t i = 0; i < g.token_list_.size() - 2; ++i)
+            {
+               token t;
+
+               while (join(g.token_list_[i],g.token_list_[i + 1],g.token_list_[i + 2],t))
+               {
+                  g.token_list_[i] = t;
+                  g.token_list_.erase(g.token_list_.begin() + (i + 1),
+                                      g.token_list_.begin() + (i + 3));
+                  ++changes;
+               }
+            }
+
+            return changes;
+         }
+
+         std::size_t stride_;
+      };
+
+      namespace helper
+      {
+
+         inline void dump(lexer::generator& generator)
+         {
+            for (std::size_t i = 0; i < generator.size(); ++i)
+            {
+               lexer::token t = generator[i];
+               printf("Token[%02d] @ %03d  %6s  -->  '%s'\n",
+                      static_cast<int>(i),
+                      static_cast<int>(t.position),
+                      t.to_str(t.type).c_str(),
+                      t.value.c_str());
+            }
+         }
+
+         class commutative_inserter : public lexer::token_inserter
+         {
+         public:
+
+            commutative_inserter()
+            : lexer::token_inserter(2)
+            {}
+
+            inline void ignore_symbol(const std::string& symbol)
+            {
+               ignore_set_.insert(symbol);
+            }
+
+            inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
+            {
+               bool match         = false;
+               new_token.type     = lexer::token::e_mul;
+               new_token.value    = "*";
+               new_token.position = t1.position;
+
+               if (t0.type == lexer::token::e_symbol)
+               {
+                  if (ignore_set_.end() != ignore_set_.find(t0.value))
+                  {
+                     return -1;
+                  }
+                  else if (!t0.value.empty() && ('$' == t0.value[0]))
+                  {
+                     return -1;
+                  }
+               }
+
+               if (t1.type == lexer::token::e_symbol)
+               {
+                  if (ignore_set_.end() != ignore_set_.find(t1.value))
+                  {
+                     return -1;
+                  }
+               }
+                    if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_symbol     )) match = true;
+               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lbracket   )) match = true;
+               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
+               else if ((t0.type == lexer::token::e_number     ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
+               else if ((t0.type == lexer::token::e_symbol     ) && (t1.type == lexer::token::e_number     )) match = true;
+               else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_number     )) match = true;
+               else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number     )) match = true;
+               else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number     )) match = true;
+               else if ((t0.type == lexer::token::e_rbracket   ) && (t1.type == lexer::token::e_symbol     )) match = true;
+               else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
+               else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol     )) match = true;
+
+               return (match) ? 1 : -1;
+            }
+
+         private:
+
+            std::set<std::string,details::ilesscompare> ignore_set_;
+         };
+
+         class operator_joiner : public token_joiner
+         {
+         public:
+
+            operator_joiner(const std::size_t& stride)
+            : token_joiner(stride)
+            {}
+
+            inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
+            {
+               // ': =' --> ':='
+               if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_assign;
+                  t.value    = ":=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '+ =' --> '+='
+               else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_addass;
+                  t.value    = "+=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '- =' --> '-='
+               else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_subass;
+                  t.value    = "-=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '* =' --> '*='
+               else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_mulass;
+                  t.value    = "*=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '/ =' --> '/='
+               else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_divass;
+                  t.value    = "/=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '% =' --> '%='
+               else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_modass;
+                  t.value    = "%=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '> =' --> '>='
+               else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_gte;
+                  t.value    = ">=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '< =' --> '<='
+               else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_lte;
+                  t.value    = "<=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '= =' --> '=='
+               else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_eq;
+                  t.value    = "==";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '! =' --> '!='
+               else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
+               {
+                  t.type     = lexer::token::e_ne;
+                  t.value    = "!=";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '< >' --> '<>'
+               else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
+               {
+                  t.type     = lexer::token::e_ne;
+                  t.value    = "<>";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '<= >' --> '<=>'
+               else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
+               {
+                  t.type     = lexer::token::e_swap;
+                  t.value    = "<=>";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '+ -' --> '-'
+               else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
+               {
+                  t.type     = lexer::token::e_sub;
+                  t.value    = "-";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '- +' --> '-'
+               else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
+               {
+                  t.type     = lexer::token::e_sub;
+                  t.value    = "-";
+                  t.position = t0.position;
+                  return true;
+               }
+               // '- -' --> '-'
+               else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
+               {
+                  /*
+                     Note: May need to reconsider this when wanting to implement
+                     pre/postfix decrement operator
+                  */
+                  t.type     = lexer::token::e_add;
+                  t.value    = "+";
+                  t.position = t0.position;
+                  return true;
+               }
+               else
+                  return false;
+            }
+
+            inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
+            {
+               // '[ * ]' --> '[*]'
+               if (
+                    (t0.type == lexer::token::e_lsqrbracket) &&
+                    (t1.type == lexer::token::e_mul        ) &&
+                    (t2.type == lexer::token::e_rsqrbracket)
+                  )
+               {
+                  t.type     = lexer::token::e_symbol;
+                  t.value    = "[*]";
+                  t.position = t0.position;
+
+                  return true;
+               }
+               else
+                  return false;
+            }
+         };
+
+         class bracket_checker : public lexer::token_scanner
+         {
+         public:
+
+            bracket_checker()
+            : token_scanner(1),
+              state_(true)
+            {}
+
+            bool result()
+            {
+               if (!stack_.empty())
+               {
+                  lexer::token t;
+                  t.value      = stack_.top().first;
+                  t.position   = stack_.top().second;
+                  error_token_ = t;
+                  state_       = false;
+
+                  return false;
+               }
+               else
+                  return state_;
+            }
+
+            lexer::token error_token()
+            {
+               return error_token_;
+            }
+
+            void reset()
+            {
+               // Why? because msvc doesn't support swap properly.
+               stack_ = std::stack<std::pair<char,std::size_t> >();
+               state_ = true;
+               error_token_.clear();
+            }
+
+            bool operator()(const lexer::token& t)
+            {
+               if (
+                    !t.value.empty()                       &&
+                    (lexer::token::e_string != t.type)     &&
+                    (lexer::token::e_symbol != t.type)     &&
+                    exprtk::details::is_bracket(t.value[0])
+                  )
+               {
+                  char c = t.value[0];
+
+                       if (t.type == lexer::token::e_lbracket)    stack_.push(std::make_pair(')',t.position));
+                  else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
+                  else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
+                  else if (exprtk::details::is_right_bracket(c))
+                  {
+                     if (stack_.empty())
+                     {
+                        state_ = false;
+                        error_token_ = t;
+
+                        return false;
+                     }
+                     else if (c != stack_.top().first)
+                     {
+                        state_ = false;
+                        error_token_ = t;
+
+                        return false;
+                     }
+                     else
+                        stack_.pop();
+                  }
+               }
+
+               return true;
+            }
+
+         private:
+
+            bool state_;
+            std::stack<std::pair<char,std::size_t> > stack_;
+            lexer::token error_token_;
+         };
+
+         class numeric_checker : public lexer::token_scanner
+         {
+         public:
+
+            numeric_checker()
+            : token_scanner (1),
+              current_index_(0)
+            {}
+
+            bool result()
+            {
+               return error_list_.empty();
+            }
+
+            void reset()
+            {
+               error_list_.clear();
+               current_index_ = 0;
+            }
+
+            bool operator()(const lexer::token& t)
+            {
+               if (token::e_number == t.type)
+               {
+                  double v;
+
+                  if (!exprtk::details::string_to_real(t.value,v))
+                  {
+                     error_list_.push_back(current_index_);
+                  }
+               }
+
+               ++current_index_;
+
+               return true;
+            }
+
+            std::size_t error_count() const
+            {
+               return error_list_.size();
+            }
+
+            std::size_t error_index(const std::size_t& i)
+            {
+               if (i < error_list_.size())
+                  return error_list_[i];
+               else
+                  return std::numeric_limits<std::size_t>::max();
+            }
+
+            void clear_errors()
+            {
+               error_list_.clear();
+            }
+
+         private:
+
+            std::size_t current_index_;
+            std::vector<std::size_t> error_list_;
+         };
+
+         class symbol_replacer : public lexer::token_modifier
+         {
+         private:
+
+            typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
+
+         public:
+
+            bool remove(const std::string& target_symbol)
+            {
+               replace_map_t::iterator itr = replace_map_.find(target_symbol);
+
+               if (replace_map_.end() == itr)
+                  return false;
+
+               replace_map_.erase(itr);
+
+               return true;
+            }
+
+            bool add_replace(const std::string& target_symbol,
+                             const std::string& replace_symbol,
+                             const lexer::token::token_type token_type = lexer::token::e_symbol)
+            {
+               replace_map_t::iterator itr = replace_map_.find(target_symbol);
+
+               if (replace_map_.end() != itr)
+               {
+                  return false;
+               }
+
+               replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
+
+               return true;
+            }
+
+            void clear()
+            {
+               replace_map_.clear();
+            }
+
+         private:
+
+            bool modify(lexer::token& t)
+            {
+               if (lexer::token::e_symbol == t.type)
+               {
+                  if (replace_map_.empty())
+                     return false;
+
+                  replace_map_t::iterator itr = replace_map_.find(t.value);
+
+                  if (replace_map_.end() != itr)
+                  {
+                     t.value = itr->second.first;
+                     t.type  = itr->second.second;
+
+                     return true;
+                  }
+               }
+
+               return false;
+            }
+
+            replace_map_t replace_map_;
+         };
+
+         class sequence_validator : public lexer::token_scanner
+         {
+         private:
+
+            typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
+            typedef std::set<token_pair_t> set_t;
+
+         public:
+
+            sequence_validator()
+            : lexer::token_scanner(2)
+            {
+               add_invalid(lexer::token::e_number ,lexer::token::e_number );
+               add_invalid(lexer::token::e_string ,lexer::token::e_string );
+               add_invalid(lexer::token::e_number ,lexer::token::e_string );
+               add_invalid(lexer::token::e_string ,lexer::token::e_number );
+               add_invalid(lexer::token::e_string ,lexer::token::e_ternary);
+               add_invalid_set1(lexer::token::e_assign );
+               add_invalid_set1(lexer::token::e_shr    );
+               add_invalid_set1(lexer::token::e_shl    );
+               add_invalid_set1(lexer::token::e_lte    );
+               add_invalid_set1(lexer::token::e_ne     );
+               add_invalid_set1(lexer::token::e_gte    );
+               add_invalid_set1(lexer::token::e_lt     );
+               add_invalid_set1(lexer::token::e_gt     );
+               add_invalid_set1(lexer::token::e_eq     );
+               add_invalid_set1(lexer::token::e_comma  );
+               add_invalid_set1(lexer::token::e_add    );
+               add_invalid_set1(lexer::token::e_sub    );
+               add_invalid_set1(lexer::token::e_div    );
+               add_invalid_set1(lexer::token::e_mul    );
+               add_invalid_set1(lexer::token::e_mod    );
+               add_invalid_set1(lexer::token::e_pow    );
+               add_invalid_set1(lexer::token::e_colon  );
+               add_invalid_set1(lexer::token::e_ternary);
+            }
+
+            bool result()
+            {
+               return error_list_.empty();
+            }
+
+            bool operator()(const lexer::token& t0, const lexer::token& t1)
+            {
+               set_t::value_type p = std::make_pair(t0.type,t1.type);
+
+               if (invalid_bracket_check(t0.type,t1.type))
+               {
+                  error_list_.push_back(std::make_pair(t0,t1));
+               }
+               else if (invalid_comb_.find(p) != invalid_comb_.end())
+               {
+                  error_list_.push_back(std::make_pair(t0,t1));
+               }
+
+               return true;
+            }
+
+            std::size_t error_count()
+            {
+               return error_list_.size();
+            }
+
+            std::pair<lexer::token,lexer::token> error(const std::size_t index)
+            {
+               if (index < error_list_.size())
+               {
+                  return error_list_[index];
+               }
+               else
+               {
+                  static const lexer::token error_token;
+                  return std::make_pair(error_token,error_token);
+               }
+            }
+
+            void clear_errors()
+            {
+               error_list_.clear();
+            }
+
+         private:
+
+            void add_invalid(lexer::token::token_type base, lexer::token::token_type t)
+            {
+               invalid_comb_.insert(std::make_pair(base,t));
+            }
+
+            void add_invalid_set1(lexer::token::token_type t)
+            {
+               add_invalid(t,lexer::token::e_assign);
+               add_invalid(t,lexer::token::e_shr   );
+               add_invalid(t,lexer::token::e_shl   );
+               add_invalid(t,lexer::token::e_lte   );
+               add_invalid(t,lexer::token::e_ne    );
+               add_invalid(t,lexer::token::e_gte   );
+               add_invalid(t,lexer::token::e_lt    );
+               add_invalid(t,lexer::token::e_gt    );
+               add_invalid(t,lexer::token::e_eq    );
+               add_invalid(t,lexer::token::e_comma );
+               add_invalid(t,lexer::token::e_div   );
+               add_invalid(t,lexer::token::e_mul   );
+               add_invalid(t,lexer::token::e_mod   );
+               add_invalid(t,lexer::token::e_pow   );
+               add_invalid(t,lexer::token::e_colon );
+            }
+
+            bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t)
+            {
+               if (details::is_right_bracket(static_cast<char>(base)))
+               {
+                  switch (t)
+                  {
+                     case lexer::token::e_assign : return (']' != base);
+                     case lexer::token::e_string : return true;
+                     default                     : return false;
+                  }
+               }
+               else if (details::is_left_bracket(static_cast<char>(base)))
+               {
+                  if (details::is_right_bracket(static_cast<char>(t)))
+                     return false;
+                  else if (details::is_left_bracket(static_cast<char>(t)))
+                     return false;
+                  else
+                  {
+                     switch (t)
+                     {
+                        case lexer::token::e_number  : return false;
+                        case lexer::token::e_symbol  : return false;
+                        case lexer::token::e_string  : return false;
+                        case lexer::token::e_add     : return false;
+                        case lexer::token::e_sub     : return false;
+                        case lexer::token::e_colon   : return false;
+                        case lexer::token::e_ternary : return false;
+                        default                      : return true;
+                     }
+                  }
+               }
+               else if (details::is_right_bracket(static_cast<char>(t)))
+               {
+                  switch (base)
+                  {
+                     case lexer::token::e_number  : return false;
+                     case lexer::token::e_symbol  : return false;
+                     case lexer::token::e_string  : return false;
+                     case lexer::token::e_eof     : return false;
+                     case lexer::token::e_colon   : return false;
+                     case lexer::token::e_ternary : return false;
+                     default                      : return true;
+                  }
+               }
+               else if (details::is_left_bracket(static_cast<char>(t)))
+               {
+                  switch (base)
+                  {
+                     case lexer::token::e_rbracket    : return true;
+                     case lexer::token::e_rsqrbracket : return true;
+                     case lexer::token::e_rcrlbracket : return true;
+                     default                          : return false;
+                  }
+               }
+
+               return false;
+            }
+
+            set_t invalid_comb_;
+            std::vector<std::pair<lexer::token,lexer::token> > error_list_;
+         };
+
+         struct helper_assembly
+         {
+            inline bool register_scanner(lexer::token_scanner* scanner)
+            {
+               if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
+                                                         token_scanner_list.end(),
+                                                         scanner))
+               {
+                  return false;
+               }
+
+               token_scanner_list.push_back(scanner);
+               return true;
+            }
+
+            inline bool register_modifier(lexer::token_modifier* modifier)
+            {
+               if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
+                                                          token_modifier_list.end(),
+                                                          modifier))
+               {
+                  return false;
+               }
+
+               token_modifier_list.push_back(modifier);
+               return true;
+            }
+
+            inline bool register_joiner(lexer::token_joiner* joiner)
+            {
+               if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
+                                                        token_joiner_list.end(),
+                                                        joiner))
+               {
+                  return false;
+               }
+
+               token_joiner_list.push_back(joiner);
+               return true;
+            }
+
+            inline bool register_inserter(lexer::token_inserter* inserter)
+            {
+               if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
+                                                          token_inserter_list.end(),
+                                                          inserter))
+               {
+                  return false;
+               }
+
+               token_inserter_list.push_back(inserter);
+               return true;
+            }
+
+            inline bool run_modifiers(lexer::generator& g)
+            {
+               error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
+               bool result = true;
+
+               for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
+               {
+                  lexer::token_modifier& modifier = (*token_modifier_list[i]);
+
+                  modifier.reset();
+                  modifier.process(g);
+
+                  if (!modifier.result())
+                  {
+                     error_token_modifier = token_modifier_list[i];
+                     return false;
+                  }
+               }
+
+               return result;
+            }
+
+            inline bool run_joiners(lexer::generator& g)
+            {
+               error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
+               bool result = true;
+
+               for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
+               {
+                  lexer::token_joiner& joiner = (*token_joiner_list[i]);
+
+                  joiner.reset();
+                  joiner.process(g);
+
+                  if (!joiner.result())
+                  {
+                     error_token_joiner = token_joiner_list[i];
+                     return false;
+                  }
+               }
+
+               return result;
+            }
+
+            inline bool run_inserters(lexer::generator& g)
+            {
+               error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
+               bool result = true;
+
+               for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
+               {
+                  lexer::token_inserter& inserter = (*token_inserter_list[i]);
+
+                  inserter.reset();
+                  inserter.process(g);
+
+                  if (!inserter.result())
+                  {
+                     error_token_inserter = token_inserter_list[i];
+                     return false;
+                  }
+               }
+
+               return result;
+            }
+
+            inline bool run_scanners(lexer::generator& g)
+            {
+               error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
+               bool result = true;
+
+               for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
+               {
+                  lexer::token_scanner& scanner = (*token_scanner_list[i]);
+
+                  scanner.reset();
+                  scanner.process(g);
+
+                  if (!scanner.result())
+                  {
+                     error_token_scanner = token_scanner_list[i];
+                     return false;
+                  }
+               }
+
+               return result;
+            }
+
+            std::vector<lexer::token_scanner*>  token_scanner_list;
+            std::vector<lexer::token_modifier*> token_modifier_list;
+            std::vector<lexer::token_joiner*>   token_joiner_list;
+            std::vector<lexer::token_inserter*> token_inserter_list;
+
+            lexer::token_scanner*  error_token_scanner;
+            lexer::token_modifier* error_token_modifier;
+            lexer::token_joiner*   error_token_joiner;
+            lexer::token_inserter* error_token_inserter;
+         };
+      }
+
+      class parser_helper
+      {
+      public:
+
+         typedef token         token_t;
+         typedef generator generator_t;
+
+         inline bool init(const std::string& str)
+         {
+            if (!lexer_.process(str))
+            {
+               return false;
+            }
+
+            lexer_.begin();
+
+            next_token();
+
+            return true;
+         }
+
+         inline generator_t& lexer()
+         {
+            return lexer_;
+         }
+
+         inline const generator_t& lexer() const
+         {
+            return lexer_;
+         }
+
+         inline void store_token()
+         {
+            lexer_.store();
+            store_current_token_ = current_token_;
+         }
+
+         inline void restore_token()
+         {
+            lexer_.restore();
+            current_token_ = store_current_token_;
+         }
+
+         inline void next_token()
+         {
+            current_token_ = lexer_.next_token();
+         }
+
+         inline const token_t& current_token() const
+         {
+            return current_token_;
+         }
+
+         inline bool token_is(const token_t::token_type& ttype, const bool advance_token = true)
+         {
+            if (current_token().type != ttype)
+            {
+               return false;
+            }
+
+            if (advance_token)
+            {
+               next_token();
+            }
+
+            return true;
+         }
+
+         inline bool token_is(const token_t::token_type& ttype,
+                              const std::string& value,
+                              const bool advance_token = true)
+         {
+            if (
+                 (current_token().type != ttype) ||
+                 !exprtk::details::imatch(value,current_token().value)
+               )
+            {
+               return false;
+            }
+
+            if (advance_token)
+            {
+               next_token();
+            }
+
+            return true;
+         }
+
+         inline bool token_is_then_assign(const token_t::token_type& ttype,
+                                          std::string& token,
+                                          const bool advance_token = true)
+         {
+            if (current_token_.type != ttype)
+            {
+               return false;
+            }
+
+            token = current_token_.value;
+
+            if (advance_token)
+            {
+               next_token();
+            }
+
+            return true;
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Container>
+         inline bool token_is_then_assign(const token_t::token_type& ttype,
+                                          Container<std::string,Allocator>& token_list,
+                                          const bool advance_token = true)
+         {
+            if (current_token_.type != ttype)
+            {
+               return false;
+            }
+
+            token_list.push_back(current_token_.value);
+
+            if (advance_token)
+            {
+               next_token();
+            }
+
+            return true;
+         }
+
+         inline bool peek_token_is(const token_t::token_type& ttype)
+         {
+            return (lexer_.peek_next_token().type == ttype);
+         }
+
+         inline bool peek_token_is(const std::string& s)
+         {
+            return (exprtk::details::imatch(lexer_.peek_next_token().value,s));
+         }
+
+      private:
+
+         generator_t lexer_;
+         token_t     current_token_;
+         token_t     store_current_token_;
+      };
+   }
+
+   template <typename T> class results_context;
+
+   template <typename T>
+   struct type_store
+   {
+      enum store_type
+      {
+         e_unknown,
+         e_scalar,
+         e_vector,
+         e_string
+      };
+
+      type_store()
+      : size(0),
+        data(0),
+        type(e_unknown)
+      {}
+
+      std::size_t size;
+      void*       data;
+      store_type  type;
+
+      class parameter_list
+      {
+      public:
+
+         parameter_list(std::vector<type_store>& pl)
+         : parameter_list_(pl)
+         {}
+
+         inline bool empty() const
+         {
+            return parameter_list_.empty();
+         }
+
+         inline std::size_t size() const
+         {
+            return parameter_list_.size();
+         }
+
+         inline type_store& operator[](const std::size_t& index)
+         {
+            return parameter_list_[index];
+         }
+
+         inline const type_store& operator[](const std::size_t& index) const
+         {
+            return parameter_list_[index];
+         }
+
+         inline type_store& front()
+         {
+            return parameter_list_[0];
+         }
+
+         inline const type_store& front() const
+         {
+            return parameter_list_[0];
+         }
+
+         inline type_store& back()
+         {
+            return parameter_list_.back();
+         }
+
+         inline const type_store& back() const
+         {
+            return parameter_list_.back();
+         }
+
+      private:
+
+         std::vector<type_store>& parameter_list_;
+
+         friend class results_context<T>;
+      };
+
+      template <typename ViewType>
+      struct type_view
+      {
+         typedef type_store<T> type_store_t;
+         typedef ViewType      value_t;
+
+         type_view(type_store_t& ts)
+         : ts_(ts),
+           data_(reinterpret_cast<value_t*>(ts_.data))
+         {}
+
+         inline std::size_t size() const
+         {
+            return ts_.size;
+         }
+
+         inline value_t& operator[](const std::size_t& i)
+         {
+            return data_[i];
+         }
+
+         inline const value_t& operator[](const std::size_t& i) const
+         {
+            return data_[i];
+         }
+
+         inline const value_t* begin() const { return data_; }
+         inline       value_t* begin()       { return data_; }
+
+         inline const value_t* end() const
+         {
+            return static_cast<value_t*>(data_ + ts_.size);
+         }
+
+         inline value_t* end()
+         {
+            return static_cast<value_t*>(data_ + ts_.size);
+         }
+
+         type_store_t& ts_;
+         value_t* data_;
+      };
+
+      typedef type_view<T>    vector_view;
+      typedef type_view<char> string_view;
+
+      struct scalar_view
+      {
+         typedef type_store<T> type_store_t;
+         typedef T value_t;
+
+         scalar_view(type_store_t& ts)
+         : v_(*reinterpret_cast<value_t*>(ts.data))
+         {}
+
+         scalar_view(const type_store_t& ts)
+         : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
+         {}
+
+         value_t& operator()()
+         {
+            return v_;
+         }
+
+         const value_t& operator()() const
+         {
+            return v_;
+         }
+
+         T& v_;
+      };
+   };
+
+   template <typename StringView>
+   inline std::string to_str(const StringView& view)
+   {
+      return std::string(view.begin(),view.size());
+   }
+
+   namespace details
+   {
+      template <typename T> class return_node;
+      template <typename T> class return_envelope_node;
+   }
+
+   template <typename T>
+   class results_context
+   {
+   public:
+
+      typedef type_store<T> type_store_t;
+
+      results_context()
+      : results_available_(false)
+      {}
+
+      inline std::size_t count() const
+      {
+         if (results_available_)
+            return parameter_list_.size();
+         else
+            return 0;
+      }
+
+      inline type_store_t& operator[](const std::size_t& index)
+      {
+         return parameter_list_[index];
+      }
+
+      inline const type_store_t& operator[](const std::size_t& index) const
+      {
+         return parameter_list_[index];
+      }
+
+   private:
+
+      inline void clear()
+      {
+         results_available_ = false;
+      }
+
+      typedef std::vector<type_store_t> ts_list_t;
+      typedef typename type_store_t::parameter_list parameter_list_t;
+
+      inline void assign(const parameter_list_t& pl)
+      {
+         parameter_list_    = pl.parameter_list_;
+         results_available_ = true;
+      }
+
+      bool results_available_;
+      ts_list_t parameter_list_;
+
+      friend class details::return_node<T>;
+      friend class details::return_envelope_node<T>;
+   };
+
+   namespace details
+   {
+      enum operator_type
+      {
+         e_default , e_null    , e_add     , e_sub     ,
+         e_mul     , e_div     , e_mod     , e_pow     ,
+         e_atan2   , e_min     , e_max     , e_avg     ,
+         e_sum     , e_prod    , e_lt      , e_lte     ,
+         e_eq      , e_equal   , e_ne      , e_nequal  ,
+         e_gte     , e_gt      , e_and     , e_nand    ,
+         e_or      , e_nor     , e_xor     , e_xnor    ,
+         e_mand    , e_mor     , e_scand   , e_scor    ,
+         e_shr     , e_shl     , e_abs     , e_acos    ,
+         e_acosh   , e_asin    , e_asinh   , e_atan    ,
+         e_atanh   , e_ceil    , e_cos     , e_cosh    ,
+         e_exp     , e_expm1   , e_floor   , e_log     ,
+         e_log10   , e_log2    , e_log1p   , e_logn    ,
+         e_neg     , e_pos     , e_round   , e_roundn  ,
+         e_root    , e_sqrt    , e_sin     , e_sinc    ,
+         e_sinh    , e_sec     , e_csc     , e_tan     ,
+         e_tanh    , e_cot     , e_clamp   , e_iclamp  ,
+         e_inrange , e_sgn     , e_r2d     , e_d2r     ,
+         e_d2g     , e_g2d     , e_hypot   , e_notl    ,
+         e_erf     , e_erfc    , e_ncdf    , e_frac    ,
+         e_trunc   , e_assign  , e_addass  , e_subass  ,
+         e_mulass  , e_divass  , e_modass  , e_in      ,
+         e_like    , e_ilike   , e_multi   , e_swap    ,
+
+         // Do not add new functions/operators after this point.
+         e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
+         e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
+         e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
+         e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
+         e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
+         e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
+         e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
+         e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
+         e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
+         e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
+         e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
+         e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
+         e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
+         e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
+         e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
+         e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
+         e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
+         e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
+         e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
+         e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
+         e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
+         e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
+         e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
+         e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
+         e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
+         e_sffinal  = 1100,
+         e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
+         e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
+         e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
+         e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
+         e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
+         e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
+         e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
+         e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
+         e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
+         e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
+         e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
+         e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
+         e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
+         e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
+         e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
+         e_sf4ext60 = 2060
+      };
+
+      inline std::string to_str(const operator_type opr)
+      {
+         switch (opr)
+         {
+            case e_add    : return  "+";
+            case e_sub    : return  "-";
+            case e_mul    : return  "*";
+            case e_div    : return  "/";
+            case e_mod    : return  "%";
+            case e_pow    : return  "^";
+            case e_assign : return ":=";
+            case e_addass : return "+=";
+            case e_subass : return "-=";
+            case e_mulass : return "*=";
+            case e_divass : return "/=";
+            case e_modass : return "%=";
+            case e_lt     : return  "<";
+            case e_lte    : return "<=";
+            case e_eq     : return "==";
+            case e_equal  : return  "=";
+            case e_ne     : return "!=";
+            case e_nequal : return "<>";
+            case e_gte    : return ">=";
+            case e_gt     : return  ">";
+            default       : return"N/A";
+         }
+      }
+
+      struct base_operation_t
+      {
+         base_operation_t(const operator_type t, const unsigned int& np)
+         : type(t),
+           num_params(np)
+         {}
+
+         operator_type type;
+         unsigned int num_params;
+      };
+
+      namespace numeric
+      {
+         namespace details
+         {
+            template <typename T>
+            inline T process_impl(const operator_type operation, const T arg)
+            {
+               switch (operation)
+               {
+                  case e_abs   : return numeric::abs  (arg);
+                  case e_acos  : return numeric::acos (arg);
+                  case e_acosh : return numeric::acosh(arg);
+                  case e_asin  : return numeric::asin (arg);
+                  case e_asinh : return numeric::asinh(arg);
+                  case e_atan  : return numeric::atan (arg);
+                  case e_atanh : return numeric::atanh(arg);
+                  case e_ceil  : return numeric::ceil (arg);
+                  case e_cos   : return numeric::cos  (arg);
+                  case e_cosh  : return numeric::cosh (arg);
+                  case e_exp   : return numeric::exp  (arg);
+                  case e_expm1 : return numeric::expm1(arg);
+                  case e_floor : return numeric::floor(arg);
+                  case e_log   : return numeric::log  (arg);
+                  case e_log10 : return numeric::log10(arg);
+                  case e_log2  : return numeric::log2 (arg);
+                  case e_log1p : return numeric::log1p(arg);
+                  case e_neg   : return numeric::neg  (arg);
+                  case e_pos   : return numeric::pos  (arg);
+                  case e_round : return numeric::round(arg);
+                  case e_sin   : return numeric::sin  (arg);
+                  case e_sinc  : return numeric::sinc (arg);
+                  case e_sinh  : return numeric::sinh (arg);
+                  case e_sqrt  : return numeric::sqrt (arg);
+                  case e_tan   : return numeric::tan  (arg);
+                  case e_tanh  : return numeric::tanh (arg);
+                  case e_cot   : return numeric::cot  (arg);
+                  case e_sec   : return numeric::sec  (arg);
+                  case e_csc   : return numeric::csc  (arg);
+                  case e_r2d   : return numeric::r2d  (arg);
+                  case e_d2r   : return numeric::d2r  (arg);
+                  case e_d2g   : return numeric::d2g  (arg);
+                  case e_g2d   : return numeric::g2d  (arg);
+                  case e_notl  : return numeric::notl (arg);
+                  case e_sgn   : return numeric::sgn  (arg);
+                  case e_erf   : return numeric::erf  (arg);
+                  case e_erfc  : return numeric::erfc (arg);
+                  case e_ncdf  : return numeric::ncdf (arg);
+                  case e_frac  : return numeric::frac (arg);
+                  case e_trunc : return numeric::trunc(arg);
+                  default      : return std::numeric_limits<T>::quiet_NaN();
+               }
+            }
+
+            template <typename T>
+            inline T process_impl(const operator_type operation, const T arg0, const T arg1)
+            {
+               switch (operation)
+               {
+                  case e_add    : return (arg0 + arg1);
+                  case e_sub    : return (arg0 - arg1);
+                  case e_mul    : return (arg0 * arg1);
+                  case e_div    : return (arg0 / arg1);
+                  case e_mod    : return modulus<T>(arg0,arg1);
+                  case e_pow    : return pow<T>(arg0,arg1);
+                  case e_atan2  : return atan2<T>(arg0,arg1);
+                  case e_min    : return std::min<T>(arg0,arg1);
+                  case e_max    : return std::max<T>(arg0,arg1);
+                  case e_logn   : return logn<T>(arg0,arg1);
+                  case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
+                  case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
+                  case e_eq     : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
+                  case e_ne     : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
+                  case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
+                  case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
+                  case e_and    : return and_opr<T> (arg0,arg1);
+                  case e_nand   : return nand_opr<T>(arg0,arg1);
+                  case e_or     : return or_opr<T>  (arg0,arg1);
+                  case e_nor    : return nor_opr<T> (arg0,arg1);
+                  case e_xor    : return xor_opr<T> (arg0,arg1);
+                  case e_xnor   : return xnor_opr<T>(arg0,arg1);
+                  case e_root   : return root<T>    (arg0,arg1);
+                  case e_roundn : return roundn<T>  (arg0,arg1);
+                  case e_equal  : return equal<T>   (arg0,arg1);
+                  case e_nequal : return nequal<T>  (arg0,arg1);
+                  case e_hypot  : return hypot<T>   (arg0,arg1);
+                  case e_shr    : return shr<T>     (arg0,arg1);
+                  case e_shl    : return shl<T>     (arg0,arg1);
+                  default       : return std::numeric_limits<T>::quiet_NaN();
+               }
+            }
+
+            template <typename T>
+            inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
+            {
+               switch (operation)
+               {
+                  case e_add    : return (arg0 + arg1);
+                  case e_sub    : return (arg0 - arg1);
+                  case e_mul    : return (arg0 * arg1);
+                  case e_div    : return (arg0 / arg1);
+                  case e_mod    : return arg0 % arg1;
+                  case e_pow    : return pow<T>(arg0,arg1);
+                  case e_min    : return std::min<T>(arg0,arg1);
+                  case e_max    : return std::max<T>(arg0,arg1);
+                  case e_logn   : return logn<T>(arg0,arg1);
+                  case e_lt     : return (arg0 <  arg1) ? T(1) : T(0);
+                  case e_lte    : return (arg0 <= arg1) ? T(1) : T(0);
+                  case e_eq     : return (arg0 == arg1) ? T(1) : T(0);
+                  case e_ne     : return (arg0 != arg1) ? T(1) : T(0);
+                  case e_gte    : return (arg0 >= arg1) ? T(1) : T(0);
+                  case e_gt     : return (arg0 >  arg1) ? T(1) : T(0);
+                  case e_and    : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
+                  case e_nand   : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
+                  case e_or     : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
+                  case e_nor    : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
+                  case e_xor    : return arg0 ^ arg1;
+                  case e_xnor   : return !(arg0 ^ arg1);
+                  case e_root   : return root<T>(arg0,arg1);
+                  case e_equal  : return arg0 == arg1;
+                  case e_nequal : return arg0 != arg1;
+                  case e_hypot  : return hypot<T>(arg0,arg1);
+                  case e_shr    : return arg0 >> arg1;
+                  case e_shl    : return arg0 << arg1;
+                  default       : return std::numeric_limits<T>::quiet_NaN();
+               }
+            }
+         }
+
+         template <typename T>
+         inline T process(const operator_type operation, const T arg)
+         {
+            return exprtk::details::numeric::details::process_impl(operation,arg);
+         }
+
+         template <typename T>
+         inline T process(const operator_type operation, const T arg0, const T arg1)
+         {
+            return exprtk::details::numeric::details::process_impl(operation,arg0,arg1);
+         }
+      }
+
+      template <typename T>
+      class expression_node
+      {
+      public:
+
+         enum node_type
+         {
+            e_none         , e_null         , e_constant     , e_unary        ,
+            e_binary       , e_binary_ext   , e_trinary      , e_quaternary   ,
+            e_vararg       , e_conditional  , e_while        , e_repeat       ,
+            e_for          , e_switch       , e_mswitch      , e_return       ,
+            e_retenv       , e_variable     , e_stringvar    , e_stringconst  ,
+            e_stringvarrng , e_cstringvarrng, e_strgenrange  , e_strconcat    ,
+            e_stringvarsize, e_strswap      , e_stringsize   , e_function     ,
+            e_vafunction   , e_genfunction  , e_strfunction  , e_strcondition ,
+            e_strccondition, e_add          , e_sub          , e_mul          ,
+            e_div          , e_mod          , e_pow          , e_lt           ,
+            e_lte          , e_gt           , e_gte          , e_eq           ,
+            e_ne           , e_and          , e_nand         , e_or           ,
+            e_nor          , e_xor          , e_xnor         , e_in           ,
+            e_like         , e_ilike        , e_inranges     , e_ipow         ,
+            e_ipowinv      , e_abs          , e_acos         , e_acosh        ,
+            e_asin         , e_asinh        , e_atan         , e_atanh        ,
+            e_ceil         , e_cos          , e_cosh         , e_exp          ,
+            e_expm1        , e_floor        , e_log          , e_log10        ,
+            e_log2         , e_log1p        , e_neg          , e_pos          ,
+            e_round        , e_sin          , e_sinc         , e_sinh         ,
+            e_sqrt         , e_tan          , e_tanh         , e_cot          ,
+            e_sec          , e_csc          , e_r2d          , e_d2r          ,
+            e_d2g          , e_g2d          , e_notl         , e_sgn          ,
+            e_erf          , e_erfc         , e_ncdf         , e_frac         ,
+            e_trunc        , e_uvouv        , e_vov          , e_cov          ,
+            e_voc          , e_vob          , e_bov          , e_cob          ,
+            e_boc          , e_vovov        , e_vovoc        , e_vocov        ,
+            e_covov        , e_covoc        , e_vovovov      , e_vovovoc      ,
+            e_vovocov      , e_vocovov      , e_covovov      , e_covocov      ,
+            e_vocovoc      , e_covovoc      , e_vococov      , e_sf3ext       ,
+            e_sf4ext       , e_nulleq       , e_strass       , e_vector       ,
+            e_vecelem      , e_vecdefass    , e_vecvalass    , e_vecvecass    ,
+            e_vecopvalass  , e_vecopvecass  , e_vecfunc      , e_vecvecswap   ,
+            e_vecvecineq   , e_vecvalineq   , e_valvecineq   , e_vecvecarith  ,
+            e_vecvalarith  , e_valvecarith  , e_vecunaryop   , e_break        ,
+            e_continue     , e_swap
+         };
+
+         typedef T value_type;
+         typedef expression_node<T>* expression_ptr;
+
+         virtual ~expression_node()
+         {}
+
+         inline virtual T value() const
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
+         {
+            return reinterpret_cast<expression_ptr>(index * 0);
+         }
+
+         inline virtual node_type type() const
+         {
+            return e_none;
+         }
+      };
+
+      template <typename T>
+      inline bool is_generally_string_node(const expression_node<T>* node);
+
+      inline bool is_true(const double v)
+      {
+         return std::not_equal_to<double>()(0.0,v);
+      }
+
+      inline bool is_true(const long double v)
+      {
+         return std::not_equal_to<long double>()(0.0L,v);
+      }
+
+      inline bool is_true(const float v)
+      {
+         return std::not_equal_to<float>()(0.0f,v);
+      }
+
+      template <typename T>
+      inline bool is_true(const std::complex<T>& v)
+      {
+         return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
+      }
+
+      template <typename T>
+      inline bool is_true(const expression_node<T>* node)
+      {
+         return std::not_equal_to<T>()(T(0),node->value());
+      }
+
+      template <typename T>
+      inline bool is_false(const expression_node<T>* node)
+      {
+         return std::equal_to<T>()(T(0),node->value());
+      }
+
+      template <typename T>
+      inline bool is_unary_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_unary == node->type());
+      }
+
+      template <typename T>
+      inline bool is_neg_unary_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_neg == node->type());
+      }
+
+      template <typename T>
+      inline bool is_binary_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_binary == node->type());
+      }
+
+      template <typename T>
+      inline bool is_variable_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_variable == node->type());
+      }
+
+      template <typename T>
+      inline bool is_ivariable_node(const expression_node<T>* node)
+      {
+         return node &&
+                (
+                  details::expression_node<T>::e_variable == node->type() ||
+                  details::expression_node<T>::e_vecelem  == node->type()
+                );
+      }
+
+      template <typename T>
+      inline bool is_vector_elem_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_vecelem == node->type());
+      }
+
+      template <typename T>
+      inline bool is_vector_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_vector == node->type());
+      }
+
+      template <typename T>
+      inline bool is_ivector_node(const expression_node<T>* node)
+      {
+         if (node)
+         {
+            switch (node->type())
+            {
+               case details::expression_node<T>::e_vector      :
+               case details::expression_node<T>::e_vecvalass   :
+               case details::expression_node<T>::e_vecvecass   :
+               case details::expression_node<T>::e_vecopvalass :
+               case details::expression_node<T>::e_vecopvecass :
+               case details::expression_node<T>::e_vecvecswap  :
+               case details::expression_node<T>::e_vecvecarith :
+               case details::expression_node<T>::e_vecvalarith :
+               case details::expression_node<T>::e_valvecarith :
+               case details::expression_node<T>::e_vecunaryop  : return true;
+               default                                         : return false;
+            }
+         }
+         else
+            return false;
+      }
+
+      template <typename T>
+      inline bool is_constant_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_constant == node->type());
+      }
+
+      template <typename T>
+      inline bool is_null_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_null == node->type());
+      }
+
+      template <typename T>
+      inline bool is_break_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_break == node->type());
+      }
+
+      template <typename T>
+      inline bool is_continue_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_continue == node->type());
+      }
+
+      template <typename T>
+      inline bool is_swap_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_swap == node->type());
+      }
+
+      template <typename T>
+      inline bool is_function(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_function == node->type());
+      }
+
+      template <typename T>
+      inline bool is_return_node(const expression_node<T>* node)
+      {
+         return node && (details::expression_node<T>::e_return == node->type());
+      }
+
+      template <typename T> class unary_node;
+
+      template <typename T>
+      inline bool is_negate_node(const expression_node<T>* node)
+      {
+         if (node && is_unary_node(node))
+         {
+            return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
+         }
+         else
+            return false;
+      }
+
+      template <typename T>
+      inline bool branch_deletable(expression_node<T>* node)
+      {
+         return !is_variable_node(node) &&
+                !is_string_node  (node) ;
+      }
+
+      template <std::size_t N, typename T>
+      inline bool all_nodes_valid(expression_node<T>* (&b)[N])
+      {
+         for (std::size_t i = 0; i < N; ++i)
+         {
+            if (0 == b[i]) return false;
+         }
+
+         return true;
+      }
+
+      template <typename T,
+                typename Allocator,
+                template <typename,typename> class Sequence>
+      inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
+      {
+         for (std::size_t i = 0; i < b.size(); ++i)
+         {
+            if (0 == b[i]) return false;
+         }
+
+         return true;
+      }
+
+      template <std::size_t N, typename T>
+      inline bool all_nodes_variables(expression_node<T>* (&b)[N])
+      {
+         for (std::size_t i = 0; i < N; ++i)
+         {
+            if (0 == b[i])
+               return false;
+            else if (!is_variable_node(b[i]))
+               return false;
+         }
+
+         return true;
+      }
+
+      template <typename T,
+                typename Allocator,
+                template <typename,typename> class Sequence>
+      inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
+      {
+         for (std::size_t i = 0; i < b.size(); ++i)
+         {
+            if (0 == b[i])
+               return false;
+            else if (!is_variable_node(b[i]))
+               return false;
+         }
+
+         return true;
+      }
+
+      template <typename NodeAllocator, typename T, std::size_t N>
+      inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
+      {
+         for (std::size_t i = 0; i < N; ++i)
+         {
+            free_node(node_allocator,b[i]);
+         }
+      }
+
+      template <typename NodeAllocator,
+                typename T,
+                typename Allocator,
+                template <typename,typename> class Sequence>
+      inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
+      {
+         for (std::size_t i = 0; i < b.size(); ++i)
+         {
+            free_node(node_allocator,b[i]);
+         }
+
+         b.clear();
+      }
+
+      template <typename NodeAllocator, typename T>
+      inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
+      {
+         if (0 != node)
+         {
+            if (
+                 (is_variable_node(node) || is_string_node(node)) ||
+                 force_delete
+               )
+               return;
+
+            node_allocator.free(node);
+            node = 0;
+         }
+      }
+
+      template <typename Type>
+      class vector_holder
+      {
+      private:
+
+         typedef Type value_type;
+         typedef value_type* value_ptr;
+         typedef const value_ptr const_value_ptr;
+
+         class vector_holder_base
+         {
+         public:
+
+            virtual ~vector_holder_base(){}
+
+            inline value_ptr operator[](const std::size_t& index) const
+            {
+               return value_at(index);
+            }
+
+            inline std::size_t size() const
+            {
+               return vector_size();
+            }
+
+         protected:
+
+            virtual value_ptr value_at(const std::size_t&) const = 0;
+            virtual std::size_t vector_size()              const = 0;
+         };
+
+         class array_vector_impl : public vector_holder_base
+         {
+         public:
+
+            array_vector_impl(const Type* vec, const std::size_t& vec_size)
+            : vec_(vec),
+              size_(vec_size)
+            {}
+
+         protected:
+
+            value_ptr value_at(const std::size_t& index) const
+            {
+               if (index < size_)
+                  return const_cast<const_value_ptr>(vec_ + index);
+               else
+                  return const_value_ptr(0);
+            }
+
+            std::size_t vector_size() const
+            {
+               return size_;
+            }
+
+         private:
+
+            array_vector_impl operator=(const array_vector_impl&);
+
+            const Type* vec_;
+            const std::size_t size_;
+         };
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         class sequence_vector_impl : public vector_holder_base
+         {
+         public:
+
+            typedef Sequence<Type,Allocator> sequence_t;
+
+            sequence_vector_impl(sequence_t& seq)
+            : sequence_(seq)
+            {}
+
+         protected:
+
+            value_ptr value_at(const std::size_t& index) const
+            {
+               return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
+            }
+
+            std::size_t vector_size() const
+            {
+               return sequence_.size();
+            }
+
+         private:
+
+            sequence_vector_impl operator=(const sequence_vector_impl&);
+
+            sequence_t& sequence_;
+         };
+
+      public:
+
+         vector_holder(Type* vec, const std::size_t& vec_size)
+         : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
+         {}
+
+         template <typename Allocator>
+         vector_holder(std::vector<Type,Allocator>& vec)
+         : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
+         {}
+
+         template <typename Allocator>
+         vector_holder(std::deque<Type,Allocator>& deq)
+         : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::deque>(deq))
+         {}
+
+         inline value_ptr operator[](const std::size_t& index) const
+         {
+            return (*vector_holder_base_)[index];
+         }
+
+         inline std::size_t size() const
+         {
+            return vector_holder_base_->size();
+         }
+
+      private:
+
+         mutable vector_holder_base* vector_holder_base_;
+         unsigned char buffer[64];
+      };
+
+      template <typename T>
+      class null_node : public expression_node<T>
+      {
+      public:
+
+         inline T value() const
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_null;
+         }
+      };
+
+      template <typename T>
+      class null_eq_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         null_eq_node(expression_ptr brnch, const bool equality = true)
+         : branch_(brnch),
+           branch_deletable_(branch_deletable(branch_)),
+           equality_(equality)
+         {}
+
+        ~null_eq_node()
+         {
+            if (branch_ && branch_deletable_)
+            {
+               delete branch_;
+               branch_ = 0;
+            }
+         }
+
+         inline T value() const
+         {
+            const T v = branch_->value();
+            const bool result = details::numeric::is_nan(v);
+
+            if (result)
+               return (equality_) ? T(1) : T(0);
+            else
+               return (equality_) ? T(0) : T(1);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_nulleq;
+         }
+
+         inline operator_type operation() const
+         {
+            return details::e_eq;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return branch_;
+         }
+
+      private:
+
+         expression_ptr branch_;
+         bool branch_deletable_;
+         bool equality_;
+      };
+
+      template <typename T>
+      class literal_node : public expression_node<T>
+      {
+      public:
+
+         explicit literal_node(const T& v)
+         : value_(v)
+         {}
+
+         inline T value() const
+         {
+            return value_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_constant;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return reinterpret_cast<expression_node<T>*>(0);
+         }
+
+      private:
+
+         literal_node(literal_node<T>&) {}
+         literal_node<T>& operator=(literal_node<T>&) { return *this; }
+
+         const T value_;
+      };
+
+      template <typename T>
+      struct range_pack;
+
+      template <typename T>
+      struct range_data_type;
+
+      template <typename T>
+      class range_interface
+      {
+      public:
+
+         typedef range_pack<T> range_t;
+
+         virtual ~range_interface()
+         {}
+
+         virtual range_t& range_ref() = 0;
+
+         virtual const range_t& range_ref() const = 0;
+      };
+
+      template <typename T>
+      class string_base_node
+      {
+      public:
+
+         typedef range_data_type<T> range_data_type_t;
+
+         virtual ~string_base_node()
+         {}
+
+         virtual std::string str () const = 0;
+
+         virtual const char* base() const = 0;
+
+         virtual std::size_t size() const = 0;
+      };
+
+      template <typename T>
+      class string_literal_node : public expression_node <T>,
+                                  public string_base_node<T>,
+                                  public range_interface <T>
+      {
+      public:
+
+         typedef range_pack<T> range_t;
+
+         explicit string_literal_node(const std::string& v)
+         : value_(v)
+         {
+            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
+            rp_.cache.first  = rp_.n0_c.second;
+            rp_.cache.second = rp_.n1_c.second;
+         }
+
+         inline T value() const
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_stringconst;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return reinterpret_cast<expression_node<T>*>(0);
+         }
+
+         std::string str() const
+         {
+            return value_;
+         }
+
+         const char* base() const
+         {
+           return value_.data();
+         }
+
+         std::size_t size() const
+         {
+            return value_.size();
+         }
+
+         range_t& range_ref()
+         {
+            return rp_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return rp_;
+         }
+
+      private:
+
+         string_literal_node(const string_literal_node<T>&);
+         string_literal_node<T>& operator=(const string_literal_node<T>&);
+
+         const std::string value_;
+         range_t rp_;
+      };
+
+      template <typename T>
+      class unary_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         unary_node(const operator_type& opr,
+                    expression_ptr brnch)
+         : operation_(opr),
+           branch_(brnch),
+           branch_deletable_(branch_deletable(branch_))
+         {}
+
+        ~unary_node()
+         {
+            if (branch_ && branch_deletable_)
+            {
+               delete branch_;
+               branch_ = 0;
+            }
+         }
+
+         inline T value() const
+         {
+            const T arg = branch_->value();
+            return numeric::process<T>(operation_,arg);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_unary;
+         }
+
+         inline operator_type operation() const
+         {
+            return operation_;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return branch_;
+         }
+
+         inline void release()
+         {
+            branch_deletable_ = false;
+         }
+
+      protected:
+
+         operator_type operation_;
+         expression_ptr branch_;
+         bool branch_deletable_;
+      };
+
+      template <typename T, std::size_t D, bool B>
+      struct construct_branch_pair
+      {
+         template <std::size_t N>
+         static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
+         {}
+      };
+
+      template <typename T, std::size_t D>
+      struct construct_branch_pair<T,D,true>
+      {
+         template <std::size_t N>
+         static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
+         {
+            if (b)
+            {
+               branch[D] = std::make_pair(b,branch_deletable(b));
+            }
+         }
+      };
+
+      template <std::size_t N, typename T>
+      inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
+                                expression_node<T>* b0,
+                                expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
+                                expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
+      {
+         construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
+         construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
+         construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
+         construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
+         construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
+         construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
+         construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
+         construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
+         construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
+         construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
+      }
+
+      struct cleanup_branches
+      {
+         template <typename T, std::size_t N>
+         static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
+         {
+            for (std::size_t i = 0; i < N; ++i)
+            {
+               if (branch[i].first && branch[i].second)
+               {
+                  delete branch[i].first;
+                  branch[i].first = 0;
+               }
+            }
+         }
+
+         template <typename T,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)
+         {
+            for (std::size_t i = 0; i < branch.size(); ++i)
+            {
+               if (branch[i].first && branch[i].second)
+               {
+                  delete branch[i].first;
+                  branch[i].first = 0;
+               }
+            }
+         }
+      };
+
+      template <typename T>
+      class binary_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+
+         binary_node(const operator_type& opr,
+                     expression_ptr branch0,
+                     expression_ptr branch1)
+         : operation_(opr)
+         {
+            init_branches<2>(branch_,branch0,branch1);
+         }
+
+        ~binary_node()
+         {
+            cleanup_branches::execute<T,2>(branch_);
+         }
+
+         inline T value() const
+         {
+            const T arg0 = branch_[0].first->value();
+            const T arg1 = branch_[1].first->value();
+            return numeric::process<T>(operation_,arg0,arg1);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_binary;
+         }
+
+         inline operator_type operation()
+         {
+            return operation_;
+         }
+
+         inline expression_node<T>* branch(const std::size_t& index = 0) const
+         {
+            if (0 == index)
+               return branch_[0].first;
+            else if (1 == index)
+               return branch_[1].first;
+            else
+               return reinterpret_cast<expression_ptr>(0);
+         }
+
+      protected:
+
+         operator_type operation_;
+         branch_t branch_[2];
+      };
+
+      template <typename T, typename Operation>
+      class binary_ext_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+
+         binary_ext_node(expression_ptr branch0, expression_ptr branch1)
+         {
+            init_branches<2>(branch_,branch0,branch1);
+         }
+
+        ~binary_ext_node()
+         {
+            cleanup_branches::execute<T,2>(branch_);
+         }
+
+         inline T value() const
+         {
+            const T arg0 = branch_[0].first->value();
+            const T arg1 = branch_[1].first->value();
+            return Operation::process(arg0,arg1);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_binary_ext;
+         }
+
+         inline operator_type operation()
+         {
+            return Operation::operation();
+         }
+
+         inline expression_node<T>* branch(const std::size_t& index = 0) const
+         {
+            if (0 == index)
+               return branch_[0].first;
+            else if (1 == index)
+               return branch_[1].first;
+            else
+               return reinterpret_cast<expression_ptr>(0);
+         }
+
+      protected:
+
+         branch_t branch_[2];
+      };
+
+      template <typename T>
+      class trinary_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+
+         trinary_node(const operator_type& opr,
+                      expression_ptr branch0,
+                      expression_ptr branch1,
+                      expression_ptr branch2)
+         : operation_(opr)
+         {
+            init_branches<3>(branch_,branch0,branch1,branch2);
+         }
+
+        ~trinary_node()
+         {
+            cleanup_branches::execute<T,3>(branch_);
+         }
+
+         inline T value() const
+         {
+            const T arg0 = branch_[0].first->value();
+            const T arg1 = branch_[1].first->value();
+            const T arg2 = branch_[2].first->value();
+
+            switch (operation_)
+            {
+               case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
+               case e_clamp   : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
+               case e_iclamp  : if ((arg1 <= arg0) || (arg1 >= arg2))
+                                   return arg1;
+                                else
+                                   return ((T(2) * arg1  <= (arg2 + arg0)) ? arg0 : arg2);
+               default        : return std::numeric_limits<T>::quiet_NaN();
+            }
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_trinary;
+         }
+
+      protected:
+
+         operator_type operation_;
+         branch_t branch_[3];
+      };
+
+      template <typename T>
+      class quaternary_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+
+         quaternary_node(const operator_type& opr,
+                         expression_ptr branch0,
+                         expression_ptr branch1,
+                         expression_ptr branch2,
+                         expression_ptr branch3)
+         : operation_(opr)
+         {
+            init_branches<4>(branch_,branch0,branch1,branch2,branch3);
+         }
+
+        ~quaternary_node()
+         {
+            cleanup_branches::execute<T,4>(branch_);
+         }
+
+         inline T value() const
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_quaternary;
+         }
+
+      protected:
+
+         operator_type operation_;
+         branch_t branch_[4];
+      };
+
+      template <typename T>
+      class conditional_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         conditional_node(expression_ptr test,
+                          expression_ptr consequent,
+                          expression_ptr alternative)
+         : test_(test),
+           consequent_(consequent),
+           alternative_(alternative),
+           test_deletable_(branch_deletable(test_)),
+           consequent_deletable_(branch_deletable(consequent_)),
+           alternative_deletable_(branch_deletable(alternative_))
+         {}
+
+        ~conditional_node()
+         {
+            if (test_        && test_deletable_       ) delete test_;
+            if (consequent_  && consequent_deletable_ ) delete consequent_;
+            if (alternative_ && alternative_deletable_) delete alternative_;
+         }
+
+         inline T value() const
+         {
+            if (is_true(test_))
+               return consequent_->value();
+            else
+               return alternative_->value();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_conditional;
+         }
+
+      private:
+
+         expression_ptr test_;
+         expression_ptr consequent_;
+         expression_ptr alternative_;
+         bool test_deletable_;
+         bool consequent_deletable_;
+         bool alternative_deletable_;
+      };
+
+      template <typename T>
+      class cons_conditional_node : public expression_node<T>
+      {
+      public:
+
+         // Consequent only conditional statement node
+         typedef expression_node<T>* expression_ptr;
+
+         cons_conditional_node(expression_ptr test,
+                               expression_ptr consequent)
+         : test_(test),
+           consequent_(consequent),
+           test_deletable_(branch_deletable(test_)),
+           consequent_deletable_(branch_deletable(consequent_))
+         {}
+
+        ~cons_conditional_node()
+         {
+            if (test_       && test_deletable_      ) delete test_;
+            if (consequent_ && consequent_deletable_) delete consequent_;
+         }
+
+         inline T value() const
+         {
+            if (is_true(test_))
+               return consequent_->value();
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_conditional;
+         }
+
+      private:
+
+         expression_ptr test_;
+         expression_ptr consequent_;
+         bool test_deletable_;
+         bool consequent_deletable_;
+      };
+
+      #ifndef exprtk_disable_break_continue
+      template <typename T>
+      class break_exception
+      {
+      public:
+
+         break_exception(const T& v)
+         : value(v)
+         {}
+
+         T value;
+      };
+
+      class continue_exception
+      {};
+
+      template <typename T>
+      class break_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         break_node(expression_ptr ret = expression_ptr(0))
+         : return_(ret),
+           return_deletable_(branch_deletable(return_))
+         {}
+
+        ~break_node()
+         {
+            if (return_deletable_)
+            {
+               delete return_;
+            }
+         }
+
+         inline T value() const
+         {
+            throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
+            #ifndef _MSC_VER
+            return std::numeric_limits<T>::quiet_NaN();
+            #endif
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_break;
+         }
+
+      private:
+
+         expression_ptr return_;
+         bool return_deletable_;
+      };
+
+      template <typename T>
+      class continue_node : public expression_node<T>
+      {
+      public:
+
+         inline T value() const
+         {
+            throw continue_exception();
+            #ifndef _MSC_VER
+            return std::numeric_limits<T>::quiet_NaN();
+            #endif
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_break;
+         }
+      };
+      #endif
+
+      template <typename T>
+      class while_loop_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         while_loop_node(expression_ptr condition, expression_ptr loop_body)
+         : condition_(condition),
+           loop_body_(loop_body),
+           condition_deletable_(branch_deletable(condition_)),
+           loop_body_deletable_(branch_deletable(loop_body_))
+         {}
+
+        ~while_loop_node()
+         {
+            if (condition_ && condition_deletable_)
+            {
+               delete condition_;
+            }
+
+            if (loop_body_ && loop_body_deletable_)
+            {
+               delete loop_body_;
+            }
+         }
+
+         inline T value() const
+         {
+            T result = T(0);
+
+            while (is_true(condition_))
+            {
+               result = loop_body_->value();
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_while;
+         }
+
+      private:
+
+         expression_ptr condition_;
+         expression_ptr loop_body_;
+         bool condition_deletable_;
+         bool loop_body_deletable_;
+      };
+
+      template <typename T>
+      class repeat_until_loop_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body)
+         : condition_(condition),
+           loop_body_(loop_body),
+           condition_deletable_(branch_deletable(condition_)),
+           loop_body_deletable_(branch_deletable(loop_body_))
+         {}
+
+        ~repeat_until_loop_node()
+         {
+            if (condition_ && condition_deletable_)
+            {
+               delete condition_;
+            }
+
+            if (loop_body_ && loop_body_deletable_)
+            {
+               delete loop_body_;
+            }
+         }
+
+         inline T value() const
+         {
+            T result = T(0);
+
+            do
+            {
+               result = loop_body_->value();
+            }
+            while (is_false(condition_));
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_repeat;
+         }
+
+      private:
+
+         expression_ptr condition_;
+         expression_ptr loop_body_;
+         bool condition_deletable_;
+         bool loop_body_deletable_;
+      };
+
+      template <typename T>
+      class for_loop_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         for_loop_node(expression_ptr initialiser,
+                       expression_ptr condition,
+                       expression_ptr incrementor,
+                       expression_ptr loop_body)
+         : initialiser_(initialiser),
+           condition_  (condition),
+           incrementor_(incrementor),
+           loop_body_  (loop_body),
+           initialiser_deletable_(branch_deletable(initialiser_)),
+           condition_deletable_  (branch_deletable(condition_  )),
+           incrementor_deletable_(branch_deletable(incrementor_)),
+           loop_body_deletable_  (branch_deletable(loop_body_  ))
+         {}
+
+        ~for_loop_node()
+         {
+            if (initialiser_ && initialiser_deletable_)
+            {
+               delete initialiser_;
+            }
+
+            if (condition_ && condition_deletable_)
+            {
+               delete condition_;
+            }
+
+            if (incrementor_ && incrementor_deletable_)
+            {
+               delete incrementor_;
+            }
+
+            if (loop_body_ && loop_body_deletable_)
+            {
+               delete loop_body_;
+            }
+         }
+
+         inline T value() const
+         {
+            T result = T(0);
+
+            if (initialiser_)
+               initialiser_->value();
+
+            if (incrementor_)
+            {
+               while (is_true(condition_))
+               {
+                  result = loop_body_->value();
+                  incrementor_->value();
+               }
+            }
+            else
+            {
+               while (is_true(condition_))
+               {
+                  result = loop_body_->value();
+               }
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_for;
+         }
+
+      private:
+
+         expression_ptr initialiser_;
+         expression_ptr condition_  ;
+         expression_ptr incrementor_;
+         expression_ptr loop_body_  ;
+         bool initialiser_deletable_;
+         bool condition_deletable_  ;
+         bool incrementor_deletable_;
+         bool loop_body_deletable_  ;
+      };
+
+      #ifndef exprtk_disable_break_continue
+      template <typename T>
+      class while_loop_bc_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         while_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
+         : condition_(condition),
+           loop_body_(loop_body),
+           condition_deletable_(branch_deletable(condition_)),
+           loop_body_deletable_(branch_deletable(loop_body_))
+         {}
+
+        ~while_loop_bc_node()
+         {
+            if (condition_ && condition_deletable_)
+            {
+               delete condition_;
+            }
+
+            if (loop_body_ && loop_body_deletable_)
+            {
+               delete loop_body_;
+            }
+         }
+
+         inline T value() const
+         {
+            T result = T(0);
+            while (is_true(condition_))
+            {
+               try
+               {
+                  result = loop_body_->value();
+               }
+               catch(const break_exception<T>& e)
+               {
+                  return e.value;
+               }
+               catch(const continue_exception&)
+               {}
+            }
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_while;
+         }
+
+      private:
+
+         expression_ptr condition_;
+         expression_ptr loop_body_;
+         bool condition_deletable_;
+         bool loop_body_deletable_;
+      };
+
+      template <typename T>
+      class repeat_until_loop_bc_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body)
+         : condition_(condition),
+           loop_body_(loop_body),
+           condition_deletable_(branch_deletable(condition_)),
+           loop_body_deletable_(branch_deletable(loop_body_))
+         {}
+
+        ~repeat_until_loop_bc_node()
+         {
+            if (condition_ && condition_deletable_)
+            {
+               delete condition_;
+            }
+
+            if (loop_body_ && loop_body_deletable_)
+            {
+               delete loop_body_;
+            }
+         }
+
+         inline T value() const
+         {
+            T result = T(0);
+
+            do
+            {
+               try
+               {
+                  result = loop_body_->value();
+               }
+               catch(const break_exception<T>& e)
+               {
+                  return e.value;
+               }
+               catch(const continue_exception&)
+               {}
+            }
+            while (is_false(condition_));
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_repeat;
+         }
+
+      private:
+
+         expression_ptr condition_;
+         expression_ptr loop_body_;
+         bool condition_deletable_;
+         bool loop_body_deletable_;
+      };
+
+      template <typename T>
+      class for_loop_bc_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         for_loop_bc_node(expression_ptr initialiser,
+                       expression_ptr condition,
+                       expression_ptr incrementor,
+                       expression_ptr loop_body)
+         : initialiser_(initialiser),
+           condition_  (condition  ),
+           incrementor_(incrementor),
+           loop_body_  (loop_body  ),
+           initialiser_deletable_(branch_deletable(initialiser_)),
+           condition_deletable_  (branch_deletable(condition_  )),
+           incrementor_deletable_(branch_deletable(incrementor_)),
+           loop_body_deletable_  (branch_deletable(loop_body_  ))
+         {}
+
+        ~for_loop_bc_node()
+         {
+            if (initialiser_ && initialiser_deletable_)
+            {
+               delete initialiser_;
+            }
+
+            if (condition_ && condition_deletable_)
+            {
+               delete condition_;
+            }
+
+            if (incrementor_ && incrementor_deletable_)
+            {
+               delete incrementor_;
+            }
+
+            if (loop_body_ && loop_body_deletable_)
+            {
+               delete loop_body_;
+            }
+         }
+
+         inline T value() const
+         {
+            T result = T(0);
+
+            if (initialiser_)
+               initialiser_->value();
+
+            if (incrementor_)
+            {
+               while (is_true(condition_))
+               {
+                  try
+                  {
+                     result = loop_body_->value();
+                  }
+                  catch(const break_exception<T>& e)
+                  {
+                     return e.value;
+                  }
+                  catch(const continue_exception&)
+                  {}
+
+                  incrementor_->value();
+               }
+            }
+            else
+            {
+               while (is_true(condition_))
+               {
+                  try
+                  {
+                     result = loop_body_->value();
+                  }
+                  catch(const break_exception<T>& e)
+                  {
+                     return e.value;
+                  }
+                  catch(const continue_exception&)
+                  {}
+               }
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_for;
+         }
+
+      private:
+
+         expression_ptr initialiser_;
+         expression_ptr condition_  ;
+         expression_ptr incrementor_;
+         expression_ptr loop_body_  ;
+         bool initialiser_deletable_;
+         bool condition_deletable_  ;
+         bool incrementor_deletable_;
+         bool loop_body_deletable_  ;
+      };
+      #endif
+
+      template <typename T>
+      class switch_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
+         {
+            if (1 != (arg_list.size() & 1))
+               return;
+
+            arg_list_.resize(arg_list.size());
+            delete_branch_.resize(arg_list.size());
+
+            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            {
+               if (arg_list[i])
+               {
+                       arg_list_[i] = arg_list[i];
+                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
+               }
+               else
+               {
+                  arg_list_.clear();
+                  delete_branch_.clear();
+                  return;
+               }
+            }
+         }
+
+        ~switch_node()
+         {
+            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            {
+               if (arg_list_[i] && delete_branch_[i])
+               {
+                  delete arg_list_[i];
+                  arg_list_[i] = 0;
+               }
+            }
+         }
+
+         inline T value() const
+         {
+            if (!arg_list_.empty())
+            {
+               const std::size_t upper_bound = (arg_list_.size() - 1);
+
+               for (std::size_t i = 0; i < upper_bound; i += 2)
+               {
+                  expression_ptr condition  = arg_list_[i    ];
+                  expression_ptr consequent = arg_list_[i + 1];
+
+                  if (is_true(condition))
+                  {
+                     return consequent->value();
+                  }
+               }
+
+               return arg_list_[upper_bound]->value();
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_switch;
+         }
+
+      protected:
+
+         std::vector<expression_ptr> arg_list_;
+         std::vector<unsigned char> delete_branch_;
+      };
+
+      template <typename T, typename Switch_N>
+      class switch_n_node : public switch_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
+         : switch_node<T>(arg_list)
+         {}
+
+         inline T value() const
+         {
+            return Switch_N::process(switch_node<T>::arg_list_);
+         }
+      };
+
+      template <typename T>
+      class multi_switch_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
+         {
+            if (0 != (arg_list.size() & 1))
+               return;
+
+            arg_list_.resize(arg_list.size());
+            delete_branch_.resize(arg_list.size());
+
+            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            {
+               if (arg_list[i])
+               {
+                       arg_list_[i] = arg_list[i];
+                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
+               }
+               else
+               {
+                  arg_list_.clear();
+                  delete_branch_.clear();
+                  return;
+               }
+            }
+         }
+
+        ~multi_switch_node()
+         {
+            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            {
+               if (arg_list_[i] && delete_branch_[i])
+               {
+                  delete arg_list_[i];
+                  arg_list_[i] = 0;
+               }
+            }
+         }
+
+         inline T value() const
+         {
+            T result = T(0);
+
+            if (arg_list_.empty())
+            {
+               return std::numeric_limits<T>::quiet_NaN();
+            }
+
+            const std::size_t upper_bound = (arg_list_.size() - 1);
+
+            for (std::size_t i = 0; i < upper_bound; i += 2)
+            {
+               expression_ptr condition  = arg_list_[i    ];
+               expression_ptr consequent = arg_list_[i + 1];
+
+               if (is_true(condition))
+               {
+                  result = consequent->value();
+               }
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_mswitch;
+         }
+
+      private:
+
+         std::vector<expression_ptr> arg_list_;
+         std::vector<unsigned char> delete_branch_;
+      };
+
+      template <typename T>
+      class ivariable
+      {
+      public:
+
+         virtual ~ivariable()
+         {}
+
+         virtual T& ref() = 0;
+         virtual const T& ref() const = 0;
+      };
+
+      template <typename T>
+      class variable_node : public expression_node<T>,
+                            public ivariable      <T>
+      {
+      public:
+
+         static T null_value;
+
+         explicit variable_node()
+         : value_(&null_value),
+           delete_value_(false)
+         {}
+
+         variable_node(T& v)
+         : value_(&v),
+           delete_value_(false)
+         {}
+
+        ~variable_node()
+         {
+            if (delete_value_)
+            {
+               delete value_;
+            }
+         }
+
+         inline bool operator <(const variable_node<T>& v) const
+         {
+            return this < (&v);
+         }
+
+         inline T value() const
+         {
+            return (*value_);
+         }
+
+         inline T& ref()
+         {
+            return (*value_);
+         }
+
+         inline const T& ref() const
+         {
+            return (*value_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_variable;
+         }
+
+         inline bool& delete_value()
+         {
+            return delete_value_;
+         }
+
+      private:
+
+         T* value_;
+         bool delete_value_;
+      };
+
+      template <typename T>
+      T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
+
+      template <typename T>
+      struct range_pack
+      {
+         typedef expression_node<T>*           expression_node_ptr;
+         typedef std::pair<std::size_t,std::size_t> cached_range_t;
+
+         range_pack()
+         : n0_e (std::make_pair(false,expression_node_ptr(0))),
+           n1_e (std::make_pair(false,expression_node_ptr(0))),
+           n0_c (std::make_pair(false,0)),
+           n1_c (std::make_pair(false,0)),
+           cache(std::make_pair(0,0))
+         {}
+
+         void clear()
+         {
+            n0_e  = std::make_pair(false,expression_node_ptr(0));
+            n1_e  = std::make_pair(false,expression_node_ptr(0));
+            n0_c  = std::make_pair(false,0);
+            n1_c  = std::make_pair(false,0);
+            cache = std::make_pair(0,0);
+         }
+
+         void free()
+         {
+            if (n0_e.first && n0_e.second)
+            {
+               n0_e.first = false;
+
+               if (
+                    !is_variable_node(n0_e.second) &&
+                    !is_string_node  (n0_e.second)
+                  )
+               {
+                  delete n0_e.second;
+                  n0_e.second = expression_node_ptr(0);
+               }
+            }
+
+            if (n1_e.first && n1_e.second)
+            {
+               n1_e.first = false;
+
+               if (
+                    !is_variable_node(n1_e.second) &&
+                    !is_string_node  (n1_e.second)
+                  )
+               {
+                  delete n1_e.second;
+                  n1_e.second = expression_node_ptr(0);
+               }
+            }
+         }
+
+         bool const_range()
+         {
+           return ( n0_c.first &&  n1_c.first) &&
+                  (!n0_e.first && !n1_e.first);
+         }
+
+         bool var_range()
+         {
+           return ( n0_e.first &&  n1_e.first) &&
+                  (!n0_c.first && !n1_c.first);
+         }
+
+         bool operator()(std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
+         {
+            if (n0_c.first)
+               r0 = n0_c.second;
+            else if (n0_e.first)
+            {
+               T r0_value = n0_e.second->value();
+
+               if (r0_value < 0)
+                  return false;
+               else
+                  r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
+            }
+            else
+               return false;
+
+            if (n1_c.first)
+               r1 = n1_c.second;
+            else if (n1_e.first)
+            {
+               T r1_value = n1_e.second->value();
+
+               if (r1_value < 0)
+                  return false;
+               else
+                  r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
+            }
+            else
+               return false;
+
+            if (
+                 (std::numeric_limits<std::size_t>::max() != size) &&
+                 (std::numeric_limits<std::size_t>::max() == r1  )
+               )
+            {
+               r1 = size - 1;
+            }
+
+            cache.first  = r0;
+            cache.second = r1;
+
+            return (r0 <= r1);
+         }
+
+         inline std::size_t const_size() const
+         {
+            return (n1_c.second - n0_c.second + 1);
+         }
+
+         inline std::size_t cache_size() const
+         {
+            return (cache.second - cache.first + 1);
+         }
+
+         std::pair<bool,expression_node_ptr> n0_e;
+         std::pair<bool,expression_node_ptr> n1_e;
+         std::pair<bool,std::size_t        > n0_c;
+         std::pair<bool,std::size_t        > n1_c;
+         mutable cached_range_t             cache;
+      };
+
+      template <typename T>
+      class string_base_node;
+
+      template <typename T>
+      struct range_data_type
+      {
+         typedef range_pack<T> range_t;
+         typedef string_base_node<T>* strbase_ptr_t;
+
+         range_data_type()
+         : range(0),
+           data (0),
+           size (0),
+           type_size(0),
+           str_node (0)
+         {}
+
+         range_t*      range;
+         void*         data;
+         std::size_t   size;
+         std::size_t   type_size;
+         strbase_ptr_t str_node;
+      };
+
+      template <typename T> class vector_node;
+
+      template <typename T>
+      class vector_interface
+      {
+      public:
+
+         typedef vector_node<T>* vector_node_ptr;
+
+         virtual ~vector_interface()
+         {}
+
+         virtual vector_node_ptr vec() const = 0;
+
+         virtual vector_node_ptr vec() = 0;
+
+         virtual std::size_t size() const = 0;
+      };
+
+      template <typename T>
+      class vector_node : public expression_node <T>,
+                          public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*  expression_ptr;
+         typedef vector_holder<T>    vector_holder_t;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         vector_node(vector_holder_t* vh)
+         : vector_holder_(vh)
+         {}
+
+         inline T value() const
+         {
+            return *(ref()[0]);
+         }
+
+         inline const vector_holder_t& ref() const
+         {
+            return (*vector_holder_);
+         }
+
+         inline vector_holder_t& ref()
+         {
+            return (*vector_holder_);
+         }
+
+         vector_node_ptr vec() const
+         {
+            return const_cast<vector_node_ptr>(this);
+         }
+
+         vector_node_ptr vec()
+         {
+            return this;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vector;
+         }
+
+         std::size_t size() const
+         {
+            return ref().size();
+         }
+
+      private:
+
+         vector_holder_t* vector_holder_;
+      };
+
+      template <typename T>
+      class vector_elem_node : public expression_node<T>,
+                               public ivariable      <T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_holder<T>    vector_holder_t;
+         typedef vector_holder_t*    vector_holder_ptr;
+
+         vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder)
+         : index_(index),
+           vec_holder_(vec_holder),
+           vector_base_((*vec_holder)[0]),
+           index_deletable_(branch_deletable(index_))
+         {}
+
+        ~vector_elem_node()
+         {
+            if (index_ && index_deletable_)
+            {
+               delete index_;
+            }
+         }
+
+         inline T value() const
+         {
+           return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+         }
+
+         inline T& ref()
+         {
+            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+         }
+
+         inline const T& ref() const
+         {
+            return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecelem;
+         }
+
+         inline vector_holder_t& vec_holder()
+         {
+            return (*vec_holder_);
+         }
+
+      private:
+
+         expression_ptr index_;
+         vector_holder_ptr vec_holder_;
+         T* vector_base_;
+         bool index_deletable_;
+      };
+
+      template <typename T>
+      class vector_assignment_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vector_assignment_node(T* vector_base,
+                                const std::size_t& size,
+                                const std::vector<expression_ptr>& initialiser_list,
+                                const bool single_value_initialse)
+         : vector_base_(vector_base),
+           initialiser_list_(initialiser_list),
+           size_(size),
+           single_value_initialse_(single_value_initialse)
+         {}
+
+        ~vector_assignment_node()
+         {
+            for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
+            {
+               if (branch_deletable(initialiser_list_[i]))
+               {
+                  delete initialiser_list_[i];
+               }
+            }
+         }
+
+         inline T value() const
+         {
+            if (single_value_initialse_)
+            {
+               for (std::size_t i = 0; i < size_; ++i)
+               {
+                  *(vector_base_ + i) = initialiser_list_[0]->value();
+               }
+            }
+            else
+            {
+               std::size_t il_size = initialiser_list_.size();
+
+               for (std::size_t i = 0; i < il_size; ++i)
+               {
+                  *(vector_base_ + i) = initialiser_list_[i]->value();
+               }
+
+               if (il_size < size_)
+               {
+                  for (std::size_t i = il_size; i < size_; ++i)
+                  {
+                     *(vector_base_ + i) = T(0);
+                  }
+               }
+            }
+
+            return *(vector_base_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecdefass;
+         }
+
+      private:
+
+         vector_assignment_node<T>& operator=(const vector_assignment_node<T>&);
+
+         mutable T* vector_base_;
+         std::vector<expression_ptr> initialiser_list_;
+         const std::size_t size_;
+         const bool single_value_initialse_;
+      };
+
+      template <typename T>
+      class swap_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef variable_node<T>*   variable_node_ptr;
+
+         swap_node(variable_node_ptr var0, variable_node_ptr var1)
+         : var0_(var0),
+           var1_(var1)
+         {}
+
+         inline T value() const
+         {
+            std::swap(var0_->ref(),var1_->ref());
+            return var1_->ref();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_swap;
+         }
+
+      private:
+
+         variable_node_ptr var0_;
+         variable_node_ptr var1_;
+      };
+
+      template <typename T>
+      class swap_generic_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef ivariable<T>* ivariable_ptr;
+
+         swap_generic_node(expression_ptr var0, expression_ptr var1)
+         : binary_node<T>(details::e_swap,var0,var1),
+           var0_(dynamic_cast<ivariable_ptr>(var0)),
+           var1_(dynamic_cast<ivariable_ptr>(var1))
+         {}
+
+         inline T value() const
+         {
+            std::swap(var0_->ref(),var1_->ref());
+            return var1_->ref();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_swap;
+         }
+
+      private:
+
+         ivariable_ptr var0_;
+         ivariable_ptr var1_;
+      };
+
+      template <typename T>
+      class swap_vecvec_node : public binary_node     <T>,
+                               public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         swap_vecvec_node(expression_ptr branch0,
+                          expression_ptr branch1)
+         : binary_node<T>(details::e_swap,branch0,branch1),
+           vec0_node_ptr_(0),
+           vec1_node_ptr_(0),
+           vec_size_     (0),
+           initialised_(false)
+         {
+            if (is_ivector_node(binary_node<T>::branch_[0].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               {
+                  vec0_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (is_ivector_node(binary_node<T>::branch_[1].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               {
+                  vec1_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_ && vec1_node_ptr_)
+            {
+               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
+                                    vec1_node_ptr_->ref().size());
+
+               initialised_ = true;
+            }
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  std::swap((*vec0[i]),(*vec1[i]));
+               }
+
+               return vec1_node_ptr_->value();
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec0_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec0_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvecswap;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec0_node_ptr_;
+         vector_node<T>* vec1_node_ptr_;
+         std::size_t     vec_size_;
+         bool            initialised_;
+      };
+
+      #ifndef exprtk_disable_string_capabilities
+      template <typename T>
+      class stringvar_node : public expression_node <T>,
+                             public string_base_node<T>,
+                             public range_interface <T>
+      {
+      public:
+
+         typedef range_pack<T> range_t;
+
+         static std::string null_value;
+
+         explicit stringvar_node()
+         : value_(&null_value)
+         {}
+
+         explicit stringvar_node(std::string& v)
+         : value_(&v)
+         {
+            rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
+            rp_.cache.first  = rp_.n0_c.second;
+            rp_.cache.second = rp_.n1_c.second;
+         }
+
+         inline bool operator <(const stringvar_node<T>& v) const
+         {
+            return this < (&v);
+         }
+
+         inline T value() const
+         {
+            rp_.n1_c.second  = (*value_).size() - 1;
+            rp_.cache.second = rp_.n1_c.second;
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return ref();
+         }
+
+         const char* base() const
+         {
+           return (*value_).data();
+         }
+
+         std::size_t size() const
+         {
+            return ref().size();
+         }
+
+         std::string& ref()
+         {
+            return (*value_);
+         }
+
+         const std::string& ref() const
+         {
+            return (*value_);
+         }
+
+         range_t& range_ref()
+         {
+            return rp_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return rp_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_stringvar;
+         }
+
+      private:
+
+         std::string* value_;
+         mutable range_t rp_;
+      };
+
+      template <typename T>
+      std::string stringvar_node<T>::null_value = std::string("");
+
+      template <typename T>
+      class string_range_node : public expression_node <T>,
+                                public string_base_node<T>,
+                                public range_interface <T>
+      {
+      public:
+
+         typedef range_pack<T> range_t;
+
+         static std::string null_value;
+
+         explicit string_range_node(std::string& v, range_t rp)
+         : value_(&v),
+           rp_(rp)
+         {}
+
+         virtual ~string_range_node()
+         {
+            rp_.free();
+         }
+
+         inline bool operator <(const string_range_node<T>& v) const
+         {
+            return this < (&v);
+         }
+
+         inline T value() const
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline std::string str() const
+         {
+            return (*value_);
+         }
+
+         const char* base() const
+         {
+           return (*value_).data();
+         }
+
+         std::size_t size() const
+         {
+            return ref().size();
+         }
+
+         inline range_t range() const
+         {
+            return rp_;
+         }
+
+         inline virtual std::string& ref()
+         {
+            return (*value_);
+         }
+
+         inline virtual const std::string& ref() const
+         {
+            return (*value_);
+         }
+
+         inline range_t& range_ref()
+         {
+            return rp_;
+         }
+
+         inline const range_t& range_ref() const
+         {
+            return rp_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_stringvarrng;
+         }
+
+      private:
+
+         std::string* value_;
+         range_t      rp_;
+      };
+
+      template <typename T>
+      std::string string_range_node<T>::null_value = std::string("");
+
+      template <typename T>
+      class const_string_range_node : public expression_node <T>,
+                                      public string_base_node<T>,
+                                      public range_interface <T>
+      {
+      public:
+
+         typedef range_pack<T> range_t;
+
+         explicit const_string_range_node(const std::string& v, range_t rp)
+         : value_(v),
+           rp_(rp)
+         {}
+
+        ~const_string_range_node()
+         {
+            rp_.free();
+         }
+
+         inline T value() const
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return value_;
+         }
+
+         const char* base() const
+         {
+           return value_.data();
+         }
+
+         std::size_t size() const
+         {
+            return value_.size();
+         }
+
+         range_t range() const
+         {
+            return rp_;
+         }
+
+         range_t& range_ref()
+         {
+            return rp_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return rp_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_cstringvarrng;
+         }
+
+      private:
+
+         const_string_range_node<T>& operator=(const const_string_range_node<T>&);
+
+         const std::string value_;
+         range_t rp_;
+      };
+
+      template <typename T>
+      class generic_string_range_node : public expression_node <T>,
+                                        public string_base_node<T>,
+                                        public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>*  expression_ptr;
+         typedef stringvar_node  <T>* strvar_node_ptr;
+         typedef string_base_node<T>*    str_base_ptr;
+         typedef range_pack      <T>          range_t;
+         typedef range_t*                   range_ptr;
+         typedef range_interface<T>          irange_t;
+         typedef irange_t*                 irange_ptr;
+
+         generic_string_range_node(expression_ptr str_branch, range_t brange)
+         : initialised_(false),
+           branch_(str_branch),
+           branch_deletable_(branch_deletable(branch_)),
+           str_base_ptr_ (0),
+           str_range_ptr_(0),
+           base_range_(brange)
+         {
+            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.cache.first  = range_.n0_c.second;
+            range_.cache.second = range_.n1_c.second;
+
+            if (is_generally_string_node(branch_))
+            {
+               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
+
+               if (0 == str_base_ptr_)
+                  return;
+
+               str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
+
+               if (0 == str_range_ptr_)
+                  return;
+            }
+
+            initialised_ = (str_base_ptr_ && str_range_ptr_);
+         }
+
+        ~generic_string_range_node()
+         {
+            base_range_.free();
+
+            if (branch_ && branch_deletable_)
+            {
+               delete branch_;
+               branch_ = 0;
+            }
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               branch_->value();
+
+               std::size_t str_r0 = 0;
+               std::size_t str_r1 = 0;
+
+               std::size_t r0 = 0;
+               std::size_t r1 = 0;
+
+               range_t& range = str_range_ptr_->range_ref();
+
+               const std::size_t base_str_size = str_base_ptr_->size();
+
+               if (
+                    range      (str_r0,str_r1,base_str_size) &&
+                    base_range_(    r0,    r1,base_str_size)
+                  )
+               {
+                  const std::size_t size = (r1 - r0) + 1;
+
+                  range_.n1_c.second  = size - 1;
+                  range_.cache.second = range_.n1_c.second;
+
+                  value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return value_;
+         }
+
+         const char* base() const
+         {
+           return value_.data();
+         }
+
+         std::size_t size() const
+         {
+            return value_.size();
+         }
+
+         range_t& range_ref()
+         {
+            return range_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return range_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strgenrange;
+         }
+
+      private:
+
+         bool               initialised_;
+         expression_ptr          branch_;
+         bool          branch_deletable_;
+         str_base_ptr      str_base_ptr_;
+         irange_ptr       str_range_ptr_;
+         mutable range_t     base_range_;
+         mutable range_t          range_;
+         mutable std::string      value_;
+      };
+
+      template <typename T>
+      class string_concat_node : public binary_node     <T>,
+                                 public string_base_node<T>,
+                                 public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>*  expression_ptr;
+         typedef string_base_node<T>*    str_base_ptr;
+         typedef range_pack      <T>          range_t;
+         typedef range_t*                   range_ptr;
+         typedef range_interface<T>          irange_t;
+         typedef irange_t*                 irange_ptr;
+
+         string_concat_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           initialised_(false),
+           str0_base_ptr_ (0),
+           str1_base_ptr_ (0),
+           str0_range_ptr_(0),
+           str1_range_ptr_(0)
+         {
+            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+
+            range_.cache.first  = range_.n0_c.second;
+            range_.cache.second = range_.n1_c.second;
+
+            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            {
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+
+               if (0 == str0_base_ptr_)
+                  return;
+
+               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+
+               if (0 == str0_range_ptr_)
+                  return;
+            }
+
+            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            {
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == str1_base_ptr_)
+                  return;
+
+               str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == str1_range_ptr_)
+                  return;
+            }
+
+            initialised_ = str0_base_ptr_  &&
+                           str1_base_ptr_  &&
+                           str0_range_ptr_ &&
+                           str1_range_ptr_ ;
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               std::size_t str0_r0 = 0;
+               std::size_t str0_r1 = 0;
+
+               std::size_t str1_r0 = 0;
+               std::size_t str1_r1 = 0;
+
+               range_t& range0 = str0_range_ptr_->range_ref();
+               range_t& range1 = str1_range_ptr_->range_ref();
+
+               if (
+                    range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
+                    range1(str1_r0,str1_r1,str1_base_ptr_->size())
+                  )
+               {
+                  const std::size_t size0 = (str0_r1 - str0_r0) + 1;
+                  const std::size_t size1 = (str1_r1 - str1_r0) + 1;
+
+                  value_.assign(str0_base_ptr_->base() + str0_r0, size0);
+                  value_.append(str1_base_ptr_->base() + str1_r0, size1);
+
+                  range_.n1_c.second  = value_.size() - 1;
+                  range_.cache.second = range_.n1_c.second;
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return value_;
+         }
+
+         const char* base() const
+         {
+           return value_.data();
+         }
+
+         std::size_t size() const
+         {
+            return value_.size();
+         }
+
+         range_t& range_ref()
+         {
+            return range_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return range_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strconcat;
+         }
+
+      private:
+
+         bool initialised_;
+         str_base_ptr str0_base_ptr_;
+         str_base_ptr str1_base_ptr_;
+         irange_ptr   str0_range_ptr_;
+         irange_ptr   str1_range_ptr_;
+         mutable range_t     range_;
+         mutable std::string value_;
+      };
+
+      template <typename T>
+      class swap_string_node : public binary_node     <T>,
+                               public string_base_node<T>,
+                               public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>*  expression_ptr;
+         typedef stringvar_node  <T>* strvar_node_ptr;
+         typedef string_base_node<T>*    str_base_ptr;
+         typedef range_pack      <T>          range_t;
+         typedef range_t*                   range_ptr;
+         typedef range_interface<T>          irange_t;
+         typedef irange_t*                 irange_ptr;
+
+         swap_string_node(expression_ptr branch0, expression_ptr branch1)
+         : binary_node<T>(details::e_swap,branch0,branch1),
+           initialised_(false),
+           str0_node_ptr_(0),
+           str1_node_ptr_(0)
+         {
+            if (is_string_node(binary_node<T>::branch_[0].first))
+            {
+               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+            }
+
+            if (is_string_node(binary_node<T>::branch_[1].first))
+            {
+               str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
+            }
+
+            initialised_ = (str0_node_ptr_ && str1_node_ptr_);
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref());
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return str0_node_ptr_->str();
+         }
+
+         const char* base() const
+         {
+           return str0_node_ptr_->base();
+         }
+
+         std::size_t size() const
+         {
+            return str0_node_ptr_->size();
+         }
+
+         range_t& range_ref()
+         {
+            return str0_node_ptr_->range_ref();
+         }
+
+         const range_t& range_ref() const
+         {
+            return str0_node_ptr_->range_ref();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strswap;
+         }
+
+      private:
+
+         bool initialised_;
+         strvar_node_ptr str0_node_ptr_;
+         strvar_node_ptr str1_node_ptr_;
+      };
+
+      template <typename T>
+      class stringvar_size_node : public expression_node<T>
+      {
+      public:
+
+         static std::string null_value;
+
+         explicit stringvar_size_node()
+         : value_(&null_value)
+         {}
+
+         explicit stringvar_size_node(std::string& v)
+         : value_(&v)
+         {}
+
+         inline T value() const
+         {
+            return T((*value_).size());
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_stringvarsize;
+         }
+
+      private:
+
+         std::string* value_;
+      };
+
+      template <typename T>
+      std::string stringvar_size_node<T>::null_value = std::string("");
+
+      template <typename T>
+      class string_size_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node <T>* expression_ptr;
+         typedef string_base_node<T>*   str_base_ptr;
+
+         string_size_node(expression_ptr brnch)
+         : branch_(brnch),
+           branch_deletable_(branch_deletable(branch_)),
+           str_base_ptr_(0)
+         {
+            if (is_generally_string_node(branch_))
+            {
+               str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
+
+               if (0 == str_base_ptr_)
+                  return;
+            }
+         }
+
+        ~string_size_node()
+         {
+            if (branch_ && branch_deletable_)
+            {
+               delete branch_;
+               branch_ = 0;
+            }
+         }
+
+         inline T value() const
+         {
+            T result = std::numeric_limits<T>::quiet_NaN();
+
+            if (str_base_ptr_)
+            {
+               branch_->value();
+               result = T(str_base_ptr_->size());
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_stringsize;
+         }
+
+      private:
+
+         expression_ptr branch_;
+         bool branch_deletable_;
+         str_base_ptr str_base_ptr_;
+      };
+
+      struct asn_assignment
+      {
+         static inline void execute(std::string& s, const char* data, const std::size_t size)
+         { s.assign(data,size); }
+      };
+
+      struct asn_addassignment
+      {
+         static inline void execute(std::string& s, const char* data, const std::size_t size)
+         { s.append(data,size); }
+      };
+
+      template <typename T, typename AssignmentProcess = asn_assignment>
+      class assignment_string_node : public binary_node     <T>,
+                                     public string_base_node<T>,
+                                     public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>*  expression_ptr;
+         typedef stringvar_node  <T>* strvar_node_ptr;
+         typedef string_base_node<T>*    str_base_ptr;
+         typedef range_pack      <T>          range_t;
+         typedef range_t*                   range_ptr;
+         typedef range_interface<T>          irange_t;
+         typedef irange_t*                 irange_ptr;
+
+         assignment_string_node(const operator_type& opr,
+                                expression_ptr branch0,
+                                expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           initialised_(false),
+           str0_base_ptr_ (0),
+           str1_base_ptr_ (0),
+           str0_node_ptr_ (0),
+           str1_range_ptr_(0)
+         {
+            if (is_string_node(binary_node<T>::branch_[0].first))
+            {
+               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+            }
+
+            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            {
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == str1_base_ptr_)
+                  return;
+
+               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == range_ptr)
+                  return;
+
+               str1_range_ptr_ = &(range_ptr->range_ref());
+            }
+
+            initialised_ = str0_base_ptr_  &&
+                           str1_base_ptr_  &&
+                           str0_node_ptr_  &&
+                           str1_range_ptr_ ;
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[1].first->value();
+
+               std::size_t r0 = 0;
+               std::size_t r1 = 0;
+
+               range_t& range = (*str1_range_ptr_);
+
+               if (range(r0,r1,str1_base_ptr_->size()))
+               {
+                  AssignmentProcess::execute(str0_node_ptr_->ref(),
+                                             str1_base_ptr_->base() + r0,
+                                             (r1 - r0) + 1);
+
+                  binary_node<T>::branch_[0].first->value();
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return str0_node_ptr_->str();
+         }
+
+         const char* base() const
+         {
+           return str0_node_ptr_->base();
+         }
+
+         std::size_t size() const
+         {
+            return str0_node_ptr_->size();
+         }
+
+         range_t& range_ref()
+         {
+            return str0_node_ptr_->range_ref();
+         }
+
+         const range_t& range_ref() const
+         {
+            return str0_node_ptr_->range_ref();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strass;
+         }
+
+      private:
+
+         bool            initialised_;
+         str_base_ptr    str0_base_ptr_;
+         str_base_ptr    str1_base_ptr_;
+         strvar_node_ptr str0_node_ptr_;
+         range_ptr       str1_range_ptr_;
+      };
+
+      template <typename T, typename AssignmentProcess = asn_assignment>
+      class assignment_string_range_node : public binary_node     <T>,
+                                           public string_base_node<T>,
+                                           public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>*  expression_ptr;
+         typedef stringvar_node  <T>* strvar_node_ptr;
+         typedef string_base_node<T>*    str_base_ptr;
+         typedef range_pack      <T>          range_t;
+         typedef range_t*                   range_ptr;
+         typedef range_interface<T>          irange_t;
+         typedef irange_t*                 irange_ptr;
+
+         assignment_string_range_node(const operator_type& opr,
+                                      expression_ptr branch0,
+                                      expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           initialised_(false),
+           str0_base_ptr_ (0),
+           str1_base_ptr_ (0),
+           str0_node_ptr_ (0),
+           str0_range_ptr_(0),
+           str1_range_ptr_(0)
+         {
+            if (is_string_range_node(binary_node<T>::branch_[0].first))
+            {
+               str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
+
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+
+               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+
+               if (0 == range_ptr)
+                  return;
+
+               str0_range_ptr_ = &(range_ptr->range_ref());
+            }
+
+            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            {
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == str1_base_ptr_)
+                  return;
+
+               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == range_ptr)
+                  return;
+
+               str1_range_ptr_ = &(range_ptr->range_ref());
+            }
+
+            initialised_ = str0_base_ptr_  &&
+                           str1_base_ptr_  &&
+                           str0_node_ptr_  &&
+                           str0_range_ptr_ &&
+                           str1_range_ptr_ ;
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               std::size_t s0_r0 = 0;
+               std::size_t s0_r1 = 0;
+
+               std::size_t s1_r0 = 0;
+               std::size_t s1_r1 = 0;
+
+               range_t& range0 = (*str0_range_ptr_);
+               range_t& range1 = (*str1_range_ptr_);
+
+               if (
+                    range0(s0_r0,s0_r1,str0_base_ptr_->size()) &&
+                    range1(s1_r0,s1_r1,str1_base_ptr_->size())
+                  )
+               {
+                  std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1;
+
+                  std::copy(str1_base_ptr_->base() + s1_r0,
+                            str1_base_ptr_->base() + s1_r0 + size,
+                            const_cast<char*>(base() + s0_r0));
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return str0_node_ptr_->str();
+         }
+
+         const char* base() const
+         {
+           return str0_node_ptr_->base();
+         }
+
+         std::size_t size() const
+         {
+            return str0_node_ptr_->size();
+         }
+
+         range_t& range_ref()
+         {
+            return str0_node_ptr_->range_ref();
+         }
+
+         const range_t& range_ref() const
+         {
+            return str0_node_ptr_->range_ref();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strass;
+         }
+
+      private:
+
+         bool            initialised_;
+         str_base_ptr    str0_base_ptr_;
+         str_base_ptr    str1_base_ptr_;
+         strvar_node_ptr str0_node_ptr_;
+         range_ptr       str0_range_ptr_;
+         range_ptr       str1_range_ptr_;
+      };
+
+      template <typename T>
+      class conditional_string_node : public trinary_node    <T>,
+                                      public string_base_node<T>,
+                                      public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>* expression_ptr;
+         typedef string_base_node<T>*   str_base_ptr;
+         typedef range_pack      <T>         range_t;
+         typedef range_t*                  range_ptr;
+         typedef range_interface<T>         irange_t;
+         typedef irange_t*                irange_ptr;
+
+         conditional_string_node(expression_ptr test,
+                                 expression_ptr consequent,
+                                 expression_ptr alternative)
+         : trinary_node<T>(details::e_default,consequent,alternative,test),
+           initialised_(false),
+           str0_base_ptr_ (0),
+           str1_base_ptr_ (0),
+           str0_range_ptr_(0),
+           str1_range_ptr_(0),
+           test_              (test),
+           consequent_  (consequent),
+           alternative_(alternative)
+         {
+            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+
+            range_.cache.first  = range_.n0_c.second;
+            range_.cache.second = range_.n1_c.second;
+
+            if (is_generally_string_node(trinary_node<T>::branch_[0].first))
+            {
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
+
+               if (0 == str0_base_ptr_)
+                  return;
+
+               str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
+
+               if (0 == str0_range_ptr_)
+                  return;
+            }
+
+            if (is_generally_string_node(trinary_node<T>::branch_[1].first))
+            {
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
+
+               if (0 == str1_base_ptr_)
+                  return;
+
+               str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
+
+               if (0 == str1_range_ptr_)
+                  return;
+            }
+
+            initialised_ = str0_base_ptr_  &&
+                           str1_base_ptr_  &&
+                           str0_range_ptr_ &&
+                           str1_range_ptr_ ;
+
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               std::size_t r0 = 0;
+               std::size_t r1 = 0;
+
+               if (is_true(test_))
+               {
+                  consequent_->value();
+
+                  range_t& range = str0_range_ptr_->range_ref();
+
+                  if (range(r0,r1,str0_base_ptr_->size()))
+                  {
+                     const std::size_t size = (r1 - r0) + 1;
+
+                     value_.assign(str0_base_ptr_->base() + r0, size);
+
+                     range_.n1_c.second  = value_.size() - 1;
+                     range_.cache.second = range_.n1_c.second;
+
+                     return T(1);
+                  }
+               }
+               else
+               {
+                  alternative_->value();
+
+                  range_t& range = str1_range_ptr_->range_ref();
+
+                  if (range(r0,r1,str1_base_ptr_->size()))
+                  {
+                     const std::size_t size = (r1 - r0) + 1;
+
+                     value_.assign(str1_base_ptr_->base() + r0, size);
+
+                     range_.n1_c.second  = value_.size() - 1;
+                     range_.cache.second = range_.n1_c.second;
+
+                     return T(0);
+                  }
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return value_;
+         }
+
+         const char* base() const
+         {
+           return value_.data();
+         }
+
+         std::size_t size() const
+         {
+            return value_.size();
+         }
+
+         range_t& range_ref()
+         {
+            return range_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return range_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strcondition;
+         }
+
+      private:
+
+         bool initialised_;
+         str_base_ptr str0_base_ptr_;
+         str_base_ptr str1_base_ptr_;
+         irange_ptr   str0_range_ptr_;
+         irange_ptr   str1_range_ptr_;
+         mutable range_t     range_;
+         mutable std::string value_;
+
+         expression_ptr test_;
+         expression_ptr consequent_;
+         expression_ptr alternative_;
+      };
+
+      template <typename T>
+      class cons_conditional_str_node : public binary_node     <T>,
+                                        public string_base_node<T>,
+                                        public range_interface <T>
+      {
+      public:
+
+         typedef expression_node <T>* expression_ptr;
+         typedef string_base_node<T>*   str_base_ptr;
+         typedef range_pack      <T>         range_t;
+         typedef range_t*                  range_ptr;
+         typedef range_interface<T>         irange_t;
+         typedef irange_t*                irange_ptr;
+
+         cons_conditional_str_node(expression_ptr test,
+                                   expression_ptr consequent)
+         : binary_node<T>(details::e_default,consequent,test),
+           initialised_(false),
+           str0_base_ptr_ (0),
+           str0_range_ptr_(0),
+           test_      (test),
+           consequent_(consequent)
+         {
+            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+
+            range_.cache.first  = range_.n0_c.second;
+            range_.cache.second = range_.n1_c.second;
+
+            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            {
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+
+               if (0 == str0_base_ptr_)
+                  return;
+
+               str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+
+               if (0 == str0_range_ptr_)
+                  return;
+            }
+
+            initialised_ = str0_base_ptr_ && str0_range_ptr_ ;
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               std::size_t r0 = 0;
+               std::size_t r1 = 0;
+
+               if (is_true(test_))
+               {
+                  consequent_->value();
+
+                  range_t& range = str0_range_ptr_->range_ref();
+
+                  if (range(r0,r1,str0_base_ptr_->size()))
+                  {
+                     const std::size_t size = (r1 - r0) + 1;
+
+                     value_.assign(str0_base_ptr_->base() + r0, size);
+
+                     range_.n1_c.second  = value_.size() - 1;
+                     range_.cache.second = range_.n1_c.second;
+
+                     return T(1);
+                  }
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         std::string str() const
+         {
+            return value_;
+         }
+
+         const char* base() const
+         {
+           return value_.data();
+         }
+
+         std::size_t size() const
+         {
+            return value_.size();
+         }
+
+         range_t& range_ref()
+         {
+            return range_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return range_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strccondition;
+         }
+
+      private:
+
+         bool initialised_;
+         str_base_ptr str0_base_ptr_;
+         irange_ptr   str0_range_ptr_;
+         mutable range_t     range_;
+         mutable std::string value_;
+
+         expression_ptr test_;
+         expression_ptr consequent_;
+      };
+      #endif
+
+      template <typename T, std::size_t N>
+      inline T axn(T a, T x)
+      {
+         // a*x^n
+         return a * exprtk::details::numeric::fast_exp<T,N>::result(x);
+      }
+
+      template <typename T, std::size_t N>
+      inline T axnb(T a, T x, T b)
+      {
+         // a*x^n+b
+         return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b;
+      }
+
+      template <typename T>
+      struct sf_base
+      {
+         typedef typename details::functor_t<T>::Type Type;
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::qfunc_t quaternary_functor_t;
+         typedef typename functor_t::tfunc_t    trinary_functor_t;
+         typedef typename functor_t::bfunc_t     binary_functor_t;
+         typedef typename functor_t::ufunc_t      unary_functor_t;
+      };
+
+      #define define_sfop3(NN,OP0,OP1)                   \
+      template <typename T>                              \
+      struct sf##NN##_op : public sf_base<T>             \
+      {                                                  \
+         typedef typename sf_base<T>::Type Type;         \
+         static inline T process(Type x, Type y, Type z) \
+         {                                               \
+            return (OP0);                                \
+         }                                               \
+         static inline std::string id()                  \
+         {                                               \
+            return OP1;                                  \
+         }                                               \
+      };                                                 \
+
+      define_sfop3(00,(x + y) / z       ,"(t+t)/t")
+      define_sfop3(01,(x + y) * z       ,"(t+t)*t")
+      define_sfop3(02,(x + y) - z       ,"(t+t)-t")
+      define_sfop3(03,(x + y) + z       ,"(t+t)+t")
+      define_sfop3(04,(x - y) + z       ,"(t-t)+t")
+      define_sfop3(05,(x - y) / z       ,"(t-t)/t")
+      define_sfop3(06,(x - y) * z       ,"(t-t)*t")
+      define_sfop3(07,(x * y) + z       ,"(t*t)+t")
+      define_sfop3(08,(x * y) - z       ,"(t*t)-t")
+      define_sfop3(09,(x * y) / z       ,"(t*t)/t")
+      define_sfop3(10,(x * y) * z       ,"(t*t)*t")
+      define_sfop3(11,(x / y) + z       ,"(t/t)+t")
+      define_sfop3(12,(x / y) - z       ,"(t/t)-t")
+      define_sfop3(13,(x / y) / z       ,"(t/t)/t")
+      define_sfop3(14,(x / y) * z       ,"(t/t)*t")
+      define_sfop3(15,x / (y + z)       ,"t/(t+t)")
+      define_sfop3(16,x / (y - z)       ,"t/(t-t)")
+      define_sfop3(17,x / (y * z)       ,"t/(t*t)")
+      define_sfop3(18,x / (y / z)       ,"t/(t/t)")
+      define_sfop3(19,x * (y + z)       ,"t*(t+t)")
+      define_sfop3(20,x * (y - z)       ,"t*(t-t)")
+      define_sfop3(21,x * (y * z)       ,"t*(t*t)")
+      define_sfop3(22,x * (y / z)       ,"t*(t/t)")
+      define_sfop3(23,x - (y + z)       ,"t-(t+t)")
+      define_sfop3(24,x - (y - z)       ,"t-(t-t)")
+      define_sfop3(25,x - (y / z)       ,"t-(t/t)")
+      define_sfop3(26,x - (y * z)       ,"t-(t*t)")
+      define_sfop3(27,x + (y * z)       ,"t+(t*t)")
+      define_sfop3(28,x + (y / z)       ,"t+(t/t)")
+      define_sfop3(29,x + (y + z)       ,"t+(t+t)")
+      define_sfop3(30,x + (y - z)       ,"t+(t-t)")
+      define_sfop3(31,(axnb<T,2>(x,y,z)),"       ")
+      define_sfop3(32,(axnb<T,3>(x,y,z)),"       ")
+      define_sfop3(33,(axnb<T,4>(x,y,z)),"       ")
+      define_sfop3(34,(axnb<T,5>(x,y,z)),"       ")
+      define_sfop3(35,(axnb<T,6>(x,y,z)),"       ")
+      define_sfop3(36,(axnb<T,7>(x,y,z)),"       ")
+      define_sfop3(37,(axnb<T,8>(x,y,z)),"       ")
+      define_sfop3(38,(axnb<T,9>(x,y,z)),"       ")
+      define_sfop3(39,x * numeric::log(y)   + z,"")
+      define_sfop3(40,x * numeric::log(y)   - z,"")
+      define_sfop3(41,x * numeric::log10(y) + z,"")
+      define_sfop3(42,x * numeric::log10(y) - z,"")
+      define_sfop3(43,x * numeric::sin(y) + z  ,"")
+      define_sfop3(44,x * numeric::sin(y) - z  ,"")
+      define_sfop3(45,x * numeric::cos(y) + z  ,"")
+      define_sfop3(46,x * numeric::cos(y) - z  ,"")
+      define_sfop3(47,details::is_true(x) ? y : z,"")
+
+      #define define_sfop4(NN,OP0,OP1)                           \
+      template <typename T>                                      \
+      struct sf##NN##_op : public sf_base<T>                     \
+      {                                                          \
+         typedef typename sf_base<T>::Type Type;                 \
+         static inline T process(Type x, Type y, Type z, Type w) \
+         {                                                       \
+            return (OP0);                                        \
+         }                                                       \
+         static inline std::string id() { return OP1; }          \
+      };                                                         \
+
+      define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
+      define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
+      define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
+      define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
+      define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
+      define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
+      define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
+      define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
+      define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
+      define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
+      define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
+      define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
+      define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
+      define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
+      define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
+      define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
+      define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
+      define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
+      define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
+      define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
+      define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
+      define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
+      define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
+      define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
+      define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
+      define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
+      define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
+      define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
+      define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
+      define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
+      define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
+      define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
+      define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
+      define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
+      define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
+      define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
+
+      define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
+      define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
+      define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
+      define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
+      define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
+      define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
+      define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
+      define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
+      define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
+      define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
+      define_sfop4(94,((x <  y) ? z : w),"")
+      define_sfop4(95,((x <= y) ? z : w),"")
+      define_sfop4(96,((x >  y) ? z : w),"")
+      define_sfop4(97,((x >= y) ? z : w),"")
+      define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
+      define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
+
+      define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
+      define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
+      define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
+      define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
+      define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
+      define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
+      define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
+      define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
+      define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
+      define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
+      define_sfop4(ext10,((x + y) * (z - w)),"(t+t)*(t-t)")
+      define_sfop4(ext11,((x + y) / (z - w)),"(t+t)/(t-t)")
+      define_sfop4(ext12,((x - y) - (z + w)),"(t-t)-(t+t)")
+      define_sfop4(ext13,((x - y) + (z + w)),"(t-t)+(t+t)")
+      define_sfop4(ext14,((x - y) * (z + w)),"(t-t)*(t+t)")
+      define_sfop4(ext15,((x - y) / (z + w)),"(t-t)/(t+t)")
+      define_sfop4(ext16,((x * y) - (z + w)),"(t*t)-(t+t)")
+      define_sfop4(ext17,((x / y) - (z + w)),"(t/t)-(t+t)")
+      define_sfop4(ext18,((x * y) + (z + w)),"(t*t)+(t+t)")
+      define_sfop4(ext19,((x / y) + (z + w)),"(t/t)+(t+t)")
+      define_sfop4(ext20,((x * y) + (z - w)),"(t*t)+(t-t)")
+      define_sfop4(ext21,((x / y) + (z - w)),"(t/t)+(t-t)")
+      define_sfop4(ext22,((x * y) - (z - w)),"(t*t)-(t-t)")
+      define_sfop4(ext23,((x / y) - (z - w)),"(t/t)-(t-t)")
+      define_sfop4(ext24,((x + y) * (z * w)),"(t+t)*(t*t)")
+      define_sfop4(ext25,((x + y) * (z / w)),"(t+t)*(t/t)")
+      define_sfop4(ext26,((x + y) / (z * w)),"(t+t)/(t*t)")
+      define_sfop4(ext27,((x + y) / (z / w)),"(t+t)/(t/t)")
+      define_sfop4(ext28,((x - y) / (z * w)),"(t-t)/(t*t)")
+      define_sfop4(ext29,((x - y) / (z / w)),"(t-t)/(t/t)")
+      define_sfop4(ext30,((x - y) * (z * w)),"(t-t)*(t*t)")
+      define_sfop4(ext31,((x - y) * (z / w)),"(t-t)*(t/t)")
+      define_sfop4(ext32,((x * y) * (z + w)),"(t*t)*(t+t)")
+      define_sfop4(ext33,((x / y) * (z + w)),"(t/t)*(t+t)")
+      define_sfop4(ext34,((x * y) / (z + w)),"(t*t)/(t+t)")
+      define_sfop4(ext35,((x / y) / (z + w)),"(t/t)/(t+t)")
+      define_sfop4(ext36,((x * y) / (z - w)),"(t*t)/(t-t)")
+      define_sfop4(ext37,((x / y) / (z - w)),"(t/t)/(t-t)")
+      define_sfop4(ext38,((x * y) * (z - w)),"(t*t)*(t-t)")
+      define_sfop4(ext39,((x * y) / (z * w)),"(t*t)/(t*t)")
+      define_sfop4(ext40,((x / y) * (z / w)),"(t/t)*(t/t)")
+      define_sfop4(ext41,((x / y) * (z - w)),"(t/t)*(t-t)")
+      define_sfop4(ext42,((x * y) * (z * w)),"(t*t)*(t*t)")
+      define_sfop4(ext43,(x + (y * (z / w))),"t+(t*(t/t))")
+      define_sfop4(ext44,(x - (y * (z / w))),"t-(t*(t/t))")
+      define_sfop4(ext45,(x + (y / (z * w))),"t+(t/(t*t))")
+      define_sfop4(ext46,(x - (y / (z * w))),"t-(t/(t*t))")
+      define_sfop4(ext47,(((x - y) - z) * w),"((t-t)-t)*t")
+      define_sfop4(ext48,(((x - y) - z) / w),"((t-t)-t)/t")
+      define_sfop4(ext49,(((x - y) + z) * w),"((t-t)+t)*t")
+      define_sfop4(ext50,(((x - y) + z) / w),"((t-t)+t)/t")
+      define_sfop4(ext51,((x + (y - z)) * w),"(t+(t-t))*t")
+      define_sfop4(ext52,((x + (y - z)) / w),"(t+(t-t))/t")
+      define_sfop4(ext53,((x + y) / (z + w)),"(t+t)/(t+t)")
+      define_sfop4(ext54,((x - y) / (z - w)),"(t-t)/(t-t)")
+      define_sfop4(ext55,((x + y) * (z + w)),"(t+t)*(t+t)")
+      define_sfop4(ext56,((x - y) * (z - w)),"(t-t)*(t-t)")
+      define_sfop4(ext57,((x - y) + (z - w)),"(t-t)+(t-t)")
+      define_sfop4(ext58,((x - y) - (z - w)),"(t-t)-(t-t)")
+      define_sfop4(ext59,((x / y) + (z * w)),"(t/t)+(t*t)")
+      define_sfop4(ext60,(((x * y) * z) / w),"((t*t)*t)/t")
+
+      #undef define_sfop3
+      #undef define_sfop4
+
+      template <typename T, typename SpecialFunction>
+      class sf3_node : public trinary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         sf3_node(const operator_type& opr,
+                  expression_ptr branch0,
+                  expression_ptr branch1,
+                  expression_ptr branch2)
+         : trinary_node<T>(opr,branch0,branch1,branch2)
+         {}
+
+         inline T value() const
+         {
+            const T x = trinary_node<T>::branch_[0].first->value();
+            const T y = trinary_node<T>::branch_[1].first->value();
+            const T z = trinary_node<T>::branch_[2].first->value();
+
+            return SpecialFunction::process(x,y,z);
+         }
+      };
+
+      template <typename T, typename SpecialFunction>
+      class sf4_node : public quaternary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         sf4_node(const operator_type& opr,
+                  expression_ptr branch0,
+                  expression_ptr branch1,
+                  expression_ptr branch2,
+                  expression_ptr branch3)
+         : quaternary_node<T>(opr,branch0,branch1,branch2,branch3)
+         {}
+
+         inline T value() const
+         {
+            const T x = quaternary_node<T>::branch_[0].first->value();
+            const T y = quaternary_node<T>::branch_[1].first->value();
+            const T z = quaternary_node<T>::branch_[2].first->value();
+            const T w = quaternary_node<T>::branch_[3].first->value();
+
+            return SpecialFunction::process(x,y,z,w);
+         }
+      };
+
+      template <typename T, typename SpecialFunction>
+      class sf3_var_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         sf3_var_node(const T& v0, const T& v1, const T& v2)
+         : v0_(v0),
+           v1_(v1),
+           v2_(v2)
+         {}
+
+         inline T value() const
+         {
+            return SpecialFunction::process(v0_,v1_,v2_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_trinary;
+         }
+
+      private:
+
+         sf3_var_node(sf3_var_node<T,SpecialFunction>&);
+         sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&);
+
+         const T& v0_;
+         const T& v1_;
+         const T& v2_;
+      };
+
+      template <typename T, typename SpecialFunction>
+      class sf4_var_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
+         : v0_(v0),
+           v1_(v1),
+           v2_(v2),
+           v3_(v3)
+         {}
+
+         inline T value() const
+         {
+            return SpecialFunction::process(v0_,v1_,v2_,v3_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_trinary;
+         }
+
+      private:
+
+         sf4_var_node(sf4_var_node<T,SpecialFunction>&);
+         sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&);
+
+         const T& v0_;
+         const T& v1_;
+         const T& v2_;
+         const T& v3_;
+      };
+
+      template <typename T, typename VarArgFunction>
+      class vararg_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
+         {
+            arg_list_.resize(arg_list.size());
+            delete_branch_.resize(arg_list.size());
+
+            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            {
+               if (arg_list[i])
+               {
+                       arg_list_[i] = arg_list[i];
+                  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
+               }
+               else
+               {
+                  arg_list_.clear();
+                  delete_branch_.clear();
+                  return;
+               }
+            }
+         }
+
+        ~vararg_node()
+         {
+            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            {
+               if (arg_list_[i] && delete_branch_[i])
+               {
+                  delete arg_list_[i];
+                  arg_list_[i] = 0;
+               }
+            }
+         }
+
+         inline T value() const
+         {
+            if (!arg_list_.empty())
+               return VarArgFunction::process(arg_list_);
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vararg;
+         }
+
+      private:
+
+         std::vector<expression_ptr> arg_list_;
+         std::vector<unsigned char> delete_branch_;
+      };
+
+      template <typename T, typename VarArgFunction>
+      class vararg_varnode : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
+         {
+            arg_list_.resize(arg_list.size());
+
+            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            {
+               if (arg_list[i] && is_variable_node(arg_list[i]))
+               {
+                  variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
+                  arg_list_[i] = (&var_node_ptr->ref());
+               }
+               else
+               {
+                  arg_list_.clear();
+                  return;
+               }
+            }
+         }
+
+         inline T value() const
+         {
+            if (!arg_list_.empty())
+               return VarArgFunction::process(arg_list_);
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vararg;
+         }
+
+      private:
+
+         std::vector<const T*> arg_list_;
+      };
+
+      template <typename T, typename VecFunction>
+      class vectorize_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vectorize_node(const expression_ptr v)
+         : ivec_ptr_(0),
+           v_(v),
+           v_deletable_(branch_deletable(v_))
+         {
+            if (is_ivector_node(v))
+            {
+               ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
+            }
+            else
+               ivec_ptr_ = 0;
+         }
+
+        ~vectorize_node()
+         {
+            if (v_ && v_deletable_)
+            {
+               delete v_;
+            }
+         }
+
+         inline T value() const
+         {
+            if (ivec_ptr_)
+            {
+               v_->value();
+               return VecFunction::process(ivec_ptr_);
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecfunc;
+         }
+
+      private:
+
+         vector_interface<T>* ivec_ptr_;
+         expression_ptr v_;
+         bool v_deletable_;
+      };
+
+      template <typename T>
+      class assignment_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         assignment_node(const operator_type& opr,
+                         expression_ptr branch0,
+                         expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           var_node_ptr_(0)
+         {
+            if (is_variable_node(binary_node<T>::branch_[0].first))
+            {
+               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+            }
+         }
+
+         inline T value() const
+         {
+            if (var_node_ptr_)
+            {
+               T& result = var_node_ptr_->ref();
+               result = binary_node<T>::branch_[1].first->value();
+
+               return result;
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+      private:
+
+         variable_node<T>* var_node_ptr_;
+      };
+
+      template <typename T>
+      class assignment_vec_elem_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         assignment_vec_elem_node(const operator_type& opr,
+                                  expression_ptr branch0,
+                                  expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec_node_ptr_(0)
+         {
+            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            {
+               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+            }
+         }
+
+         inline T value() const
+         {
+            if (vec_node_ptr_)
+            {
+               T& result = vec_node_ptr_->ref();
+               result = binary_node<T>::branch_[1].first->value();
+
+               return result;
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+      private:
+
+         vector_elem_node<T>* vec_node_ptr_;
+      };
+
+      template <typename T>
+      class assignment_vec_node : public binary_node     <T>,
+                                  public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*    vector_node_ptr;
+
+         assignment_vec_node(const operator_type& opr,
+                             expression_ptr branch0,
+                             expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec_node_ptr_(0),
+           vec_size_    (0)
+         {
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_size_     = vec_node_ptr_->ref().size();
+            }
+         }
+
+         inline T value() const
+         {
+            if (vec_node_ptr_)
+            {
+               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
+               const T v = binary_node<T>::branch_[1].first->value();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  (*vec_hldr[i]) = v;
+               }
+
+               return vec_node_ptr_->value();
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvalass;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec_node_ptr_;
+         std::size_t     vec_size_;
+      };
+
+      template <typename T>
+      class assignment_vecvec_node : public binary_node     <T>,
+                                     public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         assignment_vecvec_node(const operator_type& opr,
+                                expression_ptr branch0,
+                                expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec0_node_ptr_(0),
+           vec1_node_ptr_(0),
+           vec_size_     (0),
+           initialised_(false)
+         {
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+            }
+
+            if (is_vector_node(binary_node<T>::branch_[1].first))
+            {
+               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               {
+                  vec1_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_ && vec1_node_ptr_)
+            {
+               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
+                                    vec1_node_ptr_->ref().size());
+
+               initialised_ = true;
+            }
+         }
+
+         inline T value() const
+         {
+            binary_node<T>::branch_[1].first->value();
+
+            if (initialised_)
+            {
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  (*vec0[i]) = (*vec1[i]);
+               }
+
+               return vec0_node_ptr_->value();
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec0_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec0_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvecass;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec0_node_ptr_;
+         vector_node<T>* vec1_node_ptr_;
+         std::size_t     vec_size_;
+         bool            initialised_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_op_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         assignment_op_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           var_node_ptr_(0)
+         {
+            if (is_variable_node(binary_node<T>::branch_[0].first))
+            {
+               var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
+            }
+         }
+
+         inline T value() const
+         {
+            if (var_node_ptr_)
+            {
+               T& v = var_node_ptr_->ref();
+               v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+
+               return v;
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+      private:
+
+         variable_node<T>* var_node_ptr_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_vec_elem_op_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         assignment_vec_elem_op_node(const operator_type& opr,
+                                     expression_ptr branch0,
+                                     expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec_node_ptr_(0)
+         {
+            if (is_vector_elem_node(binary_node<T>::branch_[0].first))
+            {
+               vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
+            }
+         }
+
+         inline T value() const
+         {
+            if (vec_node_ptr_)
+            {
+               T& v = vec_node_ptr_->ref();
+                  v = Operation::process(v,binary_node<T>::branch_[1].first->value());
+
+               return v;
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+      private:
+
+         vector_elem_node<T>* vec_node_ptr_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_vec_op_node : public binary_node     <T>,
+                                     public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         assignment_vec_op_node(const operator_type& opr,
+                                expression_ptr branch0,
+                                expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec_node_ptr_(0),
+           vec_size_    (0)
+         {
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vec_size_     = vec_node_ptr_->ref().size();
+            }
+         }
+
+         inline T value() const
+         {
+            if (vec_node_ptr_)
+            {
+               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
+               const T v = binary_node<T>::branch_[1].first->value();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  T& vec_i = *vec_hldr[i];
+                     vec_i = Operation::process(vec_i,v);
+               }
+
+               return vec_node_ptr_->value();
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecopvalass;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec_node_ptr_;
+         std::size_t     vec_size_;
+      };
+
+      template <typename T, typename Operation>
+      class assignment_vecvec_op_node : public binary_node     <T>,
+                                        public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         assignment_vecvec_op_node(const operator_type& opr,
+                                   expression_ptr branch0,
+                                   expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec0_node_ptr_(0),
+           vec1_node_ptr_(0),
+           vec_size_     (0),
+           initialised_(false)
+         {
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+            }
+
+            if (is_vector_node(binary_node<T>::branch_[1].first))
+            {
+               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               {
+                  vec1_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_ && vec1_node_ptr_)
+            {
+               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
+                                    vec1_node_ptr_->ref().size());
+
+               initialised_ = true;
+            }
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  T& vec0_i = *vec0[i];
+                  T& vec1_i = *vec1[i];
+                  vec0_i = Operation::process(vec0_i,vec1_i);
+               }
+
+               return vec0_node_ptr_->value();
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec0_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec0_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecopvecass;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec0_node_ptr_;
+         vector_node<T>* vec1_node_ptr_;
+         std::size_t     vec_size_;
+         bool            initialised_;
+      };
+
+      template <typename T, typename Operation>
+      class eqineq_vecvec_node : public binary_node     <T>,
+                                 public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*  expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         eqineq_vecvec_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec0_node_ptr_(0),
+           vec1_node_ptr_(0),
+           vec_size_     (0),
+           initialised_(false)
+         {
+
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               {
+                  vec0_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (is_vector_node(binary_node<T>::branch_[1].first))
+            {
+               vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               {
+                  vec1_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_ && vec1_node_ptr_)
+            {
+               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
+                                    vec1_node_ptr_->ref().size());
+
+               initialised_ = true;
+            }
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  if (std::equal_to<T>()(T(0),Operation::process(*vec0[i],*vec1[i])))
+                  {
+                     return T(0);
+                  }
+               }
+
+               return T(1);
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec0_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec0_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvecineq;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec0_node_ptr_;
+         vector_node<T>* vec1_node_ptr_;
+         std::size_t     vec_size_;
+         bool            initialised_;
+      };
+
+      template <typename T, typename Operation>
+      class eqineq_vecval_node : public binary_node     <T>,
+                                 public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*  expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         eqineq_vecval_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec_node_ptr_(0),
+           vec_size_    (0)
+         {
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               {
+                  vec_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec_node_ptr_)
+            {
+               vec_size_ = vec_node_ptr_->ref().size();
+            }
+         }
+
+         inline T value() const
+         {
+            if (vec_node_ptr_)
+            {
+                     binary_node<T>::branch_[0].first->value();
+               T v = binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  if (std::equal_to<T>()(T(0),Operation::process(*vec_hldr[i],v)))
+                  {
+                     return T(0);
+                  }
+               }
+
+               return T(1);
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvalineq;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec_node_ptr_;
+         std::size_t     vec_size_;
+      };
+
+      template <typename T, typename Operation>
+      class eqineq_valvec_node : public binary_node     <T>,
+                                 public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*  expression_ptr;
+         typedef vector_node<T>*     vector_node_ptr;
+
+         eqineq_valvec_node(const operator_type& opr,
+                            expression_ptr branch0,
+                            expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec_node_ptr_(0),
+           vec_size_    (0)
+         {
+            if (is_vector_node(binary_node<T>::branch_[1].first))
+            {
+               vec_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               {
+                  vec_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec_node_ptr_)
+            {
+               vec_size_ = vec_node_ptr_->ref().size();
+            }
+         }
+
+         inline T value() const
+         {
+            if (vec_node_ptr_)
+            {
+               T v = binary_node<T>::branch_[0].first->value();
+                     binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec_hldr = vec_node_ptr_->ref();
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  if (std::equal_to<T>()(T(0),Operation::process(v,*vec_hldr[i])))
+                  {
+                     return T(0);
+                  }
+               }
+
+               return T(1);
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return vec_node_ptr_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return vec_node_ptr_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_valvecineq;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node<T>* vec_node_ptr_;
+         std::size_t     vec_size_;
+      };
+
+      template <typename T, typename Operation>
+      class vecarith_vecvec_node : public binary_node     <T>,
+                                   public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*    expression_ptr;
+         typedef vector_node<T>*       vector_node_ptr;
+         typedef vector_holder<T>*   vector_holder_ptr;
+
+         vecarith_vecvec_node(const operator_type& opr,
+                              expression_ptr branch0,
+                              expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec0_node_ptr_(0),
+           vec1_node_ptr_(0),
+           vec_size_     (0),
+           data_         (0),
+           temp_         (0),
+           temp_vec_node_(0),
+           initialised_(false)
+         {
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               {
+                  vec0_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (is_vector_node(binary_node<T>::branch_[1].first))
+            {
+               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               {
+                  vec1_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_ && vec1_node_ptr_)
+            {
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
+
+               vec_size_      = std::min(vec0.size(),vec1.size());
+               data_          = new T[vec_size_];
+               temp_          = new vector_holder<T>(data_,vec_size_);
+               temp_vec_node_ = new vector_node<T>  (temp_);
+
+               initialised_ = true;
+            }
+         }
+
+        ~vecarith_vecvec_node()
+         {
+            delete[] data_;
+            delete   temp_;
+            delete   temp_vec_node_;
+         }
+
+         inline T value() const
+         {
+            if (initialised_)
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
+               vector_holder<T>& vec2 = *temp_;
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+
+                  T& vec0_i = *vec0[i];
+                  T& vec1_i = *vec1[i];
+                  T& vec2_i = *vec2[i];
+
+                  vec2_i = Operation::process(vec0_i,vec1_i);
+               }
+
+               return *vec2[0];
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return temp_vec_node_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return temp_vec_node_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvecarith;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node_ptr   vec0_node_ptr_;
+         vector_node_ptr   vec1_node_ptr_;
+         std::size_t       vec_size_;
+         T*                data_;
+         vector_holder_ptr temp_;
+         vector_node_ptr   temp_vec_node_;
+         bool              initialised_;
+      };
+
+      template <typename T, typename Operation>
+      class vecarith_vecval_node : public binary_node     <T>,
+                                   public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*    expression_ptr;
+         typedef vector_node<T>*       vector_node_ptr;
+         typedef vector_holder<T>*   vector_holder_ptr;
+
+         vecarith_vecval_node(const operator_type& opr,
+                              expression_ptr branch0,
+                              expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec0_node_ptr_(0),
+           vec_size_     (0),
+           data_         (0),
+           temp_         (0),
+           temp_vec_node_(0)
+         {
+            if (is_vector_node(binary_node<T>::branch_[0].first))
+            {
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[0].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
+               {
+                  vec0_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_)
+            {
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+
+               vec_size_      = vec0.size();
+               data_          = new T[vec_size_];
+               temp_          = new vector_holder<T>(data_,vec_size_);
+               temp_vec_node_ = new vector_node<T>  (temp_);
+            }
+         }
+
+        ~vecarith_vecval_node()
+         {
+            delete[] data_;
+            delete   temp_;
+            delete   temp_vec_node_;
+         }
+
+         inline T value() const
+         {
+            if (vec0_node_ptr_)
+            {
+                           binary_node<T>::branch_[0].first->value();
+               const T v = binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = *temp_;
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  T& vec0_i = *vec0[i];
+                  T& vec1_i = *vec1[i];
+
+                  vec1_i = Operation::process(vec0_i,v);
+               }
+
+               return *vec1[0];
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return temp_vec_node_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return temp_vec_node_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvalarith;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node_ptr   vec0_node_ptr_;
+         std::size_t       vec_size_;
+         T*                data_;
+         vector_holder_ptr temp_;
+         vector_node_ptr   temp_vec_node_;
+      };
+
+      template <typename T, typename Operation>
+      class vecarith_valvec_node : public binary_node     <T>,
+                                   public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*    expression_ptr;
+         typedef vector_node<T>*       vector_node_ptr;
+         typedef vector_holder<T>*   vector_holder_ptr;
+
+         vecarith_valvec_node(const operator_type& opr,
+                              expression_ptr branch0,
+                              expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           vec1_node_ptr_(0),
+           vec_size_     (0),
+           data_         (0),
+           temp_         (0),
+           temp_vec_node_(0)
+         {
+            if (is_vector_node(binary_node<T>::branch_[1].first))
+            {
+               vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
+            }
+            else if (is_ivector_node(binary_node<T>::branch_[1].first))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
+               {
+                  vec1_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec1_node_ptr_)
+            {
+               vector_holder<T>& vec0 = vec1_node_ptr_->ref();
+
+               vec_size_      = vec0.size();
+               data_          = new T[vec_size_];
+               temp_          = new vector_holder<T>(data_,vec_size_);
+               temp_vec_node_ = new vector_node<T>  (temp_);
+            }
+         }
+
+        ~vecarith_valvec_node()
+         {
+            delete[] data_;
+            delete   temp_;
+            delete   temp_vec_node_;
+         }
+
+         inline T value() const
+         {
+            if (vec1_node_ptr_)
+            {
+               const T v = binary_node<T>::branch_[0].first->value();
+                           binary_node<T>::branch_[1].first->value();
+
+               vector_holder<T>& vec1 = vec1_node_ptr_->ref();
+               vector_holder<T>& vec2 = *temp_;
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  T& vec1_i = *vec1[i];
+                  T& vec2_i = *vec2[i];
+
+                  vec2_i = Operation::process(v,vec1_i);
+               }
+
+               return *vec2[0];
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return temp_vec_node_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return temp_vec_node_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecvalarith;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node_ptr   vec1_node_ptr_;
+         std::size_t       vec_size_;
+         T*                data_;
+         vector_holder_ptr temp_;
+         vector_node_ptr   temp_vec_node_;
+      };
+
+      template <typename T, typename Operation>
+      class unary_vector_node : public unary_node      <T>,
+                                public vector_interface<T>
+      {
+      public:
+
+         typedef expression_node<T>*    expression_ptr;
+         typedef vector_node<T>*       vector_node_ptr;
+         typedef vector_holder<T>*   vector_holder_ptr;
+
+         unary_vector_node(const operator_type& opr, expression_ptr branch0)
+         : unary_node<T>(opr,branch0),
+           vec0_node_ptr_(0),
+           vec_size_     (0),
+           data_         (0),
+           temp_         (0),
+           temp_vec_node_(0)
+         {
+            if (is_vector_node(unary_node<T>::branch_))
+            {
+               vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
+            }
+            else if (is_ivector_node(unary_node<T>::branch_))
+            {
+               vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+               if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
+               {
+                  vec0_node_ptr_ = vi->vec();
+               }
+            }
+
+            if (vec0_node_ptr_)
+            {
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+
+               vec_size_      = vec0.size();
+               data_          = new T[vec_size_];
+               temp_          = new vector_holder<T>(data_,vec_size_);
+               temp_vec_node_ = new vector_node<T>  (temp_);
+            }
+         }
+
+        ~unary_vector_node()
+         {
+            delete[] data_;
+            delete   temp_;
+            delete   temp_vec_node_;
+         }
+
+         inline T value() const
+         {
+            unary_node<T>::branch_->value();
+
+            if (vec0_node_ptr_)
+            {
+               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               vector_holder<T>& vec1 = *temp_;
+
+               for (std::size_t i = 0; i < vec_size_; ++i)
+               {
+                  T& vec0_i = *vec0[i];
+                  T& vec1_i = *vec1[i];
+
+                  vec1_i = Operation::process(vec0_i);
+               }
+
+               return *vec1[0];
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         vector_node_ptr vec() const
+         {
+            return temp_vec_node_;
+         }
+
+         vector_node_ptr vec()
+         {
+            return temp_vec_node_;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vecunaryop;
+         }
+
+         std::size_t size() const
+         {
+            return vec_size_;
+         }
+
+      private:
+
+         vector_node_ptr   vec0_node_ptr_;
+         std::size_t       vec_size_;
+         T*                data_;
+         vector_holder_ptr temp_;
+         vector_node_ptr   temp_vec_node_;
+      };
+
+      template <typename T>
+      class scand_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         scand_node(const operator_type& opr,
+                    expression_ptr branch0,
+                    expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1)
+         {}
+
+         inline T value() const
+         {
+            return (
+                     std::not_equal_to<T>()
+                        (T(0),binary_node<T>::branch_[0].first->value()) &&
+                     std::not_equal_to<T>()
+                        (T(0),binary_node<T>::branch_[1].first->value())
+                   ) ? T(1) : T(0);
+         }
+      };
+
+      template <typename T>
+      class scor_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         scor_node(const operator_type& opr,
+                   expression_ptr branch0,
+                   expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1)
+         {}
+
+         inline T value() const
+         {
+            return (
+                     std::not_equal_to<T>()
+                        (T(0),binary_node<T>::branch_[0].first->value()) ||
+                     std::not_equal_to<T>()
+                        (T(0),binary_node<T>::branch_[1].first->value())
+                   ) ? T(1) : T(0);
+         }
+      };
+
+      template <typename T, typename IFunction, std::size_t N>
+      class function_N_node : public expression_node<T>
+      {
+      public:
+
+         // Function of N paramters.
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef IFunction ifunction;
+
+         function_N_node(ifunction* func)
+         : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
+           parameter_count_(func->param_count)
+         {}
+
+        ~function_N_node()
+         {
+            cleanup_branches::execute<T,N>(branch_);
+         }
+
+         template <std::size_t NumBranches>
+         bool init_branches(expression_ptr (&b)[NumBranches])
+         {
+            // Needed for incompetent and broken msvc compiler versions
+            #ifdef _MSC_VER
+             #pragma warning(push)
+             #pragma warning(disable: 4127)
+            #endif
+            if (N != NumBranches)
+               return false;
+            else
+            {
+               for (std::size_t i = 0; i < NumBranches; ++i)
+               {
+                  if (b[i])
+                     branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
+                  else
+                     return false;
+               }
+               return true;
+            }
+            #ifdef _MSC_VER
+             #pragma warning(pop)
+            #endif
+         }
+
+         inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
+         {
+            return this < (&fn);
+         }
+
+         inline T value() const
+         {
+            // Needed for incompetent and broken msvc compiler versions
+            #ifdef _MSC_VER
+             #pragma warning(push)
+             #pragma warning(disable: 4127)
+            #endif
+            if ((0 == function_) || (0 == N))
+               return std::numeric_limits<T>::quiet_NaN();
+            else
+            {
+               T v[N];
+               evaluate_branches<T,N>::execute(v,branch_);
+               return invoke<T,N>::execute(*function_,v);
+            }
+            #ifdef _MSC_VER
+             #pragma warning(pop)
+            #endif
+         }
+
+         template <typename T_, std::size_t BranchCount>
+         struct evaluate_branches
+         {
+            static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
+            {
+               for (std::size_t i = 0; i < BranchCount; ++i)
+               {
+                  v[i] = b[i].first->value();
+               }
+            }
+         };
+
+         template <typename T_>
+         struct evaluate_branches <T_,5>
+         {
+            static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
+            {
+               v[0] = b[0].first->value();
+               v[1] = b[1].first->value();
+               v[2] = b[2].first->value();
+               v[3] = b[3].first->value();
+               v[4] = b[4].first->value();
+            }
+         };
+
+         template <typename T_>
+         struct evaluate_branches <T_,4>
+         {
+            static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
+            {
+               v[0] = b[0].first->value();
+               v[1] = b[1].first->value();
+               v[2] = b[2].first->value();
+               v[3] = b[3].first->value();
+            }
+         };
+
+         template <typename T_>
+         struct evaluate_branches <T_,3>
+         {
+            static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
+            {
+               v[0] = b[0].first->value();
+               v[1] = b[1].first->value();
+               v[2] = b[2].first->value();
+            }
+         };
+
+         template <typename T_>
+         struct evaluate_branches <T_,2>
+         {
+            static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
+            {
+               v[0] = b[0].first->value();
+               v[1] = b[1].first->value();
+            }
+         };
+
+         template <typename T_>
+         struct evaluate_branches <T_,1>
+         {
+            static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
+            {
+               v[0] = b[0].first->value();
+            }
+         };
+
+         template <typename T_, std::size_t ParamCount>
+         struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
+
+         template <typename T_>
+         struct invoke<T_,20>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[20])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,19>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[19])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,18>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[18])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,17>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[17])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,16>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[16])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,15>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[15])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,14>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[14])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,13>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[13])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,12>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[12])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,11>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[11])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,10>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[10])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,9>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[9])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,8>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[8])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,7>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[7])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,6>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[6])
+            { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,5>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[5])
+            { return f(v[0],v[1],v[2],v[3],v[4]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,4>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[4])
+            { return f(v[0],v[1],v[2],v[3]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,3>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[3])
+            { return f(v[0],v[1],v[2]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,2>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[2])
+            { return f(v[0],v[1]); }
+         };
+
+         template <typename T_>
+         struct invoke<T_,1>
+         {
+            static inline T_ execute(ifunction& f, T_ (&v)[1])
+            { return f(v[0]); }
+         };
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_function;
+         }
+
+      private:
+
+         ifunction* function_;
+         std::size_t parameter_count_;
+         branch_t branch_[N];
+      };
+
+      template <typename T, typename IFunction>
+      class function_N_node<T,IFunction,0> : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef IFunction ifunction;
+
+         function_N_node(ifunction* func)
+         : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
+         {}
+
+         inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
+         {
+            return this < (&fn);
+         }
+
+         inline T value() const
+         {
+            if (function_)
+               return (*function_)();
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_function;
+         }
+
+      private:
+
+         ifunction* function_;
+      };
+
+      template <typename T, typename VarArgFunction>
+      class vararg_function_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+
+         vararg_function_node(VarArgFunction*  func,
+                              const std::vector<expression_ptr>& arg_list)
+         : function_(func),
+           arg_list_(arg_list)
+         {
+            value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
+         }
+
+        ~vararg_function_node()
+         {
+            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            {
+               if (arg_list_[i] && !details::is_variable_node(arg_list_[i]))
+               {
+                  delete arg_list_[i];
+                  arg_list_[i] = 0;
+               }
+            }
+         }
+
+         inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
+         {
+            return this < (&fn);
+         }
+
+         inline T value() const
+         {
+            if (function_)
+            {
+               populate_value_list();
+               return (*function_)(value_list_);
+            }
+            else
+               return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_vafunction;
+         }
+
+      private:
+
+         inline void populate_value_list() const
+         {
+            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            {
+               value_list_[i] = arg_list_[i]->value();
+            }
+         }
+
+         VarArgFunction* function_;
+         std::vector<expression_ptr> arg_list_;
+         mutable std::vector<T> value_list_;
+      };
+
+      template <typename T, typename GenericFunction>
+      class generic_function_node : public expression_node<T>
+      {
+      public:
+
+         typedef type_store<T>                      type_store_t;
+         typedef expression_node<T>*              expression_ptr;
+         typedef variable_node<T>                variable_node_t;
+         typedef vector_elem_node<T>          vector_elem_node_t;
+         typedef vector_node<T>                    vector_node_t;
+         typedef variable_node_t*            variable_node_ptr_t;
+         typedef vector_elem_node_t*      vector_elem_node_ptr_t;
+         typedef vector_node_t*                vector_node_ptr_t;
+         typedef range_interface<T>            range_interface_t;
+         typedef range_data_type<T>            range_data_type_t;
+         typedef range_pack<T>                           range_t;
+         typedef std::pair<expression_ptr,bool>         branch_t;
+         typedef std::pair<void*,std::size_t>             void_t;
+         typedef std::vector<T>                         tmp_vs_t;
+         typedef std::vector<type_store_t>      typestore_list_t;
+         typedef std::vector<range_data_type_t>     range_list_t;
+
+         generic_function_node(const std::vector<expression_ptr>& arg_list,
+                               GenericFunction* func = (GenericFunction*)(0))
+         : function_(func),
+           arg_list_(arg_list)
+         {}
+
+         virtual ~generic_function_node()
+         {
+            cleanup_branches::execute(branch_);
+         }
+
+         virtual bool init_branches()
+         {
+            expr_as_vec1_store_.resize(arg_list_.size(),T(0)               );
+            typestore_list_    .resize(arg_list_.size(),type_store_t()     );
+            range_list_        .resize(arg_list_.size(),range_data_type_t());
+            branch_            .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
+
+            for (std::size_t i = 0; i < arg_list_.size(); ++i)
+            {
+               type_store_t& ts = typestore_list_[i];
+
+               if (0 == arg_list_[i])
+                  return false;
+               else if (is_ivector_node(arg_list_[i]))
+               {
+                  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
+
+                  if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
+                     return false;
+
+                  ts.size = vi->size();
+                  ts.data = vi->vec()->ref()[0];
+                  ts.type = type_store_t::e_vector;
+               }
+               else if (is_generally_string_node(arg_list_[i]))
+               {
+                  string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
+
+                  if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
+                     return false;
+
+                  ts.size = sbn->size();
+                  ts.data = reinterpret_cast<void*>(const_cast<char*>(sbn->base()));
+                  ts.type = type_store_t::e_string;
+
+                  range_list_[i].data      = ts.data;
+                  range_list_[i].size      = ts.size;
+                  range_list_[i].type_size = sizeof(char);
+                  range_list_[i].str_node  = sbn;
+
+                  range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
+
+                  if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
+                     return false;
+
+                  range_t& rp = ri->range_ref();
+
+                  if (
+                       rp.const_range() &&
+                       is_const_string_range_node(arg_list_[i])
+                     )
+                  {
+                     ts.size = rp.const_size();
+                     ts.data = static_cast<char*>(ts.data) + rp.n0_c.second;
+                     range_list_[i].range = reinterpret_cast<range_t*>(0);
+                  }
+                  else
+                     range_list_[i].range = &(ri->range_ref());
+               }
+               else if (is_variable_node(arg_list_[i]))
+               {
+                  variable_node_ptr_t var = variable_node_ptr_t(0);
+
+                  if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
+                     return false;
+
+                  ts.size = 1;
+                  ts.data = &var->ref();
+                  ts.type = type_store_t::e_scalar;
+               }
+               else if (is_vector_elem_node(arg_list_[i]))
+               {
+                  vector_elem_node_ptr_t var = vector_elem_node_ptr_t(0);
+
+                  if (0 == (var = dynamic_cast<vector_elem_node_ptr_t>(arg_list_[i])))
+                     return false;
+
+                  ts.size = 1;
+                  ts.data = reinterpret_cast<void*>(&var->ref());
+                  ts.type = type_store_t::e_scalar;
+               }
+               else
+               {
+                  ts.size = 1;
+                  ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
+                  ts.type = type_store_t::e_scalar;
+               }
+
+               branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
+            }
+
+            return true;
+         }
+
+         inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
+         {
+            return this < (&fn);
+         }
+
+         inline T value() const
+         {
+            if (function_)
+            {
+               if (populate_value_list())
+               {
+                  typedef typename GenericFunction::parameter_list_t parameter_list_t;
+
+                  return (*function_)(parameter_list_t(typestore_list_));
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_genfunction;
+         }
+
+      protected:
+
+         inline virtual bool populate_value_list() const
+         {
+            for (std::size_t i = 0; i < branch_.size(); ++i)
+            {
+               expr_as_vec1_store_[i] = branch_[i].first->value();
+            }
+
+            for (std::size_t i = 0; i < branch_.size(); ++i)
+            {
+               range_data_type_t& rdt = range_list_[i];
+
+               if (rdt.range)
+               {
+                  range_t&    rp = (*rdt.range);
+                  std::size_t r0 = 0;
+                  std::size_t r1 = 0;
+
+                  if (rp(r0,r1,rdt.size))
+                  {
+                     type_store_t& ts = typestore_list_[i];
+
+                     ts.size = rp.cache_size();
+
+                     if (ts.type == type_store_t::e_string)
+                        ts.data = const_cast<char*>(rdt.str_node->base()) + rp.cache.first;
+                     else
+                        ts.data = static_cast<char*>(rdt.data) + (rp.cache.first * rdt.type_size);
+                  }
+                  else
+                     return false;
+               }
+            }
+
+            return true;
+         }
+
+         GenericFunction* function_;
+         mutable typestore_list_t typestore_list_;
+
+      private:
+
+         std::vector<expression_ptr> arg_list_;
+         std::vector<branch_t> branch_;
+         mutable tmp_vs_t expr_as_vec1_store_;
+         mutable range_list_t range_list_;
+      };
+
+      template <typename T, typename StringFunction>
+      class string_function_node : public generic_function_node<T,StringFunction>,
+                                   public string_base_node<T>,
+                                   public range_interface <T>
+      {
+      public:
+
+         typedef generic_function_node<T,StringFunction> gen_function_t;
+         typedef range_pack<T> range_t;
+
+         string_function_node(StringFunction* func,
+                              const std::vector<typename gen_function_t::expression_ptr>& arg_list)
+         : gen_function_t(arg_list,func)
+         {
+            range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
+            range_.cache.first  = range_.n0_c.second;
+            range_.cache.second = range_.n1_c.second;
+         }
+
+         inline bool operator <(const string_function_node<T,StringFunction>& fn) const
+         {
+            return this < (&fn);
+         }
+
+         inline T value() const
+         {
+            T result = std::numeric_limits<T>::quiet_NaN();
+
+            if (gen_function_t::function_)
+            {
+               if (gen_function_t::populate_value_list())
+               {
+                  typedef typename StringFunction::parameter_list_t parameter_list_t;
+
+                  result = (*gen_function_t::function_)(ret_string_,
+                                                        parameter_list_t(gen_function_t::typestore_list_));
+
+                  range_.n1_c.second  = ret_string_.size() - 1;
+                  range_.cache.second = range_.n1_c.second;
+
+                  return result;
+               }
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strfunction;
+         }
+
+         std::string str() const
+         {
+            return ret_string_;
+         }
+
+         const char* base() const
+         {
+           return ret_string_.data();
+         }
+
+         std::size_t size() const
+         {
+            return ret_string_.size();
+         }
+
+         range_t& range_ref()
+         {
+            return range_;
+         }
+
+         const range_t& range_ref() const
+         {
+            return range_;
+         }
+
+      protected:
+
+         mutable range_t     range_;
+         mutable std::string ret_string_;
+      };
+
+      template <typename T, typename GenericFunction>
+      class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
+      {
+      public:
+
+         typedef generic_function_node<T,GenericFunction> gen_function_t;
+         typedef range_pack<T> range_t;
+
+         multimode_genfunction_node(GenericFunction* func,
+                                    const std::size_t& param_seq_index,
+                                    const std::vector<typename gen_function_t::expression_ptr>& arg_list)
+         : gen_function_t(arg_list,func),
+           param_seq_index_(param_seq_index)
+         {}
+
+         inline T value() const
+         {
+            T result = std::numeric_limits<T>::quiet_NaN();
+
+            if (gen_function_t::function_)
+            {
+               if (gen_function_t::populate_value_list())
+               {
+                  typedef typename GenericFunction::parameter_list_t parameter_list_t;
+
+                  return (*gen_function_t::function_)(param_seq_index_,
+                                                      parameter_list_t(gen_function_t::typestore_list_));
+               }
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_genfunction;
+         }
+
+      private:
+
+         std::size_t param_seq_index_;
+      };
+
+      template <typename T, typename StringFunction>
+      class multimode_strfunction_node : public string_function_node<T,StringFunction>
+      {
+      public:
+
+         typedef string_function_node<T,StringFunction> str_function_t;
+         typedef range_pack<T> range_t;
+
+         multimode_strfunction_node(StringFunction* func,
+                                    const std::size_t& param_seq_index,
+                                    const std::vector<typename str_function_t::expression_ptr>& arg_list)
+         : str_function_t(func,arg_list),
+           param_seq_index_(param_seq_index)
+         {}
+
+         inline T value() const
+         {
+            T result = std::numeric_limits<T>::quiet_NaN();
+
+            if (str_function_t::function_)
+            {
+               if (str_function_t::populate_value_list())
+               {
+                  typedef typename StringFunction::parameter_list_t parameter_list_t;
+
+                  result = (*str_function_t::function_)(param_seq_index_,
+                                                        str_function_t::ret_string_,
+                                                        parameter_list_t(str_function_t::typestore_list_));
+
+                  str_function_t::range_.n1_c.second  = str_function_t::ret_string_.size() - 1;
+                  str_function_t::range_.cache.second = str_function_t::range_.n1_c.second;
+
+                  return result;
+               }
+            }
+
+            return result;
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_strfunction;
+         }
+
+      private:
+
+         std::size_t param_seq_index_;
+      };
+
+      class return_exception
+      {};
+
+      template <typename T>
+      class null_igenfunc
+      {
+      public:
+
+         virtual ~null_igenfunc()
+         {}
+
+         typedef type_store<T> generic_type;
+         typedef typename generic_type::parameter_list parameter_list_t;
+
+         inline virtual T operator()(parameter_list_t)
+         {
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+      };
+
+      template <typename T>
+      class return_node : public generic_function_node<T,null_igenfunc<T> >
+      {
+      public:
+
+         typedef null_igenfunc<T> igeneric_function_t;
+         typedef igeneric_function_t* igeneric_function_ptr;
+         typedef generic_function_node<T,igeneric_function_t> gen_function_t;
+         typedef results_context<T> results_context_t;
+
+         return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
+                     results_context_t& rc)
+         : gen_function_t  (arg_list),
+           results_context_(&rc)
+         {}
+
+         inline T value() const
+         {
+            if (
+                 (0 != results_context_) &&
+                 gen_function_t::populate_value_list()
+               )
+            {
+               typedef typename type_store<T>::parameter_list parameter_list_t;
+
+               results_context_->
+                  assign(parameter_list_t(gen_function_t::typestore_list_));
+
+               throw return_exception();
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_return;
+         }
+
+      private:
+
+         results_context_t* results_context_;
+      };
+
+      template <typename T>
+      class return_envelope_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef results_context<T>  results_context_t;
+
+         return_envelope_node(expression_ptr body, results_context_t& rc)
+         : results_context_(&rc),
+           return_invoked_ (false),
+           body_           (body),
+           body_deletable_ (branch_deletable(body_))
+         {}
+
+        ~return_envelope_node()
+         {
+            if (body_ && body_deletable_)
+            {
+               delete body_;
+            }
+         }
+
+         inline T value() const
+         {
+            try
+            {
+               return_invoked_ = false;
+               results_context_->clear();
+
+               return body_->value();
+            }
+            catch(const return_exception&)
+            {
+               return_invoked_ = true;
+               return std::numeric_limits<T>::quiet_NaN();
+            }
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_retenv;
+         }
+
+         inline bool* retinvk_ptr()
+         {
+            return &return_invoked_;
+         }
+
+      private:
+
+         results_context_t* results_context_;
+         mutable bool       return_invoked_;
+         expression_ptr     body_;
+         bool               body_deletable_;
+      };
+
+      #define exprtk_define_unary_op(OpName)                         \
+      template <typename T>                                          \
+      struct OpName##_op                                             \
+      {                                                              \
+         typedef typename functor_t<T>::Type Type;                   \
+                                                                     \
+         static inline T process(Type v)                             \
+         {                                                           \
+            return numeric:: OpName (v);                             \
+         }                                                           \
+                                                                     \
+         static inline typename expression_node<T>::node_type type() \
+         {                                                           \
+            return expression_node<T>::e_##OpName;                   \
+         }                                                           \
+                                                                     \
+         static inline details::operator_type operation()            \
+         {                                                           \
+            return details::e_##OpName;                              \
+         }                                                           \
+      };                                                             \
+
+      exprtk_define_unary_op(abs  )
+      exprtk_define_unary_op(acos )
+      exprtk_define_unary_op(acosh)
+      exprtk_define_unary_op(asin )
+      exprtk_define_unary_op(asinh)
+      exprtk_define_unary_op(atan )
+      exprtk_define_unary_op(atanh)
+      exprtk_define_unary_op(ceil )
+      exprtk_define_unary_op(cos  )
+      exprtk_define_unary_op(cosh )
+      exprtk_define_unary_op(cot  )
+      exprtk_define_unary_op(csc  )
+      exprtk_define_unary_op(d2g  )
+      exprtk_define_unary_op(d2r  )
+      exprtk_define_unary_op(erf  )
+      exprtk_define_unary_op(erfc )
+      exprtk_define_unary_op(exp  )
+      exprtk_define_unary_op(expm1)
+      exprtk_define_unary_op(floor)
+      exprtk_define_unary_op(frac )
+      exprtk_define_unary_op(g2d  )
+      exprtk_define_unary_op(log  )
+      exprtk_define_unary_op(log10)
+      exprtk_define_unary_op(log2 )
+      exprtk_define_unary_op(log1p)
+      exprtk_define_unary_op(ncdf )
+      exprtk_define_unary_op(neg  )
+      exprtk_define_unary_op(notl )
+      exprtk_define_unary_op(pos  )
+      exprtk_define_unary_op(r2d  )
+      exprtk_define_unary_op(round)
+      exprtk_define_unary_op(sec  )
+      exprtk_define_unary_op(sgn  )
+      exprtk_define_unary_op(sin  )
+      exprtk_define_unary_op(sinc )
+      exprtk_define_unary_op(sinh )
+      exprtk_define_unary_op(sqrt )
+      exprtk_define_unary_op(tan  )
+      exprtk_define_unary_op(tanh )
+      exprtk_define_unary_op(trunc)
+      #undef exprtk_define_unary_op
+
+      template <typename T>
+      struct opr_base
+      {
+         typedef typename details::functor_t<T>::Type Type;
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::qfunc_t quaternary_functor_t;
+         typedef typename functor_t::tfunc_t    trinary_functor_t;
+         typedef typename functor_t::bfunc_t     binary_functor_t;
+         typedef typename functor_t::ufunc_t      unary_functor_t;
+      };
+
+      template <typename T>
+      struct add_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return t1 + t2; }
+         static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
+         static inline details::operator_type operation() { return details::e_add; }
+      };
+
+      template <typename T>
+      struct mul_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return t1 * t2; }
+         static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
+         static inline details::operator_type operation() { return details::e_mul; }
+      };
+
+      template <typename T>
+      struct sub_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return t1 - t2; }
+         static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
+         static inline details::operator_type operation() { return details::e_sub; }
+      };
+
+      template <typename T>
+      struct div_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return t1 / t2; }
+         static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
+         static inline details::operator_type operation() { return details::e_div; }
+      };
+
+      template <typename T>
+      struct mod_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
+         static inline details::operator_type operation() { return details::e_mod; }
+      };
+
+      template <typename T>
+      struct pow_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
+         static inline details::operator_type operation() { return details::e_pow; }
+      };
+
+      template <typename T>
+      struct lt_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
+         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
+         static inline details::operator_type operation() { return details::e_lt; }
+      };
+
+      template <typename T>
+      struct lte_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
+         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
+         static inline details::operator_type operation() { return details::e_lte; }
+      };
+
+      template <typename T>
+      struct gt_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
+         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
+         static inline details::operator_type operation() { return details::e_gt; }
+      };
+
+      template <typename T>
+      struct gte_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
+         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
+         static inline details::operator_type operation() { return details::e_gte; }
+      };
+
+      template <typename T>
+      struct eq_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
+         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
+         static inline details::operator_type operation() { return details::e_eq; }
+      };
+
+      template <typename T>
+      struct ne_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
+         static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
+         static inline details::operator_type operation() { return details::e_ne; }
+      };
+
+      template <typename T>
+      struct and_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
+         static inline details::operator_type operation() { return details::e_and; }
+      };
+
+      template <typename T>
+      struct nand_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
+         static inline details::operator_type operation() { return details::e_nand; }
+      };
+
+      template <typename T>
+      struct or_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
+         static inline details::operator_type operation() { return details::e_or; }
+      };
+
+      template <typename T>
+      struct nor_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
+         static inline details::operator_type operation() { return details::e_nor; }
+      };
+
+      template <typename T>
+      struct xor_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
+         static inline details::operator_type operation() { return details::e_xor; }
+      };
+
+      template <typename T>
+      struct xnor_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
+         static inline details::operator_type operation() { return details::e_xnor; }
+      };
+
+      template <typename T>
+      struct in_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
+         static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
+         static inline details::operator_type operation() { return details::e_in; }
+      };
+
+      template <typename T>
+      struct like_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
+         static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
+         static inline details::operator_type operation() { return details::e_like; }
+      };
+
+      template <typename T>
+      struct ilike_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
+         static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
+         static inline details::operator_type operation() { return details::e_ilike; }
+      };
+
+      template <typename T>
+      struct inrange_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+         static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
+         static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
+         {
+            return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
+         }
+         static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
+         static inline details::operator_type operation() { return details::e_inrange; }
+      };
+
+      template <typename T>
+      inline T value(details::expression_node<T>* n)
+      {
+         return n->value();
+      }
+
+      template <typename T>
+      inline T value(T* t)
+      {
+         return (*t);
+      }
+
+      template <typename T>
+      struct vararg_add_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 0  : return T(0);
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               default :
+                         {
+                            T result = T(0);
+
+                            for (std::size_t i = 0; i < arg_list.size(); ++i)
+                            {
+                              result += value(arg_list[i]);
+                            }
+
+                            return result;
+                         }
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return value(arg_list[0]);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) + value(arg_list[1]);
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) + value(arg_list[1]) +
+                   value(arg_list[2]);
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) + value(arg_list[1]) +
+                   value(arg_list[2]) + value(arg_list[3]);
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) + value(arg_list[1]) +
+                   value(arg_list[2]) + value(arg_list[3]) +
+                   value(arg_list[4]);
+         }
+      };
+
+      template <typename T>
+      struct vararg_mul_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 0  : return T(0);
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               default :
+                         {
+                            T result = T(value(arg_list[0]));
+
+                            for (std::size_t i = 1; i < arg_list.size(); ++i)
+                            {
+                               result *= value(arg_list[i]);
+                            }
+
+                            return result;
+                         }
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return value(arg_list[0]);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) * value(arg_list[1]);
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) * value(arg_list[1]) *
+                   value(arg_list[2]);
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) * value(arg_list[1]) *
+                   value(arg_list[2]) * value(arg_list[3]);
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+            return value(arg_list[0]) * value(arg_list[1]) *
+                   value(arg_list[2]) * value(arg_list[3]) *
+                   value(arg_list[4]);
+         }
+      };
+
+      template <typename T>
+      struct vararg_avg_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 0  : return T(0);
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return value(arg_list[0]);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+            return (value(arg_list[0]) + value(arg_list[1])) / T(2);
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+            return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+            return (value(arg_list[0]) + value(arg_list[1]) +
+                    value(arg_list[2]) + value(arg_list[3])) / T(4);
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+            return (value(arg_list[0]) + value(arg_list[1]) +
+                    value(arg_list[2]) + value(arg_list[3]) +
+                    value(arg_list[4])) / T(5);
+         }
+      };
+
+      template <typename T>
+      struct vararg_min_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 0  : return T(0);
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               default :
+                         {
+                            T result = T(value(arg_list[0]));
+
+                            for (std::size_t i = 1; i < arg_list.size(); ++i)
+                            {
+                               const T v = value(arg_list[i]);
+
+                               if (v < result)
+                                  result = v;
+                            }
+
+                            return result;
+                         }
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return value(arg_list[0]);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+            return std::min<T>(value(arg_list[0]),value(arg_list[1]));
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+            return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+            return std::min<T>(
+                        std::min<T>(value(arg_list[0]),value(arg_list[1])),
+                        std::min<T>(value(arg_list[2]),value(arg_list[3])));
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+            return std::min<T>(
+                   std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),
+                               std::min<T>(value(arg_list[2]),value(arg_list[3]))),
+                               value(arg_list[4]));
+         }
+      };
+
+      template <typename T>
+      struct vararg_max_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 0  : return T(0);
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               default :
+                         {
+                            T result = T(value(arg_list[0]));
+
+                            for (std::size_t i = 1; i < arg_list.size(); ++i)
+                            {
+                               const T v = value(arg_list[i]);
+                               if (v > result)
+                                  result = v;
+                            }
+
+                            return result;
+                         }
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return value(arg_list[0]);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+            return std::max<T>(value(arg_list[0]),value(arg_list[1]));
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+            return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+            return std::max<T>(
+                        std::max<T>(value(arg_list[0]),value(arg_list[1])),
+                        std::max<T>(value(arg_list[2]),value(arg_list[3])));
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+            return std::max<T>(
+                   std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),
+                               std::max<T>(value(arg_list[2]),value(arg_list[3]))),
+                               value(arg_list[4]));
+         }
+      };
+
+      template <typename T>
+      struct vararg_mand_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               default :
+                         {
+                            for (std::size_t i = 0; i < arg_list.size(); ++i)
+                            {
+                               if (std::equal_to<T>()(T(0),value(arg_list[i])))
+                                  return T(0);
+                            }
+
+                            return T(1);
+                         }
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return std::not_equal_to<T>()
+                      (T(0),value(arg_list[0])) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[1]))
+                   ) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[2]))
+                   ) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[2])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[3]))
+                   ) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[1])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[2])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[3])) &&
+                     std::not_equal_to<T>()(T(0),value(arg_list[4]))
+                   ) ? T(1) : T(0);
+         }
+      };
+
+      template <typename T>
+      struct vararg_mor_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               default :
+                         {
+                            for (std::size_t i = 0; i < arg_list.size(); ++i)
+                            {
+                               if (std::not_equal_to<T>()(T(0),value(arg_list[i])))
+                                  return T(1);
+                            }
+
+                            return T(0);
+                         }
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return std::not_equal_to<T>()
+                      (T(0),value(arg_list[0])) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[1]))
+                   ) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[2]))
+                   ) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[2])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[3]))
+                   ) ? T(1) : T(0);
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+            return (
+                     std::not_equal_to<T>()(T(0),value(arg_list[0])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[1])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[2])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[3])) ||
+                     std::not_equal_to<T>()(T(0),value(arg_list[4]))
+                   ) ? T(1) : T(0);
+         }
+      };
+
+      template <typename T>
+      struct vararg_multi_op : public opr_base<T>
+      {
+         typedef typename opr_base<T>::Type Type;
+
+         template <typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         static inline T process(const Sequence<Type,Allocator>& arg_list)
+         {
+            switch (arg_list.size())
+            {
+               case 0  : return std::numeric_limits<T>::quiet_NaN();
+               case 1  : return process_1(arg_list);
+               case 2  : return process_2(arg_list);
+               case 3  : return process_3(arg_list);
+               case 4  : return process_4(arg_list);
+               case 5  : return process_5(arg_list);
+               case 6  : return process_6(arg_list);
+               case 7  : return process_7(arg_list);
+               case 8  : return process_8(arg_list);
+               default :
+                         {
+                            for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
+                            {
+                               value(arg_list[i]);
+                            }
+
+                            return value(arg_list.back());
+                         }
+            }
+         }
+
+         template <typename Sequence>
+         static inline T process_1(const Sequence& arg_list)
+         {
+            return value(arg_list[0]);
+         }
+
+         template <typename Sequence>
+         static inline T process_2(const Sequence& arg_list)
+         {
+                   value(arg_list[0]);
+            return value(arg_list[1]);
+         }
+
+         template <typename Sequence>
+         static inline T process_3(const Sequence& arg_list)
+         {
+                   value(arg_list[0]);
+                   value(arg_list[1]);
+            return value(arg_list[2]);
+         }
+
+         template <typename Sequence>
+         static inline T process_4(const Sequence& arg_list)
+         {
+                   value(arg_list[0]);
+                   value(arg_list[1]);
+                   value(arg_list[2]);
+            return value(arg_list[3]);
+         }
+
+         template <typename Sequence>
+         static inline T process_5(const Sequence& arg_list)
+         {
+                   value(arg_list[0]);
+                   value(arg_list[1]);
+                   value(arg_list[2]);
+                   value(arg_list[3]);
+            return value(arg_list[4]);
+         }
+
+         template <typename Sequence>
+         static inline T process_6(const Sequence& arg_list)
+         {
+                   value(arg_list[0]);
+                   value(arg_list[1]);
+                   value(arg_list[2]);
+                   value(arg_list[3]);
+                   value(arg_list[4]);
+            return value(arg_list[5]);
+         }
+
+         template <typename Sequence>
+         static inline T process_7(const Sequence& arg_list)
+         {
+                   value(arg_list[0]);
+                   value(arg_list[1]);
+                   value(arg_list[2]);
+                   value(arg_list[3]);
+                   value(arg_list[4]);
+                   value(arg_list[5]);
+            return value(arg_list[6]);
+         }
+
+         template <typename Sequence>
+         static inline T process_8(const Sequence& arg_list)
+         {
+                   value(arg_list[0]);
+                   value(arg_list[1]);
+                   value(arg_list[2]);
+                   value(arg_list[3]);
+                   value(arg_list[4]);
+                   value(arg_list[5]);
+                   value(arg_list[6]);
+            return value(arg_list[7]);
+         }
+      };
+
+      template <typename T>
+      struct vec_add_op
+      {
+         typedef vector_interface<T>* ivector_ptr;
+
+         static inline T process(const ivector_ptr v)
+         {
+            vector_holder<T>& vec = v->vec()->ref();
+
+            T result = T(0);
+
+            for (std::size_t i = 0; i < vec.size(); ++i)
+            {
+              result += (*vec[i]);
+            }
+
+            return result;
+         }
+      };
+
+      template <typename T>
+      struct vec_mul_op
+      {
+         typedef vector_interface<T>* ivector_ptr;
+
+         static inline T process(const ivector_ptr v)
+         {
+            vector_holder<T>& vec = v->vec()->ref();
+
+            T result = (*vec[0]);
+
+            for (std::size_t i = 1; i < vec.size(); ++i)
+            {
+              result *= (*vec[i]);
+            }
+
+            return result;
+         }
+      };
+
+      template <typename T>
+      struct vec_avg_op
+      {
+         typedef vector_interface<T>* ivector_ptr;
+
+         static inline T process(const ivector_ptr v)
+         {
+            vector_holder<T>& vec = v->vec()->ref();
+
+            T result = T(0);
+
+            for (std::size_t i = 0; i < vec.size(); ++i)
+            {
+              result += (*vec[i]);
+            }
+
+            return result / vec.size();
+         }
+      };
+
+      template <typename T>
+      struct vec_min_op
+      {
+         typedef vector_interface<T>* ivector_ptr;
+
+         static inline T process(const ivector_ptr v)
+         {
+            vector_holder<T>& vec = v->vec()->ref();
+
+            T result = (*vec[0]);
+
+            for (std::size_t i = 1; i < vec.size(); ++i)
+            {
+              T v_i = (*vec[i]);
+
+              if (v_i < result)
+                result = v_i;
+            }
+
+            return result;
+         }
+      };
+
+      template <typename T>
+      struct vec_max_op
+      {
+         typedef vector_interface<T>* ivector_ptr;
+
+         static inline T process(const ivector_ptr v)
+         {
+            vector_holder<T>& vec = v->vec()->ref();
+
+            T result = (*vec[0]);
+
+            for (std::size_t i = 1; i < vec.size(); ++i)
+            {
+              T v_i = (*vec[i]);
+              if (v_i > result)
+                result = v_i;
+            }
+
+            return result;
+         }
+      };
+
+      template <typename T>
+      class vov_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~vov_base_node()
+         {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+
+         virtual const T& v0() const = 0;
+
+         virtual const T& v1() const = 0;
+      };
+
+      template <typename T>
+      class cov_base_node : public expression_node<T>
+      {
+      public:
+
+       virtual ~cov_base_node()
+          {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+
+         virtual const T c() const = 0;
+
+         virtual const T& v() const = 0;
+      };
+
+      template <typename T>
+      class voc_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~voc_base_node()
+         {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+
+         virtual const T c() const = 0;
+
+         virtual const T& v() const = 0;
+      };
+
+      template <typename T>
+      class vob_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~vob_base_node()
+         {}
+
+         virtual const T& v() const = 0;
+      };
+
+      template <typename T>
+      class bov_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~bov_base_node()
+         {}
+
+         virtual const T& v() const = 0;
+      };
+
+      template <typename T>
+      class cob_base_node : public expression_node<T>
+      {
+      public:
+
+       virtual ~cob_base_node()
+       {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+
+         virtual const T c() const = 0;
+
+         virtual void set_c(const T) = 0;
+
+         virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
+      };
+
+      template <typename T>
+      class boc_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~boc_base_node()
+         {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+
+         virtual const T c() const = 0;
+
+         virtual void set_c(const T) = 0;
+
+         virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
+      };
+
+      template <typename T>
+      class uv_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~uv_base_node()
+         {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+
+         virtual const T& v() const = 0;
+      };
+
+      template <typename T>
+      class sos_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~sos_base_node()
+         {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+      };
+
+      template <typename T>
+      class sosos_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~sosos_base_node()
+         {}
+
+         inline virtual operator_type operation() const
+         {
+            return details::e_default;
+         }
+      };
+
+      template <typename T>
+      class T0oT1oT2_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~T0oT1oT2_base_node()
+         {}
+
+         virtual std::string type_id() const = 0;
+      };
+
+      template <typename T>
+      class T0oT1oT2oT3_base_node : public expression_node<T>
+      {
+      public:
+
+         virtual ~T0oT1oT2oT3_base_node()
+         {}
+
+         virtual std::string type_id() const = 0;
+      };
+
+      template <typename T, typename Operation>
+      class unary_variable_node : public uv_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         explicit unary_variable_node(const T& var)
+         : v_(var)
+         {}
+
+         inline T value() const
+         {
+            return Operation::process(v_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T& v() const
+         {
+            return v_;
+         }
+
+      private:
+
+         unary_variable_node(unary_variable_node<T,Operation>&);
+         unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
+
+         const T& v_;
+      };
+
+      template <typename T>
+      class uvouv_node : public expression_node<T>
+      {
+      public:
+
+         // UOpr1(v0) Op UOpr2(v1)
+
+         typedef expression_node<T>* expression_ptr;
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef typename functor_t::ufunc_t      ufunc_t;
+
+         explicit uvouv_node(const T& var0,const T& var1,
+                             ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
+         : v0_(var0),
+           v1_(var1),
+           u0_(uf0),
+           u1_(uf1),
+           f_ (bf)
+         {}
+
+         inline T value() const
+         {
+            return f_(u0_(v0_),u1_(v1_));
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_uvouv;
+         }
+
+         inline operator_type operation() const
+         {
+            return details::e_default;
+         }
+
+         inline const T& v0()
+         {
+            return v0_;
+         }
+
+         inline const T& v1()
+         {
+            return v1_;
+         }
+
+         inline ufunc_t u0()
+         {
+            return u0_;
+         }
+
+         inline ufunc_t u1()
+         {
+            return u1_;
+         }
+
+         inline ufunc_t f()
+         {
+            return f_;
+         }
+
+      private:
+
+         uvouv_node(uvouv_node<T>&);
+         uvouv_node<T>& operator=(uvouv_node<T>&);
+
+         const T& v0_;
+         const T& v1_;
+         const ufunc_t u0_;
+         const ufunc_t u1_;
+         const bfunc_t f_;
+      };
+
+      template <typename T, typename Operation>
+      class unary_branch_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         explicit unary_branch_node(expression_ptr brnch)
+         : branch_(brnch),
+           branch_deletable_(branch_deletable(branch_))
+         {}
+
+        ~unary_branch_node()
+         {
+            if (branch_ && branch_deletable_)
+            {
+               delete branch_;
+               branch_ = 0;
+            }
+         }
+
+         inline T value() const
+         {
+            return Operation::process(branch_->value());
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return branch_;
+         }
+
+         inline void release()
+         {
+            branch_deletable_ = false;
+         }
+
+      private:
+
+         unary_branch_node(unary_branch_node<T,Operation>&);
+         unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
+
+         expression_ptr branch_;
+         bool           branch_deletable_;
+      };
+
+      template <typename T> struct is_const                { enum {result = 0}; };
+      template <typename T> struct is_const <const T>      { enum {result = 1}; };
+      template <typename T> struct is_const_ref            { enum {result = 0}; };
+      template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
+      template <typename T> struct is_ref                  { enum {result = 0}; };
+      template <typename T> struct is_ref<T&>              { enum {result = 1}; };
+      template <typename T> struct is_ref<const T&>        { enum {result = 0}; };
+
+      template <std::size_t State>
+      struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
+
+      template <>
+      struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
+
+      #define exprtk_crtype(Type)                          \
+      param_to_str<is_const_ref< Type >::result>::result() \
+
+      template <typename T>
+      struct T0oT1oT2process
+      {
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::bfunc_t      bfunc_t;
+
+         struct mode0
+         {
+            static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
+            {
+               // (T0 o0 T1) o1 T2
+               return bf1(bf0(t0,t1),t2);
+            }
+
+            template <typename T0, typename T1, typename T2>
+            static inline std::string id()
+            {
+               static const std::string result = "(" + exprtk_crtype(T0) + "o"   +
+                                                       exprtk_crtype(T1) + ")o(" +
+                                                       exprtk_crtype(T2) + ")"   ;
+               return result;
+            }
+         };
+
+         struct mode1
+         {
+            static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
+            {
+               // T0 o0 (T1 o1 T2)
+               return bf0(t0,bf1(t1,t2));
+            }
+
+            template <typename T0, typename T1, typename T2>
+            static inline std::string id()
+            {
+               static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
+                                                       exprtk_crtype(T1) + "o"   +
+                                                       exprtk_crtype(T2) + ")"   ;
+               return result;
+            }
+         };
+      };
+
+      template <typename T>
+      struct T0oT1oT20T3process
+      {
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::bfunc_t      bfunc_t;
+
+         struct mode0
+         {
+            static inline T process(const T& t0, const T& t1,
+                                    const T& t2, const T& t3,
+                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            {
+               // (T0 o0 T1) o1 (T2 o2 T3)
+               return bf1(bf0(t0,t1),bf2(t2,t3));
+            }
+
+            template <typename T0, typename T1, typename T2, typename T3>
+            static inline std::string id()
+            {
+               static const std::string result = "(" + exprtk_crtype(T0) + "o"  +
+                                                       exprtk_crtype(T1) + ")o" +
+                                                 "(" + exprtk_crtype(T2) + "o"  +
+                                                       exprtk_crtype(T3) + ")"  ;
+               return result;
+            }
+         };
+
+         struct mode1
+         {
+            static inline T process(const T& t0, const T& t1,
+                                    const T& t2, const T& t3,
+                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            {
+               // (T0 o0 (T1 o1 (T2 o2 T3))
+               return bf0(t0,bf1(t1,bf2(t2,t3)));
+            }
+            template <typename T0, typename T1, typename T2, typename T3>
+            static inline std::string id()
+            {
+               static const std::string result = "(" + exprtk_crtype(T0) +  ")o((" +
+                                                       exprtk_crtype(T1) +  ")o("  +
+                                                       exprtk_crtype(T2) +  "o"    +
+                                                       exprtk_crtype(T3) +  "))"   ;
+               return result;
+            }
+         };
+
+         struct mode2
+         {
+            static inline T process(const T& t0, const T& t1,
+                                    const T& t2, const T& t3,
+                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            {
+               // (T0 o0 ((T1 o1 T2) o2 T3)
+               return bf0(t0,bf2(bf1(t1,t2),t3));
+            }
+
+            template <typename T0, typename T1, typename T2, typename T3>
+            static inline std::string id()
+            {
+               static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
+                                                       exprtk_crtype(T1) + "o"    +
+                                                       exprtk_crtype(T2) + ")o("  +
+                                                       exprtk_crtype(T3) + "))"   ;
+               return result;
+            }
+         };
+
+         struct mode3
+         {
+            static inline T process(const T& t0, const T& t1,
+                                    const T& t2, const T& t3,
+                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            {
+               // (((T0 o0 T1) o1 T2) o2 T3)
+               return bf2(bf1(bf0(t0,t1),t2),t3);
+            }
+
+            template <typename T0, typename T1, typename T2, typename T3>
+            static inline std::string id()
+            {
+               static const std::string result = "((" + exprtk_crtype(T0) + "o"    +
+                                                        exprtk_crtype(T1) + ")o("  +
+                                                        exprtk_crtype(T2) + "))o(" +
+                                                        exprtk_crtype(T3) + ")";
+               return result;
+            }
+         };
+
+         struct mode4
+         {
+            static inline T process(const T& t0, const T& t1,
+                                    const T& t2, const T& t3,
+                                    const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
+            {
+               // ((T0 o0 (T1 o1 T2)) o2 T3
+               return bf2(bf0(t0,bf1(t1,t2)),t3);
+            }
+
+            template <typename T0, typename T1, typename T2, typename T3>
+            static inline std::string id()
+            {
+               static const std::string result = "((" + exprtk_crtype(T0) + ")o("  +
+                                                        exprtk_crtype(T1) + "o"    +
+                                                        exprtk_crtype(T2) + "))o(" +
+                                                        exprtk_crtype(T3) + ")"    ;
+               return result;
+            }
+         };
+      };
+
+      #undef exprtk_crtype
+
+      template <typename T, typename T0, typename T1>
+      struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
+      template <typename T, typename T0, typename T1>
+      const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none;
+
+      #define synthesis_node_type_define(T0_,T1_,v_)                                                            \
+      template <typename T, typename T0, typename T1>                                                           \
+      struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; };         \
+      template <typename T, typename T0, typename T1>                                                           \
+      const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
+
+      synthesis_node_type_define(const T0&,const T1&, e_vov)
+      synthesis_node_type_define(const T0&,const T1 , e_voc)
+      synthesis_node_type_define(const T0 ,const T1&, e_cov)
+      synthesis_node_type_define(      T0&,      T1&,e_none)
+      synthesis_node_type_define(const T0 ,const T1 ,e_none)
+      synthesis_node_type_define(      T0&,const T1 ,e_none)
+      synthesis_node_type_define(const T0 ,      T1&,e_none)
+      synthesis_node_type_define(const T0&,      T1&,e_none)
+      synthesis_node_type_define(      T0&,const T1&,e_none)
+      #undef synthesis_node_type_define
+
+      template <typename T, typename T0, typename T1, typename T2>
+      struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
+      template <typename T, typename T0, typename T1, typename T2>
+      const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none;
+
+      #define synthesis_node_type_define(T0_,T1_,T2_,v_)                                                               \
+      template <typename T, typename T0, typename T1, typename T2>                                                     \
+      struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; };         \
+      template <typename T, typename T0, typename T1, typename T2>                                                     \
+      const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
+
+      synthesis_node_type_define(const T0&,const T1&,const T2&, e_vovov)
+      synthesis_node_type_define(const T0&,const T1&,const T2 , e_vovoc)
+      synthesis_node_type_define(const T0&,const T1 ,const T2&, e_vocov)
+      synthesis_node_type_define(const T0 ,const T1&,const T2&, e_covov)
+      synthesis_node_type_define(const T0 ,const T1&,const T2 , e_covoc)
+      synthesis_node_type_define(const T0 ,const T1 ,const T2 , e_none )
+      synthesis_node_type_define(const T0 ,const T1 ,const T2&, e_none )
+      synthesis_node_type_define(const T0&,const T1 ,const T2 , e_none )
+      synthesis_node_type_define(      T0&,      T1&,      T2&, e_none )
+      #undef synthesis_node_type_define
+
+      template <typename T, typename T0, typename T1, typename T2, typename T3>
+      struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
+      template <typename T, typename T0, typename T1, typename T2, typename T3>
+      const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none;
+
+      #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_)                                                                  \
+      template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
+      struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; };         \
+      template <typename T, typename T0, typename T1, typename T2, typename T3>                                               \
+      const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
+
+      synthesis_node_type_define(const T0&,const T1&,const T2&, const T3&,e_vovovov)
+      synthesis_node_type_define(const T0&,const T1&,const T2&, const T3 ,e_vovovoc)
+      synthesis_node_type_define(const T0&,const T1&,const T2 , const T3&,e_vovocov)
+      synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3&,e_vocovov)
+      synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3&,e_covovov)
+      synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3&,e_covocov)
+      synthesis_node_type_define(const T0&,const T1 ,const T2&, const T3 ,e_vocovoc)
+      synthesis_node_type_define(const T0 ,const T1&,const T2&, const T3 ,e_covovoc)
+      synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3&,e_vococov)
+      synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3 ,e_none   )
+      synthesis_node_type_define(const T0 ,const T1 ,const T2 , const T3&,e_none   )
+      synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3 ,e_none   )
+      synthesis_node_type_define(const T0 ,const T1&,const T2 , const T3 ,e_none   )
+      synthesis_node_type_define(const T0&,const T1 ,const T2 , const T3 ,e_none   )
+      synthesis_node_type_define(const T0 ,const T1 ,const T2&, const T3&,e_none   )
+      synthesis_node_type_define(const T0&,const T1&,const T2 , const T3 ,e_none   )
+      #undef synthesis_node_type_define
+
+      template <typename T, typename T0, typename T1>
+      class T0oT1 : public expression_node<T>
+      {
+      public:
+
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef T value_type;
+         typedef T0oT1<T,T0,T1> node_type;
+
+         T0oT1(T0 p0, T1 p1, const bfunc_t p2)
+         : t0_(p0),
+           t1_(p1),
+           f_ (p2)
+         {}
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
+            return result;
+         }
+
+         inline operator_type operation() const
+         {
+            return e_default;
+         }
+
+         inline T value() const
+         {
+            return f_(t0_,t1_);
+         }
+
+         inline T0 t0() const
+         {
+            return t0_;
+         }
+
+         inline T1 t1() const
+         {
+            return t1_;
+         }
+
+         inline bfunc_t f() const
+         {
+            return f_;
+         }
+
+         template <typename Allocator>
+         static inline expression_node<T>* allocate(Allocator& allocator,
+                                                    T0 p0, T1 p1,
+                                                    bfunc_t p2)
+         {
+            return allocator.template allocate_type<node_type,T0,T1,bfunc_t&>(p0,p1,p2);
+         }
+
+      private:
+
+         T0oT1(T0oT1<T,T0,T1>&) {}
+         T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return *this; }
+
+         T0 t0_;
+         T1 t1_;
+         const bfunc_t f_;
+      };
+
+      template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
+      class T0oT1oT2 : public T0oT1oT2_base_node<T>
+      {
+      public:
+
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef T value_type;
+         typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type;
+         typedef ProcessMode process_mode_t;
+
+         T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
+         : t0_(p0),
+           t1_(p1),
+           t2_(p2),
+           f0_(p3),
+           f1_(p4)
+         {}
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
+            return result;
+         }
+
+         inline operator_type operation() const
+         {
+            return e_default;
+         }
+
+         inline T value() const
+         {
+            return ProcessMode::process(t0_,t1_,t2_,f0_,f1_);
+         }
+
+         inline T0 t0() const
+         {
+            return t0_;
+         }
+
+         inline T1 t1() const
+         {
+            return t1_;
+         }
+
+         inline T2 t2() const
+         {
+            return t2_;
+         }
+
+         bfunc_t f0() const
+         {
+            return f0_;
+         }
+
+         bfunc_t f1() const
+         {
+            return f1_;
+         }
+
+         std::string type_id() const
+         {
+            return id();
+         }
+
+         static inline std::string id()
+         {
+            return process_mode_t::template id<T0,T1,T2>();
+         }
+
+         template <typename Allocator>
+         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
+         {
+            return allocator.template allocate_type<node_type,T0,T1,T2,bfunc_t,bfunc_t>(p0,p1,p2,p3,p4);
+         }
+
+      private:
+
+         T0oT1oT2(node_type&) {}
+         node_type& operator=(node_type&) { return *this; }
+
+         T0 t0_;
+         T1 t1_;
+         T2 t2_;
+         const bfunc_t f0_;
+         const bfunc_t f1_;
+      };
+
+      template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
+      class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T>
+      {
+      public:
+
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::bfunc_t      bfunc_t;
+         typedef T value_type;
+         typedef T0_ T0;
+         typedef T1_ T1;
+         typedef T2_ T2;
+         typedef T3_ T3;
+         typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type;
+         typedef ProcessMode process_mode_t;
+
+         T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
+         : t0_(p0),
+           t1_(p1),
+           t2_(p2),
+           t3_(p3),
+           f0_(p4),
+           f1_(p5),
+           f2_(p6)
+         {}
+
+         inline T value() const
+         {
+            return ProcessMode::process(t0_,t1_,t2_,t3_,f0_,f1_,f2_);
+         }
+
+         inline T0 t0() const
+         {
+            return t0_;
+         }
+
+         inline T1 t1() const
+         {
+            return t1_;
+         }
+
+         inline T2 t2() const
+         {
+            return t2_;
+         }
+
+         inline T3 t3() const
+         {
+            return t3_;
+         }
+
+         inline bfunc_t f0() const
+         {
+            return f0_;
+         }
+
+         inline bfunc_t f1() const
+         {
+            return f1_;
+         }
+
+         inline bfunc_t f2() const
+         {
+            return f2_;
+         }
+
+         inline std::string type_id() const
+         {
+            return id();
+         }
+
+         static inline std::string id()
+         {
+            return process_mode_t::template id<T0,T1,T2,T3>();
+         }
+
+         template <typename Allocator>
+         static inline expression_node<T>* allocate(Allocator& allocator,
+                                                    T0 p0, T1 p1, T2 p2, T3 p3,
+                                                    bfunc_t p4, bfunc_t p5, bfunc_t p6)
+         {
+            return allocator.template allocate_type<node_type,T0,T1,T2,T3,bfunc_t,bfunc_t>(p0,p1,p2,p3,p4,p5,p6);
+         }
+
+      private:
+
+         T0oT1oT2oT3(node_type&) {}
+         node_type& operator=(node_type&) { return *this; }
+
+         T0 t0_;
+         T1 t1_;
+         T2 t2_;
+         T3 t3_;
+         const bfunc_t f0_;
+         const bfunc_t f1_;
+         const bfunc_t f2_;
+      };
+
+      template <typename T, typename T0, typename T1, typename T2>
+      class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T>
+      {
+      public:
+
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::tfunc_t      tfunc_t;
+         typedef T value_type;
+         typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type;
+
+         T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
+         : t0_(p0),
+           t1_(p1),
+           t2_(p2),
+           f_ (p3)
+         {}
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
+            return result;
+         }
+
+         inline operator_type operation() const
+         {
+            return e_default;
+         }
+
+         inline T value() const
+         {
+            return f_(t0_,t1_,t2_);
+         }
+
+         inline T0 t0() const
+         {
+            return t0_;
+         }
+
+         inline T1 t1() const
+         {
+            return t1_;
+         }
+
+         inline T2 t2() const
+         {
+            return t2_;
+         }
+
+         tfunc_t f() const
+         {
+            return f_;
+         }
+
+         std::string type_id() const
+         {
+            return id();
+         }
+
+         static inline std::string id()
+         {
+            return "sf3";
+         }
+
+         template <typename Allocator>
+         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
+         {
+            return allocator.template allocate_type<node_type,T0,T1,T2,tfunc_t>(p0,p1,p2,p3);
+         }
+
+      private:
+
+         T0oT1oT2_sf3(node_type&) {}
+         node_type& operator=(node_type&) { return *this; }
+
+         T0 t0_;
+         T1 t1_;
+         T2 t2_;
+         const tfunc_t f_;
+      };
+
+      template <typename T, typename T0, typename T1, typename T2>
+      class sf3ext_type_node : public T0oT1oT2_base_node<T>
+      {
+      public:
+
+         virtual ~sf3ext_type_node()
+         {}
+
+         virtual T0 t0() const = 0;
+
+         virtual T1 t1() const = 0;
+
+         virtual T2 t2() const = 0;
+      };
+
+      template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
+      class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
+      {
+      public:
+
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::tfunc_t      tfunc_t;
+         typedef T value_type;
+         typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type;
+
+         T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
+         : t0_(p0),
+           t1_(p1),
+           t2_(p2)
+         {}
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result;
+            return result;
+         }
+
+         inline operator_type operation() const
+         {
+            return e_default;
+         }
+
+         inline T value() const
+         {
+            return SF3Operation::process(t0_,t1_,t2_);
+         }
+
+         T0 t0() const
+         {
+            return t0_;
+         }
+
+         T1 t1() const
+         {
+            return t1_;
+         }
+
+         T2 t2() const
+         {
+            return t2_;
+         }
+
+         std::string type_id() const
+         {
+            return id();
+         }
+
+         static inline std::string id()
+         {
+            return SF3Operation::id();
+         }
+
+         template <typename Allocator>
+         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
+         {
+            return allocator.template allocate_type<node_type,T0,T1,T2>(p0,p1,p2);
+         }
+
+      private:
+
+         T0oT1oT2_sf3ext(node_type&) {}
+         node_type& operator=(node_type&) { return *this; }
+
+         T0 t0_;
+         T1 t1_;
+         T2 t2_;
+      };
+
+      template <typename T>
+      inline bool is_sf3ext_node(const expression_node<T>* n)
+      {
+         switch (n->type())
+         {
+            case expression_node<T>::e_vovov : return true;
+            case expression_node<T>::e_vovoc : return true;
+            case expression_node<T>::e_vocov : return true;
+            case expression_node<T>::e_covov : return true;
+            case expression_node<T>::e_covoc : return true;
+            default                          : return false;
+         }
+      }
+
+      template <typename T, typename T0, typename T1, typename T2, typename T3>
+      class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T>
+      {
+      public:
+
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::qfunc_t      qfunc_t;
+         typedef T value_type;
+         typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type;
+
+         T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
+         : t0_(p0),
+           t1_(p1),
+           t2_(p2),
+           t3_(p3),
+           f_ (p4)
+         {}
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
+            return result;
+         }
+
+         inline operator_type operation() const
+         {
+            return e_default;
+         }
+
+         inline T value() const
+         {
+            return f_(t0_,t1_,t2_,t3_);
+         }
+
+         inline T0 t0() const
+         {
+            return t0_;
+         }
+
+         inline T1 t1() const
+         {
+            return t1_;
+         }
+
+         inline T2 t2() const
+         {
+            return t2_;
+         }
+
+         inline T3 t3() const
+         {
+            return t3_;
+         }
+
+         qfunc_t f() const
+         {
+            return f_;
+         }
+
+         std::string type_id() const
+         {
+            return id();
+         }
+
+         static inline std::string id()
+         {
+            return "sf4";
+         }
+
+         template <typename Allocator>
+         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
+         {
+            return allocator.template allocate_type<node_type,T0,T1,T2,T3,qfunc_t>(p0,p1,p2,p3,p4);
+         }
+
+      private:
+
+         T0oT1oT2oT3_sf4(node_type&) {}
+         node_type& operator=(node_type&) { return *this; }
+
+         T0 t0_;
+         T1 t1_;
+         T2 t2_;
+         T3 t3_;
+         const qfunc_t f_;
+      };
+
+      template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
+      class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T>
+      {
+      public:
+
+         typedef typename details::functor_t<T> functor_t;
+         typedef typename functor_t::tfunc_t      tfunc_t;
+         typedef T value_type;
+         typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type;
+
+         T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
+         : t0_(p0),
+           t1_(p1),
+           t2_(p2),
+           t3_(p3)
+         {}
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result;
+            return result;
+         }
+
+         inline operator_type operation() const
+         {
+            return e_default;
+         }
+
+         inline T value() const
+         {
+            return SF4Operation::process(t0_,t1_,t2_,t3_);
+         }
+
+         inline T0 t0() const
+         {
+            return t0_;
+         }
+
+         inline T1 t1() const
+         {
+            return t1_;
+         }
+
+         inline T2 t2() const
+         {
+            return t2_;
+         }
+
+         inline T3 t3() const
+         {
+            return t2_;
+         }
+
+         std::string type_id() const
+         {
+            return id();
+         }
+
+         static inline std::string id()
+         {
+            return SF4Operation::id();
+         }
+
+         template <typename Allocator>
+         static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
+         {
+            return allocator.template allocate_type<node_type,T0,T1,T2,T3>(p0,p1,p2,p3);
+         }
+
+      private:
+
+         T0oT1oT2oT3_sf4ext(node_type&) {}
+         node_type& operator=(node_type&) { return *this; }
+
+         T0 t0_;
+         T1 t1_;
+         T2 t2_;
+         T3 t3_;
+      };
+
+      template <typename T>
+      inline bool is_sf4ext_node(const expression_node<T>* n)
+      {
+         switch (n->type())
+         {
+            case expression_node<T>::e_vovovov : return true;
+            case expression_node<T>::e_vovovoc : return true;
+            case expression_node<T>::e_vovocov : return true;
+            case expression_node<T>::e_vocovov : return true;
+            case expression_node<T>::e_covovov : return true;
+            case expression_node<T>::e_covocov : return true;
+            case expression_node<T>::e_vocovoc : return true;
+            case expression_node<T>::e_covovoc : return true;
+            case expression_node<T>::e_vococov : return true;
+            default                            : return false;
+         }
+      }
+
+      template <typename T, typename T0, typename T1>
+      struct T0oT1_define
+      {
+         typedef details::T0oT1<T,T0,T1> type0;
+      };
+
+      template <typename T, typename T0, typename T1, typename T2>
+      struct T0oT1oT2_define
+      {
+         typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode0> type0;
+         typedef details::T0oT1oT2<T,T0,T1,T2,typename T0oT1oT2process<T>::mode1> type1;
+         typedef details::T0oT1oT2_sf3<T,T0,T1,T2> sf3_type;
+         typedef details::sf3ext_type_node<T,T0,T1,T2> sf3_type_node;
+      };
+
+      template <typename T, typename T0, typename T1, typename T2, typename T3>
+      struct T0oT1oT2oT3_define
+      {
+         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode0> type0;
+         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode1> type1;
+         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode2> type2;
+         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode3> type3;
+         typedef details::T0oT1oT2oT3<T,T0,T1,T2,T3,typename T0oT1oT20T3process<T>::mode4> type4;
+         typedef details::T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> sf4_type;
+      };
+
+      template <typename T, typename Operation>
+      class vov_node : public vov_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // variable op variable node
+         explicit vov_node(const T& var0, const T& var1)
+         : v0_(var0),
+           v1_(var1)
+         {}
+
+         inline T value() const
+         {
+            return Operation::process(v0_,v1_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T& v0() const
+         {
+            return v0_;
+         }
+
+         inline const T& v1() const
+         {
+            return v1_;
+         }
+
+      protected:
+
+         const T& v0_;
+         const T& v1_;
+
+      private:
+
+         vov_node(vov_node<T,Operation>&);
+         vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
+      };
+
+      template <typename T, typename Operation>
+      class cov_node : public cov_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // constant op variable node
+         explicit cov_node(const T& const_var, const T& var)
+         : c_(const_var),
+           v_(var)
+         {}
+
+         inline T value() const
+         {
+            return Operation::process(c_,v_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T c() const
+         {
+            return c_;
+         }
+
+         inline const T& v() const
+         {
+            return v_;
+         }
+
+      protected:
+
+         const T  c_;
+         const T& v_;
+
+      private:
+
+         cov_node(const cov_node<T,Operation>&);
+         cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
+      };
+
+      template <typename T, typename Operation>
+      class voc_node : public voc_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // variable op constant node
+         explicit voc_node(const T& var, const T& const_var)
+         : v_(var),
+           c_(const_var)
+         {}
+
+         inline T value() const
+         {
+            return Operation::process(v_,c_);
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T c() const
+         {
+            return c_;
+         }
+
+         inline const T& v() const
+         {
+            return v_;
+         }
+
+      protected:
+
+         const T& v_;
+         const T  c_;
+
+      private:
+
+         voc_node(const voc_node<T,Operation>&);
+         voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
+      };
+
+      template <typename T, typename Operation>
+      class vob_node : public vob_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef Operation operation_t;
+
+         // variable op constant node
+         explicit vob_node(const T& var, const expression_ptr brnch)
+         : v_(var)
+         {
+            init_branches<1>(branch_,brnch);
+         }
+
+        ~vob_node()
+         {
+            cleanup_branches::execute<T,1>(branch_);
+         }
+
+         inline T value() const
+         {
+            return Operation::process(v_,branch_[0].first->value());
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T& v() const
+         {
+            return v_;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return branch_[0].first;
+         }
+
+      private:
+
+         vob_node(const vob_node<T,Operation>&);
+         vob_node<T,Operation>& operator=(const vob_node<T,Operation>&);
+
+         const T& v_;
+         branch_t branch_[1];
+      };
+
+      template <typename T, typename Operation>
+      class bov_node : public bov_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef Operation operation_t;
+
+         // variable op constant node
+         explicit bov_node(const expression_ptr brnch, const T& var)
+         : v_(var)
+         {
+            init_branches<1>(branch_,brnch);
+         }
+
+        ~bov_node()
+         {
+            cleanup_branches::execute<T,1>(branch_);
+         }
+
+         inline T value() const
+         {
+            return Operation::process(branch_[0].first->value(),v_);
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T& v() const
+         {
+            return v_;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return branch_[0].first;
+         }
+
+      private:
+
+         bov_node(const bov_node<T,Operation>&);
+         bov_node<T,Operation>& operator=(const bov_node<T,Operation>&);
+
+         const T& v_;
+         branch_t branch_[1];
+      };
+
+      template <typename T, typename Operation>
+      class cob_node : public cob_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef Operation operation_t;
+
+         // variable op constant node
+         explicit cob_node(const T const_var, const expression_ptr brnch)
+         : c_(const_var)
+         {
+            init_branches<1>(branch_,brnch);
+         }
+
+        ~cob_node()
+         {
+            cleanup_branches::execute<T,1>(branch_);
+         }
+
+         inline T value() const
+         {
+            return Operation::process(c_,branch_[0].first->value());
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T c() const
+         {
+            return c_;
+         }
+
+         inline void set_c(const T new_c)
+         {
+            (*const_cast<T*>(&c_)) = new_c;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return branch_[0].first;
+         }
+
+         inline expression_node<T>* move_branch(const std::size_t&)
+         {
+            branch_[0].second = false;
+            return branch_[0].first;
+         }
+
+      private:
+
+         cob_node(const cob_node<T,Operation>&);
+         cob_node<T,Operation>& operator=(const cob_node<T,Operation>&);
+
+         const T c_;
+         branch_t branch_[1];
+      };
+
+      template <typename T, typename Operation>
+      class boc_node : public boc_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr,bool> branch_t;
+         typedef Operation operation_t;
+
+         // variable op constant node
+         explicit boc_node(const expression_ptr brnch, const T const_var)
+         : c_(const_var)
+         {
+            init_branches<1>(branch_,brnch);
+         }
+
+        ~boc_node()
+         {
+            cleanup_branches::execute<T,1>(branch_);
+         }
+
+         inline T value() const
+         {
+            return Operation::process(branch_[0].first->value(),c_);
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline const T c() const
+         {
+            return c_;
+         }
+
+         inline void set_c(const T new_c)
+         {
+            (*const_cast<T*>(&c_)) = new_c;
+         }
+
+         inline expression_node<T>* branch(const std::size_t&) const
+         {
+            return branch_[0].first;
+         }
+
+         inline expression_node<T>* move_branch(const std::size_t&)
+         {
+            branch_[0].second = false;
+            return branch_[0].first;
+         }
+
+      private:
+
+         boc_node(const boc_node<T,Operation>&);
+         boc_node<T,Operation>& operator=(const boc_node<T,Operation>&);
+
+         const T c_;
+         branch_t branch_[1];
+      };
+
+      #ifndef exprtk_disable_string_capabilities
+      template <typename T, typename SType0, typename SType1, typename Operation>
+      class sos_node : public sos_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // string op string node
+         explicit sos_node(SType0 p0, SType1 p1)
+         : s0_(p0),
+           s1_(p1)
+         {}
+
+         inline T value() const
+         {
+            return Operation::process(s0_,s1_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline std::string& s0()
+         {
+            return s0_;
+         }
+
+         inline std::string& s1()
+         {
+            return s1_;
+         }
+
+      protected:
+
+         SType0 s0_;
+         SType1 s1_;
+
+      private:
+
+         sos_node(sos_node<T,SType0,SType1,Operation>&);
+         sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
+      };
+
+      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
+      class str_xrox_node : public sos_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // string-range op string node
+         explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
+         : s0_(p0),
+           s1_(p1),
+           rp0_(rp0)
+         {}
+
+        ~str_xrox_node()
+         {
+            rp0_.free();
+         }
+
+         inline T value() const
+         {
+            std::size_t r0 = 0;
+            std::size_t r1 = 0;
+
+            if (rp0_(r0,r1,s0_.size()))
+               return Operation::process(s0_.substr(r0,(r1 - r0) + 1),s1_);
+            else
+               return T(0);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline std::string& s0()
+         {
+            return s0_;
+         }
+
+         inline std::string& s1()
+         {
+            return s1_;
+         }
+
+      protected:
+
+         SType0    s0_;
+         SType1    s1_;
+         RangePack rp0_;
+
+      private:
+
+         str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
+         str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&);
+      };
+
+      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
+      class str_xoxr_node : public sos_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // string op string range node
+         explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
+         : s0_ (p0 ),
+           s1_ (p1 ),
+           rp1_(rp1)
+         {}
+
+        ~str_xoxr_node()
+         {
+            rp1_.free();
+         }
+
+         inline T value() const
+         {
+            std::size_t r0 = 0;
+            std::size_t r1 = 0;
+
+            if (rp1_(r0,r1,s1_.size()))
+               return Operation::process(s0_,s1_.substr(r0,(r1 - r0) + 1));
+            else
+               return T(0);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline std::string& s0()
+         {
+            return s0_;
+         }
+
+         inline std::string& s1()
+         {
+            return s1_;
+         }
+
+      protected:
+
+         SType0    s0_;
+         SType1    s1_;
+         RangePack rp1_;
+
+      private:
+
+         str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
+         str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&);
+      };
+
+      template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
+      class str_xroxr_node : public sos_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // string-range op string-range node
+         explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
+         : s0_ (p0 ),
+           s1_ (p1 ),
+           rp0_(rp0),
+           rp1_(rp1)
+         {}
+
+        ~str_xroxr_node()
+         {
+            rp0_.free();
+            rp1_.free();
+         }
+
+         inline T value() const
+         {
+            std::size_t r0_0 = 0;
+            std::size_t r0_1 = 0;
+            std::size_t r1_0 = 0;
+            std::size_t r1_1 = 0;
+            if (
+                 rp0_(r0_0,r1_0,s0_.size()) &&
+                 rp1_(r0_1,r1_1,s1_.size())
+               )
+            {
+               return Operation::process(
+                                          s0_.substr(r0_0,(r1_0 - r0_0) + 1),
+                                          s1_.substr(r0_1,(r1_1 - r0_1) + 1)
+                                        );
+            }
+            else
+               return T(0);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline std::string& s0()
+         {
+            return s0_;
+         }
+
+         inline std::string& s1()
+         {
+            return s1_;
+         }
+
+      protected:
+
+         SType0    s0_;
+         SType1    s1_;
+         RangePack rp0_;
+         RangePack rp1_;
+
+      private:
+
+         str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
+         str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&);
+      };
+
+      template <typename T, typename Operation>
+      class str_sogens_node : public binary_node<T>
+      {
+      public:
+
+         typedef expression_node <T>* expression_ptr;
+         typedef string_base_node<T>*   str_base_ptr;
+         typedef range_pack      <T>         range_t;
+         typedef range_t*                  range_ptr;
+         typedef range_interface<T>         irange_t;
+         typedef irange_t*                irange_ptr;
+
+         str_sogens_node(const operator_type& opr,
+                         expression_ptr branch0,
+                         expression_ptr branch1)
+         : binary_node<T>(opr,branch0,branch1),
+           str0_base_ptr_ (0),
+           str1_base_ptr_ (0),
+           str0_range_ptr_(0),
+           str1_range_ptr_(0)
+         {
+            if (is_generally_string_node(binary_node<T>::branch_[0].first))
+            {
+               str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
+
+               if (0 == str0_base_ptr_)
+                  return;
+
+               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
+
+               if (0 == range_ptr)
+                  return;
+
+               str0_range_ptr_ = &(range_ptr->range_ref());
+            }
+
+            if (is_generally_string_node(binary_node<T>::branch_[1].first))
+            {
+               str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == str1_base_ptr_)
+                  return;
+
+               irange_ptr range_ptr = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
+
+               if (0 == range_ptr)
+                  return;
+
+               str1_range_ptr_ = &(range_ptr->range_ref());
+            }
+         }
+
+         inline T value() const
+         {
+            if (
+                 str0_base_ptr_  &&
+                 str1_base_ptr_  &&
+                 str0_range_ptr_ &&
+                 str1_range_ptr_
+               )
+            {
+               binary_node<T>::branch_[0].first->value();
+               binary_node<T>::branch_[1].first->value();
+
+               std::size_t str0_r0 = 0;
+               std::size_t str0_r1 = 0;
+
+               std::size_t str1_r0 = 0;
+               std::size_t str1_r1 = 0;
+
+               range_t& range0 = (*str0_range_ptr_);
+               range_t& range1 = (*str1_range_ptr_);
+
+               if (
+                    range0(str0_r0,str0_r1,str0_base_ptr_->size()) &&
+                    range1(str1_r0,str1_r1,str1_base_ptr_->size())
+                  )
+               {
+                  return Operation::process(
+                                             str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
+                                             str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
+                                           );
+               }
+            }
+
+            return std::numeric_limits<T>::quiet_NaN();
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+      private:
+
+         str_sogens_node(str_sogens_node<T,Operation>&);
+         str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&);
+
+         str_base_ptr str0_base_ptr_;
+         str_base_ptr str1_base_ptr_;
+         range_ptr    str0_range_ptr_;
+         range_ptr    str1_range_ptr_;
+      };
+
+      template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
+      class sosos_node : public sosos_base_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef Operation operation_t;
+
+         // variable op variable node
+         explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
+         : s0_(p0),
+           s1_(p1),
+           s2_(p2)
+         {}
+
+         inline T value() const
+         {
+            return Operation::process(s0_,s1_,s2_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return Operation::type();
+         }
+
+         inline operator_type operation() const
+         {
+            return Operation::operation();
+         }
+
+         inline std::string& s0()
+         {
+            return s0_;
+         }
+
+         inline std::string& s1()
+         {
+            return s1_;
+         }
+
+         inline std::string& s2()
+         {
+            return s2_;
+         }
+
+      protected:
+
+         SType0 s0_;
+         SType1 s1_;
+         SType2 s2_;
+
+      private:
+
+         sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
+         sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
+      };
+      #endif
+
+      template <typename T, typename PowOp>
+      class ipow_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef PowOp operation_t;
+
+         explicit ipow_node(const T& v)
+         : v_(v)
+         {}
+
+         inline T value() const
+         {
+            return PowOp::result(v_);
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_ipow;
+         }
+
+      private:
+
+         ipow_node(const ipow_node<T,PowOp>&);
+         ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
+
+         const T& v_;
+      };
+
+      template <typename T, typename PowOp>
+      class bipow_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr, bool> branch_t;
+         typedef PowOp operation_t;
+
+         explicit bipow_node(expression_ptr brnch)
+         {
+            init_branches<1>(branch_, brnch);
+         }
+
+        ~bipow_node()
+         {
+            cleanup_branches::execute<T,1>(branch_);
+         }
+
+         inline T value() const
+         {
+            return PowOp::result(branch_[0].first->value());
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_ipow;
+         }
+
+      private:
+
+         bipow_node(const bipow_node<T,PowOp>&);
+         bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&);
+
+         branch_t branch_[1];
+      };
+
+      template <typename T, typename PowOp>
+      class ipowinv_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef PowOp operation_t;
+
+         explicit ipowinv_node(const T& v)
+         : v_(v)
+         {}
+
+         inline T value() const
+         {
+            return (T(1) / PowOp::result(v_));
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_ipowinv;
+         }
+
+      private:
+
+         ipowinv_node(const ipowinv_node<T,PowOp>&);
+         ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&);
+
+         const T& v_;
+      };
+
+      template <typename T, typename PowOp>
+      class bipowninv_node : public expression_node<T>
+      {
+      public:
+
+         typedef expression_node<T>* expression_ptr;
+         typedef std::pair<expression_ptr, bool> branch_t;
+         typedef PowOp operation_t;
+
+         explicit bipowninv_node(expression_ptr brnch)
+         {
+            init_branches<1>(branch_, brnch);
+         }
+
+        ~bipowninv_node()
+         {
+            cleanup_branches::execute<T,1>(branch_);
+         }
+
+         inline T value() const
+         {
+            return (T(1) / PowOp::result(branch_[0].first->value()));
+         }
+
+         inline typename expression_node<T>::node_type type() const
+         {
+            return expression_node<T>::e_ipowinv;
+         }
+
+      private:
+
+         bipowninv_node(const bipowninv_node<T,PowOp>&);
+         bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&);
+
+         branch_t branch_[1];
+      };
+
+      template <typename T>
+      inline bool is_vov_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const vov_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_cov_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const cov_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_voc_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const voc_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_cob_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const cob_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_boc_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const boc_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_t0ot1ot2_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_uv_node(const expression_node<T>* node)
+      {
+         return (0 != dynamic_cast<const uv_base_node<T>*>(node));
+      }
+
+      template <typename T>
+      inline bool is_string_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_stringvar == node->type());
+      }
+
+      template <typename T>
+      inline bool is_string_range_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_stringvarrng == node->type());
+      }
+
+      template <typename T>
+      inline bool is_const_string_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_stringconst == node->type());
+      }
+
+      template <typename T>
+      inline bool is_const_string_range_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_cstringvarrng == node->type());
+      }
+
+      template <typename T>
+      inline bool is_string_assignment_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_strass == node->type());
+      }
+
+      template <typename T>
+      inline bool is_string_concat_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_strconcat == node->type());
+      }
+
+      template <typename T>
+      inline bool is_string_function_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_strfunction == node->type());
+      }
+
+      template <typename T>
+      inline bool is_string_condition_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_strcondition == node->type());
+      }
+
+      template <typename T>
+      inline bool is_string_ccondition_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_strccondition == node->type());
+      }
+
+      template <typename T>
+      inline bool is_genricstring_range_node(const expression_node<T>* node)
+      {
+         return node && (expression_node<T>::e_strgenrange == node->type());
+      }
+
+      template <typename T>
+      inline bool is_generally_string_node(const expression_node<T>* node)
+      {
+         if (node)
+         {
+            switch (node->type())
+            {
+               case expression_node<T>::e_stringvar     :
+               case expression_node<T>::e_stringconst   :
+               case expression_node<T>::e_stringvarrng  :
+               case expression_node<T>::e_cstringvarrng :
+               case expression_node<T>::e_strgenrange   :
+               case expression_node<T>::e_strass        :
+               case expression_node<T>::e_strconcat     :
+               case expression_node<T>::e_strfunction   :
+               case expression_node<T>::e_strcondition  :
+               case expression_node<T>::e_strccondition : return true;
+               default                                  : return false;
+            }
+         }
+
+         return false;
+      }
+
+      class node_allocator
+      {
+      public:
+
+         template <typename ResultNode, typename OpType, typename ExprNode>
+         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
+         {
+            return allocate<ResultNode>(operation,branch[0]);
+         }
+
+         template <typename ResultNode, typename OpType, typename ExprNode>
+         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
+         {
+            return allocate<ResultNode>(operation,branch[0],branch[1]);
+         }
+
+         template <typename ResultNode, typename OpType, typename ExprNode>
+         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
+         {
+            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);
+         }
+
+         template <typename ResultNode, typename OpType, typename ExprNode>
+         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
+         {
+            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);
+         }
+
+         template <typename ResultNode, typename OpType, typename ExprNode>
+         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
+         {
+            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);
+         }
+
+         template <typename ResultNode, typename OpType, typename ExprNode>
+         inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
+         {
+            return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);
+         }
+
+         template <typename node_type>
+         inline expression_node<typename node_type::value_type>* allocate() const
+         {
+            return new node_type();
+         }
+
+         template <typename node_type,
+                   typename Type,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
+         {
+            return new node_type(seq);
+         }
+
+         template <typename node_type, typename T1>
+         inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
+         {
+            return new node_type(t1);
+         }
+
+         template <typename node_type, typename T1>
+         inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
+         {
+            return new node_type(t1);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
+         {
+            return new node_type(t1,t2);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2>
+         inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
+         {
+            return new node_type(t1,t2);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2>
+         inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
+         {
+            return new node_type(t1,t2);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2>
+         inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
+         {
+            return new node_type(t1,t2);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2>
+         inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
+         {
+            return new node_type(t1,t2);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2, typename T3>
+         inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const
+         {
+            return new node_type(t1,t2,t3);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2, typename T3, typename T4>
+         inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const
+         {
+            return new node_type(t1,t2,t3,t4);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2, typename T3>
+         inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
+         {
+            return new node_type(t1,t2,t3);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2, typename T3, typename T4>
+         inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const
+         {
+            return new node_type(t1,t2,t3,t4);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2, typename T3, typename T4, typename T5>
+         inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
+         {
+            return new node_type(t1,t2,t3,t4,t5);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2, typename T3>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                          const T3& t3) const
+         {
+            return new node_type(t1,t2,t3);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                          const T3& t3, const T4& t4) const
+         {
+            return new node_type(t1,t2,t3,t4);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4, typename T5>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                          const T3& t3, const T4& t4,
+                                                                          const T5& t5) const
+         {
+            return new node_type(t1,t2,t3,t4,t5);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4, typename T5, typename T6>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                          const T3& t3, const T4& t4,
+                                                                          const T5& t5, const T6& t6) const
+         {
+            return new node_type(t1,t2,t3,t4,t5,t6);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4,
+                   typename T5, typename T6, typename T7>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                          const T3& t3, const T4& t4,
+                                                                          const T5& t5, const T6& t6,
+                                                                          const T7& t7) const
+         {
+            return new node_type(t1,t2,t3,t4,t5,t6,t7);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4,
+                   typename T5, typename T6,
+                   typename T7, typename T8>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                          const T3& t3, const T4& t4,
+                                                                          const T5& t5, const T6& t6,
+                                                                          const T7& t7, const T8& t8) const
+         {
+            return new node_type(t1,t2,t3,t4,t5,t6,t7,t8);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4,
+                   typename T5, typename T6,
+                   typename T7, typename T8, typename T9>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
+                                                                          const T3& t3, const T4& t4,
+                                                                          const T5& t5, const T6& t6,
+                                                                          const T7& t7, const T8& t8,
+                                                                          const T9& t9) const
+         {
+            return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4,
+                   typename T5, typename T6,
+                   typename T7, typename T8,
+                   typename T9, typename T10>
+         inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const  T2&  t2,
+                                                                          const T3& t3, const  T4&  t4,
+                                                                          const T5& t5, const  T6&  t6,
+                                                                          const T7& t7, const  T8&  t8,
+                                                                          const T9& t9, const T10& t10) const
+         {
+            return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2, typename T3>
+         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
+         {
+            return new node_type(t1,t2,t3);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4>
+         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
+                                                                               T3 t3, T4 t4) const
+         {
+            return new node_type(t1,t2,t3,t4);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4,
+                   typename T5>
+         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
+                                                                               T3 t3, T4 t4,
+                                                                               T5 t5) const
+         {
+            return new node_type(t1,t2,t3,t4,t5);
+         }
+
+         template <typename node_type,
+                   typename T1, typename T2,
+                   typename T3, typename T4,
+                   typename T5, typename T6, typename T7>
+         inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2,
+                                                                               T3 t3, T4 t4,
+                                                                               T5 t5, T6 t6,
+                                                                               T7 t7) const
+         {
+            return new node_type(t1,t2,t3,t4,t5,t6,t7);
+         }
+
+         template <typename T>
+         void inline free(expression_node<T>*& e) const
+         {
+            delete e;
+            e = 0;
+         }
+      };
+
+      inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
+      {
+         #define register_op(Symbol,Type,Args)                                               \
+         m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
+
+         register_op(      "abs",e_abs     , 1)
+         register_op(     "acos",e_acos    , 1)
+         register_op(    "acosh",e_acosh   , 1)
+         register_op(     "asin",e_asin    , 1)
+         register_op(    "asinh",e_asinh   , 1)
+         register_op(     "atan",e_atan    , 1)
+         register_op(    "atanh",e_atanh   , 1)
+         register_op(     "ceil",e_ceil    , 1)
+         register_op(      "cos",e_cos     , 1)
+         register_op(     "cosh",e_cosh    , 1)
+         register_op(      "exp",e_exp     , 1)
+         register_op(    "expm1",e_expm1   , 1)
+         register_op(    "floor",e_floor   , 1)
+         register_op(      "log",e_log     , 1)
+         register_op(    "log10",e_log10   , 1)
+         register_op(     "log2",e_log2    , 1)
+         register_op(    "log1p",e_log1p   , 1)
+         register_op(    "round",e_round   , 1)
+         register_op(      "sin",e_sin     , 1)
+         register_op(     "sinc",e_sinc    , 1)
+         register_op(     "sinh",e_sinh    , 1)
+         register_op(      "sec",e_sec     , 1)
+         register_op(      "csc",e_csc     , 1)
+         register_op(     "sqrt",e_sqrt    , 1)
+         register_op(      "tan",e_tan     , 1)
+         register_op(     "tanh",e_tanh    , 1)
+         register_op(      "cot",e_cot     , 1)
+         register_op(  "rad2deg",e_r2d     , 1)
+         register_op(  "deg2rad",e_d2r     , 1)
+         register_op( "deg2grad",e_d2g     , 1)
+         register_op( "grad2deg",e_g2d     , 1)
+         register_op(      "sgn",e_sgn     , 1)
+         register_op(      "not",e_notl    , 1)
+         register_op(      "erf",e_erf     , 1)
+         register_op(     "erfc",e_erfc    , 1)
+         register_op(     "ncdf",e_ncdf    , 1)
+         register_op(     "frac",e_frac    , 1)
+         register_op(    "trunc",e_trunc   , 1)
+         register_op(    "atan2",e_atan2   , 2)
+         register_op(      "mod",e_mod     , 2)
+         register_op(     "logn",e_logn    , 2)
+         register_op(      "pow",e_pow     , 2)
+         register_op(     "root",e_root    , 2)
+         register_op(   "roundn",e_roundn  , 2)
+         register_op(    "equal",e_equal   , 2)
+         register_op("not_equal",e_nequal  , 2)
+         register_op(    "hypot",e_hypot   , 2)
+         register_op(      "shr",e_shr     , 2)
+         register_op(      "shl",e_shl     , 2)
+         register_op(    "clamp",e_clamp   , 3)
+         register_op(   "iclamp",e_iclamp  , 3)
+         register_op(  "inrange",e_inrange , 3)
+         #undef register_op
+      }
+
+   } // namespace details
+
+   class function_traits
+   {
+   public:
+
+      function_traits()
+      : allow_zero_parameters_(false),
+        has_side_effects_(true),
+        min_num_args_(0),
+        max_num_args_(std::numeric_limits<std::size_t>::max())
+      {}
+
+      inline bool& allow_zero_parameters()
+      {
+         return allow_zero_parameters_;
+      }
+
+      inline bool& has_side_effects()
+      {
+         return has_side_effects_;
+      }
+
+      std::size_t& min_num_args()
+      {
+         return min_num_args_;
+      }
+
+      std::size_t& max_num_args()
+      {
+         return max_num_args_;
+      }
+
+   private:
+
+      bool allow_zero_parameters_;
+      bool has_side_effects_;
+      std::size_t min_num_args_;
+      std::size_t max_num_args_;
+   };
+
+   template <typename FunctionType>
+   void enable_zero_parameters(FunctionType& func)
+   {
+      func.allow_zero_parameters() = true;
+
+      if (0 != func.min_num_args())
+      {
+         func.min_num_args() = 0;
+      }
+   }
+
+   template <typename FunctionType>
+   void disable_zero_parameters(FunctionType& func)
+   {
+      func.allow_zero_parameters() = false;
+   }
+
+   template <typename FunctionType>
+   void enable_has_side_effects(FunctionType& func)
+   {
+      func.has_side_effects() = true;
+   }
+
+   template <typename FunctionType>
+   void disable_has_side_effects(FunctionType& func)
+   {
+      func.has_side_effects() = false;
+   }
+
+   template <typename FunctionType>
+   void set_min_num_args(FunctionType& func, const std::size_t& num_args)
+   {
+      func.min_num_args() = num_args;
+
+      if ((0 != func.min_num_args()) && func.allow_zero_parameters())
+         func.allow_zero_parameters() = false;
+   }
+
+   template <typename FunctionType>
+   void set_max_num_args(FunctionType& func, const std::size_t& num_args)
+   {
+      func.max_num_args() = num_args;
+   }
+
+   template <typename T>
+   class ifunction : public function_traits
+   {
+   public:
+
+      explicit ifunction(const std::size_t& pc)
+      : param_count(pc)
+      {}
+
+      virtual ~ifunction()
+      {}
+
+      inline virtual T operator()()
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&,const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
+                                  const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      std::size_t param_count;
+   };
+
+   template <typename T>
+   class ivararg_function : public function_traits
+   {
+   public:
+
+      virtual ~ivararg_function()
+      {}
+
+      inline virtual T operator()(const std::vector<T>&)
+      {
+         exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+   };
+
+   template <typename T>
+   class igeneric_function : public function_traits
+   {
+   public:
+
+      enum return_type
+      {
+         e_rtrn_scalar = 0,
+         e_rtrn_string = 1
+      };
+
+      typedef T type;
+      typedef type_store<T> generic_type;
+      typedef typename generic_type::parameter_list parameter_list_t;
+
+      igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
+      : parameter_sequence(param_seq),
+        rtrn_type(rtr_type)
+      {}
+
+      virtual ~igeneric_function()
+      {}
+
+      // f(i_0,i_1,....,i_N) --> Scalar
+      inline virtual T operator()(parameter_list_t)
+      {
+         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [1]\n"));
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      // f(i_0,i_1,....,i_N) --> String
+      inline virtual T operator()(std::string&, parameter_list_t)
+      {
+         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [2]\n"));
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      // f(psi,i_0,i_1,....,i_N) --> Scalar
+      inline virtual T operator()(const std::size_t&, parameter_list_t)
+      {
+         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [3]\n"));
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      // f(psi,i_0,i_1,....,i_N) --> String
+      inline virtual T operator()(const std::size_t&, std::string&, parameter_list_t)
+      {
+         exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. [4]\n"));
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      std::string parameter_sequence;
+      return_type rtrn_type;
+   };
+
+   template <typename T> class parser;
+   template <typename T> class expression_helper;
+
+   template <typename T>
+   class symbol_table
+   {
+   public:
+
+      typedef T (*ff1_functor)(T);
+      typedef T (*ff2_functor)(T,T);
+      typedef T (*ff3_functor)(T,T,T);
+      typedef T (*ff4_functor)(T,T,T,T);
+      typedef T (*ff5_functor)(T,T,T,T,T);
+
+   protected:
+
+      struct freefunc1 : public exprtk::ifunction<T>
+      {
+         freefunc1(ff1_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
+         inline T operator()(const T& v0)
+         { return f(v0); }
+         ff1_functor f;
+      };
+
+      struct freefunc2 : public exprtk::ifunction<T>
+      {
+         freefunc2(ff2_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
+         inline T operator()(const T& v0, const T& v1)
+         { return f(v0,v1); }
+         ff2_functor f;
+      };
+
+      struct freefunc3 : public exprtk::ifunction<T>
+      {
+         freefunc3(ff3_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
+         inline T operator()(const T& v0, const T& v1, const T& v2)
+         { return f(v0,v1,v2); }
+         ff3_functor f;
+      };
+
+      struct freefunc4 : public exprtk::ifunction<T>
+      {
+         freefunc4(ff4_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
+         inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3)
+         { return f(v0,v1,v2,v3); }
+         ff4_functor f;
+      };
+
+      struct freefunc5 : public exprtk::ifunction<T>
+      {
+         freefunc5(ff5_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
+         inline T operator()(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
+         { return f(v0,v1,v2,v3,v4); }
+         ff5_functor f;
+      };
+
+      template <typename Type, typename RawType>
+      struct type_store
+      {
+         typedef details::expression_node<T>*        expression_ptr;
+         typedef typename details::variable_node<T>  variable_node_t;
+         typedef ifunction<T>                        ifunction_t;
+         typedef ivararg_function<T>                 ivararg_function_t;
+         typedef igeneric_function<T>                igeneric_function_t;
+         typedef details::vector_holder<T>           vector_t;
+         #ifndef exprtk_disable_string_capabilities
+         typedef typename details::stringvar_node<T> stringvar_node_t;
+         #endif
+
+         typedef Type type_t;
+         typedef type_t* type_ptr;
+         typedef std::pair<bool,type_ptr> type_pair_t;
+         typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
+         typedef typename type_map_t::iterator tm_itr_t;
+         typedef typename type_map_t::const_iterator tm_const_itr_t;
+
+         enum { lut_size = 256 };
+
+         type_map_t  map;
+         std::size_t size;
+
+         type_store()
+         : size(0)
+         {}
+
+         inline bool symbol_exists(const std::string& symbol_name) const
+         {
+            if (symbol_name.empty())
+               return false;
+            else if (map.end() != map.find(symbol_name))
+               return true;
+            else
+               return false;
+         }
+
+         template <typename PtrType>
+         inline std::string entity_name(const PtrType& ptr) const
+         {
+            if (map.empty())
+               return std::string();
+
+            tm_const_itr_t itr = map.begin();
+
+            while (map.end() != itr)
+            {
+               if (itr->second.second == ptr)
+               {
+                  return itr->first;
+               }
+               else
+                  ++itr;
+            }
+
+            return std::string();
+         }
+
+         inline bool is_constant(const std::string& symbol_name) const
+         {
+            if (symbol_name.empty())
+               return false;
+            else
+            {
+               tm_const_itr_t itr = map.find(symbol_name);
+
+               if (map.end() == itr)
+                  return false;
+               else
+                  return (*itr).second.first;
+            }
+         }
+
+         template <typename Tie, typename RType>
+         inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
+         {
+            if (symbol_name.size() > 1)
+            {
+               for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
+               {
+                  if (details::imatch(symbol_name,details::reserved_symbols[i]))
+                  {
+                     return false;
+                  }
+               }
+            }
+
+            tm_itr_t itr = map.find(symbol_name);
+
+            if (map.end() == itr)
+            {
+               map[symbol_name] = Tie::make(t,is_const);
+               ++size;
+            }
+
+            return true;
+         }
+
+         struct tie_array
+         {
+            static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
+            {
+               return std::make_pair(is_const,new vector_t(v.first,v.second));
+            }
+         };
+
+         struct tie_stdvec
+         {
+            template <typename Allocator>
+            static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
+            {
+               return std::make_pair(is_const,new vector_t(v));
+            }
+         };
+
+         struct tie_stddeq
+         {
+            template <typename Allocator>
+            static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
+            {
+               return std::make_pair(is_const,new vector_t(v));
+            }
+         };
+
+         template <std::size_t v_size>
+         inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
+         {
+            return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_const);
+         }
+
+         inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
+         {
+            return add_impl<tie_array,std::pair<T*,std::size_t> >(symbol_name,std::make_pair(v,v_size),is_const);
+         }
+
+         template <typename Allocator>
+         inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
+         {
+            return add_impl<tie_stdvec,std::vector<T,Allocator>&>(symbol_name,v,is_const);
+         }
+
+         template <typename Allocator>
+         inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
+         {
+            return add_impl<tie_stddeq,std::deque<T,Allocator>&>(symbol_name,v,is_const);
+         }
+
+         inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
+         {
+            struct tie
+            {
+               static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
+               {
+                  return std::make_pair(is_const,new variable_node_t(t));
+               }
+
+               #ifndef exprtk_disable_string_capabilities
+               static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
+               {
+                  return std::make_pair(is_const,new stringvar_node_t(t));
+               }
+               #endif
+
+               static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
+               {
+                  return std::make_pair(is_constant,&t);
+               }
+
+               static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
+               {
+                  return std::make_pair(is_const,&t);
+               }
+
+               static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
+               {
+                  return std::make_pair(is_constant,&t);
+               }
+            };
+
+            tm_itr_t itr = map.find(symbol_name);
+
+            if (map.end() == itr)
+            {
+               map[symbol_name] = tie::make(t,is_const);
+               ++size;
+            }
+
+            return true;
+         }
+
+         inline type_ptr get(const std::string& symbol_name) const
+         {
+            tm_const_itr_t itr = map.find(symbol_name);
+
+            if (map.end() == itr)
+               return reinterpret_cast<type_ptr>(0);
+            else
+               return itr->second.second;
+         }
+
+         template <typename TType, typename TRawType, typename PtrType>
+         struct ptr_match
+         {
+            static inline bool test(const PtrType, const void*)
+            {
+               return false;
+            }
+         };
+
+         template <typename TType, typename TRawType>
+         struct ptr_match<TType,TRawType,variable_node_t*>
+         {
+            static inline bool test(const variable_node_t* p, const void* ptr)
+            {
+               exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
+               return (&(p->ref()) == ptr);
+            }
+         };
+
+         inline type_ptr get_from_varptr(const void* ptr) const
+         {
+            tm_const_itr_t itr = map.begin();
+
+            while (map.end() != itr)
+            {
+               type_ptr ret_ptr = itr->second.second;
+
+               if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
+               {
+                  return ret_ptr;
+               }
+
+               ++itr;
+            }
+
+            return type_ptr(0);
+         }
+
+         inline bool remove(const std::string& symbol_name, const bool delete_node = true)
+         {
+            tm_itr_t itr = map.find(symbol_name);
+
+            if (map.end() != itr)
+            {
+               struct deleter
+               {
+                  static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
+                  static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
+                  #ifndef exprtk_disable_string_capabilities
+                  static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
+                  #endif
+                  static inline void process(std::pair<bool,function_t*>&)         {                  }
+               };
+
+               if (delete_node)
+               {
+                  deleter::process((*itr).second);
+               }
+
+               map.erase(itr);
+               --size;
+
+               return true;
+            }
+            else
+               return false;
+         }
+
+         inline RawType& type_ref(const std::string& symbol_name)
+         {
+            struct init_type
+            {
+               static inline double set(double)           { return (0.0);           }
+               static inline double set(long double)      { return (0.0);           }
+               static inline float  set(float)            { return (0.0f);          }
+               static inline std::string set(std::string) { return std::string(""); }
+            };
+
+            static RawType null_type = init_type::set(RawType());
+
+            tm_const_itr_t itr = map.find(symbol_name);
+            if (map.end() == itr)
+               return null_type;
+            else
+               return itr->second.second->ref();
+         }
+
+         inline void clear(const bool delete_node = true)
+         {
+            struct deleter
+            {
+               static inline void process(std::pair<bool,variable_node_t*>& n)  { delete n.second; }
+               static inline void process(std::pair<bool,vector_t*>& n)         { delete n.second; }
+               static inline void process(std::pair<bool,function_t*>&)         {                  }
+               #ifndef exprtk_disable_string_capabilities
+               static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
+               #endif
+            };
+
+            if (!map.empty())
+            {
+               if (delete_node)
+               {
+                  tm_itr_t itr = map.begin();
+                  tm_itr_t end = map.end();
+
+                  while (end != itr)
+                  {
+                     deleter::process((*itr).second);
+                     ++itr;
+                  }
+               }
+
+               map.clear();
+            }
+
+            size = 0;
+         }
+
+         template <typename Allocator,
+                   template <typename, typename> class Sequence>
+         inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
+         {
+            std::size_t count = 0;
+
+            if (!map.empty())
+            {
+               tm_const_itr_t itr = map.begin();
+               tm_const_itr_t end = map.end();
+
+               while (end != itr)
+               {
+                  list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
+                  ++itr;
+                  ++count;
+               }
+            }
+
+            return count;
+         }
+
+         template <typename Allocator,
+                   template <typename, typename> class Sequence>
+         inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
+         {
+            std::size_t count = 0;
+
+            if (!map.empty())
+            {
+               tm_const_itr_t itr = map.begin();
+               tm_const_itr_t end = map.end();
+
+               while (end != itr)
+               {
+                  vlist.push_back((*itr).first);
+                  ++itr;
+                  ++count;
+               }
+            }
+
+            return count;
+         }
+      };
+
+      typedef details::expression_node<T>* expression_ptr;
+      typedef typename details::variable_node<T> variable_t;
+      typedef typename details::vector_holder<T> vector_holder_t;
+      typedef variable_t* variable_ptr;
+      #ifndef exprtk_disable_string_capabilities
+      typedef typename details::stringvar_node<T> stringvar_t;
+      typedef stringvar_t* stringvar_ptr;
+      #endif
+      typedef ifunction        <T> function_t;
+      typedef ivararg_function <T> vararg_function_t;
+      typedef igeneric_function<T> generic_function_t;
+      typedef function_t* function_ptr;
+      typedef vararg_function_t*  vararg_function_ptr;
+      typedef generic_function_t* generic_function_ptr;
+
+      static const std::size_t lut_size = 256;
+
+      // Symbol Table Holder
+      struct st_holder
+      {
+         struct st_data
+         {
+            type_store<typename details::variable_node<T>,T> variable_store;
+            #ifndef exprtk_disable_string_capabilities
+            type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
+            #endif
+            type_store<ifunction<T>,ifunction<T> > function_store;
+            type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store;
+            type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store;
+            type_store<igeneric_function<T>,igeneric_function<T> > string_function_store;
+            type_store<vector_holder_t,vector_holder_t> vector_store;
+
+            st_data()
+            {
+               for (std::size_t i = 0; i < details::reserved_words_size; ++i)
+               {
+                  reserved_symbol_table_.insert(details::reserved_words[i]);
+               }
+
+               for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
+               {
+                  reserved_symbol_table_.insert(details::reserved_symbols[i]);
+               }
+            }
+
+           ~st_data()
+            {
+               for (std::size_t i = 0; i < free_function_list_.size(); ++i)
+               {
+                  delete free_function_list_[i];
+               }
+            }
+
+            inline bool is_reserved_symbol(const std::string& symbol) const
+            {
+               return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
+            }
+
+            std::list<T>               local_symbol_list_;
+            std::list<std::string>     local_stringvar_list_;
+            std::set<std::string>      reserved_symbol_table_;
+            std::vector<ifunction<T>*> free_function_list_;
+         };
+
+         st_holder()
+         : ref_count(1),
+           data_(new st_data)
+         {}
+
+         st_holder(st_data* data)
+         : ref_count(1),
+           data_(data)
+         {}
+
+        ~st_holder()
+         {
+            if (data_ && (0 == ref_count))
+            {
+               delete data_;
+               data_ = 0;
+            }
+         }
+
+         std::size_t ref_count;
+         st_data* data_;
+      };
+
+   public:
+
+      symbol_table()
+      : holder_(new st_holder)
+      {
+         clear();
+      }
+
+     ~symbol_table()
+      {
+         if (holder_)
+         {
+            if (0 == --holder_->ref_count)
+            {
+               clear();
+               delete holder_;
+            }
+         }
+      }
+
+      symbol_table(const symbol_table<T>& st)
+      {
+         holder_ = st.holder_;
+         holder_->ref_count++;
+      }
+
+      inline symbol_table<T>& operator=(const symbol_table<T>& st)
+      {
+         if (holder_)
+         {
+            if (0 == --holder_->ref_count)
+            {
+               delete holder_;
+            }
+
+            holder_ = 0;
+         }
+
+         holder_ = st.holder_;
+         holder_->ref_count++;
+
+         return *this;
+      }
+
+      inline bool operator==(const symbol_table<T>& st)
+      {
+         return (this == &st) || (holder_ == st.holder_);
+      }
+
+      inline void clear_variables(const bool delete_node = true)
+      {
+         local_data().variable_store.clear(delete_node);
+      }
+
+      inline void clear_functions()
+      {
+         local_data().function_store.clear();
+      }
+
+      inline void clear_strings()
+      {
+         #ifndef exprtk_disable_string_capabilities
+         local_data().stringvar_store.clear();
+         #endif
+      }
+
+      inline void clear_vectors()
+      {
+         local_data().vector_store.clear();
+      }
+
+      inline void clear()
+      {
+         if (!valid()) return;
+         clear_variables();
+         clear_functions();
+         clear_strings  ();
+         clear_vectors  ();
+      }
+
+      inline std::size_t variable_count() const
+      {
+         if (valid())
+            return local_data().variable_store.size;
+         else
+            return 0;
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline std::size_t stringvar_count() const
+      {
+         if (valid())
+            return local_data().stringvar_store.size;
+         else
+            return 0;
+      }
+      #endif
+
+      inline std::size_t function_count() const
+      {
+         if (valid())
+            return local_data().function_store.size;
+         else
+            return 0;
+      }
+
+      inline std::size_t vector_count() const
+      {
+         if (valid())
+            return local_data().vector_store.size;
+         else
+            return 0;
+      }
+
+      inline variable_ptr get_variable(const std::string& variable_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<variable_ptr>(0);
+         else if (!valid_symbol(variable_name))
+            return reinterpret_cast<variable_ptr>(0);
+         else
+            return local_data().variable_store.get(variable_name);
+      }
+
+      inline variable_ptr get_variable(const T& var_ref) const
+      {
+         if (!valid())
+            return reinterpret_cast<variable_ptr>(0);
+         else
+            return local_data().variable_store.get_from_varptr(
+                                                  reinterpret_cast<const void*>(&var_ref));
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline stringvar_ptr get_stringvar(const std::string& string_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<stringvar_ptr>(0);
+         else if (!valid_symbol(string_name))
+            return reinterpret_cast<stringvar_ptr>(0);
+         else
+            return local_data().stringvar_store.get(string_name);
+      }
+      #endif
+
+      inline function_ptr get_function(const std::string& function_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<function_ptr>(0);
+         else if (!valid_symbol(function_name))
+            return reinterpret_cast<function_ptr>(0);
+         else
+            return local_data().function_store.get(function_name);
+      }
+
+      inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<vararg_function_ptr>(0);
+         else if (!valid_symbol(vararg_function_name))
+            return reinterpret_cast<vararg_function_ptr>(0);
+         else
+            return local_data().vararg_function_store.get(vararg_function_name);
+      }
+
+      inline generic_function_ptr get_generic_function(const std::string& function_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<generic_function_ptr>(0);
+         else if (!valid_symbol(function_name))
+            return reinterpret_cast<generic_function_ptr>(0);
+         else
+            return local_data().generic_function_store.get(function_name);
+      }
+
+      inline generic_function_ptr get_string_function(const std::string& function_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<generic_function_ptr>(0);
+         else if (!valid_symbol(function_name))
+            return reinterpret_cast<generic_function_ptr>(0);
+         else
+            return local_data().string_function_store.get(function_name);
+      }
+
+      typedef vector_holder_t* vector_holder_ptr;
+
+      inline vector_holder_ptr get_vector(const std::string& vector_name) const
+      {
+         if (!valid())
+            return reinterpret_cast<vector_holder_ptr>(0);
+         else if (!valid_symbol(vector_name))
+            return reinterpret_cast<vector_holder_ptr>(0);
+         else
+            return local_data().vector_store.get(vector_name);
+      }
+
+      inline T& variable_ref(const std::string& symbol_name)
+      {
+         static T null_var = T(0);
+         if (!valid())
+            return null_var;
+         else if (!valid_symbol(symbol_name))
+            return null_var;
+         else
+            return local_data().variable_store.type_ref(symbol_name);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline std::string& stringvar_ref(const std::string& symbol_name)
+      {
+         static std::string null_stringvar;
+         if (!valid())
+            return null_stringvar;
+         else if (!valid_symbol(symbol_name))
+            return null_stringvar;
+         else
+            return local_data().stringvar_store.type_ref(symbol_name);
+      }
+      #endif
+
+      inline bool is_constant_node(const std::string& symbol_name) const
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(symbol_name))
+            return false;
+         else
+            return local_data().variable_store.is_constant(symbol_name);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline bool is_constant_string(const std::string& symbol_name) const
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(symbol_name))
+            return false;
+         else if (!local_data().stringvar_store.symbol_exists(symbol_name))
+            return false;
+         else
+            return local_data().stringvar_store.is_constant(symbol_name);
+      }
+      #endif
+
+      inline bool create_variable(const std::string& variable_name, const T& value = T(0))
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(variable_name))
+            return false;
+         else if (symbol_exists(variable_name))
+            return false;
+
+         local_data().local_symbol_list_.push_back(value);
+         T& t = local_data().local_symbol_list_.back();
+
+         return add_variable(variable_name,t);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(stringvar_name))
+            return false;
+         else if (symbol_exists(stringvar_name))
+            return false;
+
+         local_data().local_stringvar_list_.push_back(value);
+         std::string& s = local_data().local_stringvar_list_.back();
+
+         return add_stringvar(stringvar_name,s);
+      }
+      #endif
+
+      inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(variable_name))
+            return false;
+         else if (symbol_exists(variable_name))
+            return false;
+         else
+            return local_data().variable_store.add(variable_name,t,is_constant);
+      }
+
+      inline bool add_constant(const std::string& constant_name, const T& value)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(constant_name))
+            return false;
+         else if (symbol_exists(constant_name))
+            return false;
+
+         local_data().local_symbol_list_.push_back(value);
+         T& t = local_data().local_symbol_list_.back();
+
+         return add_variable(constant_name,t,true);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(stringvar_name))
+            return false;
+         else if (symbol_exists(stringvar_name))
+            return false;
+         else
+            return local_data().stringvar_store.add(stringvar_name,s,is_constant);
+      }
+      #endif
+
+      inline bool add_function(const std::string& function_name, function_t& function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+         else
+            return local_data().function_store.add(function_name,function);
+      }
+
+      inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(vararg_function_name))
+            return false;
+         else if (symbol_exists(vararg_function_name))
+            return false;
+         else
+            return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
+      }
+
+      inline bool add_function(const std::string& function_name, generic_function_t& function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+         else if (std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|"))
+            return false;
+         else if (generic_function_t::e_rtrn_scalar == function.rtrn_type)
+            return local_data().generic_function_store.add(function_name,function);
+         else if (generic_function_t::e_rtrn_string == function.rtrn_type)
+            return local_data().string_function_store.add(function_name, function);
+         else
+            return false;
+      }
+
+      inline bool add_function(const std::string& function_name, ff1_functor function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+
+         exprtk::ifunction<T>* ifunc = new freefunc1(function);
+
+         local_data().free_function_list_.push_back(ifunc);
+
+         return add_function(function_name,(*local_data().free_function_list_.back()));
+      }
+
+      inline bool add_function(const std::string& function_name, ff2_functor function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+
+         exprtk::ifunction<T>* ifunc = new freefunc2(function);
+
+         local_data().free_function_list_.push_back(ifunc);
+
+         return add_function(function_name,(*local_data().free_function_list_.back()));
+      }
+
+      inline bool add_function(const std::string& function_name, ff3_functor function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+
+         exprtk::ifunction<T>* ifunc = new freefunc3(function);
+
+         local_data().free_function_list_.push_back(ifunc);
+
+         return add_function(function_name,(*local_data().free_function_list_.back()));
+      }
+
+      inline bool add_function(const std::string& function_name, ff4_functor function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+
+         exprtk::ifunction<T>* ifunc = new freefunc4(function);
+
+         local_data().free_function_list_.push_back(ifunc);
+
+         return add_function(function_name,(*local_data().free_function_list_.back()));
+      }
+
+      inline bool add_function(const std::string& function_name, ff5_functor function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name))
+            return false;
+         else if (symbol_exists(function_name))
+            return false;
+
+         exprtk::ifunction<T>* ifunc = new freefunc5(function);
+
+         local_data().free_function_list_.push_back(ifunc);
+
+         return add_function(function_name,(*local_data().free_function_list_.back()));
+      }
+
+      inline bool add_reserved_function(const std::string& function_name, function_t& function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name,false))
+            return false;
+         else if (symbol_exists(function_name,false))
+            return false;
+         else
+            return local_data().function_store.add(function_name,function);
+      }
+
+      inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(vararg_function_name,false))
+            return false;
+         else if (symbol_exists(vararg_function_name,false))
+            return false;
+         else
+            return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
+      }
+
+      inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(function_name,false))
+            return false;
+         else if (symbol_exists(function_name,false))
+            return false;
+         else if (std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|"))
+            return false;
+         else if (generic_function_t::e_rtrn_scalar == function.rtrn_type)
+            return local_data().generic_function_store.add(function_name,function);
+         else if (generic_function_t::e_rtrn_string == function.rtrn_type)
+            return local_data().string_function_store.add(function_name, function);
+         else
+            return false;
+      }
+
+      template <std::size_t N>
+      inline bool add_vector(const std::string& vector_name, T (&v)[N])
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(vector_name))
+            return false;
+         else if (symbol_exists(vector_name))
+            return false;
+         else
+            return local_data().vector_store.add(vector_name,v);
+      }
+
+      inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(vector_name))
+            return false;
+         else if (symbol_exists(vector_name))
+            return false;
+         else
+            return local_data().vector_store.add(vector_name,v,v_size);
+      }
+
+      template <typename Allocator>
+      inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(vector_name))
+            return false;
+         else if (symbol_exists(vector_name))
+            return false;
+         else
+            return local_data().vector_store.add(vector_name,v);
+      }
+
+      template <typename Allocator>
+      inline bool add_vector(const std::string& vector_name, std::deque<T,Allocator>& v)
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(vector_name))
+            return false;
+         else if (symbol_exists(vector_name))
+            return false;
+         else
+            return local_data().vector_store.add(vector_name,v);
+      }
+
+      inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().variable_store.remove(variable_name, delete_node);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline bool remove_stringvar(const std::string& string_name)
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().stringvar_store.remove(string_name);
+      }
+      #endif
+
+      inline bool remove_function(const std::string& function_name)
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().function_store.remove(function_name);
+      }
+
+      inline bool remove_vararg_function(const std::string& vararg_function_name)
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().vararg_function_store.remove(vararg_function_name);
+      }
+
+      inline bool remove_vector(const std::string& vector_name)
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().vector_store.remove(vector_name);
+      }
+
+      inline bool add_constants()
+      {
+         return add_pi      () &&
+                add_epsilon () &&
+                add_infinity();
+      }
+
+      inline bool add_pi()
+      {
+         static const T local_pi = T(details::numeric::constant::pi);
+         return add_constant("pi",local_pi);
+      }
+
+      inline bool add_epsilon()
+      {
+         static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
+         return add_constant("epsilon",local_epsilon);
+      }
+
+      inline bool add_infinity()
+      {
+         static const T local_infinity = std::numeric_limits<T>::infinity();
+         return add_constant("inf",local_infinity);
+      }
+
+      template <typename Allocator,
+                template <typename, typename> class Sequence>
+      inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
+      {
+         if (!valid())
+            return 0;
+         else
+            return local_data().variable_store.get_list(vlist);
+      }
+
+      template <typename Allocator,
+                template <typename, typename> class Sequence>
+      inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
+      {
+         if (!valid())
+            return 0;
+         else
+            return local_data().variable_store.get_list(vlist);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      template <typename Allocator,
+                template <typename, typename> class Sequence>
+      inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
+      {
+         if (!valid())
+            return 0;
+         else
+            return local_data().stringvar_store.get_list(svlist);
+      }
+
+      template <typename Allocator,
+                template <typename, typename> class Sequence>
+      inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
+      {
+         if (!valid())
+            return 0;
+         else
+            return local_data().stringvar_store.get_list(svlist);
+      }
+      #endif
+
+      template <typename Allocator,
+                template <typename, typename> class Sequence>
+      inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
+      {
+         if (!valid())
+            return 0;
+         else
+            return local_data().vector_store.get_list(vlist);
+      }
+
+      inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
+      {
+         /*
+            Will return true if symbol_name exists as either a reserved symbol,
+            variable, stringvar or function name in any of the type stores.
+         */
+         if (!valid())
+            return false;
+         else if (local_data().variable_store.symbol_exists(symbol_name))
+            return true;
+         #ifndef exprtk_disable_string_capabilities
+         else if (local_data().stringvar_store.symbol_exists(symbol_name))
+            return true;
+         #endif
+         else if (local_data().function_store.symbol_exists(symbol_name))
+            return true;
+         else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
+            return true;
+         else
+            return false;
+      }
+
+      inline bool is_variable(const std::string& variable_name) const
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().variable_store.symbol_exists(variable_name);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline bool is_stringvar(const std::string& stringvar_name) const
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().stringvar_store.symbol_exists(stringvar_name);
+      }
+
+      inline bool is_conststr_stringvar(const std::string& symbol_name) const
+      {
+         if (!valid())
+            return false;
+         else if (!valid_symbol(symbol_name))
+            return false;
+         else if (!local_data().stringvar_store.symbol_exists(symbol_name))
+            return false;
+
+         return (
+                  local_data().stringvar_store.symbol_exists(symbol_name) ||
+                  local_data().stringvar_store.is_constant  (symbol_name)
+                );
+      }
+      #endif
+
+      inline bool is_function(const std::string& function_name) const
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().function_store.symbol_exists(function_name);
+      }
+
+      inline bool is_vararg_function(const std::string& vararg_function_name) const
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().vararg_function_store.symbol_exists(vararg_function_name);
+      }
+
+      inline bool is_vector(const std::string& vector_name) const
+      {
+         if (!valid())
+            return false;
+         else
+            return local_data().vector_store.symbol_exists(vector_name);
+      }
+
+      inline std::string get_variable_name(const expression_ptr& ptr) const
+      {
+         return local_data().variable_store.entity_name(ptr);
+      }
+
+      inline std::string get_vector_name(const vector_holder_ptr& ptr) const
+      {
+         return local_data().vector_store.entity_name(ptr);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline std::string get_stringvar_name(const expression_ptr& ptr) const
+      {
+         return local_data().stringvar_store.entity_name(ptr);
+      }
+
+      inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const
+      {
+         return local_data().stringvar_store.entity_name(ptr);
+      }
+      #endif
+
+      inline bool valid() const
+      {
+         // Symbol table sanity check.
+         return holder_ && holder_->data_;
+      }
+
+      inline void load_from(const symbol_table<T>& st)
+      {
+         {
+            std::vector<std::string> name_list;
+
+            st.local_data().function_store.get_list(name_list);
+
+            if (!name_list.empty())
+            {
+               for (std::size_t i = 0; i < name_list.size(); ++i)
+               {
+                  exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
+                  add_function(name_list[i],ifunc);
+               }
+            }
+         }
+
+         {
+            std::vector<std::string> name_list;
+
+            st.local_data().vararg_function_store.get_list(name_list);
+
+            if (!name_list.empty())
+            {
+               for (std::size_t i = 0; i < name_list.size(); ++i)
+               {
+                  exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
+                  add_function(name_list[i],ivafunc);
+               }
+            }
+         }
+
+         {
+            std::vector<std::string> name_list;
+
+            st.local_data().generic_function_store.get_list(name_list);
+
+            if (!name_list.empty())
+            {
+               for (std::size_t i = 0; i < name_list.size(); ++i)
+               {
+                  exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
+                  add_function(name_list[i],ifunc);
+               }
+            }
+         }
+
+         {
+            std::vector<std::string> name_list;
+
+            st.local_data().string_function_store.get_list(name_list);
+
+            if (!name_list.empty())
+            {
+               for (std::size_t i = 0; i < name_list.size(); ++i)
+               {
+                  exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
+                  add_function(name_list[i],ifunc);
+               }
+            }
+         }
+      }
+
+   private:
+
+      inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
+      {
+         if (symbol.empty())
+            return false;
+         if (!details::is_letter(symbol[0]))
+            return false;
+         else if (symbol.size() > 1)
+         {
+            for (std::size_t i = 1; i < symbol.size(); ++i)
+            {
+               if (
+                    (!details::is_letter(symbol[i])) &&
+                    (!details:: is_digit(symbol[i])) &&
+                    ('_' != symbol[i])
+                  )
+               {
+                  return false;
+               }
+            }
+         }
+
+         return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
+      }
+
+      inline bool valid_function(const std::string& symbol) const
+      {
+         if (symbol.empty())
+            return false;
+         if (!details::is_letter(symbol[0]))
+            return false;
+         else if (symbol.size() > 1)
+         {
+            for (std::size_t i = 1; i < symbol.size(); ++i)
+            {
+               if (
+                    (!details::is_letter(symbol[i])) &&
+                    (!details:: is_digit(symbol[i])) &&
+                    ('_' != symbol[i])
+                  )
+               {
+                  return false;
+               }
+            }
+         }
+
+         return true;
+      }
+
+      typedef typename st_holder::st_data local_data_t;
+
+      inline local_data_t& local_data()
+      {
+         return *(holder_->data_);
+      }
+
+      inline const local_data_t& local_data() const
+      {
+         return *(holder_->data_);
+      }
+
+      st_holder* holder_;
+
+      friend class parser<T>;
+   };
+
+   template <typename T>
+   class function_compositor;
+
+   template <typename T>
+   class expression
+   {
+   private:
+
+      typedef details::expression_node<T>*  expression_ptr;
+      typedef details::vector_holder<T>* vector_holder_ptr;
+      typedef std::vector<symbol_table<T> >  symtab_list_t;
+
+      struct expression_holder
+      {
+         enum data_type
+         {
+            e_unknown  ,
+            e_expr     ,
+            e_vecholder,
+            e_data     ,
+            e_vecdata  ,
+            e_string
+         };
+
+         struct data_pack
+         {
+            data_pack()
+            : pointer(0),
+              type(e_unknown),
+              size(0)
+            {}
+
+            data_pack(void* ptr, data_type dt, std::size_t sz = 0)
+            : pointer(ptr),
+              type(dt),
+              size(sz)
+            {}
+
+            void*       pointer;
+            data_type   type;
+            std::size_t size;
+         };
+
+         typedef std::vector<data_pack> local_data_list_t;
+         typedef results_context<T>     results_context_t;
+
+         expression_holder()
+         : ref_count(0),
+           expr     (0),
+           results  (0),
+           retinv_null(false),
+           return_invoked(&retinv_null)
+         {}
+
+         expression_holder(expression_ptr e)
+         : ref_count(1),
+           expr     (e),
+           results  (0),
+           retinv_null(false),
+           return_invoked(&retinv_null)
+         {}
+
+        ~expression_holder()
+         {
+            if (expr && details::branch_deletable(expr))
+            {
+               delete expr;
+            }
+
+            if (!local_data_list.empty())
+            {
+               for (std::size_t i = 0; i < local_data_list.size(); ++i)
+               {
+                  switch (local_data_list[i].type)
+                  {
+                     case e_expr      : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
+                                        break;
+
+                     case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
+                                        break;
+
+                     case e_data      : delete (T*)(local_data_list[i].pointer);
+                                        break;
+
+                     case e_vecdata   : delete [] (T*)(local_data_list[i].pointer);
+                                        break;
+
+                     case e_string    : delete (std::string*)(local_data_list[i].pointer);
+                                        break;
+
+                     default          : break;
+                  }
+               }
+            }
+
+            if (results)
+            {
+               delete results;
+            }
+         }
+
+         std::size_t ref_count;
+         expression_ptr expr;
+         local_data_list_t local_data_list;
+         results_context_t* results;
+         bool  retinv_null;
+         bool* return_invoked;
+
+         friend class function_compositor<T>;
+      };
+
+   public:
+
+      expression()
+      : expression_holder_(0)
+      {
+         set_expression(new details::null_node<T>());
+      }
+
+      expression(const expression<T>& e)
+      : expression_holder_(e.expression_holder_),
+        symbol_table_list_(e.symbol_table_list_)
+      {
+         expression_holder_->ref_count++;
+      }
+
+      inline expression<T>& operator=(const expression<T>& e)
+      {
+         if (this != &e)
+         {
+            if (expression_holder_)
+            {
+               if (0 == --expression_holder_->ref_count)
+               {
+                  delete expression_holder_;
+               }
+
+               expression_holder_ = 0;
+            }
+
+            expression_holder_ = e.expression_holder_;
+            expression_holder_->ref_count++;
+            symbol_table_list_ = e.symbol_table_list_;
+         }
+
+         return *this;
+      }
+
+      inline bool operator==(const expression<T>& e)
+      {
+         return (this == &e);
+      }
+
+      inline bool operator!() const
+      {
+         return (
+                  (0 == expression_holder_      ) ||
+                  (0 == expression_holder_->expr)
+                );
+      }
+
+      inline expression<T>& release()
+      {
+         if (expression_holder_)
+         {
+            if (0 == --expression_holder_->ref_count)
+            {
+               delete expression_holder_;
+            }
+
+            expression_holder_ = 0;
+         }
+
+         return *this;
+      }
+
+     ~expression()
+      {
+         if (expression_holder_)
+         {
+            if (0 == --expression_holder_->ref_count)
+            {
+               delete expression_holder_;
+            }
+         }
+      }
+
+      inline T value() const
+      {
+         return expression_holder_->expr->value();
+      }
+
+      inline T operator()() const
+      {
+         return value();
+      }
+
+      inline operator T() const
+      {
+         return value();
+      }
+
+      inline operator bool() const
+      {
+         return details::is_true(value());
+      }
+
+      inline void register_symbol_table(symbol_table<T>& st)
+      {
+         symbol_table_list_.push_back(st);
+      }
+
+      inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
+      {
+         return symbol_table_list_[index];
+      }
+
+      inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
+      {
+         return symbol_table_list_[index];
+      }
+
+      typedef results_context<T> results_context_t;
+
+      inline const results_context_t& results() const
+      {
+         if (expression_holder_->results)
+            return (*expression_holder_->results);
+         else
+         {
+            static const results_context_t null_results;
+            return null_results;
+         }
+      }
+
+      inline bool return_invoked() const
+      {
+         return (*expression_holder_->return_invoked);
+      }
+
+   private:
+
+      inline symtab_list_t get_symbol_table_list() const
+      {
+         return symbol_table_list_;
+      }
+
+      inline void set_expression(const expression_ptr expr)
+      {
+         if (expr)
+         {
+            if (expression_holder_)
+            {
+               if (0 == --expression_holder_->ref_count)
+               {
+                  delete expression_holder_;
+               }
+            }
+
+            expression_holder_ = new expression_holder(expr);
+         }
+      }
+
+      inline void register_local_var(expression_ptr expr)
+      {
+         if (expr)
+         {
+            if (expression_holder_)
+            {
+               expression_holder_->
+                  local_data_list.push_back(
+                     typename expression<T>::expression_holder::
+                        data_pack(reinterpret_cast<void*>(expr),
+                                  expression_holder::e_expr));
+            }
+         }
+      }
+
+      inline void register_local_var(vector_holder_ptr vec_holder)
+      {
+         if (vec_holder)
+         {
+            if (expression_holder_)
+            {
+               expression_holder_->
+                  local_data_list.push_back(
+                     typename expression<T>::expression_holder::
+                        data_pack(reinterpret_cast<void*>(vec_holder),
+                                  expression_holder::e_vecholder));
+            }
+         }
+      }
+
+      inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
+      {
+         if (data)
+         {
+            if (expression_holder_)
+            {
+               typename expression_holder::data_type dt = expression_holder::e_data;
+
+               switch(data_mode)
+               {
+                  case 0 : dt = expression_holder::e_data;    break;
+                  case 1 : dt = expression_holder::e_vecdata; break;
+                  case 2 : dt = expression_holder::e_string;  break;
+               }
+
+               expression_holder_->
+                  local_data_list.push_back(
+                     typename expression<T>::expression_holder::
+                        data_pack(reinterpret_cast<void*>(data),dt,size));
+            }
+         }
+      }
+
+      inline const typename expression_holder::local_data_list_t& local_data_list()
+      {
+         if (expression_holder_)
+         {
+            return expression_holder_->local_data_list;
+         }
+         else
+         {
+            static typename expression_holder::local_data_list_t null_local_data_list;
+            return null_local_data_list;
+         }
+      }
+
+      inline void register_return_results(results_context_t* rc)
+      {
+         if (expression_holder_ && rc)
+         {
+            expression_holder_->results = rc;
+         }
+      }
+
+      inline void set_retinvk(bool* retinvk_ptr)
+      {
+         if (expression_holder_)
+         {
+            expression_holder_->return_invoked = retinvk_ptr;
+         }
+      }
+
+      expression_holder* expression_holder_;
+      symtab_list_t      symbol_table_list_;
+
+      friend class parser<T>;
+      friend class expression_helper<T>;
+      friend class function_compositor<T>;
+   };
+
+   template <typename T>
+   class expression_helper
+   {
+   public:
+
+      static inline bool is_constant(const expression<T>& expr)
+      {
+         return details::is_constant_node(expr.expression_holder_->expr);
+      }
+
+      static inline bool is_variable(const expression<T>& expr)
+      {
+         return details::is_variable_node(expr.expression_holder_->expr);
+      }
+
+      static inline bool is_unary(const expression<T>& expr)
+      {
+         return details::is_unary_node(expr.expression_holder_->expr);
+      }
+
+      static inline bool is_binary(const expression<T>& expr)
+      {
+         return details::is_binary_node(expr.expression_holder_->expr);
+      }
+
+      static inline bool is_function(const expression<T>& expr)
+      {
+         return details::is_function(expr.expression_holder_->expr);
+      }
+   };
+
+   namespace parser_error
+   {
+      enum error_mode
+      {
+         e_unknown = 0,
+         e_syntax  = 1,
+         e_token   = 2,
+         e_numeric = 4,
+         e_symtab  = 5,
+         e_lexer   = 6,
+         e_helper  = 7
+      };
+
+      struct type
+      {
+         type()
+         : mode(parser_error::e_unknown),
+           line_no  (0),
+           column_no(0)
+         {}
+
+         lexer::token token;
+         error_mode mode;
+         std::string diagnostic;
+         std::string error_line;
+         std::size_t line_no;
+         std::size_t column_no;
+      };
+
+      inline type make_error(error_mode mode, const std::string& diagnostic = "")
+      {
+         type t;
+         t.mode       = mode;
+         t.token.type = lexer::token::e_error;
+         t.diagnostic = diagnostic;
+         exprtk_debug(("%s\n",diagnostic .c_str()));
+         return t;
+      }
+
+      inline type make_error(error_mode mode, const lexer::token& tk, const std::string& diagnostic = "")
+      {
+         type t;
+         t.mode       = mode;
+         t.token      = tk;
+         t.diagnostic = diagnostic;
+         exprtk_debug(("%s\n",diagnostic .c_str()));
+         return t;
+      }
+
+      inline std::string to_str(error_mode mode)
+      {
+         switch (mode)
+         {
+            case e_unknown : return std::string("Unknown Error");
+            case e_syntax  : return std::string("Syntax Error" );
+            case e_token   : return std::string("Token Error"  );
+            case e_numeric : return std::string("Numeric Error");
+            case e_symtab  : return std::string("Symbol Error" );
+            case e_lexer   : return std::string("Lexer Error"  );
+            case e_helper  : return std::string("Helper Error" );
+            default        : return std::string("Unknown Error");
+         }
+      }
+
+      inline bool update_error(type& error, const std::string& expression)
+      {
+         if (
+              expression.empty()                         ||
+              (error.token.position > expression.size()) ||
+              (std::numeric_limits<std::size_t>::max() == error.token.position)
+            )
+         {
+            return false;
+         }
+
+         std::size_t error_line_start = 0;
+
+         for (std::size_t i = error.token.position; i > 0; --i)
+         {
+            const char c = expression[i];
+
+            if (('\n' == c) || ('\r' == c))
+            {
+               error_line_start = i + 1;
+               break;
+            }
+         }
+
+         std::size_t next_nl_position = std::min(expression.size(),
+                                                 expression.find_first_of('\n',error.token.position + 1));
+
+         error.column_no  = error.token.position - error_line_start;
+         error.error_line = expression.substr(error_line_start,
+                                              next_nl_position - error_line_start);
+
+         error.line_no = 0;
+
+         for (std::size_t i = 0; i < next_nl_position; ++i)
+         {
+            if ('\n' == expression[i])
+               ++error.line_no;
+         }
+
+         return true;
+      }
+
+      inline void dump_error(const type& error)
+      {
+         printf("Position: %02d   Type: [%s]   Msg: %s\n",
+                static_cast<int>(error.token.position),
+                exprtk::parser_error::to_str(error.mode).c_str(),
+                error.diagnostic.c_str());
+      }
+   }
+
+   template <typename T>
+   class parser : public lexer::parser_helper
+   {
+   private:
+
+      enum precedence_level
+      {
+         e_level00,
+         e_level01,
+         e_level02,
+         e_level03,
+         e_level04,
+         e_level05,
+         e_level06,
+         e_level07,
+         e_level08,
+         e_level09,
+         e_level10,
+         e_level11,
+         e_level12,
+         e_level13,
+         e_level14
+      };
+
+      typedef const T&                                               cref_t;
+      typedef const T                                               const_t;
+      typedef ifunction                <T>                                F;
+      typedef ivararg_function         <T>                              VAF;
+      typedef igeneric_function        <T>                               GF;
+      typedef ifunction                <T>                      ifunction_t;
+      typedef ivararg_function         <T>               ivararg_function_t;
+      typedef igeneric_function        <T>              igeneric_function_t;
+      typedef details::expression_node <T>                expression_node_t;
+      typedef details::literal_node    <T>                   literal_node_t;
+      typedef details::unary_node      <T>                     unary_node_t;
+      typedef details::binary_node     <T>                    binary_node_t;
+      typedef details::trinary_node    <T>                   trinary_node_t;
+      typedef details::quaternary_node <T>                quaternary_node_t;
+      typedef details::conditional_node<T>               conditional_node_t;
+      typedef details::cons_conditional_node<T>     cons_conditional_node_t;
+      typedef details::while_loop_node <T>                while_loop_node_t;
+      typedef details::repeat_until_loop_node<T>   repeat_until_loop_node_t;
+      typedef details::for_loop_node   <T>                  for_loop_node_t;
+      #ifndef exprtk_disable_break_continue
+      typedef details::while_loop_bc_node <T>          while_loop_bc_node_t;
+      typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t;
+      typedef details::for_loop_bc_node<T>               for_loop_bc_node_t;
+      #endif
+      typedef details::switch_node     <T>                    switch_node_t;
+      typedef details::variable_node   <T>                  variable_node_t;
+      typedef details::vector_elem_node<T>               vector_elem_node_t;
+      typedef details::vector_node     <T>                    vector_node_t;
+      typedef details::range_pack      <T>                          range_t;
+      #ifndef exprtk_disable_string_capabilities
+      typedef details::stringvar_node     <T>              stringvar_node_t;
+      typedef details::string_literal_node<T>         string_literal_node_t;
+      typedef details::string_range_node  <T>           string_range_node_t;
+      typedef details::const_string_range_node<T> const_string_range_node_t;
+      typedef details::generic_string_range_node<T> generic_string_range_node_t;
+      typedef details::string_concat_node <T>          string_concat_node_t;
+      typedef details::assignment_string_node<T>   assignment_string_node_t;
+      typedef details::assignment_string_range_node<T> assignment_string_range_node_t;
+      typedef details::conditional_string_node<T>  conditional_string_node_t;
+      typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t;
+      #endif
+      typedef details::assignment_node<T>                 assignment_node_t;
+      typedef details::assignment_vec_elem_node<T> assignment_vec_elem_node_t;
+      typedef details::assignment_vec_node     <T>    assignment_vec_node_t;
+      typedef details::assignment_vecvec_node  <T> assignment_vecvec_node_t;
+      typedef details::scand_node<T>                           scand_node_t;
+      typedef details::scor_node<T>                             scor_node_t;
+      typedef lexer::token                                          token_t;
+      typedef expression_node_t*                        expression_node_ptr;
+      typedef symbol_table<T>                                symbol_table_t;
+      typedef typename expression<T>::symtab_list_t     symbol_table_list_t;
+      typedef details::vector_holder<T>*                  vector_holder_ptr;
+
+      typedef typename details::functor_t<T>         functor_t;
+      typedef typename functor_t::qfunc_t quaternary_functor_t;
+      typedef typename functor_t::tfunc_t    trinary_functor_t;
+      typedef typename functor_t::bfunc_t     binary_functor_t;
+      typedef typename functor_t::ufunc_t      unary_functor_t;
+
+      typedef details::operator_type operator_t;
+
+      typedef std::map<operator_t,  unary_functor_t>   unary_op_map_t;
+      typedef std::map<operator_t, binary_functor_t>  binary_op_map_t;
+      typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
+
+      typedef std::map<std::string,std::pair<trinary_functor_t   ,operator_t> > sf3_map_t;
+      typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
+
+      typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
+      typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
+      typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
+
+      typedef details::T0oT1_define<T, cref_t, cref_t> vov_t;
+      typedef details::T0oT1_define<T,const_t, cref_t> cov_t;
+      typedef details::T0oT1_define<T, cref_t,const_t> voc_t;
+
+      typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t;
+      typedef details::T0oT1oT2_define<T, cref_t, cref_t,const_t> vovoc_t;
+      typedef details::T0oT1oT2_define<T, cref_t,const_t, cref_t> vocov_t;
+      typedef details::T0oT1oT2_define<T,const_t, cref_t, cref_t> covov_t;
+      typedef details::T0oT1oT2_define<T,const_t, cref_t,const_t> covoc_t;
+      typedef details::T0oT1oT2_define<T,const_t,const_t, cref_t> cocov_t;
+      typedef details::T0oT1oT2_define<T,cref_t,const_t, const_t> vococ_t;
+
+      typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t,const_t> vovovoc_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t,const_t, cref_t> vovocov_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t, cref_t> vocovov_t;
+      typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t, cref_t> covovov_t;
+
+      typedef details::T0oT1oT2oT3_define<T,const_t, cref_t,const_t, cref_t> covocov_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t,const_t, cref_t,const_t> vocovoc_t;
+      typedef details::T0oT1oT2oT3_define<T,const_t, cref_t, cref_t,const_t> covovoc_t;
+      typedef details::T0oT1oT2oT3_define<T, cref_t,const_t,const_t, cref_t> vococov_t;
+
+      typedef results_context<T> results_context_t;
+
+      struct scope_element
+      {
+         enum element_type
+         {
+            e_none    ,
+            e_variable,
+            e_vector  ,
+            e_vecelem ,
+            e_string
+         };
+
+         typedef details::vector_holder<T> vector_holder_t;
+         typedef variable_node_t*   variable_node_ptr;
+         typedef vector_holder_t*   vector_holder_ptr;
+         #ifndef exprtk_disable_string_capabilities
+         typedef stringvar_node_t* stringvar_node_ptr;
+         #endif
+
+         scope_element()
+         : name("???"),
+           size (std::numeric_limits<std::size_t>::max()),
+           index(std::numeric_limits<std::size_t>::max()),
+           depth(std::numeric_limits<std::size_t>::max()),
+           ref_count(0),
+           ip_index (0),
+           type (e_none),
+           active(false),
+           data    (0),
+           var_node(0),
+           vec_node(0)
+           #ifndef exprtk_disable_string_capabilities
+           ,str_node(0)
+           #endif
+         {}
+
+         bool operator < (const scope_element& se) const
+         {
+            if (ip_index < se.ip_index)
+               return true;
+            else if (ip_index > se.ip_index)
+               return false;
+            else if (depth < se.depth)
+               return true;
+            else if (depth > se.depth)
+               return false;
+            else if (index < se.index)
+               return true;
+            else if (index > se.index)
+               return false;
+            else
+               return (name < se.name);
+         }
+
+         void clear()
+         {
+            name   = "???";
+            size   = std::numeric_limits<std::size_t>::max();
+            index  = std::numeric_limits<std::size_t>::max();
+            depth  = std::numeric_limits<std::size_t>::max();
+            type   = e_none;
+            active = false;
+            ref_count = 0;
+            ip_index  = 0;
+            data      = 0;
+            var_node  = 0;
+            vec_node  = 0;
+            #ifndef exprtk_disable_string_capabilities
+            str_node  = 0;
+            #endif
+         }
+
+         std::string  name;
+         std::size_t  size;
+         std::size_t  index;
+         std::size_t  depth;
+         std::size_t  ref_count;
+         std::size_t  ip_index;
+         element_type type;
+         bool         active;
+         void*        data;
+         variable_node_ptr  var_node;
+         vector_holder_ptr  vec_node;
+         #ifndef exprtk_disable_string_capabilities
+         stringvar_node_ptr str_node;
+         #endif
+      };
+
+      class scope_element_manager
+      {
+      public:
+
+         typedef variable_node_t* variable_node_ptr;
+         typedef parser<T> parser_t;
+
+         scope_element_manager(parser<T>& p)
+         : parser_(p),
+           input_param_cnt_(0)
+         {}
+
+         inline std::size_t size() const
+         {
+            return element_.size();
+         }
+
+         inline bool empty() const
+         {
+            return element_.empty();
+         }
+
+         inline scope_element& get_element(const std::size_t& index)
+         {
+            if (index < element_.size())
+               return element_[index];
+            else
+               return null_element_;
+         }
+
+         inline scope_element& get_element(const std::string& var_name,
+                                           const std::size_t index = std::numeric_limits<std::size_t>::max())
+         {
+            const std::size_t current_depth = parser_.state_.scope_depth;
+
+            for (std::size_t i = 0; i < element_.size(); ++i)
+            {
+               scope_element& se = element_[i];
+
+               if (se.depth > current_depth)
+                  continue;
+               else if (
+                         (se.name  == var_name) &&
+                         (se.index == index)
+                       )
+                  return se;
+            }
+
+            return null_element_;
+         }
+
+         inline scope_element& get_active_element(const std::string& var_name,
+                                                  const std::size_t index = std::numeric_limits<std::size_t>::max())
+         {
+            const std::size_t current_depth = parser_.state_.scope_depth;
+
+            for (std::size_t i = 0; i < element_.size(); ++i)
+            {
+               scope_element& se = element_[i];
+
+               if (se.depth > current_depth)
+                  continue;
+               else if (
+                         (se.name  == var_name) &&
+                         (se.index == index)    &&
+                         (se.active)
+                       )
+                  return se;
+            }
+
+            return null_element_;
+         }
+
+         inline bool add_element(const scope_element& se)
+         {
+            for (std::size_t i = 0; i < element_.size(); ++i)
+            {
+               scope_element& cse = element_[i];
+
+               if (
+                    (cse.name  == se.name ) &&
+                    (cse.depth <= se.depth) &&
+                    (cse.index == se.index) &&
+                    (cse.size  == se.size ) &&
+                    (cse.type  == se.type ) &&
+                    (cse.active)
+                  )
+                  return false;
+            }
+
+            element_.push_back(se);
+            std::sort(element_.begin(),element_.end());
+
+            return true;
+         }
+
+         inline void deactivate(const std::size_t& scope_depth)
+         {
+            exprtk_debug(("deactivate() - Scope depth: %d\n",
+                          static_cast<int>(parser_.state_.scope_depth)));
+
+            for (std::size_t i = 0; i < element_.size(); ++i)
+            {
+               scope_element& se = element_[i];
+
+               if (se.active && (se.depth >= scope_depth))
+               {
+                  exprtk_debug(("deactivate() - element[%02d] '%s'\n",
+                                static_cast<int>(i),
+                                se.name.c_str()));
+
+                  se.active = false;
+               }
+            }
+         }
+
+         inline void free_element(scope_element& se)
+         {
+            switch (se.type)
+            {
+               case scope_element::e_variable: if (se.data    ) delete (T*) se.data;
+                                               if (se.var_node) delete se.var_node;
+                                               break;
+
+               case scope_element::e_vector  : if (se.data    ) delete[] (T*) se.data;
+                                               if (se.vec_node) delete se.vec_node;
+                                               break;
+
+               case scope_element::e_vecelem : if (se.var_node) delete se.var_node;
+                                               break;
+
+               #ifndef exprtk_disable_string_capabilities
+               case scope_element::e_string  : if (se.data    ) delete (std::string*) se.data;
+                                               if (se.str_node) delete se.str_node;
+                                               break;
+               #endif
+
+               default                       : return;
+            }
+
+            se.clear();
+         }
+
+         inline void cleanup()
+         {
+            for (std::size_t i = 0; i < element_.size(); ++i)
+            {
+               free_element(element_[i]);
+            }
+
+            element_.clear();
+
+            input_param_cnt_ = 0;
+         }
+
+         inline std::size_t next_ip_index()
+         {
+            return ++input_param_cnt_;
+         }
+
+         inline variable_node_ptr get_variable(const T& v)
+         {
+            for (std::size_t i = 0; i < element_.size(); ++i)
+            {
+               scope_element& se = element_[i];
+
+               if (se.active && se.var_node)
+               {
+                  if (&se.var_node->ref() == (&v))
+                  {
+                     return se.var_node;
+                  }
+               }
+            }
+
+            return variable_node_ptr(0);
+         }
+
+      private:
+
+         scope_element_manager& operator=(const scope_element_manager&);
+
+         parser_t& parser_;
+         std::vector<scope_element> element_;
+         scope_element null_element_;
+         std::size_t input_param_cnt_;
+      };
+
+      class scope_handler
+      {
+      public:
+
+         typedef parser<T> parser_t;
+
+         scope_handler(parser<T>& p)
+         : parser_(p)
+         {
+            parser_.state_.scope_depth++;
+            #ifdef exprtk_enable_debugging
+            std::string depth(2 * parser_.state_.scope_depth,'-');
+            exprtk_debug(("%s> Scope Depth: %02d\n",
+                          depth.c_str(),
+                          static_cast<int>(parser_.state_.scope_depth)));
+            #endif
+         }
+
+        ~scope_handler()
+         {
+            parser_.sem_.deactivate(parser_.state_.scope_depth);
+            parser_.state_.scope_depth--;
+            #ifdef exprtk_enable_debugging
+            std::string depth(2 * parser_.state_.scope_depth,'-');
+            exprtk_debug(("<%s Scope Depth: %02d\n",
+                          depth.c_str(),
+                          static_cast<int>(parser_.state_.scope_depth)));
+            #endif
+         }
+
+      private:
+
+         scope_handler& operator=(const scope_handler&);
+
+         parser_t& parser_;
+      };
+
+      struct symtab_store
+      {
+         symbol_table_list_t symtab_list_;
+
+         typedef typename symbol_table_t::local_data_t   local_data_t;
+         typedef typename symbol_table_t::variable_ptr   variable_ptr;
+         typedef typename symbol_table_t::function_ptr   function_ptr;
+         #ifndef exprtk_disable_string_capabilities
+         typedef typename symbol_table_t::stringvar_ptr stringvar_ptr;
+         #endif
+         typedef typename symbol_table_t::vector_holder_ptr       vector_holder_ptr;
+         typedef typename symbol_table_t::vararg_function_ptr   vararg_function_ptr;
+         typedef typename symbol_table_t::generic_function_ptr generic_function_ptr;
+
+         inline bool empty() const
+         {
+            return symtab_list_.empty();
+         }
+
+         inline void clear()
+         {
+            symtab_list_.clear();
+         }
+
+         inline bool valid() const
+         {
+            if (!empty())
+            {
+               for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+               {
+                  if (symtab_list_[i].valid())
+                     return true;
+               }
+            }
+
+            return false;
+         }
+
+         inline bool valid_symbol(const std::string& symbol) const
+         {
+            if (!symtab_list_.empty())
+               return symtab_list_[0].valid_symbol(symbol);
+            else
+               return false;
+         }
+
+         inline bool valid_function_name(const std::string& symbol) const
+         {
+            if (!symtab_list_.empty())
+               return symtab_list_[0].valid_function(symbol);
+            else
+               return false;
+         }
+
+         inline variable_ptr get_variable(const std::string& variable_name) const
+         {
+            if (!valid_symbol(variable_name))
+               return reinterpret_cast<variable_ptr>(0);
+
+            variable_ptr result = reinterpret_cast<variable_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result = local_data(i)
+                              .variable_store.get(variable_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
+         inline variable_ptr get_variable(const T& var_ref) const
+         {
+            variable_ptr result = reinterpret_cast<variable_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result = local_data(i).variable_store
+                              .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline stringvar_ptr get_stringvar(const std::string& string_name) const
+         {
+            if (!valid_symbol(string_name))
+               return reinterpret_cast<stringvar_ptr>(0);
+
+            stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result = local_data(i)
+                              .stringvar_store.get(string_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+         #endif
+
+         inline function_ptr get_function(const std::string& function_name) const
+         {
+            if (!valid_function_name(function_name))
+               return reinterpret_cast<function_ptr>(0);
+
+            function_ptr result = reinterpret_cast<function_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result = local_data(i)
+                              .function_store.get(function_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
+         inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
+         {
+            if (!valid_function_name(vararg_function_name))
+               return reinterpret_cast<vararg_function_ptr>(0);
+
+            vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result = local_data(i)
+                              .vararg_function_store.get(vararg_function_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
+         inline generic_function_ptr get_generic_function(const std::string& function_name) const
+         {
+            if (!valid_function_name(function_name))
+               return reinterpret_cast<generic_function_ptr>(0);
+
+            generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result = local_data(i)
+                              .generic_function_store.get(function_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
+         inline generic_function_ptr get_string_function(const std::string& function_name) const
+         {
+            if (!valid_function_name(function_name))
+               return reinterpret_cast<generic_function_ptr>(0);
+
+            generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result =
+                     local_data(i).string_function_store.get(function_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
+         inline vector_holder_ptr get_vector(const std::string& vector_name) const
+         {
+            if (!valid_symbol(vector_name))
+               return reinterpret_cast<vector_holder_ptr>(0);
+
+            vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else
+                  result =
+                     local_data(i).vector_store.get(vector_name);
+
+               if (result) break;
+            }
+
+            return result;
+         }
+
+         inline bool is_constant_node(const std::string& symbol_name) const
+         {
+            if (!valid_symbol(symbol_name))
+               return false;
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (local_data(i).variable_store.is_constant(symbol_name))
+                  return true;
+            }
+
+            return false;
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline bool is_constant_string(const std::string& symbol_name) const
+         {
+            if (!valid_symbol(symbol_name))
+               return false;
+
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
+                  continue;
+               else if ( local_data(i).stringvar_store.is_constant(symbol_name))
+                  return true;
+            }
+
+            return false;
+         }
+         #endif
+
+         inline bool symbol_exists(const std::string& symbol) const
+         {
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (symtab_list_[i].symbol_exists(symbol))
+                  return true;
+            }
+
+            return false;
+         }
+
+         inline bool is_variable(const std::string& variable_name) const
+         {
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (
+                         symtab_list_[i].local_data().variable_store
+                           .symbol_exists(variable_name)
+                       )
+                  return true;
+            }
+
+            return false;
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline bool is_stringvar(const std::string& stringvar_name) const
+         {
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (
+                         symtab_list_[i].local_data().stringvar_store
+                           .symbol_exists(stringvar_name)
+                       )
+                  return true;
+            }
+
+            return false;
+         }
+
+         inline bool is_conststr_stringvar(const std::string& symbol_name) const
+         {
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (
+                         symtab_list_[i].local_data().stringvar_store
+                           .symbol_exists(symbol_name)
+                       )
+               {
+                  return (
+                           local_data(i).stringvar_store.symbol_exists(symbol_name) ||
+                           local_data(i).stringvar_store.is_constant  (symbol_name)
+                         );
+
+               }
+            }
+
+            return false;
+         }
+         #endif
+
+         inline bool is_function(const std::string& function_name) const
+         {
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (
+                         local_data(i).vararg_function_store
+                           .symbol_exists(function_name)
+                       )
+                  return true;
+            }
+
+            return false;
+         }
+
+         inline bool is_vararg_function(const std::string& vararg_function_name) const
+         {
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (
+                         local_data(i).vararg_function_store
+                           .symbol_exists(vararg_function_name)
+                       )
+                  return true;
+            }
+
+            return false;
+         }
+
+         inline bool is_vector(const std::string& vector_name) const
+         {
+            for (std::size_t i = 0; i < symtab_list_.size(); ++i)
+            {
+               if (!symtab_list_[i].valid())
+                  continue;
+               else if (
+                         local_data(i).vector_store
+                           .symbol_exists(vector_name)
+                       )
+                  return true;
+            }
+
+            return false;
+         }
+
+         inline std::string get_variable_name(const expression_node_ptr& ptr) const
+         {
+            return local_data().variable_store.entity_name(ptr);
+         }
+
+         inline std::string get_vector_name(const vector_holder_ptr& ptr) const
+         {
+            return local_data().vector_store.entity_name(ptr);
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline std::string get_stringvar_name(const expression_node_ptr& ptr) const
+         {
+            return local_data().stringvar_store.entity_name(ptr);
+         }
+
+         inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const
+         {
+            return local_data().stringvar_store.entity_name(ptr);
+         }
+         #endif
+
+         inline local_data_t& local_data(const std::size_t& index = 0)
+         {
+            return symtab_list_[index].local_data();
+         }
+
+         inline const local_data_t& local_data(const std::size_t& index = 0) const
+         {
+            return symtab_list_[index].local_data();
+         }
+
+         inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
+         {
+            return symtab_list_[index];
+         }
+      };
+
+      struct parser_state
+      {
+         parser_state()
+         : parsing_return_stmt(false),
+           parsing_break_stmt (false),
+           return_stmt_present(false),
+           side_effect_present(false),
+           scope_depth(0)
+         {}
+
+         void reset()
+         {
+            parsing_return_stmt = false;
+            parsing_break_stmt  = false;
+            return_stmt_present = false;
+            side_effect_present = false;
+            scope_depth         = 0;
+         }
+
+         #ifndef exprtk_enable_debugging
+         void activate_side_effect(const std::string&)
+         #else
+         void activate_side_effect(const std::string& source)
+         #endif
+         {
+            if (!side_effect_present)
+            {
+               side_effect_present = true;
+
+               exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
+            }
+         }
+
+         bool parsing_return_stmt;
+         bool parsing_break_stmt;
+         bool return_stmt_present;
+         bool side_effect_present;
+         std::size_t scope_depth;
+      };
+
+   public:
+
+      struct unknown_symbol_resolver
+      {
+
+         enum usr_symbol_type
+         {
+            e_usr_variable_type = 0,
+            e_usr_constant_type = 1
+         };
+
+         virtual ~unknown_symbol_resolver()
+         {}
+
+         virtual bool process(const std::string& /*unknown_symbol*/,
+                              usr_symbol_type& st,
+                              T& default_value,
+                              std::string& error_message)
+         {
+            st = e_usr_variable_type;
+            default_value = T(0);
+            error_message.clear();
+
+            return true;
+         }
+      };
+
+      enum collect_type
+      {
+         e_ct_none        = 0,
+         e_ct_variables   = 1,
+         e_ct_functions   = 2,
+         e_ct_assignments = 4
+      };
+
+      enum symbol_type
+      {
+         e_st_unknown        = 0,
+         e_st_variable       = 1,
+         e_st_vector         = 2,
+         e_st_vecelem        = 3,
+         e_st_string         = 4,
+         e_st_function       = 5,
+         e_st_local_variable = 6,
+         e_st_local_vector   = 7,
+         e_st_local_string   = 8
+      };
+
+      class dependent_entity_collector
+      {
+      public:
+
+         typedef std::pair<std::string,symbol_type> symbol_t;
+         typedef std::vector<symbol_t> symbol_list_t;
+
+         dependent_entity_collector(const std::size_t options = e_ct_none)
+         : options_(options),
+           collect_variables_  ((options_ & e_ct_variables  ) == e_ct_variables  ),
+           collect_functions_  ((options_ & e_ct_functions  ) == e_ct_functions  ),
+           collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
+           return_present_   (false),
+           final_stmt_return_(false)
+         {}
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
+         {
+            if (!collect_variables_ && !collect_functions_)
+               return 0;
+            else if (symbol_name_list_.empty())
+               return 0;
+
+            for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
+            {
+               std::string& s = symbol_name_list_[i].first;
+               std::transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(std::tolower));
+            }
+
+            std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
+            std::unique_copy(symbol_name_list_.begin(),
+                             symbol_name_list_.end(),
+                             std::back_inserter(symbols_list));
+
+            return symbols_list.size();
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
+         {
+            if (!collect_assignments_)
+               return 0;
+            else if (assignment_name_list_.empty())
+               return 0;
+
+            for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
+            {
+               std::string& s = assignment_name_list_[i].first;
+               std::transform(s.begin(),s.end(),s.begin(),static_cast<int(*)(int)>(std::tolower));
+            }
+
+            std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
+            std::unique_copy(assignment_name_list_.begin(),
+                             assignment_name_list_.end(),
+                             std::back_inserter(assignment_list));
+
+            return assignment_list.size();
+         }
+
+         void clear()
+         {
+            symbol_name_list_    .clear();
+            assignment_name_list_.clear();
+            retparam_list_       .clear();
+            return_present_    = false;
+            final_stmt_return_ = false;
+         }
+
+         bool& collect_variables()
+         {
+            return collect_variables_;
+         }
+
+         bool& collect_functions()
+         {
+            return collect_functions_;
+         }
+
+         bool& collect_assignments()
+         {
+            return collect_assignments_;
+         }
+
+         bool return_present() const
+         {
+            return return_present_;
+         }
+
+         bool final_stmt_return() const
+         {
+            return final_stmt_return_;
+         }
+
+         typedef std::vector<std::string> retparam_list_t;
+
+         retparam_list_t return_param_type_list() const
+         {
+            return retparam_list_;
+         }
+
+      private:
+
+         inline void add_symbol(const std::string& symbol, const symbol_type st)
+         {
+            switch (st)
+            {
+               case e_st_variable       :
+               case e_st_vector         :
+               case e_st_string         :
+               case e_st_local_variable :
+               case e_st_local_vector   :
+               case e_st_local_string   :
+               case e_st_function       :
+                  if (collect_variables_ || collect_functions_)
+                     symbol_name_list_.push_back(std::make_pair(symbol,st));
+                  break;
+
+               default                  : return;
+            }
+         }
+
+         inline void add_assignment(const std::string& symbol, const symbol_type st)
+         {
+            switch (st)
+            {
+               case e_st_variable       :
+               case e_st_vector         :
+               case e_st_string         :
+                  if (collect_assignments_)
+                     assignment_name_list_.push_back(std::make_pair(symbol,st));
+                  break;
+
+               default                  : return;
+            }
+         }
+
+         std::size_t options_;
+         bool collect_variables_;
+         bool collect_functions_;
+         bool collect_assignments_;
+         bool return_present_;
+         bool final_stmt_return_;
+         symbol_list_t symbol_name_list_;
+         symbol_list_t assignment_name_list_;
+         retparam_list_t retparam_list_;
+
+         friend class parser<T>;
+      };
+
+      class settings_store
+      {
+      private:
+
+         typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
+         typedef disabled_entity_set_t::iterator des_itr_t;
+
+      public:
+
+         enum settings_compilation_options
+         {
+            e_unknown              =    0,
+            e_replacer             =    1,
+            e_joiner               =    2,
+            e_numeric_check        =    4,
+            e_bracket_check        =    8,
+            e_sequence_check       =   16,
+            e_commutative_check    =   32,
+            e_strength_reduction   =   64,
+            e_disable_vardef       =  128,
+            e_collect_vars         =  256,
+            e_collect_funcs        =  512,
+            e_collect_assings      = 1024,
+            e_disable_usr_on_rsrvd = 2048,
+            e_disable_zero_return  = 4096
+         };
+
+         enum settings_base_funcs
+         {
+            e_bf_unknown = 0,
+            e_bf_abs       , e_bf_acos     , e_bf_acosh    , e_bf_asin   ,
+            e_bf_asinh     , e_bf_atan     , e_bf_atan2    , e_bf_atanh  ,
+            e_bf_avg       , e_bf_ceil     , e_bf_clamp    , e_bf_cos    ,
+            e_bf_cosh      , e_bf_cot      , e_bf_csc      , e_bf_equal  ,
+            e_bf_erf       , e_bf_erfc     , e_bf_exp      , e_bf_expm1  ,
+            e_bf_floor     , e_bf_frac     , e_bf_hypot    , e_bf_iclamp ,
+            e_bf_like      , e_bf_log      , e_bf_log10    , e_bf_log1p  ,
+            e_bf_log2      , e_bf_logn     , e_bf_mand     , e_bf_max    ,
+            e_bf_min       , e_bf_mod      , e_bf_mor      , e_bf_mul    ,
+            e_bf_ncdf      , e_bf_pow      , e_bf_root     , e_bf_round  ,
+            e_bf_roundn    , e_bf_sec      , e_bf_sgn      , e_bf_sin    ,
+            e_bf_sinc      , e_bf_sinh     , e_bf_sqrt     , e_bf_sum    ,
+            e_bf_swap      , e_bf_tan      , e_bf_tanh     , e_bf_trunc  ,
+            e_bf_not_equal , e_bf_inrange  , e_bf_deg2grad , e_bf_deg2rad,
+            e_bf_rad2deg   , e_bf_grad2deg
+         };
+
+         enum settings_control_structs
+         {
+            e_ctrl_unknown = 0,
+            e_ctrl_ifelse,
+            e_ctrl_switch,
+            e_ctrl_for_loop,
+            e_ctrl_while_loop,
+            e_ctrl_repeat_loop
+         };
+
+         enum settings_logic_opr
+         {
+            e_logic_unknown = 0,
+            e_logic_and, e_logic_nand,  e_logic_nor,
+            e_logic_not, e_logic_or,    e_logic_xnor,
+            e_logic_xor, e_logic_scand, e_logic_scor
+         };
+
+         enum settings_arithmetic_opr
+         {
+            e_arith_unknown = 0,
+            e_arith_add, e_arith_sub, e_arith_mul,
+            e_arith_div, e_arith_mod, e_arith_pow
+         };
+
+         enum settings_assignment_opr
+         {
+            e_assign_unknown = 0,
+            e_assign_assign, e_assign_addass, e_assign_subass,
+            e_assign_mulass, e_assign_divass, e_assign_modass
+         };
+
+         enum settings_inequality_opr
+         {
+            e_ineq_unknown = 0,
+            e_ineq_lt,    e_ineq_lte, e_ineq_eq,
+            e_ineq_equal, e_ineq_ne,  e_ineq_nequal,
+            e_ineq_gte,   e_ineq_gt
+         };
+
+         static const std::size_t compile_all_opts = e_replacer          +
+                                                     e_joiner            +
+                                                     e_numeric_check     +
+                                                     e_bracket_check     +
+                                                     e_sequence_check    +
+                                                     e_commutative_check +
+                                                     e_strength_reduction;
+
+         settings_store(const std::size_t compile_options = compile_all_opts)
+         {
+           load_compile_options(compile_options);
+         }
+
+         settings_store& enable_all_base_functions()
+         {
+            disabled_func_set_.clear();
+            return *this;
+         }
+
+         settings_store& enable_all_control_structures()
+         {
+            disabled_ctrl_set_.clear();
+            return *this;
+         }
+
+         settings_store& enable_all_logic_ops()
+         {
+            disabled_logic_set_.clear();
+            return *this;
+         }
+
+         settings_store& enable_all_arithmetic_ops()
+         {
+            disabled_arithmetic_set_.clear();
+            return *this;
+         }
+
+         settings_store& enable_all_assignment_ops()
+         {
+            disabled_assignment_set_.clear();
+            return *this;
+         }
+
+         settings_store& enable_all_inequality_ops()
+         {
+            disabled_inequality_set_.clear();
+            return *this;
+         }
+
+         settings_store& enable_local_vardef()
+         {
+            disable_vardef_ = false;
+            return *this;
+         }
+
+         settings_store& disable_all_base_functions()
+         {
+            std::copy(details::base_function_list,
+                      details::base_function_list + details::base_function_list_size,
+                      std::insert_iterator<disabled_entity_set_t>
+                        (disabled_func_set_,disabled_func_set_.begin()));
+            return *this;
+         }
+
+         settings_store& disable_all_control_structures()
+         {
+            std::copy(details::cntrl_struct_list,
+                      details::cntrl_struct_list + details::cntrl_struct_list_size,
+                      std::insert_iterator<disabled_entity_set_t>
+                        (disabled_ctrl_set_,disabled_ctrl_set_.begin()));
+            return *this;
+         }
+
+         settings_store& disable_all_logic_ops()
+         {
+            std::copy(details::logic_ops_list,
+                      details::logic_ops_list + details::logic_ops_list_size,
+                      std::insert_iterator<disabled_entity_set_t>
+                        (disabled_logic_set_,disabled_logic_set_.begin()));
+            return *this;
+         }
+
+         settings_store& disable_all_arithmetic_ops()
+         {
+            std::copy(details::arithmetic_ops_list,
+                      details::arithmetic_ops_list + details::arithmetic_ops_list_size,
+                      std::insert_iterator<disabled_entity_set_t>
+                        (disabled_arithmetic_set_,disabled_arithmetic_set_.begin()));
+            return *this;
+         }
+
+         settings_store& disable_all_assignment_ops()
+         {
+            std::copy(details::assignment_ops_list,
+                      details::assignment_ops_list + details::assignment_ops_list_size,
+                      std::insert_iterator<disabled_entity_set_t>
+                        (disabled_assignment_set_,disabled_assignment_set_.begin()));
+            return *this;
+         }
+
+         settings_store& disable_all_inequality_ops()
+         {
+            std::copy(details::inequality_ops_list,
+                      details::inequality_ops_list + details::inequality_ops_list_size,
+                      std::insert_iterator<disabled_entity_set_t>
+                        (disabled_inequality_set_,disabled_inequality_set_.begin()));
+            return *this;
+         }
+
+         settings_store& disable_local_vardef()
+         {
+            disable_vardef_ = true;
+            return *this;
+         }
+
+         bool replacer_enabled           () const { return enable_replacer_;           }
+         bool commutative_check_enabled  () const { return enable_commutative_check_;  }
+         bool joiner_enabled             () const { return enable_joiner_;             }
+         bool numeric_check_enabled      () const { return enable_numeric_check_;      }
+         bool bracket_check_enabled      () const { return enable_bracket_check_;      }
+         bool sequence_check_enabled     () const { return enable_sequence_check_;     }
+         bool strength_reduction_enabled () const { return enable_strength_reduction_; }
+         bool collect_variables_enabled  () const { return enable_collect_vars_;       }
+         bool collect_functions_enabled  () const { return enable_collect_funcs_;      }
+         bool collect_assignments_enabled() const { return enable_collect_assings_;    }
+         bool vardef_disabled            () const { return disable_vardef_;            }
+         bool rsrvd_sym_usr_disabled     () const { return disable_rsrvd_sym_usr_;     }
+         bool zero_return_disabled       () const { return disable_zero_return_;       }
+
+         bool function_enabled(const std::string& function_name)
+         {
+            if (disabled_func_set_.empty())
+               return true;
+            else
+               return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
+         }
+
+         bool control_struct_enabled(const std::string& control_struct)
+         {
+            if (disabled_ctrl_set_.empty())
+               return true;
+            else
+               return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
+         }
+
+         bool logic_enabled(const std::string& logic_operation)
+         {
+            if (disabled_logic_set_.empty())
+               return true;
+            else
+               return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
+         }
+
+         bool arithmetic_enabled(const details::operator_type& arithmetic_operation)
+         {
+            if (disabled_logic_set_.empty())
+               return true;
+            else
+               return (disabled_arithmetic_set_.end() == disabled_arithmetic_set_.find(arith_opr_to_string(arithmetic_operation)));
+         }
+
+         bool assignment_enabled(const details::operator_type& assignment)
+         {
+            if (disabled_assignment_set_.empty())
+               return true;
+            else
+               return (disabled_assignment_set_.end() == disabled_assignment_set_.find(assign_opr_to_string(assignment)));
+         }
+
+         bool inequality_enabled(const details::operator_type& inequality)
+         {
+            if (disabled_inequality_set_.empty())
+               return true;
+            else
+               return (disabled_inequality_set_.end() == disabled_inequality_set_.find(inequality_opr_to_string(inequality)));
+         }
+
+         bool function_disabled(const std::string& function_name)
+         {
+            if (disabled_func_set_.empty())
+               return false;
+            else
+               return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
+         }
+
+         bool control_struct_disabled(const std::string& control_struct)
+         {
+            if (disabled_ctrl_set_.empty())
+               return false;
+            else
+               return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
+         }
+
+         bool logic_disabled(const std::string& logic_operation)
+         {
+            if (disabled_logic_set_.empty())
+               return false;
+            else
+               return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
+         }
+
+         bool assignment_disabled(const details::operator_type assignment_operation)
+         {
+            if (disabled_assignment_set_.empty())
+               return false;
+            else
+               return (disabled_assignment_set_.end() != disabled_assignment_set_.find(assign_opr_to_string(assignment_operation)));
+         }
+
+         bool arithmetic_disabled(const details::operator_type arithmetic_operation)
+         {
+            if (disabled_arithmetic_set_.empty())
+               return false;
+            else
+               return (disabled_arithmetic_set_.end() != disabled_arithmetic_set_.find(arith_opr_to_string(arithmetic_operation)));
+         }
+
+         bool inequality_disabled(const details::operator_type& inequality)
+         {
+            if (disabled_inequality_set_.empty())
+               return false;
+            else
+               return (disabled_inequality_set_.end() != disabled_inequality_set_.find(inequality_opr_to_string(inequality)));
+         }
+
+         settings_store& disable_base_function(settings_base_funcs bf)
+         {
+            if (
+                 (e_bf_unknown != bf) &&
+                 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
+               )
+            {
+               disabled_func_set_.insert(details::base_function_list[bf - 1]);
+            }
+
+            return *this;
+         }
+
+         settings_store& disable_control_structure(settings_control_structs ctrl_struct)
+         {
+            if (
+                 (e_ctrl_unknown != ctrl_struct) &&
+                 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
+               )
+            {
+               disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
+            }
+
+            return *this;
+         }
+
+         settings_store& disable_logic_operation(settings_logic_opr logic)
+         {
+            if (
+                 (e_logic_unknown != logic) &&
+                 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
+               )
+            {
+               disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
+            }
+
+            return *this;
+         }
+
+         settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic)
+         {
+            if (
+                 (e_arith_unknown != arithmetic) &&
+                 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
+               )
+            {
+               disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
+            }
+
+            return *this;
+         }
+
+         settings_store& disable_assignment_operation(settings_assignment_opr assignment)
+         {
+            if (
+                 (e_assign_unknown != assignment) &&
+                 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
+               )
+            {
+               disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
+            }
+
+            return *this;
+         }
+
+         settings_store& disable_inequality_operation(settings_inequality_opr inequality)
+         {
+            if (
+                 (e_ineq_unknown != inequality) &&
+                 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
+               )
+            {
+               disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
+            }
+
+            return *this;
+         }
+
+         settings_store& enable_base_function(settings_base_funcs bf)
+         {
+            if (
+                 (e_bf_unknown != bf) &&
+                 (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
+               )
+            {
+               des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
+
+               if (disabled_func_set_.end() != itr)
+               {
+                  disabled_func_set_.erase(itr);
+               }
+            }
+
+            return *this;
+         }
+
+         settings_store& enable_control_structure(settings_control_structs ctrl_struct)
+         {
+            if (
+                 (e_ctrl_unknown != ctrl_struct) &&
+                 (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
+               )
+            {
+               des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
+
+               if (disabled_ctrl_set_.end() != itr)
+               {
+                  disabled_ctrl_set_.erase(itr);
+               }
+            }
+
+            return *this;
+         }
+
+         settings_store& enable_logic_operation(settings_logic_opr logic)
+         {
+            if (
+                 (e_logic_unknown != logic) &&
+                 (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
+               )
+            {
+               des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
+
+               if (disabled_logic_set_.end() != itr)
+               {
+                  disabled_logic_set_.erase(itr);
+               }
+            }
+
+            return *this;
+         }
+
+         settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic)
+         {
+            if (
+                 (e_arith_unknown != arithmetic) &&
+                 (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
+               )
+            {
+               des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
+
+               if (disabled_arithmetic_set_.end() != itr)
+               {
+                  disabled_arithmetic_set_.erase(itr);
+               }
+            }
+
+            return *this;
+         }
+
+         settings_store& enable_assignment_operation(settings_assignment_opr assignment)
+         {
+            if (
+                 (e_assign_unknown != assignment) &&
+                 (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
+               )
+            {
+               des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
+
+               if (disabled_assignment_set_.end() != itr)
+               {
+                  disabled_assignment_set_.erase(itr);
+               }
+            }
+
+            return *this;
+         }
+
+         settings_store& enable_inequality_operation(settings_inequality_opr inequality)
+         {
+            if (
+                 (e_ineq_unknown != inequality) &&
+                 (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
+               )
+            {
+               des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
+
+               if (disabled_inequality_set_.end() != itr)
+               {
+                  disabled_inequality_set_.erase(itr);
+               }
+            }
+
+            return *this;
+         }
+
+      private:
+
+         void load_compile_options(const std::size_t compile_options)
+         {
+            enable_replacer_           = (compile_options & e_replacer            ) == e_replacer;
+            enable_joiner_             = (compile_options & e_joiner              ) == e_joiner;
+            enable_numeric_check_      = (compile_options & e_numeric_check       ) == e_numeric_check;
+            enable_bracket_check_      = (compile_options & e_bracket_check       ) == e_bracket_check;
+            enable_sequence_check_     = (compile_options & e_sequence_check      ) == e_sequence_check;
+            enable_commutative_check_  = (compile_options & e_commutative_check   ) == e_commutative_check;
+            enable_strength_reduction_ = (compile_options & e_strength_reduction  ) == e_strength_reduction;
+            enable_collect_vars_       = (compile_options & e_collect_vars        ) == e_collect_vars;
+            enable_collect_funcs_      = (compile_options & e_collect_funcs       ) == e_collect_funcs;
+            enable_collect_assings_    = (compile_options & e_collect_assings     ) == e_collect_assings;
+            disable_vardef_            = (compile_options & e_disable_vardef      ) == e_disable_vardef;
+            disable_rsrvd_sym_usr_     = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
+            disable_zero_return_       = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
+         }
+
+         std::string assign_opr_to_string(details::operator_type opr)
+         {
+            switch (opr)
+            {
+               case details::e_assign : return ":=";
+               case details::e_addass : return "+=";
+               case details::e_subass : return "-=";
+               case details::e_mulass : return "*=";
+               case details::e_divass : return "/=";
+               case details::e_modass : return "%=";
+               default                : return   "";
+            }
+         }
+
+         std::string arith_opr_to_string(details::operator_type opr)
+         {
+            switch (opr)
+            {
+               case details::e_add : return "+";
+               case details::e_sub : return "-";
+               case details::e_mul : return "*";
+               case details::e_div : return "/";
+               case details::e_mod : return "%";
+               default             : return  "";
+            }
+         }
+
+         std::string inequality_opr_to_string(details::operator_type opr)
+         {
+            switch (opr)
+            {
+               case details::e_lt    : return  "<";
+               case details::e_lte   : return "<=";
+               case details::e_eq    : return "==";
+               case details::e_equal : return  "=";
+               case details::e_ne    : return "!=";
+               case details::e_nequal: return "<>";
+               case details::e_gte   : return ">=";
+               case details::e_gt    : return  ">";
+               default               : return   "";
+            }
+         }
+
+         bool enable_replacer_;
+         bool enable_joiner_;
+         bool enable_numeric_check_;
+         bool enable_bracket_check_;
+         bool enable_sequence_check_;
+         bool enable_commutative_check_;
+         bool enable_strength_reduction_;
+         bool enable_collect_vars_;
+         bool enable_collect_funcs_;
+         bool enable_collect_assings_;
+         bool disable_vardef_;
+         bool disable_rsrvd_sym_usr_;
+         bool disable_zero_return_;
+
+         disabled_entity_set_t disabled_func_set_ ;
+         disabled_entity_set_t disabled_ctrl_set_ ;
+         disabled_entity_set_t disabled_logic_set_;
+         disabled_entity_set_t disabled_arithmetic_set_;
+         disabled_entity_set_t disabled_assignment_set_;
+         disabled_entity_set_t disabled_inequality_set_;
+
+         friend class parser<T>;
+      };
+
+      typedef settings_store settings_t;
+
+      parser(const settings_t& settings = settings_t())
+      : settings_(settings),
+        resolve_unknown_symbol_(false),
+        results_context_(0),
+        unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
+        #ifdef _MSC_VER
+        #pragma warning(push)
+        #pragma warning (disable:4355)
+        #endif
+        sem_(*this),
+        #ifdef _MSC_VER
+        #pragma warning(pop)
+        #endif
+        operator_joiner_2_(2),
+        operator_joiner_3_(3)
+      {
+         init_precompilation();
+
+         load_operations_map           (base_ops_map_     );
+         load_unary_operations_map     (unary_op_map_     );
+         load_binary_operations_map    (binary_op_map_    );
+         load_inv_binary_operations_map(inv_binary_op_map_);
+         load_sf3_map                  (sf3_map_          );
+         load_sf4_map                  (sf4_map_          );
+
+         expression_generator_.init_synthesize_map();
+         expression_generator_.set_parser(*this);
+         expression_generator_.set_uom(unary_op_map_);
+         expression_generator_.set_bom(binary_op_map_);
+         expression_generator_.set_ibom(inv_binary_op_map_);
+         expression_generator_.set_sf3m(sf3_map_);
+         expression_generator_.set_sf4m(sf4_map_);
+         expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
+      }
+
+     ~parser()
+      {}
+
+      inline void init_precompilation()
+      {
+         if (settings_.collect_variables_enabled())
+            dec_.collect_variables() = true;
+
+         if (settings_.collect_functions_enabled())
+            dec_.collect_functions() = true;
+
+         if (settings_.collect_assignments_enabled())
+            dec_.collect_assignments() = true;
+
+         if (settings_.replacer_enabled())
+         {
+            symbol_replacer_.clear();
+            symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number);
+            symbol_replacer_.add_replace("false","0",lexer::token::e_number);
+            helper_assembly_.token_modifier_list.clear();
+            helper_assembly_.register_modifier(&symbol_replacer_);
+         }
+
+         if (settings_.commutative_check_enabled())
+         {
+            for (std::size_t i = 0; i < details::reserved_words_size; ++i)
+            {
+               commutative_inserter_.ignore_symbol(details::reserved_words[i]);
+            }
+
+            helper_assembly_.token_inserter_list.clear();
+            helper_assembly_.register_inserter(&commutative_inserter_);
+         }
+
+         if (settings_.joiner_enabled())
+         {
+            helper_assembly_.token_joiner_list.clear();
+            helper_assembly_.register_joiner(&operator_joiner_2_);
+            helper_assembly_.register_joiner(&operator_joiner_3_);
+         }
+
+         if (
+              settings_.numeric_check_enabled () ||
+              settings_.bracket_check_enabled () ||
+              settings_.sequence_check_enabled()
+            )
+         {
+            helper_assembly_.token_scanner_list.clear();
+
+            if (settings_.numeric_check_enabled())
+            {
+               helper_assembly_.register_scanner(&numeric_checker_);
+            }
+
+            if (settings_.bracket_check_enabled())
+            {
+               helper_assembly_.register_scanner(&bracket_checker_);
+            }
+
+            if (settings_.sequence_check_enabled())
+            {
+               helper_assembly_.register_scanner(&sequence_validator_);
+            }
+         }
+      }
+
+      inline bool compile(const std::string& expression_string, expression<T>& expr)
+      {
+         state_          .reset();
+         error_list_     .clear();
+         brkcnt_list_    .clear();
+         synthesis_error_.clear();
+         sem_            .cleanup();
+
+         return_cleanup();
+
+         expression_generator_.set_allocator(node_allocator_);
+
+         if (expression_string.empty())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          "ERR000 - Empty expression!"));
+
+            return false;
+         }
+
+         if (!init(expression_string))
+         {
+            process_lexer_errors();
+            return false;
+         }
+
+         if (lexer().empty())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          "ERR001 - Empty expression!"));
+
+            return false;
+         }
+
+         if (!run_assemblies())
+         {
+            return false;
+         }
+
+         symtab_store_.symtab_list_ = expr.get_symbol_table_list();
+         dec_.clear();
+
+         lexer().begin();
+
+         next_token();
+
+         expression_node_ptr e = parse_corpus();
+
+         if ((0 != e) && (token_t::e_eof == current_token().type))
+         {
+            bool* retinvk_ptr = 0;
+
+            if (state_.return_stmt_present)
+            {
+               dec_.return_present_ = true;
+
+               e = expression_generator_
+                     .return_envelope(e,results_context_,retinvk_ptr);
+            }
+
+            expr.set_expression(e);
+            expr.set_retinvk(retinvk_ptr);
+
+            register_local_vars(expr);
+            register_return_results(expr);
+
+            return !(!expr);
+         }
+         else
+         {
+            if (error_list_.empty())
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR002 - Invalid expression encountered"));
+            }
+
+            dec_.clear    ();
+            sem_.cleanup  ();
+            return_cleanup();
+
+            if ((0 != e) && branch_deletable(e))
+            {
+               delete e;
+            }
+
+            return false;
+         }
+      }
+
+      void process_lexer_errors()
+      {
+         for (std::size_t i = 0; i < lexer().size(); ++i)
+         {
+            if (lexer()[i].is_error())
+            {
+               std::string diagnostic = "ERR003 - ";
+
+               switch (lexer()[i].type)
+               {
+                  case lexer::token::e_error      : diagnostic += "General token error";
+                                                    break;
+
+                  case lexer::token::e_err_symbol : diagnostic += "Symbol error";
+                                                    break;
+
+                  case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
+                                                    break;
+
+                  case lexer::token::e_err_string : diagnostic += "Invalid string token";
+                                                    break;
+
+                  case lexer::token::e_err_sfunc  : diagnostic += "Invalid special function token";
+                                                    break;
+
+                  default                         : diagnostic += "Unknown compiler error";
+               }
+
+               set_error(
+                  make_error(parser_error::e_lexer,
+                             lexer()[i],
+                             diagnostic + ": " + lexer()[i].value));
+            }
+         }
+      }
+
+      inline bool run_assemblies()
+      {
+         if (settings_.commutative_check_enabled())
+         {
+            helper_assembly_.run_inserters(lexer());
+         }
+
+         if (settings_.joiner_enabled())
+         {
+            helper_assembly_.run_joiners(lexer());
+         }
+
+         if (settings_.replacer_enabled())
+         {
+            helper_assembly_.run_modifiers(lexer());
+         }
+
+         if (
+              settings_.numeric_check_enabled () ||
+              settings_.bracket_check_enabled () ||
+              settings_.sequence_check_enabled()
+            )
+         {
+            if (!helper_assembly_.run_scanners(lexer()))
+            {
+               if (helper_assembly_.error_token_scanner)
+               {
+                  lexer::helper::bracket_checker*    bracket_checker_ptr    = 0;
+                  lexer::helper::numeric_checker*    numeric_checker_ptr    = 0;
+                  lexer::helper::sequence_validator* sequence_validator_ptr = 0;
+
+                  if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
+                  {
+                     set_error(
+                        make_error(parser_error::e_token,
+                                   bracket_checker_ptr->error_token(),
+                                   "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'"));
+                  }
+                  else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
+                  {
+                     for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
+                     {
+                        lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
+
+                        set_error(
+                           make_error(parser_error::e_token,
+                                      error_token,
+                                      "ERR005 - Invalid numeric token: '" + error_token.value + "'"));
+                     }
+
+                     if (numeric_checker_ptr->error_count())
+                     {
+                        numeric_checker_ptr->clear_errors();
+                     }
+                  }
+                  else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
+                  {
+                     for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
+                     {
+                        std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
+
+                        set_error(
+                           make_error(parser_error::e_token,
+                                      error_token.first,
+                                      "ERR006 - Invalid token sequence: '" +
+                                      error_token.first.value  + "' and '" +
+                                      error_token.second.value + "'"));
+                     }
+
+                     if (sequence_validator_ptr->error_count())
+                     {
+                        sequence_validator_ptr->clear_errors();
+                     }
+                  }
+               }
+
+               return false;
+            }
+         }
+
+         return true;
+      }
+
+      inline settings_store& settings()
+      {
+         return settings_;
+      }
+
+      inline parser_error::type get_error(const std::size_t& index)
+      {
+         if (index < error_list_.size())
+            return error_list_[index];
+         else
+            throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
+      }
+
+      inline std::string error() const
+      {
+         if (!error_list_.empty())
+         {
+            return error_list_[0].diagnostic;
+         }
+         else
+            return std::string("No Error");
+      }
+
+      inline std::size_t error_count() const
+      {
+         return error_list_.size();
+      }
+
+      inline dependent_entity_collector& dec()
+      {
+         return dec_;
+      }
+
+      inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
+      {
+         if (!settings_.replacer_enabled())
+            return false;
+         else if (details::is_reserved_word(old_symbol))
+            return false;
+         else
+            return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
+      }
+
+      inline bool remove_replace_symbol(const std::string& symbol)
+      {
+         if (!settings_.replacer_enabled())
+            return false;
+         else if (details::is_reserved_word(symbol))
+            return false;
+         else
+            return symbol_replacer_.remove(symbol);
+      }
+
+      inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
+      {
+         resolve_unknown_symbol_ = true;
+
+         if (usr)
+            unknown_symbol_resolver_ = usr;
+         else
+            unknown_symbol_resolver_ = &default_usr_;
+      }
+
+      inline void disable_unknown_symbol_resolver()
+      {
+         resolve_unknown_symbol_  = false;
+         unknown_symbol_resolver_ = &default_usr_;
+      }
+
+   private:
+
+      inline bool valid_base_operation(const std::string& symbol)
+      {
+         const std::size_t length = symbol.size();
+
+         if (
+              (length < 3) || // Shortest base op symbol length
+              (length > 9)    // Longest base op symbol length
+            )
+            return false;
+         else
+            return settings_.function_enabled(symbol) &&
+                   (base_ops_map_.end() != base_ops_map_.find(symbol));
+      }
+
+      inline bool valid_vararg_operation(const std::string& symbol)
+      {
+         static const std::string s_sum     = "sum" ;
+         static const std::string s_mul     = "mul" ;
+         static const std::string s_avg     = "avg" ;
+         static const std::string s_min     = "min" ;
+         static const std::string s_max     = "max" ;
+         static const std::string s_mand    = "mand";
+         static const std::string s_mor     = "mor" ;
+         static const std::string s_multi   = "~"   ;
+         static const std::string s_mswitch = "[*]" ;
+
+         return
+               (
+                  details::imatch(symbol,s_sum    ) ||
+                  details::imatch(symbol,s_mul    ) ||
+                  details::imatch(symbol,s_avg    ) ||
+                  details::imatch(symbol,s_min    ) ||
+                  details::imatch(symbol,s_max    ) ||
+                  details::imatch(symbol,s_mand   ) ||
+                  details::imatch(symbol,s_mor    ) ||
+                  details::imatch(symbol,s_multi  ) ||
+                  details::imatch(symbol,s_mswitch)
+               ) &&
+               settings_.function_enabled(symbol);
+      }
+
+      bool is_invalid_arithmetic_operation(const details::operator_type operation)
+      {
+         return settings_.arithmetic_disabled(operation);
+      }
+
+      bool is_invalid_assignment_operation(const details::operator_type operation)
+      {
+         return settings_.assignment_disabled(operation);
+      }
+
+      bool is_invalid_inequality_operation(const details::operator_type operation)
+      {
+         return settings_.inequality_disabled(operation);
+      }
+
+      #ifdef exprtk_enable_debugging
+      inline void next_token()
+      {
+         std::string ct_str = current_token().value;
+         parser_helper::next_token();
+         std::string depth(2 * state_.scope_depth,' ');
+         exprtk_debug(("%s"
+                       "prev[%s] --> curr[%s]\n",
+                       depth.c_str(),
+                       ct_str.c_str(),
+                       current_token().value.c_str()));
+      }
+      #endif
+
+      inline expression_node_ptr parse_corpus()
+      {
+         std::vector<expression_node_ptr> arg_list;
+         std::vector<bool> side_effect_list;
+
+         expression_node_ptr result = error_node();
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         lexer::token begin_token;
+         lexer::token   end_token;
+
+         for ( ; ; )
+         {
+            state_.side_effect_present = false;
+
+            begin_token = current_token();
+
+            expression_node_ptr arg = parse_expression();
+
+            if (0 == arg)
+            {
+               if (error_list_.empty())
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR007 - Invalid expression encountered"));
+               }
+
+               return error_node();
+            }
+            else
+            {
+               arg_list.push_back(arg);
+
+               side_effect_list.push_back(state_.side_effect_present);
+
+               end_token = current_token();
+
+               std::string sub_expr = construct_subexpr(begin_token,end_token);
+
+               exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
+                             static_cast<int>(arg_list.size() - 1),
+                             sub_expr.c_str()));
+
+               exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
+                             static_cast<int>(arg_list.size() - 1),
+                             state_.side_effect_present ? "true" : "false"));
+
+               exprtk_debug(("-------------------------------------------------\n"));
+            }
+
+            if (lexer().finished())
+               break;
+            else if (token_is(token_t::e_eof,false))
+            {
+               if (lexer().finished())
+                  break;
+               else
+                  next_token();
+            }
+         }
+
+         if (
+              !arg_list.empty() &&
+              is_return_node(arg_list.back())
+            )
+         {
+            dec_.final_stmt_return_ = true;
+         }
+
+         result = simplify(arg_list,side_effect_list);
+
+         sdd.delete_ptr = (0 == result);
+
+         return result;
+      }
+
+      std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token)
+      {
+         std::string result = lexer().substr(begin_token.position,end_token.position);
+
+         for (std::size_t i = 0; i < result.size(); ++i)
+         {
+            if (details::is_whitespace(result[i])) result[i] = ' ';
+         }
+
+         return result;
+      }
+
+      static const precedence_level default_precedence = e_level00;
+
+      struct state_t
+      {
+         inline void set(const precedence_level& l,
+                         const precedence_level& r,
+                         const details::operator_type& o)
+         {
+            left  = l;
+            right = r;
+            operation = o;
+         }
+
+         inline void reset()
+         {
+            left      = e_level00;
+            right     = e_level00;
+            operation = details::e_default;
+         }
+
+         precedence_level left;
+         precedence_level right;
+         details::operator_type operation;
+      };
+
+      inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
+      {
+         expression_node_ptr expression = parse_branch(precedence);
+
+         if (0 == expression)
+         {
+            return error_node();
+         }
+
+         bool break_loop = false;
+
+         state_t current_state;
+
+         for ( ; ; )
+         {
+            current_state.reset();
+
+            switch (current_token().type)
+            {
+               case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break;
+               case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break;
+               case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break;
+               case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break;
+               case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break;
+               case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break;
+               case token_t::e_swap   : current_state.set(e_level00,e_level00,details::e_swap  ); break;
+               case token_t::e_lt     : current_state.set(e_level05,e_level06,details::    e_lt); break;
+               case token_t::e_lte    : current_state.set(e_level05,e_level06,details::   e_lte); break;
+               case token_t::e_eq     : current_state.set(e_level05,e_level06,details::    e_eq); break;
+               case token_t::e_ne     : current_state.set(e_level05,e_level06,details::    e_ne); break;
+               case token_t::e_gte    : current_state.set(e_level05,e_level06,details::   e_gte); break;
+               case token_t::e_gt     : current_state.set(e_level05,e_level06,details::    e_gt); break;
+               case token_t::e_add    : current_state.set(e_level07,e_level08,details::   e_add); break;
+               case token_t::e_sub    : current_state.set(e_level07,e_level08,details::   e_sub); break;
+               case token_t::e_div    : current_state.set(e_level10,e_level11,details::   e_div); break;
+               case token_t::e_mul    : current_state.set(e_level10,e_level11,details::   e_mul); break;
+               case token_t::e_mod    : current_state.set(e_level10,e_level11,details::   e_mod); break;
+               case token_t::e_pow    : current_state.set(e_level12,e_level12,details::   e_pow); break;
+               default                : if (token_t::e_symbol == current_token().type)
+                                        {
+                                           static const std::string s_and   =   "and";
+                                           static const std::string s_nand  =  "nand";
+                                           static const std::string s_or    =    "or";
+                                           static const std::string s_nor   =   "nor";
+                                           static const std::string s_xor   =   "xor";
+                                           static const std::string s_xnor  =  "xnor";
+                                           static const std::string s_in    =    "in";
+                                           static const std::string s_like  =  "like";
+                                           static const std::string s_ilike = "ilike";
+                                           static const std::string s_and1  =     "&";
+                                           static const std::string s_or1   =     "|";
+
+                                           if (details::imatch(current_token().value,s_and))
+                                           {
+                                              current_state.set(e_level03,e_level04,details::e_and);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_and1))
+                                           {
+                                              #ifndef exprtk_disable_sc_andor
+                                              current_state.set(e_level03,e_level04,details::e_scand);
+                                              #else
+                                              current_state.set(e_level03,e_level04,details::e_and);
+                                              #endif
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_nand))
+                                           {
+                                              current_state.set(e_level03,e_level04,details::e_nand);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_or))
+                                           {
+                                              current_state.set(e_level01,e_level02,details::e_or);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_or1))
+                                           {
+                                              #ifndef exprtk_disable_sc_andor
+                                              current_state.set(e_level01,e_level02,details::e_scor);
+                                              #else
+                                              current_state.set(e_level01,e_level02,details::e_or);
+                                              #endif
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_nor))
+                                           {
+                                              current_state.set(e_level01,e_level02,details::e_nor);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_xor))
+                                           {
+                                              current_state.set(e_level01,e_level02,details::e_xor);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_xnor))
+                                           {
+                                              current_state.set(e_level01,e_level02,details::e_xnor);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_in))
+                                           {
+                                              current_state.set(e_level04,e_level04,details::e_in);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_like))
+                                           {
+                                              current_state.set(e_level04,e_level04,details::e_like);
+                                              break;
+                                           }
+                                           else if (details::imatch(current_token().value,s_ilike))
+                                           {
+                                              current_state.set(e_level04,e_level04,details::e_ilike);
+                                              break;
+                                           }
+                                        }
+
+                                        break_loop = true;
+            }
+
+            if (break_loop)
+            {
+               parse_pending_string_rangesize(expression);
+               break;
+            }
+            else if (current_state.left < precedence)
+               break;
+
+            lexer::token prev_token = current_token();
+
+            next_token();
+
+            expression_node_ptr right_branch   = error_node();
+            expression_node_ptr new_expression = error_node();
+
+            if (is_invalid_arithmetic_operation(current_state.operation))
+            {
+               free_node(node_allocator_,expression);
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             prev_token,
+                             "ERR008 - Invalid arithmetic operation '" + details::to_str(current_state.operation) + "'"));
+
+               return error_node();
+            }
+            else if (is_invalid_inequality_operation(current_state.operation))
+            {
+               free_node(node_allocator_,expression);
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             prev_token,
+                             "ERR009 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'"));
+
+               return error_node();
+            }
+            else if (is_invalid_assignment_operation(current_state.operation))
+            {
+               free_node(node_allocator_,expression);
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             prev_token,
+                             "ERR010 - Invalid assignment operation '" + details::to_str(current_state.operation) + "'"));
+
+               return error_node();
+            }
+
+            if (0 != (right_branch = parse_expression(current_state.right)))
+            {
+               if (
+                    details::is_return_node(  expression) ||
+                    details::is_return_node(right_branch)
+                  )
+               {
+                  free_node(node_allocator_,  expression);
+                  free_node(node_allocator_,right_branch);
+
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                prev_token,
+                                "ERR011 - Return statements cannot be part of sub-expressions"));
+
+                  return error_node();
+               }
+
+               new_expression = expression_generator_
+                                  (
+                                    current_state.operation,
+                                    expression,
+                                    right_branch
+                                  );
+            }
+
+            if (0 == new_expression)
+            {
+               if (error_list_.empty())
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                prev_token,
+                                !synthesis_error_.empty() ?
+                                synthesis_error_ :
+                                "ERR012 - General parsing error at token: '" + prev_token.value + "'"));
+               }
+
+               free_node(node_allocator_,expression);
+
+               return error_node();
+            }
+            else
+            {
+               expression = new_expression;
+
+               if (token_is(token_t::e_ternary,false) && (precedence == e_level00))
+               {
+                  expression = parse_ternary_conditional_statement(expression);
+               }
+
+               parse_pending_string_rangesize(expression);
+            }
+         }
+
+         return expression;
+      }
+
+      bool simplify_unary_negation_branch(expression_node_ptr& node)
+      {
+         {
+            typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t;
+            ubn_t* n = dynamic_cast<ubn_t*>(node);
+
+            if (n)
+            {
+               expression_node_ptr un_r = n->branch(0);
+               n->release();
+               free_node(node_allocator_,node);
+               node = un_r;
+
+               return true;
+            }
+         }
+
+         {
+            typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t;
+
+            uvn_t* n = dynamic_cast<uvn_t*>(node);
+
+            if (n)
+            {
+               const T& v = n->v();
+               expression_node_ptr return_node = error_node();
+
+               if (
+                    (0 != (return_node = symtab_store_.get_variable(v))) ||
+                    (0 != (return_node = sem_         .get_variable(v)))
+                  )
+               {
+                  free_node(node_allocator_,node);
+                  node = return_node;
+
+                  return true;
+               }
+               else
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR013 - Failed to find variable node in symbol table"));
+
+                  free_node(node_allocator_,node);
+
+                  return false;
+               }
+            }
+         }
+
+         return false;
+      }
+
+      static inline expression_node_ptr error_node()
+      {
+         return reinterpret_cast<expression_node_ptr>(0);
+      }
+
+      template <typename Type, std::size_t N>
+      struct scoped_delete
+      {
+         typedef Type* ptr_t;
+
+         scoped_delete(parser<T>& pr, ptr_t& p)
+         : delete_ptr(true),
+           parser_(pr),
+           p_(&p)
+         {}
+
+         scoped_delete(parser<T>& pr, ptr_t (&p)[N])
+         : delete_ptr(true),
+           parser_(pr),
+           p_(&p[0])
+         {}
+
+        ~scoped_delete()
+         {
+            if (delete_ptr)
+            {
+               for (std::size_t i = 0; i < N; ++i)
+               {
+                  free_node(parser_.node_allocator_,p_[i]);
+               }
+            }
+         }
+
+         bool delete_ptr;
+         parser<T>& parser_;
+         ptr_t* p_;
+
+      private:
+
+         scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
+      };
+
+      template <typename Type>
+      struct scoped_deq_delete
+      {
+         typedef Type* ptr_t;
+
+         scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
+         : delete_ptr(true),
+           parser_(pr),
+           deq_(deq)
+         {}
+
+        ~scoped_deq_delete()
+         {
+            if (delete_ptr && !deq_.empty())
+            {
+               for (std::size_t i = 0; i < deq_.size(); ++i)
+               {
+                  free_node(parser_.node_allocator_,deq_[i]);
+               }
+
+               deq_.clear();
+            }
+         }
+
+         bool delete_ptr;
+         parser<T>& parser_;
+         std::deque<ptr_t>& deq_;
+
+      private:
+
+         scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&);
+      };
+
+      template <typename Type>
+      struct scoped_vec_delete
+      {
+         typedef Type* ptr_t;
+
+         scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
+         : delete_ptr(true),
+           parser_(pr),
+           vec_(vec)
+         {}
+
+        ~scoped_vec_delete()
+         {
+            if (delete_ptr && !vec_.empty())
+            {
+               for (std::size_t i = 0; i < vec_.size(); ++i)
+               {
+                  free_node(parser_.node_allocator_,vec_[i]);
+               }
+
+               vec_.clear();
+            }
+         }
+
+         bool delete_ptr;
+         parser<T>& parser_;
+         std::vector<ptr_t>& vec_;
+
+      private:
+
+         scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&);
+      };
+
+      struct scoped_bool_negator
+      {
+         scoped_bool_negator(bool& bb)
+         : b(bb)
+         { b = !b; }
+
+        ~scoped_bool_negator()
+         { b = !b; }
+
+         bool& b;
+      };
+
+      struct scoped_bool_or_restorer
+      {
+         scoped_bool_or_restorer(bool& bb)
+         : b(bb),
+           original_value_(bb)
+         {}
+
+        ~scoped_bool_or_restorer()
+         {
+            b = b || original_value_;
+         }
+
+         bool& b;
+         bool original_value_;
+      };
+
+      inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name)
+      {
+         expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
+
+         switch (function->param_count)
+         {
+            case  0 : func_node = parse_function_call_0  (function,function_name); break;
+            case  1 : func_node = parse_function_call< 1>(function,function_name); break;
+            case  2 : func_node = parse_function_call< 2>(function,function_name); break;
+            case  3 : func_node = parse_function_call< 3>(function,function_name); break;
+            case  4 : func_node = parse_function_call< 4>(function,function_name); break;
+            case  5 : func_node = parse_function_call< 5>(function,function_name); break;
+            case  6 : func_node = parse_function_call< 6>(function,function_name); break;
+            case  7 : func_node = parse_function_call< 7>(function,function_name); break;
+            case  8 : func_node = parse_function_call< 8>(function,function_name); break;
+            case  9 : func_node = parse_function_call< 9>(function,function_name); break;
+            case 10 : func_node = parse_function_call<10>(function,function_name); break;
+            case 11 : func_node = parse_function_call<11>(function,function_name); break;
+            case 12 : func_node = parse_function_call<12>(function,function_name); break;
+            case 13 : func_node = parse_function_call<13>(function,function_name); break;
+            case 14 : func_node = parse_function_call<14>(function,function_name); break;
+            case 15 : func_node = parse_function_call<15>(function,function_name); break;
+            case 16 : func_node = parse_function_call<16>(function,function_name); break;
+            case 17 : func_node = parse_function_call<17>(function,function_name); break;
+            case 18 : func_node = parse_function_call<18>(function,function_name); break;
+            case 19 : func_node = parse_function_call<19>(function,function_name); break;
+            case 20 : func_node = parse_function_call<20>(function,function_name); break;
+            default : {
+                         set_error(
+                            make_error(parser_error::e_syntax,
+                                       current_token(),
+                                       "ERR014 - Invalid number of parameters for function: '" + function_name + "'"));
+
+                         return error_node();
+                      }
+         }
+
+         if (func_node)
+            return func_node;
+         else
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR015 - Failed to generate call to function: '" + function_name + "'"));
+
+            return error_node();
+         }
+      }
+
+      template <std::size_t NumberofParameters>
+      inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
+      {
+         #ifdef _MSC_VER
+            #pragma warning(push)
+            #pragma warning(disable: 4127)
+         #endif
+         if (0 == NumberofParameters)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR016 - Expecting ifunction '" + function_name + "' to have non-zero parameter count"));
+
+            return error_node();
+         }
+         #ifdef _MSC_VER
+            #pragma warning(pop)
+         #endif
+
+         expression_node_ptr branch[NumberofParameters];
+         expression_node_ptr result  = error_node();
+
+         std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
+         scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
+
+         next_token();
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR017 - Expecting argument list for function: '" + function_name + "'"));
+
+            return error_node();
+         }
+
+         for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
+         {
+            branch[i] = parse_expression();
+
+            if (0 == branch[i])
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR018 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'"));
+
+               return error_node();
+            }
+            else if (i < static_cast<int>(NumberofParameters - 1))
+            {
+               if (!token_is(token_t::e_comma))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR019 - Invalid number of arguments for function: '" + function_name + "'"));
+
+                  return error_node();
+               }
+            }
+         }
+
+         if (!token_is(token_t::e_rbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR020 - Invalid number of arguments for function: '" + function_name + "'"));
+
+            return error_node();
+         }
+         else
+            result = expression_generator_.function(function,branch);
+
+         sd.delete_ptr = false;
+
+         return result;
+      }
+
+      inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
+      {
+         expression_node_ptr result = expression_generator_.function(function);
+
+         state_.side_effect_present = function->has_side_effects();
+
+         next_token();
+
+         if (
+               token_is(token_t::e_lbracket) &&
+              !token_is(token_t::e_rbracket)
+            )
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR021 - Expecting '()' to proceed call to function: '" + function_name + "'"));
+
+            free_node(node_allocator_,result);
+
+            return error_node();
+         }
+         else
+            return result;
+      }
+
+      template <std::size_t MaxNumberofParameters>
+      inline int parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters])
+      {
+         std::fill_n(param_list,MaxNumberofParameters,reinterpret_cast<expression_node_ptr>(0));
+
+         scoped_delete<expression_node_t,MaxNumberofParameters> sd(*this,param_list);
+
+         next_token();
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR022 - Expected a '(' at start of function call, instead got: '" + current_token().value + "'"));
+
+            return 0;
+         }
+
+         int param_index = 0;
+
+         for (; param_index < static_cast<int>(MaxNumberofParameters); ++param_index)
+         {
+            param_list[param_index] = parse_expression();
+
+            if (0 == param_list[param_index])
+               return 0;
+            else if (token_is(token_t::e_rbracket))
+               break;
+            else if (token_is(token_t::e_comma))
+               continue;
+            else
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR023 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'"));
+
+               return 0;
+            }
+         }
+
+         sd.delete_ptr = false;
+
+         return (param_index + 1);
+      }
+
+      inline expression_node_ptr parse_base_operation()
+      {
+         typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
+
+         const std::string operation_name = current_token().value;
+         map_range_t itr_range = base_ops_map_.equal_range(operation_name);
+
+         if (0 == std::distance(itr_range.first,itr_range.second))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR024 - No entry found for base operation: " + operation_name));
+
+            return error_node();
+         }
+
+         static const std::size_t MaxNumberofParameters = 4;
+         expression_node_ptr param_list[MaxNumberofParameters] = {0};
+
+         std::size_t parameter_count = parse_base_function_call(param_list);
+
+         if (0 == parameter_count)
+         {
+            return error_node();
+         }
+         else if (parameter_count <= MaxNumberofParameters)
+         {
+            for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
+            {
+               details::base_operation_t& operation = itr->second;
+
+               if (operation.num_params == parameter_count)
+               {
+                  switch (parameter_count)
+                  {
+                     #define base_opr_case(N)                                        \
+                     case N : {                                                      \
+                                 expression_node_ptr pl##N[N] = {0};                 \
+                                 std::copy(param_list,param_list + N,pl##N);         \
+                                 lodge_symbol(operation_name,e_st_function);         \
+                                 return expression_generator_(operation.type,pl##N); \
+                              }                                                      \
+
+                     base_opr_case(1)
+                     base_opr_case(2)
+                     base_opr_case(3)
+                     base_opr_case(4)
+                     #undef base_opr_case
+                  }
+               }
+            }
+         }
+
+         for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
+         {
+            free_node(node_allocator_,param_list[i]);
+         }
+
+         set_error(
+            make_error(parser_error::e_syntax,
+                       current_token(),
+                       "ERR025 - Invalid number of parameters for call to function: '" + operation_name + "'"));
+
+         return error_node();
+      }
+
+      inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition)
+      {
+         // Parse: [if][(][condition][,][consequent][,][alternative][)]
+
+         expression_node_ptr consequent  = error_node();
+         expression_node_ptr alternative = error_node();
+
+         bool result = true;
+
+         if (!token_is(token_t::e_comma))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR026 - Expected ',' between if-statement condition and consequent"));
+            result = false;
+         }
+         else if (0 == (consequent = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR027 - Failed to parse consequent for if-statement"));
+            result = false;
+         }
+         else if (!token_is(token_t::e_comma))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR028 - Expected ',' between if-statement consequent and alternative"));
+            result = false;
+         }
+         else if (0 == (alternative = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR029 - Failed to parse alternative for if-statement"));
+            result = false;
+         }
+         else if (!token_is(token_t::e_rbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR030 - Expected ')' at the end of if-statement"));
+            result = false;
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         if (result)
+         {
+            const bool consq_is_str = is_generally_string_node( consequent);
+            const bool alter_is_str = is_generally_string_node(alternative);
+
+            if (consq_is_str || alter_is_str)
+            {
+               if (consq_is_str && alter_is_str)
+               {
+                  return expression_generator_
+                           .conditional_string(condition,consequent,alternative);
+               }
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR031 - Return types of ternary if-statement differ"));
+
+               result = false;
+            }
+         }
+         #endif
+
+         if (!result)
+         {
+            free_node(node_allocator_,  condition);
+            free_node(node_allocator_, consequent);
+            free_node(node_allocator_,alternative);
+
+            return error_node();
+         }
+         else
+            return expression_generator_
+                     .conditional(condition,consequent,alternative);
+      }
+
+      inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
+      {
+         expression_node_ptr consequent  = error_node();
+         expression_node_ptr alternative = error_node();
+
+         bool result = true;
+
+         if (token_is(token_t::e_lcrlbracket,false))
+         {
+            if (0 == (consequent = parse_multi_sequence("if-statement-01")))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR032 - Failed to parse body of consequent for if-statement"));
+               result = false;
+            }
+         }
+         else
+         {
+            if (
+                 settings_.commutative_check_enabled() &&
+                 token_is(token_t::e_mul,false)
+               )
+            {
+               next_token();
+            }
+
+            if (0 != (consequent = parse_expression()))
+            {
+               if (!token_is(token_t::e_eof))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR033 - Expected ';' at the end of the consequent for if-statement"));
+                  result = false;
+               }
+            }
+            else
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR034 - Failed to parse body of consequent for if-statement"));
+               result = false;
+            }
+         }
+
+         if (result)
+         {
+            if (details::imatch(current_token().value,"else"))
+            {
+               next_token();
+
+               if (token_is(token_t::e_lcrlbracket,false))
+               {
+                  if (0 == (alternative = parse_multi_sequence("else-statement-01")))
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR035 - Failed to parse body of the 'else' for if-statement"));
+                     result = false;
+                  }
+               }
+               else if (details::imatch(current_token().value,"if"))
+               {
+                  if (0 == (alternative = parse_conditional_statement()))
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR036 - Failed to parse body of if-else statement"));
+                     result = false;
+                  }
+               }
+               else if (0 != (alternative = parse_expression()))
+               {
+                  if (!token_is(token_t::e_eof))
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR037 - Expected ';' at the end of the 'else-if' for the if-statement"));
+                     result = false;
+                  }
+               }
+               else
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR038 - Failed to parse body of the 'else' for if-statement"));
+                  result = false;
+               }
+            }
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         if (result)
+         {
+            const bool consq_is_str = is_generally_string_node( consequent);
+            const bool alter_is_str = is_generally_string_node(alternative);
+
+            if (consq_is_str || alter_is_str)
+            {
+               if (consq_is_str && alter_is_str)
+               {
+                  return expression_generator_
+                           .conditional_string(condition,consequent,alternative);
+               }
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR039 - Return types of ternary if-statement differ"));
+
+               result = false;
+            }
+         }
+         #endif
+
+         if (!result)
+         {
+            free_node(node_allocator_,  condition);
+            free_node(node_allocator_, consequent);
+            free_node(node_allocator_,alternative);
+
+            return error_node();
+         }
+         else
+            return expression_generator_
+                     .conditional(condition,consequent,alternative);
+      }
+
+      inline expression_node_ptr parse_conditional_statement()
+      {
+         expression_node_ptr condition = error_node();
+
+         next_token();
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR040 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'"));
+
+            return error_node();
+         }
+         else if (0 == (condition = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR041 - Failed to parse condition for if-statement"));
+
+            return error_node();
+         }
+         else if (token_is(token_t::e_comma,false))
+         {
+            // if (x,y,z)
+            return parse_conditional_statement_01(condition);
+         }
+         else if (token_is(token_t::e_rbracket))
+         {
+            // 00. if (x) y;
+            // 01. if (x) y; else z;
+            // 02. if (x) y; else {z0; ... zn;}
+            // 03. if (x) y; else if (z) w;
+            // 04. if (x) y; else if (z) w; else u;
+            // 05. if (x) y; else if (z) w; else {u0; ... un;}
+            // 06. if (x) y; else if (z) {w0; ... wn;}
+            // 07. if (x) {y0; ... yn;}
+            // 08. if (x) {y0; ... yn;} else z;
+            // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
+            // 10. if (x) {y0; ... yn;} else if (z) w;
+            // 11. if (x) {y0; ... yn;} else if (z) w; else u;
+            // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
+            // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
+            return parse_conditional_statement_02(condition);
+         }
+
+         set_error(
+            make_error(parser_error::e_syntax,
+                       current_token(),
+                       "ERR042 - Invalid if-statement"));
+
+         free_node(node_allocator_,condition);
+
+         return error_node();
+      }
+
+      inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition)
+      {
+         // Parse: [condition][?][consequent][:][alternative]
+         expression_node_ptr consequent  = error_node();
+         expression_node_ptr alternative = error_node();
+
+         bool result = true;
+
+         if (0 == condition)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR043 - Encountered invalid condition branch for ternary if-statement"));
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_ternary))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR044 - Expected '?' after condition of ternary if-statement"));
+
+            result = false;
+         }
+         else if (0 == (consequent = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR045 - Failed to parse consequent for ternary if-statement"));
+
+            result = false;
+         }
+         else if (!token_is(token_t::e_colon))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR046 - Expected ':' between ternary if-statement consequent and alternative"));
+
+            result = false;
+         }
+         else if (0 == (alternative = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR047 - Failed to parse alternative for ternary if-statement"));
+
+            result = false;
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         if (result)
+         {
+            const bool consq_is_str = is_generally_string_node( consequent);
+            const bool alter_is_str = is_generally_string_node(alternative);
+
+            if (consq_is_str || alter_is_str)
+            {
+               if (consq_is_str && alter_is_str)
+               {
+                  return expression_generator_
+                           .conditional_string(condition,consequent,alternative);
+               }
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR048 - Return types of ternary if-statement differ"));
+
+               result = false;
+            }
+         }
+         #endif
+
+         if (!result)
+         {
+            free_node(node_allocator_,  condition);
+            free_node(node_allocator_, consequent);
+            free_node(node_allocator_,alternative);
+
+            return error_node();
+         }
+         else
+            return expression_generator_
+                     .conditional(condition,consequent,alternative);
+      }
+
+      inline expression_node_ptr parse_while_loop()
+      {
+         // Parse: [while][(][test expr][)][{][expression][}]
+         expression_node_ptr condition   = error_node();
+         expression_node_ptr branch      = error_node();
+         expression_node_ptr result_node = error_node();
+
+         bool result = true;
+
+         next_token();
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR049 - Expected '(' at start of while-loop condition statement"));
+
+            return error_node();
+         }
+         else if (0 == (condition = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR050 - Failed to parse condition for while-loop"));
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_rbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR051 - Expected ')' at end of while-loop condition statement"));
+            result = false;
+         }
+
+         brkcnt_list_.push_front(false);
+
+         if (result)
+         {
+            if (0 == (branch = parse_multi_sequence("while-loop")))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR052 - Failed to parse body of while-loop"));
+               result = false;
+            }
+            else if (0 == (result_node = expression_generator_.while_loop(condition,
+                                                                          branch,
+                                                                          brkcnt_list_.front())))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR053 - Failed to synthesize while-loop"));
+               result = false;
+            }
+         }
+
+         if (!result)
+         {
+            free_node(node_allocator_,     branch);
+            free_node(node_allocator_,  condition);
+            free_node(node_allocator_,result_node);
+
+            brkcnt_list_.pop_front();
+
+            return error_node();
+         }
+         else
+            return result_node;
+      }
+
+      inline expression_node_ptr parse_repeat_until_loop()
+      {
+         // Parse: [repeat][{][expression][}][until][(][test expr][)]
+         expression_node_ptr condition = error_node();
+         expression_node_ptr branch    = error_node();
+         next_token();
+
+         std::vector<expression_node_ptr> arg_list;
+         std::vector<bool> side_effect_list;
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         brkcnt_list_.push_front(false);
+
+         if (details::imatch(current_token().value,"until"))
+         {
+            next_token();
+            branch = node_allocator_.allocate<details::null_node<T> >();
+         }
+         else
+         {
+            token_t::token_type seperator = token_t::e_eof;
+
+            scope_handler sh(*this);
+
+            scoped_bool_or_restorer sbr(state_.side_effect_present);
+
+            for ( ; ; )
+            {
+               state_.side_effect_present = false;
+
+               expression_node_ptr arg = parse_expression();
+
+               if (0 == arg)
+                  return error_node();
+               else
+               {
+                  arg_list.push_back(arg);
+                  side_effect_list.push_back(state_.side_effect_present);
+               }
+
+               if (details::imatch(current_token().value,"until"))
+               {
+                  next_token();
+                  break;
+               }
+
+               bool is_next_until = peek_token_is(token_t::e_symbol) &&
+                                    peek_token_is("until");
+
+               if (!token_is(seperator) && is_next_until)
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR054 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop"));
+
+                  return error_node();
+               }
+
+               if (details::imatch(current_token().value,"until"))
+               {
+                  next_token();
+                  break;
+               }
+            }
+
+            branch = simplify(arg_list,side_effect_list);
+
+            sdd.delete_ptr = (0 == branch);
+
+            if (sdd.delete_ptr)
+            {
+               brkcnt_list_.pop_front();
+
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR055 - Failed to parse body of repeat until loop"));
+
+               return error_node();
+            }
+         }
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            brkcnt_list_.pop_front();
+
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR056 - Expected '(' before condition statement of repeat until loop"));
+
+            free_node(node_allocator_,branch);
+
+            return error_node();
+         }
+         else if (0 == (condition = parse_expression()))
+         {
+            brkcnt_list_.pop_front();
+
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR057 - Failed to parse condition for repeat until loop"));
+
+            free_node(node_allocator_,branch);
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_rbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR058 - Expected ')' after condition of repeat until loop"));
+
+            free_node(node_allocator_,    branch);
+            free_node(node_allocator_, condition);
+
+            brkcnt_list_.pop_front();
+
+            return error_node();
+         }
+
+         expression_node_ptr result;
+
+         result = expression_generator_
+                     .repeat_until_loop(condition,branch,brkcnt_list_.front());
+
+         if (0 == result)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR059 - Failed to synthesize repeat until loop"));
+
+            free_node(node_allocator_, condition);
+            brkcnt_list_.pop_front();
+
+            return error_node();
+         }
+         else
+         {
+            brkcnt_list_.pop_front();
+            return result;
+         }
+      }
+
+      inline expression_node_ptr parse_for_loop()
+      {
+         expression_node_ptr initialiser = error_node();
+         expression_node_ptr condition   = error_node();
+         expression_node_ptr incrementor = error_node();
+         expression_node_ptr loop_body   = error_node();
+
+         scope_element* se = 0;
+         bool result       = true;
+         std::string loop_counter_symbol;
+
+         next_token();
+
+         scope_handler sh(*this);
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR060 - Expected '(' at start of for-loop"));
+
+            return error_node();
+         }
+
+         if (!token_is(token_t::e_eof))
+         {
+            if (
+                 !token_is(token_t::e_symbol,false) &&
+                 details::imatch(current_token().value,"var")
+               )
+            {
+               next_token();
+
+               if (!token_is(token_t::e_symbol,false))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR061 - Expected a variable at the start of initialiser section of for-loop"));
+
+                  return error_node();
+               }
+               else if (!peek_token_is(token_t::e_assign))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR062 - Expected variable assignment of initialiser section of for-loop"));
+
+                  return error_node();
+               }
+
+               loop_counter_symbol = current_token().value;
+
+               se = &sem_.get_element(loop_counter_symbol);
+
+               if ((se->name == loop_counter_symbol) && se->active)
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR063 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration"));
+
+                  return error_node();
+               }
+               else if (!symtab_store_.is_variable(loop_counter_symbol))
+               {
+                  if (
+                       !se->active &&
+                       (se->name == loop_counter_symbol) &&
+                       (se->type ==  scope_element::e_variable)
+                     )
+                  {
+                     se->active = true;
+                     se->ref_count++;
+                  }
+                  else
+                  {
+                     scope_element nse;
+                     nse.name      = loop_counter_symbol;
+                     nse.active    = true;
+                     nse.ref_count = 1;
+                     nse.type      = scope_element::e_variable;
+                     nse.depth     = state_.scope_depth;
+                     nse.data      = new T(T(0));
+                     nse.var_node  = new variable_node_t(*(T*)(nse.data));
+
+                     if (!sem_.add_element(nse))
+                     {
+                        set_error(
+                           make_error(parser_error::e_syntax,
+                                      current_token(),
+                                      "ERR064 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM"));
+
+                        sem_.free_element(nse);
+
+                        result = false;
+                     }
+                     else
+                     {
+                        exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
+
+                        state_.activate_side_effect("parse_for_loop()");
+                     }
+                  }
+               }
+            }
+
+            if (0 == (initialiser = parse_expression()))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR065 - Failed to parse initialiser of for-loop"));
+               result = false;
+            }
+            else if (!token_is(token_t::e_eof))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR066 - Expected ';' after initialiser of for-loop"));
+               result = false;
+            }
+         }
+
+         if (!token_is(token_t::e_eof))
+         {
+            if (0 == (condition = parse_expression()))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR067 - Failed to parse condition of for-loop"));
+               result = false;
+            }
+            else if (!token_is(token_t::e_eof))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR068 - Expected ';' after condition section of for-loop"));
+               result = false;
+            }
+         }
+
+         if (!token_is(token_t::e_rbracket))
+         {
+            if (0 == (incrementor = parse_expression()))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR069 - Failed to parse incrementor of for-loop"));
+               result = false;
+            }
+            else if (!token_is(token_t::e_rbracket))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR070 - Expected ')' after incrementor section of for-loop"));
+               result = false;
+            }
+         }
+
+         if (result)
+         {
+            brkcnt_list_.push_front(false);
+            if (0 == (loop_body = parse_multi_sequence("for-loop")))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR071 - Failed to parse body of for-loop"));
+               result = false;
+            }
+         }
+
+         if (!result)
+         {
+            if (se)
+            {
+               se->ref_count--;
+            }
+
+            sem_.cleanup();
+
+            free_node(node_allocator_,initialiser);
+            free_node(node_allocator_,  condition);
+            free_node(node_allocator_,incrementor);
+            free_node(node_allocator_,  loop_body);
+
+            if (!brkcnt_list_.empty())
+            {
+               brkcnt_list_.pop_front();
+            }
+
+            return error_node();
+         }
+         else
+         {
+            expression_node_ptr result_node =
+                   expression_generator_.for_loop(initialiser,
+                                                  condition,
+                                                  incrementor,
+                                                  loop_body,
+                                                  brkcnt_list_.front());
+            brkcnt_list_.pop_front();
+
+            return result_node;
+         }
+      }
+
+      inline expression_node_ptr parse_switch_statement()
+      {
+         std::vector<expression_node_ptr> arg_list;
+         expression_node_ptr result = error_node();
+
+         if (!details::imatch(current_token().value,"switch"))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR072 - Expected keyword 'switch'"));
+
+            return error_node();
+         }
+
+         scoped_vec_delete<expression_node_t> svd(*this,arg_list);
+
+         next_token();
+
+         if (!token_is(token_t::e_lcrlbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR073 - Expected '{' for call to switch statement"));
+
+            return error_node();
+         }
+
+         for ( ; ; )
+         {
+            if (!details::imatch("case",current_token().value))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR074 - Expected either a 'case' or 'default' statement"));
+
+               return error_node();
+            }
+
+            next_token();
+
+            expression_node_ptr condition = parse_expression();
+
+            if (0 == condition)
+               return error_node();
+            else if (!token_is(token_t::e_colon))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR075 - Expected ':' for case of switch statement"));
+
+               return error_node();
+            }
+
+            expression_node_ptr consequent = parse_expression();
+
+            if (0 == consequent)
+               return error_node();
+            else if (!token_is(token_t::e_eof))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR076 - Expected ';' at end of case for switch statement"));
+
+               return error_node();
+            }
+
+            // Can we optimise away the case statement?
+            if (is_constant_node(condition) && is_false(condition))
+            {
+               free_node(node_allocator_, condition);
+               free_node(node_allocator_,consequent);
+
+               condition  = 0;
+               consequent = 0;
+            }
+            else
+            {
+               arg_list.push_back( condition);
+               arg_list.push_back(consequent);
+            }
+
+            if (details::imatch("default",current_token().value))
+            {
+               next_token();
+               if (!token_is(token_t::e_colon))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR077 - Expected ':' for default of switch statement"));
+
+                  return error_node();
+               }
+
+               expression_node_ptr default_statement = error_node();
+
+               if (token_is(token_t::e_lcrlbracket,false))
+                  default_statement = parse_multi_sequence("switch-default");
+               else
+                  default_statement = parse_expression();
+
+               if (0 == default_statement)
+                  return error_node();
+               else if (!token_is(token_t::e_eof))
+               {
+                  free_node(node_allocator_,default_statement);
+
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR078 - Expected ';' at end of default for switch statement"));
+
+                  return error_node();
+               }
+
+               arg_list.push_back(default_statement);
+               break;
+            }
+         }
+
+         if (!token_is(token_t::e_rcrlbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR079 - Expected '}' at end of switch statement"));
+
+            return error_node();
+         }
+
+         result = expression_generator_.switch_statement(arg_list);
+
+         svd.delete_ptr = (0 == result);
+
+         return result;
+      }
+
+      inline expression_node_ptr parse_multi_switch_statement()
+      {
+         std::vector<expression_node_ptr> arg_list;
+         expression_node_ptr result = error_node();
+
+         if (!details::imatch(current_token().value,"[*]"))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR080 - Expected token '[*]'"));
+
+            return error_node();
+         }
+
+         scoped_vec_delete<expression_node_t> svd(*this,arg_list);
+
+         next_token();
+
+         if (!token_is(token_t::e_lcrlbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR081 - Expected '{' for call to [*] statement"));
+
+            return error_node();
+         }
+
+         for ( ; ; )
+         {
+            if (!details::imatch("case",current_token().value))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR082 - Expected a 'case' statement for multi-switch"));
+
+               return error_node();
+            }
+
+            next_token();
+
+            expression_node_ptr condition = parse_expression();
+
+            if (0 == condition)
+               return error_node();
+
+            if (!token_is(token_t::e_colon))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR083 - Expected ':' for case of [*] statement"));
+
+               return error_node();
+            }
+
+            expression_node_ptr consequent = parse_expression();
+
+            if (0 == consequent)
+               return error_node();
+
+            if (!token_is(token_t::e_eof))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR084 - Expected ';' at end of case for [*] statement"));
+
+               return error_node();
+            }
+
+            // Can we optimise away the case statement?
+            if (is_constant_node(condition) && is_false(condition))
+            {
+               free_node(node_allocator_, condition);
+               free_node(node_allocator_,consequent);
+
+               condition  = 0;
+               consequent = 0;
+            }
+            else
+            {
+               arg_list.push_back(condition);
+               arg_list.push_back(consequent);
+            }
+
+            if (token_is(token_t::e_rcrlbracket,false))
+            {
+               break;
+            }
+         }
+
+         if (!token_is(token_t::e_rcrlbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR085 - Expected '}' at end of [*] statement"));
+
+            return error_node();
+         }
+
+         result = expression_generator_.multi_switch_statement(arg_list);
+
+         svd.delete_ptr = (0 == result);
+
+         return result;
+      }
+
+      inline expression_node_ptr parse_vararg_function()
+      {
+         std::vector<expression_node_ptr> arg_list;
+         expression_node_ptr result = error_node();
+
+         details::operator_type opt_type = details::e_default;
+         const std::string symbol = current_token().value;
+
+         if (details::imatch(symbol,"~"))
+         {
+            next_token();
+            return parse_multi_sequence();
+         }
+         else if (details::imatch(symbol,"[*]"))
+         {
+            return parse_multi_switch_statement();
+         }
+         else if (details::imatch(symbol,"avg" )) opt_type = details::e_avg;
+         else if (details::imatch(symbol,"mand")) opt_type = details::e_mand;
+         else if (details::imatch(symbol,"max" )) opt_type = details::e_max;
+         else if (details::imatch(symbol,"min" )) opt_type = details::e_min;
+         else if (details::imatch(symbol,"mor" )) opt_type = details::e_mor;
+         else if (details::imatch(symbol,"mul" )) opt_type = details::e_prod;
+         else if (details::imatch(symbol,"sum" )) opt_type = details::e_sum;
+         else
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR086 - Unsupported vararg function: " + symbol));
+
+            return error_node();
+         }
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         lodge_symbol(symbol,e_st_function);
+
+         next_token();
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR087 - Expected '(' for call to vararg function: " + symbol));
+
+            return error_node();
+         }
+
+         for ( ; ; )
+         {
+            expression_node_ptr arg = parse_expression();
+
+            if (0 == arg)
+               return error_node();
+            else
+               arg_list.push_back(arg);
+
+            if (token_is(token_t::e_rbracket))
+               break;
+            else if (!token_is(token_t::e_comma))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR088 - Expected ',' for call to vararg function: " + symbol));
+
+               return error_node();
+            }
+         }
+
+         result = expression_generator_.vararg_function(opt_type,arg_list);
+
+         sdd.delete_ptr = (0 == result);
+         return result;
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression)
+      {
+         if (!token_is(token_t::e_lsqrbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR089 - Expected '[' as start of string range definition"));
+
+            free_node(node_allocator_,expression);
+
+            return error_node();
+         }
+         else if (token_is(token_t::e_rsqrbracket))
+         {
+            return node_allocator_.allocate<details::string_size_node<T> >(expression);
+         }
+
+         range_t rp;
+
+         if (!parse_range(rp,true))
+         {
+            free_node(node_allocator_,expression);
+
+            return error_node();
+         }
+
+         expression_node_ptr result = expression_generator_(expression,rp);
+
+         if (0 == result)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR090 - Failed to generate string range node"));
+
+            free_node(node_allocator_,expression);
+         }
+
+         rp.clear();
+
+         return result;
+      }
+      #else
+      inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
+      {
+         return error_node();
+      }
+      #endif
+
+      inline void parse_pending_string_rangesize(expression_node_ptr& expression)
+      {
+         // Allow no more than 100 range calls, eg: s[][][]...[][]
+         const std::size_t max_rangesize_parses = 100;
+
+         std::size_t i = 0;
+
+         while
+            (
+              (0 != expression)                      &&
+              (i++ < max_rangesize_parses)           &&
+              error_list_.empty()                    &&
+              token_is(token_t::e_lsqrbracket,false) &&
+              is_generally_string_node(expression)
+            )
+         {
+            expression = parse_string_range_statement(expression);
+         }
+      }
+
+      template <typename Allocator1,
+                typename Allocator2,
+                template <typename,typename> class Sequence>
+      inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
+                                          Sequence<bool,Allocator2>& side_effect_list)
+      {
+         if (expression_list.empty())
+            return error_node();
+         else if (1 == expression_list.size())
+            return expression_list[0];
+
+         Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
+
+         bool return_node_present = false;
+
+         for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
+         {
+            if (is_variable_node(expression_list[i]))
+               continue;
+            else if (
+                      is_return_node  (expression_list[i]) ||
+                      is_break_node   (expression_list[i]) ||
+                      is_continue_node(expression_list[i])
+                    )
+            {
+               tmp_expression_list.push_back(expression_list[i]);
+
+               // Remove all subexpressions after first short-circuit
+               // node has been encountered.
+
+               for (std::size_t j = i + 1; j < expression_list.size(); ++j)
+               {
+                  free_node(node_allocator_,expression_list[j]);
+               }
+
+               return_node_present = true;
+
+               break;
+            }
+            else if (
+                      is_constant_node(expression_list[i]) ||
+                      is_null_node    (expression_list[i]) ||
+                      !side_effect_list[i]
+                    )
+            {
+               free_node(node_allocator_,expression_list[i]);
+               continue;
+            }
+            else
+               tmp_expression_list.push_back(expression_list[i]);
+         }
+
+         if (!return_node_present)
+         {
+            tmp_expression_list.push_back(expression_list.back());
+         }
+
+         expression_list.swap(tmp_expression_list);
+
+         if (tmp_expression_list.size() > expression_list.size())
+         {
+            exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
+                          static_cast<int>(tmp_expression_list.size()),
+                          static_cast<int>(expression_list    .size())));
+         }
+
+         if (
+              return_node_present          ||
+              side_effect_list.back()      ||
+              (expression_list.size() > 1)
+            )
+            state_.activate_side_effect("simplify()");
+
+         if (1 == expression_list.size())
+            return expression_list[0];
+         else
+            return expression_generator_.vararg_function(details::e_multi,expression_list);
+      }
+
+      inline expression_node_ptr parse_multi_sequence(const std::string& source = "")
+      {
+         token_t::token_type close_bracket = token_t::e_rcrlbracket;
+         token_t::token_type seperator     = token_t::e_eof;
+
+         if (!token_is(token_t::e_lcrlbracket))
+         {
+            if (token_is(token_t::e_lbracket))
+            {
+               close_bracket = token_t::e_rbracket;
+               seperator     = token_t::e_comma;
+            }
+            else
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR091 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
+                             ((!source.empty()) ? std::string(" section of " + source): "")));
+
+               return error_node();
+            }
+         }
+         else if (token_is(token_t::e_rcrlbracket))
+         {
+            return node_allocator_.allocate<details::null_node<T> >();
+         }
+
+         std::vector<expression_node_ptr> arg_list;
+         std::vector<bool> side_effect_list;
+
+         expression_node_ptr result = error_node();
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         scope_handler sh(*this);
+
+         scoped_bool_or_restorer sbr(state_.side_effect_present);
+
+         for ( ; ; )
+         {
+            state_.side_effect_present = false;
+
+            expression_node_ptr arg = parse_expression();
+
+            if (0 == arg)
+               return error_node();
+            else
+            {
+               arg_list.push_back(arg);
+               side_effect_list.push_back(state_.side_effect_present);
+            }
+
+            if (token_is(close_bracket))
+               break;
+
+            bool is_next_close = peek_token_is(close_bracket);
+
+            if (!token_is(seperator) && is_next_close)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR092 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source));
+
+               return error_node();
+            }
+
+            if (token_is(close_bracket))
+               break;
+         }
+
+         result = simplify(arg_list,side_effect_list);
+
+         sdd.delete_ptr = (0 == result);
+         return result;
+      }
+
+      inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
+      {
+         // Examples of valid ranges:
+         // 1. [1:5]     -> 1..5
+         // 2. [ :5]     -> 0..5
+         // 3. [1: ]     -> 1..end
+         // 4. [x:y]     -> x..y where x <= y
+         // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
+         // 6. [ :y]     -> 0..y where 0 <= y
+         // 7. [x: ]     -> x..end where x <= end
+
+         rp.clear();
+
+         if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR093 - Expected '[' for start of range"));
+
+            return false;
+         }
+
+         if (token_is(token_t::e_colon))
+         {
+            rp.n0_c.first  = true;
+            rp.n0_c.second = 0;
+            rp.cache.first = 0;
+         }
+         else
+         {
+            expression_node_ptr r0 = parse_expression();
+
+            if (0 == r0)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR094 - Failed parse begin section of range"));
+
+               return false;
+
+            }
+            else if (is_constant_node(r0))
+            {
+               T r0_value = r0->value();
+
+               if (r0_value >= T(0))
+               {
+                  rp.n0_c.first  = true;
+                  rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
+                  rp.cache.first = rp.n0_c.second;
+               }
+
+               free_node(node_allocator_,r0);
+
+               if (r0_value < T(0))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR095 - Range lower bound less than zero! Constraint: r0 >= 0"));
+
+                  return false;
+               }
+            }
+            else
+            {
+               rp.n0_e.first  = true;
+               rp.n0_e.second = r0;
+            }
+
+            if (!token_is(token_t::e_colon))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR096 - Expected ':' for break  in range"));
+
+               rp.free();
+               return false;
+            }
+         }
+
+         if (token_is(token_t::e_rsqrbracket))
+         {
+            rp.n1_c.first  = true;
+            rp.n1_c.second = std::numeric_limits<std::size_t>::max();
+         }
+         else
+         {
+            expression_node_ptr r1 = parse_expression();
+
+            if (0 == r1)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR097 - Failed parse end section of range"));
+
+               rp.free();
+               return false;
+
+            }
+            else if (is_constant_node(r1))
+            {
+               T r1_value = r1->value();
+
+               if (r1_value >= T(0))
+               {
+                  rp.n1_c.first   = true;
+                  rp.n1_c.second  = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
+                  rp.cache.second = rp.n1_c.second;
+               }
+
+               free_node(node_allocator_,r1);
+
+               if (r1_value < T(0))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR098 - Range upper bound less than zero! Constraint: r1 >= 0"));
+
+                  return false;
+               }
+            }
+            else
+            {
+               rp.n1_e.first  = true;
+               rp.n1_e.second = r1;
+            }
+
+            if (!token_is(token_t::e_rsqrbracket))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR099 - Expected ']' for start of range"));
+
+               rp.free();
+               return false;
+            }
+         }
+
+         if (rp.const_range())
+         {
+            std::size_t r0 = 0;
+            std::size_t r1 = 0;
+
+            bool rp_result = rp(r0,r1);
+
+            if (!rp_result || (r0 > r1))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR100 - Invalid range, Constraint: r0 <= r1"));
+
+               return false;
+            }
+         }
+
+         return true;
+      }
+
+      inline void lodge_symbol(const std::string& symbol,
+                               const symbol_type st)
+      {
+         dec_.add_symbol(symbol,st);
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline expression_node_ptr parse_string()
+      {
+         const std::string symbol = current_token().value;
+
+         if (!symtab_store_.is_conststr_stringvar(symbol))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR101 - Unknown string symbol"));
+
+            return error_node();
+         }
+
+         expression_node_ptr result = symtab_store_.get_stringvar(symbol);
+
+         typedef details::stringvar_node<T>* strvar_node_t;
+         strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
+
+         const bool is_const_string = symtab_store_.is_constant_string(symbol);
+
+         if (is_const_string)
+         {
+            const_str_node = static_cast<strvar_node_t>(result);
+            result = expression_generator_(const_str_node->str());
+         }
+
+         lodge_symbol(symbol,e_st_string);
+
+         if (peek_token_is(token_t::e_lsqrbracket))
+         {
+            next_token();
+
+            if (peek_token_is(token_t::e_rsqrbracket))
+            {
+               next_token();
+               next_token();
+
+               if (const_str_node)
+               {
+                  free_node(node_allocator_,result);
+
+                  return expression_generator_(T(const_str_node->size()));
+               }
+               else
+                  return node_allocator_.allocate<details::stringvar_size_node<T> >
+                            (static_cast<details::stringvar_node<T>*>(result)->ref());
+            }
+
+            range_t rp;
+
+            if (!parse_range(rp))
+            {
+               free_node(node_allocator_,result);
+
+               return error_node();
+            }
+            else if (const_str_node)
+            {
+               free_node(node_allocator_,result);
+               result = expression_generator_(const_str_node->ref(),rp);
+            }
+            else
+               result = expression_generator_(static_cast<details::stringvar_node<T>*>(result)->ref(),rp);
+
+            if (result)
+               rp.clear();
+         }
+         else
+            next_token();
+
+         return result;
+      }
+      #else
+      inline expression_node_ptr parse_string()
+      {
+         return error_node();
+      }
+      #endif
+
+      #ifndef exprtk_disable_string_capabilities
+      inline expression_node_ptr parse_const_string()
+      {
+         const std::string const_str = current_token().value;
+         expression_node_ptr result = expression_generator_(const_str);
+
+         if (peek_token_is(token_t::e_lsqrbracket))
+         {
+            next_token();
+
+            if (peek_token_is(token_t::e_rsqrbracket))
+            {
+               next_token();
+               next_token();
+
+               free_node(node_allocator_,result);
+
+               return expression_generator_(T(const_str.size()));
+            }
+
+            range_t rp;
+
+            if (!parse_range(rp))
+            {
+               free_node(node_allocator_,result);
+
+               return error_node();
+            }
+
+            free_node(node_allocator_,result);
+
+            if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
+            {
+               rp.n1_c.second  = const_str.size() - 1;
+               rp.cache.second = rp.n1_c.second;
+            }
+
+            if (
+                 (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
+                 (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
+               )
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR102 - Overflow in range for string: '" + const_str + "'[" +
+                             (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
+                             (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]"));
+
+               return error_node();
+            }
+
+            result = expression_generator_(const_str,rp);
+
+            if (result)
+               rp.clear();
+         }
+         else
+            next_token();
+
+         return result;
+      }
+      #else
+      inline expression_node_ptr parse_const_string()
+      {
+         return error_node();
+      }
+      #endif
+
+      inline expression_node_ptr parse_vector()
+      {
+         const std::string symbol = current_token().value;
+
+         vector_holder_ptr vec = vector_holder_ptr(0);
+
+         const scope_element& se = sem_.get_active_element(symbol);
+
+         if (
+              (se.name != symbol)             ||
+              (se.depth > state_.scope_depth) ||
+              (scope_element::e_vector != se.type)
+            )
+         {
+            if (0 == (vec = symtab_store_.get_vector(symbol)))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR103 - Symbol '" + symbol+ " not a vector"));
+
+               return error_node();
+            }
+         }
+         else
+            vec = se.vec_node;
+
+         expression_node_ptr index_expr = error_node();
+
+         next_token();
+
+         if (!token_is(token_t::e_lsqrbracket))
+         {
+            return node_allocator_.allocate<vector_node_t>(vec);
+         }
+         else if (token_is(token_t::e_rsqrbracket))
+         {
+            return expression_generator_(T(vec->size()));
+         }
+         else if (0 == (index_expr = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR104 - Failed to parse index for vector: '" + symbol + "'"));
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_rsqrbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR105 - Expected ']' for index of vector: '" + symbol + "'"));
+
+            free_node(node_allocator_,index_expr);
+
+            return error_node();
+         }
+
+         return expression_generator_.vector_element(symbol,vec,index_expr);
+      }
+
+      inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
+      {
+         std::vector<expression_node_ptr> arg_list;
+         expression_node_ptr result = error_node();
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         next_token();
+
+         if (token_is(token_t::e_lbracket))
+         {
+            if (token_is(token_t::e_rbracket))
+            {
+               if (!vararg_function->allow_zero_parameters())
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR106 - Zero parameter call to vararg function: "
+                                + vararg_function_name + " not allowed"));
+
+                  return error_node();
+               }
+            }
+            else
+            {
+               for ( ; ; )
+               {
+                  expression_node_ptr arg = parse_expression();
+
+                  if (0 == arg)
+                     return error_node();
+                  else
+                     arg_list.push_back(arg);
+
+                  if (token_is(token_t::e_rbracket))
+                     break;
+                  else if (!token_is(token_t::e_comma))
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR107 - Expected ',' for call to vararg function: "
+                                   + vararg_function_name));
+
+                     return error_node();
+                  }
+               }
+            }
+         }
+         else if (!vararg_function->allow_zero_parameters())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR108 - Zero parameter call to vararg function: "
+                          + vararg_function_name + " not allowed"));
+
+            return error_node();
+         }
+
+         if (arg_list.size() < vararg_function->min_num_args())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR109 - Invalid number of parameters to call to vararg function: "
+                          + vararg_function_name + ", require at least "
+                          + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters"));
+
+            return error_node();
+         }
+         else if (arg_list.size() > vararg_function->max_num_args())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR110 - Invalid number of parameters to call to vararg function: "
+                          + vararg_function_name + ", require no more than "
+                          + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters"));
+
+            return error_node();
+         }
+
+         result = expression_generator_.vararg_function_call(vararg_function,arg_list);
+
+         sdd.delete_ptr = (0 == result);
+
+         return result;
+      }
+
+      class type_checker
+      {
+      public:
+
+         typedef parser<T> parser_t;
+         typedef std::vector<std::string> param_seq_list_t;
+
+         type_checker(parser_t& p,
+                      const std::string& func_name,
+                      const std::string& param_seq)
+         : invalid_state_(true),
+           parser_(p),
+           function_name_(func_name)
+         {
+            split(param_seq);
+         }
+
+         bool verify(const std::string& param_seq, std::size_t& pseq_index)
+         {
+            if (param_seq_list_.empty())
+               return true;
+
+            std::vector<std::pair<std::size_t,char> > error_list;
+
+            for (std::size_t i = 0; i < param_seq_list_.size(); ++i)
+            {
+               std::size_t diff_index = 0;
+               char        diff_value = 0;
+
+               bool result = details::sequence_match(param_seq_list_[i],
+                                                     param_seq,
+                                                     diff_index,diff_value);
+
+              if (result)
+              {
+                 pseq_index = i;
+                 return true;
+              }
+              else
+                 error_list.push_back(std::make_pair(diff_index,diff_value));
+            }
+
+            if (1 == error_list.size())
+            {
+               parser_.
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                parser_.current_token(),
+                                "ERR111 - Failed parameter type check for function '" + function_name_ + "', "
+                                "Expected '" + param_seq_list_[0] + "'  call set: '" + param_seq +"'"));
+            }
+            else
+            {
+               // find first with largest diff_index;
+               std::size_t max_diff_index = 0;
+
+               for (std::size_t i = 1; i < error_list.size(); ++i)
+               {
+                  if (error_list[i].first > error_list[max_diff_index].first)
+                  {
+                     max_diff_index = i;
+                  }
+               }
+
+               parser_.
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                parser_.current_token(),
+                                "ERR112 - Failed parameter type check for function '" + function_name_ + "', "
+                                "Best match: '" + param_seq_list_[max_diff_index] + "'  call set: '" + param_seq +"'"));
+            }
+
+            return false;
+         }
+
+         std::size_t paramseq_count() const
+         {
+            return param_seq_list_.size();
+         }
+
+         std::string paramseq(const std::size_t& index) const
+         {
+            return param_seq_list_[index];
+         }
+
+         bool invalid() const
+         {
+            return !invalid_state_;
+         }
+
+      private:
+
+         void split(const std::string& s)
+         {
+            if (s.empty())
+               return;
+
+            std::size_t start = 0;
+            std::size_t end   = 0;
+
+            param_seq_list_t param_seq_list;
+
+            struct token_validator
+            {
+               static inline bool process(const std::string& str,
+                                          std::size_t s, std::size_t e,
+                                          param_seq_list_t& psl)
+               {
+                  if (
+                       (e - s) &&
+                       (std::string::npos == str.find("?*")) &&
+                       (std::string::npos == str.find("**"))
+                     )
+                  {
+                     const std::string curr_str = str.substr(s,e - s);
+
+                     if (std::string::npos == curr_str.find_first_not_of("STV*?|"))
+                     {
+                        psl.push_back(curr_str);
+                        return true;
+                     }
+                  }
+
+                  return false;
+               }
+            };
+
+            while (std::string::npos != (end = s.find('|',start)))
+            {
+               if (!token_validator::process(s,start,end,param_seq_list))
+               {
+                  invalid_state_ = false;
+
+                  const std::string err_param_seq =  s.substr(start,end - start);
+
+                  parser_.
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   parser_.current_token(),
+                                   "ERR113 - Invalid parameter sequence of '" + err_param_seq +
+                                   "'  for function: " + function_name_));
+
+                  return;
+               }
+               else
+                  start = end + 1;
+            }
+
+            if (start < s.size())
+            {
+               if (token_validator::process(s,start,s.size(),param_seq_list))
+                  param_seq_list_ = param_seq_list;
+               else
+               {
+                  const std::string err_param_seq =  s.substr(start,s.size() - start);
+
+                  parser_.
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   parser_.current_token(),
+                                   "ERR114 - Invalid parameter sequence of '" + err_param_seq +
+                                   "'  for function: " + function_name_));
+                  return;
+               }
+            }
+         }
+
+         type_checker(const type_checker&);
+         type_checker& operator=(const type_checker&);
+
+         bool invalid_state_;
+         parser_t& parser_;
+         std::string function_name_;
+         param_seq_list_t param_seq_list_;
+      };
+
+      inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name)
+      {
+         std::vector<expression_node_ptr> arg_list;
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         next_token();
+
+         std::string param_type_list;
+
+         type_checker tc(*this,function_name,function->parameter_sequence);
+
+         if (tc.invalid())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR115 - Type checker instantiation failure for generic function: " + function_name));
+
+            return error_node();
+         }
+
+         if (token_is(token_t::e_lbracket))
+         {
+            if (token_is(token_t::e_rbracket))
+            {
+               if (!function->allow_zero_parameters())
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR116 - Zero parameter call to generic function: "
+                                + function_name + " not allowed"));
+
+                  return error_node();
+               }
+            }
+            else
+            {
+               for ( ; ; )
+               {
+                  expression_node_ptr arg = parse_expression();
+
+                  if (0 == arg)
+                     return error_node();
+
+                  if (is_ivector_node(arg))
+                     param_type_list += 'V';
+                  else if (is_generally_string_node(arg))
+                     param_type_list += 'S';
+                  else // Everything else is assumed to be a scalar returning expression
+                     param_type_list += 'T';
+
+                  arg_list.push_back(arg);
+
+                  if (token_is(token_t::e_rbracket))
+                     break;
+                  else if (!token_is(token_t::e_comma))
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR117 - Expected ',' for call to generic function: " + function_name));
+
+                     return error_node();
+                  }
+               }
+            }
+         }
+         else if (!function->allow_zero_parameters())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR118 - Zero parameter call to generic function: "
+                          + function_name + " not allowed"));
+
+            return error_node();
+         }
+
+         std::size_t param_seq_index = 0;
+
+         if (!tc.verify(param_type_list, param_seq_index))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR119 - Expected ',' for call to generic function: " + function_name));
+
+            return error_node();
+         }
+
+         expression_node_ptr result = error_node();
+
+         if (tc.paramseq_count() <= 1)
+            result = expression_generator_
+                       .generic_function_call(function,arg_list);
+         else
+            result = expression_generator_
+                       .generic_function_call(function,arg_list,param_seq_index);
+
+         sdd.delete_ptr = (0 == result);
+
+         return result;
+      }
+
+      inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name)
+      {
+         std::vector<expression_node_ptr> arg_list;
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         next_token();
+
+         std::string param_type_list;
+
+         type_checker tc(*this,function_name,function->parameter_sequence);
+
+         if (
+              (!function->parameter_sequence.empty()) &&
+              (0 == tc.paramseq_count())
+            )
+         {
+            return error_node();
+         }
+
+         if (token_is(token_t::e_lbracket))
+         {
+            if (!token_is(token_t::e_rbracket))
+            {
+               for ( ; ; )
+               {
+                  expression_node_ptr arg = parse_expression();
+
+                  if (0 == arg)
+                     return error_node();
+
+                  if (is_ivector_node(arg))
+                     param_type_list += 'V';
+                  else if (is_generally_string_node(arg))
+                     param_type_list += 'S';
+                  else // Everything else is a scalar returning expression
+                     param_type_list += 'T';
+
+                  arg_list.push_back(arg);
+
+                  if (token_is(token_t::e_rbracket))
+                     break;
+                  else if (!token_is(token_t::e_comma))
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR120 - Expected ',' for call to string function: " + function_name));
+
+                     return error_node();
+                  }
+               }
+            }
+         }
+
+         std::size_t param_seq_index = 0;
+
+         if (!tc.verify(param_type_list, param_seq_index))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR121 - Expected ',' for call to string function: " + function_name));
+
+            return error_node();
+         }
+
+         expression_node_ptr result = error_node();
+
+         if (tc.paramseq_count() <= 1)
+            result = expression_generator_
+                       .string_function_call(function,arg_list);
+         else
+            result = expression_generator_
+                       .string_function_call(function,arg_list,param_seq_index);
+
+         sdd.delete_ptr = (0 == result);
+
+         return result;
+      }
+
+      template <typename Type, std::size_t NumberOfParameters>
+      struct parse_special_function_impl
+      {
+         static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type)
+         {
+            expression_node_ptr branch[NumberOfParameters];
+            expression_node_ptr result  = error_node();
+            std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
+            scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch);
+
+            p.next_token();
+
+            if (!p.token_is(token_t::e_lbracket))
+            {
+               p.set_error(
+                    make_error(parser_error::e_syntax,
+                               p.current_token(),
+                               "ERR122 - Expected '(' for special function"));
+
+               return error_node();
+            }
+
+            for (std::size_t i = 0; i < NumberOfParameters; ++i)
+            {
+               branch[i] = p.parse_expression();
+
+               if (0 == branch[i])
+               {
+                  return p.error_node();
+               }
+               else if (i < (NumberOfParameters - 1))
+               {
+                  if (!p.token_is(token_t::e_comma))
+                  {
+                     p.set_error(
+                          make_error(parser_error::e_syntax,
+                                     p.current_token(),
+                                     "ERR123 - Expected ',' before next parameter of special function"));
+
+                     return p.error_node();
+                  }
+               }
+            }
+
+            if (!p.token_is(token_t::e_rbracket))
+               return p.error_node();
+            else
+               result = p.expression_generator_.special_function(opt_type,branch);
+
+            sd.delete_ptr = (0 == result);
+
+            return result;
+         }
+      };
+
+      inline expression_node_ptr parse_special_function()
+      {
+         // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
+         if (
+              !details::is_digit(current_token().value[2]) ||
+              !details::is_digit(current_token().value[3])
+            )
+         {
+            set_error(
+               make_error(parser_error::e_token,
+                          current_token(),
+                          "ERR124 - Invalid special function[1]: " + current_token().value));
+
+            return error_node();
+         }
+
+         const unsigned int id = (current_token().value[2] - '0') * 10 + (current_token().value[3] - '0');
+
+         if (id >= details::e_sffinal)
+         {
+            set_error(
+               make_error(parser_error::e_token,
+                          current_token(),
+                          "ERR125 - Invalid special function[2]: " + current_token().value));
+
+            return error_node();
+         }
+
+         const std::size_t sf_3_to_4 = details::e_sf48;
+         const details::operator_type opt_type = details::operator_type(id + 1000);
+         const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3 : 4;
+
+         switch (NumberOfParameters)
+         {
+            case 3  : return parse_special_function_impl<T,3>::process(*this,opt_type);
+            case 4  : return parse_special_function_impl<T,4>::process(*this,opt_type);
+            default : return error_node();
+         }
+      }
+
+      inline expression_node_ptr parse_null_statement()
+      {
+         next_token();
+         return node_allocator_.allocate<details::null_node<T> >();
+      }
+
+      #ifndef exprtk_disable_break_continue
+      inline expression_node_ptr parse_break_statement()
+      {
+         if (state_.parsing_break_stmt)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR126 - Break call within a break call is not allowed"));
+
+            return error_node();
+         }
+
+         scoped_bool_negator sbn(state_.parsing_break_stmt);
+
+         if (!brkcnt_list_.empty())
+         {
+            next_token();
+
+            brkcnt_list_.front() = true;
+
+            expression_node_ptr return_expr = error_node();
+
+            if (token_is(token_t::e_lsqrbracket))
+            {
+               if (0 == (return_expr = parse_expression()))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR127 - Failed to parse return expression for 'break' statement"));
+
+                  return error_node();
+               }
+               else if (!token_is(token_t::e_rsqrbracket))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR128 - Expected ']' at the completion of break's return expression"));
+
+                  free_node(node_allocator_,return_expr);
+
+                  return error_node();
+               }
+            }
+
+            state_.activate_side_effect("parse_break_statement()");
+
+            return node_allocator_.allocate<details::break_node<T> >(return_expr);
+         }
+         else
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR129 - Invalid use of 'break', allowed only in the scope of a loop"));
+         }
+
+         return error_node();
+      }
+
+      inline expression_node_ptr parse_continue_statement()
+      {
+         if (!brkcnt_list_.empty())
+         {
+            next_token();
+
+            brkcnt_list_.front() = true;
+            state_.activate_side_effect("parse_continue_statement()");
+
+            return node_allocator_.allocate<details::continue_node<T> >();
+         }
+         else
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR130 - Invalid use of 'continue', allowed only in the scope of a loop"));
+
+            return error_node();
+         }
+      }
+      #endif
+
+      inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name)
+      {
+         expression_node_ptr size_expr = error_node();
+
+         if (!token_is(token_t::e_lsqrbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR131 - Expected '[' as part of vector size definition"));
+
+            return error_node();
+         }
+         else if (0 == (size_expr = parse_expression()))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR132 - Failed to determine size of vector '" + vec_name + "'"));
+
+            return error_node();
+         }
+         else if (!is_constant_node(size_expr))
+         {
+            free_node(node_allocator_,size_expr);
+
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR133 - Expected a literal number as size of vector '" + vec_name + "'"));
+
+            return error_node();
+         }
+
+         T vector_size = size_expr->value();
+
+         free_node(node_allocator_,size_expr);
+
+         if (
+              (vector_size <= T(0)) ||
+              std::not_equal_to<T>()
+              (T(0),vector_size - details::numeric::trunc(vector_size))
+            )
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR134 - Invalid vector size. Must be an integer greater than zero, size: " +
+                          details::to_str(details::numeric::to_int32(vector_size))));
+
+            return error_node();
+         }
+
+         std::vector<expression_node_ptr> vec_initilizer_list;
+
+         scoped_vec_delete<expression_node_t> svd(*this,vec_initilizer_list);
+
+         bool single_value_initialiser = false;
+
+         if (!token_is(token_t::e_rsqrbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR135 - Expected ']' as part of vector size definition"));
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_eof))
+         {
+            if (!token_is(token_t::e_assign))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR136 - Expected ':=' as part of vector definition"));
+
+               return error_node();
+            }
+            else if (token_is(token_t::e_lsqrbracket))
+            {
+               expression_node_ptr initialiser = parse_expression();
+
+               if (0 == initialiser)
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR137 - Failed to parse single vector initialiser"));
+
+                  return error_node();
+               }
+
+               vec_initilizer_list.push_back(initialiser);
+
+               if (!token_is(token_t::e_rsqrbracket))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR138 - Expected ']' to close single value vector initialiser"));
+
+                  return error_node();
+               }
+
+               single_value_initialiser = true;
+            }
+            else if (!token_is(token_t::e_lcrlbracket))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR139 - Expected '{' as part of vector initialiser list"));
+
+               return error_node();
+            }
+            else if (!token_is(token_t::e_rcrlbracket))
+            {
+               for ( ; ; )
+               {
+                  expression_node_ptr initialiser = parse_expression();
+
+                  if (0 == initialiser)
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR140 - Expected '{' as part of vector initialiser list"));
+
+                     return error_node();
+                  }
+                  else
+                     vec_initilizer_list.push_back(initialiser);
+
+                  if (token_is(token_t::e_rcrlbracket))
+                     break;
+
+                  bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
+
+                  if (!token_is(token_t::e_comma) && is_next_close)
+                  {
+                     set_error(
+                        make_error(parser_error::e_syntax,
+                                   current_token(),
+                                   "ERR141 - Expected ',' between vector initialisers"));
+
+                     return error_node();
+                  }
+
+                  if (token_is(token_t::e_rcrlbracket))
+                     break;
+               }
+            }
+
+            if (
+                 !token_is(token_t::e_rbracket   ,false) &&
+                 !token_is(token_t::e_rcrlbracket,false) &&
+                 !token_is(token_t::e_rsqrbracket,false)
+               )
+            {
+               if (!token_is(token_t::e_eof))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR142 - Expected ';' at end of vector definition"));
+
+                  return error_node();
+               }
+            }
+
+            if (vec_initilizer_list.size() > vector_size)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR143 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'"));
+
+               return error_node();
+            }
+         }
+
+         typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
+
+         std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
+
+         scope_element& se = sem_.get_element(vec_name);
+
+         if (se.name == vec_name)
+         {
+            if (se.active)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR144 - Illegal redefinition of local vector: '" + vec_name + "'"));
+
+               return error_node();
+            }
+            else if (
+                      (se.size == vec_size) &&
+                      (scope_element::e_vector == se.type)
+                    )
+            {
+               vec_holder = se.vec_node;
+               se.active  = true;
+               se.depth   = state_.scope_depth;
+               se.ref_count++;
+            }
+         }
+
+         if (0 == vec_holder)
+         {
+            scope_element nse;
+            nse.name      = vec_name;
+            nse.active    = true;
+            nse.ref_count = 1;
+            nse.type      = scope_element::e_vector;
+            nse.depth     = state_.scope_depth;
+            nse.size      = vec_size;
+            nse.data      = new T[vec_size];
+            nse.vec_node  = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
+
+            if (!sem_.add_element(nse))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR145 - Failed to add new local vector '" + vec_name + "' to SEM"));
+
+               sem_.free_element(nse);
+
+               return error_node();
+            }
+
+            vec_holder = nse.vec_node;
+
+            exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
+                          nse.name.c_str(),
+                          static_cast<int>(nse.size)));
+         }
+
+         state_.activate_side_effect("parse_define_vector_statement()");
+
+         lodge_symbol(vec_name,e_st_local_vector);
+
+         expression_node_ptr result =
+                node_allocator_
+                   .allocate<details::vector_assignment_node<T> >(
+                      (*vec_holder)[0],
+                      vec_size,
+                      vec_initilizer_list,
+                      single_value_initialiser);
+
+         svd.delete_ptr = (0 == result);
+
+         return result;
+      }
+
+      #ifndef exprtk_disable_string_capabilities
+      inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
+      {
+         stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
+
+         scope_element& se = sem_.get_element(str_name);
+
+         if (se.name == str_name)
+         {
+            if (se.active)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR146 - Illegal redefinition of local variable: '" + str_name + "'"));
+
+               free_node(node_allocator_,initialisation_expression);
+
+               return error_node();
+            }
+            else if (scope_element::e_string == se.type)
+            {
+               str_node  = se.str_node;
+               se.active = true;
+               se.depth  = state_.scope_depth;
+               se.ref_count++;
+            }
+         }
+
+         if (0 == str_node)
+         {
+            scope_element nse;
+            nse.name      = str_name;
+            nse.active    = true;
+            nse.ref_count = 1;
+            nse.type      = scope_element::e_string;
+            nse.depth     = state_.scope_depth;
+            nse.data      = new std::string;
+            nse.str_node  = new stringvar_node_t(*(std::string*)(nse.data));
+
+            if (!sem_.add_element(nse))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR147 - Failed to add new local string variable '" + str_name + "' to SEM"));
+
+               free_node(node_allocator_,initialisation_expression);
+
+               sem_.free_element(nse);
+
+               return error_node();
+            }
+
+            str_node = nse.str_node;
+
+            exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
+         }
+
+         lodge_symbol(str_name,e_st_local_string);
+
+         state_.activate_side_effect("parse_define_string_statement()");
+
+         expression_node_ptr branch[2] = {0};
+
+         branch[0] = str_node;
+         branch[1] = initialisation_expression;
+
+         return expression_generator_(details::e_assign,branch);
+      }
+      #else
+      inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
+      {
+         return error_node();
+      }
+      #endif
+
+      inline bool local_variable_is_shadowed(const std::string& symbol)
+      {
+         const scope_element& se = sem_.get_element(symbol);
+         return (se.name == symbol) && se.active;
+      }
+
+      inline expression_node_ptr parse_define_var_statement()
+      {
+         if (settings_.vardef_disabled())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR148 - Illegal variable definition"));
+
+            return error_node();
+         }
+         else if (!details::imatch(current_token().value,"var"))
+         {
+            return error_node();
+         }
+         else
+            next_token();
+
+         const std::string var_name = current_token().value;
+
+         expression_node_ptr initialisation_expression = error_node();
+
+         if (!token_is(token_t::e_symbol))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR149 - Expected a symbol for variable definition"));
+
+            return error_node();
+         }
+         else if (details::is_reserved_symbol(var_name))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR150 - Illegal redefinition of reserved keyword: '" + var_name + "'"));
+
+            return error_node();
+         }
+         else if (symtab_store_.symbol_exists(var_name))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR151 - Illegal redefinition of variable '" + var_name + "'"));
+
+            return error_node();
+         }
+         else if (local_variable_is_shadowed(var_name))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR152 - Illegal redefinition of local variable: '" + var_name + "'"));
+
+            return error_node();
+         }
+         else if (token_is(token_t::e_lsqrbracket,false))
+         {
+            return parse_define_vector_statement(var_name);
+         }
+         else if (token_is(token_t::e_lcrlbracket,false))
+         {
+            return parse_uninitialised_var_statement(var_name);
+         }
+         else if (token_is(token_t::e_assign))
+         {
+            if (0 == (initialisation_expression = parse_expression()))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR153 - Failed to parse initialisation expression"));
+
+               return error_node();
+            }
+         }
+
+         if (
+              !token_is(token_t::e_rbracket   ,false) &&
+              !token_is(token_t::e_rcrlbracket,false) &&
+              !token_is(token_t::e_rsqrbracket,false)
+            )
+         {
+            if (!token_is(token_t::e_eof,false))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR154 - Expected ';' after variable definition"));
+
+               free_node(node_allocator_,initialisation_expression);
+
+               return error_node();
+            }
+         }
+
+         if (
+              (0 != initialisation_expression) &&
+              details::is_generally_string_node(initialisation_expression)
+            )
+         {
+            return parse_define_string_statement(var_name,initialisation_expression);
+         }
+
+         variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0);
+
+         scope_element& se = sem_.get_element(var_name);
+
+         if (se.name == var_name)
+         {
+            if (se.active)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR155 - Illegal redefinition of local variable: '" + var_name + "'"));
+
+               free_node(node_allocator_,initialisation_expression);
+
+               return error_node();
+            }
+            else if (scope_element::e_variable == se.type)
+            {
+               var_node  = se.var_node;
+               se.active = true;
+               se.depth  = state_.scope_depth;
+               se.ref_count++;
+            }
+         }
+
+         if (0 == var_node)
+         {
+            scope_element nse;
+            nse.name      = var_name;
+            nse.active    = true;
+            nse.ref_count = 1;
+            nse.type      = scope_element::e_variable;
+            nse.depth     = state_.scope_depth;
+            nse.data      = new T(T(0));
+            nse.var_node  = new variable_node_t(*(T*)(nse.data));
+
+            if (!sem_.add_element(nse))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR156 - Failed to add new local variable '" + var_name + "' to SEM"));
+
+               free_node(node_allocator_,initialisation_expression);
+
+               sem_.free_element(nse);
+
+               return error_node();
+            }
+
+            var_node = nse.var_node;
+
+            exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
+         }
+
+         state_.activate_side_effect("parse_define_var_statement()");
+
+         lodge_symbol(var_name,e_st_local_variable);
+
+         expression_node_ptr branch[2] = {0};
+
+         branch[0] = var_node;
+         branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
+
+         return expression_generator_(details::e_assign,branch);
+      }
+
+      inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name)
+      {
+         if (
+              !token_is(token_t::e_lcrlbracket) ||
+              !token_is(token_t::e_rcrlbracket)
+            )
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR157 - Expected a '{}' for uninitialised var definition"));
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_eof,false))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR158 - Expected ';' after uninitialised variable definition"));
+
+            return error_node();
+         }
+
+         variable_node_t* var_node = reinterpret_cast<variable_node_t*>(0);
+
+         scope_element& se = sem_.get_element(var_name);
+
+         if (se.name == var_name)
+         {
+            if (se.active)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR159 - Illegal redefinition of local variable: '" + var_name + "'"));
+
+               return error_node();
+            }
+            else if (scope_element::e_variable == se.type)
+            {
+               var_node  = se.var_node;
+               se.active = true;
+               se.ref_count++;
+            }
+         }
+
+         if (0 == var_node)
+         {
+            scope_element nse;
+            nse.name      = var_name;
+            nse.active    = true;
+            nse.ref_count = 1;
+            nse.type      = scope_element::e_variable;
+            nse.depth     = state_.scope_depth;
+            nse.ip_index  = sem_.next_ip_index();
+            nse.data      = new T(T(0));
+            nse.var_node  = new variable_node_t(*(T*)(nse.data));
+
+            if (!sem_.add_element(nse))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR160 - Failed to add new local variable '" + var_name + "' to SEM"));
+
+               sem_.free_element(nse);
+
+               return error_node();
+            }
+
+            exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
+                          nse.name.c_str()));
+         }
+
+         lodge_symbol(var_name,e_st_local_variable);
+
+         state_.activate_side_effect("parse_uninitialised_var_statement()");
+
+         return expression_generator_(T(0));
+      }
+
+      inline expression_node_ptr parse_swap_statement()
+      {
+         if (!details::imatch(current_token().value,"swap"))
+         {
+            return error_node();
+         }
+         else
+            next_token();
+
+         if (!token_is(token_t::e_lbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR161 - Expected '(' at start of swap statement"));
+
+            return error_node();
+         }
+
+         expression_node_ptr variable0 = error_node();
+         expression_node_ptr variable1 = error_node();
+
+         bool variable0_generated = false;
+         bool variable1_generated = false;
+
+         const std::string var0_name = current_token().value;
+
+         if (!token_is(token_t::e_symbol,false))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR162 - Expected a symbol for variable or vector element definition"));
+
+            return error_node();
+         }
+         else if (peek_token_is(token_t::e_lsqrbracket))
+         {
+            if (0 == (variable0 = parse_vector()))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR163 - First parameter to swap is an invalid vector element: '" + var0_name + "'"));
+
+               return error_node();
+            }
+
+            variable0_generated = true;
+         }
+         else
+         {
+            if (symtab_store_.is_variable(var0_name))
+            {
+               variable0 = symtab_store_.get_variable(var0_name);
+            }
+
+            scope_element& se = sem_.get_element(var0_name);
+
+            if (
+                 (se.active)            &&
+                 (se.name == var0_name) &&
+                 (scope_element::e_variable == se.type)
+               )
+            {
+               variable0 = se.var_node;
+            }
+
+            lodge_symbol(var0_name,e_st_variable);
+
+            if (0 == variable0)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR164 - First parameter to swap is an invalid variable: '" + var0_name + "'"));
+
+               return error_node();
+            }
+            else
+               next_token();
+         }
+
+         if (!token_is(token_t::e_comma))
+         {
+            set_error(
+                make_error(parser_error::e_syntax,
+                           current_token(),
+                           "ERR165 - Expected ',' between parameters to swap"));
+
+            if (variable0_generated)
+            {
+               free_node(node_allocator_,variable0);
+            }
+
+            return error_node();
+         }
+
+         const std::string var1_name = current_token().value;
+
+         if (!token_is(token_t::e_symbol,false))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR166 - Expected a symbol for variable or vector element definition"));
+
+            if (variable0_generated)
+            {
+               free_node(node_allocator_,variable0);
+            }
+
+            return error_node();
+         }
+         else if (peek_token_is(token_t::e_lsqrbracket))
+         {
+            if (0 == (variable1 = parse_vector()))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR167 - Second parameter to swap is an invalid vector element: '" + var1_name + "'"));
+
+               if (variable0_generated)
+               {
+                  free_node(node_allocator_,variable0);
+               }
+
+               return error_node();
+            }
+
+            variable1_generated = true;
+         }
+         else
+         {
+            if (symtab_store_.is_variable(var1_name))
+            {
+               variable1 = symtab_store_.get_variable(var1_name);
+            }
+
+            scope_element& se = sem_.get_element(var1_name);
+
+            if (
+                 (se.active) &&
+                 (se.name == var1_name) &&
+                 (scope_element::e_variable == se.type)
+               )
+            {
+               variable1 = se.var_node;
+            }
+
+            lodge_symbol(var1_name,e_st_variable);
+
+            if (0 == variable1)
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR168 - Second parameter to swap is an invalid variable: '" + var1_name + "'"));
+
+               if (variable0_generated)
+               {
+                  free_node(node_allocator_,variable0);
+               }
+
+               return error_node();
+            }
+            else
+               next_token();
+         }
+
+         if (!token_is(token_t::e_rbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR169 - Expected ')' at end of swap statement"));
+
+            if (variable0_generated)
+            {
+               free_node(node_allocator_,variable0);
+            }
+
+            if (variable1_generated)
+            {
+               free_node(node_allocator_,variable1);
+            }
+
+            return error_node();
+         }
+
+         typedef details::variable_node<T>* variable_node_ptr;
+         variable_node_ptr v0 = variable_node_ptr(0);
+         variable_node_ptr v1 = variable_node_ptr(0);
+
+         expression_node_ptr result = error_node();
+
+         if (
+              (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
+              (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
+            )
+         {
+            result = node_allocator_.allocate<details::swap_node<T> >(v0,v1);
+
+            if (variable0_generated)
+            {
+               free_node(node_allocator_,variable0);
+            }
+
+            if (variable1_generated)
+            {
+               free_node(node_allocator_,variable1);
+            }
+         }
+         else
+            result = node_allocator_.allocate<details::swap_generic_node<T> >(variable0,variable1);
+
+         state_.activate_side_effect("parse_swap_statement()");
+
+         return result;
+      }
+
+      inline expression_node_ptr parse_return_statement()
+      {
+         if (state_.parsing_return_stmt)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR170 - Return call within a return call is not allowed"));
+
+            return error_node();
+         }
+
+         scoped_bool_negator sbn(state_.parsing_return_stmt);
+
+         std::vector<expression_node_ptr> arg_list;
+
+         scoped_vec_delete<expression_node_t> sdd(*this,arg_list);
+
+         if (!details::imatch(current_token().value,"return"))
+         {
+            return error_node();
+         }
+         else
+            next_token();
+
+         if (!token_is(token_t::e_lsqrbracket))
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR171 - Expected '[' at start of return statement"));
+
+            return error_node();
+         }
+         else if (!token_is(token_t::e_rsqrbracket))
+         {
+            for ( ; ; )
+            {
+               expression_node_ptr arg = parse_expression();
+
+               if (0 == arg)
+                  return error_node();
+
+               arg_list.push_back(arg);
+
+               if (token_is(token_t::e_rsqrbracket))
+                  break;
+               else if (!token_is(token_t::e_comma))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR172 - Expected ',' between values during call to return"));
+
+                  return error_node();
+               }
+            }
+         }
+         else if (settings_.zero_return_disabled())
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR173 - Zero parameter return statement not allowed"));
+
+            return error_node();
+         }
+
+         lexer::token prev_token = current_token();
+
+         if (token_is(token_t::e_rsqrbracket))
+         {
+            if (!arg_list.empty())
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             prev_token,
+                             "ERR174 - Invalid ']' found during return call"));
+
+               return error_node();
+            }
+         }
+
+         std::string ret_param_type_list;
+
+         for (std::size_t i = 0; i < arg_list.size(); ++i)
+         {
+            if (0 == arg_list[i])
+               return error_node();
+            else if (is_ivector_node(arg_list[i]))
+               ret_param_type_list += 'V';
+            else if (is_generally_string_node(arg_list[i]))
+               ret_param_type_list += 'S';
+            else
+               ret_param_type_list += 'T';
+         }
+
+         dec_.retparam_list_.push_back(ret_param_type_list);
+
+         expression_node_ptr result = expression_generator_.return_call(arg_list);
+
+         sdd.delete_ptr = (0 == result);
+
+         state_.return_stmt_present = true;
+
+         state_.activate_side_effect("parse_return_statement()");
+
+         return result;
+      }
+
+      inline bool post_variable_process(const std::string& symbol)
+      {
+         if (
+              peek_token_is(token_t::e_lbracket   ) ||
+              peek_token_is(token_t::e_lcrlbracket) ||
+              peek_token_is(token_t::e_lsqrbracket)
+            )
+         {
+            if (!settings_.commutative_check_enabled())
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR175 - Invalid sequence of variable '"+ symbol + "' and bracket"));
+
+               return false;
+            }
+
+            lexer().insert_front(token_t::e_mul);
+         }
+
+         return true;
+      }
+
+      inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch)
+      {
+         bool implied_mul = false;
+
+         if (is_generally_string_node(branch))
+            return true;
+
+         switch (token)
+         {
+            case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket   ,false) ||
+                                                        token_is(token_t::e_lcrlbracket,false) ||
+                                                        token_is(token_t::e_lsqrbracket,false) ;
+                                          break;
+
+            case token_t::e_lbracket    : implied_mul = token_is(token_t::e_lbracket   ,false) ||
+                                                        token_is(token_t::e_lcrlbracket,false) ||
+                                                        token_is(token_t::e_lsqrbracket,false) ;
+                                          break;
+
+            case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket   ,false) ||
+                                                        token_is(token_t::e_lcrlbracket,false) ||
+                                                        token_is(token_t::e_lsqrbracket,false) ;
+                                          break;
+
+            default                     : return true;
+         }
+
+         if (implied_mul)
+         {
+            if (!settings_.commutative_check_enabled())
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR176 - Invalid sequence of brackets"));
+
+               return false;
+            }
+            else if (token_t::e_eof != current_token().type)
+            {
+               lexer().insert_front(current_token().type);
+               lexer().insert_front(token_t::e_mul);
+               next_token();
+            }
+         }
+
+         return true;
+      }
+
+      inline expression_node_ptr parse_symtab_symbol()
+      {
+         const std::string symbol = current_token().value;
+
+         // Are we dealing with a variable or a special constant?
+         expression_node_ptr variable = symtab_store_.get_variable(symbol);
+
+         if (variable)
+         {
+            if (symtab_store_.is_constant_node(symbol))
+            {
+               variable = expression_generator_(variable->value());
+            }
+
+            if (!post_variable_process(symbol))
+               return error_node();
+
+            lodge_symbol(symbol,e_st_variable);
+            next_token();
+
+            return variable;
+         }
+
+         // Are we dealing with a locally defined variable, vector or string?
+         if (!sem_.empty())
+         {
+            scope_element& se = sem_.get_active_element(symbol);
+
+            if (se.active && (se.name == symbol))
+            {
+               if (scope_element::e_variable == se.type)
+               {
+                  se.active = true;
+                  lodge_symbol(symbol,e_st_local_variable);
+
+                  if (!post_variable_process(symbol))
+                     return error_node();
+
+                  next_token();
+
+                  return se.var_node;
+               }
+               else if (scope_element::e_vector == se.type)
+               {
+                  return parse_vector();
+               }
+               #ifndef exprtk_disable_string_capabilities
+               else if (scope_element::e_string == se.type)
+               {
+                  se.active = true;
+                  lodge_symbol(symbol,e_st_local_string);
+
+                  next_token();
+
+                  return se.str_node;
+               }
+               #endif
+            }
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         // Are we dealing with a string variable?
+         if (symtab_store_.is_stringvar(symbol))
+         {
+            return parse_string();
+         }
+         #endif
+
+         {
+            // Are we dealing with a function?
+            ifunction<T>* function = symtab_store_.get_function(symbol);
+
+            if (function)
+            {
+               lodge_symbol(symbol,e_st_function);
+
+               expression_node_ptr func_node =
+                                      parse_function_invocation(function,symbol);
+
+               if (func_node)
+                  return func_node;
+               else
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR177 - Failed to generate node for function: '" + symbol + "'"));
+
+                  return error_node();
+               }
+            }
+         }
+
+         {
+            // Are we dealing with a vararg function?
+            ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
+
+            if (vararg_function)
+            {
+               lodge_symbol(symbol,e_st_function);
+
+               expression_node_ptr vararg_func_node =
+                                      parse_vararg_function_call(vararg_function,symbol);
+
+               if (vararg_func_node)
+                  return vararg_func_node;
+               else
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR178 - Failed to generate node for vararg function: '" + symbol + "'"));
+
+                  return error_node();
+               }
+            }
+         }
+
+         {
+            // Are we dealing with a vararg generic function?
+            igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
+
+            if (generic_function)
+            {
+               lodge_symbol(symbol,e_st_function);
+
+               expression_node_ptr genericfunc_node =
+                                      parse_generic_function_call(generic_function,symbol);
+
+               if (genericfunc_node)
+                  return genericfunc_node;
+               else
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR179 - Failed to generate node for generic function: '" + symbol + "'"));
+
+                  return error_node();
+               }
+            }
+         }
+
+         {
+            // Are we dealing with a vararg string returning function?
+            igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
+
+            if (string_function)
+            {
+               lodge_symbol(symbol,e_st_function);
+
+               expression_node_ptr stringfunc_node =
+                                      parse_string_function_call(string_function,symbol);
+
+               if (stringfunc_node)
+                  return stringfunc_node;
+               else
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR180 - Failed to generate node for string function: '" + symbol + "'"));
+
+                  return error_node();
+               }
+            }
+         }
+
+         // Are we dealing with a vector element?
+         if (symtab_store_.is_vector(symbol))
+         {
+            lodge_symbol(symbol,e_st_vector);
+            return parse_vector();
+         }
+
+         if (details::is_reserved_symbol(symbol))
+         {
+               if (settings_.function_enabled(symbol) || !details::is_base_function(symbol))
+               {
+                  set_error(
+                     make_error(parser_error::e_syntax,
+                                current_token(),
+                                "ERR181 - Invalid use of reserved symbol '" + symbol + "'"));
+
+                  return error_node();
+               }
+         }
+
+         // Should we handle unknown symbols?
+         if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
+         {
+            if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
+            {
+               T default_value = T(0);
+               std::string error_message;
+               typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type;
+
+               if (unknown_symbol_resolver_->process(symbol,usr_symbol_type,default_value,error_message))
+               {
+                  bool create_result = false;
+
+                  symbol_table_t& symtab = symtab_store_.get_symbol_table();
+
+                  switch (usr_symbol_type)
+                  {
+                     case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol,default_value);
+                                                                         break;
+
+                     case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol,default_value);
+                                                                         break;
+
+                     default                                           : create_result = false;
+                  }
+
+                  if (create_result)
+                  {
+                     expression_node_ptr var = symtab_store_.get_variable(symbol);
+
+                     if (var)
+                     {
+                        if (symtab_store_.is_constant_node(symbol))
+                        {
+                           var = expression_generator_(var->value());
+                        }
+
+                        lodge_symbol(symbol,e_st_variable);
+
+                        if (!post_variable_process(symbol))
+                           return error_node();
+
+                        next_token();
+
+                        return var;
+                     }
+                  }
+
+                  set_error(
+                     make_error(parser_error::e_symtab,
+                                current_token(),
+                                "ERR182 - Failed to create variable: '" + symbol + "'"));
+
+                  return error_node();
+               }
+            }
+         }
+
+         set_error(
+            make_error(parser_error::e_syntax,
+                       current_token(),
+                       "ERR183 - Undefined symbol: '" + symbol + "'"));
+
+         return error_node();
+      }
+
+      inline expression_node_ptr parse_symbol()
+      {
+         static const std::string symbol_if       = "if"      ;
+         static const std::string symbol_while    = "while"   ;
+         static const std::string symbol_repeat   = "repeat"  ;
+         static const std::string symbol_for      = "for"     ;
+         static const std::string symbol_switch   = "switch"  ;
+         static const std::string symbol_null     = "null"    ;
+         static const std::string symbol_break    = "break"   ;
+         static const std::string symbol_continue = "continue";
+         static const std::string symbol_var      = "var"     ;
+         static const std::string symbol_swap     = "swap"    ;
+         static const std::string symbol_return   = "return"  ;
+
+         if (valid_vararg_operation(current_token().value))
+         {
+            return parse_vararg_function();
+         }
+         else if (valid_base_operation(current_token().value))
+         {
+            return parse_base_operation();
+         }
+         else if (
+                   details::imatch(current_token().value,symbol_if) &&
+                   settings_.control_struct_enabled(current_token().value)
+                 )
+         {
+            return parse_conditional_statement();
+         }
+         else if (
+                   details::imatch(current_token().value,symbol_while) &&
+                   settings_.control_struct_enabled(current_token().value)
+                 )
+         {
+            return parse_while_loop();
+         }
+         else if (
+                   details::imatch(current_token().value,symbol_repeat) &&
+                   settings_.control_struct_enabled(current_token().value)
+                 )
+         {
+            return parse_repeat_until_loop();
+         }
+         else if (
+                   details::imatch(current_token().value,symbol_for) &&
+                   settings_.control_struct_enabled(current_token().value)
+                 )
+         {
+            return parse_for_loop();
+         }
+         else if (
+                   details::imatch(current_token().value,symbol_switch) &&
+                   settings_.control_struct_enabled(current_token().value)
+                 )
+         {
+            return parse_switch_statement();
+         }
+         else if (details::is_valid_sf_symbol(current_token().value))
+         {
+            return parse_special_function();
+         }
+         else if (details::imatch(current_token().value,symbol_null))
+         {
+            return parse_null_statement();
+         }
+         #ifndef exprtk_disable_break_continue
+         else if (details::imatch(current_token().value,symbol_break))
+         {
+            return parse_break_statement();
+         }
+         else if (details::imatch(current_token().value,symbol_continue))
+         {
+            return parse_continue_statement();
+         }
+         #endif
+         else if (details::imatch(current_token().value,symbol_var))
+         {
+            return parse_define_var_statement();
+         }
+         else if (details::imatch(current_token().value,symbol_swap))
+         {
+            return parse_swap_statement();
+         }
+         else if (details::imatch(current_token().value,symbol_return))
+         {
+            return parse_return_statement();
+         }
+         else if (symtab_store_.valid() || !sem_.empty())
+         {
+            return parse_symtab_symbol();
+         }
+         else
+         {
+            set_error(
+               make_error(parser_error::e_symtab,
+                          current_token(),
+                          "ERR184 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value));
+
+            return error_node();
+         }
+      }
+
+      inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
+      {
+         expression_node_ptr branch = error_node();
+
+         if (token_t::e_number == current_token().type)
+         {
+            T numeric_value = T(0);
+
+            if (details::string_to_real(current_token().value,numeric_value))
+            {
+               expression_node_ptr literal_exp = expression_generator_(numeric_value);
+               next_token();
+               branch = literal_exp;
+            }
+            else
+            {
+               set_error(
+                  make_error(parser_error::e_numeric,
+                             current_token(),
+                             "ERR185 - Failed to convert '" + current_token().value + "' to a number"));
+
+               return error_node();
+            }
+         }
+         else if (token_t::e_symbol == current_token().type)
+         {
+            branch = parse_symbol();
+         }
+         #ifndef exprtk_disable_string_capabilities
+         else if (token_t::e_string == current_token().type)
+         {
+            branch = parse_const_string();
+         }
+         #endif
+         else if (token_t::e_lbracket == current_token().type)
+         {
+            next_token();
+
+            if (0 == (branch = parse_expression()))
+               return error_node();
+            else if (!token_is(token_t::e_rbracket))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR186 - Expected ')' instead of: '" + current_token().value + "'"));
+
+               free_node(node_allocator_,branch);
+
+               return error_node();
+            }
+            else if (!post_bracket_process(token_t::e_lbracket,branch))
+            {
+               free_node(node_allocator_,branch);
+
+               return error_node();
+            }
+         }
+         else if (token_t::e_lsqrbracket == current_token().type)
+         {
+            next_token();
+
+            if (0 == (branch = parse_expression()))
+               return error_node();
+            else if (!token_is(token_t::e_rsqrbracket))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR187 - Expected ']' instead of: '" + current_token().value + "'"));
+
+               free_node(node_allocator_,branch);
+
+               return error_node();
+            }
+            else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
+            {
+               free_node(node_allocator_,branch);
+
+               return error_node();
+            }
+         }
+         else if (token_t::e_lcrlbracket == current_token().type)
+         {
+            next_token();
+
+            if (0 == (branch = parse_expression()))
+               return error_node();
+            else if (!token_is(token_t::e_rcrlbracket))
+            {
+               set_error(
+                  make_error(parser_error::e_syntax,
+                             current_token(),
+                             "ERR188 - Expected '}' instead of: '" + current_token().value + "'"));
+
+               free_node(node_allocator_,branch);
+
+               return error_node();
+            }
+            else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
+            {
+               free_node(node_allocator_,branch);
+
+               return error_node();
+            }
+         }
+         else if (token_t::e_sub == current_token().type)
+         {
+            next_token();
+            branch = parse_expression(e_level11);
+
+            if (
+                 branch &&
+                 !(
+                    details::is_neg_unary_node    (branch) &&
+                    simplify_unary_negation_branch(branch)
+                  )
+               )
+            {
+               branch = expression_generator_(details::e_neg,branch);
+            }
+         }
+         else if (token_t::e_add == current_token().type)
+         {
+            next_token();
+            branch = parse_expression(e_level13);
+         }
+         else if (token_t::e_eof == current_token().type)
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR189 - Premature end of expression[1]"));
+
+            return error_node();
+         }
+         else
+         {
+            set_error(
+               make_error(parser_error::e_syntax,
+                          current_token(),
+                          "ERR190 - Premature end of expression[2]"));
+
+            return error_node();
+         }
+
+         if (
+              branch                    &&
+              (e_level00 == precedence) &&
+              token_is(token_t::e_ternary,false)
+            )
+         {
+            branch = parse_ternary_conditional_statement(branch);
+         }
+
+         parse_pending_string_rangesize(branch);
+
+         return branch;
+      }
+
+      template <typename Type>
+      class expression_generator
+      {
+      public:
+
+         typedef details::expression_node<Type>* expression_node_ptr;
+         typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
+         typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
+         typedef typename exprtk::parser<Type> parser_t;
+         typedef const Type& vtype;
+         typedef const Type  ctype;
+
+         inline void init_synthesize_map()
+         {
+            #ifndef exprtk_disable_enhanced_features
+            synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
+            synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
+            synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
+
+            #define register_synthezier(S)                      \
+            synthesize_map_[S ::node_type::id()] = S ::process; \
+
+            register_synthezier(synthesize_vovov_expression0)
+            register_synthezier(synthesize_vovov_expression1)
+            register_synthezier(synthesize_vovoc_expression0)
+            register_synthezier(synthesize_vovoc_expression1)
+            register_synthezier(synthesize_vocov_expression0)
+            register_synthezier(synthesize_vocov_expression1)
+            register_synthezier(synthesize_covov_expression0)
+            register_synthezier(synthesize_covov_expression1)
+            register_synthezier(synthesize_covoc_expression0)
+            register_synthezier(synthesize_covoc_expression1)
+            register_synthezier(synthesize_cocov_expression1)
+            register_synthezier(synthesize_vococ_expression0)
+
+            register_synthezier(synthesize_vovovov_expression0)
+            register_synthezier(synthesize_vovovoc_expression0)
+            register_synthezier(synthesize_vovocov_expression0)
+            register_synthezier(synthesize_vocovov_expression0)
+            register_synthezier(synthesize_covovov_expression0)
+            register_synthezier(synthesize_covocov_expression0)
+            register_synthezier(synthesize_vocovoc_expression0)
+            register_synthezier(synthesize_covovoc_expression0)
+            register_synthezier(synthesize_vococov_expression0)
+
+            register_synthezier(synthesize_vovovov_expression1)
+            register_synthezier(synthesize_vovovoc_expression1)
+            register_synthezier(synthesize_vovocov_expression1)
+            register_synthezier(synthesize_vocovov_expression1)
+            register_synthezier(synthesize_covovov_expression1)
+            register_synthezier(synthesize_covocov_expression1)
+            register_synthezier(synthesize_vocovoc_expression1)
+            register_synthezier(synthesize_covovoc_expression1)
+            register_synthezier(synthesize_vococov_expression1)
+
+            register_synthezier(synthesize_vovovov_expression2)
+            register_synthezier(synthesize_vovovoc_expression2)
+            register_synthezier(synthesize_vovocov_expression2)
+            register_synthezier(synthesize_vocovov_expression2)
+            register_synthezier(synthesize_covovov_expression2)
+            register_synthezier(synthesize_covocov_expression2)
+            register_synthezier(synthesize_vocovoc_expression2)
+            register_synthezier(synthesize_covovoc_expression2)
+
+            register_synthezier(synthesize_vovovov_expression3)
+            register_synthezier(synthesize_vovovoc_expression3)
+            register_synthezier(synthesize_vovocov_expression3)
+            register_synthezier(synthesize_vocovov_expression3)
+            register_synthezier(synthesize_covovov_expression3)
+            register_synthezier(synthesize_covocov_expression3)
+            register_synthezier(synthesize_vocovoc_expression3)
+            register_synthezier(synthesize_covovoc_expression3)
+            register_synthezier(synthesize_vococov_expression3)
+
+            register_synthezier(synthesize_vovovov_expression4)
+            register_synthezier(synthesize_vovovoc_expression4)
+            register_synthezier(synthesize_vovocov_expression4)
+            register_synthezier(synthesize_vocovov_expression4)
+            register_synthezier(synthesize_covovov_expression4)
+            register_synthezier(synthesize_covocov_expression4)
+            register_synthezier(synthesize_vocovoc_expression4)
+            register_synthezier(synthesize_covovoc_expression4)
+            #endif
+         }
+
+         inline void set_parser(parser_t& p)
+         {
+            parser_ = &p;
+         }
+
+         inline void set_uom(unary_op_map_t& unary_op_map)
+         {
+            unary_op_map_ = &unary_op_map;
+         }
+
+         inline void set_bom(binary_op_map_t& binary_op_map)
+         {
+            binary_op_map_ = &binary_op_map;
+         }
+
+         inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
+         {
+            inv_binary_op_map_ = &inv_binary_op_map;
+         }
+
+         inline void set_sf3m(sf3_map_t& sf3_map)
+         {
+            sf3_map_ = &sf3_map;
+         }
+
+         inline void set_sf4m(sf4_map_t& sf4_map)
+         {
+            sf4_map_ = &sf4_map;
+         }
+
+         inline void set_allocator(details::node_allocator& na)
+         {
+            node_allocator_ = &na;
+         }
+
+         inline void set_strength_reduction_state(const bool enabled)
+         {
+            strength_reduction_enabled_ = enabled;
+         }
+
+         inline bool strength_reduction_enabled() const
+         {
+            return strength_reduction_enabled_;
+         }
+
+         inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
+         {
+            typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
+
+            if ((*binary_op_map_).end() == bop_itr)
+               return false;
+
+            bop = bop_itr->second;
+
+            return true;
+         }
+
+         inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
+         {
+            typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
+
+            if ((*unary_op_map_).end() == uop_itr)
+               return false;
+
+            uop = uop_itr->second;
+
+            return true;
+         }
+
+         inline details::operator_type get_operator(const binary_functor_t& bop)
+         {
+            return (*inv_binary_op_map_).find(bop)->second;
+         }
+
+         inline expression_node_ptr operator()(const Type& v) const
+         {
+            return node_allocator_->allocate<literal_node_t>(v);
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline expression_node_ptr operator()(const std::string& s) const
+         {
+            return node_allocator_->allocate<string_literal_node_t>(s);
+         }
+
+         inline expression_node_ptr operator()(std::string& s, range_t& rp) const
+         {
+            return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
+         }
+
+         inline expression_node_ptr operator()(const std::string& s, range_t& rp) const
+         {
+            return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
+         }
+
+         inline expression_node_ptr operator()(expression_node_ptr branch, range_t& rp) const
+         {
+            if (is_generally_string_node(branch))
+               return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
+            else
+               return error_node();
+         }
+         #endif
+
+         inline bool unary_optimisable(const details::operator_type& operation) const
+         {
+            return (details::e_abs   == operation) || (details::e_acos  == operation) ||
+                   (details::e_acosh == operation) || (details::e_asin  == operation) ||
+                   (details::e_asinh == operation) || (details::e_atan  == operation) ||
+                   (details::e_atanh == operation) || (details::e_ceil  == operation) ||
+                   (details::e_cos   == operation) || (details::e_cosh  == operation) ||
+                   (details::e_exp   == operation) || (details::e_expm1 == operation) ||
+                   (details::e_floor == operation) || (details::e_log   == operation) ||
+                   (details::e_log10 == operation) || (details::e_log2  == operation) ||
+                   (details::e_log1p == operation) || (details::e_neg   == operation) ||
+                   (details::e_pos   == operation) || (details::e_round == operation) ||
+                   (details::e_sin   == operation) || (details::e_sinc  == operation) ||
+                   (details::e_sinh  == operation) || (details::e_sqrt  == operation) ||
+                   (details::e_tan   == operation) || (details::e_tanh  == operation) ||
+                   (details::e_cot   == operation) || (details::e_sec   == operation) ||
+                   (details::e_csc   == operation) || (details::e_r2d   == operation) ||
+                   (details::e_d2r   == operation) || (details::e_d2g   == operation) ||
+                   (details::e_g2d   == operation) || (details::e_notl  == operation) ||
+                   (details::e_sgn   == operation) || (details::e_erf   == operation) ||
+                   (details::e_erfc  == operation) || (details::e_ncdf  == operation) ||
+                   (details::e_frac  == operation) || (details::e_trunc == operation);
+         }
+
+         inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc)
+         {
+            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
+
+            if (sf3_map_->end() == itr)
+               return false;
+            else
+               tfunc = itr->second.first;
+
+            return true;
+         }
+
+         inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc)
+         {
+            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
+
+            if (sf4_map_->end() == itr)
+               return false;
+            else
+               qfunc = itr->second.first;
+
+            return true;
+         }
+
+         inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation)
+         {
+            typename sf3_map_t::iterator itr = sf3_map_->find(sf3id);
+
+            if (sf3_map_->end() == itr)
+               return false;
+            else
+               operation = itr->second.second;
+
+            return true;
+         }
+
+         inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation)
+         {
+            typename sf4_map_t::iterator itr = sf4_map_->find(sf4id);
+
+            if (sf4_map_->end() == itr)
+               return false;
+            else
+               operation = itr->second.second;
+
+            return true;
+         }
+
+         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1])
+         {
+            if (0 == branch[0])
+               return error_node();
+            else if (details::is_null_node(branch[0]))
+               return branch[0];
+            else if (details::is_break_node(branch[0]))
+               return error_node();
+            else if (details::is_continue_node(branch[0]))
+               return error_node();
+            else if (details::is_constant_node(branch[0]))
+               return synthesize_expression<unary_node_t,1>(operation,branch);
+            else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
+               return synthesize_uv_expression(operation,branch);
+            else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
+               return synthesize_uvec_expression(operation,branch);
+            else
+               return synthesize_unary_expression(operation,branch);
+         }
+
+         inline bool is_assignment_operation(const details::operator_type& operation) const
+         {
+            return (
+                      (details::e_addass == operation) ||
+                      (details::e_subass == operation) ||
+                      (details::e_mulass == operation) ||
+                      (details::e_divass == operation) ||
+                      (details::e_modass == operation)
+                   ) &&
+                   parser_->settings_.assignment_enabled(operation);
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline bool valid_string_operation(const details::operator_type& operation) const
+         {
+            return (details::e_add    == operation) ||
+                   (details::e_lt     == operation) ||
+                   (details::e_lte    == operation) ||
+                   (details::e_gt     == operation) ||
+                   (details::e_gte    == operation) ||
+                   (details::e_eq     == operation) ||
+                   (details::e_ne     == operation) ||
+                   (details::e_in     == operation) ||
+                   (details::e_like   == operation) ||
+                   (details::e_ilike  == operation) ||
+                   (details::e_assign == operation) ||
+                   (details::e_addass == operation) ||
+                   (details::e_swap   == operation) ;
+         }
+         #else
+         inline bool valid_string_operation(const details::operator_type&) const
+         {
+            return false;
+         }
+         #endif
+
+         inline std::string to_str(const details::operator_type& operation) const
+         {
+            switch (operation)
+            {
+               case details::e_add  : return "+";
+               case details::e_sub  : return "-";
+               case details::e_mul  : return "*";
+               case details::e_div  : return "/";
+               case details::e_mod  : return "%";
+               case details::e_pow  : return "^";
+               case details::e_lt   : return "<";
+               case details::e_lte  : return "<=";
+               case details::e_gt   : return ">";
+               case details::e_gte  : return ">=";
+               case details::e_eq   : return "==";
+               case details::e_ne   : return "!=";
+               case details::e_and  : return "and";
+               case details::e_nand : return "nand";
+               case details::e_or   : return "or";
+               case details::e_nor  : return "nor";
+               case details::e_xor  : return "xor";
+               case details::e_xnor : return "xnor";
+               default              : return "UNKNOWN";
+            }
+         }
+
+         inline bool operation_optimisable(const details::operator_type& operation) const
+         {
+            return (details::e_add  == operation) ||
+                   (details::e_sub  == operation) ||
+                   (details::e_mul  == operation) ||
+                   (details::e_div  == operation) ||
+                   (details::e_mod  == operation) ||
+                   (details::e_pow  == operation) ||
+                   (details::e_lt   == operation) ||
+                   (details::e_lte  == operation) ||
+                   (details::e_gt   == operation) ||
+                   (details::e_gte  == operation) ||
+                   (details::e_eq   == operation) ||
+                   (details::e_ne   == operation) ||
+                   (details::e_and  == operation) ||
+                   (details::e_nand == operation) ||
+                   (details::e_or   == operation) ||
+                   (details::e_nor  == operation) ||
+                   (details::e_xor  == operation) ||
+                   (details::e_xnor == operation) ;
+         }
+
+         inline std::string branch_to_id(expression_node_ptr branch)
+         {
+            static const std::string null_str   ("(null)" );
+            static const std::string const_str  ("(c)"    );
+            static const std::string var_str    ("(v)"    );
+            static const std::string vov_str    ("(vov)"  );
+            static const std::string cov_str    ("(cov)"  );
+            static const std::string voc_str    ("(voc)"  );
+            static const std::string str_str    ("(s)"    );
+            static const std::string strrng_str ("(rngs)" );
+            static const std::string cs_str     ("(cs)"   );
+            static const std::string cstrrng_str("(crngs)");
+
+            if (details::is_null_node(branch))
+               return null_str;
+            else if (details::is_constant_node(branch))
+               return const_str;
+            else if (details::is_variable_node(branch))
+               return var_str;
+            else if (details::is_vov_node(branch))
+               return vov_str;
+            else if (details::is_cov_node(branch))
+               return cov_str;
+            else if (details::is_voc_node(branch))
+               return voc_str;
+            else if (details::is_string_node(branch))
+               return str_str;
+            else if (details::is_const_string_node(branch))
+               return cs_str;
+            else if (details::is_string_range_node(branch))
+               return strrng_str;
+            else if (details::is_const_string_range_node(branch))
+               return cstrrng_str;
+            else if (details::is_t0ot1ot2_node(branch))
+               return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
+            else if (details::is_t0ot1ot2ot3_node(branch))
+               return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
+            else
+               return "ERROR";
+         }
+
+         inline std::string branch_to_id(expression_node_ptr (&branch)[2])
+         {
+            return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
+         }
+
+         inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
+         }
+
+         inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
+         }
+
+         inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
+         }
+
+         inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (details::is_constant_node(branch[0]) && !details::is_constant_node(branch[1]));
+         }
+
+         inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (!details::is_constant_node(branch[0]) && details::is_constant_node(branch[1]));
+         }
+
+         inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (
+                 (details::e_add == operation) ||
+                 (details::e_sub == operation) ||
+                 (details::e_mul == operation) ||
+                 (details::e_div == operation)
+               )
+            {
+               return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
+                      (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0]));
+            }
+            else
+               return false;
+         }
+
+         inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (
+                 (details::e_add == operation) ||
+                 (details::e_sub == operation) ||
+                 (details::e_mul == operation) ||
+                 (details::e_div == operation)
+               )
+            {
+               return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
+                      (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0]));
+            }
+            else
+               return false;
+         }
+
+         inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (details::is_uv_node(branch[0]) && details::is_uv_node(branch[1]));
+         }
+
+         inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (details::is_variable_node(branch[0]) && !details::is_variable_node(branch[1]));
+         }
+
+         inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (!details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
+         }
+
+         inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
+         {
+            if (!operation_optimisable(operation))
+               return false;
+            else
+               return (!details::is_constant_node(branch[0]) || !details::is_constant_node(branch[1]));
+         }
+
+         inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            if (is_assignment_operation(operation))
+            {
+               const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
+
+               if (details::is_string_node(branch[0]))
+                  return !b1_is_genstring;
+               else
+                  return (
+                           !details::is_variable_node   (branch[0]) &&
+                           !details::is_vector_elem_node(branch[0]) &&
+                           !details::is_vector_node     (branch[0])
+                         )
+                         || b1_is_genstring;
+            }
+            else
+               return false;
+         }
+
+         inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2])
+         {
+            if (
+                 !is_constant_node(branch[1]) ||
+                  is_constant_node(branch[0]) ||
+                  is_variable_node(branch[0]) ||
+                  is_vector_node  (branch[0]) ||
+                  is_generally_string_node(branch[0])
+               )
+               return false;
+
+            const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+
+            return cardinal_pow_optimisable(operation, c);
+         }
+
+         inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2])
+         {
+            return (
+                     details::is_break_node   (branch[0]) ||
+                     details::is_break_node   (branch[1]) ||
+                     details::is_continue_node(branch[0]) ||
+                     details::is_continue_node(branch[1])
+                   );
+         }
+
+         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            const bool b0_string = is_generally_string_node(branch[0]);
+            const bool b1_string = is_generally_string_node(branch[1]);
+
+            bool result = false;
+
+            if (b0_string ^ b1_string)
+               result = true;
+            else if (!valid_string_operation(operation) && b0_string && b1_string)
+               result = true;
+
+            if (result)
+            {
+               parser_->set_synthesis_error("Invalid string operation");
+            }
+
+            return result;
+         }
+
+         inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+         {
+            const bool b0_string = is_generally_string_node(branch[0]);
+            const bool b1_string = is_generally_string_node(branch[1]);
+            const bool b2_string = is_generally_string_node(branch[2]);
+
+            bool result = false;
+
+            if ((b0_string ^ b1_string) || (b1_string ^ b2_string))
+               result = true;
+            else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
+               result = true;
+
+            if (result)
+            {
+               parser_->set_synthesis_error("Invalid string operation");
+            }
+
+            return result;
+         }
+
+         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            const bool b0_string = is_generally_string_node(branch[0]);
+            const bool b1_string = is_generally_string_node(branch[1]);
+
+            return (b0_string && b1_string && valid_string_operation(operation));
+         }
+
+         inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+         {
+            const bool b0_string = is_generally_string_node(branch[0]);
+            const bool b1_string = is_generally_string_node(branch[1]);
+            const bool b2_string = is_generally_string_node(branch[2]);
+
+            return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
+         }
+
+         #ifndef exprtk_disable_sc_andor
+         inline bool is_shortcircuit_expression(const details::operator_type& operation)
+         {
+            return (
+                     (details::e_scand == operation) ||
+                     (details::e_scor  == operation)
+                   );
+         }
+         #else
+         inline bool is_shortcircuit_expression(const details::operator_type&)
+         {
+            return false;
+         }
+         #endif
+
+         inline bool is_null_present(expression_node_ptr (&branch)[2])
+         {
+            return (
+                     details::is_null_node(branch[0]) ||
+                     details::is_null_node(branch[1])
+                   );
+         }
+
+         inline bool is_vector_eqineq_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
+               return false;
+            else
+               return (
+                        (details::e_lt  == operation) ||
+                        (details::e_lte == operation) ||
+                        (details::e_gt  == operation) ||
+                        (details::e_gte == operation) ||
+                        (details::e_eq  == operation) ||
+                        (details::e_ne  == operation)
+                      );
+         }
+
+         inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
+               return false;
+            else
+               return (
+                        (details::e_add == operation) ||
+                        (details::e_sub == operation) ||
+                        (details::e_mul == operation) ||
+                        (details::e_div == operation) ||
+                        (details::e_pow == operation)
+                      );
+         }
+
+         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            if ((0 == branch[0]) || (0 == branch[1]))
+               return error_node();
+            else if (is_invalid_string_op(operation,branch))
+               return error_node();
+            else if (is_invalid_assignment_op(operation,branch))
+               return error_node();
+            else if (is_invalid_break_continue_op(branch))
+               return error_node();
+            else if (details::e_assign == operation)
+               return synthesize_assignment_expression(operation,branch);
+            else if (details::e_swap == operation)
+               return synthesize_swap_expression(branch);
+            else if (is_assignment_operation(operation))
+               return synthesize_assignment_operation_expression(operation,branch);
+            else if (is_vector_eqineq_operation(operation,branch))
+               return synthesize_veceqineq_operation_expression(operation,branch);
+            else if (is_vector_arithmetic_operation(operation,branch))
+               return synthesize_vecarithmetic_operation_expression(operation,branch);
+            else if (is_shortcircuit_expression(operation))
+               return synthesize_shortcircuit_expression(operation,branch);
+            else if (is_string_operation(operation,branch))
+               return synthesize_string_expression(operation,branch);
+            else if (is_null_present(branch))
+               return synthesize_null_expression(operation, branch);
+            #ifndef exprtk_disable_cardinal_pow_optimisation
+            else if (is_constpow_operation(operation, branch))
+               return cardinal_pow_optimisation(branch);
+            #endif
+
+            expression_node_ptr result = error_node();
+
+            #ifndef exprtk_disable_enhanced_features
+            if (synthesize_expression(operation,branch,result))
+               return result;
+            else
+            #endif
+
+            {
+               /*
+                  Possible reductions:
+                  1. c o cob -> cob
+                  2. cob o c -> cob
+                  3. c o boc -> boc
+                  4. boc o c -> boc
+               */
+               result = error_node();
+
+               if (cocob_optimisable(operation,branch))
+                  result = synthesize_cocob_expression::process(*this,operation,branch);
+               else if (coboc_optimisable(operation,branch) && (0 == result))
+                  result = synthesize_coboc_expression::process(*this,operation,branch);
+
+               if (result)
+                  return result;
+            }
+
+            if (uvouv_optimisable(operation,branch))
+               return synthesize_uvouv_expression(operation,branch);
+            else if (vob_optimisable(operation,branch))
+               return synthesize_vob_expression::process(*this,operation,branch);
+            else if (bov_optimisable(operation,branch))
+               return synthesize_bov_expression::process(*this,operation,branch);
+            else if (cob_optimisable(operation,branch))
+               return synthesize_cob_expression::process(*this,operation,branch);
+            else if (boc_optimisable(operation,branch))
+               return synthesize_boc_expression::process(*this,operation,branch);
+            #ifndef exprtk_disable_enhanced_features
+            else if (cov_optimisable(operation,branch))
+               return synthesize_cov_expression::process(*this,operation,branch);
+            #endif
+            else if (binext_optimisable(operation,branch))
+               return synthesize_binary_ext_expression::process(*this,operation,branch);
+            else
+               return synthesize_expression<binary_node_t,2>(operation,branch);
+         }
+
+         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+         {
+            if (
+                 (0 == branch[0]) ||
+                 (0 == branch[1]) ||
+                 (0 == branch[2])
+               )
+            {
+               details::free_all_nodes(*node_allocator_,branch);
+
+               return error_node();
+            }
+            else if (is_invalid_string_op(operation,branch))
+               return error_node();
+            else if (is_string_operation(operation,branch))
+               return synthesize_string_expression(operation,branch);
+            else
+               return synthesize_expression<trinary_node_t,3>(operation,branch);
+         }
+
+         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+         {
+            return synthesize_expression<quaternary_node_t,4>(operation,branch);
+         }
+
+         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0)
+         {
+            expression_node_ptr branch[1] = { b0 };
+            return (*this)(operation,branch);
+         }
+
+         inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)
+         {
+            if ((0 == b0) || (0 == b1))
+               return error_node();
+            else
+            {
+               expression_node_ptr branch[2] = { b0, b1 };
+               return expression_generator<Type>::operator()(operation,branch);
+            }
+         }
+
+         inline expression_node_ptr conditional(expression_node_ptr condition,
+                                                expression_node_ptr consequent,
+                                                expression_node_ptr alternative) const
+         {
+            if ((0 == condition) || (0 == consequent))
+            {
+               free_node(*node_allocator_,condition  );
+               free_node(*node_allocator_,consequent );
+               free_node(*node_allocator_,alternative);
+
+               return error_node();
+            }
+            // Can the condition be immediately evaluated? if so optimise.
+            else if (details::is_constant_node(condition))
+            {
+               // True branch
+               if (details::is_true(condition))
+               {
+                  free_node(*node_allocator_,condition  );
+                  free_node(*node_allocator_,alternative);
+
+                  return consequent;
+               }
+               // False branch
+               else
+               {
+                  free_node(*node_allocator_,condition );
+                  free_node(*node_allocator_,consequent);
+
+                  if (alternative)
+                     return alternative;
+                  else
+                     return node_allocator_->allocate<details::null_node<T> >();
+               }
+            }
+            else if ((0 != consequent) && (0 != alternative))
+            {
+               return node_allocator_->
+                        allocate<conditional_node_t>(condition,consequent,alternative);
+            }
+            else
+               return node_allocator_->
+                        allocate<cons_conditional_node_t>(condition,consequent);
+         }
+
+         #ifndef exprtk_disable_string_capabilities
+         inline expression_node_ptr conditional_string(expression_node_ptr condition,
+                                                       expression_node_ptr consequent,
+                                                       expression_node_ptr alternative) const
+         {
+            if ((0 == condition) || (0 == consequent))
+            {
+               free_node(*node_allocator_,condition  );
+               free_node(*node_allocator_,consequent );
+               free_node(*node_allocator_,alternative);
+
+               return error_node();
+            }
+            // Can the condition be immediately evaluated? if so optimise.
+            else if (details::is_constant_node(condition))
+            {
+               // True branch
+               if (details::is_true(condition))
+               {
+                  free_node(*node_allocator_,condition  );
+                  free_node(*node_allocator_,alternative);
+
+                  return consequent;
+               }
+               // False branch
+               else
+               {
+                  free_node(*node_allocator_,condition );
+                  free_node(*node_allocator_,consequent);
+
+                  if (alternative)
+                     return alternative;
+                  else
+                     return node_allocator_->
+                              allocate_c<details::string_literal_node<Type> >("");
+               }
+            }
+            else if ((0 != consequent) && (0 != alternative))
+               return node_allocator_->
+                        allocate<conditional_string_node_t>(condition,consequent,alternative);
+            else
+               return error_node();
+         }
+         #else
+         inline expression_node_ptr conditional_string(expression_node_ptr,
+                                                       expression_node_ptr,
+                                                       expression_node_ptr) const
+         {
+            return error_node();
+         }
+         #endif
+
+         inline expression_node_ptr while_loop(expression_node_ptr& condition,
+                                               expression_node_ptr& branch,
+                                               const bool brkcont = false) const
+         {
+            if (!brkcont && details::is_constant_node(condition))
+            {
+               expression_node_ptr result = error_node();
+               if (details::is_true(condition))
+                  // Infinite loops are not allowed.
+                  result = error_node();
+               else
+                  result = node_allocator_->allocate<details::null_node<Type> >();
+
+               free_node(*node_allocator_, condition);
+               free_node(*node_allocator_, branch   );
+
+               return result;
+            }
+            else if (details::is_null_node(condition))
+            {
+               free_node(*node_allocator_,condition);
+
+               return branch;
+            }
+            else if (!brkcont)
+               return node_allocator_->allocate<while_loop_node_t>(condition,branch);
+            #ifndef exprtk_disable_break_continue
+            else
+               return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
+            #else
+               return error_node();
+            #endif
+         }
+
+         inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition,
+                                                      expression_node_ptr& branch,
+                                                      const bool brkcont = false) const
+         {
+            if (!brkcont && details::is_constant_node(condition))
+            {
+               if (details::is_true(condition) && details::is_constant_node(branch))
+               {
+                  free_node(*node_allocator_,condition);
+
+                  return branch;
+               }
+
+               free_node(*node_allocator_, condition);
+               free_node(*node_allocator_, branch   );
+
+               return error_node();
+            }
+            else if (details::is_null_node(condition))
+            {
+               free_node(*node_allocator_,condition);
+
+               return branch;
+            }
+            else if (!brkcont)
+               return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
+            #ifndef exprtk_disable_break_continue
+            else
+               return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
+            #else
+               return error_node();
+            #endif
+         }
+
+         inline expression_node_ptr for_loop(expression_node_ptr& initialiser,
+                                             expression_node_ptr& condition,
+                                             expression_node_ptr& incrementor,
+                                             expression_node_ptr& loop_body,
+                                             bool brkcont = false) const
+         {
+            if (!brkcont && details::is_constant_node(condition))
+            {
+               expression_node_ptr result = error_node();
+
+               if (details::is_true(condition))
+                  // Infinite loops are not allowed.
+                  result = error_node();
+               else
+                  result = node_allocator_->allocate<details::null_node<Type> >();
+
+               free_node(*node_allocator_,initialiser);
+               free_node(*node_allocator_,condition  );
+               free_node(*node_allocator_,incrementor);
+               free_node(*node_allocator_,loop_body  );
+
+               return result;
+            }
+            else if (details::is_null_node(condition))
+            {
+               free_node(*node_allocator_,initialiser);
+               free_node(*node_allocator_,condition  );
+               free_node(*node_allocator_,incrementor);
+
+               return loop_body;
+            }
+            else if (!brkcont)
+               return node_allocator_->allocate<for_loop_node_t>(initialiser,
+                                                                 condition,
+                                                                 incrementor,
+                                                                 loop_body);
+            #ifndef exprtk_disable_break_continue
+            else
+               return node_allocator_->allocate<for_loop_bc_node_t>(initialiser,
+                                                                    condition,
+                                                                    incrementor,
+                                                                    loop_body);
+            #else
+            return error_node();
+            #endif
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            expression_node_ptr result = error_node();
+
+            for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
+            {
+               expression_node_ptr condition  = arg_list[(2 * i)    ];
+               expression_node_ptr consequent = arg_list[(2 * i) + 1];
+
+               if ((0 == result) && details::is_true(condition))
+               {
+                  result = consequent;
+                  break;
+               }
+            }
+
+            if (0 == result)
+            {
+               result = arg_list.back();
+            }
+
+            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            {
+               expression_node_ptr current_expr = arg_list[i];
+
+               if (current_expr && (current_expr != result))
+               {
+                  free_node(*node_allocator_,current_expr);
+               }
+            }
+
+            return result;
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            expression_node_ptr result = error_node();
+
+            for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
+            {
+               expression_node_ptr condition  = arg_list[(2 * i)    ];
+               expression_node_ptr consequent = arg_list[(2 * i) + 1];
+
+               if (details::is_true(condition))
+               {
+                  result = consequent;
+               }
+            }
+
+            if (0 == result)
+            {
+               T zero = T(0);
+               result = node_allocator_->allocate<literal_node_t>(zero);
+            }
+
+            for (std::size_t i = 0; i < arg_list.size(); ++i)
+            {
+               expression_node_ptr& current_expr = arg_list[i];
+
+               if (current_expr && (current_expr != result))
+               {
+                  free_node(*node_allocator_,current_expr);
+               }
+            }
+
+            return result;
+         }
+
+         struct switch_nodes
+         {
+            typedef std::vector<expression_node_ptr> arg_list_t;
+
+            #define case_stmt(N) \
+            if (is_true(arg[(2 * N)])) return arg[(2 * N) + 1]->value();
+
+            struct switch_1
+            {
+               static inline T process(const arg_list_t& arg)
+               {
+                  case_stmt(0)
+                  return arg.back()->value();
+               }
+            };
+
+            struct switch_2
+            {
+               static inline T process(const arg_list_t& arg)
+               {
+                  case_stmt(0) case_stmt(1)
+                  return arg.back()->value();
+               }
+            };
+
+            struct switch_3
+            {
+               static inline T process(const arg_list_t& arg)
+               {
+                  case_stmt(0) case_stmt(1)
+                  case_stmt(2)
+                  return arg.back()->value();
+               }
+            };
+
+            struct switch_4
+            {
+               static inline T process(const arg_list_t& arg)
+               {
+                  case_stmt(0) case_stmt(1)
+                  case_stmt(2) case_stmt(3)
+                  return arg.back()->value();
+               }
+            };
+
+            struct switch_5
+            {
+               static inline T process(const arg_list_t& arg)
+               {
+                  case_stmt(0) case_stmt(1)
+                  case_stmt(2) case_stmt(3)
+                  case_stmt(4)
+                  return arg.back()->value();
+               }
+            };
+
+            struct switch_6
+            {
+               static inline T process(const arg_list_t& arg)
+               {
+                  case_stmt(0) case_stmt(1)
+                  case_stmt(2) case_stmt(3)
+                  case_stmt(4) case_stmt(5)
+                  return arg.back()->value();
+               }
+            };
+
+            struct switch_7
+            {
+               static inline T process(const arg_list_t& arg)
+               {
+                  case_stmt(0) case_stmt(1)
+                  case_stmt(2) case_stmt(3)
+                  case_stmt(4) case_stmt(5)
+                  case_stmt(6)
+                  return arg.back()->value();
+               }
+            };
+
+            #undef case_stmt
+         };
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            if (arg_list.empty())
+               return error_node();
+            else if (
+                      !all_nodes_valid(arg_list)   ||
+                      (arg_list.size() < 3)        ||
+                      ((arg_list.size() % 2) != 1)
+                    )
+            {
+               details::free_all_nodes(*node_allocator_,arg_list);
+
+               return error_node();
+            }
+            else if (is_constant_foldable(arg_list))
+               return const_optimise_switch(arg_list);
+
+            switch ((arg_list.size() - 1) / 2)
+            {
+               #define case_stmt(N)                                                 \
+               case N :                                                             \
+                  return node_allocator_->                                          \
+                            allocate<details::switch_n_node                         \
+                              <Type,typename switch_nodes::switch_##N> >(arg_list); \
+
+               case_stmt(1)
+               case_stmt(2)
+               case_stmt(3)
+               case_stmt(4)
+               case_stmt(5)
+               case_stmt(6)
+               case_stmt(7)
+               #undef case_stmt
+
+               default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
+            }
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            if (!all_nodes_valid(arg_list))
+            {
+               details::free_all_nodes(*node_allocator_,arg_list);
+
+               return error_node();
+            }
+            else if (is_constant_foldable(arg_list))
+               return const_optimise_mswitch(arg_list);
+            else
+               return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
+         }
+
+         #define unary_opr_switch_statements           \
+         case_stmt(details::  e_abs,details::  abs_op) \
+         case_stmt(details:: e_acos,details:: acos_op) \
+         case_stmt(details::e_acosh,details::acosh_op) \
+         case_stmt(details:: e_asin,details:: asin_op) \
+         case_stmt(details::e_asinh,details::asinh_op) \
+         case_stmt(details:: e_atan,details:: atan_op) \
+         case_stmt(details::e_atanh,details::atanh_op) \
+         case_stmt(details:: e_ceil,details:: ceil_op) \
+         case_stmt(details::  e_cos,details::  cos_op) \
+         case_stmt(details:: e_cosh,details:: cosh_op) \
+         case_stmt(details::  e_exp,details::  exp_op) \
+         case_stmt(details::e_expm1,details::expm1_op) \
+         case_stmt(details::e_floor,details::floor_op) \
+         case_stmt(details::  e_log,details::  log_op) \
+         case_stmt(details::e_log10,details::log10_op) \
+         case_stmt(details:: e_log2,details:: log2_op) \
+         case_stmt(details::e_log1p,details::log1p_op) \
+         case_stmt(details::  e_neg,details::  neg_op) \
+         case_stmt(details::  e_pos,details::  pos_op) \
+         case_stmt(details::e_round,details::round_op) \
+         case_stmt(details::  e_sin,details::  sin_op) \
+         case_stmt(details:: e_sinc,details:: sinc_op) \
+         case_stmt(details:: e_sinh,details:: sinh_op) \
+         case_stmt(details:: e_sqrt,details:: sqrt_op) \
+         case_stmt(details::  e_tan,details::  tan_op) \
+         case_stmt(details:: e_tanh,details:: tanh_op) \
+         case_stmt(details::  e_cot,details::  cot_op) \
+         case_stmt(details::  e_sec,details::  sec_op) \
+         case_stmt(details::  e_csc,details::  csc_op) \
+         case_stmt(details::  e_r2d,details::  r2d_op) \
+         case_stmt(details::  e_d2r,details::  d2r_op) \
+         case_stmt(details::  e_d2g,details::  d2g_op) \
+         case_stmt(details::  e_g2d,details::  g2d_op) \
+         case_stmt(details:: e_notl,details:: notl_op) \
+         case_stmt(details::  e_sgn,details::  sgn_op) \
+         case_stmt(details::  e_erf,details::  erf_op) \
+         case_stmt(details:: e_erfc,details:: erfc_op) \
+         case_stmt(details:: e_ncdf,details:: ncdf_op) \
+         case_stmt(details:: e_frac,details:: frac_op) \
+         case_stmt(details::e_trunc,details::trunc_op) \
+
+         inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation,
+                                                             expression_node_ptr (&branch)[1])
+         {
+            T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
+
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                          \
+               case op0 : return node_allocator_->                                                 \
+                             allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
+
+               unary_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation,
+                                                               expression_node_ptr (&branch)[1])
+         {
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                    \
+               case op0 : return node_allocator_->                                           \
+                             allocate<typename details::unary_vector_node<Type,op1<Type> > > \
+                                (operation,branch[0]);                                       \
+
+               unary_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation,
+                                                                expression_node_ptr (&branch)[1])
+         {
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                                \
+               case op0 : return node_allocator_->                                                       \
+                             allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
+
+               unary_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation,
+                                                       expression_node_ptr (&branch)[3])
+         {
+            expression_node_ptr temp_node = error_node();
+
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                  \
+               case op0 : temp_node = node_allocator_->                    \
+                             allocate<details::sf3_node<Type,op1<Type> > > \
+                                (operation,branch);                        \
+                          break;                                           \
+
+               case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
+               case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
+               case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
+               case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
+               case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
+               case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
+               case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
+               case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
+               case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
+               case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
+               case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
+               case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
+               case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
+               case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
+               case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
+               case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
+               case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
+               case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
+               case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
+               case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
+               case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
+               case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
+               case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
+               case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+
+            T v = temp_node->value();
+
+            details::free_node(*node_allocator_,temp_node);
+
+            return node_allocator_->allocate<literal_node_t>(v);
+         }
+
+         inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+         {
+            typedef details::variable_node<Type>* variable_ptr;
+
+            const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
+            const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
+            const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
+
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                          \
+               case op0 : return node_allocator_->                                 \
+                             allocate_rrr<details::sf3_var_node<Type,op1<Type> > > \
+                                (v0,v1,v2);                                        \
+
+               case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
+               case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
+               case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
+               case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
+               case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
+               case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
+               case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
+               case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
+               case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
+               case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
+               case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
+               case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
+               case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
+               case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
+               case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
+               case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
+               case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
+               case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
+               case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
+               case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
+               case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
+               case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
+               case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
+               case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
+         {
+            if (!all_nodes_valid(branch))
+               return error_node();
+            else if (is_constant_foldable(branch))
+               return const_optimise_sf3(operation,branch);
+            else if (all_nodes_variables(branch))
+               return varnode_optimise_sf3(operation,branch);
+            else
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                     \
+                  case op0 : return node_allocator_->                                            \
+                                allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); \
+
+                  case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
+                  case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
+                  case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
+                  case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
+                  case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
+                  case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
+                  case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
+                  case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
+                  case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
+                  case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
+                  case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
+                  case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
+                  case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
+                  case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
+                  case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
+                  case_stmt(details::e_sf30,details::sf30_op) case_stmt(details::e_sf31,details::sf31_op)
+                  case_stmt(details::e_sf32,details::sf32_op) case_stmt(details::e_sf33,details::sf33_op)
+                  case_stmt(details::e_sf34,details::sf34_op) case_stmt(details::e_sf35,details::sf35_op)
+                  case_stmt(details::e_sf36,details::sf36_op) case_stmt(details::e_sf37,details::sf37_op)
+                  case_stmt(details::e_sf38,details::sf38_op) case_stmt(details::e_sf39,details::sf39_op)
+                  case_stmt(details::e_sf40,details::sf40_op) case_stmt(details::e_sf41,details::sf41_op)
+                  case_stmt(details::e_sf42,details::sf42_op) case_stmt(details::e_sf43,details::sf43_op)
+                  case_stmt(details::e_sf44,details::sf44_op) case_stmt(details::e_sf45,details::sf45_op)
+                  case_stmt(details::e_sf46,details::sf46_op) case_stmt(details::e_sf47,details::sf47_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         }
+
+         inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+         {
+            expression_node_ptr temp_node = error_node();
+
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                                 \
+               case op0 : temp_node = node_allocator_->                                                   \
+                                         allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
+                          break;                                                                          \
+
+               case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
+               case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
+               case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
+               case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
+               case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
+               case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
+               case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
+               case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
+               case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
+               case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
+               case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
+               case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
+               case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
+               case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
+               case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
+               case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
+               case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
+               case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
+               case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
+               case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
+               case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
+               case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
+               case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
+               case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
+               case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
+               case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+
+            T v = temp_node->value();
+            details::free_node(*node_allocator_,temp_node);
+
+            return node_allocator_->allocate<literal_node_t>(v);
+         }
+
+         inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+         {
+            typedef details::variable_node<Type>* variable_ptr;
+
+            const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
+            const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
+            const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
+            const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
+
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                         \
+               case op0 : return node_allocator_->                                                \
+                             allocate_rrrr<details::sf4_var_node<Type,op1<Type> > >(v0,v1,v2,v3); \
+
+               case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
+               case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
+               case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
+               case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
+               case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
+               case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
+               case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
+               case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
+               case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
+               case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
+               case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
+               case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
+               case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
+               case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
+               case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
+               case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
+               case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
+               case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
+               case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
+               case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
+               case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
+               case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
+               case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
+               case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
+               case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
+               case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
+         {
+            if (!all_nodes_valid(branch))
+               return error_node();
+            else if (is_constant_foldable(branch))
+               return const_optimise_sf4(operation,branch);
+            else if (all_nodes_variables(branch))
+               return varnode_optimise_sf4(operation,branch);
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                     \
+               case op0 : return node_allocator_->                                            \
+                             allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); \
+
+               case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
+               case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
+               case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
+               case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
+               case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
+               case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
+               case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
+               case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
+               case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
+               case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
+               case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
+               case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
+               case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
+               case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
+               case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
+               case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
+               case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
+               case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
+               case_stmt(details::e_sf84,details::sf84_op) case_stmt(details::e_sf85,details::sf85_op)
+               case_stmt(details::e_sf86,details::sf86_op) case_stmt(details::e_sf87,details::sf87_op)
+               case_stmt(details::e_sf88,details::sf88_op) case_stmt(details::e_sf89,details::sf89_op)
+               case_stmt(details::e_sf90,details::sf90_op) case_stmt(details::e_sf91,details::sf91_op)
+               case_stmt(details::e_sf92,details::sf92_op) case_stmt(details::e_sf93,details::sf93_op)
+               case_stmt(details::e_sf94,details::sf94_op) case_stmt(details::e_sf95,details::sf95_op)
+               case_stmt(details::e_sf96,details::sf96_op) case_stmt(details::e_sf97,details::sf97_op)
+               case_stmt(details::e_sf98,details::sf98_op) case_stmt(details::e_sf99,details::sf99_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            expression_node_ptr temp_node = error_node();
+
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                 \
+               case op0 : temp_node = node_allocator_->                                   \
+                                         allocate<details::vararg_node<Type,op1<Type> > > \
+                                            (arg_list);                                   \
+                          break;                                                          \
+
+               case_stmt(details::e_sum,  details::vararg_add_op  )
+               case_stmt(details::e_prod, details::vararg_mul_op  )
+               case_stmt(details::e_avg,  details::vararg_avg_op  )
+               case_stmt(details::e_min,  details::vararg_min_op  )
+               case_stmt(details::e_max,  details::vararg_max_op  )
+               case_stmt(details::e_mand, details::vararg_mand_op )
+               case_stmt(details::e_mor,  details::vararg_mor_op  )
+               case_stmt(details::e_multi,details::vararg_multi_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+
+            T v = temp_node->value();
+            details::free_node(*node_allocator_,temp_node);
+
+            return node_allocator_->allocate<literal_node_t>(v);
+         }
+
+         inline bool special_one_parameter_vararg(const details::operator_type& operation)
+         {
+            return (
+                     (details::e_sum  == operation) ||
+                     (details::e_prod == operation) ||
+                     (details::e_avg  == operation) ||
+                     (details::e_min  == operation) ||
+                     (details::e_max  == operation)
+                   );
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                   \
+               case op0 : return node_allocator_->                                          \
+                             allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
+
+               case_stmt(details::e_sum,  details::vararg_add_op  )
+               case_stmt(details::e_prod, details::vararg_mul_op  )
+               case_stmt(details::e_avg,  details::vararg_avg_op  )
+               case_stmt(details::e_min,  details::vararg_min_op  )
+               case_stmt(details::e_max,  details::vararg_max_op  )
+               case_stmt(details::e_mand, details::vararg_mand_op )
+               case_stmt(details::e_mor,  details::vararg_mor_op  )
+               case_stmt(details::e_multi,details::vararg_multi_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            if (1 == arg_list.size())
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                      \
+                  case op0 : return node_allocator_->                                             \
+                                allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
+
+                  case_stmt(details::e_sum,  details::vec_add_op)
+                  case_stmt(details::e_prod, details::vec_mul_op)
+                  case_stmt(details::e_avg,  details::vec_avg_op)
+                  case_stmt(details::e_min,  details::vec_min_op)
+                  case_stmt(details::e_max,  details::vec_max_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else
+               return error_node();
+         }
+
+         template <typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
+         {
+            if (!all_nodes_valid(arg_list))
+            {
+               details::free_all_nodes(*node_allocator_,arg_list);
+
+               return error_node();
+            }
+            else if (is_constant_foldable(arg_list))
+               return const_optimise_varargfunc(operation,arg_list);
+            else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
+               return vectorize_func(operation,arg_list);
+            else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
+               return arg_list[0];
+            else if (all_nodes_variables(arg_list))
+               return varnode_optimise_varargfunc(operation,arg_list);
+
+            switch (operation)
+            {
+               #define case_stmt(op0,op1)                                                \
+               case op0 : return node_allocator_->                                       \
+                             allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
+
+               case_stmt(details::e_sum,  details::vararg_add_op  )
+               case_stmt(details::e_prod, details::vararg_mul_op  )
+               case_stmt(details::e_avg,  details::vararg_avg_op  )
+               case_stmt(details::e_min,  details::vararg_min_op  )
+               case_stmt(details::e_max,  details::vararg_max_op  )
+               case_stmt(details::e_mand, details::vararg_mand_op )
+               case_stmt(details::e_mor,  details::vararg_mor_op  )
+               case_stmt(details::e_multi,details::vararg_multi_op)
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         template <std::size_t N>
+         inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
+         {
+            typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
+            expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
+
+            if (0 == result)
+               return error_node();
+            else
+            {
+               // Can the function call be completely optimised?
+               if (details::is_constant_node(result))
+                  return result;
+               else if (!all_nodes_valid(b))
+                  return error_node();
+               else if (N != f->param_count)
+               {
+                  details::free_all_nodes(*node_allocator_,b);
+
+                  return error_node();
+               }
+
+               function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
+
+               if (func_node_ptr->init_branches(b))
+                  return result;
+               else
+               {
+                  details::free_all_nodes(*node_allocator_,b);
+
+                  return error_node();
+               }
+            }
+         }
+
+         inline expression_node_ptr function(ifunction_t* f)
+         {
+            typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
+            return node_allocator_->allocate<function_N_node_t>(f);
+         }
+
+         inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf,
+                                                         std::vector<expression_node_ptr>& arg_list)
+         {
+            if (!all_nodes_valid(arg_list))
+            {
+               details::free_all_nodes(*node_allocator_,arg_list);
+
+               return error_node();
+            }
+
+            typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type;
+
+            expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
+
+            if (
+                 !arg_list.empty()        &&
+                 !vaf->has_side_effects() &&
+                 is_constant_foldable(arg_list)
+               )
+            {
+               Type v = result->value();
+               details::free_node(*node_allocator_,result);
+               result = node_allocator_->allocate<literal_node_t>(v);
+            }
+
+            parser_->state_.activate_side_effect("vararg_function_call()");
+
+            return result;
+         }
+
+         inline expression_node_ptr generic_function_call(igeneric_function_t* gf,
+                                                          std::vector<expression_node_ptr>& arg_list,
+                                                          const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
+         {
+            if (!all_nodes_valid(arg_list))
+            {
+               details::free_all_nodes(*node_allocator_,arg_list);
+               return error_node();
+            }
+
+            typedef details::generic_function_node     <Type,igeneric_function_t> alloc_type1;
+            typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2;
+
+            const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
+
+            expression_node_ptr result = error_node();
+
+            if (no_psi == param_seq_index)
+               result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
+            else
+               result = node_allocator_->allocate<alloc_type2>(gf,param_seq_index,arg_list);
+
+            alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
+
+            if (
+                 !arg_list.empty()       &&
+                 !gf->has_side_effects() &&
+                 is_constant_foldable(arg_list)
+               )
+            {
+               genfunc_node_ptr->init_branches();
+               Type v = result->value();
+               details::free_node(*node_allocator_,result);
+               return node_allocator_->allocate<literal_node_t>(v);
+            }
+            else if (genfunc_node_ptr->init_branches())
+            {
+               parser_->state_.activate_side_effect("generic_function_call()");
+               return result;
+            }
+            else
+            {
+               details::free_node(*node_allocator_,result);
+               details::free_all_nodes(*node_allocator_,arg_list);
+               return error_node();
+            }
+         }
+
+         inline expression_node_ptr string_function_call(igeneric_function_t* gf,
+                                                         std::vector<expression_node_ptr>& arg_list,
+                                                         const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
+         {
+            if (!all_nodes_valid(arg_list))
+            {
+               details::free_all_nodes(*node_allocator_,arg_list);
+               return error_node();
+            }
+
+            typedef details::string_function_node      <Type,igeneric_function_t> alloc_type1;
+            typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2;
+
+            const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
+
+            expression_node_ptr result = error_node();
+
+            if (no_psi == param_seq_index)
+               result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
+            else
+               result = node_allocator_->allocate<alloc_type2>(gf,param_seq_index,arg_list);
+
+            alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
+
+            if (
+                 !arg_list.empty()       &&
+                 !gf->has_side_effects() &&
+                 is_constant_foldable(arg_list)
+               )
+            {
+               strfunc_node_ptr->init_branches();
+
+               Type v = result->value();
+
+               details::free_node(*node_allocator_,result);
+
+               return node_allocator_->allocate<literal_node_t>(v);
+            }
+            else if (strfunc_node_ptr->init_branches())
+            {
+               parser_->state_.activate_side_effect("string_function_call()");
+
+               return result;
+            }
+            else
+            {
+               details::free_node(*node_allocator_,result);
+               details::free_all_nodes(*node_allocator_,arg_list);
+
+               return error_node();
+            }
+         }
+
+         inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
+         {
+            if (!all_nodes_valid(arg_list))
+            {
+               details::free_all_nodes(*node_allocator_,arg_list);
+               return error_node();
+            }
+
+            typedef details::return_node<Type> alloc_type;
+
+            expression_node_ptr result = node_allocator_->
+                                            allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
+
+            alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
+
+            if (return_node_ptr->init_branches())
+            {
+               parser_->state_.activate_side_effect("return_call()");
+
+               return result;
+            }
+            else
+            {
+               details::free_node(*node_allocator_,result);
+               details::free_all_nodes(*node_allocator_,arg_list);
+
+               return error_node();
+            }
+         }
+
+         inline expression_node_ptr return_envelope(expression_node_ptr body,
+                                                    results_context_t* rc,
+                                                    bool*& return_invoked)
+         {
+            typedef details::return_envelope_node<Type> alloc_type;
+
+            expression_node_ptr result = node_allocator_->
+                                            allocate_cr<alloc_type>(body,(*rc));
+
+            return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
+
+            return result;
+         }
+
+         inline expression_node_ptr vector_element(const std::string& symbol,
+                                                   vector_holder_ptr vector_base,
+                                                   expression_node_ptr index)
+         {
+            expression_node_ptr result = error_node();
+
+            if (details::is_constant_node(index))
+            {
+               std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
+
+               details::free_node(*node_allocator_,index);
+
+               Type* v = (*vector_base)[i];
+
+               scope_element& se = parser_->sem_.get_element(symbol,i);
+
+               if (se.index == i)
+               {
+                  result = se.var_node;
+               }
+               else
+               {
+                  scope_element nse;
+                  nse.name      = symbol;
+                  nse.active    = true;
+                  nse.ref_count = 1;
+                  nse.type      = scope_element::e_vecelem;
+                  nse.index     = i;
+                  nse.depth     = parser_->state_.scope_depth;
+                  nse.data      = 0;
+                  nse.var_node  = new variable_node_t((*v));
+
+                  if (!parser_->sem_.add_element(nse))
+                  {
+                     parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
+
+                     parser_->sem_.free_element(nse);
+
+                     result = error_node();
+                  }
+
+                  exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
+
+                  parser_->state_.activate_side_effect("vector_element()");
+
+                  result = nse.var_node;
+               }
+            }
+            else
+               result = node_allocator_->allocate<details::vector_elem_node<Type> >(index,vector_base);
+
+            return result;
+         }
+
+      private:
+
+         template <std::size_t N, typename NodePtr>
+         inline bool is_constant_foldable(NodePtr (&b)[N]) const
+         {
+            for (std::size_t i = 0; i < N; ++i)
+            {
+               if (0 == b[i])
+                  return false;
+               else if (!details::is_constant_node(b[i]))
+                  return false;
+            }
+
+            return true;
+         }
+
+         template <typename NodePtr,
+                   typename Allocator,
+                   template <typename,typename> class Sequence>
+         inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
+         {
+            for (std::size_t i = 0; i < b.size(); ++i)
+            {
+               if (0 == b[i])
+                  return false;
+               else if (!details::is_constant_node(b[i]))
+                  return false;
+            }
+
+            return true;
+         }
+
+         void lodge_assignment(symbol_type cst, expression_node_ptr node)
+         {
+            parser_->state_.activate_side_effect("lodge_assignment()");
+
+            if (!parser_->dec_.collect_assignments())
+               return;
+
+            std::string symbol_name;
+
+            switch (cst)
+            {
+               case e_st_variable : symbol_name = parser_->symtab_store_
+                                                     .get_variable_name(node);
+                                    break;
+
+               #ifndef exprtk_disable_string_capabilities
+               case e_st_string   : symbol_name = parser_->symtab_store_
+                                                     .get_stringvar_name(node);
+                                    break;
+               #endif
+
+               case e_st_vector   : {
+                                       typedef details::vector_holder<T> vector_holder_t;
+
+                                       vector_holder_t& vh = static_cast<vector_node_t*>(node)->ref();
+
+                                       symbol_name = parser_->symtab_store_.get_vector_name(&vh);
+                                    }
+                                    break;
+
+               case e_st_vecelem   : {
+                                       typedef details::vector_holder<T> vector_holder_t;
+
+                                       vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
+
+                                       symbol_name = parser_->symtab_store_.get_vector_name(&vh);
+
+                                       cst = e_st_vector;
+                                    }
+                                    break;
+
+               default            : return;
+            }
+
+            if (!symbol_name.empty())
+            {
+               parser_->dec_.add_assignment(symbol_name,cst);
+            }
+         }
+
+         inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            if (details::is_variable_node(branch[0]))
+            {
+               lodge_assignment(e_st_variable,branch[0]);
+
+               return synthesize_expression<assignment_node_t,2>(operation,branch);
+            }
+            else if (details::is_vector_elem_node(branch[0]))
+            {
+               lodge_assignment(e_st_vecelem,branch[0]);
+
+               return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
+            }
+            #ifndef exprtk_disable_string_capabilities
+            else if (details::is_string_node(branch[0]))
+            {
+               lodge_assignment(e_st_string,branch[0]);
+
+               return synthesize_expression<assignment_string_node_t,2>(operation,branch);
+            }
+            else if (details::is_string_range_node(branch[0]))
+            {
+               lodge_assignment(e_st_string,branch[0]);
+
+               return synthesize_expression<assignment_string_range_node_t,2>(operation,branch);
+            }
+            #endif
+            else if (details::is_vector_node(branch[0]))
+            {
+               lodge_assignment(e_st_vector,branch[0]);
+
+               if (details::is_ivector_node(branch[1]))
+                  return synthesize_expression<assignment_vecvec_node_t,2>(operation,branch);
+              else
+                  return synthesize_expression<assignment_vec_node_t,2>(operation,branch);
+            }
+            else
+            {
+               parser_->set_synthesis_error("Invalid assignment operation.[1]");
+
+               return error_node();
+            }
+         }
+
+         inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation,
+                                                                               expression_node_ptr (&branch)[2])
+         {
+            if (details::is_variable_node(branch[0]))
+            {
+               lodge_assignment(e_st_variable,branch[0]);
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                  \
+                  case op0 : return node_allocator_->                                                         \
+                                template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
+                                   (operation,branch[0],branch[1]);                                           \
+
+                  case_stmt(details::e_addass,details::add_op)
+                  case_stmt(details::e_subass,details::sub_op)
+                  case_stmt(details::e_mulass,details::mul_op)
+                  case_stmt(details::e_divass,details::div_op)
+                  case_stmt(details::e_modass,details::mod_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (details::is_vector_elem_node(branch[0]))
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                            \
+                  case op0 : return node_allocator_->                                                                   \
+                                 template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
+                                    (operation,branch[0],branch[1]);                                                    \
+
+                  case_stmt(details::e_addass,details::add_op)
+                  case_stmt(details::e_subass,details::sub_op)
+                  case_stmt(details::e_mulass,details::mul_op)
+                  case_stmt(details::e_divass,details::div_op)
+                  case_stmt(details::e_modass,details::mod_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (details::is_vector_node(branch[0]))
+            {
+               lodge_assignment(e_st_vector,branch[0]);
+
+               if (details::is_ivector_node(branch[1]))
+               {
+                  switch (operation)
+                  {
+                     #define case_stmt(op0,op1)                                                                         \
+                     case op0 : return node_allocator_->                                                                \
+                                   template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
+                                      (operation,branch[0],branch[1]);                                                  \
+
+                     case_stmt(details::e_addass,details::add_op)
+                     case_stmt(details::e_subass,details::sub_op)
+                     case_stmt(details::e_mulass,details::mul_op)
+                     case_stmt(details::e_divass,details::div_op)
+                     case_stmt(details::e_modass,details::mod_op)
+                     #undef case_stmt
+                     default : return error_node();
+                  }
+               }
+               else
+               {
+                  switch (operation)
+                  {
+                     #define case_stmt(op0,op1)                                                                      \
+                     case op0 : return node_allocator_->                                                             \
+                                   template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
+                                      (operation,branch[0],branch[1]);                                               \
+
+                     case_stmt(details::e_addass,details::add_op)
+                     case_stmt(details::e_subass,details::sub_op)
+                     case_stmt(details::e_mulass,details::mul_op)
+                     case_stmt(details::e_divass,details::div_op)
+                     case_stmt(details::e_modass,details::mod_op)
+                     #undef case_stmt
+                     default : return error_node();
+                  }
+               }
+            }
+            #ifndef exprtk_disable_string_capabilities
+            else if (
+                      (details::e_addass == operation) &&
+                      details::is_string_node(branch[0])
+                    )
+            {
+               typedef details::assignment_string_node<T,details::asn_addassignment> addass_t;
+
+               lodge_assignment(e_st_string,branch[0]);
+
+               return synthesize_expression<addass_t,2>(operation,branch);
+            }
+            #endif
+            else
+            {
+               parser_->set_synthesis_error("Invalid assignment operation[2]");
+
+               return error_node();
+            }
+         }
+
+         inline expression_node_ptr synthesize_veceqineq_operation_expression(const details::operator_type& operation,
+                                                                              expression_node_ptr (&branch)[2])
+         {
+            const bool is_b0_ivec = details::is_ivector_node(branch[0]);
+            const bool is_b1_ivec = details::is_ivector_node(branch[1]);
+
+            if (is_b0_ivec && is_b1_ivec)
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                  \
+                  case op0 : return node_allocator_->                                                         \
+                                template allocate_rrr<typename details::eqineq_vecvec_node<Type,op1<Type> > > \
+                                   (operation,branch[0],branch[1]);                                           \
+
+                  case_stmt(details::  e_lt,details::  lt_op)
+                  case_stmt(details:: e_lte,details:: lte_op)
+                  case_stmt(details::  e_gt,details::  gt_op)
+                  case_stmt(details:: e_gte,details:: gte_op)
+                  case_stmt(details::  e_eq,details::  eq_op)
+                  case_stmt(details::  e_ne,details::  ne_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (is_b0_ivec && !is_b1_ivec)
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                  \
+                  case op0 : return node_allocator_->                                                         \
+                                template allocate_rrr<typename details::eqineq_vecval_node<Type,op1<Type> > > \
+                                   (operation,branch[0],branch[1]);                                           \
+
+                  case_stmt(details::  e_lt,details::  lt_op)
+                  case_stmt(details:: e_lte,details:: lte_op)
+                  case_stmt(details::  e_gt,details::  gt_op)
+                  case_stmt(details:: e_gte,details:: gte_op)
+                  case_stmt(details::  e_eq,details::  eq_op)
+                  case_stmt(details::  e_ne,details::  ne_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (!is_b0_ivec && is_b1_ivec)
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                  \
+                  case op0 : return node_allocator_->                                                         \
+                                template allocate_rrr<typename details::eqineq_valvec_node<Type,op1<Type> > > \
+                                   (operation,branch[0],branch[1]);                                           \
+
+                  case_stmt(details::  e_lt,details::  lt_op)
+                  case_stmt(details:: e_lte,details:: lte_op)
+                  case_stmt(details::  e_gt,details::  gt_op)
+                  case_stmt(details:: e_gte,details:: gte_op)
+                  case_stmt(details::  e_eq,details::  eq_op)
+                  case_stmt(details::  e_ne,details::  ne_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else
+               return error_node();
+         }
+
+         inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation,
+                                                                                  expression_node_ptr (&branch)[2])
+         {
+            const bool is_b0_ivec = details::is_ivector_node(branch[0]);
+            const bool is_b1_ivec = details::is_ivector_node(branch[1]);
+
+            #define vector_ops                        \
+            case_stmt(details::e_add,details::add_op) \
+            case_stmt(details::e_sub,details::sub_op) \
+            case_stmt(details::e_mul,details::mul_op) \
+            case_stmt(details::e_div,details::div_op) \
+            case_stmt(details::e_mod,details::mod_op) \
+
+            if (is_b0_ivec && is_b1_ivec)
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                    \
+                  case op0 : return node_allocator_->                                                           \
+                                template allocate_rrr<typename details::vecarith_vecvec_node<Type,op1<Type> > > \
+                                   (operation,branch[0],branch[1]);                                             \
+
+                  vector_ops
+                  case_stmt(details::e_pow,details:: pow_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (is_b0_ivec && !is_b1_ivec)
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                    \
+                  case op0 : return node_allocator_->                                                           \
+                                template allocate_rrr<typename details::vecarith_vecval_node<Type,op1<Type> > > \
+                                   (operation,branch[0],branch[1]);                                             \
+
+                  vector_ops
+                  case_stmt(details::e_pow,details:: pow_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else if (!is_b0_ivec && is_b1_ivec)
+            {
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                                    \
+                  case op0 : return node_allocator_->                                                           \
+                                template allocate_rrr<typename details::vecarith_valvec_node<Type,op1<Type> > > \
+                                   (operation,branch[0],branch[1]);                                             \
+
+                  vector_ops
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+            else
+               return error_node();
+
+            #undef vector_ops
+         }
+
+         inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2])
+         {
+            const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
+            const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
+
+            const bool v0_is_ivec = details::is_ivector_node(branch[0]);
+            const bool v1_is_ivec = details::is_ivector_node(branch[1]);
+
+            #ifndef exprtk_disable_string_capabilities
+            const bool v0_is_str = details::is_generally_string_node(branch[0]);
+            const bool v1_is_str = details::is_generally_string_node(branch[1]);
+            #endif
+
+            expression_node_ptr result = error_node();
+
+            if (v0_is_ivar && v1_is_ivar)
+            {
+               typedef details::variable_node<T>* variable_node_ptr;
+
+               variable_node_ptr v0 = variable_node_ptr(0);
+               variable_node_ptr v1 = variable_node_ptr(0);
+
+               if (
+                    (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
+                    (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
+                  )
+               {
+                  result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
+               }
+               else
+                  result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
+            }
+            else if (v0_is_ivec && v1_is_ivec)
+            {
+               result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
+            }
+            #ifndef exprtk_disable_string_capabilities
+            else if (v0_is_str && v1_is_str)
+            {
+               result = node_allocator_->allocate<details::swap_string_node<T> >(branch[0],branch[1]);
+            }
+            #endif
+            else
+            {
+               parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
+
+               return error_node();
+            }
+
+            parser_->state_.activate_side_effect("synthesize_swap_expression()");
+
+            return result;
+         }
+
+         #ifndef exprtk_disable_sc_andor
+         inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            expression_node_ptr result = error_node();
+
+            if (details::is_constant_node(branch[0]))
+            {
+               if (
+                    (details::e_scand == operation) &&
+                    std::equal_to<T>()(T(0),branch[0]->value())
+                  )
+                  result = node_allocator_->allocate_c<literal_node_t>(T(0));
+               else if (
+                         (details::e_scor == operation) &&
+                         std::not_equal_to<T>()(T(0),branch[0]->value())
+                       )
+                  result = node_allocator_->allocate_c<literal_node_t>(T(1));
+            }
+
+            if (details::is_constant_node(branch[1]) && (0 == result))
+            {
+               if (
+                    (details::e_scand == operation) &&
+                    std::equal_to<T>()(T(0),branch[1]->value())
+                  )
+                  result = node_allocator_->allocate_c<literal_node_t>(T(0));
+               else if (
+                         (details::e_scor == operation) &&
+                         std::not_equal_to<T>()(T(0),branch[1]->value())
+                       )
+                  result = node_allocator_->allocate_c<literal_node_t>(T(1));
+            }
+
+            if (result)
+            {
+               free_node(*node_allocator_,branch[0]);
+               free_node(*node_allocator_,branch[1]);
+
+               return result;
+            }
+            else if (details::e_scand == operation)
+               return synthesize_expression<scand_node_t,2>(operation,branch);
+            else if (details::e_scor == operation)
+               return synthesize_expression<scor_node_t,2>(operation,branch);
+            else
+               return error_node();
+         }
+         #else
+         inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
+         {
+            return error_node();
+         }
+         #endif
+
+         #define basic_opr_switch_statements       \
+         case_stmt(details::e_add,details::add_op) \
+         case_stmt(details::e_sub,details::sub_op) \
+         case_stmt(details::e_mul,details::mul_op) \
+         case_stmt(details::e_div,details::div_op) \
+         case_stmt(details::e_mod,details::mod_op) \
+         case_stmt(details::e_pow,details::pow_op) \
+
+         #define extended_opr_switch_statements      \
+         case_stmt(details::  e_lt,details::  lt_op) \
+         case_stmt(details:: e_lte,details:: lte_op) \
+         case_stmt(details::  e_gt,details::  gt_op) \
+         case_stmt(details:: e_gte,details:: gte_op) \
+         case_stmt(details::  e_eq,details::  eq_op) \
+         case_stmt(details::  e_ne,details::  ne_op) \
+         case_stmt(details:: e_and,details:: and_op) \
+         case_stmt(details::e_nand,details::nand_op) \
+         case_stmt(details::  e_or,details::  or_op) \
+         case_stmt(details:: e_nor,details:: nor_op) \
+         case_stmt(details:: e_xor,details:: xor_op) \
+         case_stmt(details::e_xnor,details::xnor_op) \
+
+         #ifndef exprtk_disable_cardinal_pow_optimisation
+         template <typename TType, template <typename,typename> class IPowNode>
+         inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
+         {
+            switch (p)
+            {
+               #define case_stmt(cp)                                                     \
+               case cp : return node_allocator_->                                        \
+                            allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
+
+               case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
+               case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
+               case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
+               case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
+               case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
+               case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
+               case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
+               case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
+               case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
+               case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
+               case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
+               case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
+               case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
+               case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
+               case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
+         {
+            const bool not_recipricol = (c >= T(0));
+            const int p = details::numeric::to_int32(details::numeric::abs(c));
+
+            if (0 == p)
+               return node_allocator_->allocate_c<literal_node_t>(T(1));
+            else if (std::equal_to<T>()(T(2),c))
+            {
+               return node_allocator_->
+                  template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
+            }
+            else
+            {
+               if (not_recipricol)
+                  return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
+               else
+                  return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
+            }
+         }
+
+         inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c)
+         {
+            return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
+         }
+
+         inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2])
+         {
+            const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+            const bool not_recipricol = (c >= T(0));
+            const int p = details::numeric::to_int32(details::numeric::abs(c));
+
+            node_allocator_->free(branch[1]);
+
+            if (0 == p)
+            {
+               details::free_all_nodes(*node_allocator_, branch);
+               return node_allocator_->allocate_c<literal_node_t>(T(1));
+            }
+            else if (not_recipricol)
+               return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
+            else
+               return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
+         }
+         #else
+         inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
+         {
+            return error_node();
+         }
+
+         inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
+         {
+            return false;
+         }
+
+         inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
+         {
+            return error_node();
+         }
+         #endif
+
+         struct synthesize_binary_ext_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const bool left_neg  = is_neg_unary_node(branch[0]);
+               const bool right_neg = is_neg_unary_node(branch[1]);
+
+               if (left_neg && right_neg)
+               {
+                  if (
+                       (details::e_add == operation) ||
+                       (details::e_sub == operation) ||
+                       (details::e_mul == operation) ||
+                       (details::e_div == operation)
+                     )
+                  {
+                     if (
+                          !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
+                          !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
+                        )
+                     {
+                        details::free_all_nodes(*expr_gen.node_allocator_,branch);
+
+                        return error_node();
+                     }
+                  }
+
+                  switch (operation)
+                  {
+                                           // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
+                     case details::e_add : return expr_gen(details::e_neg,
+                                              expr_gen.node_allocator_->
+                                                 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
+                                                    (branch[0],branch[1]));
+
+                                           // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
+                     case details::e_sub : return expr_gen.node_allocator_->
+                                              template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
+                                                 (branch[1],branch[0]);
+
+                     default             : break;
+                  }
+               }
+               else if (left_neg && !right_neg)
+               {
+                  if (
+                       (details::e_add == operation) ||
+                       (details::e_sub == operation) ||
+                       (details::e_mul == operation) ||
+                       (details::e_div == operation)
+                     )
+                  {
+                     if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
+                     {
+                        details::free_all_nodes(*expr_gen.node_allocator_,branch);
+
+                        return error_node();
+                     }
+
+                     switch (operation)
+                     {
+                                              // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
+                        case details::e_add : return expr_gen.node_allocator_->
+                                                 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
+                                                   (branch[1],branch[0]);
+
+                                              // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
+                        case details::e_sub : return expr_gen(details::e_neg,
+                                                 expr_gen.node_allocator_->
+                                                    template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
+                                                       (branch[0],branch[1]));
+
+                                              // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
+                        case details::e_mul : return expr_gen(details::e_neg,
+                                                 expr_gen.node_allocator_->
+                                                    template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
+                                                       (branch[0],branch[1]));
+
+                                              // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
+                        case details::e_div : return expr_gen(details::e_neg,
+                                                 expr_gen.node_allocator_->
+                                                    template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
+                                                       (branch[0],branch[1]));
+
+                        default             : return error_node();
+                     }
+                  }
+               }
+               else if (!left_neg && right_neg)
+               {
+                  if (
+                       (details::e_add == operation) ||
+                       (details::e_sub == operation) ||
+                       (details::e_mul == operation) ||
+                       (details::e_div == operation)
+                     )
+                  {
+                     if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
+                     {
+                        details::free_all_nodes(*expr_gen.node_allocator_,branch);
+
+                        return error_node();
+                     }
+
+                     switch (operation)
+                     {
+                                              // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1)
+                        case details::e_add : return expr_gen.node_allocator_->
+                                                 template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
+                                                   (branch[0],branch[1]);
+
+                                              // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
+                        case details::e_sub : return expr_gen.node_allocator_->
+                                                 template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
+                                                   (branch[0],branch[1]);
+
+                                              // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
+                        case details::e_mul : return expr_gen(details::e_neg,
+                                                 expr_gen.node_allocator_->
+                                                    template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
+                                                       (branch[0],branch[1]));
+
+                                              // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
+                        case details::e_div : return expr_gen(details::e_neg,
+                                                 expr_gen.node_allocator_->
+                                                    template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
+                                                       (branch[0],branch[1]));
+
+                        default             : return error_node();
+                     }
+                  }
+               }
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                           \
+                  case op0 : return expr_gen.node_allocator_->                                         \
+                                template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
+                                   (branch[0],branch[1]);                                              \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_vob_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+
+               #ifndef exprtk_disable_enhanced_features
+               if (details::is_sf3ext_node(branch[1]))
+               {
+                  expression_node_ptr result = error_node();
+
+                  if (synthesize_sf4ext_expression::template compile_right<vtype>(expr_gen,v,operation,branch[1],result))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+                     return result;
+                  }
+               }
+               #endif
+
+               if (
+                    (details::e_mul == operation) ||
+                    (details::e_div == operation)
+                  )
+               {
+                  if (details::is_uv_node(branch[1]))
+                  {
+                     typedef details::uv_base_node<Type>* uvbn_ptr_t;
+
+                     details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
+
+                     if (details::e_neg == o)
+                     {
+                        const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
+
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+
+                        switch (operation)
+                        {
+                           case details::e_mul : return expr_gen(details::e_neg,
+                                                    expr_gen.node_allocator_->
+                                                       template allocate_rr<typename details::
+                                                          vov_node<Type,details::mul_op<Type> > >(v,v1));
+
+                           case details::e_div : return expr_gen(details::e_neg,
+                                                    expr_gen.node_allocator_->
+                                                       template allocate_rr<typename details::
+                                                          vov_node<Type,details::div_op<Type> > >(v,v1));
+
+                           default             : break;
+                        }
+                     }
+                  }
+               }
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                       \
+                  case op0 : return expr_gen.node_allocator_->                                     \
+                                template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
+                                   (v,branch[1]);                                                  \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_bov_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+
+               #ifndef exprtk_disable_enhanced_features
+               if (details::is_sf3ext_node(branch[0]))
+               {
+                  expression_node_ptr result = error_node();
+
+                  if (synthesize_sf4ext_expression::template compile_left<vtype>(expr_gen,v,operation,branch[0],result))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+                     return result;
+                  }
+               }
+               #endif
+
+               if (
+                    (details::e_add == operation) ||
+                    (details::e_sub == operation) ||
+                    (details::e_mul == operation) ||
+                    (details::e_div == operation)
+                  )
+               {
+                  if (details::is_uv_node(branch[0]))
+                  {
+                     typedef details::uv_base_node<Type>* uvbn_ptr_t;
+
+                     details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
+
+                     if (details::e_neg == o)
+                     {
+                        const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
+
+                        free_node(*expr_gen.node_allocator_,branch[0]);
+
+                        switch (operation)
+                        {
+                           case details::e_add : return expr_gen.node_allocator_->
+                                                    template allocate_rr<typename details::
+                                                       vov_node<Type,details::sub_op<Type> > >(v,v0);
+
+                           case details::e_sub : return expr_gen(details::e_neg,
+                                                    expr_gen.node_allocator_->
+                                                       template allocate_rr<typename details::
+                                                          vov_node<Type,details::add_op<Type> > >(v0,v));
+
+                           case details::e_mul : return expr_gen(details::e_neg,
+                                                    expr_gen.node_allocator_->
+                                                       template allocate_rr<typename details::
+                                                          vov_node<Type,details::mul_op<Type> > >(v0,v));
+
+                           case details::e_div : return expr_gen(details::e_neg,
+                                                    expr_gen.node_allocator_->
+                                                       template allocate_rr<typename details::
+                                                          vov_node<Type,details::div_op<Type> > >(v0,v));
+                           default : break;
+                        }
+                     }
+                  }
+               }
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                       \
+                  case op0 : return expr_gen.node_allocator_->                                     \
+                                template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
+                                   (branch[0],v);                                                  \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_cob_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+
+               free_node(*expr_gen.node_allocator_,branch[0]);
+
+               if ((T(0) == c) && (details::e_mul == operation))
+               {
+                  free_node(*expr_gen.node_allocator_,branch[1]);
+
+                  return expr_gen(T(0));
+               }
+               else if ((T(0) == c) && (details::e_div == operation))
+               {
+                  free_node(*expr_gen.node_allocator_, branch[1]);
+
+                  return expr_gen(T(0));
+               }
+               else if ((T(0) == c) && (details::e_add == operation))
+                  return branch[1];
+               else if ((T(1) == c) && (details::e_mul == operation))
+                  return branch[1];
+
+               if (details::is_cob_node(branch[1]))
+               {
+                  // Simplify expressions of the form:
+                  // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
+                  // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
+                  if (
+                       (operation == details::e_mul) ||
+                       (operation == details::e_add)
+                     )
+                  {
+                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+
+                     if (operation == cobnode->operation())
+                     {
+                        switch (operation)
+                        {
+                           case details::e_add : cobnode->set_c(c + cobnode->c()); break;
+                           case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
+                           default             : return error_node();
+                        }
+
+                        return cobnode;
+                     }
+                  }
+
+                  if (operation == details::e_mul)
+                  {
+                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+                     details::operator_type cob_opr = cobnode->operation();
+
+                     if (
+                          (details::e_div == cob_opr) ||
+                          (details::e_mul == cob_opr)
+                        )
+                     {
+                        switch (cob_opr)
+                        {
+                           case details::e_div : cobnode->set_c(c * cobnode->c()); break;
+                           case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
+                           default             : return error_node();
+                        }
+
+                        return cobnode;
+                     }
+                  }
+                  else if (operation == details::e_div)
+                  {
+                     details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+                     details::operator_type cob_opr = cobnode->operation();
+
+                     if (
+                          (details::e_div == cob_opr) ||
+                          (details::e_mul == cob_opr)
+                        )
+                     {
+                        details::expression_node<Type>* new_cobnode = error_node();
+
+                        switch (cob_opr)
+                        {
+                           case details::e_div : new_cobnode = expr_gen.node_allocator_->
+                                                    template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
+                                                       (c / cobnode->c(),cobnode->move_branch(0));
+                                                 break;
+
+                           case details::e_mul : new_cobnode = expr_gen.node_allocator_->
+                                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                                       (c / cobnode->c(),cobnode->move_branch(0));
+                                                 break;
+
+                           default             : return error_node();
+                        }
+
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+
+                        return new_cobnode;
+                     }
+                  }
+               }
+               #ifndef exprtk_disable_enhanced_features
+               else if (details::is_sf3ext_node(branch[1]))
+               {
+                  expression_node_ptr result = error_node();
+
+                  if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+
+                     return result;
+                  }
+               }
+               #endif
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                       \
+                  case op0 : return expr_gen.node_allocator_->                                     \
+                                template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
+                                   (c,branch[1]);                                                  \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_boc_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               if ((T(0) == c) && (details::e_mul == operation))
+               {
+                  free_node(*expr_gen.node_allocator_,branch[0]);
+
+                  return expr_gen(T(0));
+               }
+               else if ((T(0) == c) && (details::e_div == operation))
+               {
+                  free_node(*expr_gen.node_allocator_, branch[0]);
+
+                  return expr_gen(std::numeric_limits<T>::quiet_NaN());
+               }
+               else if ((T(0) == c) && (details::e_add == operation))
+                  return branch[0];
+               else if ((T(1) == c) && (details::e_mul == operation))
+                  return branch[0];
+
+               if (details::is_boc_node(branch[0]))
+               {
+                  // Simplify expressions of the form:
+                  // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
+                  // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
+                  if (
+                       (operation == details::e_mul) ||
+                       (operation == details::e_add)
+                     )
+                  {
+                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+
+                     if (operation == bocnode->operation())
+                     {
+                        switch (operation)
+                        {
+                           case details::e_add : bocnode->set_c(c + bocnode->c()); break;
+                           case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
+                           default             : return error_node();
+                        }
+
+                        return bocnode;
+                     }
+                  }
+                  else if (operation == details::e_div)
+                  {
+                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+                     details::operator_type boc_opr = bocnode->operation();
+
+                     if (
+                          (details::e_div == boc_opr) ||
+                          (details::e_mul == boc_opr)
+                        )
+                     {
+                        switch (boc_opr)
+                        {
+                           case details::e_div : bocnode->set_c(c * bocnode->c()); break;
+                           case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
+                           default             : return error_node();
+                        }
+
+                        return bocnode;
+                     }
+                  }
+                  else if (operation == details::e_pow)
+                  {
+                     // (v ^ c0) ^ c1 --> v ^(c0 * c1)
+                     details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+                     details::operator_type boc_opr = bocnode->operation();
+
+                     if (details::e_pow == boc_opr)
+                     {
+                        bocnode->set_c(bocnode->c() * c);
+                        return bocnode;
+                     }
+                  }
+               }
+
+               #ifndef exprtk_disable_enhanced_features
+               if (details::is_sf3ext_node(branch[0]))
+               {
+                  expression_node_ptr result = error_node();
+
+                  if (synthesize_sf4ext_expression::template compile_left<ctype>(expr_gen,c,operation,branch[0],result))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+
+                     return result;
+                  }
+               }
+               #endif
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                       \
+                  case op0 : return expr_gen.node_allocator_->                                     \
+                                template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
+                                   (branch[0],c);                                                  \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_cocob_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               expression_node_ptr result = error_node();
+
+               // (cob) o c --> cob
+               if (details::is_cob_node(branch[0]))
+               {
+                  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
+                  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+
+                  if ((T(0) == c) && (details::e_mul == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+
+                     return expr_gen(T(0));
+                  }
+                  else if ((T(0) == c) && (details::e_div == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+
+                     return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
+                  }
+                  else if ((T(0) == c) && (details::e_add == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     return branch[0];
+                  }
+                  else if ((T(1) == c) && (details::e_mul == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     return branch[0];
+                  }
+                  else if ((T(1) == c) && (details::e_div == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_, branch[1]);
+                     return branch[0];
+                  }
+
+                  bool op_addsub = (details::e_add == cobnode->operation()) ||
+                                   (details::e_sub == cobnode->operation());
+
+                  if (op_addsub)
+                  {
+                     switch (operation)
+                     {
+                        case details::e_add : cobnode->set_c(cobnode->c() + c); break;
+                        case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
+                        default             : return error_node();
+                     }
+
+                     result = cobnode;
+                  }
+                  else if (details::e_mul == cobnode->operation())
+                  {
+                     switch (operation)
+                     {
+                        case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
+                        case details::e_div : cobnode->set_c(cobnode->c() / c); break;
+                        default             : return error_node();
+                     }
+
+                     result = cobnode;
+                  }
+                  else if (details::e_div == cobnode->operation())
+                  {
+                     if (details::e_mul == operation)
+                     {
+                        cobnode->set_c(cobnode->c() * c);
+                        result = cobnode;
+                     }
+                     else if (details::e_div == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                       (cobnode->c() / c,cobnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[0]);
+                     }
+                  }
+
+                  if (result)
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+                  }
+               }
+
+               // c o (cob) --> cob
+               else if (details::is_cob_node(branch[1]))
+               {
+                  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
+                  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+
+                  if ((T(0) == c) && (details::e_mul == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+
+                     return expr_gen(T(0));
+                  }
+                  else if ((T(0) == c) && (details::e_div == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+
+                     return expr_gen(T(0));
+                  }
+                  else if ((T(0) == c) && (details::e_add == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_, branch[0]);
+                     return branch[1];
+                  }
+                  else if ((T(1) == c) && (details::e_mul == operation))
+                  {
+                     free_node(*expr_gen.node_allocator_, branch[0]);
+                     return branch[1];
+                  }
+
+                  if (details::e_add == cobnode->operation())
+                  {
+                     if (details::e_add == operation)
+                     {
+                        cobnode->set_c(c + cobnode->c());
+                        result = cobnode;
+                     }
+                     else if (details::e_sub == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
+                                       (c - cobnode->c(),cobnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+                  else if (details::e_sub == cobnode->operation())
+                  {
+                     if (details::e_add == operation)
+                     {
+                        cobnode->set_c(c + cobnode->c());
+                        result = cobnode;
+                     }
+                     else if (details::e_sub == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
+                                       (c - cobnode->c(),cobnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+                  else if (details::e_mul == cobnode->operation())
+                  {
+                     if (details::e_mul == operation)
+                     {
+                        cobnode->set_c(c * cobnode->c());
+                        result = cobnode;
+                     }
+                     else if (details::e_div == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                       (c / cobnode->c(),cobnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+                  else if (details::e_div == cobnode->operation())
+                  {
+                     if (details::e_mul == operation)
+                     {
+                        cobnode->set_c(c * cobnode->c());
+                        result = cobnode;
+                     }
+                     else if (details::e_div == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
+                                       (c / cobnode->c(),cobnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+
+                  if (result)
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+                  }
+               }
+
+               return result;
+            }
+         };
+
+         struct synthesize_coboc_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               expression_node_ptr result = error_node();
+
+               // (boc) o c --> boc
+               if (details::is_boc_node(branch[0]))
+               {
+                  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
+                  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+
+                  if (details::e_add == bocnode->operation())
+                  {
+                     switch (operation)
+                     {
+                        case details::e_add : bocnode->set_c(bocnode->c() + c); break;
+                        case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
+                        default             : return error_node();
+                     }
+
+                     result = bocnode;
+                  }
+                  else if (details::e_mul == bocnode->operation())
+                  {
+                     switch (operation)
+                     {
+                        case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
+                        case details::e_div : bocnode->set_c(bocnode->c() / c); break;
+                        default             : return error_node();
+                     }
+
+                     result = bocnode;
+                  }
+                  else if (details::e_sub == bocnode->operation())
+                  {
+                     if (details::e_add == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
+                                       (bocnode->move_branch(0),c - bocnode->c());
+                        free_node(*expr_gen.node_allocator_,branch[0]);
+                     }
+                     else if (details::e_sub == operation)
+                     {
+                        bocnode->set_c(bocnode->c() + c);
+                        result = bocnode;
+                     }
+                  }
+                  else if (details::e_div == bocnode->operation())
+                  {
+                     switch (operation)
+                     {
+                        case details::e_div : bocnode->set_c(bocnode->c() * c); break;
+                        case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
+                        default             : return error_node();
+                     }
+
+                     result = bocnode;
+                  }
+
+                  if (result)
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[1]);
+                  }
+               }
+
+               // c o (boc) --> boc
+               else if (details::is_boc_node(branch[1]))
+               {
+                  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
+                  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+
+                  if (details::e_add == bocnode->operation())
+                  {
+                     if (details::e_add == operation)
+                     {
+                        bocnode->set_c(c + bocnode->c());
+                        result = bocnode;
+                     }
+                     else if (details::e_sub == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
+                                       (c - bocnode->c(),bocnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+                  else if (details::e_sub == bocnode->operation())
+                  {
+                     if (details::e_add == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
+                                       (bocnode->move_branch(0),c - bocnode->c());
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                     else if (details::e_sub == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
+                                       (c + bocnode->c(),bocnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+                  else if (details::e_mul == bocnode->operation())
+                  {
+                     if (details::e_mul == operation)
+                     {
+                        bocnode->set_c(c * bocnode->c());
+                        result = bocnode;
+                     }
+                     else if (details::e_div == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                       (c / bocnode->c(),bocnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+                  else if (details::e_div == bocnode->operation())
+                  {
+                     if (details::e_mul == operation)
+                     {
+                        bocnode->set_c(bocnode->c() / c);
+                        result = bocnode;
+                     }
+                     else if (details::e_div == operation)
+                     {
+                        result = expr_gen.node_allocator_->
+                                    template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
+                                       (c * bocnode->c(),bocnode->move_branch(0));
+                        free_node(*expr_gen.node_allocator_,branch[1]);
+                     }
+                  }
+
+                  if (result)
+                  {
+                     free_node(*expr_gen.node_allocator_,branch[0]);
+                  }
+               }
+
+               return result;
+            }
+         };
+
+         #ifndef exprtk_disable_enhanced_features
+         inline bool synthesize_expression(const details::operator_type& operation,
+                                           expression_node_ptr (&branch)[2],
+                                           expression_node_ptr& result)
+         {
+            result = error_node();
+
+            if (!operation_optimisable(operation))
+               return false;
+
+            const std::string node_id = branch_to_id(branch);
+            typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
+
+            if (synthesize_map_.end() != itr)
+            {
+               result = itr->second(*this,operation,branch);
+
+               return true;
+            }
+            else
+               return false;
+         }
+
+         struct synthesize_vov_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                       \
+                  case op0 : return expr_gen.node_allocator_->                                     \
+                                template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
+                                   (v1,v2);                                                        \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_cov_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const Type  c = static_cast<details::literal_node<Type>*> (branch[0])->value();
+               const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               if ((T(0) == c) && (details::e_mul == operation))
+                  return expr_gen(T(0));
+               else if ((T(0) == c) && (details::e_div == operation))
+                  return expr_gen(T(0));
+               else if ((T(0) == c) && (details::e_add == operation))
+                  return static_cast<details::variable_node<Type>*>(branch[1]);
+               else if ((T(1) == c) && (details::e_mul == operation))
+                  return static_cast<details::variable_node<Type>*>(branch[1]);
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                       \
+                  case op0 : return expr_gen.node_allocator_->                                     \
+                                template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
+                                   (c,v);                                                          \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_voc_expression
+         {
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type  c = static_cast<details::literal_node<Type>*> (branch[1])->value();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               if (expr_gen.cardinal_pow_optimisable(operation,c))
+               {
+                  if (std::equal_to<T>()(T(1),c))
+                     return branch[0];
+                  else
+                     return expr_gen.cardinal_pow_optimisation(v,c);
+               }
+               else if ((T(0) == c) && (details::e_mul == operation))
+                  return expr_gen(T(0));
+               else if ((T(0) == c) && (details::e_div == operation))
+                  return expr_gen(std::numeric_limits<T>::quiet_NaN());
+               else if ((T(0) == c) && (details::e_add == operation))
+                  return static_cast<details::variable_node<Type>*>(branch[0]);
+               else if ((T(1) == c) && (details::e_mul == operation))
+                  return static_cast<details::variable_node<Type>*>(branch[0]);
+               else if ((T(1) == c) && (details::e_div == operation))
+                  return static_cast<details::variable_node<Type>*>(branch[0]);
+
+               switch (operation)
+               {
+                  #define case_stmt(op0,op1)                                                       \
+                  case op0 : return expr_gen.node_allocator_->                                     \
+                                template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
+                                   (v,c);                                                          \
+
+                  basic_opr_switch_statements
+                  extended_opr_switch_statements
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+         };
+
+         struct synthesize_sf3ext_expression
+         {
+            template <typename T0, typename T1, typename T2>
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& sf3opr,
+                                                      T0 t0, T1 t1, T2 t2)
+            {
+               switch (sf3opr)
+               {
+                  #define case_stmt(op0,op1)                                          \
+                  case op0 : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,op1<Type> >:: \
+                                allocate(*(expr_gen.node_allocator_),t0,t1,t2);       \
+
+                  case_stmt(details::e_sf00,details::sf00_op) case_stmt(details::e_sf01,details::sf01_op)
+                  case_stmt(details::e_sf02,details::sf02_op) case_stmt(details::e_sf03,details::sf03_op)
+                  case_stmt(details::e_sf04,details::sf04_op) case_stmt(details::e_sf05,details::sf05_op)
+                  case_stmt(details::e_sf06,details::sf06_op) case_stmt(details::e_sf07,details::sf07_op)
+                  case_stmt(details::e_sf08,details::sf08_op) case_stmt(details::e_sf09,details::sf09_op)
+                  case_stmt(details::e_sf10,details::sf10_op) case_stmt(details::e_sf11,details::sf11_op)
+                  case_stmt(details::e_sf12,details::sf12_op) case_stmt(details::e_sf13,details::sf13_op)
+                  case_stmt(details::e_sf14,details::sf14_op) case_stmt(details::e_sf15,details::sf15_op)
+                  case_stmt(details::e_sf16,details::sf16_op) case_stmt(details::e_sf17,details::sf17_op)
+                  case_stmt(details::e_sf18,details::sf18_op) case_stmt(details::e_sf19,details::sf19_op)
+                  case_stmt(details::e_sf20,details::sf20_op) case_stmt(details::e_sf21,details::sf21_op)
+                  case_stmt(details::e_sf22,details::sf22_op) case_stmt(details::e_sf23,details::sf23_op)
+                  case_stmt(details::e_sf24,details::sf24_op) case_stmt(details::e_sf25,details::sf25_op)
+                  case_stmt(details::e_sf26,details::sf26_op) case_stmt(details::e_sf27,details::sf27_op)
+                  case_stmt(details::e_sf28,details::sf28_op) case_stmt(details::e_sf29,details::sf29_op)
+                  case_stmt(details::e_sf30,details::sf30_op)
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+
+            template <typename T0, typename T1, typename T2>
+            static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
+                                       T0 t0, T1 t1, T2 t2,
+                                       expression_node_ptr& result)
+            {
+               details::operator_type sf3opr;
+
+               if (!expr_gen.sf3_optimisable(id,sf3opr))
+                  return false;
+               else
+                  result = synthesize_sf3ext_expression::template process<T0,T1,T2>(expr_gen,sf3opr,t0,t1,t2);
+
+               return true;
+            }
+         };
+
+         struct synthesize_sf4ext_expression
+         {
+            template <typename T0, typename T1, typename T2, typename T3>
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& sf4opr,
+                                                      T0 t0, T1 t1, T2 t2, T3 t3)
+            {
+               switch (sf4opr)
+               {
+                  #define case_stmt(op0,op1)                                                   \
+                  case op0 : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,op1<Type> >:: \
+                                allocate(*(expr_gen.node_allocator_),t0,t1,t2,t3);             \
+
+                  case_stmt(details::e_sf48,details::sf48_op) case_stmt(details::e_sf49,details::sf49_op)
+                  case_stmt(details::e_sf50,details::sf50_op) case_stmt(details::e_sf51,details::sf51_op)
+                  case_stmt(details::e_sf52,details::sf52_op) case_stmt(details::e_sf53,details::sf53_op)
+                  case_stmt(details::e_sf54,details::sf54_op) case_stmt(details::e_sf55,details::sf55_op)
+                  case_stmt(details::e_sf56,details::sf56_op) case_stmt(details::e_sf57,details::sf57_op)
+                  case_stmt(details::e_sf58,details::sf58_op) case_stmt(details::e_sf59,details::sf59_op)
+                  case_stmt(details::e_sf60,details::sf60_op) case_stmt(details::e_sf61,details::sf61_op)
+                  case_stmt(details::e_sf62,details::sf62_op) case_stmt(details::e_sf63,details::sf63_op)
+                  case_stmt(details::e_sf64,details::sf64_op) case_stmt(details::e_sf65,details::sf65_op)
+                  case_stmt(details::e_sf66,details::sf66_op) case_stmt(details::e_sf67,details::sf67_op)
+                  case_stmt(details::e_sf68,details::sf68_op) case_stmt(details::e_sf69,details::sf69_op)
+                  case_stmt(details::e_sf70,details::sf70_op) case_stmt(details::e_sf71,details::sf71_op)
+                  case_stmt(details::e_sf72,details::sf72_op) case_stmt(details::e_sf73,details::sf73_op)
+                  case_stmt(details::e_sf74,details::sf74_op) case_stmt(details::e_sf75,details::sf75_op)
+                  case_stmt(details::e_sf76,details::sf76_op) case_stmt(details::e_sf77,details::sf77_op)
+                  case_stmt(details::e_sf78,details::sf78_op) case_stmt(details::e_sf79,details::sf79_op)
+                  case_stmt(details::e_sf80,details::sf80_op) case_stmt(details::e_sf81,details::sf81_op)
+                  case_stmt(details::e_sf82,details::sf82_op) case_stmt(details::e_sf83,details::sf83_op)
+                  case_stmt(details::e_sf4ext00,details::sfext00_op) case_stmt(details::e_sf4ext01,details::sfext01_op)
+                  case_stmt(details::e_sf4ext02,details::sfext02_op) case_stmt(details::e_sf4ext03,details::sfext03_op)
+                  case_stmt(details::e_sf4ext04,details::sfext04_op) case_stmt(details::e_sf4ext05,details::sfext05_op)
+                  case_stmt(details::e_sf4ext06,details::sfext06_op) case_stmt(details::e_sf4ext07,details::sfext07_op)
+                  case_stmt(details::e_sf4ext08,details::sfext08_op) case_stmt(details::e_sf4ext09,details::sfext09_op)
+                  case_stmt(details::e_sf4ext10,details::sfext10_op) case_stmt(details::e_sf4ext11,details::sfext11_op)
+                  case_stmt(details::e_sf4ext12,details::sfext12_op) case_stmt(details::e_sf4ext13,details::sfext13_op)
+                  case_stmt(details::e_sf4ext14,details::sfext14_op) case_stmt(details::e_sf4ext15,details::sfext15_op)
+                  case_stmt(details::e_sf4ext16,details::sfext16_op) case_stmt(details::e_sf4ext17,details::sfext17_op)
+                  case_stmt(details::e_sf4ext18,details::sfext18_op) case_stmt(details::e_sf4ext19,details::sfext19_op)
+                  case_stmt(details::e_sf4ext20,details::sfext20_op) case_stmt(details::e_sf4ext21,details::sfext21_op)
+                  case_stmt(details::e_sf4ext22,details::sfext22_op) case_stmt(details::e_sf4ext23,details::sfext23_op)
+                  case_stmt(details::e_sf4ext24,details::sfext24_op) case_stmt(details::e_sf4ext25,details::sfext25_op)
+                  case_stmt(details::e_sf4ext26,details::sfext26_op) case_stmt(details::e_sf4ext27,details::sfext27_op)
+                  case_stmt(details::e_sf4ext28,details::sfext28_op) case_stmt(details::e_sf4ext29,details::sfext29_op)
+                  case_stmt(details::e_sf4ext30,details::sfext30_op) case_stmt(details::e_sf4ext31,details::sfext31_op)
+                  case_stmt(details::e_sf4ext32,details::sfext32_op) case_stmt(details::e_sf4ext33,details::sfext33_op)
+                  case_stmt(details::e_sf4ext34,details::sfext34_op) case_stmt(details::e_sf4ext35,details::sfext35_op)
+                  case_stmt(details::e_sf4ext36,details::sfext36_op) case_stmt(details::e_sf4ext37,details::sfext37_op)
+                  case_stmt(details::e_sf4ext38,details::sfext38_op) case_stmt(details::e_sf4ext39,details::sfext39_op)
+                  case_stmt(details::e_sf4ext40,details::sfext40_op) case_stmt(details::e_sf4ext41,details::sfext41_op)
+                  case_stmt(details::e_sf4ext42,details::sfext42_op) case_stmt(details::e_sf4ext43,details::sfext43_op)
+                  case_stmt(details::e_sf4ext44,details::sfext44_op) case_stmt(details::e_sf4ext45,details::sfext45_op)
+                  case_stmt(details::e_sf4ext46,details::sfext46_op) case_stmt(details::e_sf4ext47,details::sfext47_op)
+                  case_stmt(details::e_sf4ext48,details::sfext48_op) case_stmt(details::e_sf4ext49,details::sfext49_op)
+                  case_stmt(details::e_sf4ext50,details::sfext50_op) case_stmt(details::e_sf4ext51,details::sfext51_op)
+                  case_stmt(details::e_sf4ext52,details::sfext52_op) case_stmt(details::e_sf4ext53,details::sfext53_op)
+                  case_stmt(details::e_sf4ext54,details::sfext54_op) case_stmt(details::e_sf4ext55,details::sfext55_op)
+                  case_stmt(details::e_sf4ext56,details::sfext56_op) case_stmt(details::e_sf4ext57,details::sfext57_op)
+                  case_stmt(details::e_sf4ext58,details::sfext58_op) case_stmt(details::e_sf4ext59,details::sfext59_op)
+                  case_stmt(details::e_sf4ext60,details::sfext60_op)
+
+                  #undef case_stmt
+                  default : return error_node();
+               }
+            }
+
+            template <typename T0, typename T1, typename T2, typename T3>
+            static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
+                                       T0 t0, T1 t1, T2 t2, T3 t3,
+                                       expression_node_ptr& result)
+            {
+               details::operator_type sf4opr;
+
+               if (!expr_gen.sf4_optimisable(id,sf4opr))
+                  return false;
+               else
+                  result = synthesize_sf4ext_expression::template process<T0,T1,T2,T3>(expr_gen,sf4opr,t0,t1,t2,t3);
+
+               return true;
+            }
+
+            // T o (sf3ext)
+            template <typename ExternalType>
+            static inline bool compile_right(expression_generator<Type>& expr_gen,
+                                             ExternalType t,
+                                             const details::operator_type& operation,
+                                             expression_node_ptr& sf3node,
+                                             expression_node_ptr& result)
+            {
+               if (!details::is_sf3ext_node(sf3node))
+                  return false;
+
+               typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
+
+               sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
+               std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
+
+               switch (n->type())
+               {
+                  case details::expression_node<Type>::e_covoc : return compile_right_impl
+                                                                    <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_covov : return compile_right_impl
+                                                                    <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_vocov : return compile_right_impl
+                                                                    <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_vovoc : return compile_right_impl
+                                                                    <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_vovov : return compile_right_impl
+                                                                    <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  default                                      : return false;
+               }
+            }
+
+            // (sf3ext) o T
+            template <typename ExternalType>
+            static inline bool compile_left(expression_generator<Type>& expr_gen,
+                                            ExternalType t,
+                                            const details::operator_type& operation,
+                                            expression_node_ptr& sf3node,
+                                            expression_node_ptr& result)
+            {
+               if (!details::is_sf3ext_node(sf3node))
+                  return false;
+
+               typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
+
+               sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
+               std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
+
+               switch (n->type())
+               {
+                  case details::expression_node<Type>::e_covoc : return compile_left_impl
+                                                                    <typename covoc_t::sf3_type_node,ExternalType,ctype,vtype,ctype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_covov : return compile_left_impl
+                                                                    <typename covov_t::sf3_type_node,ExternalType,ctype,vtype,vtype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_vocov : return compile_left_impl
+                                                                    <typename vocov_t::sf3_type_node,ExternalType,vtype,ctype,vtype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_vovoc : return compile_left_impl
+                                                                    <typename vovoc_t::sf3_type_node,ExternalType,vtype,vtype,ctype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  case details::expression_node<Type>::e_vovov : return compile_left_impl
+                                                                    <typename vovov_t::sf3_type_node,ExternalType,vtype,vtype,vtype>
+                                                                       (expr_gen,id,t,sf3node,result);
+
+                  default                                      : return false;
+               }
+            }
+
+            template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
+            static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
+                                                  const std::string& id,
+                                                  ExternalType t,
+                                                  expression_node_ptr& node,
+                                                  expression_node_ptr& result)
+            {
+               SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
+
+               if (n)
+               {
+                  T0 t0 = n->t0();
+                  T1 t1 = n->t1();
+                  T2 t2 = n->t2();
+
+                  return synthesize_sf4ext_expression::
+                           template compile<ExternalType,T0,T1,T2>(expr_gen,id,t,t0,t1,t2,result);
+               }
+               else
+                  return false;
+            }
+
+            template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
+            static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
+                                                 const std::string& id,
+                                                 ExternalType t,
+                                                 expression_node_ptr& node,
+                                                 expression_node_ptr& result)
+            {
+               SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
+
+               if (n)
+               {
+                  T0 t0 = n->t0();
+                  T1 t1 = n->t1();
+                  T2 t2 = n->t2();
+
+                  return synthesize_sf4ext_expression::
+                           template compile<T0,T1,T2,ExternalType>(expr_gen,id,t0,t1,t2,t,result);
+               }
+               else
+                  return false;
+            }
+         };
+
+         struct synthesize_vovov_expression0
+         {
+            typedef typename vovov_t::type0 node_type;
+            typedef typename vovov_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 v1) o1 (v2)
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+               const Type& v0 = vov->v0();
+               const Type& v1 = vov->v1();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = vov->operation();
+               const details::operator_type o1 = operation;
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,vtype>(expr_gen,"t/(t*t)",v0,v1,v2,result);
+
+                     exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+            }
+         };
+
+         struct synthesize_vovov_expression1
+         {
+            typedef typename vovov_t::type1 node_type;
+            typedef typename vovov_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0) o0 (v1 o1 v2)
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = vov->v0();
+               const Type& v2 = vov->v1();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = vov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,vtype>(expr_gen,"(t*t)/t",v0,v2,v1,result);
+
+                     exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<vtype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+            }
+         };
+
+         struct synthesize_vovoc_expression0
+         {
+            typedef typename vovoc_t::type0 node_type;
+            typedef typename vovoc_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 v1) o1 (c)
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+               const Type& v0 = vov->v0();
+               const Type& v1 = vov->v1();
+               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = vov->operation();
+               const details::operator_type o1 = operation;
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
+
+                     exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+            }
+         };
+
+         struct synthesize_vovoc_expression1
+         {
+            typedef typename vovoc_t::type1 node_type;
+            typedef typename vovoc_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0) o0 (v1 o1 c)
+               const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = voc->v();
+               const Type   c = voc->c();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = voc->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,ctype,vtype>(expr_gen,"(t*t)/t",v0,c,v1,result);
+
+                     exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<vtype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),v0,v1,c,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+            }
+         };
+
+         struct synthesize_vocov_expression0
+         {
+            typedef typename vocov_t::type0 node_type;
+            typedef typename vocov_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 c) o1 (v1)
+               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+               const Type& v0 = voc->v();
+               const Type   c = voc->c();
+               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = voc->operation();
+               const details::operator_type o1 = operation;
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,ctype>(expr_gen,"t/(t*t)",v0,v1,c,result);
+
+                     exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+            }
+         };
+
+         struct synthesize_vocov_expression1
+         {
+            typedef typename vocov_t::type1 node_type;
+            typedef typename vocov_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0) o0 (c o1 v1)
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type   c = cov->c();
+               const Type& v1 = cov->v();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = cov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,ctype>(expr_gen,"(t*t)/t",v0,v1,c,result);
+
+                     exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<vtype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),v0,c,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+            }
+         };
+
+         struct synthesize_covov_expression0
+         {
+            typedef typename covov_t::type0 node_type;
+            typedef typename covov_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c o0 v0) o1 (v1)
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+               const Type   c = cov->c();
+               const Type& v0 = cov->v();
+               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = cov->operation();
+               const details::operator_type o1 = operation;
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (c / v0) / v1 --> (covov) c / (v0 * v1)
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",c,v0,v1,result);
+
+                     exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+            }
+         };
+
+         struct synthesize_covov_expression1
+         {
+            typedef typename covov_t::type1 node_type;
+            typedef typename covov_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c) o0 (v0 o1 v1)
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type& v0 = vov->v0();
+               const Type& v1 = vov->v1();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = vov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // c / (v0 / v1) --> (covov) (c * v1) / v0
+                  if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",c,v1,v0,result);
+
+                     exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<ctype,vtype,vtype>(expr_gen,id(expr_gen,o0,o1),c,v0,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+            }
+         };
+
+         struct synthesize_covoc_expression0
+         {
+            typedef typename covoc_t::type0 node_type;
+            typedef typename covoc_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c0 o0 v) o1 (c1)
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+               const Type  c0 = cov->c();
+               const Type&  v = cov->v();
+               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = cov->operation();
+               const details::operator_type o1 = operation;
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (c0 + v) + c1 --> (cov) (c0 + c1) + v
+                  if ((details::e_add == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
+                  }
+                  // (c0 + v) - c1 --> (cov) (c0 - c1) + v
+                  else if ((details::e_add == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
+                  }
+                  // (c0 - v) + c1 --> (cov) (c0 + c1) - v
+                  else if ((details::e_sub == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
+                  }
+                  // (c0 - v) - c1 --> (cov) (c0 - c1) - v
+                  else if ((details::e_sub == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
+                  }
+                  // (c0 * v) * c1 --> (cov) (c0 * c1) * v
+                  else if ((details::e_mul == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
+                  }
+                  // (c0 * v) / c1 --> (cov) (c0 / c1) * v
+                  else if ((details::e_mul == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
+                  }
+                  // (c0 / v) * c1 --> (cov) (c0 * c1) / v
+                  else if ((details::e_div == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
+                  }
+                  // (c0 / v) / c1 --> (cov) (c0 / c1) / v
+                  else if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+            }
+         };
+
+         struct synthesize_covoc_expression1
+         {
+            typedef typename covoc_t::type1 node_type;
+            typedef typename covoc_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c0) o0 (v o1 c1)
+               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
+               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type&  v = voc->v();
+               const Type  c1 = voc->c();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = voc->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (c0) + (v + c1) --> (cov) (c0 + c1) + v
+                  if ((details::e_add == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
+                  }
+                  // (c0) + (v - c1) --> (cov) (c0 - c1) + v
+                  else if ((details::e_add == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
+                  }
+                  // (c0) - (v + c1) --> (cov) (c0 - c1) - v
+                  else if ((details::e_sub == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
+                  }
+                  // (c0) - (v - c1) --> (cov) (c0 + c1) - v
+                  else if ((details::e_sub == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
+                  }
+                  // (c0) * (v * c1) --> (voc) v * (c0 * c1)
+                  else if ((details::e_mul == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
+                  }
+                  // (c0) * (v / c1) --> (cov) (c0 / c1) * v
+                  else if ((details::e_mul == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
+                  }
+                  // (c0) / (v * c1) --> (cov) (c0 / c1) / v
+                  else if ((details::e_div == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
+                  }
+                  // (c0) / (v / c1) --> (cov) (c0 * c1) / v
+                  else if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<ctype,vtype,ctype>(expr_gen,id(expr_gen,o0,o1),c0,v,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v,c1,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+            }
+         };
+
+         struct synthesize_cocov_expression0
+         {
+            typedef typename cocov_t::type0 node_type;
+            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            {
+               // (c0 o0 c1) o1 (v) - Not possible.
+               return error_node();
+            }
+         };
+
+         struct synthesize_cocov_expression1
+         {
+            typedef typename cocov_t::type1 node_type;
+            typedef typename cocov_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c0) o0 (c1 o1 v)
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type  c1 = cov->c();
+               const Type&  v = cov->v();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = cov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
+                  if ((details::e_add == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1,v);
+                  }
+                  // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
+                  else if ((details::e_add == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1,v);
+                  }
+                  // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
+                  else if ((details::e_sub == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1,v);
+                  }
+                  // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
+                  else if ((details::e_sub == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1,v);
+                  }
+                  // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
+                  else if ((details::e_mul == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1,v);
+                  }
+                  // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
+                  else if ((details::e_mul == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1,v);
+                  }
+                  // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
+                  else if ((details::e_div == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1,v);
+                  }
+                  // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
+                  else if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1,v);
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<ctype,ctype,vtype>(expr_gen,id(expr_gen,o0,o1),c0,c1,v,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c0,c1,v,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)");
+            }
+         };
+
+         struct synthesize_vococ_expression0
+         {
+            typedef typename vococ_t::type0 node_type;
+            typedef typename vococ_t::sf3_type sf3_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v o0 c0) o1 (c1)
+               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+               const Type&  v = voc->v();
+               const Type& c0 = voc->c();
+               const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = voc->operation();
+               const details::operator_type o1 = operation;
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v + c0) + c1 --> (voc) v + (c0 + c1)
+                  if ((details::e_add == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 + c1);
+                  }
+                  // (v + c0) - c1 --> (voc) v + (c0 - c1)
+                  else if ((details::e_add == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c0 - c1);
+                  }
+                  // (v - c0) + c1 --> (voc) v - (c0 + c1)
+                  else if ((details::e_sub == o0) && (details::e_add == o1))
+                  {
+                     exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v,c1 - c0);
+                  }
+                  // (v - c0) - c1 --> (voc) v - (c0 + c1)
+                  else if ((details::e_sub == o0) && (details::e_sub == o1))
+                  {
+                     exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v,c0 + c1);
+                  }
+                  // (v * c0) * c1 --> (voc) v * (c0 * c1)
+                  else if ((details::e_mul == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 * c1);
+                  }
+                  // (v * c0) / c1 --> (voc) v * (c0 / c1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c0 / c1);
+                  }
+                  // (v / c0) * c1 --> (voc) v * (c1 / c0)
+                  else if ((details::e_div == o0) && (details::e_mul == o1))
+                  {
+                     exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v,c1 / c0);
+                  }
+                  // (v / c0) / c1 --> (voc) v / (c0 * c1)
+                  else if ((details::e_div == o0) && (details::e_div == o1))
+                  {
+                     exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v,c0 * c1);
+                  }
+                  // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
+                  else if ((details::e_pow == o0) && (details::e_pow == o1))
+                  {
+                     exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
+
+                     return expr_gen.node_allocator_->
+                               template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v,c0 * c1);
+                  }
+               }
+
+               if (synthesize_sf3ext_expression::template compile<vtype,ctype,ctype>(expr_gen,id(expr_gen,o0,o1),v,c0,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v,c0,c1,f0,f1);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0, const details::operator_type o1)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t");
+            }
+         };
+
+         struct synthesize_vococ_expression1
+         {
+            typedef typename vococ_t::type0 node_type;
+
+            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            {
+               // (v) o0 (c0 o1 c1) - Not possible.
+               exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
+               return error_node();
+            }
+         };
+
+         struct synthesize_vovovov_expression0
+         {
+            typedef typename vovovov_t::type0 node_type;
+            typedef typename vovovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 v1) o1 (v2 o2 v3)
+               const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
+               const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
+               const Type& v0 = vov0->v0();
+               const Type& v1 = vov0->v1();
+               const Type& v2 = vov1->v0();
+               const Type& v3 = vov1->v1();
+               const details::operator_type o0 = vov0->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = vov1->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
+                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,v3,result);
+
+                     exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v3,v1,v2,result);
+
+                     exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
+                  else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t+t)*(t/t)",v0,v1,v3,v2,result);
+
+                     exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
+                  else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,vtype,vtype>(expr_gen,"(t-t)*(t/t)",v0,v1,v3,v2,result);
+
+                     exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,vtype,vtype>(expr_gen,"((t*t)*t)/t",v0,v1,v3,v2,result);
+
+                     exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vovovoc_expression0
+         {
+            typedef typename vovovoc_t::type0 node_type;
+            typedef typename vovovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 v1) o1 (v2 o2 c)
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
+               const Type& v0 = vov->v0();
+               const Type& v1 = vov->v1();
+               const Type& v2 = voc->v ();
+               const Type   c = voc->c ();
+               const details::operator_type o0 = vov->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = voc->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
+                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
+
+                     exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
+                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
+
+                     exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vovocov_expression0
+         {
+            typedef typename vovocov_t::type0 node_type;
+            typedef typename vovocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 v1) o1 (c o2 v2)
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+               const Type& v0 = vov->v0();
+               const Type& v1 = vov->v1();
+               const Type& v2 = cov->v ();
+               const Type   c = cov->c ();
+               const details::operator_type o0 = vov->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = cov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
+                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,ctype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",v0,c,v1,v2,result);
+
+                     exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
+                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,vtype,ctype>(expr_gen,"(t*t)/(t*t)",v0,v2,v1,c,result);
+
+                     exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vocovov_expression0
+         {
+            typedef typename vocovov_t::type0 node_type;
+            typedef typename vocovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 c) o1 (v1 o2 v2)
+               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+               const Type   c = voc->c ();
+               const Type& v0 = voc->v ();
+               const Type& v1 = vov->v0();
+               const Type& v2 = vov->v1();
+               const details::operator_type o0 = voc->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = vov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
+                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v1,c,v2,result);
+
+                     exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
+                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,vtype,ctype,vtype>(expr_gen,"(t*t)/(t*t)",v0,v2,c,v1,result);
+
+                     exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_covovov_expression0
+         {
+            typedef typename covovov_t::type0 node_type;
+            typedef typename covovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c o0 v0) o1 (v1 o2 v2)
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+               const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
+               const Type   c = cov->c ();
+               const Type& v0 = cov->v ();
+               const Type& v1 = vov->v0();
+               const Type& v2 = vov->v1();
+               const details::operator_type o0 = cov->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = vov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
+                  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v1,v0,v2,result);
+
+                     exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
+                  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<ctype,vtype,vtype,vtype>(expr_gen,"(t*t)/(t*t)",c,v2,v0,v1,result);
+
+                     exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_covocov_expression0
+         {
+            typedef typename covocov_t::type0 node_type;
+            typedef typename covocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c0 o0 v0) o1 (c1 o2 v1)
+               const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
+               const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
+               const Type  c0 = cov0->c();
+               const Type& v0 = cov0->v();
+               const Type  c1 = cov1->c();
+               const Type& v1 = cov1->v();
+               const details::operator_type o0 = cov0->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = cov1->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
+                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
+                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
+                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t-t)+t",(c0 - c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
+                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
+                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v1,v0,result);
+
+                     exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t*t)",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
+                  else if (
+                            (std::equal_to<T>()(c0,c1)) &&
+                            (details::e_mul == o0)      &&
+                            (details::e_mul == o2)      &&
+                            (
+                              (details::e_add == o1) ||
+                              (details::e_sub == o1)
+                            )
+                          )
+                  {
+                     std::string specfunc;
+
+                     switch (o1)
+                     {
+                        case details::e_add : specfunc = "t*(t+t)"; break;
+                        case details::e_sub : specfunc = "t*(t-t)"; break;
+                        default             : return error_node();
+                     }
+
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+
+                     exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vocovoc_expression0
+         {
+            typedef typename vocovoc_t::type0 node_type;
+            typedef typename vocovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 c0) o1 (v1 o2 c1)
+               const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
+               const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
+               const Type  c0 = voc0->c();
+               const Type& v0 = voc0->v();
+               const Type  c1 = voc1->c();
+               const Type& v1 = voc1->v();
+               const details::operator_type o0 = voc0->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = voc1->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
+                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
+                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
+                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c1 - c0),v0,v1,result);
+
+                     exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
+                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
+                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",Type(1) / (c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
+
+                     exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",Type(1) / (c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
+                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t+t)",v0,T(1) / c0,v1,c1,result);
+
+                     exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
+                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf4ext_expression::
+                           template compile<vtype,ctype,vtype,ctype>(expr_gen,"(t*t)*(t-t)",v0,T(1) / c0,v1,c1,result);
+
+                     exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
+                  else if (
+                            (std::equal_to<T>()(c0,c1)) &&
+                            (details::e_mul == o0)      &&
+                            (details::e_mul == o2)      &&
+                            (
+                              (details::e_add == o1) ||
+                              (details::e_sub == o1)
+                            )
+                          )
+                  {
+                     std::string specfunc;
+
+                     switch (o1)
+                     {
+                        case details::e_add : specfunc = "t*(t+t)"; break;
+                        case details::e_sub : specfunc = "t*(t-t)"; break;
+                        default             : return error_node();
+                     }
+
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+
+                     exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
+                  else if (
+                            (std::equal_to<T>()(c0,c1)) &&
+                            (details::e_div == o0)      &&
+                            (details::e_div == o2)      &&
+                            (
+                              (details::e_add == o1) ||
+                              (details::e_sub == o1)
+                            )
+                          )
+                  {
+                     std::string specfunc;
+
+                     switch (o1)
+                     {
+                        case details::e_add : specfunc = "(t+t)/t"; break;
+                        case details::e_sub : specfunc = "(t-t)/t"; break;
+                        default             : return error_node();
+                     }
+
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,ctype>(expr_gen,specfunc,v0,v1,c0,result);
+
+                     exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_covovoc_expression0
+         {
+            typedef typename covovoc_t::type0 node_type;
+            typedef typename covovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (c0 o0 v0) o1 (v1 o2 c1)
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
+               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
+               const Type  c0 = cov->c();
+               const Type& v0 = cov->v();
+               const Type  c1 = voc->c();
+               const Type& v1 = voc->v();
+               const details::operator_type o0 = cov->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = voc->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
+                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
+                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
+                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t-(t+t)",(c0 + c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
+                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
+                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t*(t/t)",(c0 / c1),v1,v0,result);
+
+                     exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"t/(t*t)",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
+                  else if (
+                            (std::equal_to<T>()(c0,c1)) &&
+                            (details::e_mul == o0)      &&
+                            (details::e_mul == o2)      &&
+                            (
+                              (details::e_add == o1) ||
+                              (details::e_sub == o1)
+                            )
+                          )
+                  {
+                     std::string specfunc;
+
+                     switch (o1)
+                     {
+                        case details::e_add : specfunc = "t*(t+t)"; break;
+                        case details::e_sub : specfunc = "t*(t-t)"; break;
+                        default             : return error_node();
+                     }
+
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+
+                     exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vococov_expression0
+         {
+            typedef typename vococov_t::type0 node_type;
+            typedef typename vococov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 c0) o1 (c1 o2 v1)
+               const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
+               const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
+               const Type  c0 = voc->c();
+               const Type& v0 = voc->v();
+               const Type  c1 = cov->c();
+               const Type& v1 = cov->v();
+               const details::operator_type o0 = voc->operation();
+               const details::operator_type o1 = operation;
+               const details::operator_type o2 = cov->operation();
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (expr_gen.parser_->settings_.strength_reduction_enabled())
+               {
+                  // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
+                  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)+t",(c0 + c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
+                  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t+t)-t",(c0 - c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
+                  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,ctype>(expr_gen,"(t+t)-t",v0,v1,(c1 + c0),result);
+
+                     exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
+                  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
+                  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",(c1 / c0),v0,v1,result);
+
+                     exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
+                  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)*t",(c0 / c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,"(t*t)/t",Type(1) / (c0 * c1),v0,v1,result);
+
+                     exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
+                  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
+                  {
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<vtype,vtype,ctype>(expr_gen,"(t*t)*t",v0,v1,Type(1) / (c0 * c1),result);
+
+                     exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+                  // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
+                  else if (
+                            (std::equal_to<T>()(c0,c1)) &&
+                            (details::e_mul == o0)      &&
+                            (details::e_mul == o2)      &&
+                            (
+                              (details::e_add == o1) || (details::e_sub == o1)
+                            )
+                          )
+                  {
+                     std::string specfunc;
+
+                     switch (o1)
+                     {
+                        case details::e_add : specfunc = "t*(t+t)"; break;
+                        case details::e_sub : specfunc = "t*(t-t)"; break;
+                        default             : return error_node();
+                     }
+
+                     const bool synthesis_result =
+                        synthesize_sf3ext_expression::
+                           template compile<ctype,vtype,vtype>(expr_gen,specfunc,c0,v0,v1,result);
+
+                     exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
+
+                     return (synthesis_result) ? result : error_node();
+                  }
+               }
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o1,f1))
+                  return error_node();
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+               else
+                  return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vovovov_expression1
+         {
+            typedef typename vovovov_t::type1 node_type;
+            typedef typename vovovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 (v1 o1 (v2 o2 v3))
+               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = vovov->t0();
+               const Type& v2 = vovov->t1();
+               const Type& v3 = vovov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovov->f0();
+               binary_functor_t f2 = vovov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_vovovoc_expression1
+         {
+            typedef typename vovovoc_t::type1 node_type;
+            typedef typename vovovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 (v1 o1 (v2 o2 c))
+               typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
+
+               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = vovoc->t0();
+               const Type& v2 = vovoc->t1();
+               const Type   c = vovoc->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovoc->f0();
+               binary_functor_t f2 = vovoc->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_vovocov_expression1
+         {
+            typedef typename vovocov_t::type1 node_type;
+            typedef typename vovocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 (v1 o1 (c o2 v2))
+               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = vocov->t0();
+               const Type   c = vocov->t1();
+               const Type& v2 = vocov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vocov->f0();
+               binary_functor_t f2 = vocov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                  return result;
+               if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_vocovov_expression1
+         {
+            typedef typename vocovov_t::type1 node_type;
+            typedef typename vocovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 (c o1 (v1 o2 v2))
+               typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
+
+               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type   c = covov->t0();
+               const Type& v1 = covov->t1();
+               const Type& v2 = covov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(covov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(covov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = covov->f0();
+               binary_functor_t f2 = covov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_covovov_expression1
+         {
+            typedef typename covovov_t::type1 node_type;
+            typedef typename covovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // c o0 (v0 o1 (v1 o2 v2))
+               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type& v0 = vovov->t0();
+               const Type& v1 = vovov->t1();
+               const Type& v2 = vovov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovov->f0();
+               binary_functor_t f2 = vovov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                  return result;
+               if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_covocov_expression1
+         {
+            typedef typename covocov_t::type1 node_type;
+            typedef typename covocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // c0 o0 (v0 o1 (c1 o2 v1))
+               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type& v0 = vocov->t0();
+               const Type  c1 = vocov->t1();
+               const Type& v1 = vocov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vocov->f0();
+               binary_functor_t f2 = vocov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_vocovoc_expression1
+         {
+            typedef typename vocovoc_t::type1 node_type;
+            typedef typename vocovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 (c0 o1 (v1 o2 c2))
+               typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
+
+               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type  c0 = covoc->t0();
+               const Type& v1 = covoc->t1();
+               const Type  c1 = covoc->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
+               const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = covoc->f0();
+               binary_functor_t f2 = covoc->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_covovoc_expression1
+         {
+            typedef typename covovoc_t::type1 node_type;
+            typedef typename covovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // c0 o0 (v0 o1 (v1 o2 c1))
+               typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
+
+               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type& v0 = vovoc->t0();
+               const Type& v1 = vovoc->t1();
+               const Type  c1 = vovoc->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovoc->f0();
+               binary_functor_t f2 = vovoc->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_vococov_expression1
+         {
+            typedef typename vococov_t::type1 node_type;
+            typedef typename vococov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 (c0 o1 (c1 o2 v1))
+               typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
+
+               const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type  c0 = cocov->t0();
+               const Type  c1 = cocov->t1();
+               const Type& v1 = cocov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = cocov->f0();
+               binary_functor_t f2 = cocov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "(t" << expr_gen.to_str(o2) << "t))");
+            }
+         };
+
+         struct synthesize_vovovov_expression2
+         {
+            typedef typename vovovov_t::type2 node_type;
+            typedef typename vovovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 ((v1 o1 v2) o2 v3)
+               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = vovov->t0();
+               const Type& v2 = vovov->t1();
+               const Type& v3 = vovov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovov->f0();
+               binary_functor_t f2 = vovov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vovovoc_expression2
+         {
+            typedef typename vovovoc_t::type2 node_type;
+            typedef typename vovovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 ((v1 o1 v2) o2 c)
+               typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
+
+               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = vovoc->t0();
+               const Type& v2 = vovoc->t1();
+               const Type   c = vovoc->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovoc->f0();
+               binary_functor_t f2 = vovoc->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vovocov_expression2
+         {
+            typedef typename vovocov_t::type2 node_type;
+            typedef typename vovocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 ((v1 o1 c) o2 v2)
+               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type& v1 = vocov->t0();
+               const Type   c = vocov->t1();
+               const Type& v2 = vocov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vocov->f0();
+               binary_functor_t f2 = vocov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vocovov_expression2
+         {
+            typedef typename vocovov_t::type2 node_type;
+            typedef typename vocovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 ((c o1 v1) o2 v2)
+               typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
+
+               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type   c = covov->t0();
+               const Type& v1 = covov->t1();
+               const Type& v2 = covov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(covov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(covov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = covov->f0();
+               binary_functor_t f2 = covov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_covovov_expression2
+         {
+            typedef typename covovov_t::type2 node_type;
+            typedef typename covovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // c o0 ((v1 o1 v2) o2 v3)
+               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
+               const Type   c = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type& v0 = vovov->t0();
+               const Type& v1 = vovov->t1();
+               const Type& v2 = vovov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovov->f0();
+               binary_functor_t f2 = vovov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+        };
+
+         struct synthesize_covocov_expression2
+         {
+            typedef typename covocov_t::type2 node_type;
+            typedef typename covocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // c0 o0 ((v0 o1 c1) o2 v1)
+               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
+               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type& v0 = vocov->t0();
+               const Type  c1 = vocov->t1();
+               const Type& v1 = vocov->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vocov->f0();
+               binary_functor_t f2 = vocov->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vocovoc_expression2
+         {
+            typedef typename vocovoc_t::type2 node_type;
+            typedef typename vocovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // v0 o0 ((c0 o1 v1) o2 c1)
+               typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
+
+               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
+               const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
+               const Type  c0 = covoc->t0();
+               const Type& v1 = covoc->t1();
+               const Type  c1 = covoc->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
+               const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = covoc->f0();
+               binary_functor_t f2 = covoc->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_covovoc_expression2
+         {
+            typedef typename covovoc_t::type2 node_type;
+            typedef typename covovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // c0 o0 ((v0 o1 v1) o2 c1)
+               typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
+
+               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
+               const Type  c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
+               const Type& v0 = vovoc->t0();
+               const Type& v1 = vovoc->t1();
+               const Type  c1 = vovoc->t2();
+               const details::operator_type o0 = operation;
+               const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
+               const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
+
+               binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
+               binary_functor_t f1 = vovoc->f0();
+               binary_functor_t f2 = vovoc->f1();
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o0,f0))
+                  return error_node();
+
+               exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "t" << expr_gen.to_str(o0) << "((t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t)");
+            }
+         };
+
+         struct synthesize_vococov_expression2
+         {
+            typedef typename vococov_t::type2 node_type;
+            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            {
+               // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
+               exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
+               return error_node();
+            }
+
+            static inline std::string id(expression_generator<Type>&,
+                                         const details::operator_type, const details::operator_type, const details::operator_type)
+            {
+               return "INVALID";
+            }
+         };
+
+         struct synthesize_vovovov_expression3
+         {
+            typedef typename vovovov_t::type3 node_type;
+            typedef typename vovovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 v1) o1 v2) o2 v3
+               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+               const Type& v0 = vovov->t0();
+               const Type& v1 = vovov->t1();
+               const Type& v2 = vovov->t2();
+               const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vovov->f0();
+               binary_functor_t f1 = vovov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vovovoc_expression3
+         {
+            typedef typename vovovoc_t::type3 node_type;
+            typedef typename vovovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 v1) o1 v2) o2 c
+               typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+               const Type& v0 = vovov->t0();
+               const Type& v1 = vovov->t1();
+               const Type& v2 = vovov->t2();
+               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vovov->f0();
+               binary_functor_t f1 = vovov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vovocov_expression3
+         {
+            typedef typename vovocov_t::type3 node_type;
+            typedef typename vovocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 v1) o1 c) o2 v2
+               typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
+
+               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
+               const Type& v0 = vovoc->t0();
+               const Type& v1 = vovoc->t1();
+               const Type   c = vovoc->t2();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vovoc->f0();
+               binary_functor_t f1 = vovoc->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vocovov_expression3
+         {
+            typedef typename vocovov_t::type3 node_type;
+            typedef typename vocovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 c) o1 v1) o2 v2
+               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+               const Type& v0 = vocov->t0();
+               const Type   c = vocov->t1();
+               const Type& v1 = vocov->t2();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vocov->f0();
+               binary_functor_t f1 = vocov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_covovov_expression3
+         {
+            typedef typename covovov_t::type3 node_type;
+            typedef typename covovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((c o0 v0) o1 v1) o2 v2
+               typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
+
+               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+               const Type   c = covov->t0();
+               const Type& v0 = covov->t1();
+               const Type& v1 = covov->t2();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = covov->f0();
+               binary_functor_t f1 = covov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_covocov_expression3
+         {
+            typedef typename covocov_t::type3 node_type;
+            typedef typename covocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((c0 o0 v0) o1 c1) o2 v1
+               typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
+
+               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
+               const Type  c0 = covoc->t0();
+               const Type& v0 = covoc->t1();
+               const Type  c1 = covoc->t2();
+               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
+               const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = covoc->f0();
+               binary_functor_t f1 = covoc->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vocovoc_expression3
+         {
+            typedef typename vocovoc_t::type3 node_type;
+            typedef typename vocovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 c0) o1 v1) o2 c1
+               typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+               const Type& v0 = vocov->t0();
+               const Type  c0 = vocov->t1();
+               const Type& v1 = vocov->t2();
+               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vocov->f0();
+               binary_functor_t f1 = vocov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_covovoc_expression3
+         {
+            typedef typename covovoc_t::type3 node_type;
+            typedef typename covovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((c0 o0 v0) o1 v1) o2 c1
+               typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
+
+               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+               const Type  c0 = covov->t0();
+               const Type& v0 = covov->t1();
+               const Type& v1 = covov->t2();
+               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = covov->f0();
+               binary_functor_t f1 = covov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vococov_expression3
+         {
+            typedef typename vococov_t::type3 node_type;
+            typedef typename vococov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 c0) o1 c1) o2 v1
+               typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
+
+               const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
+               const Type& v0 = vococ->t0();
+               const Type  c0 = vococ->t1();
+               const Type  c1 = vococ->t2();
+               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vococ->f0();
+               binary_functor_t f1 = vococ->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "((t" << expr_gen.to_str(o0) << "t)" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vovovov_expression4
+         {
+            typedef typename vovovov_t::type4 node_type;
+            typedef typename vovovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // (v0 o0 (v1 o1 v2)) o2 v3
+               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+               const Type& v0 = vovov->t0();
+               const Type& v1 = vovov->t1();
+               const Type& v2 = vovov->t2();
+               const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vovov->f0();
+               binary_functor_t f1 = vovov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vovovoc_expression4
+         {
+            typedef typename vovovoc_t::type4 node_type;
+            typedef typename vovovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 (v1 o1 v2)) o2 c)
+               typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
+
+               const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
+               const Type& v0 = vovov->t0();
+               const Type& v1 = vovov->t1();
+               const Type& v2 = vovov->t2();
+               const Type   c = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vovov->f0();
+               binary_functor_t f1 = vovov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,c,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,c,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vovocov_expression4
+         {
+            typedef typename vovocov_t::type4 node_type;
+            typedef typename vovocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 (v1 o1 c)) o2 v1)
+               typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
+
+               const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
+               const Type& v0 = vovoc->t0();
+               const Type& v1 = vovoc->t1();
+               const Type   c = vovoc->t2();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vovoc->f0();
+               binary_functor_t f1 = vovoc->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,c,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,c,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vocovov_expression4
+         {
+            typedef typename vocovov_t::type4 node_type;
+            typedef typename vocovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 (c o1 v1)) o2 v2)
+               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+               const Type& v0 = vocov->t0();
+               const Type   c = vocov->t1();
+               const Type& v1 = vocov->t2();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vocov->f0();
+               binary_functor_t f1 = vocov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_covovov_expression4
+         {
+            typedef typename covovov_t::type4 node_type;
+            typedef typename covovov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((c o0 (v0 o1 v1)) o2 v2)
+               typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
+
+               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+               const Type   c = covov->t0();
+               const Type& v0 = covov->t1();
+               const Type& v1 = covov->t2();
+               const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = covov->f0();
+               binary_functor_t f1 = covov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c,v0,v1,v2,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c,v0,v1,v2,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_covocov_expression4
+         {
+            typedef typename covocov_t::type4 node_type;
+            typedef typename covocov_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((c0 o0 (v0 o1 c1)) o2 v1)
+               typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
+
+               const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
+               const Type  c0 = covoc->t0();
+               const Type& v0 = covoc->t1();
+               const Type  c1 = covoc->t2();
+               const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
+               const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
+               const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = covoc->f0();
+               binary_functor_t f1 = covoc->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,c1,v1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,c1,v1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vocovoc_expression4
+         {
+            typedef typename vocovoc_t::type4 node_type;
+            typedef typename vocovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((v0 o0 (c0 o1 v1)) o2 c1)
+               typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
+
+               const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
+               const Type& v0 = vocov->t0();
+               const Type  c0 = vocov->t1();
+               const Type& v1 = vocov->t2();
+               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = vocov->f0();
+               binary_functor_t f1 = vocov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,c0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),v0,c0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_covovoc_expression4
+         {
+            typedef typename covovoc_t::type4 node_type;
+            typedef typename covovoc_t::sf4_type sf4_type;
+            typedef typename node_type::T0 T0;
+            typedef typename node_type::T1 T1;
+            typedef typename node_type::T2 T2;
+            typedef typename node_type::T3 T3;
+
+            static inline expression_node_ptr process(expression_generator<Type>& expr_gen,
+                                                      const details::operator_type& operation,
+                                                      expression_node_ptr (&branch)[2])
+            {
+               // ((c0 o0 (v0 o1 v1)) o2 c1)
+               typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
+
+               const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
+               const Type  c0 = covov->t0();
+               const Type& v0 = covov->t1();
+               const Type& v1 = covov->t2();
+               const Type  c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
+               const details::operator_type o0 = expr_gen.get_operator(covov->f0());
+               const details::operator_type o1 = expr_gen.get_operator(covov->f1());
+               const details::operator_type o2 = operation;
+
+               binary_functor_t f0 = covov->f0();
+               binary_functor_t f1 = covov->f1();
+               binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
+
+               details::free_node(*(expr_gen.node_allocator_),branch[0]);
+               details::free_node(*(expr_gen.node_allocator_),branch[1]);
+
+               expression_node_ptr result = error_node();
+
+               if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),c0,v0,v1,c1,result))
+                  return result;
+               else if (!expr_gen.valid_operator(o2,f2))
+                  return error_node();
+
+               exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
+
+               return node_type::allocate(*(expr_gen.node_allocator_),c0,v0,v1,c1,f0,f1,f2);
+            }
+
+            static inline std::string id(expression_generator<Type>& expr_gen,
+                                         const details::operator_type o0,
+                                         const details::operator_type o1,
+                                         const details::operator_type o2)
+            {
+               return (details::build_string() << "(t" << expr_gen.to_str(o0) << "(t" << expr_gen.to_str(o1) << "t)" << expr_gen.to_str(o2) << "t");
+            }
+         };
+
+         struct synthesize_vococov_expression4
+         {
+            typedef typename vococov_t::type4 node_type;
+            static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2])
+            {
+               // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
+               exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
+               return error_node();
+            }
+
+            static inline std::string id(expression_generator<Type>&,
+                                         const details::operator_type, const details::operator_type, const details::operator_type)
+            {
+               return "INVALID";
+            }
+         };
+         #endif
+
+         inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            // Definition: uv o uv
+            details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
+            details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
+            const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
+            const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
+            unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
+            unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
+            binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
+
+            if (!valid_operator(o0,u0))
+               return error_node();
+            else if (!valid_operator(o1,u1))
+               return error_node();
+            else if (!valid_operator(operation,f))
+               return error_node();
+
+            expression_node_ptr result = error_node();
+
+            if (
+                 (details::e_neg == o0) &&
+                 (details::e_neg == o1)
+               )
+            {
+               switch (operation)
+               {
+                  // (-v0 + -v1) --> -(v0 + v1)
+                  case details::e_add : result = (*this)(details::e_neg,
+                                                    node_allocator_->
+                                                       allocate_rr<typename details::
+                                                          vov_node<Type,details::add_op<Type> > >(v0,v1));
+                                        exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
+                                        break;
+
+                  // (-v0 - -v1) --> (v1 - v0)
+                  case details::e_sub : result = node_allocator_->
+                                                    allocate_rr<typename details::
+                                                       vov_node<Type,details::sub_op<Type> > >(v1,v0);
+                                        exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
+                                        break;
+
+                  // (-v0 * -v1) --> (v0 * v1)
+                  case details::e_mul : result = node_allocator_->
+                                                    allocate_rr<typename details::
+                                                       vov_node<Type,details::mul_op<Type> > >(v0,v1);
+                                        exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
+                                        break;
+
+                  // (-v0 / -v1) --> (v0 / v1)
+                  case details::e_div : result = node_allocator_->
+                                                    allocate_rr<typename details::
+                                                       vov_node<Type,details::div_op<Type> > >(v0,v1);
+                                        exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
+                                        break;
+
+                  default             : break;
+               }
+            }
+
+            if (0 == result)
+            {
+               result = node_allocator_->
+                            allocate_rrrrr<typename details::uvouv_node<Type> >(v0,v1,u0,u1,f);
+            }
+
+            details::free_all_nodes(*node_allocator_,branch);
+            return result;
+         }
+
+         #undef basic_opr_switch_statements
+         #undef extended_opr_switch_statements
+         #undef unary_opr_switch_statements
+
+         #ifndef exprtk_disable_string_capabilities
+
+         #define string_opr_switch_statements          \
+         case_stmt(details::  e_lt ,details::   lt_op) \
+         case_stmt(details:: e_lte ,details::  lte_op) \
+         case_stmt(details::  e_gt ,details::   gt_op) \
+         case_stmt(details:: e_gte ,details::  gte_op) \
+         case_stmt(details::  e_eq ,details::   eq_op) \
+         case_stmt(details::  e_ne ,details::   ne_op) \
+         case_stmt(details::e_in   ,details::   in_op) \
+         case_stmt(details::e_like ,details:: like_op) \
+         case_stmt(details::e_ilike,details::ilike_op) \
+
+         template <typename T0, typename T1>
+         inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr,
+                                                                        T0 s0, T1 s1,
+                                                                        range_t rp0)
+         {
+            switch (opr)
+            {
+               #define case_stmt(op0,op1)                                                                       \
+               case op0 : return node_allocator_->                                                              \
+                             allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
+                                (s0,s1,rp0);                                                                    \
+
+               string_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         template <typename T0, typename T1>
+         inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr,
+                                                                        T0 s0, T1 s1,
+                                                                        range_t rp1)
+         {
+            switch (opr)
+            {
+               #define case_stmt(op0,op1)                                                                       \
+               case op0 : return node_allocator_->                                                              \
+                             allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
+                                (s0,s1,rp1);                                                                    \
+
+               string_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         template <typename T0, typename T1>
+         inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr,
+                                                                         T0 s0, T1 s1,
+                                                                         range_t rp0, range_t rp1)
+         {
+            switch (opr)
+            {
+               #define case_stmt(op0,op1)                                                                         \
+               case op0 : return node_allocator_->                                                                \
+                             allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
+                                (s0,s1,rp0,rp1);                                                                  \
+
+               string_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         template <typename T0, typename T1>
+         inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
+         {
+            switch (opr)
+            {
+               #define case_stmt(op0,op1)                                                                 \
+               case op0 : return node_allocator_->                                                        \
+                             allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1); \
+
+               string_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+
+         inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
+            std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
+
+            return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1);
+         }
+
+         inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
+            std::string&  s1 = static_cast<details::stringvar_node<Type>*>   (branch[1])->ref  ();
+            range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
+
+            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
+
+            free_node(*node_allocator_,branch[0]);
+
+            return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0);
+         }
+
+         inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string&  s0 = static_cast<details::stringvar_node<Type>*>   (branch[0])->ref  ();
+            std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
+            range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
+
+            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
+
+            free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp1);
+         }
+
+         inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string&  s0 = static_cast<details::stringvar_node<Type>*>         (branch[0])->ref  ();
+            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+
+            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
+
+            free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xoxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp1);
+         }
+
+         inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string&  s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref  ();
+            std::string&  s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref  ();
+            range_t      rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
+            range_t      rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
+
+            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
+            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
+
+            details::free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr,s0,s1,rp0,rp1);
+         }
+
+         inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
+            std::string  s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
+
+            details::free_node(*node_allocator_,branch[1]);
+
+            return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1);
+         }
+
+         inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+            std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+
+            details::free_node(*node_allocator_,branch[0]);
+
+            return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1);
+         }
+
+         inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string   s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str  ();
+            std::string&  s1 = static_cast<details::string_range_node<Type>*>  (branch[1])->ref  ();
+            range_t      rp1 = static_cast<details::string_range_node<Type>*>  (branch[1])->range();
+
+            static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
+
+            details::free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp1);
+         }
+
+         inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string&  s0 = static_cast<details::string_range_node<Type>*>  (branch[0])->ref  ();
+            std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str  ();
+            range_t      rp0 = static_cast<details::string_range_node<Type>*>  (branch[0])->range();
+
+            static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
+
+            details::free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xrox_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0);
+         }
+
+         inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string&  s0 = static_cast<details::string_range_node<Type>*>      (branch[0])->ref  ();
+            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+            range_t      rp0 = static_cast<details::string_range_node<Type>*>      (branch[0])->range();
+            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+
+            static_cast<details::string_range_node<Type>*>      (branch[0])->range_ref().clear();
+            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
+
+            details::free_node(*node_allocator_,branch[0]);
+            details::free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xroxr_expression_impl<std::string&,const std::string>(opr,s0,s1,rp0,rp1);
+         }
+
+         inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+            const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
+
+            expression_node_ptr result = error_node();
+
+            if (details::e_add == opr)
+               result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
+            else if (details::e_in == opr)
+               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1));
+            else if (details::e_like == opr)
+               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1));
+            else if (details::e_ilike == opr)
+               result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
+            else
+            {
+               expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1);
+               Type v = temp->value();
+               details::free_node(*node_allocator_,temp);
+               result = node_allocator_->allocate<literal_node_t>(v);
+            }
+
+            details::free_all_nodes(*node_allocator_,branch);
+
+            return result;
+         }
+
+         inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            const std::string s0 = static_cast<details::string_literal_node<Type>*>    (branch[0])->str  ();
+                  std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+            range_t          rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+
+            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
+
+            free_node(*node_allocator_,branch[0]);
+            free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xoxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp1);
+         }
+
+         inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
+            std::string&  s1 = static_cast<details::stringvar_node<Type>*>         (branch[1])->ref  ();
+            range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
+
+            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
+
+            free_node(*node_allocator_,branch[0]);
+
+            return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0);
+         }
+
+         inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            const std::string  s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
+                  std::string& s1 = static_cast<details::string_range_node<Type>*>      (branch[1])->ref  ();
+            range_t           rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
+            range_t           rp1 = static_cast<details::string_range_node<Type>*>      (branch[1])->range();
+
+            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
+            static_cast<details::string_range_node<Type>*>      (branch[1])->range_ref().clear();
+
+            free_node(*node_allocator_,branch[0]);
+            free_node(*node_allocator_,branch[1]);
+
+            return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr,s0,s1,rp0,rp1);
+         }
+
+         inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string       s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
+            const std::string s1 = static_cast<details::string_literal_node<Type>*>    (branch[1])->str  ();
+            range_t          rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
+
+            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
+
+            details::free_all_nodes(*node_allocator_,branch);
+
+            return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr,s0,s1,rp0);
+         }
+
+         inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            std::string   s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str  ();
+            std::string   s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str  ();
+            range_t      rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
+            range_t      rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
+
+            static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
+            static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
+
+            details::free_all_nodes(*node_allocator_,branch);
+
+            return synthesize_str_xroxr_expression_impl<const std::string,const std::string>(opr,s0,s1,rp0,rp1);
+         }
+
+         inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            switch (opr)
+            {
+               #define case_stmt(op0,op1)                                                       \
+               case op0 : return node_allocator_->                                              \
+                             allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > >  \
+                                (opr,branch[0],branch[1]);                                      \
+
+               string_opr_switch_statements
+               #undef case_stmt
+               default : return error_node();
+            }
+         }
+         #endif
+
+         #ifndef exprtk_disable_string_capabilities
+         inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
+         {
+            if ((0 == branch[0]) || (0 == branch[1]))
+            {
+               details::free_all_nodes(*node_allocator_,branch);
+
+               return error_node();
+            }
+
+            const bool b0_is_s   = details::is_string_node            (branch[0]);
+            const bool b0_is_cs  = details::is_const_string_node      (branch[0]);
+            const bool b0_is_sr  = details::is_string_range_node      (branch[0]);
+            const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
+
+            const bool b1_is_s   = details::is_string_node            (branch[1]);
+            const bool b1_is_cs  = details::is_const_string_node      (branch[1]);
+            const bool b1_is_sr  = details::is_string_range_node      (branch[1]);
+            const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
+
+            const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
+                                   details::is_genricstring_range_node(branch[0]) ||
+                                   details::is_string_concat_node     (branch[0]) ||
+                                   details::is_string_function_node   (branch[0]) ||
+                                   details::is_string_condition_node  (branch[0]) ||
+                                   details::is_string_ccondition_node (branch[0]) ;
+
+            const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
+                                   details::is_genricstring_range_node(branch[1]) ||
+                                   details::is_string_concat_node     (branch[1]) ||
+                                   details::is_string_function_node   (branch[1]) ||
+                                   details::is_string_condition_node  (branch[1]) ||
+                                   details::is_string_ccondition_node (branch[1]) ;
+
+            if (details::e_add == opr)
+            {
+               if (!b0_is_cs || !b1_is_cs)
+               {
+                  return synthesize_expression<string_concat_node_t,2>(opr,branch);
+               }
+            }
+
+            if (b0_is_gen || b1_is_gen)
+            {
+               return synthesize_strogen_expression(opr,branch);
+            }
+            else if (b0_is_s)
+            {
+                    if (b1_is_s  ) return synthesize_sos_expression   (opr,branch);
+               else if (b1_is_cs ) return synthesize_socs_expression  (opr,branch);
+               else if (b1_is_sr ) return synthesize_sosr_expression  (opr,branch);
+               else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
+            }
+            else if (b0_is_cs)
+            {
+                    if (b1_is_s  ) return synthesize_csos_expression  (opr,branch);
+               else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
+               else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
+               else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
+            }
+            else if (b0_is_sr)
+            {
+                    if (b1_is_s  ) return synthesize_sros_expression  (opr,branch);
+               else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
+               else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
+               else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
+            }
+            else if (b0_is_csr)
+            {
+                    if (b1_is_s  ) return synthesize_csros_expression  (opr,branch);
+               else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
+               else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
+               else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
+            }
+
+            return error_node();
+         }
+         #else
+         inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
+         {
+            details::free_all_nodes(*node_allocator_,branch);
+            return error_node();
+         }
+         #endif
+
+         #ifndef exprtk_disable_string_capabilities
+         inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
+         {
+            if (details::e_inrange != opr)
+               return error_node();
+            else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
+            {
+               details::free_all_nodes(*node_allocator_,branch);
+
+               return error_node();
+            }
+            else if (
+                      details::is_const_string_node(branch[0]) &&
+                      details::is_const_string_node(branch[1]) &&
+                      details::is_const_string_node(branch[2])
+                    )
+            {
+               const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+               const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
+               const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
+
+               Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
+               details::free_all_nodes(*node_allocator_,branch);
+
+               return node_allocator_->allocate_c<details::literal_node<Type> >(v);
+            }
+            else if (
+                      details::is_string_node(branch[0]) &&
+                      details::is_string_node(branch[1]) &&
+                      details::is_string_node(branch[2])
+                    )
+            {
+               std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
+               std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
+               std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
+
+               typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
+
+               return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);
+            }
+            else if (
+                      details::is_const_string_node(branch[0]) &&
+                            details::is_string_node(branch[1]) &&
+                      details::is_const_string_node(branch[2])
+                    )
+            {
+               std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+               std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
+
+               typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;
+
+               details::free_node(*node_allocator_,branch[0]);
+               details::free_node(*node_allocator_,branch[2]);
+
+               return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);
+            }
+            else if (
+                            details::is_string_node(branch[0]) &&
+                      details::is_const_string_node(branch[1]) &&
+                            details::is_string_node(branch[2])
+                    )
+            {
+               std::string&  s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
+               std::string   s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
+               std::string&  s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
+
+               typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;
+
+               details::free_node(*node_allocator_,branch[1]);
+
+               return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
+            }
+            else if (
+                      details::is_string_node(branch[0]) &&
+                      details::is_string_node(branch[1]) &&
+                      details::is_const_string_node(branch[2])
+                    )
+            {
+               std::string& s0 = static_cast<     details::stringvar_node<Type>*>(branch[0])->ref();
+               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+               std::string  s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
+
+               typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;
+
+               details::free_node(*node_allocator_,branch[2]);
+
+               return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);
+            }
+            else if (
+                      details::is_const_string_node(branch[0]) &&
+                      details::      is_string_node(branch[1]) &&
+                      details::      is_string_node(branch[2])
+                    )
+            {
+               std::string  s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
+               std::string& s1 = static_cast<     details::stringvar_node<Type>*>(branch[1])->ref();
+               std::string& s2 = static_cast<     details::stringvar_node<Type>*>(branch[2])->ref();
+
+               typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
+
+               details::free_node(*node_allocator_,branch[0]);
+
+               return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
+            }
+            else
+               return error_node();
+         }
+         #else
+         inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
+         {
+            details::free_all_nodes(*node_allocator_,branch);
+            return error_node();
+         }
+         #endif
+
+         inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
+         {
+            /*
+             Note: The following are the type promotion rules
+             that relate to operations that include 'null':
+             0. null ==/!=     null --> true false
+             1. null operation null --> null
+             2. x    ==/!=     null --> true/false
+             3. null ==/!=     x    --> true/false
+             4. x   operation  null --> x
+             5. null operation x    --> x
+            */
+
+            typedef typename details::null_eq_node<T> nulleq_node_t;
+
+            bool b0_null = details::is_null_node(branch[0]);
+            bool b1_null = details::is_null_node(branch[1]);
+
+            if (b0_null && b1_null)
+            {
+               expression_node_ptr result = error_node();
+
+               if (details::e_eq == operation)
+                  result = node_allocator_->allocate_c<literal_node_t>(T(1));
+               else if (details::e_ne == operation)
+                  result = node_allocator_->allocate_c<literal_node_t>(T(0));
+
+               if (result)
+               {
+                  details::free_node(*node_allocator_,branch[0]);
+                  details::free_node(*node_allocator_,branch[1]);
+
+                  return result;
+               }
+
+               details::free_node(*node_allocator_,branch[1]);
+
+               return branch[0];
+            }
+            else if (details::e_eq == operation)
+            {
+               expression_node_ptr result = node_allocator_->
+                                                allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
+
+               details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
+
+               return result;
+            }
+            else if (details::e_ne == operation)
+            {
+               expression_node_ptr result = node_allocator_->
+                                                allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
+
+               details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
+
+               return result;
+            }
+            else if (b0_null)
+            {
+               details::free_node(*node_allocator_,branch[0]);
+               branch[0] = branch[1];
+               branch[1] = error_node();
+            }
+            else if (b1_null)
+            {
+               details::free_node(*node_allocator_,branch[1]);
+               branch[1] = error_node();
+            }
+
+            if (
+                 (details::e_add == operation) || (details::e_sub == operation) ||
+                 (details::e_mul == operation) || (details::e_div == operation) ||
+                 (details::e_mod == operation) || (details::e_pow == operation)
+               )
+            {
+               return branch[0];
+            }
+            else if (
+                      (details::e_lt    == operation) || (details::e_lte  == operation) ||
+                      (details::e_gt    == operation) || (details::e_gte  == operation) ||
+                      (details::e_and   == operation) || (details::e_nand == operation) ||
+                      (details::e_or    == operation) || (details::e_nor  == operation) ||
+                      (details::e_xor   == operation) || (details::e_xnor == operation) ||
+                      (details::e_in    == operation) || (details::e_like == operation) ||
+                      (details::e_ilike == operation)
+                    )
+            {
+               return node_allocator_->allocate_c<literal_node_t>(T(0));
+            }
+
+            details::free_node(*node_allocator_,branch[0]);
+
+            return node_allocator_->allocate<details::null_node<Type> >();
+         }
+
+         template <typename NodeType, std::size_t N>
+         inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
+         {
+            if (
+                 (details::e_in    == operation) ||
+                 (details::e_like  == operation) ||
+                 (details::e_ilike == operation)
+               )
+               return error_node();
+            else if (!details::all_nodes_valid<N>(branch))
+            {
+               free_all_nodes(*node_allocator_,branch);
+
+               return error_node();
+            }
+            else if ((details::e_default != operation))
+            {
+               // Attempt simple constant folding optimisation.
+               expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
+
+               if (is_constant_foldable<N>(branch))
+               {
+                  Type v = expression_point->value();
+                  details::free_node(*node_allocator_,expression_point);
+
+                  return node_allocator_->allocate<literal_node_t>(v);
+               }
+               else
+                  return expression_point;
+            }
+            else
+               return error_node();
+         }
+
+         template <typename NodeType, std::size_t N>
+         inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
+         {
+            if (!details::all_nodes_valid<N>(branch))
+            {
+               free_all_nodes(*node_allocator_,branch);
+
+               return error_node();
+            }
+
+            typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
+
+            // Attempt simple constant folding optimisation.
+
+            expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
+            function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
+
+            if (0 == func_node_ptr)
+            {
+               free_all_nodes(*node_allocator_,branch);
+
+               return error_node();
+            }
+            else
+               func_node_ptr->init_branches(branch);
+
+            if (is_constant_foldable<N>(branch) && !f->has_side_effects())
+            {
+               Type v = expression_point->value();
+               details::free_node(*node_allocator_,expression_point);
+
+               return node_allocator_->allocate<literal_node_t>(v);
+            }
+
+            parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
+
+            return expression_point;
+         }
+
+         bool strength_reduction_enabled_;
+         details::node_allocator* node_allocator_;
+         synthesize_map_t synthesize_map_;
+         unary_op_map_t* unary_op_map_;
+         binary_op_map_t* binary_op_map_;
+         inv_binary_op_map_t* inv_binary_op_map_;
+         sf3_map_t* sf3_map_;
+         sf4_map_t* sf4_map_;
+         parser_t* parser_;
+      };
+
+      inline void set_error(const parser_error::type& error_type)
+      {
+         error_list_.push_back(error_type);
+      }
+
+      inline void remove_last_error()
+      {
+         if (!error_list_.empty())
+         {
+            error_list_.pop_back();
+         }
+      }
+
+      inline void set_synthesis_error(const std::string& synthesis_error_message)
+      {
+         if (synthesis_error_.empty())
+         {
+            synthesis_error_ = synthesis_error_message;
+         }
+      }
+
+      inline void register_local_vars(expression<T>& e)
+      {
+         for (std::size_t i = 0; i < sem_.size(); ++i)
+         {
+            scope_element& se = sem_.get_element(i);
+
+            if (
+                 (scope_element::e_variable == se.type) ||
+                 (scope_element::e_vecelem  == se.type)
+               )
+            {
+               if (se.var_node)
+               {
+                  e.register_local_var(se.var_node);
+               }
+
+               if (se.data)
+               {
+                  e.register_local_data(se.data,1,0);
+               }
+            }
+            else if (scope_element::e_vector == se.type)
+            {
+               if (se.vec_node)
+               {
+                  e.register_local_var(se.vec_node);
+               }
+
+               if (se.data)
+               {
+                  e.register_local_data(se.data,se.size,1);
+               }
+            }
+            #ifndef exprtk_disable_string_capabilities
+            else if (scope_element::e_string == se.type)
+            {
+               if (se.str_node)
+               {
+                  e.register_local_var(se.str_node);
+               }
+
+               if (se.data)
+               {
+                  e.register_local_data(se.data,se.size,2);
+               }
+            }
+            #endif
+
+            se.var_node  = 0;
+            se.vec_node  = 0;
+            #ifndef exprtk_disable_string_capabilities
+            se.str_node  = 0;
+            #endif
+            se.data      = 0;
+            se.ref_count = 0;
+            se.active    = false;
+         }
+      }
+
+      inline void register_return_results(expression<T>& e)
+      {
+         e.register_return_results(results_context_);
+         results_context_ = 0;
+      }
+
+      inline void load_unary_operations_map(unary_op_map_t& m)
+      {
+         #define register_unary_op(Op,UnaryFunctor)             \
+         m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
+
+         register_unary_op(details::  e_abs,details::  abs_op)
+         register_unary_op(details:: e_acos,details:: acos_op)
+         register_unary_op(details::e_acosh,details::acosh_op)
+         register_unary_op(details:: e_asin,details:: asin_op)
+         register_unary_op(details::e_asinh,details::asinh_op)
+         register_unary_op(details::e_atanh,details::atanh_op)
+         register_unary_op(details:: e_ceil,details:: ceil_op)
+         register_unary_op(details::  e_cos,details::  cos_op)
+         register_unary_op(details:: e_cosh,details:: cosh_op)
+         register_unary_op(details::  e_exp,details::  exp_op)
+         register_unary_op(details::e_expm1,details::expm1_op)
+         register_unary_op(details::e_floor,details::floor_op)
+         register_unary_op(details::  e_log,details::  log_op)
+         register_unary_op(details::e_log10,details::log10_op)
+         register_unary_op(details:: e_log2,details:: log2_op)
+         register_unary_op(details::e_log1p,details::log1p_op)
+         register_unary_op(details::  e_neg,details::  neg_op)
+         register_unary_op(details::  e_pos,details::  pos_op)
+         register_unary_op(details::e_round,details::round_op)
+         register_unary_op(details::  e_sin,details::  sin_op)
+         register_unary_op(details:: e_sinc,details:: sinc_op)
+         register_unary_op(details:: e_sinh,details:: sinh_op)
+         register_unary_op(details:: e_sqrt,details:: sqrt_op)
+         register_unary_op(details::  e_tan,details::  tan_op)
+         register_unary_op(details:: e_tanh,details:: tanh_op)
+         register_unary_op(details::  e_cot,details::  cot_op)
+         register_unary_op(details::  e_sec,details::  sec_op)
+         register_unary_op(details::  e_csc,details::  csc_op)
+         register_unary_op(details::  e_r2d,details::  r2d_op)
+         register_unary_op(details::  e_d2r,details::  d2r_op)
+         register_unary_op(details::  e_d2g,details::  d2g_op)
+         register_unary_op(details::  e_g2d,details::  g2d_op)
+         register_unary_op(details:: e_notl,details:: notl_op)
+         register_unary_op(details::  e_sgn,details::  sgn_op)
+         register_unary_op(details::  e_erf,details::  erf_op)
+         register_unary_op(details:: e_erfc,details:: erfc_op)
+         register_unary_op(details:: e_ncdf,details:: ncdf_op)
+         register_unary_op(details:: e_frac,details:: frac_op)
+         register_unary_op(details::e_trunc,details::trunc_op)
+         #undef register_unary_op
+      }
+
+      inline void load_binary_operations_map(binary_op_map_t& m)
+      {
+         typedef typename binary_op_map_t::value_type value_type;
+
+         #define register_binary_op(Op,BinaryFunctor)        \
+         m.insert(value_type(Op,BinaryFunctor<T>::process)); \
+
+         register_binary_op(details:: e_add,details:: add_op)
+         register_binary_op(details:: e_sub,details:: sub_op)
+         register_binary_op(details:: e_mul,details:: mul_op)
+         register_binary_op(details:: e_div,details:: div_op)
+         register_binary_op(details:: e_mod,details:: mod_op)
+         register_binary_op(details:: e_pow,details:: pow_op)
+         register_binary_op(details::  e_lt,details::  lt_op)
+         register_binary_op(details:: e_lte,details:: lte_op)
+         register_binary_op(details::  e_gt,details::  gt_op)
+         register_binary_op(details:: e_gte,details:: gte_op)
+         register_binary_op(details::  e_eq,details::  eq_op)
+         register_binary_op(details::  e_ne,details::  ne_op)
+         register_binary_op(details:: e_and,details:: and_op)
+         register_binary_op(details::e_nand,details::nand_op)
+         register_binary_op(details::  e_or,details::  or_op)
+         register_binary_op(details:: e_nor,details:: nor_op)
+         register_binary_op(details:: e_xor,details:: xor_op)
+         register_binary_op(details::e_xnor,details::xnor_op)
+         #undef register_binary_op
+      }
+
+      inline void load_inv_binary_operations_map(inv_binary_op_map_t& m)
+      {
+         typedef typename inv_binary_op_map_t::value_type value_type;
+
+         #define register_binary_op(Op,BinaryFunctor)        \
+         m.insert(value_type(BinaryFunctor<T>::process,Op)); \
+
+         register_binary_op(details:: e_add,details:: add_op)
+         register_binary_op(details:: e_sub,details:: sub_op)
+         register_binary_op(details:: e_mul,details:: mul_op)
+         register_binary_op(details:: e_div,details:: div_op)
+         register_binary_op(details:: e_mod,details:: mod_op)
+         register_binary_op(details:: e_pow,details:: pow_op)
+         register_binary_op(details::  e_lt,details::  lt_op)
+         register_binary_op(details:: e_lte,details:: lte_op)
+         register_binary_op(details::  e_gt,details::  gt_op)
+         register_binary_op(details:: e_gte,details:: gte_op)
+         register_binary_op(details::  e_eq,details::  eq_op)
+         register_binary_op(details::  e_ne,details::  ne_op)
+         register_binary_op(details:: e_and,details:: and_op)
+         register_binary_op(details::e_nand,details::nand_op)
+         register_binary_op(details::  e_or,details::  or_op)
+         register_binary_op(details:: e_nor,details:: nor_op)
+         register_binary_op(details:: e_xor,details:: xor_op)
+         register_binary_op(details::e_xnor,details::xnor_op)
+         #undef register_binary_op
+      }
+
+      inline void load_sf3_map(sf3_map_t& sf3_map)
+      {
+         typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
+
+         #define register_sf3(Op)                                                                             \
+         sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
+
+         register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03)
+         register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07)
+         register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11)
+         register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15)
+         register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19)
+         register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23)
+         register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27)
+         register_sf3(28) register_sf3(29) register_sf3(30)
+         #undef register_sf3
+      }
+
+      inline void load_sf4_map(sf4_map_t& sf4_map)
+      {
+         typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
+
+         #define register_sf4(Op)                                                                             \
+         sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
+
+         register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51)
+         register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55)
+         register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59)
+         register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63)
+         register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67)
+         register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71)
+         register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75)
+         register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79)
+         register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83)
+         #undef register_sf4
+
+         #define register_sf4ext(Op)                                                                                    \
+         sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
+
+         register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03)
+         register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07)
+         register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11)
+         register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15)
+         register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19)
+         register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23)
+         register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27)
+         register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31)
+         register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35)
+         register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39)
+         register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43)
+         register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47)
+         register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51)
+         register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55)
+         register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59)
+         register_sf4ext(60)
+         #undef register_sf4ext
+      }
+
+      inline results_context_t& results_ctx()
+      {
+         if (0 == results_context_)
+         {
+            results_context_ = new results_context_t();
+         }
+
+         return (*results_context_);
+      }
+
+      inline void return_cleanup()
+      {
+         if (results_context_)
+         {
+            delete results_context_;
+            results_context_ = 0;
+         }
+
+         state_.return_stmt_present = false;
+      }
+
+   private:
+
+      parser(const parser<T>&);
+      parser<T>& operator=(const parser<T>&);
+
+      settings_store settings_;
+      expression_generator<T> expression_generator_;
+      details::node_allocator node_allocator_;
+      symtab_store symtab_store_;
+      dependent_entity_collector dec_;
+      std::deque<parser_error::type> error_list_;
+      std::deque<bool> brkcnt_list_;
+      parser_state state_;
+      bool resolve_unknown_symbol_;
+      results_context_t* results_context_;
+      unknown_symbol_resolver* unknown_symbol_resolver_;
+      unknown_symbol_resolver default_usr_;
+      base_ops_map_t base_ops_map_;
+      unary_op_map_t unary_op_map_;
+      binary_op_map_t binary_op_map_;
+      inv_binary_op_map_t inv_binary_op_map_;
+      sf3_map_t sf3_map_;
+      sf4_map_t sf4_map_;
+      std::string synthesis_error_;
+      scope_element_manager sem_;
+
+      lexer::helper::helper_assembly helper_assembly_;
+
+      lexer::helper::commutative_inserter commutative_inserter_;
+      lexer::helper::operator_joiner      operator_joiner_2_;
+      lexer::helper::operator_joiner      operator_joiner_3_;
+      lexer::helper::symbol_replacer      symbol_replacer_;
+      lexer::helper::bracket_checker      bracket_checker_;
+      lexer::helper::numeric_checker      numeric_checker_;
+      lexer::helper::sequence_validator   sequence_validator_;
+   };
+
+   template <typename T>
+   inline T integrate(const expression<T>& e,
+                      T& x,
+                      const T& r0, const T& r1,
+                      const std::size_t number_of_intervals = 1000000)
+   {
+      if (r0 > r1)
+         return T(0);
+
+      T h = (r1 - r0) / (T(2) * number_of_intervals);
+      T total_area = T(0);
+
+      for (std::size_t i = 0; i < number_of_intervals; ++i)
+      {
+         x = r0 + T(2) * i * h;
+         T y0 = e.value(); x += h;
+         T y1 = e.value(); x += h;
+         T y2 = e.value(); x += h;
+         total_area += h * (y0 + T(4) * y1 + y2) / T(3);
+      }
+
+      return total_area;
+   }
+
+   template <typename T>
+   inline T integrate(const expression<T>& e,
+                      const std::string& variable_name,
+                      const T& r0, const T& r1,
+                      const std::size_t number_of_intervals = 1000000)
+   {
+      const symbol_table<T>& sym_table = e.get_symbol_table();
+
+      if (!sym_table.valid())
+         return std::numeric_limits<T>::quiet_NaN();
+
+      details::variable_node<T>* var = sym_table.get_variable(variable_name);
+
+      if (var)
+      {
+         T& x = var->ref();
+         T  x_original = x;
+         T result = integrate(e,x,r0,r1,number_of_intervals);
+         x = x_original;
+
+         return result;
+      }
+      else
+         return std::numeric_limits<T>::quiet_NaN();
+   }
+
+   template <typename T>
+   inline T derivative(const expression<T>& e,
+                       T& x,
+                       const T& h = T(0.00000001))
+   {
+      T x_init = x;
+      x = x_init + T(2) * h;
+      T y0 = e.value();
+      x = x_init + h;
+      T y1 = e.value();
+      x = x_init - h;
+      T y2 = e.value();
+      x = x_init - T(2) * h;
+      T y3 = e.value();
+      x = x_init;
+
+      return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
+   }
+
+   template <typename T>
+   inline T second_derivative(const expression<T>& e,
+                              T& x,
+                              const T& h = T(0.00001))
+   {
+      T y = e.value();
+      T x_init = x;
+      x = x_init + T(2) * h;
+      T y0 = e.value();
+      x = x_init + h;
+      T y1 = e.value();
+      x = x_init - h;
+      T y2 = e.value();
+      x = x_init - T(2) * h;
+      T y3 = e.value();
+      x = x_init;
+
+      return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
+   }
+
+   template <typename T>
+   inline T third_derivative(const expression<T>& e,
+                             T& x,
+                             const T& h = T(0.0001))
+   {
+      T x_init = x;
+      x = x_init + T(2) * h;
+      T y0 = e.value();
+      x = x_init + h;
+      T y1 = e.value();
+      x = x_init - h;
+      T y2 = e.value();
+      x = x_init - T(2) * h;
+      T y3 = e.value();
+      x = x_init;
+
+      return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
+   }
+
+   template <typename T>
+   inline T derivative(const expression<T>& e,
+                       const std::string& variable_name,
+                       const T& h = T(0.00000001))
+   {
+      const symbol_table<T>& sym_table = e.get_symbol_table();
+
+      if (!sym_table.valid())
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      details::variable_node<T>* var = sym_table.get_variable(variable_name);
+
+      if (var)
+      {
+         T& x = var->ref();
+         T x_original = x;
+         T result = derivative(e,x,h);
+         x = x_original;
+
+         return result;
+      }
+      else
+         return std::numeric_limits<T>::quiet_NaN();
+   }
+
+   template <typename T>
+   inline T second_derivative(const expression<T>& e,
+                              const std::string& variable_name,
+                              const T& h = T(0.00001))
+   {
+      const symbol_table<T>& sym_table = e.get_symbol_table();
+
+      if (!sym_table.valid())
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      details::variable_node<T>* var = sym_table.get_variable(variable_name);
+
+      if (var)
+      {
+         T& x = var->ref();
+         T x_original = x;
+         T result = second_derivative(e,x,h);
+         x = x_original;
+
+         return result;
+      }
+      else
+         return std::numeric_limits<T>::quiet_NaN();
+   }
+
+   template <typename T>
+   inline T third_derivative(const expression<T>& e,
+                             const std::string& variable_name,
+                             const T& h = T(0.0001))
+   {
+      const symbol_table<T>& sym_table = e.get_symbol_table();
+
+      if (!sym_table.valid())
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      details::variable_node<T>* var = sym_table.get_variable(variable_name);
+
+      if (var)
+      {
+         T& x = var->ref();
+         T x_original = x;
+         T result = third_derivative(e,x,h);
+         x = x_original;
+
+         return result;
+      }
+      else
+         return std::numeric_limits<T>::quiet_NaN();
+   }
+
+   /*
+      Note: The following 'compute' routines are simple helpers,
+      for quickly setting up the required pieces of code in order
+      to evaluate an expression. By virtue of how they operate
+      there will be an overhead with regards to their setup and
+      teardown and hence should not be used in time critical
+      sections of code.
+      Furthermore they only assume a small sub set of variables - no
+      string variables or user defined functions.
+   */
+   template <typename T>
+   inline bool compute(const std::string& expression_string, T& result)
+   {
+      // No variables
+      symbol_table<T> symbol_table;
+      symbol_table.add_constants();
+
+      expression<T> expression;
+      parser<T> parser;
+
+      if (parser.compile(expression_string,expression))
+      {
+         result = expression.value();
+
+         return true;
+      }
+      else
+         return false;
+   }
+
+   template <typename T>
+   inline bool compute(const std::string& expression_string,
+                       const T& x,
+                       T& result)
+   {
+      // Only 'x'
+      static const std::string x_var("x");
+
+      symbol_table<T> symbol_table;
+      symbol_table.add_constants();
+      symbol_table.add_variable(x_var,x);
+
+      expression<T> expression;
+      parser<T> parser;
+
+      if (parser.compile(expression_string,expression))
+      {
+         result = expression.value();
+
+         return true;
+      }
+      else
+         return false;
+   }
+
+   template <typename T>
+   inline bool compute(const std::string& expression_string,
+                       const T&x, const T& y,
+                       T& result)
+   {
+      // Only 'x' and 'y'
+      static const std::string x_var("x");
+      static const std::string y_var("y");
+
+      symbol_table<T> symbol_table;
+      symbol_table.add_constants();
+      symbol_table.add_variable(x_var,x);
+      symbol_table.add_variable(y_var,y);
+
+      expression<T> expression;
+      parser<T> parser;
+
+      if (parser.compile(expression_string,expression))
+      {
+         result = expression.value();
+
+         return true;
+      }
+      else
+         return false;
+   }
+
+   template <typename T>
+   inline bool compute(const std::string& expression_string,
+                       const T& x, const T& y, const T& z,
+                       T& result)
+   {
+      // Only 'x', 'y' or 'z'
+      static const std::string x_var("x");
+      static const std::string y_var("y");
+      static const std::string z_var("z");
+
+      symbol_table<T> symbol_table;
+      symbol_table.add_constants();
+      symbol_table.add_variable(x_var,x);
+      symbol_table.add_variable(y_var,y);
+      symbol_table.add_variable(z_var,z);
+
+      expression<T> expression;
+      parser<T> parser;
+
+      if (parser.compile(expression_string,expression))
+      {
+         result = expression.value();
+
+         return true;
+      }
+      else
+         return false;
+   }
+
+   template <typename T, std::size_t N>
+   class polynomial : public ifunction<T>
+   {
+   private:
+
+      template <typename Type, std::size_t NumberOfCoefficients>
+      struct poly_impl { };
+
+      template <typename Type>
+      struct poly_impl <Type,12>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
+                                  const Type  c7, const Type  c6, const Type  c5, const Type c4, const Type c3,
+                                  const Type  c2, const Type  c1, const Type  c0)
+         {
+            // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,11>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
+                                  const Type c6,  const Type  c5, const Type c4, const Type c3, const Type c2,
+                                  const Type c1,  const Type  c0)
+         {
+            // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,10>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
+                                  const Type c5,  const Type c4, const Type c3, const Type c2, const Type c1,
+                                  const Type c0)
+         {
+            // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,9>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
+                                  const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
+         {
+            // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,8>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
+                                  const Type c3, const Type c2, const Type c1, const Type c0)
+         {
+            // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,7>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
+                                  const Type c2, const Type c1, const Type c0)
+         {
+            // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,6>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
+                                  const Type c1, const Type c0)
+         {
+            // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,5>
+      {
+         static inline T evaluate(const Type x,
+                                  const Type c5, const Type c4, const Type c3, const Type c2,
+                                  const Type c1, const Type c0)
+         {
+            // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,4>
+      {
+         static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
+         {
+            // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,3>
+      {
+         static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
+         {
+            // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
+            return (((c3 * x + c2) * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,2>
+      {
+         static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
+         {
+            // p(x) = c_2x^2 + c_1x^1 + c_0x^0
+            return ((c2 * x + c1) * x + c0);
+         }
+      };
+
+      template <typename Type>
+      struct poly_impl <Type,1>
+      {
+         static inline T evaluate(const Type x, const Type c1, const Type c0)
+         {
+            // p(x) = c_1x^1 + c_0x^0
+            return (c1 * x + c0);
+         }
+      };
+
+   public:
+
+      polynomial()
+      : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
+      {
+         disable_has_side_effects(*this);
+      }
+
+      virtual ~polynomial()
+      {}
+
+      inline virtual T operator()(const T& x, const T& c1, const T& c0)
+      {
+         return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0)
+      {
+         return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((9 == N) ? poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((10 == N) ? poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((11 == N) ? poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()(const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
+      {
+         return ((12 == N) ? poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
+      }
+
+      inline virtual T operator()()
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+
+      inline virtual T operator()(const T&, const T&)
+      {
+         return std::numeric_limits<T>::quiet_NaN();
+      }
+   };
+
+   template <typename T>
+   class function_compositor
+   {
+   public:
+
+      typedef exprtk::expression<T>             expression_t;
+      typedef exprtk::symbol_table<T>           symbol_table_t;
+      typedef exprtk::parser<T>                 parser_t;
+      typedef typename parser_t::settings_store settings_t;
+
+      struct function
+      {
+         function()
+         {}
+
+         function(const std::string& n)
+         : name_(n)
+         {}
+
+         function(const std::string& name,
+                  const std::string& expression)
+         : name_(name),
+           expression_(expression)
+         {}
+
+         function(const std::string& name,
+                  const std::string& expression,
+                  const std::string& v0)
+         : name_(name),
+           expression_(expression)
+         {
+            v_.push_back(v0);
+         }
+
+         function(const std::string& name,
+                  const std::string& expression,
+                  const std::string& v0, const std::string& v1)
+         : name_(name),
+           expression_(expression)
+         {
+            v_.push_back(v0); v_.push_back(v1);
+         }
+
+         function(const std::string& name,
+                  const std::string& expression,
+                  const std::string& v0, const std::string& v1,
+                  const std::string& v2)
+         : name_(name),
+           expression_(expression)
+         {
+            v_.push_back(v0); v_.push_back(v1);
+            v_.push_back(v2);
+         }
+
+         function(const std::string& name,
+                  const std::string& expression,
+                  const std::string& v0, const std::string& v1,
+                  const std::string& v2, const std::string& v3)
+         : name_(name),
+           expression_(expression)
+         {
+            v_.push_back(v0); v_.push_back(v1);
+            v_.push_back(v2); v_.push_back(v3);
+         }
+
+         inline function& name(const std::string& n)
+         {
+            name_ = n;
+            return (*this);
+         }
+
+         inline function& expression(const std::string& e)
+         {
+            expression_ = e;
+            return (*this);
+         }
+
+         inline function& var(const std::string& v)
+         {
+            v_.push_back(v);
+            return (*this);
+         }
+
+         std::string name_;
+         std::string expression_;
+         std::deque<std::string> v_;
+      };
+
+   private:
+
+      struct base_func : public exprtk::ifunction<T>
+      {
+         typedef const T& type;
+         typedef exprtk::ifunction<T> function_t;
+         typedef std::vector<T*> varref_t;
+         typedef std::vector<T> var_t;
+         typedef std::pair<T*,std::size_t> lvarref_t;
+         typedef std::vector<lvarref_t> lvr_vec_t;
+
+         base_func(const std::size_t& pc = 0)
+         : exprtk::ifunction<T>(pc),
+           local_var_stack_size(0),
+           stack_depth(0)
+         {
+            v.resize(pc);
+         }
+
+         virtual ~base_func()
+         {}
+
+         inline void update(const T& v0)
+         {
+            (*v[0]) = v0;
+         }
+
+         inline void update(const T& v0, const T& v1)
+         {
+            (*v[0]) = v0; (*v[1]) = v1;
+         }
+
+         inline void update(const T& v0, const T& v1, const T& v2)
+         {
+            (*v[0]) = v0; (*v[1]) = v1;
+            (*v[2]) = v2;
+         }
+
+         inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
+         {
+            (*v[0]) = v0; (*v[1]) = v1;
+            (*v[2]) = v2; (*v[3]) = v3;
+         }
+
+         inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
+         {
+            (*v[0]) = v0; (*v[1]) = v1;
+            (*v[2]) = v2; (*v[3]) = v3;
+            (*v[4]) = v4;
+         }
+
+         inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
+         {
+            (*v[0]) = v0; (*v[1]) = v1;
+            (*v[2]) = v2; (*v[3]) = v3;
+            (*v[4]) = v4; (*v[5]) = v5;
+         }
+
+         inline function_t& setup(expression_t& expr)
+         {
+            expression = expr;
+
+            typedef typename expression_t::expression_holder::local_data_list_t ldl_t;
+            ldl_t ldl = expr.local_data_list();
+
+            std::vector<std::size_t> index_list;
+
+            for (std::size_t i = 0; i < ldl.size(); ++i)
+            {
+               if (ldl[i].size)
+               {
+                  index_list.push_back(i);
+               }
+            }
+
+            std::size_t input_param_count = 0;
+
+            for (std::size_t i = 0; i < index_list.size(); ++i)
+            {
+               const std::size_t index = index_list[i];
+
+               if (i < (index_list.size() - v.size()))
+               {
+                  lv.push_back(
+                        std::make_pair(
+                           reinterpret_cast<T*>(ldl[index].pointer),
+                           ldl[index].size));
+
+                  local_var_stack_size += ldl[index].size;
+               }
+               else
+                  v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
+            }
+
+            clear_stack();
+
+            return (*this);
+         }
+
+         inline void pre()
+         {
+            if (stack_depth++)
+            {
+               if (!v.empty())
+               {
+                  var_t var_stack(v.size(),T(0));
+                  copy(v,var_stack);
+                  param_stack.push_back(var_stack);
+               }
+
+               if (!lv.empty())
+               {
+                  var_t local_var_stack(local_var_stack_size,T(0));
+                  copy(lv,local_var_stack);
+                  local_stack.push_back(local_var_stack);
+               }
+            }
+         }
+
+         inline void post()
+         {
+            if (--stack_depth)
+            {
+               if (!v.empty())
+               {
+                  copy(param_stack.back(),v);
+                  param_stack.pop_back();
+               }
+
+               if (!lv.empty())
+               {
+                  copy(local_stack.back(),lv);
+                  local_stack.pop_back();
+               }
+            }
+         }
+
+         void copy(const varref_t& src_v, var_t& dest_v)
+         {
+            for (std::size_t i = 0; i < src_v.size(); ++i)
+            {
+               dest_v[i] = (*src_v[i]);
+            }
+         }
+
+         void copy(const var_t& src_v, varref_t& dest_v)
+         {
+            for (std::size_t i = 0; i < src_v.size(); ++i)
+            {
+               (*dest_v[i]) = src_v[i];
+            }
+         }
+
+         void copy(const lvr_vec_t& src_v, var_t& dest_v)
+         {
+            typename var_t::iterator itr = dest_v.begin();
+
+            for (std::size_t i = 0; i < src_v.size(); ++i)
+            {
+               lvarref_t vr = src_v[i];
+
+               if (1 == vr.second)
+                  *itr++ = (*vr.first);
+               else
+               {
+                  std::copy(vr.first,vr.first + vr.second,itr);
+                  itr += vr.second;
+               }
+            }
+         }
+
+         void copy(const var_t& src_v, lvr_vec_t& dest_v)
+         {
+            typename var_t::const_iterator itr = src_v.begin();
+
+            for (std::size_t i = 0; i < src_v.size(); ++i)
+            {
+               lvarref_t vr = dest_v[i];
+
+               if (1 == vr.second)
+                  (*vr.first) = *itr++;
+               else
+               {
+                  std::copy(itr,itr + vr.second,vr.first);
+                  itr += vr.second;
+               }
+            }
+         }
+
+         inline void clear_stack()
+         {
+            for (std::size_t i = 0; i < v.size(); ++i)
+            {
+               (*v[i]) = 0;
+            }
+         }
+
+         inline virtual T value(expression_t& e)
+         {
+            return e.value();
+         }
+
+         expression_t expression;
+         varref_t v;
+         lvr_vec_t lv;
+         std::size_t local_var_stack_size;
+         std::size_t stack_depth;
+         std::deque<var_t> param_stack;
+         std::deque<var_t> local_stack;
+      };
+
+      typedef std::map<std::string,base_func*> funcparam_t;
+
+      struct func_0param : public base_func
+      {
+         func_0param() : base_func(0) {}
+
+         inline T operator()()
+         {
+            return this->value(base_func::expression);
+         }
+      };
+
+      typedef const T& type;
+
+      struct func_1param : public base_func
+      {
+         func_1param() : base_func(1) {}
+
+         inline T operator()(type v0)
+         {
+            base_func::pre();
+            base_func::update(v0);
+            T result = this->value(base_func::expression);
+            base_func::post();
+            return result;
+         }
+      };
+
+      struct func_2param : public base_func
+      {
+         func_2param() : base_func(2) {}
+
+         inline T operator()(type v0, type v1)
+         {
+            base_func::pre();
+            base_func::update(v0,v1);
+            T result = this->value(base_func::expression);
+            base_func::post();
+            return result;
+         }
+      };
+
+      struct func_3param : public base_func
+      {
+         func_3param() : base_func(3) {}
+
+         inline T operator()(type v0, type v1, type v2)
+         {
+            base_func::pre();
+            base_func::update(v0,v1,v2);
+            T result = this->value(base_func::expression);
+            base_func::post();
+            return result;
+         }
+      };
+
+      struct func_4param : public base_func
+      {
+         func_4param() : base_func(4) {}
+
+         inline T operator()(type v0, type v1, type v2, type v3)
+         {
+            base_func::pre();
+            base_func::update(v0,v1,v2,v3);
+            T result = this->value(base_func::expression);
+            base_func::post();
+            return result;
+         }
+      };
+
+      struct func_5param : public base_func
+      {
+         func_5param() : base_func(5) {}
+
+         inline T operator()(type v0, type v1, type v2, type v3, type v4)
+         {
+            base_func::pre();
+            base_func::update(v0,v1,v2,v3,v4);
+            T result = this->value(base_func::expression);
+            base_func::post();
+            return result;
+         }
+      };
+
+      struct func_6param : public base_func
+      {
+         func_6param() : base_func(6) {}
+
+         inline T operator()(type v0, type v1, type v2, type v3, type v4, type v5)
+         {
+            base_func::pre();
+            base_func::update(v0,v1,v2,v3,v4,v5);
+            T result = this->value(base_func::expression);
+            base_func::post();
+            return result;
+         }
+      };
+
+      static T return_value(expression_t& e)
+      {
+         typedef exprtk::results_context<T> results_context_t;
+         typedef typename results_context_t::type_store_t type_t;
+         typedef typename type_t::scalar_view scalar_t;
+
+         T result = e.value();
+
+         if (e.return_invoked())
+         {
+            // Due to the post compilation checks, it can be safely
+            // assumed that there will be at least one parameter
+            // and that the first parameter will always be scalar.
+            return scalar_t(e.results()[0])();
+         }
+
+         return result;
+      }
+
+      #define def_fp_retval(N)                               \
+      struct func_##N##param_retval : public func_##N##param \
+      {                                                      \
+         inline T value(expression_t& e)                     \
+         {                                                   \
+            return return_value(e);                          \
+         }                                                   \
+      };                                                     \
+
+      def_fp_retval(0)
+      def_fp_retval(1)
+      def_fp_retval(2)
+      def_fp_retval(3)
+      def_fp_retval(4)
+      def_fp_retval(5)
+      def_fp_retval(6)
+
+      template <typename Allocator,
+                template <typename,typename> class Sequence>
+      inline bool add(const std::string& name,
+                      const std::string& expression,
+                      const Sequence<std::string,Allocator>& var_list,
+                      const bool override = false)
+      {
+         const std::size_t n = var_list.size();
+
+         typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
+
+         if (expr_map_.end() != itr)
+         {
+            if (!override)
+            {
+               exprtk_debug(("Compositor error(add): function '%s' already defined\n",
+                             name.c_str()));
+
+               return false;
+            }
+
+            remove(name, var_list.size());
+         }
+
+         if (compile_expression(name,expression,var_list))
+         {
+            fp_map_[n][name]->setup(expr_map_[name]);
+            return true;
+         }
+         else
+         {
+            exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
+                          name.c_str()));
+
+            return false;
+         }
+      }
+
+   public:
+
+      function_compositor()
+      : parser_(settings_t::compile_all_opts +
+                settings_t::e_disable_zero_return),
+        fp_map_(7)
+      {}
+
+      function_compositor(const symbol_table_t& st)
+      : symbol_table_(st),
+        parser_(settings_t::compile_all_opts +
+                settings_t::e_disable_zero_return),
+        fp_map_(7)
+      {}
+
+     ~function_compositor()
+      {
+         clear();
+      }
+
+      inline symbol_table_t& symbol_table()
+      {
+         return symbol_table_;
+      }
+
+      inline void add_auxiliary_symtab(symbol_table_t& symtab)
+      {
+         auxiliary_symtab_list_.push_back(&symtab);
+      }
+
+      void clear()
+      {
+         symbol_table_.clear();
+         expr_map_    .clear();
+
+         for (std::size_t i = 0; i < fp_map_.size(); ++i)
+         {
+            typename funcparam_t::iterator itr = fp_map_[i].begin();
+            typename funcparam_t::iterator end = fp_map_[i].end  ();
+
+            while (itr != end)
+            {
+               delete itr->second;
+               ++itr;
+            }
+
+            fp_map_[i].clear();
+         }
+      }
+
+      inline bool add(const function& f, const bool override = false)
+      {
+         return add(f.name_,f.expression_,f.v_,override);
+      }
+
+   private:
+
+      template <typename Allocator,
+                template <typename,typename> class Sequence>
+      bool compile_expression(const std::string& name,
+                              const std::string& expression,
+                              const Sequence<std::string,Allocator>& input_var_list,
+                              bool  return_present = false)
+      {
+         expression_t compiled_expression;
+         symbol_table_t local_symbol_table;
+
+         local_symbol_table.load_from(symbol_table_);
+         local_symbol_table.add_constants();
+
+         if (!valid(name,input_var_list.size()))
+            return false;
+
+         if (!forward(name,
+                      input_var_list.size(),
+                      local_symbol_table,
+                      return_present))
+            return false;
+
+         compiled_expression.register_symbol_table(local_symbol_table);
+
+         for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
+         {
+            compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
+         }
+
+         std::string mod_expression;
+
+         for (std::size_t i = 0; i < input_var_list.size(); ++i)
+         {
+            mod_expression += " var " + input_var_list[i] + "{};\n";
+         }
+
+         if (
+              ('{' == details::front(expression)) &&
+              ('}' == details::back (expression))
+            )
+            mod_expression += "~" + expression + ";";
+         else
+            mod_expression += "~{" + expression + "};";
+
+         if (!parser_.compile(mod_expression,compiled_expression))
+         {
+            exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
+            exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
+
+            remove(name,input_var_list.size());
+
+            return false;
+         }
+
+         if (!return_present && parser_.dec().return_present())
+         {
+            remove(name,input_var_list.size());
+
+            return compile_expression(name,expression,input_var_list,true);
+         }
+
+         // Make sure every return point has a scalar as its first parameter
+         if (parser_.dec().return_present())
+         {
+            typedef std::vector<std::string> str_list_t;
+
+            str_list_t ret_param_list = parser_.dec().return_param_type_list();
+
+            for (std::size_t i = 0; i < ret_param_list.size(); ++i)
+            {
+               const std::string& params = ret_param_list[i];
+
+               if (params.empty() || ('T' != params[0]))
+               {
+                  exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
+                                name.c_str()));
+
+                  remove(name,input_var_list.size());
+
+                  return false;
+               }
+            }
+         }
+
+         expr_map_[name] = compiled_expression;
+
+         exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
+
+         if (symbol_table_.add_function(name,ifunc))
+            return true;
+         else
+         {
+            exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
+                          name.c_str()));
+            return false;
+         }
+      }
+
+      inline bool symbol_used(const std::string& symbol) const
+      {
+         return (
+                  symbol_table_.is_variable       (symbol) ||
+                  symbol_table_.is_stringvar      (symbol) ||
+                  symbol_table_.is_function       (symbol) ||
+                  symbol_table_.is_vector         (symbol) ||
+                  symbol_table_.is_vararg_function(symbol)
+                );
+      }
+
+      inline bool valid(const std::string& name,
+                        const std::size_t& arg_count) const
+      {
+         if (arg_count > 6)
+            return false;
+         else if (symbol_used(name))
+            return false;
+         else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
+            return false;
+         else
+            return true;
+      }
+
+      inline bool forward(const std::string& name,
+                          const std::size_t& arg_count,
+                          symbol_table_t& sym_table,
+                          const bool ret_present = false)
+      {
+         switch (arg_count)
+         {
+            #define case_stmt(N)                                     \
+            case N : (fp_map_[arg_count])[name] =                    \
+                     (!ret_present) ? static_cast<base_func*>        \
+                                      (new func_##N##param) :        \
+                                      static_cast<base_func*>        \
+                                      (new func_##N##param_retval) ; \
+                     break;                                          \
+
+            case_stmt(0) case_stmt(1) case_stmt(2)
+            case_stmt(3) case_stmt(4) case_stmt(5)
+            case_stmt(6)
+            #undef case_stmt
+         }
+
+         exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
+
+         return sym_table.add_function(name,ifunc);
+      }
+
+      inline void remove(const std::string& name, const std::size_t& arg_count)
+      {
+         if (arg_count > 6)
+            return;
+
+         typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
+
+         if (expr_map_.end() != em_itr)
+         {
+            expr_map_.erase(em_itr);
+         }
+
+         typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
+
+         if (fp_map_[arg_count].end() != fp_itr)
+         {
+            delete fp_itr->second;
+            fp_map_[arg_count].erase(fp_itr);
+         }
+
+         symbol_table_.remove_function(name);
+      }
+
+   private:
+
+      symbol_table_t symbol_table_;
+      parser_t parser_;
+      std::map<std::string,expression_t> expr_map_;
+      std::vector<funcparam_t> fp_map_;
+      std::vector<symbol_table_t*> auxiliary_symtab_list_;
+   };
+
+   template <typename T>
+   inline bool pgo_primer()
+   {
+      static const std::string expression_list[]
+                                        = {
+                                             "(y + x)",
+                                             "2 * (y + x)",
+                                             "(2 * y + 2 * x)",
+                                             "(y + x / y) * (x - y / x)",
+                                             "x / ((x + y) * (x - y)) / y",
+                                             "1 - ((x * y) + (y / x)) - 3",
+                                             "sin(2 * x) + cos(pi / y)",
+                                             "1 - sin(2 * x) + cos(pi / y)",
+                                             "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
+                                             "(x^2 / sin(2 * pi / y)) -x / 2",
+                                             "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
+                                             "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
+                                             "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
+                                             "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
+                                             "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
+                                             "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
+                                             "(yy + xx)",
+                                             "2 * (yy + xx)",
+                                             "(2 * yy + 2 * xx)",
+                                             "(yy + xx / yy) * (xx - yy / xx)",
+                                             "xx / ((xx + yy) * (xx - yy)) / yy",
+                                             "1 - ((xx * yy) + (yy / xx)) - 3",
+                                             "sin(2 * xx) + cos(pi / yy)",
+                                             "1 - sin(2 * xx) + cos(pi / yy)",
+                                             "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
+                                             "(xx^2 / sin(2 * pi / yy)) -xx / 2",
+                                             "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
+                                             "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
+                                             "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
+                                             "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
+                                             "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
+                                             "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
+                                             "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
+                                             "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
+                                             "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
+                                             "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
+                                             "(x + 2) * 3", "x + (2 * 3)",
+                                             "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
+                                             "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
+                                             "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
+                                             "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
+                                             "2 + (x * (y / 3))", "x + (2 * (3 / y))",
+                                             "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
+                                             "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
+                                             "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
+                                             "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
+                                             "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
+                                             "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
+                                             "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
+                                             "((x + (2 * 3)) / y)",
+                                             "(xx + yy) * zz", "xx + (yy * zz)",
+                                             "(xx + yy) * 7", "xx + (yy * 7)",
+                                             "(xx + 7) * yy", "xx + (7 * yy)",
+                                             "(7 + xx) * yy", "7 + (xx * yy)",
+                                             "(2 + x) * 3", "2 + (x * 3)",
+                                             "(2 + 3) * x", "2 + (3 * x)",
+                                             "(x + 2) * 3", "x + (2 * 3)",
+                                             "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
+                                             "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
+                                             "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
+                                             "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
+                                             "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
+                                             "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
+                                             "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
+                                             "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
+                                             "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
+                                             "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
+                                             "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
+                                             "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
+                                             "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
+                                             "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
+                                             "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
+                                             "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
+                                             "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
+                                             "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
+                                             "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
+                                             "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
+                                             "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
+                                             "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
+                                             "((xx + (2 * 3)) / yy)"
+                                          };
+      static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
+
+      T  x = T(0);
+      T  y = T(0);
+      T  z = T(0);
+      T  w = T(0);
+      T xx = T(0);
+      T yy = T(0);
+      T zz = T(0);
+      T ww = T(0);
+
+      exprtk::symbol_table<T> symbol_table;
+      symbol_table.add_constants();
+      symbol_table.add_variable( "x", x);
+      symbol_table.add_variable( "y", y);
+      symbol_table.add_variable( "z", z);
+      symbol_table.add_variable( "w", w);
+      symbol_table.add_variable("xx",xx);
+      symbol_table.add_variable("yy",yy);
+      symbol_table.add_variable("zz",zz);
+      symbol_table.add_variable("ww",ww);
+
+      typedef typename std::deque<exprtk::expression<T> > expr_list_t;
+      expr_list_t expr_list;
+
+      const std::size_t rounds = 50;
+
+      {
+         for (std::size_t r = 0; r < rounds; ++r)
+         {
+            expr_list.clear();
+            exprtk::parser<T> parser;
+
+            for (std::size_t i = 0; i < expression_list_size; ++i)
+            {
+               exprtk::expression<T> expression;
+               expression.register_symbol_table(symbol_table);
+
+               if (!parser.compile(expression_list[i],expression))
+               {
+                  return false;
+               }
+
+               expr_list.push_back(expression);
+            }
+         }
+      }
+
+      struct execute
+      {
+         static inline T process(T& x, T& y, expression<T>& expression)
+         {
+            static const T lower_bound = T(-20);
+            static const T upper_bound = T(+20);
+
+            T delta = T(0.1);
+            T total = T(0);
+
+            for (x = lower_bound; x <= upper_bound; x += delta)
+            {
+               for (y = lower_bound; y <= upper_bound; y += delta)
+               {
+                  total += expression.value();
+               }
+            }
+
+            return total;
+         }
+      };
+
+      for (std::size_t i = 0; i < expr_list.size(); ++i)
+      {
+         execute::process( x, y,expr_list[i]);
+         execute::process(xx,yy,expr_list[i]);
+      }
+
+      {
+         for (std::size_t i = 0; i < 10000; ++i)
+         {
+            T v = T(123.456 + i);
+                 if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 2>::result(v),details::numeric::pow(v,T( 2))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 3>::result(v),details::numeric::pow(v,T( 3))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 4>::result(v),details::numeric::pow(v,T( 4))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 5>::result(v),details::numeric::pow(v,T( 5))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 6>::result(v),details::numeric::pow(v,T( 6))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 7>::result(v),details::numeric::pow(v,T( 7))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 8>::result(v),details::numeric::pow(v,T( 8))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 9>::result(v),details::numeric::pow(v,T( 9))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,10>::result(v),details::numeric::pow(v,T(10))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,11>::result(v),details::numeric::pow(v,T(11))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,12>::result(v),details::numeric::pow(v,T(12))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,13>::result(v),details::numeric::pow(v,T(13))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,14>::result(v),details::numeric::pow(v,T(14))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,15>::result(v),details::numeric::pow(v,T(15))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,16>::result(v),details::numeric::pow(v,T(16))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,17>::result(v),details::numeric::pow(v,T(17))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,18>::result(v),details::numeric::pow(v,T(18))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,19>::result(v),details::numeric::pow(v,T(19))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,20>::result(v),details::numeric::pow(v,T(20))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,21>::result(v),details::numeric::pow(v,T(21))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,22>::result(v),details::numeric::pow(v,T(22))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,23>::result(v),details::numeric::pow(v,T(23))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,24>::result(v),details::numeric::pow(v,T(24))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,25>::result(v),details::numeric::pow(v,T(25))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,26>::result(v),details::numeric::pow(v,T(26))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,27>::result(v),details::numeric::pow(v,T(27))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,28>::result(v),details::numeric::pow(v,T(28))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,29>::result(v),details::numeric::pow(v,T(29))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,30>::result(v),details::numeric::pow(v,T(30))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,31>::result(v),details::numeric::pow(v,T(31))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,32>::result(v),details::numeric::pow(v,T(32))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,33>::result(v),details::numeric::pow(v,T(33))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,34>::result(v),details::numeric::pow(v,T(34))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,35>::result(v),details::numeric::pow(v,T(35))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,36>::result(v),details::numeric::pow(v,T(36))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,37>::result(v),details::numeric::pow(v,T(37))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,38>::result(v),details::numeric::pow(v,T(38))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,39>::result(v),details::numeric::pow(v,T(39))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,40>::result(v),details::numeric::pow(v,T(40))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,41>::result(v),details::numeric::pow(v,T(41))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,42>::result(v),details::numeric::pow(v,T(42))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,43>::result(v),details::numeric::pow(v,T(43))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,44>::result(v),details::numeric::pow(v,T(44))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,45>::result(v),details::numeric::pow(v,T(45))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,46>::result(v),details::numeric::pow(v,T(46))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,47>::result(v),details::numeric::pow(v,T(47))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,48>::result(v),details::numeric::pow(v,T(48))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,49>::result(v),details::numeric::pow(v,T(49))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,50>::result(v),details::numeric::pow(v,T(50))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,51>::result(v),details::numeric::pow(v,T(51))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,52>::result(v),details::numeric::pow(v,T(52))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,53>::result(v),details::numeric::pow(v,T(53))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,54>::result(v),details::numeric::pow(v,T(54))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,55>::result(v),details::numeric::pow(v,T(55))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,56>::result(v),details::numeric::pow(v,T(56))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,57>::result(v),details::numeric::pow(v,T(57))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,58>::result(v),details::numeric::pow(v,T(58))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,59>::result(v),details::numeric::pow(v,T(59))))) return false;
+            else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,60>::result(v),details::numeric::pow(v,T(60))))) return false;
+         }
+      }
+
+      return true;
+   }
+
+   namespace helper
+   {
+      namespace details
+      {
+         template <typename T>
+         inline void print_type(const std::string& fmt,
+                                const T v,
+                                exprtk::details::numeric::details::real_type_tag)
+         {
+            printf(fmt.c_str(),v);
+         }
+
+         template <typename T>
+         struct print_impl
+         {
+            typedef typename igeneric_function<T>::generic_type generic_type;
+            typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
+            typedef typename generic_type::scalar_view scalar_t;
+            typedef typename generic_type::vector_view vector_t;
+            typedef typename generic_type::string_view string_t;
+
+            static void process(const std::string& scalar_format, parameter_list_t parameters)
+            {
+               for (std::size_t i = 0; i < parameters.size(); ++i)
+               {
+                  generic_type& gt = parameters[i];
+
+                  typename exprtk::details::numeric::details::number_type<T>::type num_type;
+
+                  switch (gt.type)
+                  {
+                     case generic_type::e_scalar : print_type(scalar_format,scalar_t(gt)(),num_type);
+                                                   break;
+
+                     case generic_type::e_vector : {
+                                                      vector_t vector(gt);
+
+                                                      for (std::size_t x = 0; x < vector.size(); ++x)
+                                                      {
+                                                         print_type(scalar_format,vector[x],num_type);
+
+                                                         if ((x + 1) < vector.size())
+                                                            printf(" ");
+                                                      }
+                                                   }
+                                                   break;
+
+                     case generic_type::e_string : printf("%s",to_str(string_t(gt)).c_str());
+                                                   break;
+
+                     default                     : continue;
+                  }
+               }
+            }
+         };
+      }
+
+      template <typename T>
+      struct print : public exprtk::igeneric_function<T>
+      {
+         typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
+
+         print(const std::string& scalar_format = "%10.5f")
+         : scalar_format_(scalar_format)
+         {
+            exprtk::enable_zero_parameters(*this);
+         }
+
+         inline T operator()(parameter_list_t parameters)
+         {
+            details::print_impl<T>::process(scalar_format_,parameters);
+            return T(0);
+         }
+
+         std::string scalar_format_;
+      };
+
+      template <typename T>
+      struct println : public exprtk::igeneric_function<T>
+      {
+         typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
+
+         println(const std::string& scalar_format = "%10.5f")
+         : scalar_format_(scalar_format)
+         {
+            exprtk::enable_zero_parameters(*this);
+         }
+
+         inline T operator()(parameter_list_t parameters)
+         {
+            details::print_impl<T>::process(scalar_format_,parameters);
+            printf("\n");
+            return T(0);
+         }
+
+         std::string scalar_format_;
+      };
+   }
+}
+
+#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+#   ifndef NOMINMAX
+#      define NOMINMAX
+#   endif
+#   ifndef WIN32_LEAN_AND_MEAN
+#      define WIN32_LEAN_AND_MEAN
+#   endif
+#   include <windows.h>
+#   include <ctime>
+#else
+#   include <ctime>
+#   include <sys/time.h>
+#   include <sys/types.h>
+#endif
+
+namespace exprtk
+{
+
+   class timer
+   {
+   public:
+
+      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+      timer()
+      : in_use_(false)
+      {
+         QueryPerformanceFrequency(&clock_frequency_);
+      }
+
+      inline void start()
+      {
+         in_use_ = true;
+         QueryPerformanceCounter(&start_time_);
+      }
+
+      inline void stop()
+      {
+         QueryPerformanceCounter(&stop_time_);
+         in_use_ = false;
+      }
+
+      inline double time() const
+      {
+         return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
+      }
+
+      #else
+
+      timer()
+      : in_use_(false)
+      {
+         start_time_.tv_sec  = 0;
+         start_time_.tv_usec = 0;
+         stop_time_.tv_sec   = 0;
+         stop_time_.tv_usec  = 0;
+      }
+
+      inline void start()
+      {
+         in_use_ = true;
+         gettimeofday(&start_time_,0);
+      }
+
+      inline void stop()
+      {
+         gettimeofday(&stop_time_, 0);
+         in_use_ = false;
+      }
+
+      inline unsigned long long int usec_time() const
+      {
+         if (!in_use_)
+         {
+            if (stop_time_.tv_sec >= start_time_.tv_sec)
+            {
+               return 1000000 * (stop_time_.tv_sec  - start_time_.tv_sec ) +
+                                (stop_time_.tv_usec - start_time_.tv_usec);
+            }
+            else
+               return std::numeric_limits<unsigned long long int>::max();
+         }
+         else
+            return std::numeric_limits<unsigned long long int>::max();
+      }
+
+      inline double time() const
+      {
+         return usec_time() * 0.000001;
+      }
+
+      #endif
+
+      inline bool in_use() const
+      {
+         return in_use_;
+      }
+
+   private:
+
+      bool in_use_;
+
+      #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+         LARGE_INTEGER start_time_;
+         LARGE_INTEGER stop_time_;
+         LARGE_INTEGER clock_frequency_;
+      #else
+         struct timeval start_time_;
+         struct timeval stop_time_;
+      #endif
+   };
+
+   namespace information
+   {
+      static const char* library = "Mathematical Expression Toolkit";
+      static const char* version = "2.71828182845904523536028747135266"
+                                   "2497757247093699959574966967627724";
+      static const char* date    = "20160113";
+
+      static inline std::string data()
+      {
+         static const std::string info_str = std::string(library) +
+                                             std::string(" v") + std::string(version) +
+                                             std::string(" (") + date + std::string(")");
+         return info_str;
+      }
+
+   } // namespace information
+
+} // namespace exprtk
+
+#endif
diff --git a/SRC/OpenMeca/Util/trash/None.hpp b/SRC/OpenMeca/Util/trash/None.hpp
new file mode 100644
index 0000000..477e681
--- /dev/null
+++ b/SRC/OpenMeca/Util/trash/None.hpp
@@ -0,0 +1,41 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#ifndef OpenMeca_Core_None_hpp
+#define OpenMeca_Core_None_hpp
+
+
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    class None
+    {
+
+    private:  
+      None();
+      ~None();
+    }; 
+    
+  }
+}
+#endif
diff --git a/SRC/OpenMeca/Util/trash/XmlSerializer.hpp b/SRC/OpenMeca/Util/trash/XmlSerializer.hpp
new file mode 100644
index 0000000..de16c73
--- /dev/null
+++ b/SRC/OpenMeca/Util/trash/XmlSerializer.hpp
@@ -0,0 +1,183 @@
+// This file is part of OpenMeca, an easy software to do mechanical simulation.
+//
+// Author(s)    :  - Damien ANDRE  <openmeca at yakuru.fr>
+//
+// Copyright (C) 2012-2017 Damien ANDRE
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+#include <QString>
+#include <QDomElement>
+#include <map>
+#include <string>
+#include "Boost/BUILD/include/boost/any.hpp"
+#include "Boost/BUILD/include/boost/lexical_cast.hpp"
+
+namespace OpenMeca
+{
+  namespace Util
+  {
+
+    class TypeXmlSerializerManagerBase
+    {
+    public:
+      TypeXmlSerializerManagerBase(){}
+      virtual ~TypeXmlSerializerManagerBase(){}
+      virtual void ReadQDomElement(const QDomElement& e, const QString xmlKey)=0;
+      virtual void WriteQDomElement(QDomElement& e, const QString xmlKey) const =0;
+    };
+
+    template<typename T>
+    class TypeXmlSerializerManager: public TypeXmlSerializerManagerBase
+    {
+    public:
+      TypeXmlSerializerManager();
+      TypeXmlSerializerManager(const TypeXmlSerializerManager&);
+      TypeXmlSerializerManager(T*);
+      TypeXmlSerializerManager(T*, const T);
+      ~TypeXmlSerializerManager();
+      void ReadQDomElement(const QDomElement& e, const QString xmlKey);
+      void WriteQDomElement(QDomElement& e, const QString xmlKey) const;
+      
+    private:
+      T* value_;
+      const bool hasDefaultValue_;
+      const T defaultValue_;
+    };
+    
+    template<typename T>
+    inline 
+    TypeXmlSerializerManager<T>::TypeXmlSerializerManager()
+      :TypeXmlSerializerManagerBase(),
+       value_(0),
+       hasDefaultValue_(false),
+       defaultValue_()
+    {
+    }
+
+    template<typename T>
+    inline 
+    TypeXmlSerializerManager<T>::TypeXmlSerializerManager(const TypeXmlSerializerManager& t)
+      :TypeXmlSerializerManagerBase(),
+       value_(t.value_),
+       hasDefaultValue_(t.hasDefaultValue_),
+       defaultValue_(t.defaultValue_)
+    {
+    }
+      
+    template<typename T>
+    inline 
+    TypeXmlSerializerManager<T>::TypeXmlSerializerManager(T* val)
+      :TypeXmlSerializerManagerBase(),
+       value_(val),
+       hasDefaultValue_(false),
+       defaultValue_()
+    {
+    }
+
+    template<typename T>
+    inline 
+    TypeXmlSerializerManager<T>::TypeXmlSerializerManager(T* val, T defaultVal)
+      :TypeXmlSerializerManagerBase(),
+       value_(val),
+       hasDefaultValue_(true),
+       defaultValue_(defaultVal)
+    {
+    }
+    
+    template<typename T>
+    inline 
+    TypeXmlSerializerManager<T>::~TypeXmlSerializerManager()
+    {
+    } 
+    
+
+
+    template<typename T>
+    inline void
+    TypeXmlSerializerManager<T>::ReadQDomElement(const QDomElement& e, const QString xmlKey)
+    { 
+      QString valStr = e.attribute(xmlKey);
+      if (valStr==QString())
+	{
+	  if (hasDefaultValue_)
+	    {
+	      *value_ = defaultValue_;
+	      return;
+	    }
+	  OMC_ASSERT(0, "No defaut value && no tag find in xml file");
+	}
+      try
+        {
+	  *value_ = boost::lexical_cast<T>(valStr.toStdString());
+        }
+      catch(boost::bad_lexical_cast &)
+        {
+	  OMC_ASSERT(0, "Can't cast this");
+        }
+    }
+    
+    template<typename T>
+    inline void
+    TypeXmlSerializerManager<T>::WriteQDomElement(QDomElement& e, const QString xmlKey) const
+    {
+      try
+        {
+	  std::string str = boost::lexical_cast<std::string>(*value_);
+	  e.setAttribute (xmlKey, str.c_str());
+        }
+      catch(boost::bad_lexical_cast &)
+        {
+	  OMC_ASSERT(0, "Can't cast this");
+        }
+     
+    }
+
+    class XmlSerializer
+    {
+
+    public:
+      ~XmlSerializer();
+      XmlSerializer();
+      template<typename T>void Add(const QString key, T& value);
+      template<typename T>void Add(const QString key, T& value, const T& defaultValue);
+      void ReadQDomElement(const QDomElement& e);
+      void WriteQDomElement(QDomElement& e) const;
+    private :
+      //Copy constructor and assignment operator are built by compiler
+
+    private:
+      std::map<QString,TypeXmlSerializerManagerBase*> map_;
+    };
+
+    template<typename T>
+    inline void 
+    XmlSerializer::Add(const QString key, T& value)
+    {
+      assert(map_.count(key)==0);
+      map_[key]==new TypeXmlSerializerManager<T>(&value);
+    }
+    
+    template<typename T>
+    inline void 
+    XmlSerializer::Add(const QString key, T& value, const T& defaultValue)
+    {
+      assert(map_.count(key)==0);
+      map_[key]= new TypeXmlSerializerManager<T>(&value, defaultValue);
+    }
+    
+    
+  }
+}
diff --git a/SRC/README b/SRC/README
new file mode 100644
index 0000000..9ff9a7f
--- /dev/null
+++ b/SRC/README
@@ -0,0 +1,38 @@
+*************************************
+* Welcome in the openmeca sources ! *
+*************************************
+You will find here the following structure :
+
+- Boost : a third party library v1.48, see http://www.boost.org/.
+  The version is frozen to ensure serialization compatibility.
+
+- QGLViewer : a third party library v2.6.3, see http://libqglviewer.com/.
+  The version is embedded in the openmeca to make easier the packaging.
+
+- Qwt : a third party library v6.1.2, see http://libqglviewer.com/.
+  The version is embedded in the openmeca to make easier the packaging.
+
+- ChronoEngine : a third party library, see www.chronoengine.info/.
+  This is a custom version (highly simplified). 
+
+- OpenMeca : The main project with graphical interface.
+
+
+****************
+* Dependencies *
+****************
+You need the qt5 library with the help, svg, xml and opengl modules.
+Particularly, please check that the 'qmake', 'lrelease', 'qhelpgenerator' and 'qcollectiongenerator' tools are installed on your system.
+
+************************
+* Binary file location *
+************************
+All the binaries are placed under the "BUILD" of each subdirectories (Boost, QGLViewer, Qwt, ChronoEngine and OpenMeca).
+Particularly you will find the openmeca executable in ./OpenMeca/BUILD/openmeca
+
+******************
+* How to compile *
+******************
+Check the dependencies and simply type 'make' in the current directory.... take a coffee and pray the GNU saints !
+
+
diff --git a/SRC/Serialization/Serialization.pro b/SRC/Serialization/Serialization.pro
new file mode 100644
index 0000000..01cf1d2
--- /dev/null
+++ b/SRC/Serialization/Serialization.pro
@@ -0,0 +1,67 @@
+######################################################################
+# qmake internal options
+######################################################################
+
+CONFIG           += qt     
+CONFIG           += warn_on
+CONFIG           += no_keywords
+CONFIG           += silent
+CONFIG           += release
+CONFIG           += staticlib
+
+TEMPLATE  = lib
+TARGET    = ./BUILD/serialization
+DESTDIR   = ./
+
+QMAKE_CXXFLAGS +=-w -D CH_API_COMPILE
+
+OBJECTS_DIR = ./BUILD/obj
+
+INCLUDEPATH = ../ 
+
+CONFIG += c++11
+
+SOURCES += ./src/binary_oarchive.cpp \
+./src/basic_pointer_iserializer.cpp  \
+./src/extended_type_info_typeid.cpp  \
+./src/xml_oarchive.cpp  \
+./src/xml_iarchive.cpp \
+./src/binary_woarchive.cpp \
+./src/codecvt_null.cpp \
+./src/binary_wiarchive.cpp \
+./src/text_woarchive.cpp \
+./src/shared_ptr_helper.cpp \
+./src/basic_xml_archive.cpp \
+./src/basic_oarchive.cpp \
+./src/binary_iarchive.cpp \
+./src/archive_exception.cpp \
+./src/stl_port.cpp \
+./src/basic_iarchive.cpp \
+./src/xml_archive_exception.cpp \
+./src/extended_type_info.cpp \
+./src/basic_text_woprimitive.cpp \
+./src/void_cast.cpp \
+./src/basic_text_wiprimitive.cpp \
+./src/basic_iserializer.cpp \
+./src/polymorphic_oarchive.cpp \
+./src/basic_archive.cpp \
+./src/text_iarchive.cpp \
+./src/xml_woarchive.cpp \
+./src/xml_wiarchive.cpp \
+./src/basic_pointer_oserializer.cpp \
+./src/xml_grammar.cpp \
+./src/basic_text_oprimitive.cpp \
+./src/utf8_codecvt_facet.cpp \
+./src/polymorphic_iarchive.cpp \
+./src/basic_text_iprimitive.cpp \
+./src/text_oarchive.cpp \
+./src/basic_oserializer.cpp \
+./src/basic_serializer_map.cpp \
+./src/extended_type_info_no_rtti.cpp \
+./src/xml_wgrammar.cpp \
+./src/text_wiarchive.cpp
+
+target.path = ./BUILD/lib
+include.path = ./BUILD/include/Serialization
+include.files = $${HEADERS}
+INSTALLS *= target
diff --git a/SRC/Serialization/access.hpp b/SRC/Serialization/access.hpp
new file mode 100755
index 0000000..d682fde
--- /dev/null
+++ b/SRC/Serialization/access.hpp
@@ -0,0 +1,147 @@
+#ifndef BOOST_SERIALIZATION_ACCESS_HPP
+#define BOOST_SERIALIZATION_ACCESS_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// access.hpp: interface for serialization system.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#include <Serialization/pfto.hpp>
+
+namespace boost {
+
+namespace archive {
+namespace detail {
+    template<class Archive, class T>
+    class iserializer;
+    template<class Archive, class T>
+    class oserializer;
+} // namespace detail
+} // namespace archive
+
+namespace serialization {
+
+// forward declarations
+template<class Archive, class T>
+inline void serialize_adl(Archive &, T &, const unsigned int);
+namespace detail {
+    template<class Archive, class T>
+    struct member_saver;
+    template<class Archive, class T>
+    struct member_loader;
+} // namespace detail
+
+// use an "accessor class so that we can use: 
+// "friend class boost::serialization::access;" 
+// in any serialized class to permit clean, safe access to private class members
+// by the serialization system
+
+class access {
+public:
+    // grant access to "real" serialization defaults
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    template<class Archive, class T>
+    friend struct detail::member_saver;
+    template<class Archive, class T>
+    friend struct detail::member_loader;
+    template<class Archive, class T>
+    friend class archive::detail::iserializer;
+    template<class Archive, class T>
+    friend class archive::detail::oserializer;
+    template<class Archive, class T>
+    friend inline void serialize(
+        Archive & ar, 
+        T & t, 
+        const BOOST_PFTO unsigned int file_version
+    );
+    template<class Archive, class T>
+    friend inline void save_construct_data(
+        Archive & ar, 
+        const T * t, 
+        const BOOST_PFTO unsigned int file_version
+    );
+    template<class Archive, class T>
+    friend inline void load_construct_data(
+        Archive & ar, 
+        T * t, 
+        const BOOST_PFTO unsigned int file_version
+    );
+#endif
+
+    // pass calls to users's class implementation
+    template<class Archive, class T>
+    static void member_save(
+        Archive & ar, 
+        //const T & t,
+        T & t,
+        const unsigned int file_version
+    ){
+        t.save(ar, file_version);
+    }
+    template<class Archive, class T>
+    static void member_load(
+        Archive & ar, 
+        T & t,
+        const unsigned int file_version
+    ){
+        t.load(ar, file_version);
+    }
+    template<class Archive, class T>
+    static void serialize(
+        Archive & ar, 
+        T & t, 
+        const unsigned int file_version
+    ){
+        // note: if you get a compile time error here with a
+        // message something like:
+        // cannot convert parameter 1 from <file type 1> to <file type 2 &>
+        // a likely possible cause is that the class T contains a 
+        // serialize function - but that serialize function isn't 
+        // a template and corresponds to a file type different than
+        // the class Archive.  To resolve this, don't include an
+        // archive type other than that for which the serialization
+        // function is defined!!!
+        t.serialize(ar, file_version);
+    }
+    template<class T>
+    static void destroy( const T * t) // const appropriate here?
+    {
+        // the const business is an MSVC 6.0 hack that should be
+        // benign on everything else
+        delete const_cast<T *>(t);
+    }
+    template<class T>
+    static void construct(T * t){
+        // default is inplace invocation of default constructor
+        // Note the :: before the placement new. Required if the
+        // class doesn't have a class-specific placement new defined.
+        ::new(t)T;
+    }
+    template<class T, class U>
+    static T & cast_reference(U & u){
+        return static_cast<T &>(u);
+    }
+    template<class T, class U>
+    static T * cast_pointer(U * u){
+        return static_cast<T *>(u);
+    }
+};
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_ACCESS_HPP
diff --git a/SRC/Serialization/archive/add_facet.hpp b/SRC/Serialization/archive/add_facet.hpp
new file mode 100755
index 0000000..e50543f
--- /dev/null
+++ b/SRC/Serialization/archive/add_facet.hpp
@@ -0,0 +1,55 @@
+#ifndef BOOST_ARCHIVE_ADD_FACET_HPP
+#define BOOST_ARCHIVE_ADD_FACET_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// add_facet.hpp
+
+// (C) Copyright 2003 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <locale>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+// does STLport uses native STL for locales?
+#if (defined(__SGI_STL_PORT)&& defined(_STLP_NO_OWN_IOSTREAMS))
+// and this native STL lib is old Dinkumware (has not defined _CPPLIB_VER)
+#  if (defined(_YVALS) && !defined(__IBMCPP__)) || !defined(_CPPLIB_VER)
+#    define BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT
+#  endif
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class Facet>
+inline std::locale * 
+add_facet(const std::locale &l, Facet * f){
+    return
+        #if defined BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT 
+            // std namespace used for native locale
+            new std::locale(std::_Addfac(l, f));
+        #elif BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) // old Dinkumwar
+            // std namespace used for native locale
+            new std::locale(std::_Addfac(l, f));
+        #else
+            // standard compatible
+            new std::locale(l, f);
+        #endif
+}
+
+} // namespace archive
+} // namespace boost
+
+#undef BOOST_ARCHIVE_OLD_DINKUMWARE_BENEATH_STLPORT
+
+#endif // BOOST_ARCHIVE_ADD_FACET_HPP
diff --git a/SRC/Serialization/archive/archive_exception.hpp b/SRC/Serialization/archive/archive_exception.hpp
new file mode 100755
index 0000000..c458dac
--- /dev/null
+++ b/SRC/Serialization/archive/archive_exception.hpp
@@ -0,0 +1,97 @@
+#ifndef BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP
+#define BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// archive/archive_exception.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <exception>
+#include <boost/assert.hpp>
+#include <string>
+
+#include <boost/config.hpp> 
+#include <boost/preprocessor/empty.hpp>
+#include <Serialization/archive/detail/decl.hpp>
+
+// note: the only reason this is in here is that windows header
+// includes #define exception_code _exception_code (arrrgghhhh!).
+// the most expedient way to address this is be sure that this
+// header is always included whenever this header file is included.
+#if defined(BOOST_WINDOWS) 
+#include <excpt.h> 
+#endif 
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// exceptions thrown by archives
+//
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) archive_exception : 
+    public virtual std::exception
+{
+public:
+    typedef enum {
+        no_exception,       // initialized without code
+        other_exception,    // any excepton not listed below
+        unregistered_class, // attempt to serialize a pointer of an
+                            // an unregistered class
+        invalid_signature,  // first line of archive does not contain
+                            // expected string
+        unsupported_version,// archive created with library version
+                            // subsequent to this one
+        pointer_conflict,   // an attempt has been made to directly
+                            // serialize an object which has
+                            // already been serialzed through a pointer.  
+                            // Were this permited, the archive load would result 
+                            // in the creation of an extra copy of the obect.
+        incompatible_native_format, // attempt to read native binary format
+                            // on incompatible platform
+        array_size_too_short,// array being loaded doesn't fit in array allocated
+        input_stream_error, // error on input stream
+        invalid_class_name, // class name greater than the maximum permitted.
+                            // most likely a corrupted archive or an attempt
+                            // to insert virus via buffer overrun method.
+        unregistered_cast,   // base - derived relationship not registered with 
+                            // void_cast_register
+        unsupported_class_version, // type saved with a version # greater than the 
+                            // one used by the program.  This indicates that the proggram
+                            // needs to be rebuilt.
+        multiple_code_instantiation, // code for implementing serialization for some
+                            // type has been instantiated in more than one module.
+        output_stream_error // error on input stream
+    } exception_code;
+protected:
+    std::string m_msg;
+public:
+    exception_code code;
+    archive_exception(
+        exception_code c, 
+        const char * e1 = NULL,
+        const char * e2 = NULL
+    );
+    ~archive_exception() throw ();
+    virtual const char *what( ) const throw();
+protected:
+    archive_exception();
+};
+
+}// namespace archive
+}// namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif //BOOST_ARCHIVE_ARCHIVE_EXCEPTION_HPP
diff --git a/SRC/Serialization/archive/basic_archive.hpp b/SRC/Serialization/archive/basic_archive.hpp
new file mode 100755
index 0000000..c804b62
--- /dev/null
+++ b/SRC/Serialization/archive/basic_archive.hpp
@@ -0,0 +1,300 @@
+#ifndef BOOST_ARCHIVE_BASIC_ARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_ARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_archive.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp> // size_t
+#include <boost/noncopyable.hpp>
+#include <boost/integer_traits.hpp>
+
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace archive {
+
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4244 4267 )
+#endif
+
+/* NOTE : Warning  : Warning : Warning : Warning : Warning
+ * Don't ever changes this.  If you do, they previously created
+ * binary archives won't be readable !!!
+ */
+class library_version_type {
+private:
+    typedef uint_least16_t base_type;
+    base_type t;
+public:
+    library_version_type(): t(0) {};
+    explicit library_version_type(const unsigned int & t_) : t(t_){
+        BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max);
+    }
+    library_version_type(const library_version_type & t_) : 
+        t(t_.t)
+    {}
+    library_version_type & operator=(const library_version_type & rhs){
+        t = rhs.t; 
+        return *this;
+    }
+    // used for text output
+    operator base_type () const {
+        return t;
+    }                
+    // used for text input
+    operator base_type & (){
+        return t;
+    }                
+    bool operator==(const library_version_type & rhs) const {
+        return t == rhs.t;
+    } 
+    bool operator<(const library_version_type & rhs) const {
+        return t < rhs.t;
+    }   
+};
+
+BOOST_ARCHIVE_DECL(library_version_type)
+BOOST_ARCHIVE_VERSION();
+
+class version_type {
+private:
+    typedef uint_least32_t base_type;
+    base_type t;
+public:
+    // should be private - but MPI fails if it's not!!!
+    version_type(): t(0) {};
+    explicit version_type(const unsigned int & t_) : t(t_){
+        BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max);
+    }
+    version_type(const version_type & t_) : 
+        t(t_.t)
+    {}
+    version_type & operator=(const version_type & rhs){
+        t = rhs.t; 
+        return *this;
+    }
+    // used for text output
+    operator base_type () const {
+        return t;
+    }                
+    // used for text intput
+    operator base_type  & (){
+        return t;
+    }                
+    bool operator==(const version_type & rhs) const {
+        return t == rhs.t;
+    } 
+    bool operator<(const version_type & rhs) const {
+        return t < rhs.t;
+    }   
+};
+
+class class_id_type {
+private:
+    typedef int_least16_t base_type;
+    base_type t;
+public:
+    // should be private - but then can't use BOOST_STRONG_TYPE below
+    class_id_type() : t(0) {};
+    explicit class_id_type(const int t_) : t(t_){
+        BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max);
+    }
+    explicit class_id_type(const std::size_t t_) : t(t_){
+ //       BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max);
+    }
+    class_id_type(const class_id_type & t_) : 
+        t(t_.t)
+    {}
+    class_id_type & operator=(const class_id_type & rhs){
+        t = rhs.t; 
+        return *this;
+    }
+
+    // used for text output
+    operator int () const {
+        return t;
+    }                
+    // used for text input
+    operator int_least16_t &() {
+        return t;
+    }                
+    bool operator==(const class_id_type & rhs) const {
+        return t == rhs.t;
+    } 
+    bool operator<(const class_id_type & rhs) const {
+        return t < rhs.t;
+    }   
+};
+
+#define NULL_POINTER_TAG boost::archive::class_id_type(-1)
+
+class object_id_type {
+private:
+    typedef uint_least32_t base_type;
+    base_type t;
+public:
+    object_id_type(): t(0) {};
+    explicit object_id_type(const unsigned int & t_) : t(t_){
+        BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max);
+    }
+    object_id_type(const object_id_type & t_) : 
+        t(t_.t)
+    {}
+    object_id_type & operator=(const object_id_type & rhs){
+        t = rhs.t; 
+        return *this;
+    }
+    // used for text output
+    operator uint_least32_t () const {
+        return t;
+    }                
+    // used for text input
+    operator uint_least32_t & () {
+        return t;
+    }                
+    bool operator==(const object_id_type & rhs) const {
+        return t == rhs.t;
+    } 
+    bool operator<(const object_id_type & rhs) const {
+        return t < rhs.t;
+    }   
+};
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+struct tracking_type {
+    bool t;
+    explicit tracking_type(const bool t_ = false)
+        : t(t_)
+    {};
+    tracking_type(const tracking_type & t_)
+        : t(t_.t)
+    {}
+    operator bool () const {
+        return t;
+    };
+    operator bool & () {
+        return t;
+    };
+    tracking_type & operator=(const bool t_){
+        t = t_;
+        return *this;
+    }
+    bool operator==(const tracking_type & rhs) const {
+        return t == rhs.t;
+    }
+    bool operator==(const bool & rhs) const {
+        return t == rhs;
+    }
+    tracking_type & operator=(const tracking_type & rhs){
+        t = rhs.t;
+        return *this;
+    }
+};
+
+struct class_name_type : 
+    private boost::noncopyable 
+{
+    char *t;
+    operator const char * & () const {
+        return const_cast<const char * &>(t);
+    }
+    operator char * () {
+        return t;
+    }
+    explicit class_name_type(const char *key_) 
+    : t(const_cast<char *>(key_)){}
+    explicit class_name_type(char *key_) 
+    : t(key_){}
+    class_name_type & operator=(const class_name_type & rhs){
+        t = rhs.t;
+        return *this;
+    }
+};
+
+enum archive_flags {
+    no_header = 1,  // suppress archive header info
+    no_codecvt = 2,  // suppress alteration of codecvt facet
+    no_xml_tag_checking = 4,   // suppress checking of xml tags
+    no_tracking = 8,           // suppress ALL tracking
+    flags_last = 8
+};
+
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_SIGNATURE();
+
+/* NOTE : Warning  : Warning : Warning : Warning : Warning
+ * If any of these are changed to different sized types, 
+ * binary_iarchive won't be able to read older archives
+ * unless you rev the library version and include conditional
+ * code based on the library version.  There is nothing
+ * inherently wrong in doing this - but you have to be super
+ * careful because it's easy to get wrong and start breaking
+ * old archives !!!
+ */
+
+#define BOOST_ARCHIVE_STRONG_TYPEDEF(T, D)         \
+    class D : public T {                           \
+    public:                                        \
+        explicit D(const T tt) : T(tt){}           \
+    };                                             \
+/**/
+
+BOOST_ARCHIVE_STRONG_TYPEDEF(class_id_type, class_id_reference_type)
+BOOST_ARCHIVE_STRONG_TYPEDEF(class_id_type, class_id_optional_type)
+BOOST_ARCHIVE_STRONG_TYPEDEF(object_id_type, object_reference_type)
+
+}// namespace archive
+}// namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#include <Serialization/level.hpp>
+
+// set implementation level to primitive for all types
+// used internally by the serialization library
+
+BOOST_CLASS_IMPLEMENTATION(boost::archive::library_version_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::version_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_reference_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::class_id_optional_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::class_name_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::object_id_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::object_reference_type, primitive_type)
+BOOST_CLASS_IMPLEMENTATION(boost::archive::tracking_type, primitive_type)
+
+#include <Serialization/is_bitwise_serializable.hpp>
+
+// set types used internally by the serialization library 
+// to be bitwise serializable
+
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::library_version_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::version_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_id_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_id_reference_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_id_optional_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::class_name_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::object_id_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::object_reference_type)
+BOOST_IS_BITWISE_SERIALIZABLE(boost::archive::tracking_type)
+
+#endif //BOOST_ARCHIVE_BASIC_ARCHIVE_HPP
diff --git a/SRC/Serialization/archive/basic_binary_iarchive.hpp b/SRC/Serialization/archive/basic_binary_iarchive.hpp
new file mode 100755
index 0000000..b3cdf5e
--- /dev/null
+++ b/SRC/Serialization/archive/basic_binary_iarchive.hpp
@@ -0,0 +1,222 @@
+#ifndef BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_iarchive.hpp
+//
+// archives stored as native binary - this should be the fastest way
+// to archive the state of a group of obects.  It makes no attempt to
+// convert to any canonical form.
+
+// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE
+// ON PLATFORM APART FROM THE ONE THEY ARE CREATED ON
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/archive/detail/common_iarchive.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/string.hpp>
+#include <Serialization/item_version_type.hpp>
+#include <boost/integer_traits.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost { 
+namespace archive {
+
+/////////////////////////////////////////////////////////////////////////
+// class basic_binary_iarchive - read serialized objects from a input binary stream
+template<class Archive>
+class basic_binary_iarchive : 
+    public detail::common_iarchive<Archive>
+{
+protected:
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+public:
+#elif defined(BOOST_MSVC)
+    // for some inexplicable reason insertion of "class" generates compile erro
+    // on msvc 7.1
+    friend detail::interface_iarchive<Archive>;
+#else
+    friend class detail::interface_iarchive<Archive>;
+#endif
+    // intermediate level to support override of operators
+    // fot templates in the absence of partial function 
+    // template ordering. If we get here pass to base class
+    // note extra nonsense to sneak it pass the borland compiers
+    typedef detail::common_iarchive<Archive> detail_common_iarchive;
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int version){
+      this->detail_common_iarchive::load_override(t, static_cast<int>(version));
+    }
+
+    // include these to trap a change in binary format which
+    // isn't specifically handled
+    // upto 32K classes
+    BOOST_STATIC_ASSERT(sizeof(class_id_type) == sizeof(int_least16_t));
+    BOOST_STATIC_ASSERT(sizeof(class_id_reference_type) == sizeof(int_least16_t));
+    // upto 2G objects
+    BOOST_STATIC_ASSERT(sizeof(object_id_type) == sizeof(uint_least32_t));
+    BOOST_STATIC_ASSERT(sizeof(object_reference_type) == sizeof(uint_least32_t));
+
+    // binary files don't include the optional information 
+    void load_override(class_id_optional_type & /* t */, int){}
+
+    void load_override(tracking_type & t, int /*version*/){
+        library_version_type lvt = this->get_library_version();
+        if(boost::archive::library_version_type(6) < lvt){
+            int_least8_t x=0;
+            * this->This() >> x;
+            t = boost::archive::tracking_type(x);
+        }
+        else{
+            bool x=0;
+            * this->This() >> x;
+            t = boost::archive::tracking_type(x);
+        }
+    }
+    void load_override(class_id_type & t, int version){
+        library_version_type lvt = this->get_library_version();
+        if(boost::archive::library_version_type(7) < lvt){
+            this->detail_common_iarchive::load_override(t, version);
+        }
+        else
+        if(boost::archive::library_version_type(6) < lvt){
+            int_least16_t x=0;
+            * this->This() >> x;
+            t = boost::archive::class_id_type(x);
+        }
+        else{
+            int x=0;
+            * this->This() >> x;
+            t = boost::archive::class_id_type(x);
+        }
+    }
+    void load_override(class_id_reference_type & t, int version){
+        load_override(static_cast<class_id_type &>(t), version);
+    }
+#if 0
+    void load_override(class_id_reference_type & t, int version){
+        library_version_type lvt = this->get_library_version();
+        if(boost::archive::library_version_type(7) < lvt){
+            this->detail_common_iarchive::load_override(t, version);
+        }
+        else
+        if(boost::archive::library_version_type(6) < lvt){
+            int_least16_t x=0;
+            * this->This() >> x;
+            t = boost::archive::class_id_reference_type(
+                boost::archive::class_id_type(x)
+            );
+        }
+        else{
+            int x=0;
+            * this->This() >> x;
+            t = boost::archive::class_id_reference_type(
+                boost::archive::class_id_type(x)
+            );
+        }
+    }
+#endif
+
+    void load_override(version_type & t, int version){
+        library_version_type lvt = this->get_library_version();
+        if(boost::archive::library_version_type(7) < lvt){
+            this->detail_common_iarchive::load_override(t, version);
+        }
+        else
+        if(boost::archive::library_version_type(6) < lvt){
+            uint_least8_t x=0;
+            * this->This() >> x;
+            t = boost::archive::version_type(x);
+        }
+        else
+        if(boost::archive::library_version_type(5) < lvt){
+            uint_least16_t x=0;
+            * this->This() >> x;
+            t = boost::archive::version_type(x);
+        }
+        else
+        if(boost::archive::library_version_type(2) < lvt){
+            // upto 255 versions
+            unsigned char x=0;
+            * this->This() >> x;
+            t = version_type(x);
+        }
+        else{
+            unsigned int x=0;
+            * this->This() >> x;
+            t = boost::archive::version_type(x);
+        }
+    }
+
+    void load_override(boost::serialization::item_version_type & t, int version){
+        library_version_type lvt = this->get_library_version();
+//        if(boost::archive::library_version_type(7) < lvt){
+        if(boost::archive::library_version_type(6) < lvt){
+            this->detail_common_iarchive::load_override(t, version);
+        }
+        else
+        if(boost::archive::library_version_type(6) < lvt){
+            uint_least16_t x=0;
+            * this->This() >> x;
+            t = boost::serialization::item_version_type(x);
+        }
+        else{
+            unsigned int x=0;
+            * this->This() >> x;
+            t = boost::serialization::item_version_type(x);
+        }
+    }
+
+    void load_override(serialization::collection_size_type & t, int version){
+        if(boost::archive::library_version_type(5) < this->get_library_version()){
+            this->detail_common_iarchive::load_override(t, version);
+        }
+        else{
+            unsigned int x=0;
+            * this->This() >> x;
+            t = serialization::collection_size_type(x);
+        } 
+    }
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_override(class_name_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    init();
+   
+    basic_binary_iarchive(unsigned int flags) :
+        detail::common_iarchive<Archive>(flags)
+    {}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_BINARY_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/basic_binary_iprimitive.hpp b/SRC/Serialization/archive/basic_binary_iprimitive.hpp
new file mode 100755
index 0000000..d563daa
--- /dev/null
+++ b/SRC/Serialization/archive/basic_binary_iprimitive.hpp
@@ -0,0 +1,190 @@
+#ifndef BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP
+#define BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning( disable : 4800 )
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_iprimitive.hpp
+//
+// archives stored as native binary - this should be the fastest way
+// to archive the state of a group of obects.  It makes no attempt to
+// convert to any canonical form.
+
+// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE
+// ON PLATFORM APART FROM THE ONE THEY ARE CREATED ON
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <iosfwd>
+#include <boost/assert.hpp>
+#include <locale>
+#include <cstring> // std::memcpy
+#include <cstddef> // std::size_t
+#include <streambuf> // basic_streambuf
+#include <string>
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::memcpy; 
+    using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/cstdint.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <Serialization/throw_exception.hpp>
+#include <boost/integer.hpp>
+#include <boost/integer_traits.hpp>
+
+#include <Serialization/archive/basic_streambuf_locale_saver.hpp>
+#include <Serialization/archive/archive_exception.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <Serialization/is_bitwise_serializable.hpp>
+#include <Serialization/array.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost { 
+namespace archive {
+
+/////////////////////////////////////////////////////////////////////////////
+// class binary_iarchive - read serialized objects from a input binary stream
+template<class Archive, class Elem, class Tr>
+class basic_binary_iprimitive
+{
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+    friend class load_access;
+protected:
+#else
+public:
+#endif
+    std::basic_streambuf<Elem, Tr> & m_sb;
+    // return a pointer to the most derived class
+    Archive * This(){
+        return static_cast<Archive *>(this);
+    }
+
+    #ifndef BOOST_NO_STD_LOCALE
+    boost::scoped_ptr<std::locale> archive_locale;
+    basic_streambuf_locale_saver<Elem, Tr> locale_saver;
+    #endif
+
+    // main template for serilization of primitive types
+    template<class T>
+    void load(T & t){
+        load_binary(& t, sizeof(T));
+    }
+
+    /////////////////////////////////////////////////////////
+    // fundamental types that need special treatment
+    
+    // trap usage of invalid uninitialized boolean 
+    void load(bool & t){
+        load_binary(& t, sizeof(t));
+        int i = t;
+        BOOST_ASSERT(0 == i || 1 == i);
+        (void)i; // warning suppression for release builds.
+    }
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load(std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load(std::wstring &ws);
+    #endif
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load(char * t);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load(wchar_t * t);
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    init();
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    basic_binary_iprimitive(
+        std::basic_streambuf<Elem, Tr> & sb, 
+        bool no_codecvt
+    );
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    ~basic_binary_iprimitive();
+public:
+    // we provide an optimized load for all fundamental types
+    // typedef serialization::is_bitwise_serializable<mpl::_1> 
+    // use_array_optimization;
+    struct use_array_optimization {  
+        template <class T>  
+        #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)  
+            struct apply {  
+                typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable< T >::type type;  
+            };
+        #else
+            struct apply : public boost::serialization::is_bitwise_serializable< T > {};  
+        #endif
+    };
+
+    // the optimized load_array dispatches to load_binary 
+    template <class ValueType>
+    void load_array(serialization::array<ValueType>& a, unsigned int)
+    {
+      load_binary(a.address(),a.count()*sizeof(ValueType));
+    }
+
+    void
+    load_binary(void *address, std::size_t count);
+};
+
+template<class Archive, class Elem, class Tr>
+inline void
+basic_binary_iprimitive<Archive, Elem, Tr>::load_binary(
+    void *address, 
+    std::size_t count
+){
+    // note: an optimizer should eliminate the following for char files
+    BOOST_ASSERT(
+        static_cast<std::streamsize>(count / sizeof(Elem)) 
+        <= boost::integer_traits<std::streamsize>::const_max
+    );
+    std::streamsize s = static_cast<std::streamsize>(count / sizeof(Elem));
+    std::streamsize scount = m_sb.sgetn(
+        static_cast<Elem *>(address), 
+        s
+    );
+    if(scount != s)
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::input_stream_error)
+        );
+    // note: an optimizer should eliminate the following for char files
+    BOOST_ASSERT(count % sizeof(Elem) <= boost::integer_traits<std::streamsize>::const_max);
+    s = static_cast<std::streamsize>(count % sizeof(Elem));
+    if(0 < s){
+//        if(is.fail())
+//            boost::serialization::throw_exception(
+//                archive_exception(archive_exception::stream_error)
+//        );
+        Elem t;
+        scount = m_sb.sgetn(& t, 1);
+        if(scount != 1)
+            boost::serialization::throw_exception(
+                archive_exception(archive_exception::input_stream_error)
+            );
+        std::memcpy(static_cast<char*>(address) + (count - s), &t, s);
+    }
+}
+
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pop pragmas
+
+#endif // BOOST_ARCHIVE_BINARY_IPRIMITIVE_HPP
diff --git a/SRC/Serialization/archive/basic_binary_oarchive.hpp b/SRC/Serialization/archive/basic_binary_oarchive.hpp
new file mode 100755
index 0000000..7e8fef6
--- /dev/null
+++ b/SRC/Serialization/archive/basic_binary_oarchive.hpp
@@ -0,0 +1,180 @@
+#ifndef BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// archives stored as native binary - this should be the fastest way
+// to archive the state of a group of obects.  It makes no attempt to
+// convert to any canonical form.
+
+// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE
+// ON PLATFORM APART FROM THE ONE THEY ARE CREATE ON
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <boost/integer.hpp>
+#include <boost/integer_traits.hpp>
+
+#include <Serialization/archive/detail/common_oarchive.hpp>
+#include <Serialization/string.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// class basic_binary_oarchive - write serialized objects to a binary output stream
+// note: this archive has no pretensions to portability.  Archive format
+// may vary across machine architectures and compilers.  About the only
+// guarentee is that an archive created with this code will be readable
+// by a program built with the same tools for the same machne.  This class
+// does have the virtue of buiding the smalles archive in the minimum amount
+// of time.  So under some circumstances it may be he right choice.
+template<class Archive>
+class basic_binary_oarchive : 
+    public archive::detail::common_oarchive<Archive>
+{
+protected:
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+public:
+#elif defined(BOOST_MSVC)
+    // for some inexplicable reason insertion of "class" generates compile erro
+    // on msvc 7.1
+    friend detail::interface_oarchive<Archive>;
+#else
+    friend class detail::interface_oarchive<Archive>;
+#endif
+    // any datatype not specifed below will be handled by base class
+    typedef detail::common_oarchive<Archive> detail_common_oarchive;
+    template<class T>
+    void save_override(const T & t, BOOST_PFTO int version){
+      this->detail_common_oarchive::save_override(t, static_cast<int>(version));
+    }
+
+    // include these to trap a change in binary format which
+    // isn't specifically handled
+    BOOST_STATIC_ASSERT(sizeof(tracking_type) == sizeof(bool));
+    // upto 32K classes
+    BOOST_STATIC_ASSERT(sizeof(class_id_type) == sizeof(int_least16_t));
+    BOOST_STATIC_ASSERT(sizeof(class_id_reference_type) == sizeof(int_least16_t));
+    // upto 2G objects
+    BOOST_STATIC_ASSERT(sizeof(object_id_type) == sizeof(uint_least32_t));
+    BOOST_STATIC_ASSERT(sizeof(object_reference_type) == sizeof(uint_least32_t));
+
+    // binary files don't include the optional information 
+    void save_override(const class_id_optional_type & /* t */, int){}
+
+    // enable this if we decide to support generation of previous versions
+    #if 0
+    void save_override(const boost::archive::version_type & t, int version){
+        library_version_type lvt = this->get_library_version();
+        if(boost::archive::library_version_type(7) < lvt){
+            this->detail_common_oarchive::save_override(t, version);
+        }
+        else
+        if(boost::archive::library_version_type(6) < lvt){
+            const boost::uint_least16_t x = t;
+            * this->This() << x;
+        }
+        else{
+            const unsigned int x = t;
+            * this->This() << x;
+        }
+    }
+    void save_override(const boost::serialization::item_version_type & t, int version){
+        library_version_type lvt = this->get_library_version();
+        if(boost::archive::library_version_type(7) < lvt){
+            this->detail_common_oarchive::save_override(t, version);
+        }
+        else
+        if(boost::archive::library_version_type(6) < lvt){
+            const boost::uint_least16_t x = t;
+            * this->This() << x;
+        }
+        else{
+            const unsigned int x = t;
+            * this->This() << x;
+        }
+    }
+
+    void save_override(class_id_type & t, int version){
+        library_version_type lvt = this->get_library_version();
+        if(boost::archive::library_version_type(7) < lvt){
+            this->detail_common_oarchive::save_override(t, version);
+        }
+        else
+        if(boost::archive::library_version_type(6) < lvt){
+            const boost::int_least16_t x = t;
+            * this->This() << x;
+        }
+        else{
+            const int x = t;
+            * this->This() << x;
+        }
+    }
+    void save_override(class_id_reference_type & t, int version){
+        save_override(static_cast<class_id_type &>(t), version);
+    }
+
+    #endif
+
+    // explicitly convert to char * to avoid compile ambiguities
+    void save_override(const class_name_type & t, int){
+        const std::string s(t);
+        * this->This() << s;
+    }
+
+    #if 0
+    void save_override(const serialization::collection_size_type & t, int){
+        if (get_library_version() < boost::archive::library_version_type(6)){
+            unsigned int x=0;
+            * this->This() >> x;
+            t = serialization::collection_size_type(x);
+        } 
+        else{
+            * this->This() >> t;
+        }
+    }
+    #endif
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    init();
+
+    basic_binary_oarchive(unsigned int flags) :
+        detail::common_oarchive<Archive>(flags)
+    {}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_BINARY_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/basic_binary_oprimitive.hpp b/SRC/Serialization/archive/basic_binary_oprimitive.hpp
new file mode 100755
index 0000000..74123b6
--- /dev/null
+++ b/SRC/Serialization/archive/basic_binary_oprimitive.hpp
@@ -0,0 +1,184 @@
+#ifndef BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP
+#define BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_oprimitive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// archives stored as native binary - this should be the fastest way
+// to archive the state of a group of obects.  It makes no attempt to
+// convert to any canonical form.
+
+// IN GENERAL, ARCHIVES CREATED WITH THIS CLASS WILL NOT BE READABLE
+// ON PLATFORM APART FROM THE ONE THEY ARE CREATE ON
+
+#include <iosfwd>
+#include <boost/assert.hpp>
+#include <locale>
+#include <streambuf> // basic_streambuf
+#include <string>
+#include <cstddef> // size_t
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <boost/cstdint.hpp>
+#include <boost/integer.hpp>
+#include <boost/integer_traits.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <Serialization/throw_exception.hpp>
+
+#include <Serialization/archive/basic_streambuf_locale_saver.hpp>
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/is_bitwise_serializable.hpp>
+#include <boost/mpl/placeholders.hpp>
+#include <Serialization/array.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace archive {
+
+/////////////////////////////////////////////////////////////////////////
+// class basic_binary_oprimitive - binary output of prmitives
+
+template<class Archive, class Elem, class Tr>
+class basic_binary_oprimitive
+{
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+    friend class save_access;
+protected:
+#else
+public:
+#endif
+    std::basic_streambuf<Elem, Tr> & m_sb;
+    // return a pointer to the most derived class
+    Archive * This(){
+        return static_cast<Archive *>(this);
+    }
+    #ifndef BOOST_NO_STD_LOCALE
+    boost::scoped_ptr<std::locale> archive_locale;
+    basic_streambuf_locale_saver<Elem, Tr> locale_saver;
+    #endif
+    // default saving of primitives.
+    template<class T>
+    void save(const T & t)
+    {
+        save_binary(& t, sizeof(T));
+    }
+
+    /////////////////////////////////////////////////////////
+    // fundamental types that need special treatment
+    
+    // trap usage of invalid uninitialized boolean which would
+    // otherwise crash on load.
+    void save(const bool t){
+        BOOST_ASSERT(0 == static_cast<int>(t) || 1 == static_cast<int>(t));
+        save_binary(& t, sizeof(t));
+    }
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save(const std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save(const std::wstring &ws);
+    #endif
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save(const char * t);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save(const wchar_t * t);
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    init();
+    
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    basic_binary_oprimitive(
+        std::basic_streambuf<Elem, Tr> & sb, 
+        bool no_codecvt
+    );
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    ~basic_binary_oprimitive();
+public:
+
+    // we provide an optimized save for all fundamental types
+    // typedef serialization::is_bitwise_serializable<mpl::_1> 
+    // use_array_optimization;
+    // workaround without using mpl lambdas
+    struct use_array_optimization {
+        template <class T>  
+        #if defined(BOOST_NO_DEPENDENT_NESTED_DERIVATIONS)  
+            struct apply {  
+                typedef BOOST_DEDUCED_TYPENAME boost::serialization::is_bitwise_serializable< T >::type type;  
+            };
+        #else
+            struct apply : public boost::serialization::is_bitwise_serializable< T > {};  
+        #endif
+    };
+    
+
+    // the optimized save_array dispatches to save_binary 
+    template <class ValueType>
+    void save_array(boost::serialization::array<ValueType> const& a, unsigned int)
+    {
+      save_binary(a.address(),a.count()*sizeof(ValueType));
+    }
+
+    void save_binary(const void *address, std::size_t count);
+};
+
+template<class Archive, class Elem, class Tr>
+inline void 
+basic_binary_oprimitive<Archive, Elem, Tr>::save_binary(
+    const void *address, 
+    std::size_t count
+){
+    //BOOST_ASSERT(
+    //    static_cast<std::size_t>((std::numeric_limits<std::streamsize>::max)()) >= count
+    //);
+    // note: if the following assertions fail
+    // a likely cause is that the output stream is set to "text"
+    // mode where by cr characters recieve special treatment.
+    // be sure that the output stream is opened with ios::binary
+    //if(os.fail())
+    //    boost::serialization::throw_exception(
+    //        archive_exception(archive_exception::output_stream_error)
+    //    );
+    // figure number of elements to output - round up
+    count = ( count + sizeof(Elem) - 1) 
+        / sizeof(Elem);
+    BOOST_ASSERT(count <= std::size_t(boost::integer_traits<std::streamsize>::const_max));
+    std::streamsize scount = m_sb.sputn(
+        static_cast<const Elem *>(address), 
+        static_cast<std::streamsize>(count)
+    );
+    if(count != static_cast<std::size_t>(scount))
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::output_stream_error)
+        );
+    //os.write(
+    //    static_cast<const BOOST_DEDUCED_TYPENAME OStream::char_type *>(address), 
+    //    count
+    //);
+    //BOOST_ASSERT(os.good());
+}
+
+} //namespace boost 
+} //namespace archive 
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pop pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_BINARY_OPRIMITIVE_HPP
diff --git a/SRC/Serialization/archive/basic_streambuf_locale_saver.hpp b/SRC/Serialization/archive/basic_streambuf_locale_saver.hpp
new file mode 100755
index 0000000..c32d835
--- /dev/null
+++ b/SRC/Serialization/archive/basic_streambuf_locale_saver.hpp
@@ -0,0 +1,73 @@
+#ifndef BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP
+#define BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_streambuf_local_saver.hpp
+
+// (C) Copyright 2005 Robert Ramey - http://www.rrsd.com
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// note derived from boost/io/ios_state.hpp
+// Copyright 2002, 2005 Daryle Walker.  Use, modification, and distribution
+// are subject to the Boost Software License, Version 1.0.  (See accompanying
+// file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
+
+//  See <http://www.boost.org/libs/io/> for the library's home page.
+
+#ifndef BOOST_NO_STD_LOCALE
+
+#include <locale>     // for std::locale
+#include <streambuf>  // for std::basic_streambuf
+
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost{
+namespace archive{
+
+template < typename Ch, class Tr >
+class basic_streambuf_locale_saver :
+    private boost::noncopyable
+{
+public:
+    typedef ::std::basic_streambuf<Ch, Tr> state_type;
+    typedef ::std::locale aspect_type;
+    explicit basic_streambuf_locale_saver( state_type &s )
+        : s_save_( s ), a_save_( s.getloc() )
+        {}
+    basic_streambuf_locale_saver( state_type &s, aspect_type const &a )
+        : s_save_( s ), a_save_( s.pubimbue(a) )
+        {}
+    ~basic_streambuf_locale_saver()
+        { this->restore(); }
+    void  restore()
+        { s_save_.pubimbue( a_save_ ); }
+private:
+    state_type &       s_save_;
+    aspect_type const  a_save_;
+};
+
+} // archive
+} // boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_NO_STD_LOCALE
+#endif // BOOST_ARCHIVE_BASIC_STREAMBUF_LOCALE_SAVER_HPP
diff --git a/SRC/Serialization/archive/basic_text_iarchive.hpp b/SRC/Serialization/archive/basic_text_iarchive.hpp
new file mode 100755
index 0000000..a573cb8
--- /dev/null
+++ b/SRC/Serialization/archive/basic_text_iarchive.hpp
@@ -0,0 +1,91 @@
+#ifndef BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// archives stored as text - note these ar templated on the basic
+// stream templates to accommodate wide (and other?) kind of characters
+//
+// note the fact that on libraries without wide characters, ostream is
+// is not a specialization of basic_ostream which in fact is not defined
+// in such cases.   So we can't use basic_ostream<IStream::char_type> but rather
+// use two template parameters
+
+#include <boost/config.hpp>
+#include <Serialization/pfto.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <Serialization/archive/detail/common_iarchive.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+/////////////////////////////////////////////////////////////////////////
+// class basic_text_iarchive - read serialized objects from a input text stream
+template<class Archive>
+class basic_text_iarchive : 
+    public detail::common_iarchive<Archive>
+{
+protected:
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+public:
+#elif defined(BOOST_MSVC)
+    // for some inexplicable reason insertion of "class" generates compile erro
+    // on msvc 7.1
+    friend detail::interface_iarchive<Archive>;
+#else
+    friend class detail::interface_iarchive<Archive>;
+#endif
+    // intermediate level to support override of operators
+    // fot templates in the absence of partial function 
+    // template ordering
+    typedef detail::common_iarchive<Archive> detail_common_iarchive;
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int){
+        this->detail_common_iarchive::load_override(t, 0);
+    }
+    // text file don't include the optional information 
+    void load_override(class_id_optional_type & /*t*/, int){}
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_override(class_name_type & t, int);
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    init(void);
+
+    basic_text_iarchive(unsigned int flags) : 
+        detail::common_iarchive<Archive>(flags)
+    {}
+    ~basic_text_iarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_TEXT_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/basic_text_iprimitive.hpp b/SRC/Serialization/archive/basic_text_iprimitive.hpp
new file mode 100755
index 0000000..8570656
--- /dev/null
+++ b/SRC/Serialization/archive/basic_text_iprimitive.hpp
@@ -0,0 +1,144 @@
+#ifndef BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP
+#define BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_iprimitive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// archives stored as text - note these are templated on the basic
+// stream templates to accommodate wide (and other?) kind of characters
+//
+// Note the fact that on libraries without wide characters, ostream is
+// not a specialization of basic_ostream which in fact is not defined
+// in such cases.   So we can't use basic_ostream<IStream::char_type> but rather
+// use two template parameters
+
+#include <boost/assert.hpp>
+#include <locale>
+#include <cstddef> // size_t
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+    #if ! defined(BOOST_DINKUMWARE_STDLIB) && ! defined(__SGI_STL_PORT)
+        using ::locale;
+    #endif
+} // namespace std
+#endif
+
+#include <boost/detail/workaround.hpp>
+#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
+#include <Serialization/archive/dinkumware.hpp>
+#endif
+
+#include <boost/limits.hpp>
+#include <boost/io/ios_state.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/static_assert.hpp>
+
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/archive/basic_streambuf_locale_saver.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace archive {
+
+/////////////////////////////////////////////////////////////////////////
+// class basic_text_iarchive - load serialized objects from a input text stream
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4244 4267 )
+#endif
+
+template<class IStream>
+class basic_text_iprimitive
+{
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+protected:
+#else
+public:
+#endif
+    IStream &is;
+    io::ios_flags_saver flags_saver;
+    io::ios_precision_saver precision_saver;
+
+    #ifndef BOOST_NO_STD_LOCALE
+    boost::scoped_ptr<std::locale> archive_locale;
+    basic_streambuf_locale_saver<
+        BOOST_DEDUCED_TYPENAME IStream::char_type, 
+        BOOST_DEDUCED_TYPENAME IStream::traits_type
+    > locale_saver;
+    #endif
+
+    template<class T>
+    void load(T & t)
+    {
+        if(! is.fail()){
+            is >> t;
+            return;
+        }
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::input_stream_error)
+        );
+    }
+
+    void load(char & t)
+    {
+        short int i;
+        load(i);
+        t = i;
+    }
+    void load(signed char & t)
+    {
+        short int i;
+        load(i);
+        t = i;
+    }
+    void load(unsigned char & t)
+    {
+        unsigned short int i;
+        load(i);
+        t = i;
+    }
+
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    void load(wchar_t & t)
+    {
+        BOOST_STATIC_ASSERT(sizeof(wchar_t) <= sizeof(int));
+        int i;
+        load(i);
+        t = i;
+    }
+    #endif
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    basic_text_iprimitive(IStream  &is, bool no_codecvt);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    ~basic_text_iprimitive();
+public:
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_binary(void *address, std::size_t count);
+};
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pop pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_TEXT_IPRIMITIVE_HPP
diff --git a/SRC/Serialization/archive/basic_text_oarchive.hpp b/SRC/Serialization/archive/basic_text_oarchive.hpp
new file mode 100755
index 0000000..50d5f53
--- /dev/null
+++ b/SRC/Serialization/archive/basic_text_oarchive.hpp
@@ -0,0 +1,116 @@
+#ifndef BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// archives stored as text - note these ar templated on the basic
+// stream templates to accommodate wide (and other?) kind of characters
+//
+// note the fact that on libraries without wide characters, ostream is
+// is not a specialization of basic_ostream which in fact is not defined
+// in such cases.   So we can't use basic_ostream<OStream::char_type> but rather
+// use two template parameters
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <Serialization/pfto.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <Serialization/archive/detail/common_oarchive.hpp>
+#include <Serialization/string.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+/////////////////////////////////////////////////////////////////////////
+// class basic_text_oarchive 
+template<class Archive>
+class basic_text_oarchive : 
+    public detail::common_oarchive<Archive>
+{
+protected:
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) \
+|| BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x560))
+public:
+#elif defined(BOOST_MSVC)
+    // for some inexplicable reason insertion of "class" generates compile erro
+    // on msvc 7.1
+    friend detail::interface_oarchive<Archive>;
+#else
+    friend class detail::interface_oarchive<Archive>;
+#endif
+    enum {
+        none,
+        eol,
+        space
+    } delimiter;
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    newtoken();
+
+    void newline(){
+        delimiter = eol;
+    }
+
+    // default processing - kick back to base class.  Note the
+    // extra stuff to get it passed borland compilers
+    typedef detail::common_oarchive<Archive> detail_common_oarchive;
+    template<class T>
+    void save_override(T & t, BOOST_PFTO int){
+        this->detail_common_oarchive::save_override(t, 0);
+    }
+
+    // start new objects on a new line
+    void save_override(const object_id_type & t, int){
+        this->This()->newline();
+        this->detail_common_oarchive::save_override(t, 0);
+    }
+
+    // text file don't include the optional information 
+    void save_override(const class_id_optional_type & /* t */, int){}
+
+    void save_override(const class_name_type & t, int){
+        const std::string s(t);
+        * this->This() << s;
+    }
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    init();
+
+    basic_text_oarchive(unsigned int flags) :
+        detail::common_oarchive<Archive>(flags),
+        delimiter(none)
+    {}
+    ~basic_text_oarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_TEXT_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/basic_text_oprimitive.hpp b/SRC/Serialization/archive/basic_text_oprimitive.hpp
new file mode 100755
index 0000000..62f7139
--- /dev/null
+++ b/SRC/Serialization/archive/basic_text_oprimitive.hpp
@@ -0,0 +1,173 @@
+#ifndef BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP
+#define BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_oprimitive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// archives stored as text - note these ar templated on the basic
+// stream templates to accommodate wide (and other?) kind of characters
+//
+// note the fact that on libraries without wide characters, ostream is
+// is not a specialization of basic_ostream which in fact is not defined
+// in such cases.   So we can't use basic_ostream<OStream::char_type> but rather
+// use two template parameters
+
+#include <iomanip>
+#include <locale>
+#include <boost/config/no_tr1/cmath.hpp> // isnan
+#include <boost/assert.hpp>
+#include <cstddef> // size_t
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/detail/workaround.hpp>
+#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
+#include <Serialization/archive/dinkumware.hpp>
+#endif
+
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t;
+    #if ! defined(BOOST_DINKUMWARE_STDLIB) && ! defined(__SGI_STL_PORT)
+        using ::locale;
+    #endif
+} // namespace std
+#endif
+
+#include <boost/limits.hpp>
+#include <boost/integer.hpp>
+#include <boost/io/ios_state.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/archive/basic_streambuf_locale_saver.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace archive {
+
+class save_access;
+
+/////////////////////////////////////////////////////////////////////////
+// class basic_text_oprimitive - output of prmitives to stream
+template<class OStream>
+class basic_text_oprimitive
+{
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+protected:
+#else
+public:
+#endif
+    OStream &os;
+    io::ios_flags_saver flags_saver;
+    io::ios_precision_saver precision_saver;
+
+    #ifndef BOOST_NO_STD_LOCALE
+    boost::scoped_ptr<std::locale> archive_locale;
+    basic_streambuf_locale_saver<
+        BOOST_DEDUCED_TYPENAME OStream::char_type, 
+        BOOST_DEDUCED_TYPENAME OStream::traits_type
+    > locale_saver;
+    #endif
+
+    // default saving of primitives.
+    template<class T>
+    void save(const T &t){
+        if(os.fail())
+            boost::serialization::throw_exception(
+                archive_exception(archive_exception::output_stream_error)
+            );
+        os << t;
+    }
+
+    /////////////////////////////////////////////////////////
+    // fundamental types that need special treatment
+    void save(const bool t){
+        // trap usage of invalid uninitialized boolean which would
+        // otherwise crash on load.
+        BOOST_ASSERT(0 == static_cast<int>(t) || 1 == static_cast<int>(t));
+        if(os.fail())
+            boost::serialization::throw_exception(
+                archive_exception(archive_exception::output_stream_error)
+            );
+        os << t;
+    }
+    void save(const signed char t)
+    {
+        save(static_cast<short int>(t));
+    }
+    void save(const unsigned char t)
+    {
+        save(static_cast<short unsigned int>(t));
+    }
+    void save(const char t)
+    {
+        save(static_cast<short int>(t));
+    }
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    void save(const wchar_t t)
+    {
+        BOOST_STATIC_ASSERT(sizeof(wchar_t) <= sizeof(int));
+        save(static_cast<int>(t));
+    }
+    #endif
+    void save(const float t)
+    {
+        // must be a user mistake - can't serialize un-initialized data
+        if(os.fail())
+            boost::serialization::throw_exception(
+                archive_exception(archive_exception::output_stream_error)
+            );
+        os << std::setprecision(std::numeric_limits<float>::digits10 + 2);
+        os << t;
+    }
+    void save(const double t)
+    {
+        // must be a user mistake - can't serialize un-initialized data
+        if(os.fail())
+            boost::serialization::throw_exception(
+                archive_exception(archive_exception::output_stream_error)
+            );
+        os << std::setprecision(std::numeric_limits<double>::digits10 + 2);
+        os << t;
+    }
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+    basic_text_oprimitive(OStream & os, bool no_codecvt);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    ~basic_text_oprimitive();
+public:
+    // unformatted append of one character
+    void put(BOOST_DEDUCED_TYPENAME OStream::char_type c){
+        if(os.fail())
+            boost::serialization::throw_exception(
+                archive_exception(archive_exception::output_stream_error)
+            );
+        os.put(c);
+    }
+    // unformatted append of null terminated string
+    void put(const char * s){
+        while('\0' != *s)
+            os.put(*s++);
+    }
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void) 
+    save_binary(const void *address, std::size_t count);
+};
+
+} //namespace boost 
+} //namespace archive 
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_TEXT_OPRIMITIVE_HPP
diff --git a/SRC/Serialization/archive/basic_xml_archive.hpp b/SRC/Serialization/archive/basic_xml_archive.hpp
new file mode 100755
index 0000000..00e0624
--- /dev/null
+++ b/SRC/Serialization/archive/basic_xml_archive.hpp
@@ -0,0 +1,67 @@
+#ifndef BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_archive.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <Serialization/archive/archive_exception.hpp>
+
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost { 
+namespace archive {
+
+// constant strings used in xml i/o
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_OBJECT_ID();
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_OBJECT_REFERENCE();
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_CLASS_ID();
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE();
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_CLASS_NAME();
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_TRACKING();
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_VERSION();
+
+extern 
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_SIGNATURE();
+
+}// namespace archive
+}// namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_XML_TEXT_ARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/basic_xml_iarchive.hpp b/SRC/Serialization/archive/basic_xml_iarchive.hpp
new file mode 100755
index 0000000..0bfe865
--- /dev/null
+++ b/SRC/Serialization/archive/basic_xml_iarchive.hpp
@@ -0,0 +1,127 @@
+#ifndef BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <Serialization/pfto.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <Serialization/archive/detail/common_iarchive.hpp>
+
+#include <Serialization/nvp.hpp>
+#include <Serialization/string.hpp>
+
+#include <boost/mpl/assert.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+/////////////////////////////////////////////////////////////////////////
+// class xml_iarchive - read serialized objects from a input text stream
+template<class Archive>
+class basic_xml_iarchive :
+    public detail::common_iarchive<Archive>
+{
+protected:
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+public:
+#elif defined(BOOST_MSVC)
+    // for some inexplicable reason insertion of "class" generates compile erro
+    // on msvc 7.1
+    friend detail::interface_oarchive<Archive>;
+#else
+    friend class detail::interface_oarchive<Archive>;
+#endif
+    unsigned int depth;
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_start(const char *name);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_end(const char *name);
+
+    // Anything not an attribute and not a name-value pair is an
+    // should be trapped here.
+    template<class T>
+    void load_override(T & t,  BOOST_PFTO int)
+    {
+        // If your program fails to compile here, its most likely due to
+        // not specifying an nvp wrapper around the variable to
+        // be serialized.
+        BOOST_MPL_ASSERT((serialization::is_wrapper< T >));
+        this->detail_common_iarchive::load_override(t, 0);
+    }
+
+    // Anything not an attribute - see below - should be a name value
+    // pair and be processed here
+    typedef detail::common_iarchive<Archive> detail_common_iarchive;
+    template<class T>
+    void load_override(
+        #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+        const
+        #endif
+        boost::serialization::nvp< T > & t,
+        int
+    ){
+        this->This()->load_start(t.name());
+        this->detail_common_iarchive::load_override(t.value(), 0);
+        this->This()->load_end(t.name());
+    }
+
+    // specific overrides for attributes - handle as
+    // primitives. These are not name-value pairs
+    // so they have to be intercepted here and passed on to load.
+    // although the class_id is included in the xml text file in order
+    // to make the file self describing, it isn't used when loading
+    // an xml archive.  So we can skip it here.  Note: we MUST override
+    // it otherwise it will be loaded as a normal primitive w/o tag and
+    // leaving the archive in an undetermined state
+    void load_override(class_id_optional_type & /* t */, int){}
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_override(object_id_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_override(version_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_override(class_id_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    load_override(tracking_type & t, int);
+    // class_name_type can't be handled here as it depends upon the
+    // char type used by the stream.  So require the derived implementation
+    // handle this.
+    // void load_override(class_name_type & t, int);
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+    basic_xml_iarchive(unsigned int flags);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+    ~basic_xml_iarchive();
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_XML_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/basic_xml_oarchive.hpp b/SRC/Serialization/archive/basic_xml_oarchive.hpp
new file mode 100755
index 0000000..88792c5
--- /dev/null
+++ b/SRC/Serialization/archive/basic_xml_oarchive.hpp
@@ -0,0 +1,145 @@
+#ifndef BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#include <Serialization/archive/detail/common_oarchive.hpp>
+
+#include <Serialization/nvp.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/string.hpp>
+
+#include <boost/mpl/assert.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// class basic_xml_oarchive - write serialized objects to a xml output stream
+template<class Archive>
+class basic_xml_oarchive :
+    public detail::common_oarchive<Archive>
+{
+protected:
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+public:
+#elif defined(BOOST_MSVC)
+    // for some inexplicable reason insertion of "class" generates compile erro
+    // on msvc 7.1
+    friend detail::interface_oarchive<Archive>;
+    friend class save_access;
+#else
+    friend class detail::interface_oarchive<Archive>;
+    friend class save_access;
+#endif
+    // special stuff for xml output
+    unsigned int depth;
+    bool indent_next;
+    bool pending_preamble;
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    indent();
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    init();
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    write_attribute(
+        const char *attribute_name,
+        int t,
+        const char *conjunction = "=\""
+    );
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    write_attribute(
+        const char *attribute_name,
+        const char *key
+    );
+    // helpers used below
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_start(const char *name);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_end(const char *name);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    end_preamble();
+
+    // Anything not an attribute and not a name-value pair is an
+    // error and should be trapped here.
+    template<class T>
+    void save_override(T & t, BOOST_PFTO int)
+    {
+        // If your program fails to compile here, its most likely due to
+        // not specifying an nvp wrapper around the variable to
+        // be serialized.
+        BOOST_MPL_ASSERT((serialization::is_wrapper< T >));
+        this->detail_common_oarchive::save_override(t, 0);
+    }
+
+    // special treatment for name-value pairs.
+    typedef detail::common_oarchive<Archive> detail_common_oarchive;
+    template<class T>
+    void save_override(
+        #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+        const
+        #endif
+        ::boost::serialization::nvp< T > & t,
+        int
+    ){
+        this->This()->save_start(t.name());
+        this->detail_common_oarchive::save_override(t.const_value(), 0);
+        this->This()->save_end(t.name());
+    }
+
+    // specific overrides for attributes - not name value pairs so we
+    // want to trap them before the above "fall through"
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const object_id_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const object_reference_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const version_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const class_id_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const class_id_optional_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const class_id_reference_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const class_name_type & t, int);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+    save_override(const tracking_type & t, int);
+
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+    basic_xml_oarchive(unsigned int flags);
+    BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+    ~basic_xml_oarchive();
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_XML_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/binary_iarchive.hpp b/SRC/Serialization/archive/binary_iarchive.hpp
new file mode 100755
index 0000000..9c73c53
--- /dev/null
+++ b/SRC/Serialization/archive/binary_iarchive.hpp
@@ -0,0 +1,103 @@
+#ifndef BOOST_ARCHIVE_BINARY_IARCHIVE_HPP
+#define BOOST_ARCHIVE_BINARY_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <istream>
+#include <Serialization/archive/binary_iarchive_impl.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+// do not derive from the classes below.  If you want to extend this functionality
+// via inhertance, derived from text_iarchive_impl instead.  This will
+// preserve correct static polymorphism.
+
+// same as binary_iarchive below - without the shared_ptr_helper
+class naked_binary_iarchive : 
+    public binary_iarchive_impl<
+        boost::archive::naked_binary_iarchive, 
+        std::istream::char_type, 
+        std::istream::traits_type
+    >
+{
+public:
+    naked_binary_iarchive(std::istream & is, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            naked_binary_iarchive, std::istream::char_type, std::istream::traits_type
+        >(is, flags)
+    {}
+    naked_binary_iarchive(std::streambuf & bsb, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            naked_binary_iarchive, std::istream::char_type, std::istream::traits_type
+        >(bsb, flags)
+    {}
+};
+
+} // namespace archive
+} // namespace boost
+
+// note special treatment of shared_ptr. This type needs a special
+// structure associated with every archive.  We created a "mix-in"
+// class to provide this functionality.  Since shared_ptr holds a
+// special esteem in the boost library - we included it here by default.
+#include <Serialization/archive/shared_ptr_helper.hpp>
+
+namespace boost { 
+namespace archive {
+
+// do not derive from this class.  If you want to extend this functionality
+// via inhertance, derived from binary_iarchive_impl instead.  This will
+// preserve correct static polymorphism.
+class binary_iarchive : 
+    public binary_iarchive_impl<
+        boost::archive::binary_iarchive, 
+        std::istream::char_type, 
+        std::istream::traits_type
+    >,
+    public detail::shared_ptr_helper
+{
+public:
+    binary_iarchive(std::istream & is, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            binary_iarchive, std::istream::char_type, std::istream::traits_type
+        >(is, flags)
+    {}
+    binary_iarchive(std::streambuf & bsb, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            binary_iarchive, std::istream::char_type, std::istream::traits_type
+        >(bsb, flags)
+    {}
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_iarchive)
+BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::binary_iarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_BINARY_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/binary_iarchive_impl.hpp b/SRC/Serialization/archive/binary_iarchive_impl.hpp
new file mode 100755
index 0000000..088207f
--- /dev/null
+++ b/SRC/Serialization/archive/binary_iarchive_impl.hpp
@@ -0,0 +1,96 @@
+#ifndef BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP
+#define BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_iarchive_impl.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <istream>
+#include <Serialization/pfto.hpp>
+#include <Serialization/archive/basic_binary_iprimitive.hpp>
+#include <Serialization/archive/basic_binary_iarchive.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class Archive, class Elem, class Tr>
+class binary_iarchive_impl : 
+    public basic_binary_iprimitive<Archive, Elem, Tr>,
+    public basic_binary_iarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_iarchive<Archive>;
+    friend class basic_binary_iarchive<Archive>;
+    friend class load_access;
+protected:
+#endif
+    // note: the following should not needed - but one compiler (vc 7.1)
+    // fails to compile one test (test_shared_ptr) without it !!!
+    // make this protected so it can be called from a derived archive
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int){
+        this->basic_binary_iarchive<Archive>::load_override(t, 0L);
+    }
+    void init(unsigned int flags){
+        if(0 != (flags & no_header))
+            return;
+        #if ! defined(__MWERKS__)
+            this->basic_binary_iarchive<Archive>::init();
+            this->basic_binary_iprimitive<Archive, Elem, Tr>::init();
+        #else
+            basic_binary_iarchive<Archive>::init();
+            basic_binary_iprimitive<Archive, Elem, Tr>::init();
+        #endif
+    }
+    binary_iarchive_impl(
+        std::basic_streambuf<Elem, Tr> & bsb, 
+        unsigned int flags
+    ) :
+        basic_binary_iprimitive<Archive, Elem, Tr>(
+            bsb, 
+            0 != (flags & no_codecvt)
+        ),
+        basic_binary_iarchive<Archive>(flags)
+    {
+        init(flags);
+    }
+    binary_iarchive_impl(
+        std::basic_istream<Elem, Tr> & is, 
+        unsigned int flags
+    ) :
+        basic_binary_iprimitive<Archive, Elem, Tr>(
+            * is.rdbuf(), 
+            0 != (flags & no_codecvt)
+        ),
+        basic_binary_iarchive<Archive>(flags)
+    {
+        init(flags);
+    }
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_BINARY_IARCHIVE_IMPL_HPP
diff --git a/SRC/Serialization/archive/binary_oarchive.hpp b/SRC/Serialization/archive/binary_oarchive.hpp
new file mode 100755
index 0000000..985b990
--- /dev/null
+++ b/SRC/Serialization/archive/binary_oarchive.hpp
@@ -0,0 +1,66 @@
+#ifndef BOOST_ARCHIVE_BINARY_OARCHIVE_HPP
+#define BOOST_ARCHIVE_BINARY_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ostream>
+#include <boost/config.hpp>
+#include <Serialization/archive/binary_oarchive_impl.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+// do not derive from this class.  If you want to extend this functionality
+// via inhertance, derived from binary_oarchive_impl instead.  This will
+// preserve correct static polymorphism.
+class binary_oarchive : 
+    public binary_oarchive_impl<
+        binary_oarchive, std::ostream::char_type, std::ostream::traits_type
+    >
+{
+public:
+    binary_oarchive(std::ostream & os, unsigned int flags = 0) :
+        binary_oarchive_impl<
+            binary_oarchive, std::ostream::char_type, std::ostream::traits_type
+        >(os, flags)
+    {}
+    binary_oarchive(std::streambuf & bsb, unsigned int flags = 0) :
+        binary_oarchive_impl<
+            binary_oarchive, std::ostream::char_type, std::ostream::traits_type
+        >(bsb, flags)
+    {}
+};
+
+typedef binary_oarchive naked_binary_oarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_oarchive)
+BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(boost::archive::binary_oarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_BINARY_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/binary_oarchive_impl.hpp b/SRC/Serialization/archive/binary_oarchive_impl.hpp
new file mode 100755
index 0000000..e23a721
--- /dev/null
+++ b/SRC/Serialization/archive/binary_oarchive_impl.hpp
@@ -0,0 +1,97 @@
+#ifndef BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP
+#define BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_oarchive_impl.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ostream>
+#include <boost/config.hpp>
+#include <Serialization/pfto.hpp>
+#include <Serialization/archive/basic_binary_oprimitive.hpp>
+#include <Serialization/archive/basic_binary_oarchive.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class Archive, class Elem, class Tr>
+class binary_oarchive_impl : 
+    public basic_binary_oprimitive<Archive, Elem, Tr>,
+    public basic_binary_oarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_oarchive<Archive>;
+    friend class basic_binary_oarchive<Archive>;
+    friend class save_access;
+protected:
+#endif
+    // note: the following should not needed - but one compiler (vc 7.1)
+    // fails to compile one test (test_shared_ptr) without it !!!
+    // make this protected so it can be called from a derived archive
+    template<class T>
+    void save_override(T & t, BOOST_PFTO int){
+        this->basic_binary_oarchive<Archive>::save_override(t, 0L);
+    }
+    void init(unsigned int flags) {
+        if(0 != (flags & no_header))
+            return;
+        #if ! defined(__MWERKS__)
+            this->basic_binary_oarchive<Archive>::init();
+            this->basic_binary_oprimitive<Archive, Elem, Tr>::init();
+        #else
+            basic_binary_oarchive<Archive>::init();
+            basic_binary_oprimitive<Archive, Elem, Tr>::init();
+        #endif
+    }
+    binary_oarchive_impl(
+        std::basic_streambuf<Elem, Tr> & bsb, 
+        unsigned int flags
+    ) :
+        basic_binary_oprimitive<Archive, Elem, Tr>(
+            bsb, 
+            0 != (flags & no_codecvt)
+        ),
+        basic_binary_oarchive<Archive>(flags)
+    {
+        init(flags);
+    }
+    binary_oarchive_impl(
+        std::basic_ostream<Elem, Tr> & os, 
+        unsigned int flags
+    ) :
+        basic_binary_oprimitive<Archive, Elem, Tr>(
+            * os.rdbuf(), 
+            0 != (flags & no_codecvt)
+        ),
+        basic_binary_oarchive<Archive>(flags)
+    {
+        init(flags);
+    }
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_BINARY_OARCHIVE_IMPL_HPP
diff --git a/SRC/Serialization/archive/binary_wiarchive.hpp b/SRC/Serialization/archive/binary_wiarchive.hpp
new file mode 100755
index 0000000..7253d96
--- /dev/null
+++ b/SRC/Serialization/archive/binary_wiarchive.hpp
@@ -0,0 +1,93 @@
+#ifndef BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP
+#define BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_wiarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <istream> // wistream
+#include <Serialization/archive/binary_iarchive_impl.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+
+namespace boost { 
+namespace archive {
+
+// same as binary_wiarchive below - without the shared_ptr_helper
+class naked_binary_wiarchive : 
+    public binary_iarchive_impl<
+        boost::archive::naked_binary_wiarchive, 
+        std::wistream::char_type, 
+        std::wistream::traits_type
+    >
+{
+public:
+    naked_binary_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            naked_binary_wiarchive, 
+            std::wistream::char_type, 
+            std::wistream::traits_type
+        >(is, flags)
+    {}
+    naked_binary_wiarchive(std::wstreambuf & bsb, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            naked_binary_wiarchive, 
+            std::wistream::char_type, 
+            std::wistream::traits_type
+        >(bsb, flags)
+    {}
+};
+
+} // namespace archive
+} // namespace boost
+
+// note special treatment of shared_ptr. This type needs a special
+// structure associated with every archive.  We created a "mix-in"
+// class to provide this functionality.  Since shared_ptr holds a
+// special esteem in the boost library - we included it here by default.
+#include <Serialization/archive/shared_ptr_helper.hpp>
+
+namespace boost { 
+namespace archive {
+
+class binary_wiarchive : 
+    public binary_iarchive_impl<
+        binary_wiarchive, std::wistream::char_type, std::wistream::traits_type
+    >
+{
+public:
+    binary_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            binary_wiarchive, std::wistream::char_type, std::wistream::traits_type
+        >(is, flags)
+    {}
+    binary_wiarchive(std::wstreambuf & bsb, unsigned int flags = 0) :
+        binary_iarchive_impl<
+            binary_wiarchive, std::wistream::char_type, std::wistream::traits_type
+        >(bsb, flags)
+    {}
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_wiarchive)
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_BINARY_WIARCHIVE_HPP
diff --git a/SRC/Serialization/archive/binary_woarchive.hpp b/SRC/Serialization/archive/binary_woarchive.hpp
new file mode 100755
index 0000000..2ac9590
--- /dev/null
+++ b/SRC/Serialization/archive/binary_woarchive.hpp
@@ -0,0 +1,61 @@
+#ifndef BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP
+#define BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_woarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <ostream>
+#include <Serialization/archive/binary_oarchive_impl.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+
+namespace boost { 
+namespace archive {
+
+// do not derive from this class.  If you want to extend this functionality
+// via inhertance, derived from binary_oarchive_impl instead.  This will
+// preserve correct static polymorphism.
+class binary_woarchive : 
+    public binary_oarchive_impl<
+            binary_woarchive, std::wostream::char_type, std::wostream::traits_type
+        >
+{
+public:
+    binary_woarchive(std::wostream & os, unsigned int flags = 0) :
+        binary_oarchive_impl<
+            binary_woarchive, std::wostream::char_type, std::wostream::traits_type
+        >(os, flags)
+    {}
+    binary_woarchive(std::wstreambuf & bsb, unsigned int flags = 0) :
+        binary_oarchive_impl<
+            binary_woarchive, std::wostream::char_type, std::wostream::traits_type
+        >(bsb, flags)
+    {}
+};
+
+typedef binary_woarchive naked_binary_woarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::binary_woarchive)
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_BINARY_WOARCHIVE_HPP
diff --git a/SRC/Serialization/archive/codecvt_null.hpp b/SRC/Serialization/archive/codecvt_null.hpp
new file mode 100755
index 0000000..f515ae5
--- /dev/null
+++ b/SRC/Serialization/archive/codecvt_null.hpp
@@ -0,0 +1,100 @@
+#ifndef BOOST_ARCHIVE_CODECVT_NULL_HPP
+#define BOOST_ARCHIVE_CODECVT_NULL_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// codecvt_null.hpp:
+
+// (C) Copyright 2004 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <locale>
+#include <cstddef> // NULL, size_t
+#include <cwchar>   // for mbstate_t
+#include <boost/config.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std {
+// For STLport on WinCE, BOOST_NO_STDC_NAMESPACE can get defined if STLport is putting symbols in its own namespace.
+// In the case of codecvt, however, this does not mean that codecvt is in the global namespace (it will be in STLport's namespace)
+#  if !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
+    using ::codecvt;
+#  endif
+    using ::mbstate_t;
+    using ::size_t;
+} // namespace
+#endif
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+template<class Ch>
+class codecvt_null;
+
+template<>
+class codecvt_null<char> : public std::codecvt<char, char, std::mbstate_t>
+{
+    virtual bool do_always_noconv() const throw() {
+        return true;
+    }
+public:
+    explicit codecvt_null(std::size_t no_locale_manage = 0) :
+        std::codecvt<char, char, std::mbstate_t>(no_locale_manage)
+    {}
+};
+
+template<>
+class codecvt_null<wchar_t> : public std::codecvt<wchar_t, char, std::mbstate_t>
+{
+    virtual BOOST_WARCHIVE_DECL(std::codecvt_base::result)
+    do_out(
+        std::mbstate_t & state,
+        const wchar_t * first1,
+        const wchar_t * last1,
+        const wchar_t * & next1,
+        char * first2,
+        char * last2,
+        char * & next2
+    ) const;
+    virtual BOOST_WARCHIVE_DECL(std::codecvt_base::result)
+    do_in(
+        std::mbstate_t & state,
+        const char * first1,
+        const char * last1,
+        const char * & next1,
+        wchar_t * first2,
+        wchar_t * last2,
+        wchar_t * & next2
+    ) const;
+    virtual int do_encoding( ) const throw( ){
+        return sizeof(wchar_t) / sizeof(char);
+    }
+    virtual int do_max_length( ) const throw( ){
+        return do_encoding();
+    }
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+#include <Serialization/archive/detail/abi_suffix.hpp> // pop pragmas
+
+#endif //BOOST_ARCHIVE_CODECVT_NULL_HPP
diff --git a/SRC/Serialization/archive/detail/abi_prefix.hpp b/SRC/Serialization/archive/detail/abi_prefix.hpp
new file mode 100755
index 0000000..093a109
--- /dev/null
+++ b/SRC/Serialization/archive/detail/abi_prefix.hpp
@@ -0,0 +1,20 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// abi_prefix.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config/abi_prefix.hpp> // must be the last header
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4251 4231 4660 4275)
+#endif
+
+#if defined( __BORLANDC__ )
+#pragma nopushoptwarn
+#endif
+
diff --git a/SRC/Serialization/archive/detail/abi_suffix.hpp b/SRC/Serialization/archive/detail/abi_suffix.hpp
new file mode 100755
index 0000000..61061ca
--- /dev/null
+++ b/SRC/Serialization/archive/detail/abi_suffix.hpp
@@ -0,0 +1,19 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// abi_suffix.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+#include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#if defined( __BORLANDC__ )
+#pragma nopushoptwarn
+#endif
+
diff --git a/SRC/Serialization/archive/detail/archive_serializer_map.hpp b/SRC/Serialization/archive/detail/archive_serializer_map.hpp
new file mode 100755
index 0000000..de70931
--- /dev/null
+++ b/SRC/Serialization/archive/detail/archive_serializer_map.hpp
@@ -0,0 +1,55 @@
+#ifndef BOOST_ARCHIVE_SERIALIZER_MAP_HPP
+#define BOOST_ARCHIVE_SERIALIZER_MAP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// archive_serializer_map.hpp: extenstion of type_info required for 
+// serialization.
+
+// (C) Copyright 2009 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// note: this is nothing more than the thinest of wrappers around
+// basic_serializer_map so we can have a one map / archive type. 
+
+#include <boost/config.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+namespace archive {
+namespace detail {
+
+class basic_serializer;
+
+template<class Archive>
+class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+archive_serializer_map {
+public:
+    static bool insert(const basic_serializer * bs);
+    static void erase(const basic_serializer * bs);
+    static const basic_serializer * find(
+        const boost::serialization::extended_type_info & type_
+    );
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // must be the last header
+
+#endif //BOOST_ARCHIVE_SERIALIZER_MAP_HPP
diff --git a/SRC/Serialization/archive/detail/auto_link_archive.hpp b/SRC/Serialization/archive/detail/auto_link_archive.hpp
new file mode 100755
index 0000000..a7d973b
--- /dev/null
+++ b/SRC/Serialization/archive/detail/auto_link_archive.hpp
@@ -0,0 +1,48 @@
+#ifndef BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP
+#define BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+//  auto_link_archive.hpp
+//
+//  (c) Copyright Robert Ramey 2004
+//  Use, modification, and distribution is subject to the Boost Software
+//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+//  See library home page at http://www.boost.org/libs/serialization
+
+//----------------------------------------------------------------------------// 
+
+// This header implements separate compilation features as described in
+// http://www.boost.org/more/separate_compilation.html
+
+//  enable automatic library variant selection  ------------------------------// 
+
+#include <Serialization/archive/detail/decl.hpp>
+
+#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SERIALIZATION_NO_LIB) \
+&&  !defined(BOOST_ARCHIVE_SOURCE) && !defined(BOOST_WARCHIVE_SOURCE)  \
+&&  !defined(BOOST_SERIALIZATION_SOURCE)
+
+    // Set the name of our library, this will get undef'ed by auto_link.hpp
+    // once it's done with it:
+    //
+    #define BOOST_LIB_NAME boost_serialization
+    //
+    // If we're importing code from a dll, then tell auto_link.hpp about it:
+    //
+    #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK)
+    #  define BOOST_DYN_LINK
+    #endif
+    //
+    // And include the header that does the work:
+    //
+    #include <boost/config/auto_link.hpp>
+#endif  // auto-linking disabled
+
+#endif // BOOST_ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP
diff --git a/SRC/Serialization/archive/detail/auto_link_warchive.hpp b/SRC/Serialization/archive/detail/auto_link_warchive.hpp
new file mode 100755
index 0000000..3512b2a
--- /dev/null
+++ b/SRC/Serialization/archive/detail/auto_link_warchive.hpp
@@ -0,0 +1,47 @@
+#ifndef BOOST_ARCHIVE_DETAIL_AUTO_LINK_WARCHIVE_HPP
+#define BOOST_ARCHIVE_DETAIL_AUTO_LINK_WARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+//  auto_link_warchive.hpp
+//
+//  (c) Copyright Robert Ramey 2004
+//  Use, modification, and distribution is subject to the Boost Software
+//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+//  See library home page at http://www.boost.org/libs/serialization
+
+//----------------------------------------------------------------------------// 
+
+// This header implements separate compilation features as described in
+// http://www.boost.org/more/separate_compilation.html
+
+//  enable automatic library variant selection  ------------------------------// 
+
+#include <Serialization/archive/detail/decl.hpp>
+
+#if !defined(BOOST_WARCHIVE_SOURCE) \
+&& !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SERIALIZATION_NO_LIB)
+
+// Set the name of our library, this will get undef'ed by auto_link.hpp
+// once it's done with it:
+//
+#define BOOST_LIB_NAME boost_wserialization
+//
+// If we're importing code from a dll, then tell auto_link.hpp about it:
+//
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK)
+#  define BOOST_DYN_LINK
+#endif
+//
+// And include the header that does the work:
+//
+#include <boost/config/auto_link.hpp>
+#endif  // auto-linking disabled
+
+#endif // ARCHIVE_DETAIL_AUTO_LINK_ARCHIVE_HPP
diff --git a/SRC/Serialization/archive/detail/basic_iarchive.hpp b/SRC/Serialization/archive/detail/basic_iarchive.hpp
new file mode 100755
index 0000000..32e2cf6
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_iarchive.hpp
@@ -0,0 +1,110 @@
+#ifndef BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP
+#define BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_iarchive.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// can't use this - much as I'd like to as borland doesn't support it
+// #include <boost/scoped_ptr.hpp>
+
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <boost/type_traits/broken_compiler_spec.hpp>
+#include <Serialization/tracking_enum.hpp>
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/archive/detail/decl.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+namespace archive {
+namespace detail {
+
+class basic_iarchive_impl;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer;
+//////////////////////////////////////////////////////////////////////
+// class basic_iarchive - read serialized objects from a input stream
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive :
+    private boost::noncopyable
+{
+    friend class basic_iarchive_impl;
+    // hide implementation of this class to minimize header conclusion
+    // in client code. I couldn't used scoped pointer with borland
+    // boost::scoped_ptr<basic_iarchive_impl> pimpl;
+    basic_iarchive_impl * pimpl;
+
+    virtual void vload(version_type &t) =  0;
+    virtual void vload(object_id_type &t) =  0;
+    virtual void vload(class_id_type &t) =  0;
+    virtual void vload(class_id_optional_type &t) = 0;
+    virtual void vload(class_name_type &t) = 0;
+    virtual void vload(tracking_type &t) = 0;
+protected:
+    basic_iarchive(unsigned int flags);
+    // account for bogus gcc warning
+    #if defined(__GNUC__)
+    virtual
+    #endif
+    ~basic_iarchive();
+public:
+    // note: NOT part of the public API.
+    void next_object_pointer(void *t);
+    void register_basic_serializer(
+        const basic_iserializer & bis
+    );
+    void load_object(
+        void *t, 
+        const basic_iserializer & bis
+    );
+    const basic_pointer_iserializer * 
+    load_pointer(
+        void * & t, 
+        const basic_pointer_iserializer * bpis_ptr,
+        const basic_pointer_iserializer * (*finder)(
+            const boost::serialization::extended_type_info & eti
+        )
+
+    );
+    // real public API starts here
+    void 
+    set_library_version(library_version_type archive_library_version);
+    library_version_type 
+    get_library_version() const;
+    unsigned int
+    get_flags() const;
+    void 
+    reset_object_address(const void * new_address, const void * old_address);
+    void 
+    delete_created_pointers();
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+// required by smart_cast for compilers not implementing 
+// partial template specialization
+BOOST_TT_BROKEN_COMPILER_SPEC(
+    boost::archive::detail::basic_iarchive  
+) 
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif //BOOST_ARCHIVE_DETAIL_BASIC_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/detail/basic_iserializer.hpp b/SRC/Serialization/archive/detail/basic_iserializer.hpp
new file mode 100755
index 0000000..db15cf1
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_iserializer.hpp
@@ -0,0 +1,95 @@
+#ifndef BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP
+#define BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_iserializer.hpp: extenstion of type_info required for serialization.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstdlib> // NULL
+#include <boost/config.hpp>
+
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/archive/detail/decl.hpp>
+#include <Serialization/archive/detail/basic_serializer.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+// forward declarations
+namespace archive {
+namespace detail {
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer;
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer : 
+    public basic_serializer
+{
+private:
+    basic_pointer_iserializer *m_bpis;
+protected:
+    explicit basic_iserializer(
+        const boost::serialization::extended_type_info & type
+    );
+    // account for bogus gcc warning
+    #if defined(__GNUC__)
+    virtual
+    #endif
+    ~basic_iserializer();
+public:
+    bool serialized_as_pointer() const {
+        return m_bpis != NULL;
+    }
+    void set_bpis(basic_pointer_iserializer *bpis){
+        m_bpis = bpis;
+    }
+    const basic_pointer_iserializer * get_bpis_ptr() const {
+        return m_bpis;
+    }
+    virtual void load_object_data(
+        basic_iarchive & ar, 
+        void *x,
+        const unsigned int file_version
+    ) const = 0;
+    // returns true if class_info should be saved
+    virtual bool class_info() const = 0 ;
+    // returns true if objects should be tracked
+    virtual bool tracking(const unsigned int) const = 0 ;
+    // returns class version
+    virtual version_type version() const = 0 ;
+    // returns true if this class is polymorphic
+    virtual bool is_polymorphic() const = 0;
+    virtual void destroy(/*const*/ void *address) const = 0 ;
+};
+
+} // namespae detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_DETAIL_BASIC_ISERIALIZER_HPP
diff --git a/SRC/Serialization/archive/detail/basic_oarchive.hpp b/SRC/Serialization/archive/detail/basic_oarchive.hpp
new file mode 100755
index 0000000..6cfa4e3
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_oarchive.hpp
@@ -0,0 +1,106 @@
+#ifndef BOOST_ARCHIVE_BASIC_OARCHIVE_HPP
+#define BOOST_ARCHIVE_BASIC_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_oarchive.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // NULL
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <boost/type_traits/broken_compiler_spec.hpp>
+
+// can't use this - much as I'd like to as borland doesn't support it
+// #include <boost/scoped_ptr.hpp>
+
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/tracking_enum.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+namespace archive {
+namespace detail {
+
+class basic_oarchive_impl;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer;
+//////////////////////////////////////////////////////////////////////
+// class basic_oarchive - write serialized objects to an output stream
+class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive :
+    private boost::noncopyable
+{
+    friend class basic_oarchive_impl;
+    // hide implementation of this class to minimize header conclusion
+    // in client code. note: borland can't use scoped_ptr
+    //boost::scoped_ptr<basic_oarchive_impl> pimpl;
+    basic_oarchive_impl * pimpl;
+
+    // overload these to bracket object attributes. Used to implement
+    // xml archives
+    virtual void vsave(const version_type t) =  0;
+    virtual void vsave(const object_id_type t) =  0;
+    virtual void vsave(const object_reference_type t) =  0;
+    virtual void vsave(const class_id_type t) =  0;
+    virtual void vsave(const class_id_optional_type t) = 0;
+    virtual void vsave(const class_id_reference_type t) =  0;
+    virtual void vsave(const class_name_type & t) = 0;
+    virtual void vsave(const tracking_type t) = 0;
+protected:
+    basic_oarchive(unsigned int flags = 0);
+    // account for bogus gcc warning
+    #if defined(__GNUC__)
+    virtual
+    #endif
+    ~basic_oarchive();
+public:
+    // note: NOT part of the public interface
+    void register_basic_serializer(
+        const basic_oserializer & bos
+    );
+    void save_object(
+        const void *x, 
+        const basic_oserializer & bos
+    );
+    void save_pointer(
+        const void * t, 
+        const basic_pointer_oserializer * bpos_ptr
+    );
+    void save_null_pointer(){
+        vsave(NULL_POINTER_TAG);
+    }
+    // real public interface starts here
+    void end_preamble(); // default implementation does nothing
+    library_version_type get_library_version() const;
+    unsigned int get_flags() const;
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+// required by smart_cast for compilers not implementing 
+// partial template specialization
+BOOST_TT_BROKEN_COMPILER_SPEC(
+    boost::archive::detail::basic_oarchive
+)
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif //BOOST_ARCHIVE_BASIC_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/detail/basic_oserializer.hpp b/SRC/Serialization/archive/detail/basic_oserializer.hpp
new file mode 100755
index 0000000..c8d621b
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_oserializer.hpp
@@ -0,0 +1,93 @@
+#ifndef BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP
+#define BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_oserializer.hpp: extenstion of type_info required for serialization.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // NULL
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/basic_serializer.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+// forward declarations
+namespace archive {
+namespace detail {
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer;
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer : 
+    public basic_serializer
+{
+private:
+    basic_pointer_oserializer *m_bpos;
+protected:
+    explicit basic_oserializer(
+        const boost::serialization::extended_type_info & type_
+    );
+    // account for bogus gcc warning
+    #if defined(__GNUC__)
+    virtual
+    #endif
+    ~basic_oserializer();
+public:
+    bool serialized_as_pointer() const {
+        return m_bpos != NULL;
+    }
+    void set_bpos(basic_pointer_oserializer *bpos){
+        m_bpos = bpos;
+    }
+    const basic_pointer_oserializer * get_bpos() const {
+        return m_bpos;
+    }
+    virtual void save_object_data(
+        basic_oarchive & ar, const void * x
+    ) const = 0;
+    // returns true if class_info should be saved
+    virtual bool class_info() const = 0;
+    // returns true if objects should be tracked
+    virtual bool tracking(const unsigned int flags) const = 0;
+    // returns class version
+    virtual version_type version() const = 0;
+    // returns true if this class is polymorphic
+    virtual bool is_polymorphic() const = 0;
+};
+
+} // namespace detail
+} // namespace serialization
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_SERIALIZATION_BASIC_OSERIALIZER_HPP
diff --git a/SRC/Serialization/archive/detail/basic_pointer_iserializer.hpp b/SRC/Serialization/archive/detail/basic_pointer_iserializer.hpp
new file mode 100755
index 0000000..c146fee
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_pointer_iserializer.hpp
@@ -0,0 +1,73 @@
+#ifndef BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP
+#define BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_pointer_oserializer.hpp: extenstion of type_info required for 
+// serialization.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/basic_serializer.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+// forward declarations
+namespace archive {
+namespace detail {
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer;
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer 
+    : public basic_serializer {
+protected:
+    explicit basic_pointer_iserializer(
+        const boost::serialization::extended_type_info & type_
+    );
+    // account for bogus gcc warning
+    #if defined(__GNUC__)
+    virtual
+    #endif
+    ~basic_pointer_iserializer();
+public:
+    virtual const basic_iserializer & get_basic_serializer() const = 0;
+    virtual void load_object_ptr(
+        basic_iarchive & ar, 
+        void * & x,
+        const unsigned int file_version
+    ) const = 0;
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_POINTER_ISERIALIZER_HPP
diff --git a/SRC/Serialization/archive/detail/basic_pointer_oserializer.hpp b/SRC/Serialization/archive/detail/basic_pointer_oserializer.hpp
new file mode 100755
index 0000000..f5f7768
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_pointer_oserializer.hpp
@@ -0,0 +1,72 @@
+#ifndef BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP
+#define BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_pointer_oserializer.hpp: extenstion of type_info required for 
+// serialization.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/basic_serializer.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+namespace archive {
+namespace detail {
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer;
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer : 
+    public basic_serializer
+{
+protected:
+    explicit basic_pointer_oserializer(
+        const boost::serialization::extended_type_info & type_
+    );
+public:
+    // account for bogus gcc warning
+    #if defined(__GNUC__)
+    virtual
+    #endif
+    ~basic_pointer_oserializer();
+    virtual const basic_oserializer & get_basic_serializer() const = 0;
+    virtual void save_object_ptr(
+        basic_oarchive & ar,
+        const void * x
+    ) const = 0;
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_BASIC_POINTER_OSERIALIZER_HPP
diff --git a/SRC/Serialization/archive/detail/basic_serializer.hpp b/SRC/Serialization/archive/detail/basic_serializer.hpp
new file mode 100755
index 0000000..fb1230e
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_serializer.hpp
@@ -0,0 +1,79 @@
+#ifndef  BOOST_ARCHIVE_BASIC_SERIALIZER_HPP
+#define BOOST_ARCHIVE_BASIC_SERIALIZER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_serializer.hpp: extenstion of type_info required for serialization.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <cstddef> // NULL
+
+#include <boost/noncopyable.hpp>
+#include <boost/config.hpp>
+#include <Serialization/extended_type_info.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+class basic_serializer : 
+    private boost::noncopyable
+{
+    const boost::serialization::extended_type_info * m_eti;
+protected:
+    explicit basic_serializer(
+        const boost::serialization::extended_type_info & eti
+    ) : 
+        m_eti(& eti)
+    {
+        BOOST_ASSERT(NULL != & eti);
+    }
+public:
+    inline bool 
+    operator<(const basic_serializer & rhs) const {
+        // can't compare address since there can be multiple eti records
+        // for the same type in different execution modules (that is, DLLS)
+        // leave this here as a reminder not to do this!
+        // return & lhs.get_eti() < & rhs.get_eti();
+        return get_eti() < rhs.get_eti();
+    }
+    const char * get_debug_info() const {
+        return m_eti->get_debug_info();
+    }
+    const boost::serialization::extended_type_info & get_eti() const {
+        return * m_eti;
+    }
+};
+
+class basic_serializer_arg : public basic_serializer {
+public:
+    basic_serializer_arg(const serialization::extended_type_info & eti) :
+        basic_serializer(eti)
+    {}
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_BASIC_SERIALIZER_HPP
diff --git a/SRC/Serialization/archive/detail/basic_serializer_map.hpp b/SRC/Serialization/archive/detail/basic_serializer_map.hpp
new file mode 100755
index 0000000..52d6e88
--- /dev/null
+++ b/SRC/Serialization/archive/detail/basic_serializer_map.hpp
@@ -0,0 +1,69 @@
+#ifndef  BOOST_SERIALIZER_MAP_HPP
+#define BOOST_SERIALIZER_MAP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_serializer_map.hpp: extenstion of type_info required for serialization.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <set>
+
+#include <boost/config.hpp>
+#include <boost/utility.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost { 
+namespace serialization {
+    class extended_type_info;
+}
+
+namespace archive {
+namespace detail {
+
+class basic_serializer;
+
+class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_serializer_map : public
+    boost::noncopyable
+{
+    struct type_info_pointer_compare
+    {
+        bool operator()(
+            const basic_serializer * lhs, const basic_serializer * rhs
+        ) const ;
+    };
+    typedef std::set<
+        const basic_serializer *, 
+        type_info_pointer_compare
+    > map_type;
+    map_type m_map;
+public:
+    bool insert(const basic_serializer * bs);
+    void erase(const basic_serializer * bs);
+    const basic_serializer * find(
+        const boost::serialization::extended_type_info & type_
+    ) const;
+private:
+    // cw 8.3 requires this
+    basic_serializer_map& operator=(basic_serializer_map const&);
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // must be the last header
+
+#endif // BOOST_SERIALIZER_MAP_HPP
diff --git a/SRC/Serialization/archive/detail/check.hpp b/SRC/Serialization/archive/detail/check.hpp
new file mode 100755
index 0000000..342a95f
--- /dev/null
+++ b/SRC/Serialization/archive/detail/check.hpp
@@ -0,0 +1,169 @@
+#ifndef BOOST_ARCHIVE_DETAIL_CHECK_HPP
+#define BOOST_ARCHIVE_DETAIL_CHECK_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#pragma inline_depth(511)
+#pragma inline_recursion(on)
+#endif
+
+#if defined(__MWERKS__)
+#pragma inline_depth(511)
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// check.hpp: interface for serialization system.
+
+// (C) Copyright 2009 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/type_traits/is_const.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/greater.hpp>
+#include <boost/mpl/assert.hpp>
+
+#include <Serialization/static_warning.hpp>
+#include <Serialization/version.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/wrapper.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+// checks for objects
+
+template<class T>
+inline void check_object_level(){
+    typedef 
+        BOOST_DEDUCED_TYPENAME mpl::greater_equal<
+            serialization::implementation_level< T >,
+            mpl::int_<serialization::primitive_type>
+        >::type typex;
+
+    // trap attempts to serialize objects marked
+    // not_serializable
+    BOOST_STATIC_ASSERT(typex::value);
+}
+
+template<class T>
+inline void check_object_versioning(){
+    typedef 
+        BOOST_DEDUCED_TYPENAME mpl::or_<
+            BOOST_DEDUCED_TYPENAME mpl::greater<
+                serialization::implementation_level< T >,
+                mpl::int_<serialization::object_serializable>
+            >,
+            BOOST_DEDUCED_TYPENAME mpl::equal_to<
+                serialization::version< T >,
+                mpl::int_<0>
+            >
+        > typex;
+    // trap attempts to serialize with objects that don't
+    // save class information in the archive with versioning.
+    BOOST_STATIC_ASSERT(typex::value);
+}
+
+template<class T>
+inline void check_object_tracking(){
+    // presume it has already been determined that
+    // T is not a const
+    BOOST_STATIC_ASSERT(! boost::is_const< T >::value);
+    typedef BOOST_DEDUCED_TYPENAME mpl::equal_to<
+        serialization::tracking_level< T >,
+        mpl::int_<serialization::track_never>
+    >::type typex;
+    // saving an non-const object of a type not marked "track_never)
+
+    // may be an indicator of an error usage of the
+    // serialization library and should be double checked.  
+    // See documentation on object tracking.  Also, see the 
+    // "rationale" section of the documenation
+    // for motivation for this checking.
+
+    BOOST_STATIC_WARNING(typex::value);
+}
+
+// checks for pointers
+
+template<class T>
+inline void check_pointer_level(){
+    // we should only invoke this once we KNOW that T
+    // has been used as a pointer!!
+    typedef 
+        BOOST_DEDUCED_TYPENAME mpl::or_<
+            BOOST_DEDUCED_TYPENAME mpl::greater<
+                serialization::implementation_level< T >,
+                mpl::int_<serialization::object_serializable>
+            >,
+            BOOST_DEDUCED_TYPENAME mpl::not_<
+                BOOST_DEDUCED_TYPENAME mpl::equal_to<
+                    serialization::tracking_level< T >,
+                    mpl::int_<serialization::track_selectively>
+                >
+            >
+        > typex;
+    // Address the following when serializing to a pointer:
+
+    // a) This type doesn't save class information in the
+    // archive. That is, the serialization trait implementation
+    // level <= object_serializable.
+    // b) Tracking for this type is set to "track selectively"
+
+    // in this case, indication that an object is tracked is
+    // not stored in the archive itself - see level == object_serializable
+    // but rather the existence of the operation ar >> T * is used to 
+    // infer that an object of this type should be tracked.  So, if
+    // you save via a pointer but don't load via a pointer the operation
+    // will fail on load without given any valid reason for the failure.
+
+    // So if your program traps here, consider changing the 
+    // tracking or implementation level traits - or not
+    // serializing via a pointer.
+    BOOST_STATIC_WARNING(typex::value);
+}
+
+template<class T>
+void inline check_pointer_tracking(){
+    typedef BOOST_DEDUCED_TYPENAME mpl::greater<
+        serialization::tracking_level< T >,
+        mpl::int_<serialization::track_never>
+    >::type typex;
+    // serializing an object of a type marked "track_never" through a pointer
+    // could result in creating more objects than were saved!
+    BOOST_STATIC_WARNING(typex::value);
+}
+
+template<class T>
+inline void check_const_loading(){
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::or_<
+            BOOST_DEDUCED_TYPENAME boost::serialization::is_wrapper< T >,
+            BOOST_DEDUCED_TYPENAME mpl::not_<
+                BOOST_DEDUCED_TYPENAME boost::is_const< T >
+            >
+        >::type typex;
+    // cannot load data into a "const" object unless it's a
+    // wrapper around some other non-const object.
+    BOOST_STATIC_ASSERT(typex::value);
+}
+
+} // detail
+} // archive
+} // boost
+
+#endif // BOOST_ARCHIVE_DETAIL_CHECK_HPP
diff --git a/SRC/Serialization/archive/detail/common_iarchive.hpp b/SRC/Serialization/archive/detail/common_iarchive.hpp
new file mode 100755
index 0000000..35e49ca
--- /dev/null
+++ b/SRC/Serialization/archive/detail/common_iarchive.hpp
@@ -0,0 +1,88 @@
+#ifndef BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP
+#define BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// common_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#include <Serialization/archive/detail/basic_iarchive.hpp>
+#include <Serialization/archive/detail/basic_pointer_iserializer.hpp>
+#include <Serialization/archive/detail/interface_iarchive.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+class extended_type_info;
+
+// note: referred to as Curiously Recurring Template Patter (CRTP)
+template<class Archive>
+class common_iarchive : 
+    public basic_iarchive,
+    public interface_iarchive<Archive>
+{
+    friend class interface_iarchive<Archive>;
+private:
+    virtual void vload(version_type & t){
+        * this->This() >> t; 
+    }
+    virtual void vload(object_id_type & t){
+        * this->This() >> t;
+    }
+    virtual void vload(class_id_type & t){
+        * this->This() >> t;
+    }
+    virtual void vload(class_id_optional_type & t){
+        * this->This() >> t;
+    }
+    virtual void vload(tracking_type & t){
+        * this->This() >> t;
+    }
+    virtual void vload(class_name_type &s){
+        * this->This() >> s;
+    }
+protected:
+    // default processing - invoke serialization library
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int){
+        archive::load(* this->This(), t);
+    }
+    // default implementations of functions which emit start/end tags for
+    // archive types that require them.
+    void load_start(const char * /*name*/){}
+    void load_end(const char * /*name*/){}
+    // default archive initialization
+    common_iarchive(unsigned int flags = 0) : 
+        basic_iarchive(flags),
+        interface_iarchive<Archive>()
+    {}
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_DETAIL_COMMON_IARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/detail/common_oarchive.hpp b/SRC/Serialization/archive/detail/common_oarchive.hpp
new file mode 100755
index 0000000..e7e1985
--- /dev/null
+++ b/SRC/Serialization/archive/detail/common_oarchive.hpp
@@ -0,0 +1,87 @@
+#ifndef BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP
+#define BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// common_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#include <Serialization/archive/detail/basic_oarchive.hpp>
+#include <Serialization/archive/detail/interface_oarchive.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+// note: referred to as Curiously Recurring Template Patter (CRTP)
+template<class Archive>
+class common_oarchive : 
+    public basic_oarchive,
+    public interface_oarchive<Archive>
+{
+    friend class interface_oarchive<Archive>;
+private:
+    virtual void vsave(const version_type t){
+        * this->This() << t;
+    }
+    virtual void vsave(const object_id_type t){
+        * this->This() << t;
+    }
+    virtual void vsave(const object_reference_type t){
+        * this->This() << t;
+    }
+    virtual void vsave(const class_id_type t){
+        * this->This() << t;
+    }
+    virtual void vsave(const class_id_reference_type t){
+        * this->This() << t;
+    }
+    virtual void vsave(const class_id_optional_type t){
+        * this->This() << t;
+    }
+    virtual void vsave(const class_name_type & t){
+        * this->This() << t;
+    }
+    virtual void vsave(const tracking_type t){
+        * this->This() << t;
+    }
+protected:
+    // default processing - invoke serialization library
+    template<class T>
+    void save_override(T & t, BOOST_PFTO int){
+        archive::save(* this->This(), t);
+    }
+    void save_start(const char * /*name*/){}
+    void save_end(const char * /*name*/){}
+    common_oarchive(unsigned int flags = 0) : 
+        basic_oarchive(flags),
+        interface_oarchive<Archive>()
+    {}
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_DETAIL_COMMON_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/detail/decl.hpp b/SRC/Serialization/archive/detail/decl.hpp
new file mode 100755
index 0000000..f12f773
--- /dev/null
+++ b/SRC/Serialization/archive/detail/decl.hpp
@@ -0,0 +1,79 @@
+#ifndef BOOST_ARCHIVE_DETAIL_DECL_HPP
+#define BOOST_ARCHIVE_DETAIL_DECL_HPP 
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif 
+
+/////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8
+//  decl.hpp
+//
+//  (c) Copyright Robert Ramey 2004
+//  Use, modification, and distribution is subject to the Boost Software
+//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+//  See library home page at http://www.boost.org/libs/serialization
+
+//----------------------------------------------------------------------------// 
+
+// This header implements separate compilation features as described in
+// http://www.boost.org/more/separate_compilation.html
+
+#include <boost/config.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
+
+#if defined(BOOST_HAS_DECLSPEC)
+    #if (defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK))
+        #if defined(BOOST_ARCHIVE_SOURCE)
+            #if defined(__BORLANDC__)
+            #define BOOST_ARCHIVE_DECL(T) T __export
+            #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T)  T __export
+            #else
+            #define BOOST_ARCHIVE_DECL(T) __declspec(dllexport) T
+            #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T)  __declspec(dllexport) T
+            #endif
+        #else
+            #if defined(__BORLANDC__)
+            #define BOOST_ARCHIVE_DECL(T) T __import
+            #else
+            #define BOOST_ARCHIVE_DECL(T) __declspec(dllimport) T
+            #endif
+        #endif
+        #if defined(BOOST_WARCHIVE_SOURCE)
+            #if defined(__BORLANDC__)
+            #define BOOST_WARCHIVE_DECL(T) T __export
+            #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __export
+            #else
+            #define BOOST_WARCHIVE_DECL(T) __declspec(dllexport) T
+            #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllexport) T
+            #endif
+        #else
+            #if defined(__BORLANDC__)
+            #define BOOST_WARCHIVE_DECL(T) T __import
+            #else
+            #define BOOST_WARCHIVE_DECL(T) __declspec(dllimport) T
+            #endif
+        #endif
+        #if !defined(BOOST_WARCHIVE_SOURCE) && !defined(BOOST_ARCHIVE_SOURCE)
+            #if defined(__BORLANDC__)
+            #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T __import
+            #else
+            #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) __declspec(dllimport) T
+            #endif
+        #endif
+    #endif
+#endif // BOOST_HAS_DECLSPEC
+
+#if ! defined(BOOST_ARCHIVE_DECL)
+    #define BOOST_ARCHIVE_DECL(T) T
+#endif
+#if ! defined(BOOST_WARCHIVE_DECL)
+    #define BOOST_WARCHIVE_DECL(T) T
+#endif
+#if ! defined(BOOST_ARCHIVE_OR_WARCHIVE_DECL)
+    #define BOOST_ARCHIVE_OR_WARCHIVE_DECL(T) T
+#endif
+
+#endif // BOOST_ARCHIVE_DETAIL_DECL_HPP
diff --git a/SRC/Serialization/archive/detail/interface_iarchive.hpp b/SRC/Serialization/archive/detail/interface_iarchive.hpp
new file mode 100755
index 0000000..9f83faa
--- /dev/null
+++ b/SRC/Serialization/archive/detail/interface_iarchive.hpp
@@ -0,0 +1,77 @@
+#ifndef BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP
+#define BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// interface_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <cstddef> // NULL
+#include <boost/cstdint.hpp>
+#include <boost/mpl/bool.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/iserializer.hpp>
+#include <Serialization/singleton.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer;
+
+template<class Archive>
+class interface_iarchive 
+{
+protected:
+    interface_iarchive(){};
+public:
+    /////////////////////////////////////////////////////////
+    // archive public interface
+    typedef mpl::bool_<true> is_loading;
+    typedef mpl::bool_<false> is_saving;
+
+    // return a pointer to the most derived class
+    Archive * This(){
+        return static_cast<Archive *>(this);
+    }
+
+    template<class T>
+    const basic_pointer_iserializer * 
+    register_type(T * = NULL){
+        const basic_pointer_iserializer & bpis =
+            boost::serialization::singleton<
+                pointer_iserializer<Archive, T> 
+            >::get_const_instance();
+        this->This()->register_basic_serializer(bpis.get_basic_serializer());
+        return & bpis;
+    }
+    template<class T>
+    Archive & operator>>(T & t){
+        this->This()->load_override(t, 0);
+        return * this->This();
+    }
+
+    // the & operator 
+    template<class T>
+    Archive & operator&(T & t){
+        return *(this->This()) >> t;
+    }
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/detail/interface_oarchive.hpp b/SRC/Serialization/archive/detail/interface_oarchive.hpp
new file mode 100755
index 0000000..a80a89c
--- /dev/null
+++ b/SRC/Serialization/archive/detail/interface_oarchive.hpp
@@ -0,0 +1,84 @@
+#ifndef BOOST_ARCHIVE_DETAIL_INTERFACE_OARCHIVE_HPP
+#define BOOST_ARCHIVE_DETAIL_INTERFACE_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// interface_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <cstddef> // NULL
+#include <boost/cstdint.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/detail/oserializer.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#include <Serialization/singleton.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+class BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer;
+
+template<class Archive>
+class interface_oarchive 
+{
+protected:
+    interface_oarchive(){};
+public:
+    /////////////////////////////////////////////////////////
+    // archive public interface
+    typedef mpl::bool_<false> is_loading;
+    typedef mpl::bool_<true> is_saving;
+
+    // return a pointer to the most derived class
+    Archive * This(){
+        return static_cast<Archive *>(this);
+    }
+
+    template<class T>
+    const basic_pointer_oserializer * 
+    register_type(const T * = NULL){
+        const basic_pointer_oserializer & bpos =
+            boost::serialization::singleton<
+                pointer_oserializer<Archive, T>
+            >::get_const_instance();
+        this->This()->register_basic_serializer(bpos.get_basic_serializer());
+        return & bpos;
+    }
+
+    template<class T>
+    Archive & operator<<(T & t){
+        this->This()->save_override(t, 0);
+        return * this->This();
+    }
+    
+    // the & operator 
+    template<class T>
+    Archive & operator&(T & t){
+        #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+            return * this->This() << const_cast<const T &>(t);
+        #else
+            return * this->This() << t;
+        #endif
+    }
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_DETAIL_INTERFACE_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/detail/iserializer.hpp b/SRC/Serialization/archive/detail/iserializer.hpp
new file mode 100755
index 0000000..e522256
--- /dev/null
+++ b/SRC/Serialization/archive/detail/iserializer.hpp
@@ -0,0 +1,632 @@
+#ifndef BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
+#define BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#pragma inline_depth(511)
+#pragma inline_recursion(on)
+#endif
+
+#if defined(__MWERKS__)
+#pragma inline_depth(511)
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// iserializer.hpp: interface for serialization system.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <new>     // for placement new
+#include <memory>  // for auto_ptr
+#include <cstddef> // size_t, NULL
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <boost/static_assert.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/greater_equal.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
+    #include <Serialization/extended_type_info_typeid.hpp>   
+#endif
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/smart_cast.hpp>
+#include <Serialization/static_warning.hpp>
+
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_extent.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+
+#include <Serialization/assume_abstract.hpp>
+
+#define DONT_USE_HAS_NEW_OPERATOR (                    \
+    defined(__BORLANDC__)                              \
+    || defined(__IBMCPP__)                             \
+    || defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)     \
+    || defined(__SUNPRO_CC) && (__SUNPRO_CC < 0x590)   \
+)
+
+#if ! DONT_USE_HAS_NEW_OPERATOR
+#include <boost/type_traits/has_new_operator.hpp>
+#endif
+
+#include <Serialization/serialization.hpp>
+#include <Serialization/version.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/type_info_implementation.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/void_cast.hpp>
+#include <Serialization/array.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/singleton.hpp>
+#include <Serialization/wrapper.hpp>
+
+// the following is need only for dynamic cast of polymorphic pointers
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/archive/detail/basic_iarchive.hpp>
+#include <Serialization/archive/detail/basic_iserializer.hpp>
+#include <Serialization/archive/detail/basic_pointer_iserializer.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+#include <Serialization/archive/detail/check.hpp>
+
+namespace boost {
+
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+namespace archive {
+
+// an accessor to permit friend access to archives.  Needed because
+// some compilers don't handle friend templates completely
+class load_access {
+public:
+    template<class Archive, class T>
+    static void load_primitive(Archive &ar, T &t){
+        ar.load(t);
+    }
+};
+
+namespace detail {
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+template<class Archive, class T>
+class iserializer : public basic_iserializer
+{
+private:
+    virtual void destroy(/*const*/ void *address) const {
+        boost::serialization::access::destroy(static_cast<T *>(address));
+    }
+protected:
+    // protected constructor since it's always created by singleton
+    explicit iserializer() :
+        basic_iserializer(
+            boost::serialization::singleton<
+                BOOST_DEDUCED_TYPENAME 
+                boost::serialization::type_info_implementation< T >::type
+            >::get_const_instance()
+        )
+    {}
+public:
+    virtual BOOST_DLLEXPORT void load_object_data(
+        basic_iarchive & ar,
+        void *x, 
+        const unsigned int file_version
+    ) const BOOST_USED;
+    virtual bool class_info() const {
+        return boost::serialization::implementation_level< T >::value 
+            >= boost::serialization::object_class_info;
+    }
+    virtual bool tracking(const unsigned int /* flags */) const {
+        return boost::serialization::tracking_level< T >::value 
+                == boost::serialization::track_always
+            || ( boost::serialization::tracking_level< T >::value 
+                == boost::serialization::track_selectively
+                && serialized_as_pointer());
+    }
+    virtual version_type version() const {
+        return version_type(::boost::serialization::version< T >::value);
+    }
+    virtual bool is_polymorphic() const {
+        return boost::is_polymorphic< T >::value;
+    }
+    virtual ~iserializer(){};
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+template<class Archive, class T>
+BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data(
+    basic_iarchive & ar,
+    void *x, 
+    const unsigned int file_version
+) const {
+    // note: we now comment this out. Before we permited archive
+    // version # to be very large.  Now we don't.  To permit
+    // readers of these old archives, we have to suppress this 
+    // code.  Perhaps in the future we might re-enable it but
+    // permit its suppression with a runtime switch.
+    #if 0
+    // trap case where the program cannot handle the current version
+    if(file_version > static_cast<const unsigned int>(version()))
+        boost::serialization::throw_exception(
+            archive::archive_exception(
+                boost::archive::archive_exception::unsupported_class_version,
+                get_debug_info()
+            )
+        );
+    #endif
+    // make sure call is routed through the higest interface that might
+    // be specialized by the user.
+    boost::serialization::serialize_adl(
+        boost::serialization::smart_cast_reference<Archive &>(ar),
+        * static_cast<T *>(x), 
+        file_version
+    );
+}
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+template<class Archive, class T>
+class pointer_iserializer :
+    public basic_pointer_iserializer
+{
+private:
+    virtual const basic_iserializer & get_basic_serializer() const {
+        return boost::serialization::singleton<
+            iserializer<Archive, T>
+        >::get_const_instance();
+    }
+    BOOST_DLLEXPORT virtual void load_object_ptr(
+        basic_iarchive & ar, 
+        void * & x,
+        const unsigned int file_version
+    ) const BOOST_USED;
+protected:
+    // this should alway be a singleton so make the constructor protected
+    pointer_iserializer();
+    ~pointer_iserializer();
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+// note trick to be sure that operator new is using class specific
+// version if such exists. Due to Peter Dimov.
+// note: the following fails if T has no default constructor.
+// otherwise it would have been ideal
+//struct heap_allocator : public T 
+//{
+//    T * invoke(){
+//        return ::new(sizeof(T));
+//    }
+//}
+
+template<class T>
+struct heap_allocator
+{
+    // boost::has_new_operator< T > doesn't work on these compilers
+    #if DONT_USE_HAS_NEW_OPERATOR
+        // This doesn't handle operator new overload for class T
+        static T * invoke(){
+            return static_cast<T *>(operator new(sizeof(T)));
+        }
+    #else
+        struct has_new_operator {
+            static T* invoke() {
+                return static_cast<T *>((T::operator new)(sizeof(T)));
+            }
+        };
+        struct doesnt_have_new_operator {
+            static T* invoke() {
+                return static_cast<T *>(operator new(sizeof(T)));
+            }
+        };
+        static T * invoke() {
+            typedef BOOST_DEDUCED_TYPENAME
+                mpl::eval_if<
+                    boost::has_new_operator< T >,
+                    mpl::identity<has_new_operator >,
+                    mpl::identity<doesnt_have_new_operator >    
+                >::type typex;
+            return typex::invoke();
+        }
+    #endif
+};
+
+// due to Martin Ecker
+template <typename T>
+class auto_ptr_with_deleter
+{
+public:
+    explicit auto_ptr_with_deleter(T* p) :
+        m_p(p)
+    {}
+    ~auto_ptr_with_deleter(){
+        if (m_p)
+            boost::serialization::access::destroy(m_p);
+    }
+    T* get() const {
+        return m_p;
+    }
+
+    T* release() {
+        T* p = m_p;
+        m_p = NULL;
+        return p;
+    }
+private:
+    T* m_p;
+};
+
+// note: BOOST_DLLEXPORT is so that code for polymorphic class
+// serialized only through base class won't get optimized out
+template<class Archive, class T>
+BOOST_DLLEXPORT void pointer_iserializer<Archive, T>::load_object_ptr(
+    basic_iarchive & ar, 
+    void * & x,
+    const unsigned int file_version
+) const
+{
+    Archive & ar_impl = 
+        boost::serialization::smart_cast_reference<Archive &>(ar);
+
+    auto_ptr_with_deleter< T > ap(heap_allocator< T >::invoke());
+    if(NULL == ap.get())
+        boost::serialization::throw_exception(std::bad_alloc()) ;
+
+    T * t = ap.get();
+    x = t;
+
+    // catch exception during load_construct_data so that we don't
+    // automatically delete the t which is most likely not fully
+    // constructed
+    BOOST_TRY {
+        // this addresses an obscure situtation that occurs when 
+        // load_constructor de-serializes something through a pointer.
+        ar.next_object_pointer(t);
+        boost::serialization::load_construct_data_adl<Archive, T>(
+            ar_impl,
+            t, 
+            file_version
+        );
+    }
+    BOOST_CATCH(...){
+        ap.release();
+        BOOST_RETHROW;
+    }
+    BOOST_CATCH_END
+
+    ar_impl >> boost::serialization::make_nvp(NULL, * t);
+    ap.release();
+}
+
+template<class Archive, class T>
+pointer_iserializer<Archive, T>::pointer_iserializer() :
+    basic_pointer_iserializer(
+        boost::serialization::singleton<
+            BOOST_DEDUCED_TYPENAME 
+            boost::serialization::type_info_implementation< T >::type
+        >::get_const_instance()
+    )
+{
+    boost::serialization::singleton<
+        iserializer<Archive, T>
+    >::get_mutable_instance().set_bpis(this);
+    archive_serializer_map<Archive>::insert(this);
+}
+
+template<class Archive, class T>
+pointer_iserializer<Archive, T>::~pointer_iserializer(){
+    archive_serializer_map<Archive>::erase(this);
+}
+
+template<class Archive>
+struct load_non_pointer_type {
+    // note this bounces the call right back to the archive
+    // with no runtime overhead
+    struct load_primitive {
+        template<class T>
+        static void invoke(Archive & ar, T & t){
+            load_access::load_primitive(ar, t);
+        }
+    };
+    // note this bounces the call right back to the archive
+    // with no runtime overhead
+    struct load_only {
+        template<class T>
+        static void invoke(Archive & ar, const T & t){
+            // short cut to user's serializer
+            // make sure call is routed through the higest interface that might
+            // be specialized by the user.
+            boost::serialization::serialize_adl(
+                ar, 
+                const_cast<T &>(t), 
+                boost::serialization::version< T >::value
+            );
+        }
+    };
+
+    // note this save class information including version
+    // and serialization level to the archive
+    struct load_standard {
+        template<class T>
+        static void invoke(Archive &ar, const T & t){
+            void * x = & const_cast<T &>(t);
+            ar.load_object(
+                x, 
+                boost::serialization::singleton<
+                    iserializer<Archive, T>
+                >::get_const_instance()
+            );
+        }
+    };
+
+    struct load_conditional {
+        template<class T>
+        static void invoke(Archive &ar, T &t){
+            //if(0 == (ar.get_flags() & no_tracking))
+                load_standard::invoke(ar, t);
+            //else
+            //    load_only::invoke(ar, t);
+        }
+    };
+
+    template<class T>
+    static void invoke(Archive & ar, T &t){
+        typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                // if its primitive
+                mpl::equal_to<
+                    boost::serialization::implementation_level< T >,
+                    mpl::int_<boost::serialization::primitive_type>
+                >,
+                mpl::identity<load_primitive>,
+            // else
+            BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            // class info / version
+            mpl::greater_equal<
+                        boost::serialization::implementation_level< T >,
+                        mpl::int_<boost::serialization::object_class_info>
+                    >,
+            // do standard load
+            mpl::identity<load_standard>,
+        // else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            // no tracking
+                    mpl::equal_to<
+                        boost::serialization::tracking_level< T >,
+                        mpl::int_<boost::serialization::track_never>
+                >,
+                // do a fast load
+                mpl::identity<load_only>,
+            // else
+            // do a fast load only tracking is turned off
+            mpl::identity<load_conditional>
+        > > >::type typex;
+        check_object_versioning< T >();
+        check_object_level< T >();
+        typex::invoke(ar, t);
+    }
+};
+
+template<class Archive>
+struct load_pointer_type {
+    struct abstract
+    {
+        template<class T>
+        static const basic_pointer_iserializer * register_type(Archive & /* ar */){
+            // it has? to be polymorphic
+            BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
+            return static_cast<basic_pointer_iserializer *>(NULL);
+         }
+    };
+
+    struct non_abstract
+    {
+        template<class T>
+        static const basic_pointer_iserializer * register_type(Archive & ar){
+            return ar.register_type(static_cast<T *>(NULL));
+        }
+    };
+
+    template<class T>
+    static const basic_pointer_iserializer * register_type(Archive &ar, const T & /*t*/){
+        // there should never be any need to load an abstract polymorphic 
+        // class pointer.  Inhibiting code generation for this
+        // permits abstract base classes to be used - note: exception
+        // virtual serialize functions used for plug-ins
+        typedef BOOST_DEDUCED_TYPENAME
+            mpl::eval_if<
+                boost::serialization::is_abstract<const T>,
+                boost::mpl::identity<abstract>,
+                boost::mpl::identity<non_abstract>  
+            >::type typex;
+        return typex::template register_type< T >(ar);
+    }
+
+    template<class T>
+    static T * pointer_tweak(
+        const boost::serialization::extended_type_info & eti,
+        void const * const t,
+        const T &
+    ) {
+        // tweak the pointer back to the base class
+        return static_cast<T *>(
+            const_cast<void *>(
+                boost::serialization::void_upcast(
+                    eti,
+                    boost::serialization::singleton<
+                        BOOST_DEDUCED_TYPENAME 
+                        boost::serialization::type_info_implementation< T >::type
+                    >::get_const_instance(),
+                    t
+                )
+            )
+        );
+    }
+
+    template<class T>
+    static void check_load(T & /* t */){
+        check_pointer_level< T >();
+        check_pointer_tracking< T >();
+    }
+
+    static const basic_pointer_iserializer *
+    find(const boost::serialization::extended_type_info & type){
+        return static_cast<const basic_pointer_iserializer *>(
+            archive_serializer_map<Archive>::find(type)
+        );
+    }
+
+    template<class Tptr>
+    static void invoke(Archive & ar, Tptr & t){
+        check_load(*t);
+        const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t);
+        const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
+            // note major hack here !!!
+            // I tried every way to convert Tptr &t (where Tptr might
+            // include const) to void * &.  This is the only way
+            // I could make it work. RR
+            (void * & )t,
+            bpis_ptr,
+            find
+        );
+        // if the pointer isn't that of the base class
+        if(newbpis_ptr != bpis_ptr){
+            t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
+        }
+    }
+};
+
+template<class Archive>
+struct load_enum_type {
+    template<class T>
+    static void invoke(Archive &ar, T &t){
+        // convert integers to correct enum to load
+        int i;
+        ar >> boost::serialization::make_nvp(NULL, i);
+        t = static_cast< T >(i);
+    }
+};
+
+template<class Archive>
+struct load_array_type {
+    template<class T>
+    static void invoke(Archive &ar, T &t){
+        typedef BOOST_DEDUCED_TYPENAME remove_extent< T >::type value_type;
+        
+        // convert integers to correct enum to load
+        // determine number of elements in the array. Consider the
+        // fact that some machines will align elements on boundries
+        // other than characters.
+        std::size_t current_count = sizeof(t) / (
+            static_cast<char *>(static_cast<void *>(&t[1])) 
+            - static_cast<char *>(static_cast<void *>(&t[0]))
+        );
+        boost::serialization::collection_size_type count;
+        ar >> BOOST_SERIALIZATION_NVP(count);
+        if(static_cast<std::size_t>(count) > current_count)
+            boost::serialization::throw_exception(
+                archive::archive_exception(
+                    boost::archive::archive_exception::array_size_too_short
+                )
+            );
+        ar >> serialization::make_array(static_cast<value_type*>(&t[0]),count);
+    }
+};
+
+} // detail
+
+template<class Archive, class T>
+inline void load(Archive & ar, T &t){
+    // if this assertion trips. It means we're trying to load a
+    // const object with a compiler that doesn't have correct
+    // funtion template ordering.  On other compilers, this is
+    // handled below.
+    detail::check_const_loading< T >();
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >,
+            mpl::identity<detail::load_pointer_type<Archive> >
+        ,//else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >,
+            mpl::identity<detail::load_array_type<Archive> >
+        ,//else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >,
+            mpl::identity<detail::load_enum_type<Archive> >
+        ,//else
+            mpl::identity<detail::load_non_pointer_type<Archive> >
+        >
+        >
+        >::type typex;
+    typex::invoke(ar, t);
+}
+
+#if 0
+
+// BORLAND
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560))
+// borland has a couple of problems
+// a) if function is partially specialized - see below
+// const paramters are transformed to non-const ones
+// b) implementation of base_object can't be made to work
+// correctly which results in all base_object s being const.
+// So, strip off the const for borland.  This breaks the trap
+// for loading const objects - but I see no alternative
+template<class Archive, class T>
+inline void load(Archive &ar, const T & t){
+    load(ar, const_cast<T &>(t));
+}
+#endif
+
+// let wrappers through.
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+template<class Archive, class T>
+inline void load_wrapper(Archive &ar, const T&t, mpl::true_){
+    boost::archive::load(ar, const_cast<T&>(t));
+}
+
+#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560))
+template<class Archive, class T>
+inline void load(Archive &ar, const T&t){
+  load_wrapper(ar,t,serialization::is_wrapper< T >());
+}
+#endif 
+#endif
+
+#endif
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_DETAIL_ISERIALIZER_HPP
diff --git a/SRC/Serialization/archive/detail/oserializer.hpp b/SRC/Serialization/archive/detail/oserializer.hpp
new file mode 100755
index 0000000..045784b
--- /dev/null
+++ b/SRC/Serialization/archive/detail/oserializer.hpp
@@ -0,0 +1,531 @@
+#ifndef BOOST_ARCHIVE_OSERIALIZER_HPP
+#define BOOST_ARCHIVE_OSERIALIZER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#pragma inline_depth(511)
+#pragma inline_recursion(on)
+#endif
+
+#if defined(__MWERKS__)
+#pragma inline_depth(511)
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// oserializer.hpp: interface for serialization system.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <cstddef> // NULL
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/greater_equal.hpp>
+#include <boost/mpl/identity.hpp>
+
+#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO   
+    #include <Serialization/extended_type_info_typeid.hpp>   
+#endif
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/smart_cast.hpp>
+#include <Serialization/assume_abstract.hpp>
+#include <Serialization/static_warning.hpp>
+
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/type_traits/remove_extent.hpp>
+
+#include <Serialization/serialization.hpp>
+#include <Serialization/version.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/type_info_implementation.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/void_cast.hpp>
+#include <Serialization/array.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/singleton.hpp>
+
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/archive/detail/basic_oarchive.hpp>
+#include <Serialization/archive/detail/basic_oserializer.hpp>
+#include <Serialization/archive/detail/basic_pointer_oserializer.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+#include <Serialization/archive/detail/check.hpp>
+
+namespace boost {
+
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+
+namespace archive {
+
+// an accessor to permit friend access to archives.  Needed because
+// some compilers don't handle friend templates completely
+class save_access {
+public:
+    template<class Archive>
+    static void end_preamble(Archive & ar){
+        ar.end_preamble();
+    }
+    template<class Archive, class T>
+    static void save_primitive(Archive & ar, const  T & t){
+        ar.end_preamble();
+        ar.save(t);
+    }
+};
+
+namespace detail {
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+template<class Archive, class T>
+class oserializer : public basic_oserializer
+{
+private:
+    // private constructor to inhibit any existence other than the 
+    // static one
+public:
+    explicit BOOST_DLLEXPORT oserializer() :
+        basic_oserializer(
+            boost::serialization::singleton<
+                BOOST_DEDUCED_TYPENAME 
+                boost::serialization::type_info_implementation< T >::type
+            >::get_const_instance()
+        )
+    {}
+    virtual BOOST_DLLEXPORT void save_object_data(
+        basic_oarchive & ar,    
+        const void *x
+    ) const BOOST_USED;
+    virtual bool class_info() const {
+        return boost::serialization::implementation_level< T >::value 
+            >= boost::serialization::object_class_info;
+    }
+    virtual bool tracking(const unsigned int /* flags */) const {
+        return boost::serialization::tracking_level< T >::value == boost::serialization::track_always
+            || (boost::serialization::tracking_level< T >::value == boost::serialization::track_selectively
+                && serialized_as_pointer());
+    }
+    virtual version_type version() const {
+        return version_type(::boost::serialization::version< T >::value);
+    }
+    virtual bool is_polymorphic() const {
+        return boost::is_polymorphic< T >::value;
+    }
+    virtual ~oserializer(){}
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+template<class Archive, class T>
+BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
+    basic_oarchive & ar,    
+    const void *x
+) const {
+    // make sure call is routed through the highest interface that might
+    // be specialized by the user.
+    BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
+    boost::serialization::serialize_adl(
+        boost::serialization::smart_cast_reference<Archive &>(ar),
+        * static_cast<T *>(const_cast<void *>(x)),
+        version()
+    );
+}
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+template<class Archive, class T>
+class pointer_oserializer :
+    public basic_pointer_oserializer
+{
+private:
+    const basic_oserializer & 
+    get_basic_serializer() const {
+        return boost::serialization::singleton<
+            oserializer<Archive, T>
+        >::get_const_instance();
+    }
+    virtual BOOST_DLLEXPORT void save_object_ptr(
+        basic_oarchive & ar,
+        const void * x
+    ) const BOOST_USED;
+public:
+    pointer_oserializer();
+    ~pointer_oserializer();
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+template<class Archive, class T>
+BOOST_DLLEXPORT void pointer_oserializer<Archive, T>::save_object_ptr(
+    basic_oarchive & ar,
+    const void * x
+) const {
+    BOOST_ASSERT(NULL != x);
+    // make sure call is routed through the highest interface that might
+    // be specialized by the user.
+    T * t = static_cast<T *>(const_cast<void *>(x));
+    const unsigned int file_version = boost::serialization::version< T >::value;
+    Archive & ar_impl 
+        = boost::serialization::smart_cast_reference<Archive &>(ar);
+    boost::serialization::save_construct_data_adl<Archive, T>(
+        ar_impl, 
+        t, 
+        file_version
+    );
+    ar_impl << boost::serialization::make_nvp(NULL, * t);
+}
+
+template<class Archive, class T>
+pointer_oserializer<Archive, T>::pointer_oserializer() :
+    basic_pointer_oserializer(
+        boost::serialization::singleton<
+            BOOST_DEDUCED_TYPENAME 
+            boost::serialization::type_info_implementation< T >::type
+        >::get_const_instance()
+    )
+{
+    // make sure appropriate member function is instantiated
+    boost::serialization::singleton<
+        oserializer<Archive, T> 
+    >::get_mutable_instance().set_bpos(this);
+    archive_serializer_map<Archive>::insert(this);
+}
+
+template<class Archive, class T>
+pointer_oserializer<Archive, T>::~pointer_oserializer(){
+    archive_serializer_map<Archive>::erase(this);
+}
+
+template<class Archive>
+struct save_non_pointer_type {
+    // note this bounces the call right back to the archive
+    // with no runtime overhead
+    struct save_primitive {
+        template<class T>
+        static void invoke(Archive & ar, const T & t){
+            save_access::save_primitive(ar, t);
+        }
+    };
+    // same as above but passes through serialization
+    struct save_only {
+        template<class T>
+        static void invoke(Archive & ar, const T & t){
+            // make sure call is routed through the highest interface that might
+            // be specialized by the user.
+            boost::serialization::serialize_adl(
+                ar, 
+                const_cast<T &>(t), 
+                ::boost::serialization::version< T >::value
+            );
+        }
+    };
+    // adds class information to the archive. This includes
+    // serialization level and class version
+    struct save_standard {
+        template<class T>
+        static void invoke(Archive &ar, const T & t){
+            ar.save_object(
+                & t, 
+                boost::serialization::singleton<
+                    oserializer<Archive, T>
+                >::get_const_instance()
+            );
+        }
+    };
+
+    // adds class information to the archive. This includes
+    // serialization level and class version
+    struct save_conditional {
+        template<class T>
+        static void invoke(Archive &ar, const T &t){
+            //if(0 == (ar.get_flags() & no_tracking))
+                save_standard::invoke(ar, t);
+            //else
+            //   save_only::invoke(ar, t);
+        }
+    };
+
+
+    template<class T>
+    static void invoke(Archive & ar, const T & t){
+        typedef 
+            BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            // if its primitive
+                mpl::equal_to<
+                    boost::serialization::implementation_level< T >,
+                    mpl::int_<boost::serialization::primitive_type>
+                >,
+                mpl::identity<save_primitive>,
+            // else
+            BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                // class info / version
+                mpl::greater_equal<
+                    boost::serialization::implementation_level< T >,
+                    mpl::int_<boost::serialization::object_class_info>
+                >,
+                // do standard save
+                mpl::identity<save_standard>,
+            // else
+            BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                    // no tracking
+                mpl::equal_to<
+                    boost::serialization::tracking_level< T >,
+                    mpl::int_<boost::serialization::track_never>
+                >,
+                // do a fast save
+                mpl::identity<save_only>,
+            // else
+                // do a fast save only tracking is turned off
+                mpl::identity<save_conditional>
+            > > >::type typex; 
+        check_object_versioning< T >();
+        typex::invoke(ar, t);
+    }
+    template<class T>
+    static void invoke(Archive & ar, T & t){
+        check_object_level< T >();
+        check_object_tracking< T >();
+        invoke(ar, const_cast<const T &>(t));
+    }
+};
+
+template<class Archive>
+struct save_pointer_type {
+    struct abstract
+    {
+        template<class T>
+        static const basic_pointer_oserializer * register_type(Archive & /* ar */){
+            // it has? to be polymorphic
+            BOOST_STATIC_ASSERT(boost::is_polymorphic< T >::value);
+            return NULL;
+        }
+    };
+
+    struct non_abstract
+    {
+        template<class T>
+        static const basic_pointer_oserializer * register_type(Archive & ar){
+            return ar.register_type(static_cast<T *>(NULL));
+        }
+    };
+
+    template<class T>
+    static const basic_pointer_oserializer * register_type(Archive &ar, T & /*t*/){
+        // there should never be any need to save an abstract polymorphic 
+        // class pointer.  Inhibiting code generation for this
+        // permits abstract base classes to be used - note: exception
+        // virtual serialize functions used for plug-ins
+        typedef 
+            BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                boost::serialization::is_abstract< T >,
+                mpl::identity<abstract>,
+                mpl::identity<non_abstract>       
+            >::type typex;
+        return typex::template register_type< T >(ar);
+    }
+
+    struct non_polymorphic
+    {
+        template<class T>
+        static void save(
+            Archive &ar, 
+            T & t
+        ){
+            const basic_pointer_oserializer & bpos = 
+                boost::serialization::singleton<
+                    pointer_oserializer<Archive, T>
+                >::get_const_instance();
+            // save the requested pointer type
+            ar.save_pointer(& t, & bpos);
+        }
+    };
+
+    struct polymorphic
+    {
+        template<class T>
+        static void save(
+            Archive &ar, 
+            T & t
+        ){
+            BOOST_DEDUCED_TYPENAME 
+            boost::serialization::type_info_implementation< T >::type const
+            & i = boost::serialization::singleton<
+                BOOST_DEDUCED_TYPENAME 
+                boost::serialization::type_info_implementation< T >::type
+            >::get_const_instance();
+
+            boost::serialization::extended_type_info const * const this_type = & i;
+
+            // retrieve the true type of the object pointed to
+            // if this assertion fails its an error in this library
+            BOOST_ASSERT(NULL != this_type);
+
+            const boost::serialization::extended_type_info * true_type =
+                i.get_derived_extended_type_info(t);
+
+            // note:if this exception is thrown, be sure that derived pointer
+            // is either registered or exported.
+            if(NULL == true_type){
+                boost::serialization::throw_exception(
+                    archive_exception(
+                        archive_exception::unregistered_class,
+                        "derived class not registered or exported"
+                    )
+                );
+            }
+
+            // if its not a pointer to a more derived type
+            const void *vp = static_cast<const void *>(&t);
+            if(*this_type == *true_type){
+                const basic_pointer_oserializer * bpos = register_type(ar, t);
+                ar.save_pointer(vp, bpos);
+                return;
+            }
+            // convert pointer to more derived type. if this is thrown
+            // it means that the base/derived relationship hasn't be registered
+            vp = serialization::void_downcast(
+                *true_type, 
+                *this_type, 
+                static_cast<const void *>(&t)
+            );
+            if(NULL == vp){
+                boost::serialization::throw_exception(
+                    archive_exception(
+                        archive_exception::unregistered_cast,
+                        true_type->get_debug_info(),
+                        this_type->get_debug_info()
+                    )
+                );
+            }
+
+            // since true_type is valid, and this only gets made if the 
+            // pointer oserializer object has been created, this should never
+            // fail
+            const basic_pointer_oserializer * bpos
+                = static_cast<const basic_pointer_oserializer *>(
+                    boost::serialization::singleton<
+                        archive_serializer_map<Archive>
+                    >::get_const_instance().find(*true_type)
+                );
+            BOOST_ASSERT(NULL != bpos);
+            if(NULL == bpos)
+                boost::serialization::throw_exception(
+                    archive_exception(
+                        archive_exception::unregistered_class,
+                        "derived class not registered or exported"
+                    )
+                );
+            ar.save_pointer(vp, bpos);
+        }
+    };
+
+    template<class T>
+    static void save(
+        Archive & ar, 
+        const T & t
+    ){
+        check_pointer_level< T >();
+        check_pointer_tracking< T >();
+        typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_polymorphic< T >,
+            mpl::identity<polymorphic>,
+            mpl::identity<non_polymorphic>
+        >::type type;
+        type::save(ar, const_cast<T &>(t));
+    }
+
+    template<class TPtr>
+    static void invoke(Archive &ar, const TPtr t){
+        register_type(ar, * t);
+        if(NULL == t){
+            basic_oarchive & boa 
+                = boost::serialization::smart_cast_reference<basic_oarchive &>(ar);
+            boa.save_null_pointer();
+            save_access::end_preamble(ar);
+            return;
+        }
+        save(ar, * t);
+    }
+};
+
+template<class Archive>
+struct save_enum_type
+{
+    template<class T>
+    static void invoke(Archive &ar, const T &t){
+        // convert enum to integers on save
+        const int i = static_cast<int>(t);
+        ar << boost::serialization::make_nvp(NULL, i);
+    }
+};
+
+template<class Archive>
+struct save_array_type
+{
+    template<class T>
+    static void invoke(Archive &ar, const T &t){
+        typedef BOOST_DEDUCED_TYPENAME boost::remove_extent< T >::type value_type;
+        
+        save_access::end_preamble(ar);
+        // consider alignment
+        std::size_t c = sizeof(t) / (
+            static_cast<const char *>(static_cast<const void *>(&t[1])) 
+            - static_cast<const char *>(static_cast<const void *>(&t[0]))
+        );
+        boost::serialization::collection_size_type count(c);
+        ar << BOOST_SERIALIZATION_NVP(count);
+        ar << serialization::make_array(static_cast<value_type const*>(&t[0]),count);
+    }
+};
+
+} // detail
+
+template<class Archive, class T>
+inline void save(Archive & ar, /*const*/ T &t){
+    typedef 
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_pointer< T >,
+            mpl::identity<detail::save_pointer_type<Archive> >,
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_enum< T >,
+            mpl::identity<detail::save_enum_type<Archive> >,
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<is_array< T >,
+            mpl::identity<detail::save_array_type<Archive> >,
+        //else
+            mpl::identity<detail::save_non_pointer_type<Archive> >
+        >
+        >
+        >::type typex;
+    typex::invoke(ar, t);
+}
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_OSERIALIZER_HPP
diff --git a/SRC/Serialization/archive/detail/polymorphic_iarchive_route.hpp b/SRC/Serialization/archive/detail/polymorphic_iarchive_route.hpp
new file mode 100755
index 0000000..e6aa1be
--- /dev/null
+++ b/SRC/Serialization/archive/detail/polymorphic_iarchive_route.hpp
@@ -0,0 +1,215 @@
+#ifndef BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_ROUTE_HPP
+#define BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_ROUTE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_iarchive_route.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <string>
+#include <ostream>
+#include <cstddef>
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+    using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/cstdint.hpp>
+#include <boost/integer_traits.hpp>
+#include <Serialization/archive/polymorphic_iarchive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+namespace archive {
+namespace detail{
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iserializer;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_iserializer;
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+template<class ArchiveImplementation>
+class polymorphic_iarchive_route :
+    public polymorphic_iarchive,
+    // note: gcc dynamic cross cast fails if the the derivation below is
+    // not public.  I think this is a mistake.
+    public /*protected*/ ArchiveImplementation
+{
+private:
+    // these are used by the serialization library.
+    virtual void load_object(
+        void *t,
+        const basic_iserializer & bis
+    ){
+        ArchiveImplementation::load_object(t, bis);
+    }
+    virtual const basic_pointer_iserializer * load_pointer(
+        void * & t,
+        const basic_pointer_iserializer * bpis_ptr,
+        const basic_pointer_iserializer * (*finder)(
+            const boost::serialization::extended_type_info & type
+        )
+    ){
+        return ArchiveImplementation::load_pointer(t, bpis_ptr, finder);
+    }
+    virtual void set_library_version(library_version_type archive_library_version){
+        ArchiveImplementation::set_library_version(archive_library_version);
+    }
+    virtual library_version_type get_library_version() const{
+        return ArchiveImplementation::get_library_version();
+    }
+    virtual unsigned int get_flags() const {
+        return ArchiveImplementation::get_flags();
+    }
+    virtual void delete_created_pointers(){
+        ArchiveImplementation::delete_created_pointers();
+    }
+    virtual void reset_object_address(
+        const void * new_address,
+        const void * old_address
+    ){
+        ArchiveImplementation::reset_object_address(new_address, old_address);
+    }
+    virtual void load_binary(void * t, std::size_t size){
+        ArchiveImplementation::load_binary(t, size);
+    }
+    // primitive types the only ones permitted by polymorphic archives
+    virtual void load(bool & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(char & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(signed char & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(unsigned char & t){
+        ArchiveImplementation::load(t);
+    }
+    #ifndef BOOST_NO_CWCHAR
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    virtual void load(wchar_t & t){
+        ArchiveImplementation::load(t);
+    }
+    #endif
+    #endif
+    virtual void load(short & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(unsigned short & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(int & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(unsigned int & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(long & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(unsigned long & t){
+        ArchiveImplementation::load(t);
+    }
+    #if defined(BOOST_HAS_LONG_LONG)
+    virtual void load(boost::long_long_type & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(boost::ulong_long_type & t){
+        ArchiveImplementation::load(t);
+    }
+    #elif defined(BOOST_HAS_MS_INT64)
+    virtual void load(__int64 & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(unsigned __int64 & t){
+        ArchiveImplementation::load(t);
+    }
+    #endif
+    virtual void load(float & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(double & t){
+        ArchiveImplementation::load(t);
+    }
+    virtual void load(std::string & t){
+        ArchiveImplementation::load(t);
+    }
+    #ifndef BOOST_NO_STD_WSTRING
+    virtual void load(std::wstring & t){
+        ArchiveImplementation::load(t);
+    }
+    #endif
+    // used for xml and other tagged formats default does nothing
+    virtual void load_start(const char * name){
+        ArchiveImplementation::load_start(name);
+    }
+    virtual void load_end(const char * name){
+        ArchiveImplementation::load_end(name);
+    }
+
+    virtual void register_basic_serializer(const basic_iserializer & bis){
+        ArchiveImplementation::register_basic_serializer(bis);
+    }
+public:
+    // this can't be inheriteded because they appear in mulitple
+    // parents
+    typedef mpl::bool_<true> is_loading;
+    typedef mpl::bool_<false> is_saving;
+    // the >> operator
+    template<class T>
+    polymorphic_iarchive & operator>>(T & t){
+        return polymorphic_iarchive::operator>>(t);
+    }
+    // the & operator
+    template<class T>
+    polymorphic_iarchive & operator&(T & t){
+        return polymorphic_iarchive::operator&(t);
+    }
+    // register type function
+    template<class T>
+    const basic_pointer_iserializer * 
+    register_type(T * t = NULL){
+        return ArchiveImplementation::register_type(t);
+    }
+    // all current archives take a stream as constructor argument
+    template <class _Elem, class _Tr>
+    polymorphic_iarchive_route(
+        std::basic_istream<_Elem, _Tr> & is,
+        unsigned int flags = 0
+    ) :
+        ArchiveImplementation(is, flags)
+    {}
+    virtual ~polymorphic_iarchive_route(){};
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_DETAIL_POLYMORPHIC_IARCHIVE_DISPATCH_HPP
diff --git a/SRC/Serialization/archive/detail/polymorphic_oarchive_route.hpp b/SRC/Serialization/archive/detail/polymorphic_oarchive_route.hpp
new file mode 100755
index 0000000..530ec0b
--- /dev/null
+++ b/SRC/Serialization/archive/detail/polymorphic_oarchive_route.hpp
@@ -0,0 +1,205 @@
+#ifndef BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_ROUTE_HPP
+#define BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_ROUTE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_oarchive_route.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <string>
+#include <ostream>
+#include <cstddef> // size_t
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+    using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/cstdint.hpp>
+#include <boost/integer_traits.hpp>
+#include <Serialization/archive/polymorphic_oarchive.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+namespace archive {
+namespace detail{
+
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer;
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_pointer_oserializer;
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+template<class ArchiveImplementation>
+class polymorphic_oarchive_route :
+    public polymorphic_oarchive,
+    // note: gcc dynamic cross cast fails if the the derivation below is
+    // not public.  I think this is a mistake.
+    public /*protected*/ ArchiveImplementation
+{
+private:
+    // these are used by the serialization library.
+    virtual void save_object(
+        const void *x,
+        const detail::basic_oserializer & bos
+    ){
+        ArchiveImplementation::save_object(x, bos);
+    }
+    virtual void save_pointer(
+        const void * t,
+        const detail::basic_pointer_oserializer * bpos_ptr
+    ){
+        ArchiveImplementation::save_pointer(t, bpos_ptr);
+    }
+    virtual void save_null_pointer(){
+        ArchiveImplementation::save_null_pointer();
+    }
+    // primitive types the only ones permitted by polymorphic archives
+    virtual void save(const bool t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const char t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const signed char t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const unsigned char t){
+        ArchiveImplementation::save(t);
+    }
+    #ifndef BOOST_NO_CWCHAR
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    virtual void save(const wchar_t t){
+        ArchiveImplementation::save(t);
+    }
+    #endif
+    #endif
+    virtual void save(const short t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const unsigned short t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const int t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const unsigned int t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const long t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const unsigned long t){
+        ArchiveImplementation::save(t);
+    }
+    #if defined(BOOST_HAS_LONG_LONG)
+    virtual void save(const boost::long_long_type t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const boost::ulong_long_type t){
+        ArchiveImplementation::save(t);
+    }
+    #elif defined(BOOST_HAS_MS_INT64)
+    virtual void save(const boost::int64_t t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const boost::uint64_t t){
+        ArchiveImplementation::save(t);
+    }
+    #endif
+    virtual void save(const float t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const double t){
+        ArchiveImplementation::save(t);
+    }
+    virtual void save(const std::string & t){
+        ArchiveImplementation::save(t);
+    }
+    #ifndef BOOST_NO_STD_WSTRING
+    virtual void save(const std::wstring & t){
+        ArchiveImplementation::save(t);
+    }
+    #endif
+    virtual library_version_type get_library_version() const{
+        return ArchiveImplementation::get_library_version();
+    }
+    virtual unsigned int get_flags() const {
+        return ArchiveImplementation::get_flags();
+    }
+    virtual void save_binary(const void * t, std::size_t size){
+        ArchiveImplementation::save_binary(t, size);
+    }
+    // used for xml and other tagged formats default does nothing
+    virtual void save_start(const char * name){
+        ArchiveImplementation::save_start(name);
+    }
+    virtual void save_end(const char * name){
+        ArchiveImplementation::save_end(name);
+    }
+    virtual void end_preamble(){
+        ArchiveImplementation::end_preamble();
+    }
+    virtual void register_basic_serializer(const detail::basic_oserializer & bos){
+        ArchiveImplementation::register_basic_serializer(bos);
+    }
+public:
+    // this can't be inheriteded because they appear in mulitple
+    // parents
+    typedef mpl::bool_<false> is_loading;
+    typedef mpl::bool_<true> is_saving;
+    // the << operator
+    template<class T>
+    polymorphic_oarchive & operator<<(T & t){
+        return polymorphic_oarchive::operator<<(t);
+    }
+    // the & operator
+    template<class T>
+    polymorphic_oarchive & operator&(T & t){
+        return polymorphic_oarchive::operator&(t);
+    }
+    // register type function
+    template<class T>
+    const basic_pointer_oserializer * 
+    register_type(T * t = NULL){
+        return ArchiveImplementation::register_type(t);
+    }
+    // all current archives take a stream as constructor argument
+    template <class _Elem, class _Tr>
+    polymorphic_oarchive_route(
+        std::basic_ostream<_Elem, _Tr> & os,
+        unsigned int flags = 0
+    ) :
+        ArchiveImplementation(os, flags)
+    {}
+    virtual ~polymorphic_oarchive_route(){};
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_DETAIL_POLYMORPHIC_OARCHIVE_DISPATCH_HPP
diff --git a/SRC/Serialization/archive/detail/register_archive.hpp b/SRC/Serialization/archive/detail/register_archive.hpp
new file mode 100755
index 0000000..ce6a5d1
--- /dev/null
+++ b/SRC/Serialization/archive/detail/register_archive.hpp
@@ -0,0 +1,91 @@
+// Copyright David Abrahams 2006. Distributed under the Boost
+// Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_ARCHIVE_DETAIL_REGISTER_ARCHIVE_DWA2006521_HPP
+# define BOOST_ARCHIVE_DETAIL_REGISTER_ARCHIVE_DWA2006521_HPP
+
+namespace boost { namespace archive { namespace detail { 
+
+// No instantiate_ptr_serialization overloads generated by
+// BOOST_SERIALIZATION_REGISTER_ARCHIVE that lexically follow the call
+// will be seen *unless* they are in an associated namespace of one of
+// the arguments, so we pass one of these along to make sure this
+// namespace is considered.  See temp.dep.candidate (14.6.4.2) in the
+// standard.
+struct adl_tag {};
+
+template <class Archive, class Serializable>
+struct ptr_serialization_support;
+
+// We could've just used ptr_serialization_support, above, but using
+// it with only a forward declaration causes vc6/7 to complain about a
+// missing instantiate member, even if it has one.  This is just a
+// friendly layer of indirection.
+template <class Archive, class Serializable>
+struct _ptr_serialization_support
+  : ptr_serialization_support<Archive,Serializable>
+{
+    typedef int type;
+};
+
+#ifdef __SUNPRO_CC
+
+template<int N>
+struct counter : counter<N-1> {};
+template<>
+struct counter<0> {};
+
+template<class Serializable>
+void instantiate_ptr_serialization(Serializable* s, int, adl_tag) {
+    instantiate_ptr_serialization(s, counter<20>());
+}
+
+template<class Archive>
+struct get_counter {
+    static const int value = sizeof(adjust_counter(counter<20>()));
+    typedef counter<value> type;
+    typedef counter<value - 1> prior;
+    typedef char (&next)[value+1];
+};
+
+char adjust_counter(counter<0>);
+template<class Serializable>
+void instantiate_ptr_serialization(Serializable*, counter<0>) {}
+
+#define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive)                     \
+namespace boost { namespace archive { namespace detail {                  \
+    get_counter<Archive >::next adjust_counter(get_counter<Archive >::type);\
+    template<class Serializable>                                          \
+    void instantiate_ptr_serialization(Serializable* s,                   \
+        get_counter<Archive >::type) {                                    \
+        ptr_serialization_support<Archive, Serializable> x;               \
+        instantiate_ptr_serialization(s, get_counter<Archive >::prior()); \
+    }\
+}}}
+
+
+#else
+
+// This function gets called, but its only purpose is to participate
+// in overload resolution with the functions declared by
+// BOOST_SERIALIZATION_REGISTER_ARCHIVE, below.
+template <class Serializable>
+void instantiate_ptr_serialization(Serializable*, int, adl_tag ) {}
+
+// The function declaration generated by this macro never actually
+// gets called, but its return type gets instantiated, and that's
+// enough to cause registration of serialization functions between
+// Archive and any exported Serializable type.  See also:
+// boost/serialization/export.hpp
+# define BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive)                  \
+namespace boost { namespace archive { namespace detail {                \
+                                                                        \
+template <class Serializable>                                           \
+BOOST_DEDUCED_TYPENAME _ptr_serialization_support<Archive, Serializable>::type  \
+instantiate_ptr_serialization( Serializable*, Archive*, adl_tag );              \
+                                                                        \
+}}}
+#endif
+}}} // namespace boost::archive::detail
+
+#endif // BOOST_ARCHIVE_DETAIL_INSTANTIATE_SERIALIZE_DWA2006521_HPP
diff --git a/SRC/Serialization/archive/detail/utf8_codecvt_facet.hpp b/SRC/Serialization/archive/detail/utf8_codecvt_facet.hpp
new file mode 100755
index 0000000..5718c3d
--- /dev/null
+++ b/SRC/Serialization/archive/detail/utf8_codecvt_facet.hpp
@@ -0,0 +1,21 @@
+// Copyright (c) 2001 Ronald Garcia, Indiana University (garcia at osl.iu.edu)
+// Andrew Lumsdaine, Indiana University (lums at osl.iu.edu).
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP
+#define BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP
+
+#define BOOST_UTF8_BEGIN_NAMESPACE \
+     namespace boost { namespace archive { namespace detail {
+#define BOOST_UTF8_DECL
+#define BOOST_UTF8_END_NAMESPACE }}}
+
+#include <boost/detail/utf8_codecvt_facet.hpp>
+
+#undef BOOST_UTF8_END_NAMESPACE
+#undef BOOST_UTF8_DECL
+#undef BOOST_UTF8_BEGIN_NAMESPACE
+
+#endif // BOOST_ARCHIVE_DETAIL_UTF8_CODECVT_FACET_HPP
diff --git a/SRC/Serialization/archive/dinkumware.hpp b/SRC/Serialization/archive/dinkumware.hpp
new file mode 100755
index 0000000..59afd69
--- /dev/null
+++ b/SRC/Serialization/archive/dinkumware.hpp
@@ -0,0 +1,224 @@
+#ifndef BOOST_ARCHIVE_DINKUMWARE_HPP
+#define BOOST_ARCHIVE_DINKUMWARE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// dinkumware.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// this file adds a couple of things that are missing from the dinkumware
+// implementation of the standard library.
+
+#include <iterator>
+#include <string>
+
+#include <boost/config.hpp>
+#include <boost/cstdint.hpp>
+
+namespace std {
+
+// define i/o operators for 64 bit integers
+template<class CharType>
+basic_ostream<CharType> & 
+operator<<(basic_ostream<CharType> & os, boost::uint64_t t){
+    // octal rendering of 64 bit number would be 22 octets + eos
+    CharType d[23];
+    unsigned int radix;
+
+    if(os.flags() & (int)std::ios_base::hex)
+        radix = 16;
+    else
+    if(os.flags() & (int)std::ios_base::oct)
+        radix = 8;
+    else
+    //if(s.flags() & (int)std::ios_base::dec)
+        radix =  10;
+    unsigned int i = 0;
+    do{
+        unsigned int j = t % radix;
+        d[i++] = j + ((j < 10) ? '0' : ('a' - 10));
+        t /= radix;
+    }
+    while(t > 0);
+    d[i--] = '\0';
+
+    // reverse digits
+    unsigned int j = 0;
+    while(j < i){
+        CharType k = d[i];
+        d[i] = d[j];
+        d[j] = k;
+        --i;++j;
+    }
+    os << d;
+    return os;
+
+}
+
+template<class CharType>
+basic_ostream<CharType> & 
+operator<<(basic_ostream<CharType> &os, boost::int64_t t){
+    if(0 <= t){
+        os << static_cast<boost::uint64_t>(t);
+    }
+    else{
+        os.put('-');
+        os << -t;
+    }
+    return os;
+}
+
+template<class CharType>
+basic_istream<CharType> & 
+operator>>(basic_istream<CharType> &is, boost::int64_t & t){
+    CharType d;
+    do{
+        d = is.get();
+    }
+    while(::isspace(d));
+    bool negative = (d == '-');
+    if(negative)
+        d = is.get();
+    unsigned int radix;
+    if(is.flags() & (int)std::ios_base::hex)
+        radix = 16;
+    else
+    if(is.flags() & (int)std::ios_base::oct)
+        radix = 8;
+    else
+    //if(s.flags() & (int)std::ios_base::dec)
+        radix =  10;
+    t = 0;
+    do{
+        if('0' <= d && d <= '9')
+            t = t * radix + (d - '0');
+        else
+        if('a' <= d && d <= 'f')
+            t = t * radix + (d - 'a' + 10);
+        else
+            break;
+        d = is.get();
+    }
+    while(!is.fail());
+    // restore the delimiter
+    is.putback(d);
+    is.clear();
+    if(negative)
+        t = -t;
+    return is;
+}
+
+template<class CharType>
+basic_istream<CharType> & 
+operator>>(basic_istream<CharType> &is, boost::uint64_t & t){
+    boost::int64_t it;
+    is >> it;
+    t = it;
+    return is;
+}
+
+//#endif
+
+template<>
+class back_insert_iterator<basic_string<char> > : public 
+    iterator<output_iterator_tag, char>
+{
+public:
+    typedef basic_string<char> container_type;
+    typedef container_type::reference reference;
+
+    explicit back_insert_iterator(container_type & s)
+        : container(& s)
+    {}    // construct with container
+    
+    back_insert_iterator<container_type> & operator=(
+        container_type::const_reference Val_
+    ){    // push value into container
+        //container->push_back(Val_);
+        *container += Val_;
+        return (*this);
+    }
+
+    back_insert_iterator<container_type> & operator*(){
+        return (*this);
+    }
+
+    back_insert_iterator<container_type> & operator++(){
+        // pretend to preincrement
+        return (*this);
+    }
+
+    back_insert_iterator<container_type> operator++(int){
+        // pretend to postincrement
+        return (*this);
+    }
+
+protected:
+    container_type *container;    // pointer to container
+};
+
+template<char> 
+inline back_insert_iterator<basic_string<char> > back_inserter(
+    basic_string<char> & s
+){
+    return (std::back_insert_iterator<basic_string<char> >(s));
+}
+
+template<>
+class back_insert_iterator<basic_string<wchar_t> > : public 
+    iterator<output_iterator_tag, wchar_t>
+{
+public:
+    typedef basic_string<wchar_t> container_type;
+    typedef container_type::reference reference;
+
+    explicit back_insert_iterator(container_type & s)
+        : container(& s)
+    {}    // construct with container
+    
+    back_insert_iterator<container_type> & operator=(
+        container_type::const_reference Val_
+    ){    // push value into container
+        //container->push_back(Val_);
+        *container += Val_;
+        return (*this);
+    }
+
+    back_insert_iterator<container_type> & operator*(){
+        return (*this);
+    }
+
+    back_insert_iterator<container_type> & operator++(){
+        // pretend to preincrement
+        return (*this);
+    }
+
+    back_insert_iterator<container_type> operator++(int){
+        // pretend to postincrement
+        return (*this);
+    }
+
+protected:
+    container_type *container;    // pointer to container
+};
+
+template<wchar_t> 
+inline back_insert_iterator<basic_string<wchar_t> > back_inserter(
+    basic_string<wchar_t> & s
+){
+    return (std::back_insert_iterator<basic_string<wchar_t> >(s));
+}
+
+} // namespace std
+
+#endif //BOOST_ARCHIVE_DINKUMWARE_HPP
diff --git a/SRC/Serialization/archive/impl/archive_serializer_map.ipp b/SRC/Serialization/archive/impl/archive_serializer_map.ipp
new file mode 100755
index 0000000..2b48fd0
--- /dev/null
+++ b/SRC/Serialization/archive/impl/archive_serializer_map.ipp
@@ -0,0 +1,71 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// archive_serializer_map.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+//////////////////////////////////////////////////////////////////////
+// implementation of basic_text_iprimitive overrides for the combination
+// of template parameters used to implement a text_iprimitive
+
+#include <boost/config.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+#include <Serialization/archive/detail/basic_serializer_map.hpp>
+#include <Serialization/singleton.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace extra_detail { // anon
+    template<class Archive>
+    class map : public basic_serializer_map 
+    {};
+}
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(bool)
+archive_serializer_map<Archive>::insert(const basic_serializer * bs){
+    return boost::serialization::singleton<
+        extra_detail::map<Archive>
+    >::get_mutable_instance().insert(bs);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+archive_serializer_map<Archive>::erase(const basic_serializer * bs){
+    if(boost::serialization::singleton<
+        extra_detail::map<Archive>
+    >::is_destroyed())
+        return;
+    boost::serialization::singleton<
+        extra_detail::map<Archive>
+    >::get_mutable_instance().erase(bs);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(const basic_serializer *) 
+archive_serializer_map<Archive>::find(
+    const boost::serialization::extended_type_info & eti
+) {
+    return boost::serialization::singleton<
+        extra_detail::map<Archive>
+    >::get_const_instance().find(eti);
+}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_binary_iarchive.ipp b/SRC/Serialization/archive/impl/basic_binary_iarchive.ipp
new file mode 100755
index 0000000..9a467ca
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_binary_iarchive.ipp
@@ -0,0 +1,129 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_iarchive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <string>
+#include <boost/assert.hpp>
+#include <algorithm>
+#include <cstring>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::memcpy; 
+    using ::strlen;
+    using ::size_t;
+}
+#endif
+
+#include <boost/detail/workaround.hpp>
+#include <boost/detail/endian.hpp>
+
+#include <Serialization/archive/basic_binary_iarchive.hpp>
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implementation of binary_binary_archive
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_iarchive<Archive>::load_override(class_name_type & t, int){
+    std::string cn;
+    cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE);
+    load_override(cn, 0);
+    if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1))
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::invalid_class_name)
+        );
+    std::memcpy(t, cn.data(), cn.size());
+    // borland tweak
+    t.t[cn.size()] = '\0';
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_iarchive<Archive>::init(){
+    // read signature in an archive version independent manner
+    std::string file_signature;
+    try {
+        std::size_t l;
+        this->This()->load(l);
+        if(l == std::strlen(BOOST_ARCHIVE_SIGNATURE())) {
+            // borland de-allocator fixup
+            #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+            if(NULL != file_signature.data())
+            #endif
+                file_signature.resize(l);
+            // note breaking a rule here - could be a problem on some platform
+            if(0 < l)
+                this->This()->load_binary(&(*file_signature.begin()), l);
+        }
+    }
+    catch(archive_exception const &) {  // catch stream_error archive exceptions
+        // will cause invalid_signature archive exception to be thrown below
+        file_signature = "";   
+    }
+    if(file_signature != BOOST_ARCHIVE_SIGNATURE())
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::invalid_signature)
+        );
+
+    // make sure the version of the reading archive library can
+    // support the format of the archive being read
+    library_version_type input_library_version;
+    //* this->This() >> input_library_version;
+    {
+        int v = 0;
+        v = this->This()->m_sb.sbumpc();
+        #if defined(BOOST_LITTLE_ENDIAN)
+        if(v < 6){
+            ;
+        }
+        else
+        if(v < 7){
+            // version 6 - next byte should be zero
+            this->This()->m_sb.sbumpc();
+        }
+        else
+        if(v < 8){
+            int x1;
+            // version 7 = might be followed by zero or some other byte
+            x1 = this->This()->m_sb.sgetc();
+            // it's =a zero, push it back
+            if(0 == x1)
+                this->This()->m_sb.sbumpc();
+        }
+        else{
+            // version 8+ followed by a zero
+            this->This()->m_sb.sbumpc();
+        }
+        #elif defined(BOOST_BIG_ENDIAN)
+        if(v == 0)
+            v = this->This()->m_sb.sbumpc();
+        #endif
+        input_library_version = static_cast<library_version_type>(v);
+    }
+    
+    #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
+    this->set_library_version(input_library_version);
+    #else
+    #if ! BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
+    detail::
+    #endif
+    basic_iarchive::set_library_version(input_library_version);
+    #endif
+    
+    if(BOOST_ARCHIVE_VERSION() < input_library_version)
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::unsupported_version)
+        );
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_binary_iprimitive.ipp b/SRC/Serialization/archive/impl/basic_binary_iprimitive.ipp
new file mode 100755
index 0000000..139dc4c
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_binary_iprimitive.ipp
@@ -0,0 +1,209 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_iprimitive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <cstddef> // size_t, NULL
+#include <cstring> // memcpy
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t;
+    using ::memcpy;
+} // namespace std
+#endif
+
+#include <boost/detail/workaround.hpp> // fixup for RogueWave
+
+#include <Serialization/throw_exception.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/archive/codecvt_null.hpp>
+#include <Serialization/archive/add_facet.hpp>
+
+namespace boost {
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of basic_binary_iprimitive
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_iprimitive<Archive, Elem, Tr>::init()
+{
+    // Detect  attempts to pass native binary archives across
+    // incompatible platforms. This is not fool proof but its
+    // better than nothing.
+    unsigned char size;
+    this->This()->load(size);
+    if(sizeof(int) != size)
+        boost::serialization::throw_exception(
+            archive_exception(
+                archive_exception::incompatible_native_format,
+                "size of int"
+            )
+        );
+    this->This()->load(size);
+    if(sizeof(long) != size)
+        boost::serialization::throw_exception(
+            archive_exception(
+                archive_exception::incompatible_native_format,
+                "size of long"
+            )
+        );
+    this->This()->load(size);
+    if(sizeof(float) != size)
+        boost::serialization::throw_exception(
+            archive_exception(
+                archive_exception::incompatible_native_format,
+                "size of float"
+            )
+        );
+    this->This()->load(size);
+    if(sizeof(double) != size)
+        boost::serialization::throw_exception(
+            archive_exception(
+                archive_exception::incompatible_native_format,
+                "size of double"
+            )
+        );
+
+    // for checking endian
+    int i;
+    this->This()->load(i);
+    if(1 != i)
+        boost::serialization::throw_exception(
+            archive_exception(
+                archive_exception::incompatible_native_format,
+                "endian setting"
+            )
+        );
+}
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_iprimitive<Archive, Elem, Tr>::load(wchar_t * ws)
+{
+    std::size_t l; // number of wchar_t !!!
+    this->This()->load(l);
+    load_binary(ws, l * sizeof(wchar_t) / sizeof(char));
+    ws[l] = L'\0';
+}
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_iprimitive<Archive, Elem, Tr>::load(std::string & s)
+{
+    std::size_t l;
+    this->This()->load(l);
+    // borland de-allocator fixup
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != s.data())
+    #endif
+        s.resize(l);
+    // note breaking a rule here - could be a problem on some platform
+    if(0 < l)
+        load_binary(&(*s.begin()), l);
+}
+
+#ifndef BOOST_NO_CWCHAR
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_iprimitive<Archive, Elem, Tr>::load(char * s)
+{
+    std::size_t l;
+    this->This()->load(l);
+    load_binary(s, l);
+    s[l] = '\0';
+}
+#endif
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_iprimitive<Archive, Elem, Tr>::load(std::wstring & ws)
+{
+    std::size_t l;
+    this->This()->load(l);
+    // borland de-allocator fixup
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != ws.data())
+    #endif
+        ws.resize(l);
+    // note breaking a rule here - is could be a problem on some platform
+    load_binary(const_cast<wchar_t *>(ws.data()), l * sizeof(wchar_t) / sizeof(char));
+}
+#endif
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_binary_iprimitive<Archive, Elem, Tr>::basic_binary_iprimitive(
+    std::basic_streambuf<Elem, Tr> & sb, 
+    bool no_codecvt
+) :
+#ifndef BOOST_NO_STD_LOCALE
+    m_sb(sb),
+    archive_locale(NULL),
+    locale_saver(m_sb)
+{
+    if(! no_codecvt){
+        archive_locale.reset(
+            boost::archive::add_facet(
+                std::locale::classic(),
+                new codecvt_null<Elem>
+            )
+        );
+        m_sb.pubimbue(* archive_locale);
+    }
+}
+#else
+    m_sb(sb)
+{}
+#endif
+
+// some libraries including stl and libcomo fail if the
+// buffer isn't flushed before the code_cvt facet is changed.
+// I think this is a bug.  We explicity invoke sync to when
+// we're done with the streambuf to work around this problem.
+// Note that sync is a protected member of stream buff so we
+// have to invoke it through a contrived derived class.
+namespace detail {
+// note: use "using" to get past msvc bug
+using namespace std;
+template<class Elem, class Tr>
+class input_streambuf_access : public std::basic_streambuf<Elem, Tr> {
+    public:
+        virtual int sync(){
+#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
+            return this->basic_streambuf::sync();
+#else
+            return this->basic_streambuf<Elem, Tr>::sync();
+#endif
+        }
+};
+} // detail
+
+// scoped_ptr requires that archive_locale be a complete type at time of
+// destruction so define destructor here rather than in the header
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_binary_iprimitive<Archive, Elem, Tr>::~basic_binary_iprimitive(){
+    // push back unread characters
+    //destructor can't throw !
+    try{
+        static_cast<detail::input_streambuf_access<Elem, Tr> &>(m_sb).sync();
+    }
+    catch(...){
+    }
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_binary_oarchive.ipp b/SRC/Serialization/archive/impl/basic_binary_oarchive.ipp
new file mode 100755
index 0000000..0d83d4a
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_binary_oarchive.ipp
@@ -0,0 +1,46 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_oarchive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <string>
+#include <boost/assert.hpp>
+#include <algorithm>
+#include <cstring>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::memcpy; 
+}
+#endif
+
+#include <Serialization/archive/basic_binary_oarchive.hpp>
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implementation of binary_binary_oarchive
+
+template<class Archive>
+#if !defined(__BORLANDC__)
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+#else
+void
+#endif
+basic_binary_oarchive<Archive>::init(){
+    // write signature in an archive version independent manner
+    const std::string file_signature(BOOST_ARCHIVE_SIGNATURE());
+    * this->This() << file_signature;
+    // write library version
+    const library_version_type v(BOOST_ARCHIVE_VERSION());
+    * this->This() << v;
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_binary_oprimitive.ipp b/SRC/Serialization/archive/impl/basic_binary_oprimitive.ipp
new file mode 100755
index 0000000..1643ae7
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_binary_oprimitive.ipp
@@ -0,0 +1,160 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_binary_oprimitive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ostream>
+#include <cstddef> // NULL
+#include <cstring>
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__)
+namespace std{ 
+    using ::strlen; 
+} // namespace std
+#endif
+
+#ifndef BOOST_NO_CWCHAR
+#include <cwchar>
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std{ using ::wcslen; }
+#endif
+#endif
+
+#include <boost/detail/workaround.hpp>
+
+#include <Serialization/archive/add_facet.hpp>
+#include <Serialization/archive/codecvt_null.hpp>
+
+namespace boost {
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of basic_binary_oprimitive
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_oprimitive<Archive, Elem, Tr>::init()
+{
+    // record native sizes of fundamental types
+    // this is to permit detection of attempts to pass
+    // native binary archives accross incompatible machines.
+    // This is not foolproof but its better than nothing.
+    this->This()->save(static_cast<unsigned char>(sizeof(int)));
+    this->This()->save(static_cast<unsigned char>(sizeof(long)));
+    this->This()->save(static_cast<unsigned char>(sizeof(float)));
+    this->This()->save(static_cast<unsigned char>(sizeof(double)));
+    // for checking endianness
+    this->This()->save(int(1));
+}
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_oprimitive<Archive, Elem, Tr>::save(const char * s)
+{
+    std::size_t l = std::strlen(s);
+    this->This()->save(l);
+    save_binary(s, l);
+}
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::string &s)
+{
+    std::size_t l = static_cast<std::size_t>(s.size());
+    this->This()->save(l);
+    save_binary(s.data(), l);
+}
+
+#ifndef BOOST_NO_CWCHAR
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_oprimitive<Archive, Elem, Tr>::save(const wchar_t * ws)
+{
+    std::size_t l = std::wcslen(ws);
+    this->This()->save(l);
+    save_binary(ws, l * sizeof(wchar_t) / sizeof(char));
+}
+#endif
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_binary_oprimitive<Archive, Elem, Tr>::save(const std::wstring &ws)
+{
+    std::size_t l = ws.size();
+    this->This()->save(l);
+    save_binary(ws.data(), l * sizeof(wchar_t) / sizeof(char));
+}
+#endif
+
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_binary_oprimitive<Archive, Elem, Tr>::basic_binary_oprimitive(
+    std::basic_streambuf<Elem, Tr> & sb, 
+    bool no_codecvt
+) : 
+#ifndef BOOST_NO_STD_LOCALE
+    m_sb(sb),
+    archive_locale(NULL),
+    locale_saver(m_sb)
+{
+    if(! no_codecvt){
+        archive_locale.reset(
+            add_facet(
+                std::locale::classic(), 
+                new codecvt_null<Elem>
+            )
+        );
+        m_sb.pubimbue(* archive_locale);
+    }
+}
+#else
+    m_sb(sb)
+{}
+#endif
+
+// some libraries including stl and libcomo fail if the
+// buffer isn't flushed before the code_cvt facet is changed.
+// I think this is a bug.  We explicity invoke sync to when
+// we're done with the streambuf to work around this problem.
+// Note that sync is a protected member of stream buff so we
+// have to invoke it through a contrived derived class.
+namespace detail {
+// note: use "using" to get past msvc bug
+using namespace std;
+template<class Elem, class Tr>
+class output_streambuf_access : public std::basic_streambuf<Elem, Tr> {
+    public:
+        virtual int sync(){
+#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
+            return this->basic_streambuf::sync();
+#else
+            return this->basic_streambuf<Elem, Tr>::sync();
+#endif
+        }
+};
+} // detail
+
+// scoped_ptr requires that g be a complete type at time of
+// destruction so define destructor here rather than in the header
+template<class Archive, class Elem, class Tr>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_binary_oprimitive<Archive, Elem, Tr>::~basic_binary_oprimitive(){
+    // flush buffer
+    //destructor can't throw
+    try{
+        static_cast<detail::output_streambuf_access<Elem, Tr> &>(m_sb).sync();
+    }
+    catch(...){
+    }
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_text_iarchive.ipp b/SRC/Serialization/archive/impl/basic_text_iarchive.ipp
new file mode 100755
index 0000000..fe75542
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_text_iarchive.ipp
@@ -0,0 +1,79 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_iarchive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <string>
+#include <algorithm>
+#include <cstring>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::memcpy; 
+}
+#endif
+
+#include <boost/detail/workaround.hpp>
+#include <Serialization/string.hpp>
+#include <Serialization/archive/basic_text_iarchive.hpp>
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implementation of text_text_archive
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_text_iarchive<Archive>::load_override(class_name_type & t, int){
+    std::string cn;
+    cn.reserve(BOOST_SERIALIZATION_MAX_KEY_SIZE);
+    load_override(cn, 0);
+    if(cn.size() > (BOOST_SERIALIZATION_MAX_KEY_SIZE - 1))
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::invalid_class_name)
+        );
+    std::memcpy(t, cn.data(), cn.size());
+    // borland tweak
+    t.t[cn.size()] = '\0';
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_text_iarchive<Archive>::init(void){
+    // read signature in an archive version independent manner
+    std::string file_signature;
+    * this->This() >> file_signature;
+    if(file_signature != BOOST_ARCHIVE_SIGNATURE())
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::invalid_signature)
+        );
+
+    // make sure the version of the reading archive library can
+    // support the format of the archive being read
+    library_version_type input_library_version;
+    * this->This() >> input_library_version;
+
+    #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
+    this->set_library_version(input_library_version);
+    #else
+    #if ! BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
+    detail::
+    #endif
+    basic_iarchive::set_library_version(input_library_version);
+    #endif
+
+    // extra little .t is to get around borland quirk
+    if(BOOST_ARCHIVE_VERSION() < input_library_version)
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::unsupported_version)
+        );
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_text_iprimitive.ipp b/SRC/Serialization/archive/impl/basic_text_iprimitive.ipp
new file mode 100755
index 0000000..47a0708
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_text_iprimitive.ipp
@@ -0,0 +1,154 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_iprimitive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // size_t
+#include <cstddef> // NULL
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <Serialization/archive/basic_text_iprimitive.hpp>
+#include <Serialization/archive/codecvt_null.hpp>
+#include <Serialization/archive/add_facet.hpp>
+
+#include <Serialization/archive/iterators/remove_whitespace.hpp>
+#include <Serialization/archive/iterators/istream_iterator.hpp>
+#include <Serialization/archive/iterators/binary_from_base64.hpp>
+#include <Serialization/archive/iterators/transform_width.hpp>
+
+namespace boost { 
+namespace archive {
+
+namespace {
+    template<class CharType>
+    bool is_whitespace(CharType c);
+
+    template<>
+    bool is_whitespace(char t){
+        return 0 != std::isspace(t);
+    }
+
+    #ifndef BOOST_NO_CWCHAR
+    template<>
+    bool is_whitespace(wchar_t t){
+        return 0 != std::iswspace(t);
+    }
+    #endif
+}
+
+// translate base64 text into binary and copy into buffer
+// until buffer is full.
+template<class IStream>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_text_iprimitive<IStream>::load_binary(
+    void *address, 
+    std::size_t count
+){
+    typedef BOOST_DEDUCED_TYPENAME IStream::char_type CharType;
+    
+    if(0 == count)
+        return;
+        
+    BOOST_ASSERT(
+        static_cast<std::size_t>((std::numeric_limits<std::streamsize>::max)())
+        > (count + sizeof(CharType) - 1)/sizeof(CharType)
+    );
+        
+    if(is.fail())
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::input_stream_error)
+        );
+    // convert from base64 to binary
+    typedef BOOST_DEDUCED_TYPENAME
+        iterators::transform_width<
+            iterators::binary_from_base64<
+                iterators::remove_whitespace<
+                    iterators::istream_iterator<CharType>
+                >
+                ,CharType
+            >
+            ,8
+            ,6
+            ,CharType
+        > 
+        binary;
+
+    binary ti_begin = binary(
+        BOOST_MAKE_PFTO_WRAPPER(
+            iterators::istream_iterator<CharType>(is)
+        )
+    );
+                
+    char * caddr = static_cast<char *>(address);
+    
+    // take care that we don't increment anymore than necessary
+    while(--count > 0){
+        *caddr++ = static_cast<char>(*ti_begin);
+        ++ti_begin;
+    }
+    *caddr++ = static_cast<char>(*ti_begin);
+    
+    iterators::istream_iterator<CharType> i;
+    for(;;){
+        BOOST_DEDUCED_TYPENAME IStream::int_type r;
+        r = is.get();
+        if(is.eof())
+            break;
+        if(is_whitespace(static_cast<CharType>(r)))
+            break;
+    }
+}
+
+template<class IStream>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_text_iprimitive<IStream>::basic_text_iprimitive(
+    IStream  &is_,
+    bool no_codecvt
+) :
+#ifndef BOOST_NO_STD_LOCALE
+    is(is_),
+    flags_saver(is_),
+    precision_saver(is_),
+    archive_locale(NULL),
+    locale_saver(* is_.rdbuf())
+{
+    if(! no_codecvt){
+        archive_locale.reset(
+            add_facet(
+                std::locale::classic(), 
+                new codecvt_null<BOOST_DEDUCED_TYPENAME IStream::char_type>
+            )
+        );
+        is.imbue(* archive_locale);
+    }
+    is >> std::noboolalpha;
+}
+#else
+    is(is_),
+    flags_saver(is_),
+    precision_saver(is_)
+{}
+#endif
+
+template<class IStream>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_text_iprimitive<IStream>::~basic_text_iprimitive(){
+    is.sync();
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_text_oarchive.ipp b/SRC/Serialization/archive/impl/basic_text_oarchive.ipp
new file mode 100755
index 0000000..5e0b2a6
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_text_oarchive.ipp
@@ -0,0 +1,62 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_oarchive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <string>
+#include <boost/assert.hpp>
+#include <cstring>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::memcpy; 
+}
+#endif
+
+#include <Serialization/archive/basic_text_oarchive.hpp>
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implementation of basic_text_oarchive
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_text_oarchive<Archive>::newtoken()
+{
+    switch(delimiter){
+    default:
+        BOOST_ASSERT(false);
+        break;
+    case eol:
+        this->This()->put('\n');
+        delimiter = space;
+        break;
+    case space:
+        this->This()->put(' ');
+        break;
+    case none:
+        delimiter = space;
+        break;
+    }
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_text_oarchive<Archive>::init(){
+    // write signature in an archive version independent manner
+    const std::string file_signature(BOOST_ARCHIVE_SIGNATURE());
+    * this->This() << file_signature;
+    // write library version
+    const library_version_type v(BOOST_ARCHIVE_VERSION());
+    * this->This() << v;
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_text_oprimitive.ipp b/SRC/Serialization/archive/impl/basic_text_oprimitive.ipp
new file mode 100755
index 0000000..3ef5138
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_text_oprimitive.ipp
@@ -0,0 +1,114 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_oprimitive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // NULL
+#include <Serialization/pfto.hpp>
+
+#include <Serialization/archive/basic_text_oprimitive.hpp>
+#include <Serialization/archive/codecvt_null.hpp>
+#include <Serialization/archive/add_facet.hpp>
+
+#include <Serialization/archive/iterators/base64_from_binary.hpp>
+#include <Serialization/archive/iterators/insert_linebreaks.hpp>
+#include <Serialization/archive/iterators/transform_width.hpp>
+#include <Serialization/archive/iterators/ostream_iterator.hpp>
+
+namespace boost {
+namespace archive {
+
+// translate to base64 and copy in to buffer.
+template<class OStream>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_text_oprimitive<OStream>::save_binary(
+    const void *address, 
+    std::size_t count
+){
+    typedef BOOST_DEDUCED_TYPENAME OStream::char_type CharType;
+    
+    if(0 == count)
+        return;
+    
+    if(os.fail())
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::output_stream_error)
+        );
+        
+    os.put('\n');
+    
+    typedef 
+        boost::archive::iterators::insert_linebreaks<
+            boost::archive::iterators::base64_from_binary<
+                boost::archive::iterators::transform_width<
+                    const char *,
+                    6,
+                    8
+                >
+            > 
+            ,72
+            ,const char // cwpro8 needs this
+        > 
+        base64_text;
+
+    boost::archive::iterators::ostream_iterator<CharType> oi(os);
+    std::copy(
+        base64_text(BOOST_MAKE_PFTO_WRAPPER(static_cast<const char *>(address))),
+        base64_text(
+            BOOST_MAKE_PFTO_WRAPPER(static_cast<const char *>(address) + count)
+        ),
+        oi
+    );
+    
+    std::size_t tail = count % 3;
+    if(tail > 0){
+        *oi++ = '=';
+        if(tail < 2)
+            *oi = '=';
+    }
+}
+
+template<class OStream>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_text_oprimitive<OStream>::basic_text_oprimitive(
+    OStream & os_,
+    bool no_codecvt
+) : 
+#ifndef BOOST_NO_STD_LOCALE
+    os(os_),
+    flags_saver(os_),
+    precision_saver(os_),
+    archive_locale(NULL),
+    locale_saver(* os_.rdbuf())
+{
+    if(! no_codecvt){
+        archive_locale.reset(
+            add_facet(
+                std::locale::classic(), 
+                new codecvt_null<BOOST_DEDUCED_TYPENAME OStream::char_type>
+            )
+        );
+        os.imbue(* archive_locale);
+    }
+    os << std::noboolalpha;
+}
+#else
+    os(os_),
+    flags_saver(os_),
+    precision_saver(os_)
+{}
+#endif
+
+template<class OStream>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_text_oprimitive<OStream>::~basic_text_oprimitive(){
+    os << std::endl;
+}
+
+} //namespace boost 
+} //namespace archive 
diff --git a/SRC/Serialization/archive/impl/basic_xml_grammar.hpp b/SRC/Serialization/archive/impl/basic_xml_grammar.hpp
new file mode 100755
index 0000000..374f73f
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_xml_grammar.hpp
@@ -0,0 +1,178 @@
+#ifndef BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP
+#define BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_grammar.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// this module is derived from simplexml.cpp - an example shipped as part of
+// the spirit parser.  This example contains the following notice:
+/*=============================================================================
+    simplexml.cpp
+
+    Spirit V1.3
+    URL: http://spirit.sourceforge.net/
+
+    Copyright (c) 2001, Daniel C. Nuffer
+
+    This software is provided 'as-is', without any express or implied
+    warranty. In no event will the copyright holder be held liable for
+    any damages arising from the use of this software.
+
+    Permission is granted to anyone to use this software for any purpose,
+    including commercial applications, and to alter it and redistribute
+    it freely, subject to the following restrictions:
+
+    1.  The origin of this software must not be misrepresented; you must
+        not claim that you wrote the original software. If you use this
+        software in a product, an acknowledgment in the product documentation
+        would be appreciated but is not required.
+
+    2.  Altered source versions must be plainly marked as such, and must
+        not be misrepresented as being the original software.
+
+    3.  This notice may not be removed or altered from any source
+        distribution.
+=============================================================================*/
+#include <string>
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+// supress noise
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <boost/spirit/include/classic_rule.hpp>
+#include <boost/spirit/include/classic_chset.hpp>
+
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/version.hpp>
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// XML grammar parsing
+
+template<class CharType>
+class basic_xml_grammar {
+public:
+    // The following is not necessary according to DR45, but at least
+    // one compiler (Compaq C++ 6.5 in strict_ansi mode) chokes otherwise.
+    struct return_values;
+    friend struct return_values;
+    
+private:
+    typedef BOOST_DEDUCED_TYPENAME std::basic_istream<CharType> IStream;
+    typedef BOOST_DEDUCED_TYPENAME std::basic_string<CharType> StringType;
+    typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::chset<CharType> chset_t;
+    typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::chlit<CharType> chlit_t;
+    typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::scanner<
+        BOOST_DEDUCED_TYPENAME  std::basic_string<CharType>::iterator
+    > scanner_t;
+    typedef BOOST_DEDUCED_TYPENAME boost::spirit::classic::rule<scanner_t> rule_t;
+    // Start grammar definition
+    rule_t    
+        Reference,
+        Eq, 
+        STag,
+        ETag,
+        LetterOrUnderscoreOrColon,
+        AttValue, 
+        CharRef1, 
+        CharRef2, 
+        CharRef, 
+        AmpRef,
+        LTRef,
+        GTRef,
+        AposRef,
+        QuoteRef,
+        CharData,
+        CharDataChars,
+        content,
+        AmpName,
+        LTName,
+        GTName,
+        ClassNameChar,
+        ClassName,
+        Name,
+        XMLDecl,
+        XMLDeclChars,
+        DocTypeDecl,
+        DocTypeDeclChars,
+        ClassIDAttribute,
+        ObjectIDAttribute,
+        ClassNameAttribute,
+        TrackingAttribute,
+        VersionAttribute,
+        UnusedAttribute,
+        Attribute,
+        SignatureAttribute,
+        SerializationWrapper,
+        NameHead,
+        NameTail,
+        AttributeList,
+        S;
+
+    // XML Character classes
+    chset_t
+        BaseChar,
+        Ideographic,
+        Char, 
+        Letter, 
+        Digit,
+        CombiningChar,
+        Extender, 
+        Sch,
+        NameChar;
+
+    void init_chset();
+
+    bool my_parse(
+        IStream & is,
+        const rule_t &rule_, 
+        const CharType delimiter = L'>'
+    ) const ;
+public:
+    struct return_values {
+        StringType object_name;
+        StringType contents;
+        //class_id_type class_id;
+        int_least16_t class_id;
+        //object_id_type object_id;
+        uint_least32_t object_id;
+        //version_type version;
+        unsigned int version;
+        tracking_type tracking_level;
+        StringType class_name;
+        return_values() :
+            version(0),
+            tracking_level(false)
+        {}
+    } rv;
+    bool parse_start_tag(IStream & is) /*const*/;
+    bool parse_end_tag(IStream & is) const;
+    bool parse_string(IStream & is, StringType & s) /*const*/;
+    void init(IStream & is);
+    void windup(IStream & is);
+    basic_xml_grammar();
+};
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_BASIC_XML_GRAMMAR_HPP
diff --git a/SRC/Serialization/archive/impl/basic_xml_iarchive.ipp b/SRC/Serialization/archive/impl/basic_xml_iarchive.ipp
new file mode 100755
index 0000000..fa4e97f
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_xml_iarchive.ipp
@@ -0,0 +1,114 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_iarchive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <cstddef> // NULL
+#include <algorithm>
+
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/archive/xml_archive_exception.hpp>
+#include <Serialization/archive/basic_xml_iarchive.hpp>
+#include <Serialization/tracking.hpp>
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implementation of xml_text_archive
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_iarchive<Archive>::load_start(const char *name){
+    // if there's no name
+    if(NULL == name)
+        return;
+    bool result = this->This()->gimpl->parse_start_tag(this->This()->get_is());
+    if(true != result){
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::input_stream_error)
+        );
+    }
+    // don't check start tag at highest level
+    ++depth;
+    return;
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_iarchive<Archive>::load_end(const char *name){
+    // if there's no name
+    if(NULL == name)
+        return;
+    bool result = this->This()->gimpl->parse_end_tag(this->This()->get_is());
+    if(true != result){
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::input_stream_error)
+        );
+    }
+    
+    // don't check start tag at highest level
+    if(0 == --depth)
+        return;
+        
+    if(0 == (this->get_flags() & no_xml_tag_checking)){
+        // double check that the tag matches what is expected - useful for debug
+        if(0 != name[this->This()->gimpl->rv.object_name.size()]
+        || ! std::equal(
+                this->This()->gimpl->rv.object_name.begin(),
+                this->This()->gimpl->rv.object_name.end(),
+                name
+            )
+        ){
+            boost::serialization::throw_exception(
+                xml_archive_exception(
+                    xml_archive_exception::xml_archive_tag_mismatch,
+                    name
+                )
+            );
+        }
+    }
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_iarchive<Archive>::load_override(object_id_type & t, int){
+    t = object_id_type(this->This()->gimpl->rv.object_id);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_iarchive<Archive>::load_override(version_type & t, int){
+    t = version_type(this->This()->gimpl->rv.version);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_iarchive<Archive>::load_override(class_id_type & t, int){
+    t = class_id_type(this->This()->gimpl->rv.class_id);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_iarchive<Archive>::load_override(tracking_type & t, int){
+    t = this->This()->gimpl->rv.tracking_level;
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_xml_iarchive<Archive>::basic_xml_iarchive(unsigned int flags) :
+    detail::common_iarchive<Archive>(flags),
+    depth(0)
+{}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_xml_iarchive<Archive>::~basic_xml_iarchive(){}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/basic_xml_oarchive.ipp b/SRC/Serialization/archive/impl/basic_xml_oarchive.ipp
new file mode 100755
index 0000000..042e718
--- /dev/null
+++ b/SRC/Serialization/archive/impl/basic_xml_oarchive.ipp
@@ -0,0 +1,275 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_oarchive.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <algorithm>
+#include <cstddef> // NULL
+#include <cstring>
+#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__)
+namespace std{
+    using ::strlen;
+} // namespace std
+#endif
+
+#include <Serialization/archive/basic_xml_archive.hpp>
+#include <Serialization/archive/basic_xml_oarchive.hpp>
+#include <Serialization/archive/xml_archive_exception.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+namespace boost {
+namespace archive {
+
+namespace detail {
+template<class CharType>
+struct XML_name {
+    void operator()(CharType t) const{
+        const unsigned char lookup_table[] = {
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0, // -.
+            1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, // 0-9
+            0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // A-
+            1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, // -Z _
+            0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // a-
+            1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0, // -z
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+        };
+        if((unsigned)t > 127)
+            return;
+        if(0 == lookup_table[(unsigned)t])
+            boost::serialization::throw_exception(
+                xml_archive_exception(
+                    xml_archive_exception::xml_archive_tag_name_error
+                )
+            );
+    }
+};
+
+} // namespace detail
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implemenations of functions common to both types of xml output
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::write_attribute(
+    const char *attribute_name,
+    int t,
+    const char *conjunction
+){
+    this->This()->put(' ');
+    this->This()->put(attribute_name);
+    this->This()->put(conjunction);
+    this->This()->save(t);
+    this->This()->put('"');
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::write_attribute(
+    const char *attribute_name,
+    const char *key
+){
+    this->This()->put(' ');
+    this->This()->put(attribute_name);
+    this->This()->put("=\"");
+    this->This()->save(key);
+    this->This()->put('"');
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::indent(){
+    int i;
+    for(i = depth; i-- > 0;)
+        this->This()->put('\t');
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_start(const char *name)
+{
+    if(NULL == name)
+        return;
+
+    // be sure name has no invalid characters
+    std::for_each(name, name + std::strlen(name), detail::XML_name<const char>());
+
+    end_preamble();
+    if(depth > 0){
+        this->This()->put('\n');
+        indent();
+    }
+    ++depth;
+    this->This()->put('<');
+    this->This()->save(name);
+    pending_preamble = true;
+    indent_next = false;
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_end(const char *name)
+{
+    if(NULL == name)
+        return;
+
+    // be sure name has no invalid characters
+    std::for_each(name, name + std::strlen(name), detail::XML_name<const char>());
+
+    end_preamble();
+    --depth;
+    if(indent_next){
+        this->This()->put('\n');
+        indent();
+    }
+    indent_next = true;
+    this->This()->put("</");
+    this->This()->save(name);
+    this->This()->put('>');
+    if(0 == depth)
+        this->This()->put('\n');
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::end_preamble(){
+    if(pending_preamble){
+        this->This()->put('>');
+        pending_preamble = false;
+    }
+}
+#if 0
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(const object_id_type & t, int)
+{
+    int i = t.t; // extra .t is for borland
+    write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_");
+}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(
+    const object_reference_type & t,
+    int
+){
+    int i = t.t; // extra .t is for borland
+    write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_");
+}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(const version_type & t, int)
+{
+    int i = t.t; // extra .t is for borland
+    write_attribute(BOOST_ARCHIVE_XML_VERSION(), i);
+}
+#endif
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(const object_id_type & t, int)
+{
+    // borland doesn't do conversion of STRONG_TYPEDEFs very well
+    const unsigned int i = t;
+    write_attribute(BOOST_ARCHIVE_XML_OBJECT_ID(), i, "=\"_");
+}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(
+    const object_reference_type & t,
+    int
+){
+    const unsigned int i = t;
+    write_attribute(BOOST_ARCHIVE_XML_OBJECT_REFERENCE(), i, "=\"_");
+}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(const version_type & t, int)
+{
+    const unsigned int i = t;
+    write_attribute(BOOST_ARCHIVE_XML_VERSION(), i);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(const class_id_type & t, int)
+{
+    write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t);
+}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(
+    const class_id_reference_type & t,
+    int
+){
+    write_attribute(BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE(), t);
+}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(
+    const class_id_optional_type & t,
+    int
+){
+    write_attribute(BOOST_ARCHIVE_XML_CLASS_ID(), t);
+}
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(const class_name_type & t, int)
+{
+    const char * key = t;
+    if(NULL == key)
+        return;
+    write_attribute(BOOST_ARCHIVE_XML_CLASS_NAME(), key);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::save_override(const tracking_type & t, int)
+{
+    write_attribute(BOOST_ARCHIVE_XML_TRACKING(), t.t);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(void)
+basic_xml_oarchive<Archive>::init(){
+    // xml header
+    this->This()->put("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n");
+    this->This()->put("<!DOCTYPE boost_serialization>\n");
+    // xml document wrapper - outer root
+    this->This()->put("<boost_serialization");
+    write_attribute("signature", BOOST_ARCHIVE_SIGNATURE());
+    write_attribute("version", BOOST_ARCHIVE_VERSION());
+    this->This()->put(">\n");
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_xml_oarchive<Archive>::basic_xml_oarchive(unsigned int flags) :
+    detail::common_oarchive<Archive>(flags),
+    depth(0),
+    indent_next(false),
+    pending_preamble(false)
+{
+}
+
+template<class Archive>
+BOOST_ARCHIVE_OR_WARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_xml_oarchive<Archive>::~basic_xml_oarchive(){
+    if(0 == (this->get_flags() & no_header)){
+        BOOST_TRY{
+                this->This()->put("</boost_serialization>\n");
+        }
+        BOOST_CATCH(...){}
+        BOOST_CATCH_END
+    }
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/text_iarchive_impl.ipp b/SRC/Serialization/archive/impl/text_iarchive_impl.ipp
new file mode 100755
index 0000000..cf769c7
--- /dev/null
+++ b/SRC/Serialization/archive/impl/text_iarchive_impl.ipp
@@ -0,0 +1,128 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_iarchive_impl.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+//////////////////////////////////////////////////////////////////////
+// implementation of basic_text_iprimitive overrides for the combination
+// of template parameters used to implement a text_iprimitive
+
+#include <cstddef> // size_t, NULL
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <boost/detail/workaround.hpp> // RogueWave
+
+#include <Serialization/archive/text_iarchive.hpp>
+
+namespace boost {
+namespace archive {
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_iarchive_impl<Archive>::load(char *s)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // skip separating space
+    is.get();
+    // Works on all tested platforms
+    is.read(s, size);
+    s[size] = '\0';
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_iarchive_impl<Archive>::load(std::string &s)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // skip separating space
+    is.get();
+    // borland de-allocator fixup
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != s.data())
+    #endif
+        s.resize(size);
+    if(0 < size)
+        is.read(&(*s.begin()), size);
+}
+
+#ifndef BOOST_NO_CWCHAR
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_iarchive_impl<Archive>::load(wchar_t *ws)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // skip separating space
+    is.get();
+    is.read((char *)ws, size * sizeof(wchar_t)/sizeof(char));
+    ws[size] = L'\0';
+}
+#endif // BOOST_NO_INTRINSIC_WCHAR_T
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_iarchive_impl<Archive>::load(std::wstring &ws)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // borland de-allocator fixup
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != ws.data())
+    #endif
+        ws.resize(size);
+    // skip separating space
+    is.get();
+    is.read((char *)ws.data(), size * sizeof(wchar_t)/sizeof(char));
+}
+
+#endif // BOOST_NO_STD_WSTRING
+#endif // BOOST_NO_CWCHAR
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_iarchive_impl<Archive>::load_override(class_name_type & t, int){
+    basic_text_iarchive<Archive>::load_override(t, 0);
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_iarchive_impl<Archive>::init(){
+    basic_text_iarchive<Archive>::init();
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+text_iarchive_impl<Archive>::text_iarchive_impl(
+    std::istream & is, 
+    unsigned int flags
+) :
+    basic_text_iprimitive<std::istream>(
+        is, 
+        0 != (flags & no_codecvt)
+    ),
+    basic_text_iarchive<Archive>(flags)
+{
+    if(0 == (flags & no_header))
+        #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
+        this->init();
+        #else
+        this->basic_text_iarchive<Archive>::init();
+        #endif
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/text_oarchive_impl.ipp b/SRC/Serialization/archive/impl/text_oarchive_impl.ipp
new file mode 100755
index 0000000..d94e4ab
--- /dev/null
+++ b/SRC/Serialization/archive/impl/text_oarchive_impl.ipp
@@ -0,0 +1,124 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_oarchive_impl.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <string>
+#include <boost/config.hpp>
+#include <locale>
+#include <cstddef> // size_t
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#ifndef BOOST_NO_CWCHAR
+#include <cwchar>
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std{ using ::wcslen; }
+#endif
+#endif
+
+#include <Serialization/archive/add_facet.hpp>
+#include <Serialization/archive/text_oarchive.hpp>
+
+namespace boost { 
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of basic_text_oprimitive overrides for the combination
+// of template parameters used to create a text_oprimitive
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_oarchive_impl<Archive>::save(const char * s)
+{
+    const std::size_t len = std::ostream::traits_type::length(s);
+    *this->This() << len;
+    this->This()->newtoken();
+    os << s;
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_oarchive_impl<Archive>::save(const std::string &s)
+{
+    const std::size_t size = s.size();
+    *this->This() << size;
+    this->This()->newtoken();
+    os << s;
+}
+
+#ifndef BOOST_NO_CWCHAR
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_oarchive_impl<Archive>::save(const wchar_t * ws)
+{
+    const std::size_t l = std::wcslen(ws);
+    * this->This() << l;
+    this->This()->newtoken();
+    os.write((const char *)ws, l * sizeof(wchar_t)/sizeof(char));
+}
+#endif
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_oarchive_impl<Archive>::save(const std::wstring &ws)
+{
+    const std::size_t l = ws.size();
+    * this->This() << l;
+    this->This()->newtoken();
+    os.write((const char *)(ws.data()), l * sizeof(wchar_t)/sizeof(char));
+}
+#endif
+#endif // BOOST_NO_CWCHAR
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+text_oarchive_impl<Archive>::text_oarchive_impl(
+    std::ostream & os, 
+    unsigned int flags
+) :
+    basic_text_oprimitive<std::ostream>(
+        os, 
+        0 != (flags & no_codecvt)
+    ),
+    basic_text_oarchive<Archive>(flags)
+{
+    if(0 == (flags & no_header))
+        #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
+        this->init();
+        #else
+        this->basic_text_oarchive<Archive>::init();
+        #endif
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+text_oarchive_impl<Archive>::save_binary(const void *address, std::size_t count){
+    put('\n');
+    this->end_preamble();
+    #if ! defined(__MWERKS__)
+    this->basic_text_oprimitive<std::ostream>::save_binary(
+    #else
+    this->basic_text_oprimitive::save_binary(
+    #endif
+        address, 
+        count
+    );
+    this->delimiter = this->eol;
+}
+
+} // namespace archive
+} // namespace boost
+
diff --git a/SRC/Serialization/archive/impl/text_wiarchive_impl.ipp b/SRC/Serialization/archive/impl/text_wiarchive_impl.ipp
new file mode 100755
index 0000000..75fc453
--- /dev/null
+++ b/SRC/Serialization/archive/impl/text_wiarchive_impl.ipp
@@ -0,0 +1,118 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_text_wiarchive_impl.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // size_t, NULL
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <boost/detail/workaround.hpp>  // fixup for RogueWave
+
+#ifndef BOOST_NO_STD_WSTREAMBUF
+#include <Serialization/archive/basic_text_iprimitive.hpp>
+
+namespace boost { 
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of wiprimtives functions
+//
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_wiarchive_impl<Archive>::load(char *s)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // skip separating space
+    is.get();
+    while(size-- > 0){
+        *s++ = is.narrow(is.get(), '\0');
+    }
+    *s = '\0';
+}
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_wiarchive_impl<Archive>::load(std::string &s)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // skip separating space
+    is.get();
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != s.data())
+    #endif
+        s.resize(0);
+    s.reserve(size);
+    while(size-- > 0){
+        int x = is.narrow(is.get(), '\0');
+        s += x;
+    }
+}
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_wiarchive_impl<Archive>::load(wchar_t *s)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // skip separating space
+    is.get();
+    // Works on all tested platforms
+    is.read(s, size);
+    s[size] = L'\0';
+}
+#endif
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_wiarchive_impl<Archive>::load(std::wstring &ws)
+{
+    std::size_t size;
+    * this->This() >> size;
+    // skip separating space
+    is.get();
+    // borland complains about resize
+    // borland de-allocator fixup
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != ws.data())
+    #endif
+        ws.resize(size);
+    // note breaking a rule here - is this a problem on some platform
+    is.read(const_cast<wchar_t *>(ws.data()), size);
+}
+#endif
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+text_wiarchive_impl<Archive>::text_wiarchive_impl(
+    std::wistream & is, 
+    unsigned int flags
+) :
+    basic_text_iprimitive<std::wistream>(
+        is, 
+        0 != (flags & no_codecvt)
+    ),
+    basic_text_iarchive<Archive>(flags)
+{
+    if(0 == (flags & no_header))
+        basic_text_iarchive<Archive>::init();
+}
+
+} // archive
+} // boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/archive/impl/text_woarchive_impl.ipp b/SRC/Serialization/archive/impl/text_woarchive_impl.ipp
new file mode 100755
index 0000000..72586ab
--- /dev/null
+++ b/SRC/Serialization/archive/impl/text_woarchive_impl.ipp
@@ -0,0 +1,85 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_woarchive_impl.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_STD_WSTREAMBUF
+
+#include <cstring>
+#include <cstddef> // size_t
+#if defined(BOOST_NO_STDC_NAMESPACE) && ! defined(__LIBCOMO__)
+namespace std{ 
+    using ::strlen;
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <ostream>
+
+#include <Serialization/archive/text_woarchive.hpp>
+
+namespace boost {
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of woarchive functions
+//
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_woarchive_impl<Archive>::save(const char *s)
+{
+    // note: superfluous local variable fixes borland warning
+    const std::size_t size = std::strlen(s);
+    * this->This() << size;
+    this->This()->newtoken();
+    while(*s != '\0')
+        os.put(os.widen(*s++));
+}
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_woarchive_impl<Archive>::save(const std::string &s)
+{
+    const std::size_t size = s.size();
+    * this->This() << size;
+    this->This()->newtoken();
+    const char * cptr = s.data();
+    for(std::size_t i = size; i-- > 0;)
+        os.put(os.widen(*cptr++));
+}
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_woarchive_impl<Archive>::save(const wchar_t *ws)
+{
+    const std::size_t size = std::wostream::traits_type::length(ws);
+    * this->This() << size;
+    this->This()->newtoken();
+    os.write(ws, size);
+}
+#endif
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+text_woarchive_impl<Archive>::save(const std::wstring &ws)
+{
+    const std::size_t size = ws.length();
+    * this->This() << size;
+    this->This()->newtoken();
+    os.write(ws.data(), size);
+}
+#endif
+
+} // namespace archive
+} // namespace boost
+
+#endif
+
diff --git a/SRC/Serialization/archive/impl/xml_iarchive_impl.ipp b/SRC/Serialization/archive/impl/xml_iarchive_impl.ipp
new file mode 100755
index 0000000..2019aed
--- /dev/null
+++ b/SRC/Serialization/archive/impl/xml_iarchive_impl.ipp
@@ -0,0 +1,204 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_iarchive_impl.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <cstring> // memcpy
+#include <cstddef> // NULL
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::memcpy;
+} // namespace std
+#endif
+
+#ifndef BOOST_NO_CWCHAR
+#include <cstdlib> // mbtowc
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::mbtowc;
+ } // namespace std
+#endif
+#endif // BOOST_NO_CWCHAR
+
+#include <boost/detail/workaround.hpp> // RogueWave and Dinkumware
+#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
+#include <Serialization/archive/dinkumware.hpp>
+#endif
+
+#include <boost/detail/no_exceptions_support.hpp>
+
+#include <Serialization/archive/xml_archive_exception.hpp>
+#include <Serialization/archive/iterators/dataflow_exception.hpp>
+#include <Serialization/archive/basic_xml_archive.hpp>
+#include <Serialization/archive/xml_iarchive.hpp>
+
+#include "basic_xml_grammar.hpp"
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implemenations of functions specific to char archives
+
+// wide char stuff used by char archives
+
+#ifndef BOOST_NO_CWCHAR
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_iarchive_impl<Archive>::load(std::wstring &ws){
+    std::string s;
+    bool result = gimpl->parse_string(is, s);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != ws.data())
+    #endif
+        ws.resize(0);
+    const char * start = s.data();
+    const char * end = start + s.size();
+    while(start < end){
+        wchar_t wc;
+        int resultx = std::mbtowc(&wc, start, end - start);
+        if(0 < resultx){
+            start += resultx;
+            ws += wc;
+            continue;
+        }
+        boost::serialization::throw_exception(
+            iterators::dataflow_exception(
+                iterators::dataflow_exception::invalid_conversion
+            )
+        );
+    }
+}
+#endif // BOOST_NO_STD_WSTRING
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_iarchive_impl<Archive>::load(wchar_t * ws){
+    std::string s;
+    bool result = gimpl->parse_string(is, s);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+        
+    const char * start = s.data();
+    const char * end = start + s.size();
+    while(start < end){
+        wchar_t wc;
+        int result = std::mbtowc(&wc, start, end - start);
+        if(0 < result){
+            start += result;
+            *ws++ = wc;
+            continue;
+        }
+        boost::serialization::throw_exception(
+            iterators::dataflow_exception(
+                iterators::dataflow_exception::invalid_conversion
+            )
+        );
+    }
+    *ws = L'\0';
+}
+#endif // BOOST_NO_INTRINSIC_WCHAR_T
+
+#endif // BOOST_NO_CWCHAR
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_iarchive_impl<Archive>::load(std::string &s){
+    bool result = gimpl->parse_string(is, s);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_iarchive_impl<Archive>::load(char * s){
+    std::string tstring;
+    bool result = gimpl->parse_string(is, tstring);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    std::memcpy(s, tstring.data(), tstring.size());
+    s[tstring.size()] = 0;
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_iarchive_impl<Archive>::load_override(class_name_type & t, int){
+    const std::string & s = gimpl->rv.class_name;
+    if(s.size() > BOOST_SERIALIZATION_MAX_KEY_SIZE - 1)
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::invalid_class_name)
+       );
+    char * tptr = t;
+    std::memcpy(tptr, s.data(), s.size());
+    tptr[s.size()] = '\0';
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_iarchive_impl<Archive>::init(){
+    gimpl->init(is);
+    this->set_library_version(
+        library_version_type(gimpl->rv.version)
+    );
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+xml_iarchive_impl<Archive>::xml_iarchive_impl(
+    std::istream &is_,
+    unsigned int flags
+) :
+    basic_text_iprimitive<std::istream>(
+        is_, 
+        0 != (flags & no_codecvt)
+    ),
+    basic_xml_iarchive<Archive>(flags),
+    gimpl(new xml_grammar())
+{
+    if(0 == (flags & no_header)){
+        BOOST_TRY{
+            init();
+        }
+        BOOST_CATCH(...){
+            delete gimpl;
+            #ifndef BOOST_NO_EXCEPTIONS
+                throw; // re-throw
+            #endif
+        }
+        BOOST_CATCH_END
+    }
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+xml_iarchive_impl<Archive>::~xml_iarchive_impl(){
+    if(0 == (this->get_flags() & no_header)){
+        BOOST_TRY{
+            gimpl->windup(is);
+        }
+        BOOST_CATCH(...){}
+        BOOST_CATCH_END
+    }
+    delete gimpl;
+}
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/xml_oarchive_impl.ipp b/SRC/Serialization/archive/impl/xml_oarchive_impl.ipp
new file mode 100755
index 0000000..b2d25fd
--- /dev/null
+++ b/SRC/Serialization/archive/impl/xml_oarchive_impl.ipp
@@ -0,0 +1,117 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_oarchive_impl.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <ostream>
+#include <iomanip>
+#include <algorithm>
+#include <string>
+
+#include <cstring> // strlen
+#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::strlen; 
+} // namespace std
+#endif
+
+#include <Serialization/archive/iterators/xml_escape.hpp>
+#include <Serialization/archive/iterators/ostream_iterator.hpp>
+
+#ifndef BOOST_NO_CWCHAR
+#include <Serialization/archive/wcslen.hpp>
+#include <Serialization/archive/iterators/mb_from_wchar.hpp>
+#endif
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implemenations of functions specific to char archives
+
+// wide char stuff used by char archives
+#ifndef BOOST_NO_CWCHAR
+// copy chars to output escaping to xml and translating wide chars to mb chars
+template<class InputIterator>
+void save_iterator(std::ostream &os, InputIterator begin, InputIterator end){
+    typedef boost::archive::iterators::mb_from_wchar<
+        boost::archive::iterators::xml_escape<InputIterator>
+    > translator;
+    std::copy(
+        translator(BOOST_MAKE_PFTO_WRAPPER(begin)), 
+        translator(BOOST_MAKE_PFTO_WRAPPER(end)), 
+        boost::archive::iterators::ostream_iterator<char>(os)
+    );
+}
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_oarchive_impl<Archive>::save(const std::wstring & ws){
+//  at least one library doesn't typedef value_type for strings
+//  so rather than using string directly make a pointer iterator out of it
+//    save_iterator(os, ws.data(), ws.data() + std::wcslen(ws.data()));
+    save_iterator(os, ws.data(), ws.data() + ws.size());
+}
+#endif
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_oarchive_impl<Archive>::save(const wchar_t * ws){
+    save_iterator(os, ws, ws + std::wcslen(ws));
+}
+#endif
+
+#endif // BOOST_NO_CWCHAR
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_oarchive_impl<Archive>::save(const std::string & s){
+//  at least one library doesn't typedef value_type for strings
+//  so rather than using string directly make a pointer iterator out of it
+    typedef boost::archive::iterators::xml_escape<
+        const char * 
+    > xml_escape_translator;
+    std::copy(
+        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data())),
+        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s.data()+ s.size())), 
+        boost::archive::iterators::ostream_iterator<char>(os)
+    );
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(void)
+xml_oarchive_impl<Archive>::save(const char * s){
+    typedef boost::archive::iterators::xml_escape<
+        const char * 
+    > xml_escape_translator;
+    std::copy(
+        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s)),
+        xml_escape_translator(BOOST_MAKE_PFTO_WRAPPER(s + std::strlen(s))), 
+        boost::archive::iterators::ostream_iterator<char>(os)
+    );
+}
+
+template<class Archive>
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+xml_oarchive_impl<Archive>::xml_oarchive_impl(
+    std::ostream & os_, 
+    unsigned int flags
+) : 
+    basic_text_oprimitive<std::ostream>(
+        os_,
+        0 != (flags & no_codecvt)
+    ),
+    basic_xml_oarchive<Archive>(flags)
+{
+    if(0 == (flags & no_header))
+        this->init();
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/archive/impl/xml_wiarchive_impl.ipp b/SRC/Serialization/archive/impl/xml_wiarchive_impl.ipp
new file mode 100755
index 0000000..bfb5afb
--- /dev/null
+++ b/SRC/Serialization/archive/impl/xml_wiarchive_impl.ipp
@@ -0,0 +1,206 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_wiprimitive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+
+#include <cstring>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::memcpy; 
+} //std
+#endif
+
+#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings
+#ifndef BOOST_NO_STD_WSTREAMBUF
+
+#include <boost/assert.hpp>
+#include <algorithm>
+
+#include <boost/detail/workaround.hpp> // Dinkumware and RogueWave
+#if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1)
+#include <Serialization/archive/dinkumware.hpp>
+#endif
+
+#include <boost/io/ios_state.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <Serialization/string.hpp>
+#include <Serialization/archive/add_facet.hpp>
+#include <Serialization/archive/xml_archive_exception.hpp>
+#include <Serialization/archive/detail/utf8_codecvt_facet.hpp>
+
+#include <Serialization/archive/iterators/mb_from_wchar.hpp>
+
+#include <Serialization/archive/basic_xml_archive.hpp>
+#include <Serialization/archive/xml_wiarchive.hpp>
+
+#include "basic_xml_grammar.hpp"
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implemenations of functions specific to wide char archives
+
+namespace { // anonymous
+
+void copy_to_ptr(char * s, const std::wstring & ws){
+    std::copy(
+        iterators::mb_from_wchar<std::wstring::const_iterator>(
+            BOOST_MAKE_PFTO_WRAPPER(ws.begin())
+        ), 
+        iterators::mb_from_wchar<std::wstring::const_iterator>(
+            BOOST_MAKE_PFTO_WRAPPER(ws.end())
+        ), 
+        s
+    );
+    s[ws.size()] = 0;
+}
+
+} // anonymous
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_wiarchive_impl<Archive>::load(std::string & s){
+    std::wstring ws;
+    bool result = gimpl->parse_string(is, ws);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    #if BOOST_WORKAROUND(_RWSTD_VER, BOOST_TESTED_AT(20101))
+    if(NULL != s.data())
+    #endif
+        s.resize(0);
+    s.reserve(ws.size());
+    std::copy(
+        iterators::mb_from_wchar<std::wstring::iterator>(
+            BOOST_MAKE_PFTO_WRAPPER(ws.begin())
+        ), 
+        iterators::mb_from_wchar<std::wstring::iterator>(
+            BOOST_MAKE_PFTO_WRAPPER(ws.end())
+        ), 
+        std::back_inserter(s)
+    );
+}
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_wiarchive_impl<Archive>::load(std::wstring & ws){
+    bool result = gimpl->parse_string(is, ws);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+}
+#endif
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_wiarchive_impl<Archive>::load(char * s){
+    std::wstring ws;
+    bool result = gimpl->parse_string(is, ws);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    copy_to_ptr(s, ws);
+}
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_wiarchive_impl<Archive>::load(wchar_t * ws){
+    std::wstring twstring;
+    bool result = gimpl->parse_string(is, twstring);
+    if(! result)
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    std::memcpy(ws, twstring.c_str(), twstring.size());
+    ws[twstring.size()] = L'\0';
+}
+#endif
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_wiarchive_impl<Archive>::load_override(class_name_type & t, int){
+    const std::wstring & ws = gimpl->rv.class_name;
+    if(ws.size() > BOOST_SERIALIZATION_MAX_KEY_SIZE - 1)
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::invalid_class_name)
+        );
+    copy_to_ptr(t, ws);
+}
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_wiarchive_impl<Archive>::init(){
+    gimpl->init(is);
+    this->set_library_version(
+        library_version_type(gimpl->rv.version)
+    );
+}
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY())
+xml_wiarchive_impl<Archive>::xml_wiarchive_impl(
+    std::wistream &is_,
+    unsigned int flags
+) :
+    basic_text_iprimitive<std::wistream>(
+        is_, 
+        true // don't change the codecvt - use the one below
+    ),
+    basic_xml_iarchive<Archive>(flags),
+    gimpl(new xml_wgrammar())
+{
+    if(0 == (flags & no_codecvt)){
+        archive_locale.reset(
+            add_facet(
+                std::locale::classic(),
+                new boost::archive::detail::utf8_codecvt_facet
+            )
+        );
+        is.imbue(* archive_locale);
+    }
+    if(0 == (flags & no_header)){
+        BOOST_TRY{
+            this->init();
+        }
+        BOOST_CATCH(...){
+            delete gimpl;
+            #ifndef BOOST_NO_EXCEPTIONS
+                throw; // re-throw
+            #endif
+        }
+        BOOST_CATCH_END
+    }
+}
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY())
+xml_wiarchive_impl<Archive>::~xml_wiarchive_impl(){
+    if(0 == (this->get_flags() & no_header)){
+        BOOST_TRY{
+            gimpl->windup(is);
+        }
+        BOOST_CATCH(...){}
+        BOOST_CATCH_END
+    }
+    delete gimpl;
+}
+
+} // namespace archive
+} // namespace boost
+
+#endif  // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/archive/impl/xml_woarchive_impl.ipp b/SRC/Serialization/archive/impl/xml_woarchive_impl.ipp
new file mode 100755
index 0000000..be816cb
--- /dev/null
+++ b/SRC/Serialization/archive/impl/xml_woarchive_impl.ipp
@@ -0,0 +1,160 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_woarchive_impl.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_STD_WSTREAMBUF
+
+#include <ostream>
+#include <string>
+#include <algorithm>
+#include <locale>
+
+#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings 
+                            // for BOOST_DEDUCED_TYPENAME
+#include <cstring> // strlen
+#include <cstdlib> // mbtowc
+#include <cwchar>  // wcslen
+
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::strlen; 
+    #if ! defined(BOOST_NO_INTRINSIC_WCHAR_T)
+        using ::mbtowc; 
+        using ::wcslen;
+    #endif
+} // namespace std
+#endif
+
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <Serialization/archive/iterators/xml_escape.hpp>
+#include <Serialization/archive/iterators/wchar_from_mb.hpp>
+#include <Serialization/archive/iterators/ostream_iterator.hpp>
+#include <Serialization/archive/iterators/dataflow_exception.hpp>
+
+#include <Serialization/archive/add_facet.hpp>
+#include <Serialization/archive/detail/utf8_codecvt_facet.hpp>
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// implemenations of functions specific to wide char archives
+
+// copy chars to output escaping to xml and widening characters as we go
+template<class InputIterator>
+void save_iterator(std::wostream &os, InputIterator begin, InputIterator end){
+    typedef iterators::wchar_from_mb<
+        iterators::xml_escape<InputIterator>
+    > xmbtows;
+    std::copy(
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(begin)),
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(end)),
+        boost::archive::iterators::ostream_iterator<wchar_t>(os)
+    );
+}
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_woarchive_impl<Archive>::save(const std::string & s){
+    // note: we don't use s.begin() and s.end() because dinkumware
+    // doesn't have string::value_type defined. So use a wrapper
+    // around these values to implement the definitions.
+    const char * begin = s.data();
+    const char * end = begin + s.size();
+    save_iterator(os, begin, end);
+}
+
+#ifndef BOOST_NO_STD_WSTRING
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_woarchive_impl<Archive>::save(const std::wstring & ws){
+#if 0
+    typedef iterators::xml_escape<std::wstring::const_iterator> xmbtows;
+    std::copy(
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.begin())),
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.end())),
+        boost::archive::iterators::ostream_iterator<wchar_t>(os)
+    );
+#endif
+    typedef iterators::xml_escape<const wchar_t *> xmbtows;
+    std::copy(
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data())),
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws.data() + ws.size())),
+        boost::archive::iterators::ostream_iterator<wchar_t>(os)
+    );
+}
+#endif //BOOST_NO_STD_WSTRING
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_woarchive_impl<Archive>::save(const char * s){
+   save_iterator(os, s, s + std::strlen(s));
+}
+
+#ifndef BOOST_NO_INTRINSIC_WCHAR_T
+template<class Archive>
+BOOST_WARCHIVE_DECL(void)
+xml_woarchive_impl<Archive>::save(const wchar_t * ws){
+    os << ws;
+    typedef iterators::xml_escape<const wchar_t *> xmbtows;
+    std::copy(
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws)),
+        xmbtows(BOOST_MAKE_PFTO_WRAPPER(ws + std::wcslen(ws))),
+        boost::archive::iterators::ostream_iterator<wchar_t>(os)
+    );
+}
+#endif
+
+template<class Archive>
+BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY())
+xml_woarchive_impl<Archive>::xml_woarchive_impl(
+    std::wostream & os_,
+    unsigned int flags
+) :
+    basic_text_oprimitive<std::wostream>(
+        os_,
+        true // don't change the codecvt - use the one below
+    ),
+    basic_xml_oarchive<Archive>(flags)
+{
+    // Standard behavior is that imbue can be called
+    // a) before output is invoked or
+    // b) after flush has been called.  This prevents one-to-many
+    // transforms (such as one to many transforms from getting
+    // mixed up.  Unfortunately, STLPort doesn't respect b) above
+    // so the restoration of the original archive locale done by
+    // the locale_saver doesn't get processed,
+    // before the current one is destroyed.
+    // so the codecvt doesn't get replaced with the orginal
+    // so closing the stream invokes codecvt::do_unshift
+    // so it crashes because the corresponding locale that contained
+    // the codecvt isn't around any more.
+    // we can hack around this by using a static codecvt that never
+    // gets destroyed.
+    if(0 == (flags & no_codecvt)){
+        boost::archive::detail::utf8_codecvt_facet *pfacet;
+        #if defined(__SGI_STL_PORT)
+            static boost::archive::detail::utf8_codecvt_facet 
+                facet(static_cast<size_t>(1));
+            pfacet = & facet;
+        #else
+            pfacet = new boost::archive::detail::utf8_codecvt_facet;
+        #endif
+        archive_locale.reset(add_facet(std::locale::classic(), pfacet));
+        os.imbue(* archive_locale);
+    }
+    if(0 == (flags & no_header))
+        this->init();
+}
+
+} // namespace archive
+} // namespace boost
+
+#endif //BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/archive/iterators/base64_from_binary.hpp b/SRC/Serialization/archive/iterators/base64_from_binary.hpp
new file mode 100755
index 0000000..9bfa3b4
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/base64_from_binary.hpp
@@ -0,0 +1,112 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP
+#define BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// base64_from_binary.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <cstddef> // size_t
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <Serialization/pfto.hpp>
+
+#include <boost/iterator/transform_iterator.hpp>
+#include <Serialization/archive/iterators/dataflow_exception.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// convert binary integers to base64 characters
+
+namespace detail {
+
+template<class CharType>
+struct from_6_bit {
+    typedef CharType result_type;
+    CharType operator()(CharType t) const{
+        const char * lookup_table = 
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+            "abcdefghijklmnopqrstuvwxyz"
+            "0123456789"
+            "+/";
+        BOOST_ASSERT(t < 64);
+        return lookup_table[static_cast<size_t>(t)];
+    }
+};
+
+} // namespace detail
+
+// note: what we would like to do is
+// template<class Base, class CharType = BOOST_DEDUCED_TYPENAME Base::value_type>
+//  typedef transform_iterator<
+//      from_6_bit<CharType>,
+//      transform_width<Base, 6, sizeof(Base::value_type) * 8, CharType>
+//  > base64_from_binary;
+// but C++ won't accept this.  Rather than using a "type generator" and
+// using a different syntax, make a derivation which should be equivalent.
+//
+// Another issue addressed here is that the transform_iterator doesn't have
+// a templated constructor.  This makes it incompatible with the dataflow
+// ideal.  This is also addressed here.
+
+//template<class Base, class CharType = BOOST_DEDUCED_TYPENAME Base::value_type>
+template<
+    class Base, 
+    class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
+>
+class base64_from_binary : 
+    public transform_iterator<
+        detail::from_6_bit<CharType>,
+        Base
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef transform_iterator<
+        BOOST_DEDUCED_TYPENAME detail::from_6_bit<CharType>,
+        Base
+    > super_t;
+
+public:
+    // make composible buy using templated constructor
+    template<class T>
+    base64_from_binary(BOOST_PFTO_WRAPPER(T) start) :
+        super_t(
+            Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start))),
+            detail::from_6_bit<CharType>()
+        )
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    base64_from_binary(const base64_from_binary & rhs) : 
+        super_t(
+            Base(rhs.base_reference()),
+            detail::from_6_bit<CharType>()
+        )
+    {}
+//    base64_from_binary(){};
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_BASE64_FROM_BINARY_HPP
diff --git a/SRC/Serialization/archive/iterators/binary_from_base64.hpp b/SRC/Serialization/archive/iterators/binary_from_base64.hpp
new file mode 100755
index 0000000..5f5fd3a
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/binary_from_base64.hpp
@@ -0,0 +1,120 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP
+#define BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_from_base64.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/pfto.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/iterator/transform_iterator.hpp>
+#include <Serialization/archive/iterators/dataflow_exception.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// convert base64 characters to binary data
+
+namespace detail {
+
+template<class CharType>
+struct to_6_bit {
+    typedef CharType result_type;
+    CharType operator()(CharType t) const{
+        const signed char lookup_table[] = {
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
+            52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,
+            -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
+            15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
+            -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
+            41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1
+        };
+        // metrowerks trips this assertion - how come?
+        #if ! defined(__MWERKS__)
+        BOOST_STATIC_ASSERT(128 == sizeof(lookup_table));
+        #endif
+        signed char value = -1;
+        if((unsigned)t <= 127)
+            value = lookup_table[(unsigned)t];
+        if(-1 == value)
+            boost::serialization::throw_exception(
+                dataflow_exception(dataflow_exception::invalid_base64_character)
+            );
+        return value;
+    }
+};
+
+} // namespace detail
+
+// note: what we would like to do is
+// template<class Base, class CharType = BOOST_DEDUCED_TYPENAME Base::value_type>
+//  typedef transform_iterator<
+//      from_6_bit<CharType>,
+//      transform_width<Base, 6, sizeof(Base::value_type) * 8, CharType>
+//  > base64_from_binary;
+// but C++ won't accept this.  Rather than using a "type generator" and
+// using a different syntax, make a derivation which should be equivalent.
+//
+// Another issue addressed here is that the transform_iterator doesn't have
+// a templated constructor.  This makes it incompatible with the dataflow
+// ideal.  This is also addressed here.
+
+template<
+    class Base, 
+    class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
+>
+class binary_from_base64 : public
+    transform_iterator<
+        detail::to_6_bit<CharType>,
+        Base
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef transform_iterator<
+        detail::to_6_bit<CharType>,
+        Base
+    > super_t;
+public:
+    // make composible buy using templated constructor
+    template<class T>
+    binary_from_base64(BOOST_PFTO_WRAPPER(T)  start) :
+        super_t(
+            Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start))), 
+            detail::to_6_bit<CharType>()
+        )
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    binary_from_base64(const binary_from_base64 & rhs) : 
+        super_t(
+            Base(rhs.base_reference()),
+            detail::to_6_bit<CharType>()
+        )
+    {}
+//    binary_from_base64(){};
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_BINARY_FROM_BASE64_HPP
diff --git a/SRC/Serialization/archive/iterators/dataflow_exception.hpp b/SRC/Serialization/archive/iterators/dataflow_exception.hpp
new file mode 100755
index 0000000..ac891a3
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/dataflow_exception.hpp
@@ -0,0 +1,80 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP
+#define BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// dataflow_exception.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_EXCEPTIONS
+#include <exception>
+#endif //BOOST_NO_EXCEPTIONS
+
+#include <boost/assert.hpp>
+
+namespace boost {
+namespace archive {
+namespace iterators {
+
+//////////////////////////////////////////////////////////////////////
+// exceptions thrown by dataflows
+//
+class dataflow_exception : public std::exception
+{
+public:
+    typedef enum {
+        invalid_6_bitcode,
+        invalid_base64_character,
+        invalid_xml_escape_sequence,
+        comparison_not_permitted,
+        invalid_conversion,
+        other_exception
+    } exception_code;
+    exception_code code;
+
+    dataflow_exception(exception_code c = other_exception) : code(c)
+    {}
+
+    virtual const char *what( ) const throw( )
+    {
+        const char *msg = "unknown exception code";
+        switch(code){
+        case invalid_6_bitcode:
+            msg = "attempt to encode a value > 6 bits";
+            break;
+        case invalid_base64_character:
+            msg = "attempt to decode a value not in base64 char set";
+            break;
+        case invalid_xml_escape_sequence:
+            msg = "invalid xml escape_sequence";
+            break;
+        case comparison_not_permitted:
+            msg = "cannot invoke iterator comparison now";
+            break;
+        case invalid_conversion:
+            msg = "invalid multbyte/wide char conversion";
+            break;
+        default:
+            BOOST_ASSERT(false);
+            break;
+        }
+        return msg;
+    }
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif //BOOST_ARCHIVE_ITERATORS_DATAFLOW_EXCEPTION_HPP
diff --git a/SRC/Serialization/archive/iterators/escape.hpp b/SRC/Serialization/archive/iterators/escape.hpp
new file mode 100755
index 0000000..5114e55
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/escape.hpp
@@ -0,0 +1,115 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP
+#define BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// escape.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <cstddef> // NULL
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// insert escapes into text
+
+template<class Derived, class Base>
+class escape : 
+    public boost::iterator_adaptor<
+        Derived, 
+        Base, 
+        BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type,
+        single_pass_traversal_tag,
+        BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
+    >
+{
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type base_value_type;
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<Base>::type reference_type;
+    friend class boost::iterator_core_access;
+
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor<
+        Derived, 
+        Base, 
+        base_value_type,
+        single_pass_traversal_tag,
+        base_value_type
+    > super_t;
+
+    typedef escape<Derived, Base> this_t;
+
+    void dereference_impl() {
+        m_current_value = static_cast<Derived *>(this)->fill(m_bnext, m_bend);
+        m_full = true;
+    }
+
+    //Access the value referred to 
+    reference_type dereference() const {
+        if(!m_full)
+            const_cast<this_t *>(this)->dereference_impl();
+        return m_current_value;
+    }
+
+    bool equal(const this_t & rhs) const {
+        if(m_full){
+            if(! rhs.m_full)
+                const_cast<this_t *>(& rhs)->dereference_impl();
+        }
+        else{
+            if(rhs.m_full)
+                const_cast<this_t *>(this)->dereference_impl();
+        }
+        if(m_bnext != rhs.m_bnext)
+            return false;
+        if(this->base_reference() != rhs.base_reference())
+            return false;
+        return true;
+    }
+
+   void increment(){
+        if(++m_bnext < m_bend){
+            m_current_value = *m_bnext;
+            return;
+        }
+        ++(this->base_reference());
+        m_bnext = NULL;
+        m_bend = NULL;
+        m_full = false;
+    }
+
+    // buffer to handle pending characters
+    const base_value_type *m_bnext;
+    const base_value_type *m_bend;
+    bool m_full;
+    base_value_type m_current_value;
+public:
+    escape(Base base) : 
+        super_t(base),
+        m_bnext(NULL),
+        m_bend(NULL),
+        m_full(false)
+    {
+    }
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_ESCAPE_HPP
diff --git a/SRC/Serialization/archive/iterators/insert_linebreaks.hpp b/SRC/Serialization/archive/iterators/insert_linebreaks.hpp
new file mode 100755
index 0000000..51e0a79
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/insert_linebreaks.hpp
@@ -0,0 +1,101 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP
+#define BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// insert_linebreaks.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ using ::memcpy; }
+#endif
+
+#include <Serialization/pfto.hpp>
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// insert line break every N characters
+template<
+    class Base, 
+    int N, 
+    class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type
+>
+class insert_linebreaks : 
+    public iterator_adaptor<
+        insert_linebreaks<Base, N, CharType>,
+        Base,
+        CharType,
+        single_pass_traversal_tag,
+        CharType
+    >
+{
+private:
+    friend class boost::iterator_core_access;
+    typedef iterator_adaptor<
+        insert_linebreaks<Base, N, CharType>,
+        Base,
+        CharType,
+        single_pass_traversal_tag,
+        CharType
+    > super_t;
+
+    bool equal(const insert_linebreaks<Base, N, CharType> & rhs) const {
+        return
+//            m_count == rhs.m_count
+//            && base_reference() == rhs.base_reference()
+            this->base_reference() == rhs.base_reference()
+        ;
+    }
+
+    void increment() {
+        if(m_count == N){
+            m_count = 0;
+            return;
+        }
+        ++m_count;
+        ++(this->base_reference());
+    }
+    CharType dereference() const {
+        if(m_count == N)
+            return '\n';
+        return * (this->base_reference());
+    }
+    unsigned int m_count;
+public:
+    // make composible buy using templated constructor
+    template<class T>
+    insert_linebreaks(BOOST_PFTO_WRAPPER(T)  start) :
+        super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))),
+        m_count(0)
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    insert_linebreaks(const insert_linebreaks & rhs) : 
+        super_t(rhs.base_reference()),
+        m_count(rhs.m_count)
+    {}
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_INSERT_LINEBREAKS_HPP
diff --git a/SRC/Serialization/archive/iterators/istream_iterator.hpp b/SRC/Serialization/archive/iterators/istream_iterator.hpp
new file mode 100755
index 0000000..92672e6
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/istream_iterator.hpp
@@ -0,0 +1,95 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP
+#define BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// istream_iterator.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// note: this is a custom version of the standard istream_iterator.
+// This is necessary as the standard version doesn't work as expected
+// for wchar_t based streams on systems for which wchar_t not a true
+// type but rather a synonym for some integer type.
+
+#include <cstddef> // NULL
+#include <istream>
+#include <boost/iterator/iterator_facade.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+// given a type, make an input iterator based on a pointer to that type
+template<class Elem = char>
+class istream_iterator :  
+    public boost::iterator_facade<
+        istream_iterator<Elem>,
+        Elem,
+        std::input_iterator_tag,
+        Elem
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef istream_iterator this_t ;
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_facade<
+        istream_iterator<Elem>,
+        Elem,
+        std::input_iterator_tag,
+        Elem
+    > super_t;
+    typedef BOOST_DEDUCED_TYPENAME std::basic_istream<Elem> istream_type;
+ 
+    //Access the value referred to 
+    Elem dereference() const {
+        return m_current_value;
+    }
+
+    bool equal(const this_t & rhs) const {
+        // note: only  works for comparison against end of stream
+        return m_istream == rhs.m_istream;
+    }
+
+    void increment(){
+        if(NULL != m_istream){
+            m_current_value = static_cast<Elem>(m_istream->get());
+            if(! m_istream->good()){
+                const_cast<this_t *>(this)->m_istream = NULL;
+            }
+        }
+    }
+
+    istream_type *m_istream;
+    Elem m_current_value;
+public:
+    istream_iterator(istream_type & is) :
+        m_istream(& is)
+    {
+        increment();
+    }
+
+    istream_iterator() :
+        m_istream(NULL)
+    {}
+
+    istream_iterator(const istream_iterator<Elem> & rhs) :
+        m_istream(rhs.m_istream),
+        m_current_value(rhs.m_current_value)
+    {}
+
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_ISTREAM_ITERATOR_HPP
diff --git a/SRC/Serialization/archive/iterators/mb_from_wchar.hpp b/SRC/Serialization/archive/iterators/mb_from_wchar.hpp
new file mode 100755
index 0000000..7790cbf
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/mb_from_wchar.hpp
@@ -0,0 +1,136 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP
+#define BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// mb_from_wchar.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <cstddef> // size_t
+#include <cstdlib> // for wctomb()
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+    using ::wctomb;
+} // namespace std
+#endif
+
+#include <Serialization/pfto.hpp>
+#include <boost/iterator/iterator_adaptor.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// class used by text archives to translate wide strings and to char
+// strings of the currently selected locale
+template<class Base>    // the input iterator
+class mb_from_wchar
+    : public boost::iterator_adaptor<
+        mb_from_wchar<Base>, 
+        Base, 
+        wchar_t,
+        single_pass_traversal_tag,
+        char
+    >
+{
+    friend class boost::iterator_core_access;
+
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor<
+        mb_from_wchar<Base>, 
+        Base, 
+        wchar_t,
+        single_pass_traversal_tag,
+        char
+    > super_t;
+
+    typedef mb_from_wchar<Base> this_t;
+
+    char dereference_impl() {
+        if(! m_full){
+            fill();
+            m_full = true;
+        }
+        return m_buffer[m_bnext];
+    }
+    char dereference() const {
+        return (const_cast<this_t *>(this))->dereference_impl();
+    }
+
+    // test for iterator equality
+    bool equal(const mb_from_wchar<Base> & rhs) const {
+        // once the value is filled, the base_reference has been incremented
+        // so don't permit comparison anymore.
+        return 
+            0 == m_bend
+            && 0 == m_bnext
+            && this->base_reference() == rhs.base_reference()
+        ;
+    }
+
+    void fill(){
+        wchar_t value = * this->base_reference();
+        #if (defined(__MINGW32__) && ((__MINGW32_MAJOR_VERSION > 3) \
+        || ((__MINGW32_MAJOR_VERSION == 3) && (__MINGW32_MINOR_VERSION >= 8))))
+        m_bend = std::wcrtomb(m_buffer, value, 0);
+        #else
+        m_bend = std::wctomb(m_buffer, value);
+        #endif
+        BOOST_ASSERT(-1 != m_bend);
+        BOOST_ASSERT((std::size_t)m_bend <= sizeof(m_buffer));
+        BOOST_ASSERT(m_bend > 0);
+        m_bnext = 0;
+    }
+
+    void increment(){
+        if(++m_bnext < m_bend)
+            return;
+        m_bend = 
+        m_bnext = 0;
+        ++(this->base_reference());
+        m_full = false;
+    }
+
+    // buffer to handle pending characters
+    int m_bend;
+    int m_bnext;
+    char m_buffer[9];
+    bool m_full;
+
+public:
+    // make composible buy using templated constructor
+    template<class T>
+    mb_from_wchar(BOOST_PFTO_WRAPPER(T) start) :
+        super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))),
+        m_bend(0),
+        m_bnext(0),
+        m_full(false)
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    mb_from_wchar(const mb_from_wchar & rhs) : 
+        super_t(rhs.base_reference()),
+        m_bend(rhs.m_bend),
+        m_bnext(rhs.m_bnext),
+        m_full(rhs.m_full)
+    {}
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_MB_FROM_WCHAR_HPP
diff --git a/SRC/Serialization/archive/iterators/ostream_iterator.hpp b/SRC/Serialization/archive/iterators/ostream_iterator.hpp
new file mode 100755
index 0000000..791529f
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/ostream_iterator.hpp
@@ -0,0 +1,83 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP
+#define BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// ostream_iterator.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// note: this is a custom version of the standard ostream_iterator.
+// This is necessary as the standard version doesn't work as expected
+// for wchar_t based streams on systems for which wchar_t not a true
+// type but rather a synonym for some integer type.
+
+#include <ostream>
+#include <boost/iterator/iterator_facade.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+// given a type, make an input iterator based on a pointer to that type
+template<class Elem>
+class ostream_iterator :  
+    public boost::iterator_facade<
+        ostream_iterator<Elem>,
+        Elem,
+        std::output_iterator_tag,
+        ostream_iterator<Elem> &
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef ostream_iterator this_t ;
+    typedef Elem char_type;
+    typedef std::basic_ostream<char_type> ostream_type;
+
+    //emulate the behavior of std::ostream 
+    ostream_iterator & dereference() const {
+        return const_cast<ostream_iterator &>(*this);
+    }
+    bool equal(const this_t & rhs) const {
+        return m_ostream == rhs.m_ostream;
+    }
+    void increment(){}
+protected:
+    ostream_type *m_ostream;
+    void put_val(char_type e){
+        if(NULL != m_ostream){
+            m_ostream->put(e);
+            if(! m_ostream->good())
+                m_ostream = NULL;
+        }
+    }
+public:
+    this_t & operator=(char_type c){
+        put_val(c);
+        return *this;
+    }
+    ostream_iterator(ostream_type & os) :
+        m_ostream (& os)
+    {}
+    ostream_iterator() :
+        m_ostream (NULL)
+    {}
+    ostream_iterator(const ostream_iterator & rhs) :
+        m_ostream (rhs.m_ostream)
+    {}
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_OSTREAM_ITERATOR_HPP
diff --git a/SRC/Serialization/archive/iterators/remove_whitespace.hpp b/SRC/Serialization/archive/iterators/remove_whitespace.hpp
new file mode 100755
index 0000000..304840e
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/remove_whitespace.hpp
@@ -0,0 +1,169 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP
+#define BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// remove_whitespace.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+
+#include <Serialization/pfto.hpp>
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/filter_iterator.hpp>
+
+//#include <boost/detail/workaround.hpp>
+//#if ! BOOST_WORKAROUND(BOOST_MSVC, <=1300)
+
+// here is the default standard implementation of the functor used
+// by the filter iterator to remove spaces.  Unfortunately usage
+// of this implementation in combination with spirit trips a bug
+// VC 6.5.  The only way I can find to work around it is to 
+// implement a special non-standard version for this platform
+
+#ifndef BOOST_NO_CWCTYPE
+#include <cwctype> // iswspace
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ using ::iswspace; }
+#endif
+#endif
+
+#include <cctype> // isspace
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ using ::isspace; }
+#endif
+
+#if defined(__STD_RWCOMPILER_H__) || defined(_RWSTD_VER)
+// this is required for the RW STL on Linux and Tru64.
+#undef isspace
+#undef iswspace
+#endif
+
+//#endif // BOOST_WORKAROUND
+
+namespace { // anonymous
+
+template<class CharType>
+struct remove_whitespace_predicate;
+
+template<>
+struct remove_whitespace_predicate<char>
+{
+    bool operator()(unsigned char t){
+        return ! std::isspace(t);
+    }
+};
+
+#ifndef BOOST_NO_CWCHAR
+template<>
+struct remove_whitespace_predicate<wchar_t>
+{
+    bool operator()(wchar_t t){
+        return ! std::iswspace(t);
+    }
+};
+#endif
+
+} // namespace anonymous
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// convert base64 file data (including whitespace and padding) to binary
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+// custom version of filter iterator which doesn't look ahead further than
+// necessary
+
+template<class Predicate, class Base>
+class filter_iterator
+    : public boost::iterator_adaptor<
+        filter_iterator<Predicate, Base>,
+        Base,
+        use_default,
+        single_pass_traversal_tag
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor<
+        filter_iterator<Predicate, Base>,
+        Base,
+        use_default,
+        single_pass_traversal_tag
+    > super_t;
+    typedef filter_iterator<Predicate, Base> this_t;
+    typedef BOOST_DEDUCED_TYPENAME super_t::reference reference_type;
+
+    reference_type dereference_impl(){
+        if(! m_full){
+            while(! m_predicate(* this->base_reference()))
+                ++(this->base_reference());
+            m_full = true;
+        }
+        return * this->base_reference();
+    }
+
+    reference_type dereference() const {
+        return const_cast<this_t *>(this)->dereference_impl();
+    }
+
+    Predicate m_predicate;
+    bool m_full;
+public:
+    // note: this function is public only because comeau compiler complained
+    // I don't know if this is because the compiler is wrong or what
+    void increment(){
+        m_full = false;
+        ++(this->base_reference());
+    }
+    filter_iterator(Base start) : 
+        super_t(start), 
+        m_full(false)
+    {}
+    filter_iterator(){}
+};
+
+template<class Base>
+class remove_whitespace : 
+    public filter_iterator<
+        remove_whitespace_predicate<BOOST_DEDUCED_TYPENAME Base::value_type>,
+        Base
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef filter_iterator<
+        remove_whitespace_predicate<BOOST_DEDUCED_TYPENAME Base::value_type>,
+        Base
+    > super_t;
+public:
+//    remove_whitespace(){} // why is this needed?
+    // make composible buy using templated constructor
+    template<class T>
+    remove_whitespace(BOOST_PFTO_WRAPPER(T) start) :
+        super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start))))
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    remove_whitespace(const remove_whitespace & rhs) : 
+        super_t(rhs.base_reference())
+    {}
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_REMOVE_WHITESPACE_HPP
diff --git a/SRC/Serialization/archive/iterators/transform_width.hpp b/SRC/Serialization/archive/iterators/transform_width.hpp
new file mode 100755
index 0000000..31f8ebc
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/transform_width.hpp
@@ -0,0 +1,170 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
+#define BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// transform_width.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// iterator which takes elements of x bits and returns elements of y bits.
+// used to change streams of 8 bit characters into streams of 6 bit characters.
+// and vice-versa for implementing base64 encodeing/decoding. Be very careful
+// when using and end iterator.  end is only reliable detected when the input
+// stream length is some common multiple of x and y.  E.G. Base64 6 bit
+// character and 8 bit bytes. Lowest common multiple is 24 => 4 6 bit characters
+// or 3 8 bit characters
+
+#include <algorithm>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME & PTFO
+#include <Serialization/pfto.hpp>
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <boost/iterator/iterator_traits.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// class used by text archives to translate char strings to wchar_t
+// strings of the currently selected locale
+template<
+    class Base, 
+    int BitsOut, 
+    int BitsIn, 
+    class CharType = BOOST_DEDUCED_TYPENAME boost::iterator_value<Base>::type // output character
+>
+class transform_width : 
+    public boost::iterator_adaptor<
+        transform_width<Base, BitsOut, BitsIn, CharType>,
+        Base,
+        CharType,
+        single_pass_traversal_tag,
+        CharType
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor<
+        transform_width<Base, BitsOut, BitsIn, CharType>,
+        Base,
+        CharType,
+        single_pass_traversal_tag,
+        CharType
+    > super_t;
+
+    typedef transform_width<Base, BitsOut, BitsIn, CharType> this_t;
+    typedef BOOST_DEDUCED_TYPENAME iterator_value<Base>::type base_value_type;
+
+    CharType fill();
+
+    CharType dereference_impl(){
+        if(! m_full){
+            m_current_value = fill();
+            m_full = true;
+        }
+        return m_current_value;
+    }
+
+    CharType dereference() const {
+        return const_cast<this_t *>(this)->dereference_impl();
+    }
+
+    // test for iterator equality
+    bool equal(const this_t & rhs) const {
+        return
+            this->base_reference() == rhs.base_reference();
+        ;
+    }
+
+    void increment(){
+        m_displacement += BitsOut;
+
+        while(m_displacement >= BitsIn){
+            m_displacement -= BitsIn;
+            if(0 == m_displacement)
+                m_bufferfull = false;
+            if(! m_bufferfull){
+                // note: suspect that this is not invoked for borland
+                ++(this->base_reference());
+            }
+        }
+        m_full = false;
+    }
+
+    CharType m_current_value;
+    // number of bits left in current input character buffer
+    unsigned int m_displacement;
+    base_value_type m_buffer;
+    // flag to current output character is ready - just used to save time
+    bool m_full;
+    // flag to indicate that m_buffer has data
+    bool m_bufferfull;
+
+public:
+    // make composible buy using templated constructor
+    template<class T>
+    transform_width(BOOST_PFTO_WRAPPER(T) start) : 
+        super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))),
+        m_displacement(0),
+        m_full(false),
+        m_bufferfull(false)
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    transform_width(const transform_width & rhs) : 
+        super_t(rhs.base_reference()),
+        m_current_value(rhs.m_current_value),
+        m_displacement(rhs.m_displacement),
+        m_buffer(rhs.m_buffer),
+        m_full(rhs.m_full),
+        m_bufferfull(rhs.m_bufferfull)
+    {}
+};
+
+template<class Base, int BitsOut, int BitsIn, class CharType>
+CharType transform_width<Base, BitsOut, BitsIn, CharType>::fill(){
+    CharType retval = 0;
+    unsigned int missing_bits = BitsOut;
+    for(;;){
+        unsigned int bcount;
+        if(! m_bufferfull){
+            m_buffer = * this->base_reference();
+            m_bufferfull = true;
+            bcount = BitsIn;
+        }
+        else
+            bcount = BitsIn - m_displacement;
+        unsigned int i = (std::min)(bcount, missing_bits);
+        // shift interesting bits to least significant position
+        unsigned int j = m_buffer >> (bcount - i);
+        // strip off uninteresting bits
+        // (note presumption of two's complement arithmetic)
+        j &= ~(-(1 << i));
+        // append then interesting bits to the output value
+        retval <<= i;
+        retval |= j;
+        missing_bits -= i;
+        if(0 == missing_bits)
+            break;
+        // note: suspect that this is not invoked for borland 5.51
+        ++(this->base_reference());
+        m_bufferfull = false;
+    }
+    return retval;
+}
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_TRANSFORM_WIDTH_HPP
diff --git a/SRC/Serialization/archive/iterators/unescape.hpp b/SRC/Serialization/archive/iterators/unescape.hpp
new file mode 100755
index 0000000..d849dee
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/unescape.hpp
@@ -0,0 +1,91 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP
+#define BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// unescape.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#include <boost/iterator/iterator_adaptor.hpp>
+//#include <boost/iterator/iterator_traits.hpp>
+#include <boost/pointee.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// class used by text archives to translate char strings to wchar_t
+// strings of the currently selected locale
+template<class Derived, class Base>
+class unescape 
+    : public boost::iterator_adaptor<
+        unescape<Derived, Base>,
+        Base, 
+        BOOST_DEDUCED_TYPENAME pointee<Base>::type,
+        single_pass_traversal_tag,
+        BOOST_DEDUCED_TYPENAME pointee<Base>::type
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor<
+        unescape<Derived, Base>, 
+        Base, 
+        BOOST_DEDUCED_TYPENAME pointee<Base>::type,
+        single_pass_traversal_tag,
+        BOOST_DEDUCED_TYPENAME pointee<Base>::type
+    > super_t;
+
+    typedef unescape<Derived, Base> this_t;
+public:
+    typedef BOOST_DEDUCED_TYPENAME this_t::value_type value_type;
+    typedef BOOST_DEDUCED_TYPENAME this_t::reference reference;
+private:
+    value_type dereference_impl() {
+        if(! m_full){
+            m_current_value = static_cast<Derived *>(this)->drain();
+            m_full = true;
+        }
+        return m_current_value;
+    }
+
+    reference dereference() const {
+        return const_cast<this_t *>(this)->dereference_impl();
+    }
+
+    value_type m_current_value;
+    bool m_full;
+
+    void increment(){
+        ++(this->base_reference());
+        dereference_impl();
+        m_full = false;
+    };
+
+public:
+
+    unescape(Base base) : 
+        super_t(base),
+        m_full(false)
+    {}
+
+};
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_UNESCAPE_HPP
diff --git a/SRC/Serialization/archive/iterators/wchar_from_mb.hpp b/SRC/Serialization/archive/iterators/wchar_from_mb.hpp
new file mode 100755
index 0000000..aee4542
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/wchar_from_mb.hpp
@@ -0,0 +1,129 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
+#define BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// wchar_from_mb.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+#include <cctype>
+#include <cstddef> // size_t
+#include <cstdlib> // mblen
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::mblen; 
+    using ::mbtowc; 
+} // namespace std
+#endif
+
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <boost/iterator/iterator_adaptor.hpp>
+#include <Serialization/archive/iterators/dataflow_exception.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// class used by text archives to translate char strings to wchar_t
+// strings of the currently selected locale
+template<class Base>
+class wchar_from_mb 
+    : public boost::iterator_adaptor<
+        wchar_from_mb<Base>, 
+        Base, 
+        wchar_t,
+        single_pass_traversal_tag,
+        wchar_t
+    >
+{
+    friend class boost::iterator_core_access;
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_adaptor<
+        wchar_from_mb<Base>, 
+        Base, 
+        wchar_t,
+        single_pass_traversal_tag,
+        wchar_t
+    > super_t;
+
+    typedef wchar_from_mb<Base> this_t;
+
+    wchar_t drain();
+
+    wchar_t dereference_impl() {
+        if(! m_full){
+            m_current_value = drain();
+            m_full = true;
+        }
+        return m_current_value;
+    }
+
+    wchar_t dereference() const {
+        return const_cast<this_t *>(this)->dereference_impl();
+    }
+
+    void increment(){
+        dereference_impl();
+        m_full = false;
+        ++(this->base_reference());
+    };
+
+    wchar_t m_current_value;
+    bool m_full;
+
+public:
+    // make composible buy using templated constructor
+    template<class T>
+    wchar_from_mb(BOOST_PFTO_WRAPPER(T) start) : 
+        super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start)))),
+        m_full(false)
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    wchar_from_mb(const wchar_from_mb & rhs) : 
+        super_t(rhs.base_reference()),
+        m_full(rhs.m_full)
+    {}
+};
+
+template<class Base>
+wchar_t wchar_from_mb<Base>::drain(){
+    char buffer[9];
+    char * bptr = buffer;
+    char val;
+    for(std::size_t i = 0; i++ < (unsigned)MB_CUR_MAX;){
+        val = * this->base_reference();
+        *bptr++ = val;
+        int result = std::mblen(buffer, i);
+        if(-1 != result)
+            break;
+        ++(this->base_reference());
+    }
+    wchar_t retval;
+    int result = std::mbtowc(& retval, buffer, MB_CUR_MAX);
+    if(0 >= result)
+        boost::serialization::throw_exception(iterators::dataflow_exception(
+            iterators::dataflow_exception::invalid_conversion
+        ));
+    return retval;
+}
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_WCHAR_FROM_MB_HPP
diff --git a/SRC/Serialization/archive/iterators/xml_escape.hpp b/SRC/Serialization/archive/iterators/xml_escape.hpp
new file mode 100755
index 0000000..2461865
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/xml_escape.hpp
@@ -0,0 +1,125 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP
+#define BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_escape.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+#include <Serialization/pfto.hpp>
+
+#include <Serialization/archive/iterators/escape.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// insert escapes into xml text
+
+template<class Base>
+class xml_escape 
+    : public escape<xml_escape<Base>, Base>
+{
+    friend class boost::iterator_core_access;
+
+    typedef escape<xml_escape<Base>, Base> super_t;
+
+public:
+    char fill(const char * & bstart, const char * & bend);
+    wchar_t fill(const wchar_t * & bstart, const wchar_t * & bend);
+
+    template<class T>
+    xml_escape(BOOST_PFTO_WRAPPER(T) start) :
+        super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start))))
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    xml_escape(const xml_escape & rhs) : 
+        super_t(rhs.base_reference())
+    {}
+};
+
+template<class Base>
+char xml_escape<Base>::fill(
+    const char * & bstart, 
+    const char * & bend
+){
+    char current_value = * this->base_reference();
+    switch(current_value){
+    case '<':
+        bstart = "<";
+        bend = bstart + 4;
+        break;
+    case '>':
+        bstart = ">";
+        bend = bstart + 4;
+        break;
+    case '&':
+        bstart = "&";
+        bend = bstart + 5;
+        break;
+    case '"':
+        bstart = """;
+        bend = bstart + 6;
+        break;
+    case '\'':
+        bstart = "'";
+        bend = bstart + 6;
+        break;
+    default:
+        return current_value;
+    }
+    return *bstart;
+}
+
+template<class Base>
+wchar_t xml_escape<Base>::fill(
+    const wchar_t * & bstart, 
+    const wchar_t * & bend
+){
+    wchar_t current_value = * this->base_reference();
+    switch(current_value){
+    case '<':
+        bstart = L"<";
+        bend = bstart + 4;
+        break;
+    case '>':
+        bstart = L">";
+        bend = bstart + 4;
+        break;
+    case '&':
+        bstart = L"&";
+        bend = bstart + 5;
+        break;
+    case '"':
+        bstart = L""";
+        bend = bstart + 6;
+        break;
+    case '\'':
+        bstart = L"'";
+        bend = bstart + 6;
+        break;
+    default:
+        return current_value;
+    }
+    return *bstart;
+}
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_XML_ESCAPE_HPP
diff --git a/SRC/Serialization/archive/iterators/xml_unescape.hpp b/SRC/Serialization/archive/iterators/xml_unescape.hpp
new file mode 100755
index 0000000..6af44a4
--- /dev/null
+++ b/SRC/Serialization/archive/iterators/xml_unescape.hpp
@@ -0,0 +1,128 @@
+#ifndef BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP
+#define BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_unescape.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp> // for BOOST_DEDUCED_TYPENAME
+
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <Serialization/archive/iterators/unescape.hpp>
+#include <Serialization/archive/iterators/dataflow_exception.hpp>
+
+namespace boost { 
+namespace archive {
+namespace iterators {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// replace &??? xml escape sequences with the corresponding characters
+template<class Base>
+class xml_unescape 
+    : public unescape<xml_unescape<Base>, Base>
+{
+    friend class boost::iterator_core_access;
+    typedef xml_unescape<Base> this_t;
+    typedef unescape<this_t, Base> super_t;
+    typedef BOOST_DEDUCED_TYPENAME boost::iterator_reference<this_t> reference_type;
+
+    reference_type dereference() const {
+        return unescape<xml_unescape<Base>, Base>::dereference();
+    }
+public:
+    // workaround msvc 7.1 ICU crash
+    #if defined(BOOST_MSVC)
+        typedef int value_type;
+    #else
+        typedef BOOST_DEDUCED_TYPENAME this_t::value_type value_type;
+    #endif
+
+    void drain_residue(const char *literal);
+    value_type drain();
+
+    template<class T>
+    xml_unescape(BOOST_PFTO_WRAPPER(T) start) : 
+        super_t(Base(BOOST_MAKE_PFTO_WRAPPER(static_cast< T >(start))))
+    {}
+    // intel 7.1 doesn't like default copy constructor
+    xml_unescape(const xml_unescape & rhs) : 
+        super_t(rhs.base_reference())
+    {}
+};
+
+template<class Base>
+void xml_unescape<Base>::drain_residue(const char * literal){
+    do{
+        if(* literal != * ++(this->base_reference()))
+            boost::serialization::throw_exception(
+                dataflow_exception(
+                    dataflow_exception::invalid_xml_escape_sequence
+                )
+            );
+    }
+    while('\0' != * ++literal);
+}
+
+// note key constraint on this function is that can't "look ahead" any
+// more than necessary into base iterator.  Doing so would alter the base
+// iterator refenence which would make subsequent iterator comparisons
+// incorrect and thereby break the composiblity of iterators.
+template<class Base>
+BOOST_DEDUCED_TYPENAME xml_unescape<Base>::value_type 
+//int 
+xml_unescape<Base>::drain(){
+    value_type retval = * this->base_reference();
+    if('&' != retval){
+        return retval;
+    }
+    retval = * ++(this->base_reference());
+    switch(retval){
+    case 'l': // <
+        drain_residue("t;");
+        retval = '<';
+        break;
+    case 'g': // >
+        drain_residue("t;");
+        retval = '>';
+        break;
+    case 'a':
+        retval = * ++(this->base_reference());
+        switch(retval){
+        case 'p': // '
+            drain_residue("os;");
+            retval = '\'';
+            break;
+        case 'm': // &
+            drain_residue("p;");
+            retval = '&';
+            break;
+        }
+        break;
+    case 'q':
+        drain_residue("uot;");
+        retval = '"';
+        break;
+    }
+    return retval;
+}
+
+} // namespace iterators
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_ARCHIVE_ITERATORS_XML_UNESCAPE_HPP
diff --git a/SRC/Serialization/archive/polymorphic_binary_iarchive.hpp b/SRC/Serialization/archive/polymorphic_binary_iarchive.hpp
new file mode 100755
index 0000000..d0fd8f9
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_binary_iarchive.hpp
@@ -0,0 +1,54 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_binary_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <Serialization/archive/binary_iarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_iarchive_route.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class polymorphic_binary_iarchive : 
+    public detail::polymorphic_iarchive_route<naked_binary_iarchive>
+{
+public:
+    polymorphic_binary_iarchive(std::istream & is, unsigned int flags = 0) :
+        detail::polymorphic_iarchive_route<naked_binary_iarchive>(is, flags)
+    {}
+    ~polymorphic_binary_iarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_binary_iarchive
+)
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_BINARY_IARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_binary_oarchive.hpp b/SRC/Serialization/archive/polymorphic_binary_oarchive.hpp
new file mode 100755
index 0000000..26c7a9b
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_binary_oarchive.hpp
@@ -0,0 +1,43 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_binary_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <Serialization/archive/binary_oarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_oarchive_route.hpp>
+
+namespace boost { 
+namespace archive {
+
+typedef detail::polymorphic_oarchive_route<
+    binary_oarchive_impl<
+        naked_binary_oarchive, 
+        std::ostream::char_type, 
+        std::ostream::traits_type
+    >
+ > polymorphic_binary_oarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_binary_oarchive
+)
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_BINARY_OARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_iarchive.hpp b/SRC/Serialization/archive/polymorphic_iarchive.hpp
new file mode 100755
index 0000000..b9b7b07
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_iarchive.hpp
@@ -0,0 +1,181 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // std::size_t
+#include <climits> // ULONG_MAX 
+#include <string>
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+    using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/cstdint.hpp>
+
+#include <Serialization/pfto.hpp>
+#include <Serialization/archive/detail/iserializer.hpp>
+#include <Serialization/archive/detail/interface_iarchive.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+
+#include <Serialization/archive/detail/decl.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+template<class T>
+class shared_ptr;
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+namespace archive {
+namespace detail {
+    class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive;
+    class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_iarchive;
+}
+
+class polymorphic_iarchive;
+
+class polymorphic_iarchive_impl :
+    public detail::interface_iarchive<polymorphic_iarchive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_iarchive<polymorphic_iarchive>;
+    friend class load_access;
+#endif
+    // primitive types the only ones permitted by polymorphic archives
+    virtual void load(bool & t) = 0;
+
+    virtual void load(char & t) = 0;
+    virtual void load(signed char & t) = 0;
+    virtual void load(unsigned char & t) = 0;
+    #ifndef BOOST_NO_CWCHAR
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    virtual void load(wchar_t & t) = 0;
+    #endif
+    #endif
+    virtual void load(short & t) = 0;
+    virtual void load(unsigned short & t) = 0;
+    virtual void load(int & t) = 0;
+    virtual void load(unsigned int & t) = 0;
+    virtual void load(long & t) = 0;
+    virtual void load(unsigned long & t) = 0;
+
+    #if defined(BOOST_HAS_LONG_LONG)
+    virtual void load(boost::long_long_type & t) = 0;
+    virtual void load(boost::ulong_long_type & t) = 0;
+    #elif defined(BOOST_HAS_MS_INT64)
+    virtual void load(__int64 & t) = 0;
+    virtual void load(unsigned __int64 & t) = 0;
+    #endif
+
+    virtual void load(float & t) = 0;
+    virtual void load(double & t) = 0;
+
+    // string types are treated as primitives
+    virtual void load(std::string & t) = 0;
+    #ifndef BOOST_NO_STD_WSTRING
+    virtual void load(std::wstring & t) = 0;
+    #endif
+
+    // used for xml and other tagged formats
+    virtual void load_start(const char * name) = 0;
+    virtual void load_end(const char * name) = 0;
+    virtual void register_basic_serializer(const detail::basic_iserializer & bis) = 0;
+
+    // msvc and borland won't automatically pass these to the base class so
+    // make it explicit here
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int)
+    {
+        archive::load(* this->This(), t);
+    }
+    // special treatment for name-value pairs.
+    template<class T>
+    void load_override(
+        #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+        const
+        #endif
+        boost::serialization::nvp< T > & t,
+        int
+    ){
+        load_start(t.name());
+        archive::load(* this->This(), t.value());
+        load_end(t.name());
+    }
+protected:
+    virtual ~polymorphic_iarchive_impl(){};
+public:
+    // utility function implemented by all legal archives
+    virtual void set_library_version(library_version_type archive_library_version) = 0;
+    virtual library_version_type get_library_version() const = 0;
+    virtual unsigned int get_flags() const = 0;
+    virtual void delete_created_pointers() = 0;
+    virtual void reset_object_address(
+        const void * new_address,
+        const void * old_address
+    ) = 0;
+
+    virtual void load_binary(void * t, std::size_t size) = 0;
+
+    // these are used by the serialization library implementation.
+    virtual void load_object(
+        void *t,
+        const detail::basic_iserializer & bis
+    ) = 0;
+    virtual const detail::basic_pointer_iserializer * load_pointer(
+        void * & t,
+        const detail::basic_pointer_iserializer * bpis_ptr,
+        const detail::basic_pointer_iserializer * (*finder)(
+            const boost::serialization::extended_type_info & type
+        )
+    ) = 0;
+};
+
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+// note special treatment of shared_ptr. This type needs a special
+// structure associated with every archive.  We created a "mix-in"
+// class to provide this functionality.  Since shared_ptr holds a
+// special esteem in the boost library - we included it here by default.
+#include <Serialization/archive/shared_ptr_helper.hpp>
+
+namespace boost { 
+namespace archive {
+
+class polymorphic_iarchive : 
+    public polymorphic_iarchive_impl,
+    public detail::shared_ptr_helper
+{
+public:
+    virtual ~polymorphic_iarchive(){};
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::polymorphic_iarchive)
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/polymorphic_oarchive.hpp b/SRC/Serialization/archive/polymorphic_oarchive.hpp
new file mode 100755
index 0000000..da79f8c
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_oarchive.hpp
@@ -0,0 +1,159 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // size_t
+#include <climits> // ULONG_MAX 
+#include <string>
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{
+    using ::size_t;
+} // namespace std
+#endif
+
+#include <boost/cstdint.hpp>
+#include <Serialization/pfto.hpp>
+#include <Serialization/archive/detail/oserializer.hpp>
+#include <Serialization/archive/detail/interface_oarchive.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+
+#include <Serialization/archive/detail/decl.hpp>
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+template<class T>
+class shared_ptr;
+namespace serialization {
+    class extended_type_info;
+} // namespace serialization
+namespace archive {
+namespace detail {
+    class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oarchive;
+    class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) basic_oserializer;
+}
+
+class polymorphic_oarchive;
+
+class polymorphic_oarchive_impl :
+    public detail::interface_oarchive<polymorphic_oarchive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_oarchive<polymorphic_oarchive>;
+    friend class save_access;
+#endif
+    // primitive types the only ones permitted by polymorphic archives
+    virtual void save(const bool t) = 0;
+
+    virtual void save(const char t) = 0;
+    virtual void save(const signed char t) = 0;
+    virtual void save(const unsigned char t) = 0;
+    #ifndef BOOST_NO_CWCHAR
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    virtual void save(const wchar_t t) = 0;
+    #endif
+    #endif
+    virtual void save(const short t) = 0;
+    virtual void save(const unsigned short t) = 0;
+    virtual void save(const int t) = 0;
+    virtual void save(const unsigned int t) = 0;
+    virtual void save(const long t) = 0;
+    virtual void save(const unsigned long t) = 0;
+
+    #if defined(BOOST_HAS_LONG_LONG)
+    virtual void save(const boost::long_long_type t) = 0;
+    virtual void save(const boost::ulong_long_type t) = 0;
+    #elif defined(BOOST_HAS_MS_INT64)
+    virtual void save(const __int64 t) = 0;
+    virtual void save(const unsigned __int64 t) = 0;
+    #endif
+
+    virtual void save(const float t) = 0;
+    virtual void save(const double t) = 0;
+
+    // string types are treated as primitives
+    virtual void save(const std::string & t) = 0;
+    #ifndef BOOST_NO_STD_WSTRING
+    virtual void save(const std::wstring & t) = 0;
+    #endif
+
+    virtual void save_null_pointer() = 0;
+    // used for xml and other tagged formats
+    virtual void save_start(const char * name) = 0;
+    virtual void save_end(const char * name) = 0;
+    virtual void register_basic_serializer(const detail::basic_oserializer & bos) = 0;
+
+    virtual void end_preamble() = 0;
+
+    // msvc and borland won't automatically pass these to the base class so
+    // make it explicit here
+    template<class T>
+    void save_override(T & t, BOOST_PFTO int)
+    {
+        archive::save(* this->This(), t);
+    }
+    // special treatment for name-value pairs.
+    template<class T>
+    void save_override(
+                #ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+                const
+                #endif
+                ::boost::serialization::nvp< T > & t, int
+        ){
+        save_start(t.name());
+        archive::save(* this->This(), t.const_value());
+        save_end(t.name());
+    }
+protected:
+    virtual ~polymorphic_oarchive_impl(){};
+public:
+    // utility functions implemented by all legal archives
+    virtual unsigned int get_flags() const = 0;
+    virtual library_version_type get_library_version() const = 0;
+    virtual void save_binary(const void * t, std::size_t size) = 0;
+
+    virtual void save_object(
+        const void *x,
+        const detail::basic_oserializer & bos
+    ) = 0;
+    virtual void save_pointer(
+        const void * t,
+        const detail::basic_pointer_oserializer * bpos_ptr
+    ) = 0;
+};
+
+// note: preserve naming symmetry
+class polymorphic_oarchive : 
+    public polymorphic_oarchive_impl
+{
+public:
+    virtual ~polymorphic_oarchive(){};
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::polymorphic_oarchive)
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/polymorphic_text_iarchive.hpp b/SRC/Serialization/archive/polymorphic_text_iarchive.hpp
new file mode 100755
index 0000000..9784e7d
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_text_iarchive.hpp
@@ -0,0 +1,54 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_text_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <Serialization/archive/text_iarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_iarchive_route.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class polymorphic_text_iarchive : 
+    public detail::polymorphic_iarchive_route<naked_text_iarchive>
+{
+public:
+    polymorphic_text_iarchive(std::istream & is, unsigned int flags = 0) :
+        detail::polymorphic_iarchive_route<naked_text_iarchive>(is, flags)
+    {}
+    ~polymorphic_text_iarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_text_iarchive
+)
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_IARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_text_oarchive.hpp b/SRC/Serialization/archive/polymorphic_text_oarchive.hpp
new file mode 100755
index 0000000..47560fa
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_text_oarchive.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_text_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <Serialization/archive/text_oarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_oarchive_route.hpp>
+
+namespace boost { 
+namespace archive {
+
+typedef detail::polymorphic_oarchive_route<
+    text_oarchive_impl<naked_text_oarchive> 
+> polymorphic_text_oarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_text_oarchive
+)
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_OARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_text_wiarchive.hpp b/SRC/Serialization/archive/polymorphic_text_wiarchive.hpp
new file mode 100755
index 0000000..ce2fca1
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_text_wiarchive.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_text_wiarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <Serialization/archive/text_wiarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_iarchive_route.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class polymorphic_text_wiarchive : 
+    public detail::polymorphic_iarchive_route<naked_text_wiarchive>
+{
+public:
+    polymorphic_text_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        detail::polymorphic_iarchive_route<naked_text_wiarchive>(is, flags)
+    {}
+    ~polymorphic_text_wiarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_text_wiarchive
+)
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_WIARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_text_woarchive.hpp b/SRC/Serialization/archive/polymorphic_text_woarchive.hpp
new file mode 100755
index 0000000..2ff5ac4
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_text_woarchive.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_text_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <Serialization/archive/text_woarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_oarchive_route.hpp>
+
+namespace boost { 
+namespace archive {
+
+typedef detail::polymorphic_oarchive_route<
+        text_woarchive_impl<naked_text_woarchive> 
+> polymorphic_text_woarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_text_woarchive
+)
+
+#endif // BOOST_NO_STD_WSTREAMBUF 
+#endif // BOOST_ARCHIVE_POLYMORPHIC_TEXT_WOARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_xml_iarchive.hpp b/SRC/Serialization/archive/polymorphic_xml_iarchive.hpp
new file mode 100755
index 0000000..3d41772
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_xml_iarchive.hpp
@@ -0,0 +1,54 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_xml_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <Serialization/archive/xml_iarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_iarchive_route.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class polymorphic_xml_iarchive : 
+    public detail::polymorphic_iarchive_route<naked_xml_iarchive>
+{
+public:
+    polymorphic_xml_iarchive(std::istream & is, unsigned int flags = 0) :
+        detail::polymorphic_iarchive_route<naked_xml_iarchive>(is, flags)
+    {}
+    ~polymorphic_xml_iarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_xml_iarchive
+)
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_IARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_xml_oarchive.hpp b/SRC/Serialization/archive/polymorphic_xml_oarchive.hpp
new file mode 100755
index 0000000..74698d5
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_xml_oarchive.hpp
@@ -0,0 +1,39 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_xml_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <Serialization/archive/xml_oarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_oarchive_route.hpp>
+
+namespace boost { 
+namespace archive {
+
+typedef detail::polymorphic_oarchive_route<
+    xml_oarchive_impl<naked_xml_oarchive> 
+> polymorphic_xml_oarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_xml_oarchive
+)
+
+#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_OARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_xml_wiarchive.hpp b/SRC/Serialization/archive/polymorphic_xml_wiarchive.hpp
new file mode 100755
index 0000000..e5e7b57
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_xml_wiarchive.hpp
@@ -0,0 +1,50 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_xml_wiarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <Serialization/archive/xml_wiarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_iarchive_route.hpp>
+
+namespace boost { 
+namespace archive {
+
+class polymorphic_xml_wiarchive : 
+    public detail::polymorphic_iarchive_route<naked_xml_wiarchive>
+{
+public:
+    polymorphic_xml_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        detail::polymorphic_iarchive_route<naked_xml_wiarchive>(is, flags)
+    {}
+    ~polymorphic_xml_wiarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_xml_wiarchive
+)
+
+#endif // BOOST_NO_STD_WSTREAMBUF 
+#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_WIARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/polymorphic_xml_woarchive.hpp b/SRC/Serialization/archive/polymorphic_xml_woarchive.hpp
new file mode 100755
index 0000000..2ab3f20
--- /dev/null
+++ b/SRC/Serialization/archive/polymorphic_xml_woarchive.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP
+#define BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_xml_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <Serialization/archive/xml_woarchive.hpp>
+#include <Serialization/archive/detail/polymorphic_oarchive_route.hpp>
+
+namespace boost { 
+namespace archive {
+
+typedef detail::polymorphic_oarchive_route<
+        xml_woarchive_impl<naked_xml_woarchive> 
+> polymorphic_xml_woarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(
+    boost::archive::polymorphic_xml_woarchive
+)
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_POLYMORPHIC_XML_WOARCHIVE_HPP
+
diff --git a/SRC/Serialization/archive/shared_ptr_helper.hpp b/SRC/Serialization/archive/shared_ptr_helper.hpp
new file mode 100755
index 0000000..5af9761
--- /dev/null
+++ b/SRC/Serialization/archive/shared_ptr_helper.hpp
@@ -0,0 +1,219 @@
+#ifndef BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP
+#define BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// shared_ptr_helper.hpp: serialization for boost shared pointern
+
+// (C) Copyright 2004-2009 Robert Ramey, Martin Ecker and Takatoshi Kondo
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <set>
+#include <list>
+#include <utility>
+#include <cstddef> // NULL
+
+#include <boost/config.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <Serialization/type_info_implementation.hpp>
+#include <Serialization/shared_ptr_132.hpp>
+#include <Serialization/throw_exception.hpp>
+
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/archive/detail/decl.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last headern
+
+namespace boost_132 {
+    template<class T> class shared_ptr;
+}
+namespace boost {
+    template<class T> class shared_ptr;
+    namespace serialization {
+        class extended_type_info;
+        template<class Archive, class T>
+        inline void load(
+            Archive & ar,
+            boost::shared_ptr< T > &t,
+            const unsigned int file_version
+        );
+    }
+namespace archive{
+namespace detail {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// a common class for holding various types of shared pointers
+
+class shared_ptr_helper {
+    struct collection_type_compare {
+        bool operator()(
+            const shared_ptr<const void> &lhs,
+            const shared_ptr<const void> &rhs
+        )const{
+            return lhs.get() < rhs.get();
+        }
+    };
+    typedef std::set<
+        boost::shared_ptr<const void>,
+        collection_type_compare
+    > collection_type;
+    typedef collection_type::const_iterator iterator_type;
+    // list of shared_pointers create accessable by raw pointer. This
+    // is used to "match up" shared pointers loaded at different
+    // points in the archive. Note, we delay construction until
+    // it is actually used since this is by default included as
+    // a "mix-in" even if shared_ptr isn't used.
+    collection_type * m_pointers;
+
+    struct null_deleter {
+        void operator()(void const *) const {}
+    };
+
+    struct void_deleter {
+        const boost::serialization::extended_type_info * m_eti;
+        void_deleter(const boost::serialization::extended_type_info *eti) :
+            m_eti(eti)
+        {}
+        void operator()(void *vp) const {
+            m_eti->destroy(vp);
+        }
+    };
+
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    template<class Archive, class T>
+    friend inline void boost::serialization::load(
+        Archive & ar,
+        boost::shared_ptr< T > &t,
+        const unsigned int file_version
+    );
+#endif
+
+//  #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+    // list of loaded pointers.  This is used to be sure that the pointers
+    // stay around long enough to be "matched" with other pointers loaded
+    // by the same archive.  These are created with a "null_deleter" so that
+    // when this list is destroyed - the underlaying raw pointers are not
+    // destroyed.  This has to be done because the pointers are also held by
+    // new system which is disjoint from this set.  This is implemented
+    // by a change in load_construct_data below.  It makes this file suitable
+    // only for loading pointers into a 1.33 or later boost system.
+    std::list<boost_132::shared_ptr<const void> > * m_pointers_132;
+//  #endif
+
+    // returns pointer to object and an indicator whether this is a
+    // new entry (true) or a previous one (false)
+    BOOST_ARCHIVE_DECL(shared_ptr<void>) 
+    get_od(
+        const void * od,
+        const boost::serialization::extended_type_info * true_type, 
+        const boost::serialization::extended_type_info * this_type
+    );
+
+    BOOST_ARCHIVE_DECL(void)
+    append(const boost::shared_ptr<const void> &);
+
+    template<class T>
+    struct non_polymorphic {
+        static const boost::serialization::extended_type_info * 
+        get_object_identifier(T & t){
+            return & boost::serialization::singleton<
+                BOOST_DEDUCED_TYPENAME 
+                boost::serialization::type_info_implementation< T >::type
+            >::get_const_instance();
+        }
+    };
+    template<class T>
+    struct polymorphic {
+        static const boost::serialization::extended_type_info * 
+        get_object_identifier(T & t){
+            return boost::serialization::singleton<
+                BOOST_DEDUCED_TYPENAME 
+                boost::serialization::type_info_implementation< T >::type
+            >::get_const_instance().get_derived_extended_type_info(t);
+        }
+    };
+public:
+    template<class T>
+    void reset(shared_ptr< T > & s, T * t){
+        if(NULL == t){
+            s.reset();
+            return;
+        }
+        const boost::serialization::extended_type_info * this_type
+            = & boost::serialization::type_info_implementation< T >::type
+                    ::get_const_instance();
+
+        // get pointer to the most derived object.  This is effectively
+        // the object identifern
+        typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_polymorphic< T >,
+            mpl::identity<polymorphic< T > >,
+            mpl::identity<non_polymorphic< T > >
+        >::type type;
+
+        const boost::serialization::extended_type_info * true_type
+            = type::get_object_identifier(*t);
+
+        // note:if this exception is thrown, be sure that derived pointern
+        // is either registered or exported.
+        if(NULL == true_type)
+            boost::serialization::throw_exception(
+                archive_exception(
+                    archive_exception::unregistered_class,
+                    this_type->get_debug_info()
+                )
+            );
+        shared_ptr<void> r =
+            get_od(
+                static_cast<const void *>(t), 
+                true_type,
+                this_type
+            );
+        if(!r){
+            s.reset(t);
+            const void * od = void_downcast(
+                *true_type,
+                *this_type,
+                static_cast<const void *>(t)
+            );
+            shared_ptr<const void> sp(s, od);
+            append(sp);
+        }
+        else{
+            s = shared_ptr< T >(
+                r,
+                static_cast<T *>(r.get())
+            );
+        }
+    }
+
+//  #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+    BOOST_ARCHIVE_DECL(void)
+    append(const boost_132::shared_ptr<const void> & t);
+//  #endif
+public:
+    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+    shared_ptr_helper();
+    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+    ~shared_ptr_helper();
+};
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_SHARED_PTR_HELPER_HPP
diff --git a/SRC/Serialization/archive/text_iarchive.hpp b/SRC/Serialization/archive/text_iarchive.hpp
new file mode 100755
index 0000000..e95f77c
--- /dev/null
+++ b/SRC/Serialization/archive/text_iarchive.hpp
@@ -0,0 +1,156 @@
+#ifndef BOOST_ARCHIVE_TEXT_IARCHIVE_HPP
+#define BOOST_ARCHIVE_TEXT_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <istream>
+
+#include <boost/config.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/basic_text_iprimitive.hpp>
+#include <Serialization/archive/basic_text_iarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class Archive>
+class text_iarchive_impl : 
+    public basic_text_iprimitive<std::istream>,
+    public basic_text_iarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_iarchive<Archive>;
+    friend class basic_text_iarchive<Archive>;
+    friend class load_access;
+protected:
+#endif
+    template<class T>
+    void load(T & t){
+        basic_text_iprimitive<std::istream>::load(t);
+    }
+    void load(version_type & t){
+        unsigned int v;
+        load(v);
+        t = version_type(v);
+    }
+    void load(boost::serialization::item_version_type & t){
+        unsigned int v;
+        load(v);
+        t = boost::serialization::item_version_type(v);
+    }
+    BOOST_ARCHIVE_DECL(void) 
+    load(char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_ARCHIVE_DECL(void) 
+    load(wchar_t * t);
+    #endif
+    BOOST_ARCHIVE_DECL(void) 
+    load(std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_ARCHIVE_DECL(void) 
+    load(std::wstring &ws);
+    #endif
+    // note: the following should not needed - but one compiler (vc 7.1)
+    // fails to compile one test (test_shared_ptr) without it !!!
+    // make this protected so it can be called from a derived archive
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int){
+        basic_text_iarchive<Archive>::load_override(t, 0);
+    }
+    BOOST_ARCHIVE_DECL(void)
+    load_override(class_name_type & t, int);
+    BOOST_ARCHIVE_DECL(void)
+    init();
+    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    text_iarchive_impl(std::istream & is, unsigned int flags);
+    // don't import inline definitions! leave this as a reminder.
+    //BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    ~text_iarchive_impl(){};
+};
+
+// do not derive from the classes below.  If you want to extend this functionality
+// via inhertance, derived from text_iarchive_impl instead.  This will
+// preserve correct static polymorphism.
+
+// same as text_iarchive below - without the shared_ptr_helper
+class naked_text_iarchive : 
+    public text_iarchive_impl<naked_text_iarchive>
+{
+public:
+    naked_text_iarchive(std::istream & is_, unsigned int flags = 0) :
+        // note: added _ to suppress useless gcc warning
+        text_iarchive_impl<naked_text_iarchive>(is_, flags)
+    {}
+    ~naked_text_iarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+// note special treatment of shared_ptr. This type needs a special
+// structure associated with every archive.  We created a "mix-in"
+// class to provide this functionality.  Since shared_ptr holds a
+// special esteem in the boost library - we included it here by default.
+#include <Serialization/archive/shared_ptr_helper.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class text_iarchive : 
+    public text_iarchive_impl<text_iarchive>,
+    public detail::shared_ptr_helper
+{
+public:
+    text_iarchive(std::istream & is_, unsigned int flags = 0) :
+        // note: added _ to suppress useless gcc warning
+        text_iarchive_impl<text_iarchive>(is_, flags)
+    {}
+    ~text_iarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_iarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_TEXT_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/text_oarchive.hpp b/SRC/Serialization/archive/text_oarchive.hpp
new file mode 100755
index 0000000..44e9ee8
--- /dev/null
+++ b/SRC/Serialization/archive/text_oarchive.hpp
@@ -0,0 +1,119 @@
+#ifndef BOOST_ARCHIVE_TEXT_OARCHIVE_HPP
+#define BOOST_ARCHIVE_TEXT_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ostream>
+#include <cstddef> // std::size_t
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/basic_text_oprimitive.hpp>
+#include <Serialization/archive/basic_text_oarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class Archive>
+class text_oarchive_impl : 
+     /* protected ? */ public basic_text_oprimitive<std::ostream>,
+     public basic_text_oarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_oarchive<Archive>;
+    friend class basic_text_oarchive<Archive>;
+    friend class save_access;
+protected:
+#endif
+    template<class T>
+    void save(const T & t){
+        this->newtoken();
+        basic_text_oprimitive<std::ostream>::save(t);
+    }
+    void save(const version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    void save(const boost::serialization::item_version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    BOOST_ARCHIVE_DECL(void) 
+    save(const char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_ARCHIVE_DECL(void) 
+    save(const wchar_t * t);
+    #endif
+    BOOST_ARCHIVE_DECL(void) 
+    save(const std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_ARCHIVE_DECL(void) 
+    save(const std::wstring &ws);
+    #endif
+    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    text_oarchive_impl(std::ostream & os, unsigned int flags);
+    // don't import inline definitions! leave this as a reminder.
+    //BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    ~text_oarchive_impl(){};
+public:
+    BOOST_ARCHIVE_DECL(void) 
+    save_binary(const void *address, std::size_t count);
+};
+
+// do not derive from this class.  If you want to extend this functionality
+// via inhertance, derived from text_oarchive_impl instead.  This will
+// preserve correct static polymorphism.
+class text_oarchive : 
+    public text_oarchive_impl<text_oarchive>
+{
+public:
+    text_oarchive(std::ostream & os_, unsigned int flags = 0) :
+        // note: added _ to suppress useless gcc warning
+        text_oarchive_impl<text_oarchive>(os_, flags)
+    {}
+    ~text_oarchive(){}
+};
+
+typedef text_oarchive naked_text_oarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_oarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_TEXT_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/text_wiarchive.hpp b/SRC/Serialization/archive/text_wiarchive.hpp
new file mode 100755
index 0000000..b85c7b0
--- /dev/null
+++ b/SRC/Serialization/archive/text_wiarchive.hpp
@@ -0,0 +1,152 @@
+#ifndef BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP
+#define BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_wiarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <istream>
+
+#include <Serialization/archive/detail/auto_link_warchive.hpp>
+#include <Serialization/archive/basic_text_iprimitive.hpp>
+#include <Serialization/archive/basic_text_iarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class Archive>
+class text_wiarchive_impl : 
+    public basic_text_iprimitive<std::wistream>,
+    public basic_text_iarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_iarchive<Archive>;
+    friend class basic_text_iarchive<Archive>;
+    friend class load_access;
+protected:
+#endif
+    template<class T>
+    void load(T & t){
+        basic_text_iprimitive<std::wistream>::load(t);
+    }
+    void load(version_type & t){
+        unsigned int v;
+        load(v);
+        t = version_type(v);
+    }
+    void load(boost::serialization::item_version_type & t){
+        unsigned int v;
+        load(v);
+        t = boost::serialization::item_version_type(v);
+    }
+    BOOST_WARCHIVE_DECL(void)
+    load(char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_WARCHIVE_DECL(void)
+    load(wchar_t * t);
+    #endif
+    BOOST_WARCHIVE_DECL(void)
+    load(std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_WARCHIVE_DECL(void)
+    load(std::wstring &ws);
+    #endif
+    // note: the following should not needed - but one compiler (vc 7.1)
+    // fails to compile one test (test_shared_ptr) without it !!!
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int){
+        basic_text_iarchive<Archive>::load_override(t, 0);
+    }
+    BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    text_wiarchive_impl(std::wistream & is, unsigned int flags);
+    ~text_wiarchive_impl(){};
+};
+
+// do not derive from the classes below.  If you want to extend this functionality
+// via inhertance, derived from text_iarchive_impl instead.  This will
+// preserve correct static polymorphism.
+
+// same as text_wiarchive below - without the shared_ptr_helper
+class naked_text_wiarchive : 
+    public text_wiarchive_impl<naked_text_wiarchive>
+{
+public:
+    naked_text_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        text_wiarchive_impl<naked_text_wiarchive>(is, flags)
+    {}
+    ~naked_text_wiarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+// note special treatment of shared_ptr. This type needs a special
+// structure associated with every archive.  We created a "mix-in"
+// class to provide this functionality.  Since shared_ptr holds a
+// special esteem in the boost library - we included it here by default.
+#include <Serialization/archive/shared_ptr_helper.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class text_wiarchive : 
+    public text_wiarchive_impl<text_wiarchive>,
+    public detail::shared_ptr_helper
+{
+public:
+    text_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        text_wiarchive_impl<text_wiarchive>(is, flags)
+    {}
+    ~text_wiarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_wiarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_TEXT_WIARCHIVE_HPP
diff --git a/SRC/Serialization/archive/text_woarchive.hpp b/SRC/Serialization/archive/text_woarchive.hpp
new file mode 100755
index 0000000..d7d5269
--- /dev/null
+++ b/SRC/Serialization/archive/text_woarchive.hpp
@@ -0,0 +1,145 @@
+#ifndef BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP
+#define BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_woarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <ostream>
+#include <cstddef> // size_t
+
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <Serialization/archive/detail/auto_link_warchive.hpp>
+#include <Serialization/archive/basic_text_oprimitive.hpp>
+#include <Serialization/archive/basic_text_oarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class Archive>
+class text_woarchive_impl : 
+    public basic_text_oprimitive<std::wostream>,
+    public basic_text_oarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_oarchive<Archive>;
+    friend class basic_text_oarchive<Archive>;
+    friend class save_access;
+protected:
+#endif
+    template<class T>
+    void save(const T & t){
+        this->newtoken();
+        basic_text_oprimitive<std::wostream>::save(t);
+    }
+    void save(const version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    void save(const boost::serialization::item_version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    BOOST_WARCHIVE_DECL(void)
+    save(const char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_WARCHIVE_DECL(void)
+    save(const wchar_t * t);
+    #endif
+    BOOST_WARCHIVE_DECL(void)
+    save(const std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_WARCHIVE_DECL(void)
+    save(const std::wstring &ws);
+    #endif
+    text_woarchive_impl(std::wostream & os, unsigned int flags) :
+        basic_text_oprimitive<std::wostream>(
+            os, 
+            0 != (flags & no_codecvt)
+        ),
+        basic_text_oarchive<Archive>(flags)
+    {
+        if(0 == (flags & no_header))
+            basic_text_oarchive<Archive>::init();
+    }
+public:
+    void save_binary(const void *address, std::size_t count){
+        put(static_cast<wchar_t>('\n'));
+        this->end_preamble();
+        #if ! defined(__MWERKS__)
+        this->basic_text_oprimitive<std::wostream>::save_binary(
+        #else
+        this->basic_text_oprimitive::save_binary(
+        #endif
+            address, 
+            count
+        );
+        put(static_cast<wchar_t>('\n'));
+        this->delimiter = this->none;
+    }
+
+};
+
+// we use the following because we can't use
+// typedef text_oarchive_impl<text_oarchive_impl<...> > text_oarchive;
+
+// do not derive from this class.  If you want to extend this functionality
+// via inhertance, derived from text_oarchive_impl instead.  This will
+// preserve correct static polymorphism.
+class text_woarchive : 
+    public text_woarchive_impl<text_woarchive>
+{
+public:
+    text_woarchive(std::wostream & os, unsigned int flags = 0) :
+        text_woarchive_impl<text_woarchive>(os, flags)
+    {}
+    ~text_woarchive(){}
+};
+
+typedef text_woarchive naked_text_woarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::text_woarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_TEXT_WOARCHIVE_HPP
diff --git a/SRC/Serialization/archive/tmpdir.hpp b/SRC/Serialization/archive/tmpdir.hpp
new file mode 100755
index 0000000..d0f6966
--- /dev/null
+++ b/SRC/Serialization/archive/tmpdir.hpp
@@ -0,0 +1,50 @@
+#ifndef BOOST_ARCHIVE_TMPDIR_HPP
+#define BOOST_ARCHIVE_TMPDIR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// tmpdir.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstdlib> // getenv
+#include <cstddef> // NULL
+//#include <boost/assert.hpp>
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std {
+    using ::getenv;
+}
+#endif
+
+namespace boost {
+namespace archive {
+
+inline const char * tmpdir(){
+    const char *dirname;
+    dirname = std::getenv("TMP");
+    if(NULL == dirname)
+        dirname = std::getenv("TMPDIR");
+    if(NULL == dirname)
+        dirname = std::getenv("TEMP");
+    if(NULL == dirname){
+        //BOOST_ASSERT(false); // no temp directory found
+        dirname = ".";
+    }
+    return dirname;
+}
+
+} // archive
+} // boost
+
+#endif // BOOST_ARCHIVE_TMPDIR_HPP
diff --git a/SRC/Serialization/archive/wcslen.hpp b/SRC/Serialization/archive/wcslen.hpp
new file mode 100755
index 0000000..88c4ba2
--- /dev/null
+++ b/SRC/Serialization/archive/wcslen.hpp
@@ -0,0 +1,56 @@
+#ifndef BOOST_ARCHIVE_WCSLEN_HPP
+#define BOOST_ARCHIVE_WCSLEN_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// wcslen.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // size_t
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#ifndef BOOST_NO_CWCHAR
+
+// a couple of libraries which include wchar_t don't include
+// wcslen
+
+#if defined(BOOST_DINKUMWARE_STDLIB) && BOOST_DINKUMWARE_STDLIB < 306 \
+|| defined(__LIBCOMO__) 
+
+namespace std {
+inline std::size_t wcslen(const wchar_t * ws)
+{
+    const wchar_t * eows = ws;
+    while(* eows != 0)
+        ++eows;
+    return eows - ws;
+}
+} // namespace std
+
+#else
+
+#include <cwchar>
+#ifdef BOOST_NO_STDC_NAMESPACE
+namespace std{ using ::wcslen; }
+#endif
+
+#endif // wcslen
+
+#endif //BOOST_NO_CWCHAR
+
+#endif //BOOST_ARCHIVE_WCSLEN_HPP
diff --git a/SRC/Serialization/archive/xml_archive_exception.hpp b/SRC/Serialization/archive/xml_archive_exception.hpp
new file mode 100755
index 0000000..5520214
--- /dev/null
+++ b/SRC/Serialization/archive/xml_archive_exception.hpp
@@ -0,0 +1,56 @@
+#ifndef BOOST_ARCHIVE_XML_ARCHIVE_EXCEPTION_HPP
+#define BOOST_ARCHIVE_XML_ARCHIVE_EXCEPTION_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_archive_exception.hpp:
+
+// (C) Copyright 2007 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <exception>
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp> 
+#include <boost/preprocessor/empty.hpp>
+#include <Serialization/archive/detail/decl.hpp>
+#include <Serialization/archive/archive_exception.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+namespace boost {
+namespace archive {
+
+//////////////////////////////////////////////////////////////////////
+// exceptions thrown by xml archives
+//
+class BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) xml_archive_exception : 
+    public virtual boost::archive::archive_exception
+{
+public:
+    typedef enum {
+        xml_archive_parsing_error,    // see save_register
+        xml_archive_tag_mismatch,
+        xml_archive_tag_name_error
+    } exception_code;
+    xml_archive_exception(
+        exception_code c, 
+        const char * e1 = NULL,
+        const char * e2 = NULL
+    );
+};
+
+}// namespace archive
+}// namespace boost
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif //BOOST_XML_ARCHIVE_ARCHIVE_EXCEPTION_HPP
diff --git a/SRC/Serialization/archive/xml_iarchive.hpp b/SRC/Serialization/archive/xml_iarchive.hpp
new file mode 100755
index 0000000..78b8ee7
--- /dev/null
+++ b/SRC/Serialization/archive/xml_iarchive.hpp
@@ -0,0 +1,164 @@
+#ifndef BOOST_ARCHIVE_XML_IARCHIVE_HPP
+#define BOOST_ARCHIVE_XML_IARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_iarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <istream>
+
+//#include <boost/scoped_ptr.hpp>
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/basic_text_iprimitive.hpp>
+#include <Serialization/archive/basic_xml_iarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class CharType>
+class basic_xml_grammar;
+typedef basic_xml_grammar<char> xml_grammar;
+
+template<class Archive>
+class xml_iarchive_impl : 
+    public basic_text_iprimitive<std::istream>,
+    public basic_xml_iarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_iarchive<Archive>;
+    friend class basic_xml_iarchive<Archive>;
+    friend class load_access;
+protected:
+#endif
+    // instances of micro xml parser to parse start preambles
+    // scoped_ptr doesn't play nice with borland - so use a naked pointer
+    // scoped_ptr<xml_grammar> gimpl;
+    xml_grammar *gimpl;
+
+    std::istream & get_is(){
+        return is;
+    }
+    template<class T>
+    void load(T & t){
+        basic_text_iprimitive<std::istream>::load(t);
+    }
+    void 
+    load(version_type & t){
+        unsigned int v;
+        load(v);
+        t = version_type(v);
+    }
+    void 
+    load(boost::serialization::item_version_type & t){
+        unsigned int v;
+        load(v);
+        t = boost::serialization::item_version_type(v);
+    }
+    BOOST_ARCHIVE_DECL(void)
+    load(char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_ARCHIVE_DECL(void)
+    load(wchar_t * t);
+    #endif
+    BOOST_ARCHIVE_DECL(void)
+    load(std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_ARCHIVE_DECL(void)
+    load(std::wstring &ws);
+    #endif
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int){
+        basic_xml_iarchive<Archive>::load_override(t, 0);
+    }
+    BOOST_ARCHIVE_DECL(void)
+    load_override(class_name_type & t, int);
+    BOOST_ARCHIVE_DECL(void)
+    init();
+    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    xml_iarchive_impl(std::istream & is, unsigned int flags);
+    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+    ~xml_iarchive_impl();
+};
+
+// do not derive from the classes below.  If you want to extend this functionality
+// via inhertance, derived from text_iarchive_impl instead.  This will
+// preserve correct static polymorphism.
+
+// same as xml_iarchive below - without the shared_ptr_helper
+class naked_xml_iarchive : 
+    public xml_iarchive_impl<naked_xml_iarchive>
+{
+public:
+    naked_xml_iarchive(std::istream & is, unsigned int flags = 0) :
+        xml_iarchive_impl<naked_xml_iarchive>(is, flags)
+    {}
+    ~naked_xml_iarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+// note special treatment of shared_ptr. This type needs a special
+// structure associated with every archive.  We created a "mix-in"
+// class to provide this functionality.  Since shared_ptr holds a
+// special esteem in the boost library - we included it here by default.
+#include <Serialization/archive/shared_ptr_helper.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class xml_iarchive : 
+    public xml_iarchive_impl<xml_iarchive>,
+    public detail::shared_ptr_helper
+{
+public:
+    xml_iarchive(std::istream & is, unsigned int flags = 0) :
+        xml_iarchive_impl<xml_iarchive>(is, flags)
+    {}
+    ~xml_iarchive(){};
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_iarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_ARCHIVE_XML_IARCHIVE_HPP
diff --git a/SRC/Serialization/archive/xml_oarchive.hpp b/SRC/Serialization/archive/xml_oarchive.hpp
new file mode 100755
index 0000000..8da58bb
--- /dev/null
+++ b/SRC/Serialization/archive/xml_oarchive.hpp
@@ -0,0 +1,133 @@
+#ifndef BOOST_ARCHIVE_XML_OARCHIVE_HPP
+#define BOOST_ARCHIVE_XML_OARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_oarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ostream>
+
+#include <cstddef> // size_t
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/basic_text_oprimitive.hpp>
+#include <Serialization/archive/basic_xml_oarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+template<class Archive>
+class xml_oarchive_impl : 
+    public basic_text_oprimitive<std::ostream>,
+    public basic_xml_oarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_oarchive<Archive>;
+    friend class basic_xml_oarchive<Archive>;
+    friend class save_access;
+protected:
+#endif
+    //void end_preamble(){
+    //    basic_xml_oarchive<Archive>::end_preamble();
+    //}
+    template<class T>
+    void save(const T & t){
+        basic_text_oprimitive<std::ostream>::save(t);
+    }
+    void 
+    save(const version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    void 
+    save(const boost::serialization::item_version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    BOOST_ARCHIVE_DECL(void) 
+    save(const char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_ARCHIVE_DECL(void)
+    save(const wchar_t * t);
+    #endif
+    BOOST_ARCHIVE_DECL(void)
+    save(const std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_ARCHIVE_DECL(void)
+    save(const std::wstring &ws);
+    #endif
+    BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    xml_oarchive_impl(std::ostream & os, unsigned int flags);
+    ~xml_oarchive_impl(){}
+public:
+    void save_binary(const void *address, std::size_t count){
+        this->end_preamble();
+        #if ! defined(__MWERKS__)
+        this->basic_text_oprimitive<std::ostream>::save_binary(
+        #else
+        this->basic_text_oprimitive::save_binary(
+        #endif
+            address, 
+            count
+        );
+        this->indent_next = true;
+    }
+};
+
+// we use the following because we can't use
+// typedef xml_oarchive_impl<xml_oarchive_impl<...> > xml_oarchive;
+
+// do not derive from this class.  If you want to extend this functionality
+// via inhertance, derived from xml_oarchive_impl instead.  This will
+// preserve correct static polymorphism.
+class xml_oarchive : 
+    public xml_oarchive_impl<xml_oarchive>
+{
+public:
+    xml_oarchive(std::ostream & os, unsigned int flags = 0) :
+        xml_oarchive_impl<xml_oarchive>(os, flags)
+    {}
+    ~xml_oarchive(){}
+};
+
+typedef xml_oarchive naked_xml_oarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_oarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP
diff --git a/SRC/Serialization/archive/xml_wiarchive.hpp b/SRC/Serialization/archive/xml_wiarchive.hpp
new file mode 100755
index 0000000..121c59f
--- /dev/null
+++ b/SRC/Serialization/archive/xml_wiarchive.hpp
@@ -0,0 +1,170 @@
+#ifndef BOOST_ARCHIVE_XML_WIARCHIVE_HPP
+#define BOOST_ARCHIVE_XML_WIARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_wiarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <istream>
+
+//#include <boost/scoped_ptr.hpp>
+#include <Serialization/archive/detail/auto_link_warchive.hpp>
+#include <Serialization/archive/basic_text_iprimitive.hpp>
+#include <Serialization/archive/basic_xml_iarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+template<class CharType>
+class basic_xml_grammar;
+typedef basic_xml_grammar<wchar_t> xml_wgrammar;
+
+template<class Archive>
+class xml_wiarchive_impl : 
+    public basic_text_iprimitive<std::wistream>,
+    public basic_xml_iarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_iarchive<Archive>;
+    friend class basic_xml_iarchive<Archive>;
+    friend class load_access;
+protected:
+#endif
+    // instances of micro xml parser to parse start preambles
+    // scoped_ptr doesn't play nice with borland - so use a naked pointer
+    // scoped_ptr<xml_wgrammar> gimpl;
+    xml_wgrammar *gimpl;
+    std::wistream & get_is(){
+        return is;
+    }
+    template<class T>
+    void 
+    load(T & t){
+        basic_text_iprimitive<std::wistream>::load(t);
+    }
+    void 
+    load(version_type & t){
+        unsigned int v;
+        load(v);
+        t = version_type(v);
+    }
+    void 
+    load(boost::serialization::item_version_type & t){
+        unsigned int v;
+        load(v);
+        t = boost::serialization::item_version_type(v);
+    }
+    BOOST_WARCHIVE_DECL(void)
+    load(char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_WARCHIVE_DECL(void)
+    load(wchar_t * t);
+    #endif
+    BOOST_WARCHIVE_DECL(void)
+    load(std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_WARCHIVE_DECL(void)
+    load(std::wstring &ws);
+    #endif
+    template<class T>
+    void load_override(T & t, BOOST_PFTO int){
+        basic_xml_iarchive<Archive>::load_override(t, 0);
+    }
+    BOOST_WARCHIVE_DECL(void)
+    load_override(class_name_type & t, int);
+    BOOST_WARCHIVE_DECL(void) 
+    init();
+    BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    xml_wiarchive_impl(std::wistream & is, unsigned int flags) ;
+    BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    ~xml_wiarchive_impl();
+};
+
+// do not derive from the classes below.  If you want to extend this functionality
+// via inhertance, derived from xml_wiarchive_impl instead.  This will
+// preserve correct static polymorphism.
+
+// same as xml_wiarchive below - without the shared_ptr_helper
+class naked_xml_wiarchive : 
+    public xml_wiarchive_impl<naked_xml_wiarchive>
+{
+public:
+    naked_xml_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        xml_wiarchive_impl<naked_xml_wiarchive>(is, flags)
+    {}
+    ~naked_xml_wiarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop) 
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+// note special treatment of shared_ptr. This type needs a special
+// structure associated with every archive.  We created a "mix-in"
+// class to provide this functionality.  Since shared_ptr holds a
+// special esteem in the boost library - we included it here by default.
+#include <Serialization/archive/shared_ptr_helper.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace archive {
+
+class xml_wiarchive : 
+    public xml_wiarchive_impl<xml_wiarchive>,
+    public detail::shared_ptr_helper
+{
+public:
+    xml_wiarchive(std::wistream & is, unsigned int flags = 0) :
+        xml_wiarchive_impl<xml_wiarchive>(is, flags)
+    {}
+    ~xml_wiarchive(){}
+};
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_wiarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_XML_WIARCHIVE_HPP
diff --git a/SRC/Serialization/archive/xml_woarchive.hpp b/SRC/Serialization/archive/xml_woarchive.hpp
new file mode 100755
index 0000000..3da6016
--- /dev/null
+++ b/SRC/Serialization/archive/xml_woarchive.hpp
@@ -0,0 +1,140 @@
+#ifndef BOOST_ARCHIVE_XML_WOARCHIVE_HPP
+#define BOOST_ARCHIVE_XML_WOARCHIVE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_woarchive.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <cstddef> // size_t
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <ostream>
+
+#include <Serialization/archive/detail/auto_link_warchive.hpp>
+#include <Serialization/archive/basic_text_oprimitive.hpp>
+#include <Serialization/archive/basic_xml_oarchive.hpp>
+#include <Serialization/archive/detail/register_archive.hpp>
+#include <Serialization/item_version_type.hpp>
+
+#include <Serialization/archive/detail/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost {
+namespace archive {
+
+template<class Archive>
+class xml_woarchive_impl : 
+    public basic_text_oprimitive<std::wostream>,
+    public basic_xml_oarchive<Archive>
+{
+#ifdef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+public:
+#else
+    friend class detail::interface_oarchive<Archive>;
+    friend class basic_xml_oarchive<Archive>;
+    friend class save_access;
+protected:
+#endif
+    //void end_preamble(){
+    //    basic_xml_oarchive<Archive>::end_preamble();
+    //}
+    template<class T>
+    void 
+    save(const T & t){
+        basic_text_oprimitive<std::wostream>::save(t);
+    }
+    void 
+    save(const version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    void 
+    save(const boost::serialization::item_version_type & t){
+        save(static_cast<const unsigned int>(t));
+    }
+    BOOST_WARCHIVE_DECL(void)
+    save(const char * t);
+    #ifndef BOOST_NO_INTRINSIC_WCHAR_T
+    BOOST_WARCHIVE_DECL(void) 
+    save(const wchar_t * t);
+    #endif
+    BOOST_WARCHIVE_DECL(void) 
+    save(const std::string &s);
+    #ifndef BOOST_NO_STD_WSTRING
+    BOOST_WARCHIVE_DECL(void)
+    save(const std::wstring &ws);
+    #endif
+    BOOST_WARCHIVE_DECL(BOOST_PP_EMPTY()) 
+    xml_woarchive_impl(std::wostream & os, unsigned int flags);
+    ~xml_woarchive_impl(){}
+public:
+    void 
+    save_binary(const void *address, std::size_t count){
+        this->end_preamble();
+        #if ! defined(__MWERKS__)
+        this->basic_text_oprimitive<std::wostream>::save_binary(
+        #else
+        this->basic_text_oprimitive::save_binary(
+        #endif
+            address, 
+            count
+        );
+        this->indent_next = true;
+    }
+};
+
+// we use the following because we can't use
+// typedef xml_woarchive_impl<xml_woarchive_impl<...> > xml_woarchive;
+
+// do not derive from this class.  If you want to extend this functionality
+// via inhertance, derived from xml_woarchive_impl instead.  This will
+// preserve correct static polymorphism.
+class xml_woarchive : 
+    public xml_woarchive_impl<xml_woarchive>
+{
+public:
+    xml_woarchive(std::wostream & os, unsigned int flags = 0) :
+        xml_woarchive_impl<xml_woarchive>(os, flags)
+    {}
+    ~xml_woarchive(){}
+};
+
+typedef xml_woarchive naked_xml_woarchive;
+
+} // namespace archive
+} // namespace boost
+
+// required by export
+BOOST_SERIALIZATION_REGISTER_ARCHIVE(boost::archive::xml_woarchive)
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <Serialization/archive/detail/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+#endif // BOOST_ARCHIVE_XML_OARCHIVE_HPP
diff --git a/SRC/Serialization/array.hpp b/SRC/Serialization/array.hpp
new file mode 100755
index 0000000..6495f92
--- /dev/null
+++ b/SRC/Serialization/array.hpp
@@ -0,0 +1,153 @@
+#ifndef BOOST_SERIALIZATION_ARRAY_HPP
+#define BOOST_SERIALIZATION_ARRAY_HPP
+
+// (C) Copyright 2005 Matthias Troyer and Dave Abrahams
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <cstddef> // std::size_t
+#include <cstddef>
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <Serialization/nvp.hpp>
+#include <Serialization/split_member.hpp>
+#include <Serialization/wrapper.hpp>
+#include <boost/mpl/always.hpp>
+#include <boost/mpl/apply.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/array.hpp>
+
+namespace boost { namespace serialization {
+
+// traits to specify whether to use  an optimized array serialization
+
+#ifdef __BORLANDC__
+// workaround for Borland compiler
+template <class Archive>
+struct use_array_optimization {
+  template <class T> struct apply : boost::mpl::false_ {};
+};
+
+#else
+template <class Archive>
+struct use_array_optimization : boost::mpl::always<boost::mpl::false_> {};
+#endif
+
+template<class T>
+class array :
+    public wrapper_traits<const array< T > >
+{
+public:    
+    typedef T value_type;
+    
+    array(value_type* t, std::size_t s) :
+        m_t(t),
+        m_element_count(s)
+    {}
+    array(const array & rhs) :
+        m_t(rhs.m_t),
+        m_element_count(rhs.m_element_count)
+    {}
+    array & operator=(const array & rhs){
+        m_t = rhs.m_t;
+        m_element_count = rhs.m_element_count;
+    }
+
+    // default implementation
+    template<class Archive>
+    void serialize_optimized(Archive &ar, const unsigned int, mpl::false_ ) const
+    {
+      // default implemention does the loop
+      std::size_t c = count();
+      value_type * t = address();
+      while(0 < c--)
+            ar & boost::serialization::make_nvp("item", *t++);
+    }
+
+    // optimized implementation
+    template<class Archive>
+    void serialize_optimized(Archive &ar, const unsigned int version, mpl::true_ )
+    {
+      boost::serialization::split_member(ar, *this, version);
+    }
+
+    // default implementation
+    template<class Archive>
+    void save(Archive &ar, const unsigned int version) const
+    {
+      ar.save_array(*this,version);
+    }
+
+    // default implementation
+    template<class Archive>
+    void load(Archive &ar, const unsigned int version)
+    {
+      ar.load_array(*this,version);
+    }
+    
+    // default implementation
+    template<class Archive>
+    void serialize(Archive &ar, const unsigned int version)
+    {
+      typedef BOOST_DEDUCED_TYPENAME 
+          boost::serialization::use_array_optimization<Archive>::template apply<
+                    BOOST_DEDUCED_TYPENAME remove_const< T >::type 
+                >::type use_optimized;
+      serialize_optimized(ar,version,use_optimized());
+    }
+    
+    value_type* address() const
+    {
+      return m_t;
+    }
+
+    std::size_t count() const
+    {
+      return m_element_count;
+    }
+    
+private:
+    value_type* m_t;
+    std::size_t m_element_count;
+};
+
+template<class T>
+inline
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+const
+#endif
+array< T > make_array( T* t, std::size_t s){
+    return array< T >(t, s);
+}
+
+template <class Archive, class T, std::size_t N>
+void serialize(Archive& ar, boost::array<T,N>& a, const unsigned int /* version */)
+{
+  ar & boost::serialization::make_nvp("elems",a.elems);
+}
+
+} } // end namespace boost::serialization
+
+#ifdef __BORLANDC__
+// ignore optimizations for Borland
+#define BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(Archive)      
+#else
+#define BOOST_SERIALIZATION_USE_ARRAY_OPTIMIZATION(Archive)           \
+namespace boost { namespace serialization {                           \
+template <> struct use_array_optimization<Archive> {                  \
+  template <class ValueType>                                          \
+  struct apply : boost::mpl::apply1<Archive::use_array_optimization   \
+      , BOOST_DEDUCED_TYPENAME boost::remove_const<ValueType>::type   \
+    >::type {};                                                       \
+}; }}
+#endif // __BORLANDC__
+
+#endif //BOOST_SERIALIZATION_ARRAY_HPP
diff --git a/SRC/Serialization/assume_abstract.hpp b/SRC/Serialization/assume_abstract.hpp
new file mode 100755
index 0000000..8aa82a4
--- /dev/null
+++ b/SRC/Serialization/assume_abstract.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SERIALIZATION_ASSUME_ABSTRACT_HPP
+#define BOOST_SERIALIZATION_ASSUME_ABSTRACT_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// assume_abstract_class.hpp:
+
+// (C) Copyright 2008 Robert Ramey
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// this is useful for compilers which don't support the boost::is_abstract
+
+#include <boost/type_traits/is_abstract.hpp>
+
+#ifndef BOOST_NO_IS_ABSTRACT
+
+// if there is an intrinsic is_abstract defined, we don't have to do anything
+#define BOOST_SERIALIZATION_ASSUME_ABSTRACT(T)
+
+// but forward to the "official" is_abstract
+namespace boost {
+namespace serialization {
+    template<class T>
+    struct is_abstract : boost::is_abstract< T > {} ;
+} // namespace serialization
+} // namespace boost
+
+#else
+// we have to "make" one
+
+namespace boost {
+namespace serialization {
+    template<class T>
+    struct is_abstract : boost::false_type {};
+} // namespace serialization
+} // namespace boost
+
+// define a macro to make explicit designation of this more transparent
+#define BOOST_SERIALIZATION_ASSUME_ABSTRACT(T)        \
+namespace boost {                                     \
+namespace serialization {                             \
+template<>                                            \
+struct is_abstract< T > : boost::true_type {};        \
+template<>                                            \
+struct is_abstract< const T > : boost::true_type {};  \
+}}                                                    \
+/**/
+
+#endif // BOOST_NO_IS_ABSTRACT
+
+#endif //BOOST_SERIALIZATION_ASSUME_ABSTRACT_HPP
diff --git a/SRC/Serialization/base_object.hpp b/SRC/Serialization/base_object.hpp
new file mode 100755
index 0000000..bc48341
--- /dev/null
+++ b/SRC/Serialization/base_object.hpp
@@ -0,0 +1,112 @@
+#ifndef BOOST_SERIALIZATION_BASE_OBJECT_HPP
+#define BOOST_SERIALIZATION_BASE_OBJECT_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// base_object.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// if no archive headers have been included this is a no op
+// this is to permit BOOST_EXPORT etc to be included in a 
+// file declaration header
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/identity.hpp>
+
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+
+#include <boost/static_assert.hpp>
+#include <Serialization/access.hpp>
+#include <Serialization/force_include.hpp>
+#include <Serialization/void_cast_fwd.hpp>
+
+namespace boost {
+namespace serialization {
+
+namespace detail
+{
+    // get the base type for a given derived type
+    // preserving the const-ness
+    template<class B, class D>
+    struct base_cast
+    {
+        typedef BOOST_DEDUCED_TYPENAME
+        mpl::if_<
+            is_const<D>,
+            const B,
+            B
+        >::type type;
+        BOOST_STATIC_ASSERT(is_const<type>::value == is_const<D>::value);
+    };
+
+    // only register void casts if the types are polymorphic
+    template<class Base, class Derived>
+    struct base_register
+    {
+        struct polymorphic {
+            static void const * invoke(){
+                Base const * const b = 0;
+                Derived const * const d = 0;
+                return & void_cast_register(d, b);
+            }
+        };
+        struct non_polymorphic {
+            static void const * invoke(){
+                return 0;
+            }
+        };
+        static void const * invoke(){
+            typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                is_polymorphic<Base>,
+                mpl::identity<polymorphic>,
+                mpl::identity<non_polymorphic>
+            >::type type;
+            return type::invoke();
+        }
+    };
+
+} // namespace detail
+#if defined(__BORLANDC__) && __BORLANDC__ < 0x610
+template<class Base, class Derived>
+const Base & 
+base_object(const Derived & d)
+{
+    BOOST_STATIC_ASSERT(! is_pointer<Derived>::value);
+    detail::base_register<Base, Derived>::invoke();
+    return access::cast_reference<const Base, Derived>(d);
+}
+#else
+template<class Base, class Derived>
+BOOST_DEDUCED_TYPENAME detail::base_cast<Base, Derived>::type & 
+base_object(Derived &d)
+{
+    BOOST_STATIC_ASSERT(( is_base_and_derived<Base,Derived>::value));
+    BOOST_STATIC_ASSERT(! is_pointer<Derived>::value);
+    typedef BOOST_DEDUCED_TYPENAME detail::base_cast<Base, Derived>::type type;
+    detail::base_register<type, Derived>::invoke();
+    return access::cast_reference<type, Derived>(d);
+}
+#endif
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_BASE_OBJECT_HPP
diff --git a/SRC/Serialization/binary_object.hpp b/SRC/Serialization/binary_object.hpp
new file mode 100755
index 0000000..09efb82
--- /dev/null
+++ b/SRC/Serialization/binary_object.hpp
@@ -0,0 +1,82 @@
+#ifndef BOOST_SERIALIZATION_BINARY_OBJECT_HPP
+#define BOOST_SERIALIZATION_BINARY_OBJECT_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// nvp.hpp: interface for serialization system.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/assert.hpp>
+
+#include <cstddef> // std::size_t
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <boost/preprocessor/stringize.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/split_member.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/wrapper.hpp>
+
+namespace boost {
+namespace serialization {
+
+struct binary_object :
+    public wrapper_traits<nvp<const binary_object> >
+{
+    void const * m_t;
+    std::size_t m_size;
+    template<class Archive>
+    void save(Archive & ar, const unsigned int /* file_version */) const {
+        ar.save_binary(m_t, m_size);
+    }
+    template<class Archive>
+    void load(Archive & ar, const unsigned int /* file_version */) const {
+        ar.load_binary(const_cast<void *>(m_t), m_size);
+    }
+    BOOST_SERIALIZATION_SPLIT_MEMBER()
+    binary_object & operator=(const binary_object & rhs) {
+        m_t = rhs.m_t;
+        m_size = rhs.m_size;
+        return *this;
+    }
+    binary_object(/* const */ void * const t, std::size_t size) :
+        m_t(t),
+        m_size(size)
+    {}
+    binary_object(const binary_object & rhs) :
+        m_t(rhs.m_t),
+        m_size(rhs.m_size)
+    {}
+};
+
+// just a little helper to support the convention that all serialization
+// wrappers follow the naming convention make_xxxxx
+inline 
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+const
+#endif
+binary_object 
+make_binary_object(/* const */ void * t, std::size_t size){
+    return binary_object(t, size);
+}
+
+} // namespace serialization
+} // boost
+
+#endif // BOOST_SERIALIZATION_BINARY_OBJECT_HPP
diff --git a/SRC/Serialization/bitset.hpp b/SRC/Serialization/bitset.hpp
new file mode 100755
index 0000000..cc198a5
--- /dev/null
+++ b/SRC/Serialization/bitset.hpp
@@ -0,0 +1,75 @@
+/*!
+ * \file      bitset.hpp
+ * \brief     Provides Boost.Serialization support for std::bitset
+ * \author    Brian Ravnsgaard Riis
+ * \author    Kenneth Riddile
+ * \date      16.09.2004, updated 04.03.2009
+ * \copyright 2004 Brian Ravnsgaard Riis
+ * \license   Boost Software License 1.0
+ */
+#ifndef BOOST_SERIALIZATION_BITSET_HPP
+#define BOOST_SERIALIZATION_BITSET_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <bitset>
+#include <cstddef> // size_t
+
+#include <boost/config.hpp>
+#include <Serialization/split_free.hpp>
+#include <Serialization/string.hpp>
+#include <Serialization/nvp.hpp>
+
+namespace boost{
+namespace serialization{
+
+template <class Archive, std::size_t size>
+inline void save(
+    Archive & ar,
+    std::bitset<size> const & t,
+    const unsigned int /* version */
+){
+    const std::string bits = t.template to_string<
+        std::string::value_type,
+        std::string::traits_type,
+        std::string::allocator_type
+    >();
+    ar << BOOST_SERIALIZATION_NVP( bits );
+}
+
+template <class Archive, std::size_t size>
+inline void load(
+    Archive & ar,
+    std::bitset<size> & t,
+    const unsigned int /* version */
+){
+    std::string bits;
+    ar >> BOOST_SERIALIZATION_NVP( bits );
+    t = std::bitset<size>(bits);
+}
+
+template <class Archive, std::size_t size>
+inline void serialize(
+    Archive & ar,
+    std::bitset<size> & t,
+    const unsigned int version
+){
+    boost::serialization::split_free( ar, t, version );
+}
+
+// don't track bitsets since that would trigger tracking
+// all over the program - which probably would be a surprise.
+// also, tracking would be hard to implement since, we're
+// serialization a representation of the data rather than
+// the data itself.
+template <std::size_t size>
+struct tracking_level<std::bitset<size> >
+    : mpl::int_<track_never> {} ;
+
+} //serialization
+} //boost
+
+#endif // BOOST_SERIALIZATION_BITSET_HPP
diff --git a/SRC/Serialization/collection_size_type.hpp b/SRC/Serialization/collection_size_type.hpp
new file mode 100755
index 0000000..5416857
--- /dev/null
+++ b/SRC/Serialization/collection_size_type.hpp
@@ -0,0 +1,62 @@
+#ifndef BOOST_SERIALIZATION_COLLECTION_SIZE_TYPE_HPP
+#define BOOST_SERIALIZATION_COLLECTION_SIZE_TYPE_HPP
+
+// (C) Copyright 2005 Matthias Troyer
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <cstddef> // size_t
+#include <Serialization/strong_typedef.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/split_free.hpp>
+#include <Serialization/is_bitwise_serializable.hpp>
+
+namespace boost { 
+namespace serialization {
+
+//BOOST_STRONG_TYPEDEF(std::size_t, collection_size_type)
+
+class collection_size_type {
+private:
+    typedef std::size_t base_type;
+    base_type t;
+public:
+    collection_size_type(): t(0) {};
+    explicit collection_size_type(const std::size_t & t_) : 
+        t(t_)
+    {}
+    collection_size_type(const collection_size_type & t_) : 
+        t(t_.t)
+    {}
+    collection_size_type & operator=(const collection_size_type & rhs){
+        t = rhs.t; 
+        return *this;
+    }
+    collection_size_type & operator=(const unsigned int & rhs){
+        t = rhs; 
+        return *this;
+    }
+    // used for text output
+    operator base_type () const {
+        return t;
+    }                
+    // used for text input
+    operator base_type & () {
+        return t;
+    }                
+    bool operator==(const collection_size_type & rhs) const {
+        return t == rhs.t;
+    } 
+    bool operator<(const collection_size_type & rhs) const {
+        return t < rhs.t;
+    }   
+};
+
+
+} } // end namespace boost::serialization
+
+BOOST_CLASS_IMPLEMENTATION(collection_size_type, primitive_type)
+BOOST_IS_BITWISE_SERIALIZABLE(collection_size_type)
+
+#endif //BOOST_SERIALIZATION_COLLECTION_SIZE_TYPE_HPP
diff --git a/SRC/Serialization/collection_traits.hpp b/SRC/Serialization/collection_traits.hpp
new file mode 100755
index 0000000..46c449a
--- /dev/null
+++ b/SRC/Serialization/collection_traits.hpp
@@ -0,0 +1,79 @@
+#ifndef BOOST_SERIALIZATION_COLLECTION_TRAITS_HPP
+#define BOOST_SERIALIZATION_COLLECTION_TRAITS_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// collection_traits.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// This header assigns a level implemenation trait to a collection type
+// for all primitives.  It is needed so that archives which are meant to be
+// portable don't write class information in the archive.  Since, not all
+// compiles recognize the same set of primitive types, the possibility
+// exists for archives to be non-portable if class information for primitive
+// types is included.  This is addressed by the following macros.
+#include <boost/config.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+
+#include <boost/cstdint.hpp>
+#include <boost/integer_traits.hpp>
+#include <climits> // ULONG_MAX
+#include <Serialization/level.hpp>
+
+#define BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(T, C)          \
+template<>                                                          \
+struct implementation_level< C < T > > {                            \
+    typedef mpl::integral_c_tag tag;                                \
+    typedef mpl::int_<object_serializable> type;                    \
+    BOOST_STATIC_CONSTANT(int, value = object_serializable);        \
+};                                                                  \
+/**/
+
+#if defined(BOOST_NO_CWCHAR) || defined(BOOST_NO_INTRINSIC_WCHAR_T)
+    #define BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER_WCHAR(C)
+#else
+    #define BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER_WCHAR(C)   \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(wchar_t, C)        \
+    /**/
+#endif
+
+#if defined(BOOST_HAS_LONG_LONG)
+    #define BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER_INT64(C)    \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(boost::long_long_type, C)  \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(boost::ulong_long_type, C) \
+    /**/
+#else
+    #define BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER_INT64(C)
+#endif
+
+#define BOOST_SERIALIZATION_COLLECTION_TRAITS(C)                     \
+    namespace boost { namespace serialization {                      \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(bool, C)            \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(char, C)            \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(signed char, C)     \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(unsigned char, C)   \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(signed int, C)      \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(unsigned int, C)    \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(signed long, C)     \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(unsigned long, C)   \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(float, C)           \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(double, C)          \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(unsigned short, C)  \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER(signed short, C)    \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER_INT64(C)            \
+    BOOST_SERIALIZATION_COLLECTION_TRAITS_HELPER_WCHAR(C)            \
+    } }                                                              \
+    /**/
+
+#endif // BOOST_SERIALIZATION_COLLECTION_TRAITS
diff --git a/SRC/Serialization/collections_load_imp.hpp b/SRC/Serialization/collections_load_imp.hpp
new file mode 100755
index 0000000..5e6a369
--- /dev/null
+++ b/SRC/Serialization/collections_load_imp.hpp
@@ -0,0 +1,166 @@
+#ifndef  BOOST_SERIALIZATION_COLLECTIONS_LOAD_IMP_HPP
+#define BOOST_SERIALIZATION_COLLECTIONS_LOAD_IMP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1020)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// collections_load_imp.hpp: serialization for loading stl collections
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// helper function templates for serialization of collections
+
+#include <boost/assert.hpp>
+#include <cstddef> // size_t
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+#include <boost/detail/workaround.hpp>
+
+#include <Serialization/archive/detail/basic_iarchive.hpp>
+#include <Serialization/access.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/detail/stack_constructor.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/item_version_type.hpp>
+
+namespace boost{
+namespace serialization {
+namespace stl {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of serialization for STL containers
+//
+
+// sequential container input
+template<class Archive, class Container>
+struct archive_input_seq
+{
+    inline BOOST_DEDUCED_TYPENAME Container::iterator
+    operator()(
+        Archive &ar, 
+        Container &s, 
+        const unsigned int v,
+        BOOST_DEDUCED_TYPENAME Container::iterator hint
+    ){
+        typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
+        detail::stack_construct<Archive, type> t(ar, v);
+        // borland fails silently w/o full namespace
+        ar >> boost::serialization::make_nvp("item", t.reference());
+        s.push_back(t.reference());
+        ar.reset_object_address(& s.back() , & t.reference());
+        return hint;
+    }
+};
+
+// map input
+template<class Archive, class Container>
+struct archive_input_map
+{
+    inline BOOST_DEDUCED_TYPENAME Container::iterator
+    operator()(
+        Archive &ar, 
+        Container &s, 
+        const unsigned int v,
+        BOOST_DEDUCED_TYPENAME Container::iterator hint
+    ){
+        typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
+        detail::stack_construct<Archive, type> t(ar, v);
+        // borland fails silently w/o full namespace
+        ar >> boost::serialization::make_nvp("item", t.reference());
+        BOOST_DEDUCED_TYPENAME Container::iterator result = 
+            s.insert(hint, t.reference());
+        // note: the following presumes that the map::value_type was NOT tracked
+        // in the archive.  This is the usual case, but here there is no way
+        // to determine that.  
+        ar.reset_object_address(
+            & (result->second),
+            & t.reference().second
+        );
+        return result;
+    }
+};
+
+// set input
+template<class Archive, class Container>
+struct archive_input_set
+{
+    inline BOOST_DEDUCED_TYPENAME Container::iterator
+    operator()(
+        Archive &ar, 
+        Container &s, 
+        const unsigned int v,
+        BOOST_DEDUCED_TYPENAME Container::iterator hint
+    ){
+        typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
+        detail::stack_construct<Archive, type> t(ar, v);
+        // borland fails silently w/o full namespace
+        ar >> boost::serialization::make_nvp("item", t.reference());
+        BOOST_DEDUCED_TYPENAME Container::iterator result = 
+            s.insert(hint, t.reference());
+        ar.reset_object_address(& (* result), & t.reference());
+        return result;
+    }
+};
+
+template<class Container>
+class reserve_imp
+{
+public:
+    void operator()(Container &s, std::size_t count) const {
+        s.reserve(count);
+    }
+};
+
+template<class Container>
+class no_reserve_imp
+{
+public:
+    void operator()(Container & /* s */, std::size_t /* count */) const{}
+};
+
+template<class Archive, class Container, class InputFunction, class R>
+inline void load_collection(Archive & ar, Container &s)
+{
+    s.clear();
+    collection_size_type count;
+    const boost::archive::library_version_type library_version(
+        ar.get_library_version()
+    );
+    // retrieve number of elements
+    item_version_type item_version(0);
+    ar >> BOOST_SERIALIZATION_NVP(count);
+    if(boost::archive::library_version_type(3) < library_version){
+        ar >> BOOST_SERIALIZATION_NVP(item_version);
+    }
+
+    R rx;
+    rx(s, count);
+    InputFunction ifunc;
+    BOOST_DEDUCED_TYPENAME Container::iterator hint;
+    hint = s.begin();
+    while(count-- > 0){
+        hint = ifunc(ar, s, item_version, hint);
+    }
+}
+
+} // namespace stl 
+} // namespace serialization
+} // namespace boost
+
+#endif //BOOST_SERIALIZATION_COLLECTIONS_LOAD_IMP_HPP
diff --git a/SRC/Serialization/collections_save_imp.hpp b/SRC/Serialization/collections_save_imp.hpp
new file mode 100755
index 0000000..8c59a1a
--- /dev/null
+++ b/SRC/Serialization/collections_save_imp.hpp
@@ -0,0 +1,72 @@
+#ifndef BOOST_SERIALIZATION_COLLECTIONS_SAVE_IMP_HPP
+#define BOOST_SERIALIZATION_COLLECTIONS_SAVE_IMP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// collections_save_imp.hpp: serialization for stl collections
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// helper function templates for serialization of collections
+
+#include <boost/config.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/serialization.hpp>
+#include <Serialization/version.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/item_version_type.hpp>
+
+namespace boost{
+namespace serialization {
+namespace stl {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of serialization for STL containers
+//
+
+template<class Archive, class Container>
+inline void save_collection(Archive & ar, const Container &s)
+{
+    // record number of elements
+    collection_size_type count(s.size());
+    const item_version_type item_version(
+        version<BOOST_DEDUCED_TYPENAME Container::value_type>::value
+    );
+    ar << BOOST_SERIALIZATION_NVP(count);
+    #if 0
+        boost::archive::library_version_type library_version(
+            ar.get_library_version()
+        );
+        if(boost::archive::library_version_type(3) < library_version){
+            ar << BOOST_SERIALIZATION_NVP(item_version);
+        }
+    #else
+        ar << BOOST_SERIALIZATION_NVP(item_version);
+    #endif
+
+    BOOST_DEDUCED_TYPENAME Container::const_iterator it = s.begin();
+    while(count-- > 0){
+        // note borland emits a no-op without the explicit namespace
+        boost::serialization::save_construct_data_adl(
+            ar, 
+            &(*it), 
+            item_version
+        );
+        ar << boost::serialization::make_nvp("item", *it++);
+    }
+}
+
+} // namespace stl 
+} // namespace serialization
+} // namespace boost
+
+#endif //BOOST_SERIALIZATION_COLLECTIONS_SAVE_IMP_HPP
diff --git a/SRC/Serialization/complex.hpp b/SRC/Serialization/complex.hpp
new file mode 100755
index 0000000..6dd2ecf
--- /dev/null
+++ b/SRC/Serialization/complex.hpp
@@ -0,0 +1,81 @@
+#ifndef  BOOST_SERIALIZATION_COMPLEX_HPP
+#define BOOST_SERIALIZATION_COMPLEX_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization/utility.hpp:
+// serialization for stl utility templates
+
+// (C) Copyright 2007 Matthias Troyer . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <complex>
+#include <boost/config.hpp>
+
+#include <Serialization/nvp.hpp>
+#include <Serialization/is_bitwise_serializable.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class T>
+inline void serialize(
+    Archive & ar,
+    std::complex< T > & t,
+    const unsigned int file_version 
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+template<class Archive, class T>
+inline void save(
+    Archive & ar,
+    std::complex< T > const & t,
+    const unsigned int /* file_version */
+){
+    const T re = t.real();
+    const T im = t.imag();
+    ar << boost::serialization::make_nvp("real", re);
+    ar << boost::serialization::make_nvp("imag", im);
+}
+
+template<class Archive, class T>
+inline void load(
+    Archive & ar,
+    std::complex< T >& t,
+    const unsigned int /* file_version */ 
+){
+    T re;
+    T im;
+    ar >> boost::serialization::make_nvp("real", re);
+    ar >> boost::serialization::make_nvp("imag", im);
+    t = std::complex< T >(re,im);
+}
+
+// specialization of serialization traits for complex
+template <class T>
+struct is_bitwise_serializable<std::complex< T > >
+    : public is_bitwise_serializable< T > {};
+
+template <class T>
+struct implementation_level<std::complex< T > >
+    : mpl::int_<object_serializable> {} ;
+
+// treat complex just like builtin arithmetic types for tracking
+template <class T>
+struct tracking_level<std::complex< T > >
+    : mpl::int_<track_never> {} ;
+
+} // serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_COMPLEX_HPP
diff --git a/SRC/Serialization/config.hpp b/SRC/Serialization/config.hpp
new file mode 100755
index 0000000..89978c5
--- /dev/null
+++ b/SRC/Serialization/config.hpp
@@ -0,0 +1,85 @@
+#ifndef BOOST_SERIALIZATION_CONFIG_HPP
+#define BOOST_SERIALIZATION_CONFIG_HPP
+
+//  config.hpp  ---------------------------------------------//
+
+//  (c) Copyright Robert Ramey 2004
+//  Use, modification, and distribution is subject to the Boost Software
+//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+//  See library home page at http://www.boost.org/libs/serialization
+
+//----------------------------------------------------------------------------// 
+
+// This header implements separate compilation features as described in
+// http://www.boost.org/more/separate_compilation.html
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
+
+// note: this version incorporates the related code into the the 
+// the same library as BOOST_ARCHIVE.  This could change some day in the
+// future
+
+// if BOOST_SERIALIZATION_DECL is defined undefine it now:
+#ifdef BOOST_SERIALIZATION_DECL
+    #undef BOOST_SERIALIZATION_DECL
+#endif
+
+#ifdef BOOST_HAS_DECLSPEC // defined in config system
+// we need to import/export our code only if the user has specifically
+// asked for it by defining either BOOST_ALL_DYN_LINK if they want all boost
+// libraries to be dynamically linked, or BOOST_SERIALIZATION_DYN_LINK
+// if they want just this one to be dynamically liked:
+#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK)
+    #if !defined(BOOST_DYN_LINK)
+        #define BOOST_DYN_LINK
+    #endif
+    // export if this is our own source, otherwise import:
+    #if defined(BOOST_SERIALIZATION_SOURCE)
+        #if defined(__BORLANDC__)
+            #define BOOST_SERIALIZATION_DECL(T) T __export
+        #else
+            #define BOOST_SERIALIZATION_DECL(T) __declspec(dllexport) T
+        #endif
+    #else
+        #if defined(__BORLANDC__)
+            #define BOOST_SERIALIZATION_DECL(T) T __import
+        #else
+            #define BOOST_SERIALIZATION_DECL(T) __declspec(dllimport) T
+        #endif
+    #endif // defined(BOOST_SERIALIZATION_SOURCE)
+#endif // defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK)
+#endif // BOOST_HAS_DECLSPEC
+
+// if BOOST_SERIALIZATION_DECL isn't defined yet define it now:
+#ifndef BOOST_SERIALIZATION_DECL
+    #define BOOST_SERIALIZATION_DECL(T) T
+#endif
+
+//  enable automatic library variant selection  ------------------------------// 
+
+#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_SERIALIZATION_NO_LIB) \
+&&  !defined(BOOST_ARCHIVE_SOURCE) && !defined(BOOST_WARCHIVE_SOURCE)  \
+&&  !defined(BOOST_SERIALIZATION_SOURCE)
+    //
+    // Set the name of our library, this will get undef'ed by auto_link.hpp
+    // once it's done with it:
+    //
+    #define BOOST_LIB_NAME boost_serialization
+    //
+    // If we're importing code from a dll, then tell auto_link.hpp about it:
+    //
+    #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_SERIALIZATION_DYN_LINK)
+    #  define BOOST_DYN_LINK
+    #endif
+    //
+    // And include the header that does the work:
+    //
+    #include <boost/config/auto_link.hpp>
+
+#endif  
+
+#endif // BOOST_SERIALIZATION_CONFIG_HPP
diff --git a/SRC/Serialization/deque.hpp b/SRC/Serialization/deque.hpp
new file mode 100755
index 0000000..636cd11
--- /dev/null
+++ b/SRC/Serialization/deque.hpp
@@ -0,0 +1,75 @@
+#ifndef  BOOST_SERIALIZATION_DEQUE_HPP
+#define BOOST_SERIALIZATION_DEQUE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// deque.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <deque>
+
+#include <boost/config.hpp>
+
+#include <Serialization/collections_save_imp.hpp>
+#include <Serialization/collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class U, class Allocator>
+inline void save(
+    Archive & ar,
+    const std::deque<U, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::save_collection<
+        Archive, std::deque<U, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class U, class Allocator>
+inline void load(
+    Archive & ar,
+    std::deque<U, Allocator> &t,
+    const unsigned int /*file_version*/
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::deque<U, Allocator>,
+        boost::serialization::stl::archive_input_seq<
+        Archive, std::deque<U, Allocator> 
+        >,
+        boost::serialization::stl::no_reserve_imp<std::deque<U, Allocator> >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class U, class Allocator>
+inline void serialize(
+    Archive & ar,
+    std::deque<U, Allocator> &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(std::deque)
+
+#endif // BOOST_SERIALIZATION_DEQUE_HPP
diff --git a/SRC/Serialization/detail/get_data.hpp b/SRC/Serialization/detail/get_data.hpp
new file mode 100755
index 0000000..7b6bc89
--- /dev/null
+++ b/SRC/Serialization/detail/get_data.hpp
@@ -0,0 +1,55 @@
+// (C) Copyright 2005 Matthias Troyer 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#ifndef BOOST_SERIALIZATION_DETAIL_GET_DATA_HPP
+#define BOOST_SERIALIZATION_DETAIL_GET_DATA_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
+#define STD _STLP_STD
+#else
+#define STD std
+#endif
+
+
+#include <vector>
+#include <valarray>
+
+namespace boost { namespace serialization { namespace detail {
+
+template <class T, class Allocator>
+T* get_data(STD::vector<T,Allocator>& v)
+{
+  return v.empty() ? 0 : &(v[0]);
+}
+
+template <class T, class Allocator>
+T* get_data(STD::vector<T,Allocator> const & v)
+{
+  return get_data(const_cast<STD::vector<T,Allocator>&>(v));
+}
+
+
+template <class T>
+T* get_data(STD::valarray<T>& v)
+{
+  return v.size()==0 ? 0 : &(v[0]);
+}
+
+template <class T>
+const T* get_data(STD::valarray<T> const& v)
+{
+  return get_data(const_cast<STD::valarray<T>&>(v));
+}
+
+} } } //namespace boost::serialization::detail
+
+#endif // BOOST_SERIALIZATION_DETAIL_GET_DATA_HPP
diff --git a/SRC/Serialization/detail/shared_count_132.hpp b/SRC/Serialization/detail/shared_count_132.hpp
new file mode 100755
index 0000000..6133a26
--- /dev/null
+++ b/SRC/Serialization/detail/shared_count_132.hpp
@@ -0,0 +1,569 @@
+#ifndef BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
+#define BOOST_DETAIL_SHARED_COUNT_132_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//
+//  detail/shared_count.hpp
+//
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#include <boost/config.hpp>
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR) && defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+# error BOOST_SP_USE_STD_ALLOCATOR and BOOST_SP_USE_QUICK_ALLOCATOR are incompatible.
+#endif
+
+#include <boost/checked_delete.hpp>
+#include <Serialization/throw_exception.hpp>
+#include <boost/detail/lightweight_mutex.hpp>
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+#include <boost/detail/quick_allocator.hpp>
+#endif
+
+#include <memory>           // std::auto_ptr, std::allocator
+#include <functional>       // std::less
+#include <exception>        // std::exception
+#include <new>              // std::bad_alloc
+#include <typeinfo>         // std::type_info in get_deleter
+#include <cstddef>          // std::size_t
+
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#ifdef __BORLANDC__
+# pragma warn -8026     // Functions with excep. spec. are not expanded inline
+# pragma warn -8027     // Functions containing try are not expanded inline
+#endif
+
+namespace boost_132 {
+
+// Debug hooks
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+void sp_scalar_constructor_hook(void * px, std::size_t size, void * pn);
+void sp_array_constructor_hook(void * px);
+void sp_scalar_destructor_hook(void * px, std::size_t size, void * pn);
+void sp_array_destructor_hook(void * px);
+
+#endif
+
+
+// The standard library that comes with Borland C++ 5.5.1
+// defines std::exception and its members as having C calling
+// convention (-pc). When the definition of bad_weak_ptr
+// is compiled with -ps, the compiler issues an error.
+// Hence, the temporary #pragma option -pc below. The version
+// check is deliberately conservative.
+
+#if defined(__BORLANDC__) && __BORLANDC__ == 0x551
+# pragma option push -pc
+#endif
+
+class bad_weak_ptr: public std::exception
+{
+public:
+
+    virtual char const * what() const throw()
+    {
+        return "boost::bad_weak_ptr";
+    }
+};
+
+#if defined(__BORLANDC__) && __BORLANDC__ == 0x551
+# pragma option pop
+#endif
+
+namespace detail{
+
+class sp_counted_base
+{
+//private:
+
+    typedef boost::detail::lightweight_mutex mutex_type;
+
+public:
+
+    sp_counted_base(): use_count_(1), weak_count_(1)
+    {
+    }
+
+    virtual ~sp_counted_base() // nothrow
+    {
+    }
+
+    // dispose() is called when use_count_ drops to zero, to release
+    // the resources managed by *this.
+
+    virtual void dispose() = 0; // nothrow
+
+    // destruct() is called when weak_count_ drops to zero.
+
+    virtual void destruct() // nothrow
+    {
+        delete this;
+    }
+
+    virtual void * get_deleter(std::type_info const & ti) = 0;
+
+    void add_ref_copy()
+    {
+#if defined(BOOST_HAS_THREADS)
+        mutex_type::scoped_lock lock(mtx_);
+#endif
+        ++use_count_;
+    }
+
+    void add_ref_lock()
+    {
+#if defined(BOOST_HAS_THREADS)
+        mutex_type::scoped_lock lock(mtx_);
+#endif
+        if(use_count_ == 0) boost::serialization::throw_exception(bad_weak_ptr());
+        ++use_count_;
+    }
+
+    void release() // nothrow
+    {
+        {
+#if defined(BOOST_HAS_THREADS)
+            mutex_type::scoped_lock lock(mtx_);
+#endif
+            long new_use_count = --use_count_;
+
+            if(new_use_count != 0) return;
+        }
+
+        dispose();
+        weak_release();
+    }
+
+    void weak_add_ref() // nothrow
+    {
+#if defined(BOOST_HAS_THREADS)
+        mutex_type::scoped_lock lock(mtx_);
+#endif
+        ++weak_count_;
+    }
+
+    void weak_release() // nothrow
+    {
+        long new_weak_count;
+
+        {
+#if defined(BOOST_HAS_THREADS)
+            mutex_type::scoped_lock lock(mtx_);
+#endif
+            new_weak_count = --weak_count_;
+        }
+
+        if(new_weak_count == 0)
+        {
+            destruct();
+        }
+    }
+
+    long use_count() const // nothrow
+    {
+#if defined(BOOST_HAS_THREADS)
+        mutex_type::scoped_lock lock(mtx_);
+#endif
+        return use_count_;
+    }
+
+//private:
+public:
+    sp_counted_base(sp_counted_base const &);
+    sp_counted_base & operator= (sp_counted_base const &);
+
+    long use_count_;        // #shared
+    long weak_count_;       // #weak + (#shared != 0)
+
+#if defined(BOOST_HAS_THREADS) || defined(BOOST_LWM_WIN32)
+    mutable mutex_type mtx_;
+#endif
+};
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+template<class T> void cbi_call_constructor_hook(sp_counted_base * pn, T * px, checked_deleter< T > const &, int)
+{
+    boost::sp_scalar_constructor_hook(px, sizeof(T), pn);
+}
+
+template<class T> void cbi_call_constructor_hook(sp_counted_base *, T * px, checked_array_deleter< T > const &, int)
+{
+    boost::sp_array_constructor_hook(px);
+}
+
+template<class P, class D> void cbi_call_constructor_hook(sp_counted_base *, P const &, D const &, long)
+{
+}
+
+template<class T> void cbi_call_destructor_hook(sp_counted_base * pn, T * px, checked_deleter< T > const &, int)
+{
+    boost::sp_scalar_destructor_hook(px, sizeof(T), pn);
+}
+
+template<class T> void cbi_call_destructor_hook(sp_counted_base *, T * px, checked_array_deleter< T > const &, int)
+{
+    boost::sp_array_destructor_hook(px);
+}
+
+template<class P, class D> void cbi_call_destructor_hook(sp_counted_base *, P const &, D const &, long)
+{
+}
+
+#endif
+
+//
+// Borland's Codeguard trips up over the -Vx- option here:
+//
+#ifdef __CODEGUARD__
+# pragma option push -Vx-
+#endif
+
+template<class P, class D> class sp_counted_base_impl: public sp_counted_base
+{
+//private:
+public:
+    P ptr; // copy constructor must not throw
+    D del; // copy constructor must not throw
+
+    sp_counted_base_impl(sp_counted_base_impl const &);
+    sp_counted_base_impl & operator= (sp_counted_base_impl const &);
+
+    typedef sp_counted_base_impl<P, D> this_type;
+
+public:
+
+    // pre: initial_use_count <= initial_weak_count, d(p) must not throw
+
+    sp_counted_base_impl(P p, D d): ptr(p), del(d)
+    {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        detail::cbi_call_constructor_hook(this, p, d, 0);
+#endif
+    }
+
+    virtual void dispose() // nothrow
+    {
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        detail::cbi_call_destructor_hook(this, ptr, del, 0);
+#endif
+        del(ptr);
+    }
+
+    virtual void * get_deleter(std::type_info const & ti)
+    {
+        return ti == typeid(D)? &del: 0;
+    }
+
+#if defined(BOOST_SP_USE_STD_ALLOCATOR)
+
+    void * operator new(std::size_t)
+    {
+        return std::allocator<this_type>().allocate(1, static_cast<this_type *>(0));
+    }
+
+    void operator delete(void * p)
+    {
+        std::allocator<this_type>().deallocate(static_cast<this_type *>(p), 1);
+    }
+
+#endif
+
+#if defined(BOOST_SP_USE_QUICK_ALLOCATOR)
+
+    void * operator new(std::size_t)
+    {
+        return boost::detail::quick_allocator<this_type>::alloc();
+    }
+
+    void operator delete(void * p)
+    {
+        boost::detail::quick_allocator<this_type>::dealloc(p);
+    }
+
+#endif
+};
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+
+int const shared_count_id = 0x2C35F101;
+int const   weak_count_id = 0x298C38A4;
+
+#endif
+
+class weak_count;
+
+class shared_count
+{
+//private:
+public:
+    sp_counted_base * pi_;
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+    int id_;
+#endif
+
+    friend class weak_count;
+
+public:
+
+    shared_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(shared_count_id)
+#endif
+    {
+    }
+
+    template<class P, class D> shared_count(P p, D d): pi_(0)
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(shared_count_id)
+#endif
+    {
+#ifndef BOOST_NO_EXCEPTIONS
+
+        try
+        {
+            pi_ = new sp_counted_base_impl<P, D>(p, d);
+        }
+        catch(...)
+        {
+            d(p); // delete p
+            throw;
+        }
+
+#else
+
+        pi_ = new sp_counted_base_impl<P, D>(p, d);
+
+        if(pi_ == 0)
+        {
+            d(p); // delete p
+            boost::serialization::throw_exception(std::bad_alloc());
+        }
+
+#endif
+    }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+    // auto_ptr<Y> is special cased to provide the strong guarantee
+
+    template<class Y>
+    explicit shared_count(std::unique_ptr<Y> & r): pi_(
+        new sp_counted_base_impl<
+            Y *, 
+            boost::checked_deleter<Y>
+        >(r.get(), boost::checked_deleter<Y>()))
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(shared_count_id)
+#endif
+    {
+        r.release();
+    }
+
+#endif 
+
+    ~shared_count() // nothrow
+    {
+        if(pi_ != 0) pi_->release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        id_ = 0;
+#endif
+    }
+
+    shared_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(shared_count_id)
+#endif
+    {
+        if(pi_ != 0) pi_->add_ref_copy();
+    }
+
+    explicit shared_count(weak_count const & r); // throws bad_weak_ptr when r.use_count() == 0
+
+    shared_count & operator= (shared_count const & r) // nothrow
+    {
+        sp_counted_base * tmp = r.pi_;
+
+        if(tmp != pi_)
+        {
+            if(tmp != 0) tmp->add_ref_copy();
+            if(pi_ != 0) pi_->release();
+            pi_ = tmp;
+        }
+
+        return *this;
+    }
+
+    void swap(shared_count & r) // nothrow
+    {
+        sp_counted_base * tmp = r.pi_;
+        r.pi_ = pi_;
+        pi_ = tmp;
+    }
+
+    long use_count() const // nothrow
+    {
+        return pi_ != 0? pi_->use_count(): 0;
+    }
+
+    bool unique() const // nothrow
+    {
+        return use_count() == 1;
+    }
+
+    friend inline bool operator==(shared_count const & a, shared_count const & b)
+    {
+        return a.pi_ == b.pi_;
+    }
+
+    friend inline bool operator<(shared_count const & a, shared_count const & b)
+    {
+        return std::less<sp_counted_base *>()(a.pi_, b.pi_);
+    }
+
+    void * get_deleter(std::type_info const & ti) const
+    {
+        return pi_? pi_->get_deleter(ti): 0;
+    }
+};
+
+#ifdef __CODEGUARD__
+# pragma option pop
+#endif
+
+
+class weak_count
+{
+private:
+
+    sp_counted_base * pi_;
+
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+    int id_;
+#endif
+
+    friend class shared_count;
+
+public:
+
+    weak_count(): pi_(0) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(weak_count_id)
+#endif
+    {
+    }
+
+    weak_count(shared_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(shared_count_id)
+#endif
+    {
+        if(pi_ != 0) pi_->weak_add_ref();
+    }
+
+    weak_count(weak_count const & r): pi_(r.pi_) // nothrow
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(shared_count_id)
+#endif
+    {
+        if(pi_ != 0) pi_->weak_add_ref();
+    }
+
+    ~weak_count() // nothrow
+    {
+        if(pi_ != 0) pi_->weak_release();
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        id_ = 0;
+#endif
+    }
+
+    weak_count & operator= (shared_count const & r) // nothrow
+    {
+        sp_counted_base * tmp = r.pi_;
+        if(tmp != 0) tmp->weak_add_ref();
+        if(pi_ != 0) pi_->weak_release();
+        pi_ = tmp;
+
+        return *this;
+    }
+
+    weak_count & operator= (weak_count const & r) // nothrow
+    {
+        sp_counted_base * tmp = r.pi_;
+        if(tmp != 0) tmp->weak_add_ref();
+        if(pi_ != 0) pi_->weak_release();
+        pi_ = tmp;
+
+        return *this;
+    }
+
+    void swap(weak_count & r) // nothrow
+    {
+        sp_counted_base * tmp = r.pi_;
+        r.pi_ = pi_;
+        pi_ = tmp;
+    }
+
+    long use_count() const // nothrow
+    {
+        return pi_ != 0? pi_->use_count(): 0;
+    }
+
+    friend inline bool operator==(weak_count const & a, weak_count const & b)
+    {
+        return a.pi_ == b.pi_;
+    }
+
+    friend inline bool operator<(weak_count const & a, weak_count const & b)
+    {
+        return std::less<sp_counted_base *>()(a.pi_, b.pi_);
+    }
+};
+
+inline shared_count::shared_count(weak_count const & r): pi_(r.pi_)
+#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
+        , id_(shared_count_id)
+#endif
+{
+    if(pi_ != 0)
+    {
+        pi_->add_ref_lock();
+    }
+    else
+    {
+        boost::serialization::throw_exception(bad_weak_ptr());
+    }
+}
+
+} // namespace detail
+
+} // namespace boost
+
+BOOST_SERIALIZATION_ASSUME_ABSTRACT(boost_132::detail::sp_counted_base)
+
+#ifdef __BORLANDC__
+# pragma warn .8027     // Functions containing try are not expanded inline
+# pragma warn .8026     // Functions with excep. spec. are not expanded inline
+#endif
+
+#endif  // #ifndef BOOST_DETAIL_SHARED_COUNT_HPP_INCLUDED
diff --git a/SRC/Serialization/detail/shared_ptr_132.hpp b/SRC/Serialization/detail/shared_ptr_132.hpp
new file mode 100755
index 0000000..c19685e
--- /dev/null
+++ b/SRC/Serialization/detail/shared_ptr_132.hpp
@@ -0,0 +1,478 @@
+#ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED
+#define BOOST_SHARED_PTR_132_HPP_INCLUDED
+
+//
+//  shared_ptr.hpp
+//
+//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+//  Copyright (c) 2001, 2002, 2003 Peter Dimov
+//
+//  Distributed under the Boost Software License, Version 1.0. (See
+//  accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+//
+//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
+//
+
+#include <boost/config.hpp>   // for broken compiler workarounds
+
+#if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+#include <Serialization/detail/shared_ptr_nmt_132.hpp>
+#else
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <Serialization/throw_exception.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <Serialization/access.hpp>
+#include <Serialization/detail/shared_count_132.hpp>
+
+#include <memory>               // for std::auto_ptr
+#include <algorithm>            // for std::swap
+#include <functional>           // for std::less
+#include <typeinfo>             // for std::bad_cast
+#include <iosfwd>               // for std::basic_ostream
+
+#ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
+# pragma warning(push)
+# pragma warning(disable:4284) // odd return type for operator->
+#endif
+
+namespace boost_132 {
+
+template<class T> class weak_ptr;
+template<class T> class enable_shared_from_this;
+
+namespace detail
+{
+
+struct static_cast_tag {};
+struct const_cast_tag {};
+struct dynamic_cast_tag {};
+struct polymorphic_cast_tag {};
+
+template<class T> struct shared_ptr_traits
+{
+    typedef T & reference;
+};
+
+template<> struct shared_ptr_traits<void>
+{
+    typedef void reference;
+};
+
+#if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
+
+template<> struct shared_ptr_traits<void const>
+{
+    typedef void reference;
+};
+
+template<> struct shared_ptr_traits<void volatile>
+{
+    typedef void reference;
+};
+
+template<> struct shared_ptr_traits<void const volatile>
+{
+    typedef void reference;
+};
+
+#endif
+
+// enable_shared_from_this support
+
+template<class T, class Y> void sp_enable_shared_from_this( shared_count const & pn, enable_shared_from_this< T > const * pe, Y const * px )
+{
+    if(pe != 0) pe->_internal_weak_this._internal_assign(const_cast<Y*>(px), pn);
+}
+
+inline void sp_enable_shared_from_this( shared_count const & /*pn*/, ... )
+{
+}
+
+} // namespace detail
+
+
+//
+//  shared_ptr
+//
+//  An enhanced relative of scoped_ptr with reference counted copy semantics.
+//  The object pointed to is deleted when the last shared_ptr pointing to it
+//  is destroyed or reset.
+//
+
+template<class T> class shared_ptr
+{
+private:
+    // Borland 5.5.1 specific workaround
+    typedef shared_ptr< T > this_type;
+
+public:
+
+    typedef T element_type;
+    typedef T value_type;
+    typedef T * pointer;
+    typedef BOOST_DEDUCED_TYPENAME detail::shared_ptr_traits< T >::reference reference;
+
+    shared_ptr(): px(0), pn() // never throws in 1.30+
+    {
+    }
+
+#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x564) )
+    template<class Y>
+    explicit shared_ptr(Y * p): px(p), pn(p, boost::checked_deleter<Y>()) // Y must be complete
+#else
+    template<class Y>
+    explicit shared_ptr(Y * p): px(p), pn(p, boost::checked_deleter<Y>()) // Y must be complete
+#endif
+    {
+        detail::sp_enable_shared_from_this( pn, p, p );
+    }
+
+    //
+    // Requirements: D's copy constructor must not throw
+    //
+    // shared_ptr will release p by calling d(p)
+    //
+
+    template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
+    {
+        detail::sp_enable_shared_from_this( pn, p, p );
+    }
+
+//  generated copy constructor, assignment, destructor are fine...
+
+//  except that Borland C++ has a bug, and g++ with -Wsynth warns
+#if defined(__BORLANDC__) || defined(__GNUC__)
+
+    shared_ptr & operator=(shared_ptr const & r) // never throws
+    {
+        px = r.px;
+        pn = r.pn; // shared_count::op= doesn't throw
+        return *this;
+    }
+
+#endif
+
+    template<class Y>
+    explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
+    {
+        // it is now safe to copy r.px, as pn(r.pn) did not throw
+        px = r.px;
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
+    {
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
+    {
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::const_cast_tag): px(const_cast<element_type *>(r.px)), pn(r.pn)
+    {
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
+    {
+        if(px == 0) // need to allocate new counter -- the cast failed
+        {
+            pn = detail::shared_count();
+        }
+    }
+
+    template<class Y>
+    shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
+    {
+        if(px == 0)
+        {
+            boost::serialization::throw_exception(std::bad_cast());
+        }
+    }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+    template<class Y>
+    explicit shared_ptr(std::unique_ptr<Y> & r): px(r.get()), pn()
+    {
+        Y * tmp = r.get();
+        pn = detail::shared_count(r);
+        detail::sp_enable_shared_from_this( pn, tmp, tmp );
+    }
+
+#endif
+
+#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
+
+    template<class Y>
+    shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
+    {
+        px = r.px;
+        pn = r.pn; // shared_count::op= doesn't throw
+        return *this;
+    }
+
+#endif
+
+#ifndef BOOST_NO_AUTO_PTR
+
+    template<class Y>
+    shared_ptr & operator=(std::unique_ptr<Y> & r)
+    {
+        this_type(r).swap(*this);
+        return *this;
+    }
+
+#endif
+
+    void reset() // never throws in 1.30+
+    {
+        this_type().swap(*this);
+    }
+
+    template<class Y> void reset(Y * p) // Y must be complete
+    {
+        BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
+        this_type(p).swap(*this);
+    }
+
+    template<class Y, class D> void reset(Y * p, D d)
+    {
+        this_type(p, d).swap(*this);
+    }
+
+    reference operator* () const // never throws
+    {
+        BOOST_ASSERT(px != 0);
+        return *px;
+    }
+
+    T * operator-> () const // never throws
+    {
+        BOOST_ASSERT(px != 0);
+        return px;
+    }
+    
+    T * get() const // never throws
+    {
+        return px;
+    }
+
+    // implicit conversion to "bool"
+
+#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
+
+    operator bool () const
+    {
+        return px != 0;
+    }
+
+#elif defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003))
+    typedef T * (this_type::*unspecified_bool_type)() const;
+    
+    operator unspecified_bool_type() const // never throws
+    {
+        return px == 0? 0: &this_type::get;
+    }
+
+#else 
+
+    typedef T * this_type::*unspecified_bool_type;
+
+    operator unspecified_bool_type() const // never throws
+    {
+        return px == 0? 0: &this_type::px;
+    }
+
+#endif
+
+    // operator! is redundant, but some compilers need it
+
+    bool operator! () const // never throws
+    {
+        return px == 0;
+    }
+
+    bool unique() const // never throws
+    {
+        return pn.unique();
+    }
+
+    long use_count() const // never throws
+    {
+        return pn.use_count();
+    }
+
+    void swap(shared_ptr< T > & other) // never throws
+    {
+        std::swap(px, other.px);
+        pn.swap(other.pn);
+    }
+
+    template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
+    {
+        return pn < rhs.pn;
+    }
+
+    void * _internal_get_deleter(std::type_info const & ti) const
+    {
+        return pn.get_deleter(ti);
+    }
+
+// Tasteless as this may seem, making all members public allows member templates
+// to work in the absence of member template friends. (Matthew Langston)
+
+#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
+
+private:
+
+    template<class Y> friend class shared_ptr;
+    template<class Y> friend class weak_ptr;
+
+
+#endif
+public: // for serialization
+    T * px;                     // contained pointer
+    detail::shared_count pn;    // reference counter
+
+};  // shared_ptr
+
+template<class T, class U> inline bool operator==(shared_ptr< T > const & a, shared_ptr<U> const & b)
+{
+    return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=(shared_ptr< T > const & a, shared_ptr<U> const & b)
+{
+    return a.get() != b.get();
+}
+
+#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
+
+// Resolve the ambiguity between our op!= and the one in rel_ops
+
+template<class T> inline bool operator!=(shared_ptr< T > const & a, shared_ptr< T > const & b)
+{
+    return a.get() != b.get();
+}
+
+#endif
+
+template<class T, class U> inline bool operator<(shared_ptr< T > const & a, shared_ptr<U> const & b)
+{
+    return a._internal_less(b);
+}
+
+template<class T> inline void swap(shared_ptr< T > & a, shared_ptr< T > & b)
+{
+    a.swap(b);
+}
+
+template<class T, class U> shared_ptr< T > static_pointer_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr< T >(r, detail::static_cast_tag());
+}
+
+template<class T, class U> shared_ptr< T > const_pointer_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr< T >(r, detail::const_cast_tag());
+}
+
+template<class T, class U> shared_ptr< T > dynamic_pointer_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr< T >(r, detail::dynamic_cast_tag());
+}
+
+// shared_*_cast names are deprecated. Use *_pointer_cast instead.
+
+template<class T, class U> shared_ptr< T > shared_static_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr< T >(r, detail::static_cast_tag());
+}
+
+template<class T, class U> shared_ptr< T > shared_dynamic_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr< T >(r, detail::dynamic_cast_tag());
+}
+
+template<class T, class U> shared_ptr< T > shared_polymorphic_cast(shared_ptr<U> const & r)
+{
+    return shared_ptr< T >(r, detail::polymorphic_cast_tag());
+}
+
+template<class T, class U> shared_ptr< T > shared_polymorphic_downcast(shared_ptr<U> const & r)
+{
+    BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
+    return shared_static_cast< T >(r);
+}
+
+// get_pointer() enables boost::mem_fn to recognize shared_ptr
+
+template<class T> inline T * get_pointer(shared_ptr< T > const & p)
+{
+    return p.get();
+}
+
+// operator<<
+
+#if defined(__GNUC__) &&  (__GNUC__ < 3)
+
+template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
+{
+    os << p.get();
+    return os;
+}
+
+#else
+
+# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
+// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
+using std::basic_ostream;
+template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# else
+template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
+# endif 
+{
+    os << p.get();
+    return os;
+}
+
+#endif
+
+// get_deleter (experimental)
+
+#if (defined(__GNUC__) &&  (__GNUC__ < 3)) || (defined(__EDG_VERSION__) && (__EDG_VERSION__ <= 238))
+
+// g++ 2.9x doesn't allow static_cast<X const *>(void *)
+// apparently EDG 2.38 also doesn't accept it
+
+template<class D, class T> D * get_deleter(shared_ptr< T > const & p)
+{
+    void const * q = p._internal_get_deleter(typeid(D));
+    return const_cast<D *>(static_cast<D const *>(q));
+}
+
+#else
+
+template<class D, class T> D * get_deleter(shared_ptr< T > const & p)
+{
+    return static_cast<D *>(p._internal_get_deleter(typeid(D)));
+}
+
+#endif
+
+} // namespace boost
+
+#ifdef BOOST_MSVC
+# pragma warning(pop)
+#endif    
+
+#endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
+
+#endif  // #ifndef BOOST_SHARED_PTR_132_HPP_INCLUDED
diff --git a/SRC/Serialization/detail/shared_ptr_nmt_132.hpp b/SRC/Serialization/detail/shared_ptr_nmt_132.hpp
new file mode 100755
index 0000000..19fea6e
--- /dev/null
+++ b/SRC/Serialization/detail/shared_ptr_nmt_132.hpp
@@ -0,0 +1,182 @@
+#ifndef BOOST_DETAIL_SHARED_PTR_NMT_132_HPP_INCLUDED
+#define BOOST_DETAIL_SHARED_PTR_NMT_132_HPP_INCLUDED
+
+//
+//  detail/shared_ptr_nmt.hpp - shared_ptr.hpp without member templates
+//
+//  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
+//  Copyright (c) 2001, 2002 Peter Dimov
+//
+//  Distributed under the Boost Software License, Version 1.0. (See
+//  accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+//
+//  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
+//
+
+#include <boost/assert.hpp>
+#include <boost/checked_delete.hpp>
+#include <Serialization/throw_exception.hpp>
+#include <boost/detail/atomic_count.hpp>
+
+#ifndef BOOST_NO_AUTO_PTR
+# include <memory>          // for std::auto_ptr
+#endif
+
+#include <algorithm>        // for std::swap
+#include <functional>       // for std::less
+#include <new>              // for std::bad_alloc
+
+namespace boost
+{
+
+template<class T> class shared_ptr
+{
+private:
+
+    typedef detail::atomic_count count_type;
+
+public:
+
+    typedef T element_type;
+    typedef T value_type;
+
+    explicit shared_ptr(T * p = 0): px(p)
+    {
+#ifndef BOOST_NO_EXCEPTIONS
+
+        try  // prevent leak if new throws
+        {
+            pn = new count_type(1);
+        }
+        catch(...)
+        {
+            boost::checked_delete(p);
+            throw;
+        }
+
+#else
+
+        pn = new count_type(1);
+
+        if(pn == 0)
+        {
+            boost::checked_delete(p);
+            boost::serialization::throw_exception(std::bad_alloc());
+        }
+
+#endif
+    }
+
+    ~shared_ptr()
+    {
+        if(--*pn == 0)
+        {
+            boost::checked_delete(px);
+            delete pn;
+        }
+    }
+
+    shared_ptr(shared_ptr const & r): px(r.px)  // never throws
+    {
+        pn = r.pn;
+        ++*pn;
+    }
+
+    shared_ptr & operator=(shared_ptr const & r)
+    {
+        shared_ptr(r).swap(*this);
+        return *this;
+    }
+
+#ifndef BOOST_NO_AUTO_PTR
+
+    explicit shared_ptr(std::auto_ptr< T > & r)
+    { 
+        pn = new count_type(1); // may throw
+        px = r.release(); // fix: moved here to stop leak if new throws
+    } 
+
+    shared_ptr & operator=(std::auto_ptr< T > & r)
+    {
+        shared_ptr(r).swap(*this);
+        return *this;
+    }
+
+#endif
+
+    void reset(T * p = 0)
+    {
+        BOOST_ASSERT(p == 0 || p != px);
+        shared_ptr(p).swap(*this);
+    }
+
+    T & operator*() const  // never throws
+    {
+        BOOST_ASSERT(px != 0);
+        return *px;
+    }
+
+    T * operator->() const  // never throws
+    {
+        BOOST_ASSERT(px != 0);
+        return px;
+    }
+
+    T * get() const  // never throws
+    {
+        return px;
+    }
+
+    long use_count() const  // never throws
+    {
+        return *pn;
+    }
+
+    bool unique() const  // never throws
+    {
+        return *pn == 1;
+    }
+    
+    void swap(shared_ptr< T > & other)  // never throws
+    {
+        std::swap(px, other.px);
+        std::swap(pn, other.pn);
+    }
+
+private:
+
+    T * px;            // contained pointer
+    count_type * pn;   // ptr to reference counter
+};
+
+template<class T, class U> inline bool operator==(shared_ptr< T > const & a, shared_ptr<U> const & b)
+{
+    return a.get() == b.get();
+}
+
+template<class T, class U> inline bool operator!=(shared_ptr< T > const & a, shared_ptr<U> const & b)
+{
+    return a.get() != b.get();
+}
+
+template<class T> inline bool operator<(shared_ptr< T > const & a, shared_ptr< T > const & b)
+{
+    return std::less<T*>()(a.get(), b.get());
+}
+
+template<class T> void swap(shared_ptr< T > & a, shared_ptr< T > & b)
+{
+    a.swap(b);
+}
+
+// get_pointer() enables boost::mem_fn to recognize shared_ptr
+
+template<class T> inline T * get_pointer(shared_ptr< T > const & p)
+{
+    return p.get();
+}
+
+} // namespace boost
+
+#endif  // #ifndef BOOST_DETAIL_SHARED_PTR_NMT_132_HPP_INCLUDED
diff --git a/SRC/Serialization/detail/stack_constructor.hpp b/SRC/Serialization/detail/stack_constructor.hpp
new file mode 100755
index 0000000..2c01c66
--- /dev/null
+++ b/SRC/Serialization/detail/stack_constructor.hpp
@@ -0,0 +1,73 @@
+#ifndef  BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
+#define BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1020)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// collections_load_imp.hpp: serialization for loading stl collections
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/aligned_storage.hpp>
+
+namespace boost{
+namespace serialization {
+namespace detail {
+
+// reserve space on stack for an object of type T without actually
+// construction such an object
+template<typename T > 
+struct stack_allocate
+{
+    T * address() {
+        return static_cast<T*>(storage_.address()); 
+    }
+    T & reference() {
+        return * address();
+    }
+private:
+    typedef BOOST_DEDUCED_TYPENAME boost::aligned_storage<
+        sizeof(T), 
+        #if BOOST_WORKAROUND(__BORLANDC__,BOOST_TESTED_AT(0x560))
+            8
+        #else
+            boost::alignment_of<T>::value
+        #endif
+    > type;
+    type storage_;
+};
+
+// construct element on the stack
+template<class Archive, class T>
+struct stack_construct : public stack_allocate<T>
+{
+    stack_construct(Archive & ar, const unsigned int version){
+        // note borland emits a no-op without the explicit namespace
+        boost::serialization::load_construct_data_adl(
+            ar, 
+            this->address(), 
+            version
+        );
+    }
+    ~stack_construct(){
+        this->address()->~T(); // undo load_construct_data above
+    }
+};
+
+} // detail
+} // serializaition
+} // boost
+
+#endif //  BOOST_SERIALIZATION_DETAIL_STACH_CONSTRUCTOR_HPP
diff --git a/SRC/Serialization/ephemeral.hpp b/SRC/Serialization/ephemeral.hpp
new file mode 100755
index 0000000..191f096
--- /dev/null
+++ b/SRC/Serialization/ephemeral.hpp
@@ -0,0 +1,80 @@
+#ifndef BOOST_SERIALIZATION_EPHEMERAL_HPP
+#define BOOST_SERIALIZATION_EPHEMERAL_HPP
+
+// MS compatible compilers support 
+#pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// ephemeral_object.hpp: interface for serialization system.
+
+// (C) Copyright 2007 Matthias Troyer. 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <utility>
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+// supress noise
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
+# pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+
+#include <Serialization/level.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/split_member.hpp>
+#include <Serialization/base_object.hpp>
+#include <Serialization/traits.hpp>
+#include <Serialization/wrapper.hpp>
+
+namespace boost {
+namespace serialization {
+
+template<class T>
+struct ephemeral_object : 
+    public wrapper_traits<ephemeral_object<T> >
+{
+    explicit ephemeral_object(T& t) :
+        val(t)
+    {}
+
+    T & value() const {
+        return val;
+    }
+
+    const T & const_value() const {
+        return val;
+    }
+
+    template<class Archive>
+    void serialize(Archive &ar, const unsigned int) const
+    {
+       ar & val;
+    }
+
+private:
+    T & val;
+};
+
+template<class T>
+inline
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+const
+#endif
+ephemeral_object<T> ephemeral(const char * name, T & t){
+    return ephemeral_object<T>(name, t);
+}
+
+} // seralization
+} // boost
+
+#endif // BOOST_SERIALIZATION_EPHEMERAL_HPP
diff --git a/SRC/Serialization/export.hpp b/SRC/Serialization/export.hpp
new file mode 100755
index 0000000..fd99476
--- /dev/null
+++ b/SRC/Serialization/export.hpp
@@ -0,0 +1,234 @@
+#ifndef BOOST_SERIALIZATION_EXPORT_HPP
+#define BOOST_SERIALIZATION_EXPORT_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// export.hpp: set traits of classes to be serialized
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com .
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// (C) Copyright 2006 David Abrahams - http://www.boost.org.
+// implementation of class export functionality.  This is an alternative to
+// "forward declaration" method to provoke instantiation of derived classes
+// that are to be serialized through pointers.
+
+#include <utility>
+#include <cstddef> // NULL
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <Serialization/extended_type_info.hpp> // for guid_defined only
+#include <Serialization/static_warning.hpp>
+#include <Serialization/assume_abstract.hpp>
+#include <Serialization/force_include.hpp>
+#include <Serialization/singleton.hpp>
+
+#include <Serialization/archive/detail/register_archive.hpp>
+
+#include <iostream>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+class basic_pointer_iserializer;
+class basic_pointer_oserializer;
+
+template<class Archive, class T>
+class pointer_iserializer;
+template<class Archive, class T>
+class pointer_oserializer;
+
+template <class Archive, class Serializable>
+struct export_impl
+{
+    static const basic_pointer_iserializer &
+    enable_load(mpl::true_){
+        return boost::serialization::singleton<
+            pointer_iserializer<Archive, Serializable> 
+        >::get_const_instance();
+    }
+
+    static const basic_pointer_oserializer &
+    enable_save(mpl::true_){
+        return boost::serialization::singleton<
+            pointer_oserializer<Archive, Serializable> 
+        >::get_const_instance();
+    }
+    inline static void enable_load(mpl::false_) {}
+    inline static void enable_save(mpl::false_) {}
+};
+
+// On many platforms, naming a specialization of this template is
+// enough to cause its argument to be instantiated.
+template <void(*)()>
+struct instantiate_function {};
+
+template <class Archive, class Serializable>
+struct ptr_serialization_support
+{
+# if defined(BOOST_MSVC) || defined(__SUNPRO_CC)
+    virtual BOOST_DLLEXPORT void instantiate() BOOST_USED;
+# elif defined(__BORLANDC__)   
+    static BOOST_DLLEXPORT void instantiate() BOOST_USED;
+    enum { x = sizeof(instantiate(),3) };
+# else
+    static BOOST_DLLEXPORT void instantiate() BOOST_USED;
+    typedef instantiate_function<
+        &ptr_serialization_support::instantiate
+    > x;
+# endif
+};
+
+template <class Archive, class Serializable>
+BOOST_DLLEXPORT void 
+ptr_serialization_support<Archive,Serializable>::instantiate()
+{
+    export_impl<Archive,Serializable>::enable_save(
+        #if ! defined(__BORLANDC__)
+        BOOST_DEDUCED_TYPENAME 
+        #endif
+        Archive::is_saving()
+    );
+
+    export_impl<Archive,Serializable>::enable_load(
+        #if ! defined(__BORLANDC__)
+        BOOST_DEDUCED_TYPENAME 
+        #endif
+        Archive::is_loading()
+    );
+}
+
+// Note INTENTIONAL usage of anonymous namespace in header.
+// This was made this way so that export.hpp could be included
+// in other headers.  This is still under study.
+
+namespace extra_detail {
+
+template<class T>
+struct guid_initializer
+{  
+    void export_guid(mpl::false_) const {
+        // generates the statically-initialized objects whose constructors
+        // register the information allowing serialization of T objects
+        // through pointers to their base classes.
+        instantiate_ptr_serialization((T*)0, 0, adl_tag());
+    }
+    void export_guid(mpl::true_) const {
+    }
+    guid_initializer const & export_guid() const {
+        BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value);
+        // note: exporting an abstract base class will have no effect
+        // and cannot be used to instantitiate serialization code
+        // (one might be using this in a DLL to instantiate code)
+        //BOOST_STATIC_WARNING(! boost::serialization::is_abstract< T >::value);
+        export_guid(boost::serialization::is_abstract< T >());
+        return *this;
+    }
+};
+
+template<typename T>
+struct init_guid;
+
+} // anonymous
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#define BOOST_CLASS_EXPORT_IMPLEMENT(T)                      \
+    namespace boost {                                        \
+    namespace archive {                                      \
+    namespace detail {                                       \
+    namespace extra_detail {                                 \
+    template<>                                               \
+    struct init_guid< T > {                                  \
+        static guid_initializer< T > const & g;              \
+    };                                                       \
+    guid_initializer< T > const & init_guid< T >::g =        \
+        ::boost::serialization::singleton<                   \
+            guid_initializer< T >                            \
+        >::get_mutable_instance().export_guid();             \
+    }}}}                                                     \
+/**/
+
+#define BOOST_CLASS_EXPORT_KEY2(T, K)          \
+namespace boost {                              \
+namespace serialization {                      \
+template<>                                     \
+struct guid_defined< T > : boost::mpl::true_ {}; \
+template<>                                     \
+inline const char * guid< T >(){                 \
+    return K;                                  \
+}                                              \
+} /* serialization */                          \
+} /* boost */                                  \
+/**/
+
+#define BOOST_CLASS_EXPORT_KEY(T)                                      \
+    BOOST_CLASS_EXPORT_KEY2(T, BOOST_PP_STRINGIZE(T))                                                                  \
+/**/
+
+#define BOOST_CLASS_EXPORT_GUID(T, K)                                  \
+BOOST_CLASS_EXPORT_KEY2(T, K)                                          \
+BOOST_CLASS_EXPORT_IMPLEMENT(T)                                        \
+/**/
+
+#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3205))
+
+// CodeWarrior fails to construct static members of class templates
+// when they are instantiated from within templates, so on that
+// compiler we ask users to specifically register base/derived class
+// relationships for exported classes.  On all other compilers, use of
+// this macro is entirely optional.
+# define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived)             \
+namespace {                                                                    \
+  static int BOOST_PP_CAT(boost_serialization_mwerks_init_, __LINE__) =        \
+  (::boost::archive::detail::instantiate_ptr_serialization((Derived*)0,0), 3); \
+  static int BOOST_PP_CAT(boost_serialization_mwerks_init2_, __LINE__) = (     \
+      ::boost::serialization::void_cast_register((Derived*)0,(Base*)0)         \
+    , 3);                                                                      \
+}
+
+#else
+
+# define BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(Base,Derived)
+
+#endif 
+
+// check for unnecessary export.  T isn't polymorphic so there is no
+// need to export it.
+#define BOOST_CLASS_EXPORT_CHECK(T)                              \
+    BOOST_STATIC_WARNING(                                        \
+        boost::is_polymorphic<U>::value                          \
+    );                                                           \
+    /**/
+
+// the default exportable class identifier is the class name
+// the default list of archives types for which code id generated
+// are the originally included with this serialization system
+#define BOOST_CLASS_EXPORT(T)                   \
+    BOOST_CLASS_EXPORT_GUID(                    \
+        T,                                      \
+        BOOST_PP_STRINGIZE(T)                   \
+    )                                           \
+    /**/
+
+#endif // BOOST_SERIALIZATION_EXPORT_HPP
+
diff --git a/SRC/Serialization/extended_type_info.hpp b/SRC/Serialization/extended_type_info.hpp
new file mode 100755
index 0000000..e4004dd
--- /dev/null
+++ b/SRC/Serialization/extended_type_info.hpp
@@ -0,0 +1,108 @@
+#ifndef BOOST_SERIALIZATION_EXTENDED_TYPE_INFO_HPP
+#define BOOST_SERIALIZATION_EXTENDED_TYPE_INFO_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// extended_type_info.hpp: interface for portable version of type_info
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// for now, extended type info is part of the serialization libraries
+// this could change in the future.
+#include <cstdarg>
+#include <boost/assert.hpp>
+#include <cstddef> // NULL
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/mpl/bool.hpp>
+
+#include <Serialization/config.hpp>
+#include <boost/config/abi_prefix.hpp> // must be the last header
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4251 4231 4660 4275)
+#endif
+
+#define BOOST_SERIALIZATION_MAX_KEY_SIZE 128
+
+namespace boost { 
+namespace serialization {
+
+namespace void_cast_detail{
+    class void_caster;
+}
+
+class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info :
+    private boost::noncopyable
+{
+private:
+    friend class boost::serialization::void_cast_detail::void_caster;
+
+    // used to uniquely identify the type of class derived from this one
+    // so that different derivations of this class can be simultaneously
+    // included in implementation of sets and maps.
+    const unsigned int m_type_info_key;
+    virtual bool is_less_than(const extended_type_info & /*rhs*/) const = 0;
+    virtual bool is_equal(const extended_type_info & /*rhs*/) const = 0;
+    const char * m_key;
+
+protected:
+    void key_unregister() const;
+    void key_register() const;
+    // this class can't be used as is. It's just the 
+    // common functionality for all type_info replacement
+    // systems.  Hence, make these protected
+    extended_type_info(
+        const unsigned int type_info_key,
+        const char * key
+    );
+    // account for bogus gcc warning
+    #if defined(__GNUC__)
+    virtual
+    #endif
+    ~extended_type_info();
+public:
+    const char * get_key() const {
+        return m_key;
+    }
+    virtual const char * get_debug_info() const = 0;
+    bool operator<(const extended_type_info &rhs) const;
+    bool operator==(const extended_type_info &rhs) const;
+    bool operator!=(const extended_type_info &rhs) const {
+        return !(operator==(rhs));
+    }
+    // note explicit "export" of static function to work around
+    // gcc 4.5 mingw error
+    static const extended_type_info *
+    find(const char *key);
+    // for plugins
+    virtual void * construct(unsigned int /*count*/ = 0, ...) const = 0;
+    virtual void destroy(void const * const /*p*/) const = 0;
+};
+
+template<class T>
+struct guid_defined : boost::mpl::false_ {};
+template<class T>
+inline const char * guid(){
+    return NULL;
+}
+
+} // namespace serialization 
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_SERIALIZATION_EXTENDED_TYPE_INFO_HPP
diff --git a/SRC/Serialization/extended_type_info_no_rtti.hpp b/SRC/Serialization/extended_type_info_no_rtti.hpp
new file mode 100755
index 0000000..828170b
--- /dev/null
+++ b/SRC/Serialization/extended_type_info_no_rtti.hpp
@@ -0,0 +1,182 @@
+#ifndef BOOST_EXTENDED_TYPE_INFO_NO_RTTI_HPP
+#define BOOST_EXTENDED_TYPE_INFO_NO_RTTI_HPP
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// extended_type_info_no_rtti.hpp: implementation for version that depends
+// on runtime typing (rtti - typeid) but uses a user specified string
+// as the portable class identifier.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <Serialization/static_warning.hpp>
+#include <Serialization/singleton.hpp>
+#include <Serialization/extended_type_info.hpp>
+#include <Serialization/factory.hpp>
+#include <Serialization/throw_exception.hpp>
+
+#include <Serialization/config.hpp>
+// hijack serialization access
+#include <Serialization/access.hpp>
+
+#include <boost/config/abi_prefix.hpp> // must be the last header
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4251 4231 4660 4275 4511 4512)
+#endif
+
+namespace boost {
+namespace serialization {
+///////////////////////////////////////////////////////////////////////
+// define a special type_info that doesn't depend on rtti which is not
+// available in all situations.
+
+namespace no_rtti_system {
+
+// common base class to share type_info_key.  This is used to 
+// identify the method used to keep track of the extended type
+class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info_no_rtti_0 : 
+    public extended_type_info
+{
+protected:
+    extended_type_info_no_rtti_0(const char * key);
+    ~extended_type_info_no_rtti_0();
+public:
+    virtual bool
+    is_less_than(const boost::serialization::extended_type_info &rhs) const ;
+    virtual bool
+    is_equal(const boost::serialization::extended_type_info &rhs) const ;
+};
+
+} // no_rtti_system
+
+template<class T>
+class extended_type_info_no_rtti : 
+    public no_rtti_system::extended_type_info_no_rtti_0,
+    public singleton<extended_type_info_no_rtti< T > >
+{
+    template<bool tf>
+    struct action {
+        struct defined {
+            static const char * invoke(){
+                return guid< T >();
+            }
+        };
+        struct undefined {
+            // if your program traps here - you failed to 
+            // export a guid for this type.  the no_rtti
+            // system requires export for types serialized
+            // as pointers.
+            BOOST_STATIC_ASSERT(0 == sizeof(T));
+            static const char * invoke();
+        };
+        static const char * invoke(){
+            typedef 
+                BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
+                    tf,
+                    defined,
+                    undefined
+                >::type type;
+            return type::invoke();
+        }
+    };
+public:
+    extended_type_info_no_rtti() :
+        no_rtti_system::extended_type_info_no_rtti_0(get_key())
+    {
+        key_register();
+    }
+    ~extended_type_info_no_rtti(){
+        key_unregister();
+    }
+    const extended_type_info *
+    get_derived_extended_type_info(const T & t) const {
+        // find the type that corresponds to the most derived type.
+        // this implementation doesn't depend on typeid() but assumes
+        // that the specified type has a function of the following signature.
+        // A common implemention of such a function is to define as a virtual
+        // function. So if the is not a polymporphic type it's likely an error
+        BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value);
+        const char * derived_key = t.get_key();
+        BOOST_ASSERT(NULL != derived_key);
+        return boost::serialization::extended_type_info::find(derived_key);
+    }
+    const char * get_key() const{
+        return action<guid_defined< T >::value >::invoke();
+    }
+    virtual const char * get_debug_info() const{
+        return action<guid_defined< T >::value >::invoke();
+    }
+    virtual void * construct(unsigned int count, ...) const{
+        // count up the arguments
+        std::va_list ap;
+        va_start(ap, count);
+        switch(count){
+        case 0:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 0>(ap);
+        case 1:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 1>(ap);
+        case 2:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 2>(ap);
+        case 3:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 3>(ap);
+        case 4:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 4>(ap);
+        default:
+            BOOST_ASSERT(false); // too many arguments
+            // throw exception here?
+            return NULL;
+        }
+    }
+    virtual void destroy(void const * const p) const{
+        boost::serialization::access::destroy(
+            static_cast<T const * const>(p)
+        );
+        //delete static_cast<T const * const>(p) ;
+    }
+};
+
+} // namespace serialization
+} // namespace boost
+
+///////////////////////////////////////////////////////////////////////////////
+// If no other implementation has been designated as default, 
+// use this one.  To use this implementation as the default, specify it
+// before any of the other headers.
+
+#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
+    #define BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
+    namespace boost {
+    namespace serialization {
+    template<class T>
+    struct extended_type_info_impl {
+        typedef BOOST_DEDUCED_TYPENAME 
+            boost::serialization::extended_type_info_no_rtti< T > type;
+    };
+    } // namespace serialization
+    } // namespace boost
+#endif
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+#include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_EXTENDED_TYPE_INFO_NO_RTTI_HPP
diff --git a/SRC/Serialization/extended_type_info_typeid.hpp b/SRC/Serialization/extended_type_info_typeid.hpp
new file mode 100755
index 0000000..7199008
--- /dev/null
+++ b/SRC/Serialization/extended_type_info_typeid.hpp
@@ -0,0 +1,165 @@
+#ifndef BOOST_SERIALIZATION_EXTENDED_TYPE_INFO_TYPEID_HPP
+#define BOOST_SERIALIZATION_EXTENDED_TYPE_INFO_TYPEID_HPP
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// extended_type_info_typeid.hpp: implementation for version that depends
+// on runtime typing (rtti - typeid) but uses a user specified string
+// as the portable class identifier.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <typeinfo>
+#include <cstdarg>
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+
+#include <boost/static_assert.hpp>
+#include <Serialization/static_warning.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/type_traits/remove_const.hpp>
+
+#include <Serialization/config.hpp>
+#include <Serialization/singleton.hpp>
+#include <Serialization/extended_type_info.hpp>
+#include <Serialization/factory.hpp>
+
+// hijack serialization access
+#include <Serialization/access.hpp>
+
+#include <boost/mpl/if.hpp>
+
+#include <boost/config/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4251 4231 4660 4275 4511 4512)
+#endif
+
+namespace boost {
+namespace serialization {
+namespace typeid_system {
+
+class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) extended_type_info_typeid_0 : 
+    public extended_type_info
+{
+    virtual const char * get_debug_info() const {
+        if(static_cast<const std::type_info *>(0) == m_ti)
+            return static_cast<const char *>(0);
+        return m_ti->name();
+    }
+protected:
+    const std::type_info * m_ti;
+    extended_type_info_typeid_0(const char * key);
+    ~extended_type_info_typeid_0();
+    void type_register(const std::type_info & ti);
+    void type_unregister();
+    const extended_type_info *
+    get_extended_type_info(const std::type_info & ti) const;
+public:
+    virtual bool
+    is_less_than(const extended_type_info &rhs) const;
+    virtual bool
+    is_equal(const extended_type_info &rhs) const;
+    const std::type_info & get_typeid() const {
+        return *m_ti;
+    }
+};
+
+} // typeid_system
+
+template<class T>
+class extended_type_info_typeid : 
+    public typeid_system::extended_type_info_typeid_0,
+    public singleton<extended_type_info_typeid< T > >
+{
+public:
+    extended_type_info_typeid() :
+        typeid_system::extended_type_info_typeid_0(get_key())
+    {
+        type_register(typeid(T));
+        key_register();
+    }
+    ~extended_type_info_typeid(){
+        key_unregister();
+        type_unregister();
+    }
+    // get the eti record for the true type of this record
+    // relying upon standard type info implemenation (rtti)
+    const extended_type_info *
+    get_derived_extended_type_info(const T & t) const {
+        // note: this implementation - based on usage of typeid (rtti)
+        // only does something if the class has at least one virtual function.
+        BOOST_STATIC_WARNING(boost::is_polymorphic< T >::value);
+        return 
+            typeid_system::extended_type_info_typeid_0::get_extended_type_info(
+                typeid(t)
+            );
+    }
+    const char * get_key() const {
+        return boost::serialization::guid< T >();
+    }
+    virtual void * construct(unsigned int count, ...) const{
+        // count up the arguments
+        std::va_list ap;
+        va_start(ap, count);
+        switch(count){
+        case 0:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 0>(ap);
+        case 1:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 1>(ap);
+        case 2:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 2>(ap);
+        case 3:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 3>(ap);
+        case 4:
+            return factory<BOOST_DEDUCED_TYPENAME boost::remove_const< T >::type, 4>(ap);
+        default:
+            BOOST_ASSERT(false); // too many arguments
+            // throw exception here?
+            return NULL;
+        }
+    }
+    virtual void destroy(void const * const p) const {
+        boost::serialization::access::destroy(
+            static_cast<T const * const>(p)
+        );
+        //delete static_cast<T const * const>(p);
+    }
+};
+
+} // namespace serialization
+} // namespace boost
+
+///////////////////////////////////////////////////////////////////////////////
+// If no other implementation has been designated as default, 
+// use this one.  To use this implementation as the default, specify it
+// before any of the other headers.
+#ifndef BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
+    #define BOOST_SERIALIZATION_DEFAULT_TYPE_INFO
+    namespace boost {
+    namespace serialization {
+    template<class T>
+    struct extended_type_info_impl {
+        typedef BOOST_DEDUCED_TYPENAME 
+            boost::serialization::extended_type_info_typeid< T > type;
+    };
+    } // namespace serialization
+    } // namespace boost
+#endif
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+#include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_SERIALIZATION_EXTENDED_TYPE_INFO_TYPEID_HPP
diff --git a/SRC/Serialization/factory.hpp b/SRC/Serialization/factory.hpp
new file mode 100755
index 0000000..1a5885d
--- /dev/null
+++ b/SRC/Serialization/factory.hpp
@@ -0,0 +1,101 @@
+#ifndef BOOST_SERIALIZATION_FACTORY_HPP
+#define BOOST_SERIALIZATION_FACTORY_HPP
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// factory.hpp: create an instance from an extended_type_info instance.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstdarg> // valist
+#include <cstddef> // NULL
+
+#include <boost/preprocessor/control/if.hpp> 
+#include <boost/preprocessor/comparison/greater.hpp>
+#include <boost/preprocessor/facilities/empty.hpp>
+
+namespace std{
+    #if defined(__LIBCOMO__) || defined(__QNXNTO__) 
+        using ::va_list;
+    #endif
+} // namespace std
+
+namespace boost {
+namespace serialization {
+
+// default implementation does nothing.
+template<class T, int N>
+T * factory(std::va_list){
+    BOOST_ASSERT(false);
+    // throw exception here?
+    return NULL;
+}
+
+} // namespace serialization
+} // namespace boost
+
+#define BOOST_SERIALIZATION_FACTORY(N, T, A0, A1, A2, A3) \
+namespace boost {                                         \
+namespace serialization {                                 \
+    template<>                                            \
+    T * factory<T, N>(std::va_list ap){                   \
+        BOOST_PP_IF(BOOST_PP_GREATER(N,0)                 \
+            ,A0 a0 = va_arg(ap, A0);                      \
+        ,BOOST_PP_IF(BOOST_PP_GREATER(N,1)                \
+            ,A1 a1 = va_arg(ap, A1);                      \
+        ,BOOST_PP_IF(BOOST_PP_GREATER(N,2)                \
+            ,A2 a2 = va_arg(ap, A2);                      \
+        ,BOOST_PP_IF(BOOST_PP_GREATER(N,3)                \
+            ,A3 a3 = va_arg(ap, A3);                      \
+            ,BOOST_PP_EMPTY()                             \
+        ))))                                              \
+        return new T(                                     \
+            BOOST_PP_IF(BOOST_PP_GREATER(N,0)             \
+                ,a0                                       \
+            ,BOOST_PP_IF(BOOST_PP_GREATER(N,1)            \
+                ,a1                                       \
+            ,BOOST_PP_IF(BOOST_PP_GREATER(N,2)            \
+                ,a2                                       \
+            ,BOOST_PP_IF(BOOST_PP_GREATER(N,3)            \
+                ,a3                                       \
+                ,BOOST_PP_EMPTY()                         \
+            ))))                                          \
+        );                                                \
+    }                                                     \
+}                                                         \
+}                                                         \
+/**/
+
+#define BOOST_SERIALIZATION_FACTORY_4(T, A0, A1, A2, A3) \
+    BOOST_SERIALIZATION_FACTORY(4, T, A0, A1, A2, A3)
+
+#define BOOST_SERIALIZATION_FACTORY_3(T, A0, A1, A2)     \
+    BOOST_SERIALIZATION_FACTORY(3, T, A0, A1, A2, 0)
+
+#define BOOST_SERIALIZATION_FACTORY_2(T, A0, A1)         \
+    BOOST_SERIALIZATION_FACTORY(2, T, A0, A1, 0, 0)
+
+#define BOOST_SERIALIZATION_FACTORY_1(T, A0)             \
+    BOOST_SERIALIZATION_FACTORY(1, T, A0, 0, 0, 0)
+
+#define BOOST_SERIALIZATION_FACTORY_0(T)                 \
+namespace boost {                                        \
+namespace serialization {                                \
+    template<>                                           \
+    T * factory<T, 0>(std::va_list){                     \
+        return new T();                                  \
+    }                                                    \
+}                                                        \
+}                                                        \
+/**/
+
+#endif // BOOST_SERIALIZATION_FACTORY_HPP
diff --git a/SRC/Serialization/force_include.hpp b/SRC/Serialization/force_include.hpp
new file mode 100755
index 0000000..8fa3c1e
--- /dev/null
+++ b/SRC/Serialization/force_include.hpp
@@ -0,0 +1,59 @@
+#ifndef BOOST_SERIALIZATION_FORCE_INCLUDE_HPP
+#define BOOST_SERIALIZATION_FORCE_INCLUDE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// force_include.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+// the following help macro is to guarentee that certain coded
+// is not removed by over-eager linker optimiser.  In certain cases
+// we create static objects must be created but are actually never
+// referenced - creation has a side-effect such as global registration
+// which is important to us. We make an effort to refer these objects
+// so that a smart linker won't remove them as being unreferenced.
+// In microsoft compilers, inlining the code that does the referring
+// means the code gets lost and the static object is not included
+// in the library and hence never registered.  This manifests itself
+// in an ungraceful crash at runtime when (and only when) built in
+// release mode.
+
+#if defined(BOOST_HAS_DECLSPEC) && !defined(__COMO__)
+#   if defined(__BORLANDC__)
+#       define BOOST_DLLEXPORT __export
+#   else
+#       define BOOST_DLLEXPORT __declspec(dllexport)
+#   endif
+#elif ! defined(_WIN32) && ! defined(_WIN64)
+#   if defined(__MWERKS__)
+#       define BOOST_DLLEXPORT __declspec(dllexport)
+#   elif defined(__GNUC__) && (__GNUC__ >= 3)
+#       define BOOST_USED __attribute__ ((used))
+#   elif defined(__IBMCPP__) && (__IBMCPP__ >= 1110)
+#       define BOOST_USED __attribute__ ((used))
+#   elif defined(__INTEL_COMPILER) && (BOOST_INTEL_CXX_VERSION >= 800)
+#       define BOOST_USED __attribute__ ((used))
+#   endif
+#endif
+
+#ifndef BOOST_USED
+#    define BOOST_USED
+#endif
+
+#ifndef BOOST_DLLEXPORT
+#    define BOOST_DLLEXPORT
+#endif
+
+#endif // BOOST_SERIALIZATION_FORCE_INCLUDE_HPP
diff --git a/SRC/Serialization/hash_collections_load_imp.hpp b/SRC/Serialization/hash_collections_load_imp.hpp
new file mode 100755
index 0000000..fddc578
--- /dev/null
+++ b/SRC/Serialization/hash_collections_load_imp.hpp
@@ -0,0 +1,77 @@
+#ifndef BOOST_SERIALIZATION_HASH_COLLECTIONS_LOAD_IMP_HPP
+#define BOOST_SERIALIZATION_HASH_COLLECTIONS_LOAD_IMP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+# pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// hash_collections_load_imp.hpp: serialization for loading stl collections
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// helper function templates for serialization of hashed collections
+#include <boost/config.hpp>
+#include <Serialization/archive/detail/basic_iarchive.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/item_version_type.hpp>
+
+namespace boost{
+namespace serialization {
+namespace stl {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of serialization for STL containers
+//
+template<class Archive, class Container, class InputFunction>
+inline void load_hash_collection(Archive & ar, Container &s)
+{
+    s.clear();
+    collection_size_type count;
+    collection_size_type bucket_count;
+    boost::serialization::item_version_type item_version(0);
+    boost::archive::library_version_type library_version(
+        ar.get_library_version()
+    );
+    // retrieve number of elements
+    if(boost::archive::library_version_type(6) != library_version){
+        ar >> BOOST_SERIALIZATION_NVP(count);
+        ar >> BOOST_SERIALIZATION_NVP(bucket_count);
+    }
+    else{
+        // note: fixup for error in version 6.  collection size was
+        // changed to size_t BUT for hashed collections it was implemented
+        // as an unsigned int.  This should be a problem only on win64 machines
+        // but I'll leave it for everyone just in case.
+        unsigned int c;
+        unsigned int bc;
+        ar >> BOOST_SERIALIZATION_NVP(c);
+        count = c;
+        ar >> BOOST_SERIALIZATION_NVP(bc);
+        bucket_count = bc;
+    }
+    if(boost::archive::library_version_type(3) < library_version){
+        ar >> BOOST_SERIALIZATION_NVP(item_version);
+    }
+    #if ! defined(__MWERKS__)
+    s.resize(bucket_count);
+    #endif
+    InputFunction ifunc;
+    while(count-- > 0){
+        ifunc(ar, s, item_version);
+    }
+}
+
+} // namespace stl 
+} // namespace serialization
+} // namespace boost
+
+#endif //BOOST_SERIALIZATION_HASH_COLLECTIONS_LOAD_IMP_HPP
diff --git a/SRC/Serialization/hash_collections_save_imp.hpp b/SRC/Serialization/hash_collections_save_imp.hpp
new file mode 100755
index 0000000..1557d3e
--- /dev/null
+++ b/SRC/Serialization/hash_collections_save_imp.hpp
@@ -0,0 +1,97 @@
+#ifndef BOOST_SERIALIZATION_HASH_COLLECTIONS_SAVE_IMP_HPP
+#define BOOST_SERIALIZATION_HASH_COLLECTIONS_SAVE_IMP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// hash_collections_save_imp.hpp: serialization for stl collections
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// helper function templates for serialization of collections
+
+#include <boost/config.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/serialization.hpp>
+#include <Serialization/version.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/item_version_type.hpp>
+
+namespace boost{
+namespace serialization {
+namespace stl {
+
+//////////////////////////////////////////////////////////////////////
+// implementation of serialization for STL containers
+//
+
+template<class Archive, class Container>
+inline void save_hash_collection(Archive & ar, const Container &s)
+{
+    collection_size_type count(s.size());
+    const collection_size_type bucket_count(s.bucket_count());
+    const item_version_type item_version(
+        version<BOOST_DEDUCED_TYPENAME Container::value_type>::value
+    );
+
+    #if 0
+    /* should only be necessary to create archives of previous versions
+     * which is not currently supported.  So for now comment this out
+     */
+    boost::archive::library_version_type library_version(
+        ar.get_library_version()
+    );
+    // retrieve number of elements
+    if(boost::archive::library_version_type(6) != library_version){
+        ar << BOOST_SERIALIZATION_NVP(count);
+        ar << BOOST_SERIALIZATION_NVP(bucket_count);
+    }
+    else{
+        // note: fixup for error in version 6.  collection size was
+        // changed to size_t BUT for hashed collections it was implemented
+        // as an unsigned int.  This should be a problem only on win64 machines
+        // but I'll leave it for everyone just in case.
+        const unsigned int c = count;
+        const unsigned int bc = bucket_count;
+        ar << BOOST_SERIALIZATION_NVP(c);
+        ar << BOOST_SERIALIZATION_NVP(bc);
+    }
+    if(boost::archive::library_version_type(3) < library_version){
+        // record number of elements
+        // make sure the target type is registered so we can retrieve
+        // the version when we load
+        ar << BOOST_SERIALIZATION_NVP(item_version);
+    }
+    #else
+        ar << BOOST_SERIALIZATION_NVP(count);
+        ar << BOOST_SERIALIZATION_NVP(bucket_count);
+        ar << BOOST_SERIALIZATION_NVP(item_version);
+    #endif
+
+    BOOST_DEDUCED_TYPENAME Container::const_iterator it = s.begin();
+    while(count-- > 0){
+        // note borland emits a no-op without the explicit namespace
+        boost::serialization::save_construct_data_adl(
+            ar, 
+            &(*it), 
+            boost::serialization::version<
+                BOOST_DEDUCED_TYPENAME Container::value_type
+            >::value
+        );
+        ar << boost::serialization::make_nvp("item", *it++);
+    }
+}
+
+} // namespace stl 
+} // namespace serialization
+} // namespace boost
+
+#endif //BOOST_SERIALIZATION_HASH_COLLECTIONS_SAVE_IMP_HPP
diff --git a/SRC/Serialization/hash_map.hpp b/SRC/Serialization/hash_map.hpp
new file mode 100755
index 0000000..8fefb2c
--- /dev/null
+++ b/SRC/Serialization/hash_map.hpp
@@ -0,0 +1,231 @@
+#ifndef  BOOST_SERIALIZATION_HASH_MAP_HPP
+#define BOOST_SERIALIZATION_HASH_MAP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization/hash_map.hpp:
+// serialization for stl hash_map templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_HASH
+#include BOOST_HASH_MAP_HEADER
+
+#include <Serialization/utility.hpp>
+#include <Serialization/hash_collections_save_imp.hpp>
+#include <Serialization/hash_collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+namespace stl {
+
+// map input
+template<class Archive, class Container>
+struct archive_input_hash_map
+{
+    inline void operator()(
+        Archive &ar, 
+        Container &s, 
+        const unsigned int v
+    ){
+        typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
+        detail::stack_construct<Archive, type> t(ar, v);
+        // borland fails silently w/o full namespace
+        ar >> boost::serialization::make_nvp("item", t.reference());
+        std::pair<BOOST_DEDUCED_TYPENAME Container::const_iterator, bool> result = 
+            s.insert(t.reference());
+        // note: the following presumes that the map::value_type was NOT tracked
+        // in the archive.  This is the usual case, but here there is no way
+        // to determine that.  
+        if(result.second){
+            ar.reset_object_address(
+                & (result.first->second),
+                & t.reference().second
+            );
+        }
+    }
+};
+
+// multimap input
+template<class Archive, class Container>
+struct archive_input_hash_multimap
+{
+    inline void operator()(
+        Archive &ar, 
+        Container &s, 
+        const unsigned int v
+    ){
+        typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
+        detail::stack_construct<Archive, type> t(ar, v);
+        // borland fails silently w/o full namespace
+        ar >> boost::serialization::make_nvp("item", t.reference());
+        BOOST_DEDUCED_TYPENAME Container::const_iterator result 
+            = s.insert(t.reference());
+        // note: the following presumes that the map::value_type was NOT tracked
+        // in the archive.  This is the usual case, but here there is no way
+        // to determine that.  
+        ar.reset_object_address(
+            & result->second,
+            & t.reference()
+        );
+    }
+};
+
+} // stl
+
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void save(
+    Archive & ar,
+    const BOOST_STD_EXTENSION_NAMESPACE::hash_map<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::save_hash_collection<
+        Archive, 
+        BOOST_STD_EXTENSION_NAMESPACE::hash_map<
+            Key, HashFcn, EqualKey, Allocator
+        >
+    >(ar, t);
+}
+
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void load(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_map<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::load_hash_collection<
+        Archive,
+        BOOST_STD_EXTENSION_NAMESPACE::hash_map<
+            Key, HashFcn, EqualKey, Allocator
+        >,
+        boost::serialization::stl::archive_input_hash_map<
+            Archive, 
+            BOOST_STD_EXTENSION_NAMESPACE::hash_map<
+                Key, HashFcn, EqualKey, Allocator
+            >
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void serialize(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_map<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+// hash_multimap
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void save(
+    Archive & ar,
+    const BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::save_hash_collection<
+        Archive, 
+        BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<
+            Key, HashFcn, EqualKey, Allocator
+        >
+    >(ar, t);
+}
+
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void load(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::load_hash_collection<
+        Archive,
+        BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<
+            Key, HashFcn, EqualKey, Allocator
+        >,
+        boost::serialization::stl::archive_input_hash_multimap<
+            Archive, 
+            BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<
+                Key, HashFcn, EqualKey, Allocator
+            >
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void serialize(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_multimap<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_HAS_HASH
+#endif // BOOST_SERIALIZATION_HASH_MAP_HPP
diff --git a/SRC/Serialization/hash_set.hpp b/SRC/Serialization/hash_set.hpp
new file mode 100755
index 0000000..7ec50b9
--- /dev/null
+++ b/SRC/Serialization/hash_set.hpp
@@ -0,0 +1,221 @@
+#ifndef  BOOST_SERIALIZATION_HASH_SET_HPP
+#define BOOST_SERIALIZATION_HASH_SET_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// hash_set.hpp: serialization for stl hash_set templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_HAS_HASH
+#include BOOST_HASH_SET_HEADER
+
+#include <Serialization/hash_collections_save_imp.hpp>
+#include <Serialization/hash_collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+namespace stl {
+
+// hash_set input
+template<class Archive, class Container>
+struct archive_input_hash_set
+{
+    inline void operator()(
+        Archive &ar, 
+        Container &s, 
+        const unsigned int v
+    ){
+        typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
+        detail::stack_construct<Archive, type> t(ar, v);
+        // borland fails silently w/o full namespace
+        ar >> boost::serialization::make_nvp("item", t.reference());
+        std::pair<BOOST_DEDUCED_TYPENAME Container::const_iterator, bool> result = 
+            s.insert(t.reference());
+        if(result.second)
+            ar.reset_object_address(& (* result.first), & t.reference());
+    }
+};
+
+// hash_multiset input
+template<class Archive, class Container>
+struct archive_input_hash_multiset
+{
+    inline void operator()(
+        Archive &ar, 
+        Container &s, 
+        const unsigned int v
+    ){
+        typedef BOOST_DEDUCED_TYPENAME Container::value_type type;
+        detail::stack_construct<Archive, type> t(ar, v);
+        // borland fails silently w/o full namespace
+        ar >> boost::serialization::make_nvp("item", t.reference());
+        BOOST_DEDUCED_TYPENAME Container::const_iterator result 
+            = s.insert(t.reference());
+        ar.reset_object_address(& (* result), & t.reference());
+    }
+};
+
+} // stl
+
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void save(
+    Archive & ar,
+    const BOOST_STD_EXTENSION_NAMESPACE::hash_set<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::save_hash_collection<
+        Archive, 
+        BOOST_STD_EXTENSION_NAMESPACE::hash_set<
+            Key, HashFcn, EqualKey, Allocator
+        > 
+    >(ar, t);
+}
+
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void load(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_set<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::load_hash_collection<
+        Archive,
+        BOOST_STD_EXTENSION_NAMESPACE::hash_set<
+            Key, HashFcn, EqualKey, Allocator
+        >,
+        boost::serialization::stl::archive_input_hash_set<
+            Archive, 
+            BOOST_STD_EXTENSION_NAMESPACE::hash_set<
+                Key, HashFcn, EqualKey, Allocator
+            >
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void serialize(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_set<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+// hash_multiset
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void save(
+    Archive & ar,
+    const BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::save_hash_collection<
+        Archive, 
+        BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<
+            Key, HashFcn, EqualKey, Allocator
+        > 
+    >(ar, t);
+}
+
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void load(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<
+        Key, HashFcn, EqualKey, Allocator
+    > &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::load_hash_collection<
+        Archive,
+        BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<
+            Key, HashFcn, EqualKey, Allocator
+        >,
+        boost::serialization::stl::archive_input_hash_multiset<
+            Archive,
+            BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<
+                Key, HashFcn, EqualKey, Allocator
+            > 
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<
+    class Archive, 
+    class Key, 
+    class HashFcn, 
+    class EqualKey,
+    class Allocator
+>
+inline void serialize(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::hash_multiset<
+        Key, HashFcn, EqualKey, Allocator
+    > & t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(BOOST_STD_EXTENSION_NAMESPACE::hash_set)
+BOOST_SERIALIZATION_COLLECTION_TRAITS(BOOST_STD_EXTENSION_NAMESPACE::hash_multiset)
+
+#endif // BOOST_HAS_HASH
+#endif // BOOST_SERIALIZATION_HASH_SET_HPP
diff --git a/SRC/Serialization/is_bitwise_serializable.hpp b/SRC/Serialization/is_bitwise_serializable.hpp
new file mode 100755
index 0000000..4ed10fd
--- /dev/null
+++ b/SRC/Serialization/is_bitwise_serializable.hpp
@@ -0,0 +1,46 @@
+// (C) Copyright 2007 Matthias Troyer
+
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  Authors: Matthias Troyer
+
+/** @file is_bitwise_serializable.hpp
+ *
+ *  This header provides a traits class for determining whether a class
+ * can be serialized (in a non-portable way) just by copying the bits.
+ */
+
+
+#ifndef BOOST_SERIALIZATION_IS_BITWISE_SERIALIZABLE_HPP
+#define BOOST_SERIALIZATION_IS_BITWISE_SERIALIZABLE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/mpl/bool.hpp>
+#include <boost/type_traits/is_arithmetic.hpp>
+
+namespace boost {
+namespace serialization {
+    template<class T>
+    struct is_bitwise_serializable
+     : public is_arithmetic< T >
+    {};
+} // namespace serialization
+} // namespace boost
+
+
+// define a macro to make explicit designation of this more transparent
+#define BOOST_IS_BITWISE_SERIALIZABLE(T)              \
+namespace boost {                                     \
+namespace serialization {                             \
+template<>                                            \
+struct is_bitwise_serializable< T > : mpl::true_ {};  \
+}}                                                    \
+/**/
+
+#endif //BOOST_SERIALIZATION_IS_BITWISE_SERIALIZABLE_HPP
diff --git a/SRC/Serialization/item_version_type.hpp b/SRC/Serialization/item_version_type.hpp
new file mode 100755
index 0000000..4d6ef1b
--- /dev/null
+++ b/SRC/Serialization/item_version_type.hpp
@@ -0,0 +1,68 @@
+#ifndef BOOST_SERIALIZATION_ITEM_VERSION_TYPE_HPP
+#define BOOST_SERIALIZATION_ITEM_VERSION_TYPE_HPP
+
+// (C) Copyright 2010 Robert Ramey
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/cstdint.hpp> // uint_least8_t
+#include <boost/integer_traits.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/is_bitwise_serializable.hpp>
+
+// fixes broken example build on x86_64-linux-gnu-gcc-4.6.0
+#include <boost/assert.hpp>
+
+namespace boost { 
+namespace serialization {
+
+#if defined(_MSC_VER)
+#pragma warning( push )
+#pragma warning( disable : 4244 4267 )
+#endif
+
+class item_version_type {
+private:
+    typedef unsigned int base_type;
+    base_type t;
+public:
+    // should be private - but MPI fails if it's not!!!
+    item_version_type(): t(0) {};
+    explicit item_version_type(const unsigned int t_) : t(t_){
+        BOOST_ASSERT(t_ <= boost::integer_traits<base_type>::const_max);
+    }
+    item_version_type(const item_version_type & t_) : 
+        t(t_.t)
+    {}
+    item_version_type & operator=(item_version_type rhs){
+        t = rhs.t; 
+        return *this;
+    }
+    // used for text output
+    operator base_type () const {
+        return t;
+    }                
+    // used for text input
+    operator base_type & () {
+        return t;
+    }
+    bool operator==(const item_version_type & rhs) const {
+        return t == rhs.t;
+    } 
+    bool operator<(const item_version_type & rhs) const {
+        return t < rhs.t;
+    }
+};
+
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+
+} } // end namespace boost::serialization
+
+BOOST_IS_BITWISE_SERIALIZABLE(item_version_type)
+
+BOOST_CLASS_IMPLEMENTATION(item_version_type, primitive_type)
+
+#endif //BOOST_SERIALIZATION_ITEM_VERSION_TYPE_HPP
diff --git a/SRC/Serialization/level.hpp b/SRC/Serialization/level.hpp
new file mode 100755
index 0000000..383453e
--- /dev/null
+++ b/SRC/Serialization/level.hpp
@@ -0,0 +1,125 @@
+#ifndef BOOST_SERIALIZATION_LEVEL_HPP
+#define BOOST_SERIALIZATION_LEVEL_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// level.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <boost/type_traits/is_fundamental.hpp>
+#include <boost/type_traits/is_enum.hpp>
+#include <boost/type_traits/is_array.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+#include <boost/mpl/aux_/nttp_decl.hpp>
+
+#include <Serialization/level_enum.hpp>
+
+namespace boost {
+namespace serialization {
+
+struct basic_traits;
+
+// default serialization implementation level
+template<class T>
+struct implementation_level_impl {
+    template<class U>
+    struct traits_class_level {
+        typedef BOOST_DEDUCED_TYPENAME U::level type;
+    };
+
+    typedef mpl::integral_c_tag tag;
+    // note: at least one compiler complained w/o the full qualification
+    // on basic traits below
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_base_and_derived<boost::serialization::basic_traits, T>,
+            traits_class_level< T >,
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_fundamental< T >,
+            mpl::int_<primitive_type>,
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_class< T >,
+            mpl::int_<object_class_info>,
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_array< T >,
+            #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560))
+                mpl::int_<not_serializable>,
+            #else
+                mpl::int_<object_serializable>,
+            #endif
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_enum< T >,
+            //#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560))
+            //    mpl::int_<not_serializable>,
+            //#else
+                mpl::int_<primitive_type>,
+            //#endif
+        //else
+            mpl::int_<not_serializable>
+        >
+        >
+        >
+        >
+        >::type type;
+        // vc 7.1 doesn't like enums here
+    BOOST_STATIC_CONSTANT(int, value = type::value);
+};
+
+template<class T>
+struct implementation_level : 
+    public implementation_level_impl<const T>
+{
+};
+
+template<class T, BOOST_MPL_AUX_NTTP_DECL(int, L) >
+inline bool operator>=(implementation_level< T > t, enum level_type l)
+{
+    return t.value >= (int)l;
+}
+
+} // namespace serialization
+} // namespace boost
+
+// specify the level of serialization implementation for the class
+// require that class info saved when versioning is used
+#define BOOST_CLASS_IMPLEMENTATION(T, E)                 \
+    namespace boost {                                    \
+    namespace serialization {                            \
+    template <>                                          \
+    struct implementation_level_impl< const T >                     \
+    {                                                    \
+        typedef mpl::integral_c_tag tag;                 \
+        typedef mpl::int_< E > type;                     \
+        BOOST_STATIC_CONSTANT(                           \
+            int,                                         \
+            value = implementation_level_impl::type::value    \
+        );                                               \
+    };                                                   \
+    }                                                    \
+    }
+    /**/
+
+#endif // BOOST_SERIALIZATION_LEVEL_HPP
diff --git a/SRC/Serialization/level_enum.hpp b/SRC/Serialization/level_enum.hpp
new file mode 100755
index 0000000..97d499e
--- /dev/null
+++ b/SRC/Serialization/level_enum.hpp
@@ -0,0 +1,55 @@
+#ifndef BOOST_SERIALIZATION_LEVEL_ENUM_HPP
+#define BOOST_SERIALIZATION_LEVEL_ENUM_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// level_enum.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+namespace boost {
+namespace serialization {
+
+// for each class used in the program, specify which level
+// of serialization should be implemented
+
+// names for each level
+enum level_type
+{
+    // Don't serialize this type. An attempt to do so should
+    // invoke a compile time assertion.
+    not_serializable = 0,
+    // write/read this type directly to the archive. In this case
+    // serialization code won't be called.  This is the default
+    // case for fundamental types.  It presumes a member function or
+    // template in the archive class that can handle this type.
+    // there is no runtime overhead associated reading/writing
+    // instances of this level
+    primitive_type = 1,
+    // Serialize the objects of this type using the objects "serialize"
+    // function or template. This permits values to be written/read
+    // to/from archives but includes no class or version information. 
+    object_serializable = 2,
+    ///////////////////////////////////////////////////////////////////
+    // once an object is serialized at one of the above levels, the
+    // corresponding archives cannot be read if the implementation level
+    // for the archive object is changed.  
+    ///////////////////////////////////////////////////////////////////
+    // Add class information to the archive.  Class information includes
+    // implementation level, class version and class name if available
+    object_class_info = 3
+};
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_LEVEL_ENUM_HPP
diff --git a/SRC/Serialization/list.hpp b/SRC/Serialization/list.hpp
new file mode 100755
index 0000000..d4d2194
--- /dev/null
+++ b/SRC/Serialization/list.hpp
@@ -0,0 +1,77 @@
+#ifndef BOOST_SERIALIZATION_LIST_HPP
+#define BOOST_SERIALIZATION_LIST_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// list.hpp: serialization for stl list templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <list>
+
+#include <boost/config.hpp>
+
+#include <Serialization/collections_save_imp.hpp>
+#include <Serialization/collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class U, class Allocator>
+inline void save(
+    Archive & ar,
+    const std::list<U, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::save_collection<
+        Archive, 
+        std::list<U, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class U, class Allocator>
+inline void load(
+    Archive & ar,
+    std::list<U, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::list<U, Allocator>,
+        boost::serialization::stl::archive_input_seq<
+            Archive, 
+            std::list<U, Allocator> 
+        >,
+        boost::serialization::stl::no_reserve_imp<std::list<U, Allocator> >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class U, class Allocator>
+inline void serialize(
+    Archive & ar,
+    std::list<U, Allocator> & t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // serialization
+} // namespace boost
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(std::list)
+
+#endif // BOOST_SERIALIZATION_LIST_HPP
diff --git a/SRC/Serialization/map.hpp b/SRC/Serialization/map.hpp
new file mode 100755
index 0000000..d5a0114
--- /dev/null
+++ b/SRC/Serialization/map.hpp
@@ -0,0 +1,118 @@
+#ifndef  BOOST_SERIALIZATION_MAP_HPP
+#define BOOST_SERIALIZATION_MAP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization/map.hpp:
+// serialization for stl map templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <map>
+
+#include <boost/config.hpp>
+
+#include <Serialization/utility.hpp>
+#include <Serialization/collections_save_imp.hpp>
+#include <Serialization/collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class Type, class Key, class Compare, class Allocator >
+inline void save(
+    Archive & ar,
+    const std::map<Key, Type, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::save_collection<
+        Archive, 
+        std::map<Key, Type, Compare, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class Type, class Key, class Compare, class Allocator >
+inline void load(
+    Archive & ar,
+    std::map<Key, Type, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::map<Key, Type, Compare, Allocator>,
+        boost::serialization::stl::archive_input_map<
+            Archive, std::map<Key, Type, Compare, Allocator> >,
+            boost::serialization::stl::no_reserve_imp<std::map<
+                Key, Type, Compare, Allocator
+            >
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class Type, class Key, class Compare, class Allocator >
+inline void serialize(
+    Archive & ar,
+    std::map<Key, Type, Compare, Allocator> &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+// multimap
+template<class Archive, class Type, class Key, class Compare, class Allocator >
+inline void save(
+    Archive & ar,
+    const std::multimap<Key, Type, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::save_collection<
+        Archive, 
+        std::multimap<Key, Type, Compare, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class Type, class Key, class Compare, class Allocator >
+inline void load(
+    Archive & ar,
+    std::multimap<Key, Type, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::multimap<Key, Type, Compare, Allocator>,
+        boost::serialization::stl::archive_input_map<
+            Archive, std::multimap<Key, Type, Compare, Allocator> 
+        >,
+        boost::serialization::stl::no_reserve_imp<
+            std::multimap<Key, Type, Compare, Allocator> 
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class Type, class Key, class Compare, class Allocator >
+inline void serialize(
+    Archive & ar,
+    std::multimap<Key, Type, Compare, Allocator> &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_MAP_HPP
diff --git a/SRC/Serialization/nvp.hpp b/SRC/Serialization/nvp.hpp
new file mode 100755
index 0000000..98e98dc
--- /dev/null
+++ b/SRC/Serialization/nvp.hpp
@@ -0,0 +1,144 @@
+#ifndef BOOST_SERIALIZATION_NVP_HPP
+#define BOOST_SERIALIZATION_NVP_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// nvp.hpp: interface for serialization system.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <utility>
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+// supress noise
+#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
+# pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+
+#include <Serialization/level.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/split_member.hpp>
+#include <Serialization/base_object.hpp>
+#include <Serialization/traits.hpp>
+#include <Serialization/wrapper.hpp>
+
+namespace boost {
+namespace serialization {
+
+template<class T>
+struct nvp : 
+    public std::pair<const char *, T *>,
+    public wrapper_traits<const nvp< T > >
+{
+    explicit nvp(const char * name_, T & t) :
+        // note: redundant cast works around borland issue
+        // note: added _ to suppress useless gcc warning
+        std::pair<const char *, T *>(name_, (T*)(& t))
+    {}
+    nvp(const nvp & rhs) : 
+        // note: redundant cast works around borland issue
+        std::pair<const char *, T *>(rhs.first, (T*)rhs.second)
+    {}
+
+    const char * name() const {
+        return this->first;
+    }
+    T & value() const {
+        return *(this->second);
+    }
+
+    const T & const_value() const {
+        return *(this->second);
+    }
+
+    // True64 compiler complains with a warning about the use of
+    // the name "Archive" hiding some higher level usage.  I'm sure this
+    // is an error but I want to accomodated as it generates a long warning
+    // listing and might be related to a lot of test failures.
+    // default treatment for name-value pairs. The name is
+    // just discarded and only the value is serialized. 
+    template<class Archivex>
+    void save(
+        Archivex & ar, 
+        const unsigned int /* file_version */
+    ) const {
+        // CodeWarrior 8.x can't seem to resolve the << op for a rhs of "const T *"
+        ar.operator<<(const_value());
+    }
+    template<class Archivex>
+    void load(
+        Archivex & ar, 
+        const unsigned int /* file_version */
+    ){
+        // CodeWarrior 8.x can't seem to resolve the >> op for a rhs of "const T *"
+        ar.operator>>(value());
+    }
+    BOOST_SERIALIZATION_SPLIT_MEMBER()
+};
+
+template<class T>
+inline
+#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+const
+#endif
+nvp< T > make_nvp(const char * name, T & t){
+    return nvp< T >(name, t);
+}
+
+// to maintain efficiency and portability, we want to assign
+// specific serialization traits to all instances of this wrappers.
+// we can't strait forward method below as it depends upon
+// Partial Template Specialization and doing so would mean that wrappers
+// wouldn't be treated the same on different platforms.  This would
+// break archive portability. Leave this here as reminder not to use it !!!
+#if 0 // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+
+template <class T>
+struct implementation_level<nvp< T > >
+{
+    typedef mpl::integral_c_tag tag;
+    typedef mpl::int_<object_serializable> type;
+    BOOST_STATIC_CONSTANT(int, value = implementation_level::type::value);
+};
+
+// nvp objects are generally created on the stack and are never tracked
+template<class T>
+struct tracking_level<nvp< T > >
+{
+    typedef mpl::integral_c_tag tag;
+    typedef mpl::int_<track_never> type;
+    BOOST_STATIC_CONSTANT(int, value = tracking_level::type::value);
+};
+
+#endif
+
+} // seralization
+} // boost
+
+#include <boost/preprocessor/stringize.hpp>
+
+#define BOOST_SERIALIZATION_NVP(name)                              \
+    boost::serialization::make_nvp(BOOST_PP_STRINGIZE(name), name)
+/**/
+
+#define BOOST_SERIALIZATION_BASE_OBJECT_NVP(name)                  \
+    boost::serialization::make_nvp(                                \
+        BOOST_PP_STRINGIZE(name),                                  \
+        boost::serialization::base_object<name >(*this)            \
+    )
+/**/
+
+#endif // BOOST_SERIALIZATION_NVP_HPP
diff --git a/SRC/Serialization/optional.hpp b/SRC/Serialization/optional.hpp
new file mode 100755
index 0000000..8b16f9c
--- /dev/null
+++ b/SRC/Serialization/optional.hpp
@@ -0,0 +1,127 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+
+// (C) Copyright 2002-4 Pavel Vozenilek . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Provides non-intrusive serialization for boost::optional.
+
+#ifndef BOOST_SERIALIZATION_OPTIONAL_HPP_
+#define BOOST_SERIALIZATION_OPTIONAL_HPP_
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#include <boost/config.hpp>
+
+#include <Serialization/archive/detail/basic_iarchive.hpp>
+
+#include <boost/optional.hpp>
+#include <Serialization/item_version_type.hpp>
+#include <Serialization/split_free.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/version.hpp>
+#include <Serialization/detail/stack_constructor.hpp>
+
+// function specializations must be defined in the appropriate
+// namespace - boost::serialization
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class T>
+void save(
+    Archive & ar, 
+    const boost::optional< T > & t, 
+    const unsigned int /*version*/
+){
+    const bool tflag = t.is_initialized();
+    ar << boost::serialization::make_nvp("initialized", tflag);
+    if (tflag){
+        const boost::serialization::item_version_type item_version(version< T >::value);
+        #if 0
+        const boost::archive::library_version_type library_version(
+            ar.get_library_version()
+        };
+        if(boost::archive::library_version_type(3) < library_version){
+            ar << BOOST_SERIALIZATION_NVP(item_version);
+        }
+        #else
+            ar << BOOST_SERIALIZATION_NVP(item_version);
+        #endif
+        ar << boost::serialization::make_nvp("value", *t);
+    }
+}
+
+template<class Archive, class T>
+void load(
+    Archive & ar, 
+    boost::optional< T > & t, 
+    const unsigned int /*version*/
+){
+    bool tflag;
+    ar >> boost::serialization::make_nvp("initialized", tflag);
+    if (tflag){
+        boost::serialization::item_version_type item_version(0);
+        boost::archive::library_version_type library_version(
+            ar.get_library_version()
+        );
+        if(boost::archive::library_version_type(3) < library_version){
+            // item_version is handled as an attribute so it doesnt need an NVP
+           ar >> BOOST_SERIALIZATION_NVP(item_version);
+        }
+        detail::stack_construct<Archive, T> aux(ar, item_version);
+        ar >> boost::serialization::make_nvp("value", aux.reference());
+        t.reset(aux.reference());
+    }
+    else {
+        t.reset();
+    }
+}
+
+template<class Archive, class T>
+void serialize(
+    Archive & ar, 
+    boost::optional< T > & t, 
+    const unsigned int version
+){
+    boost::serialization::split_free(ar, t, version);
+}
+
+// the following would be slightly more efficient.  But it
+// would mean that archives created with programs that support
+// TPS wouldn't be readable by programs that don't support TPS.
+// Hence we decline to support this otherwise convenient optimization.
+//#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+#if 0
+
+template <class T>
+struct implementation_level<optional< T > >
+{
+    typedef mpl::integral_c_tag tag;
+    typedef mpl::int_<boost::serialization::object_serializable> type;
+    BOOST_STATIC_CONSTANT(
+        int , 
+        value = boost::serialization::implementation_level::type::value
+    );
+};
+
+template<class T>
+struct tracking_level<optional< T > >
+{
+    typedef mpl::integral_c_tag tag;
+    typedef mpl::int_<boost::serialization::track_never> type;
+    BOOST_STATIC_CONSTANT(
+        int , 
+        value = boost::serialization::tracking_level::type::value
+    );
+};
+
+#endif
+
+} // serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_OPTIONAL_HPP_
diff --git a/SRC/Serialization/pfto.hpp b/SRC/Serialization/pfto.hpp
new file mode 100755
index 0000000..3b1a0b8
--- /dev/null
+++ b/SRC/Serialization/pfto.hpp
@@ -0,0 +1,78 @@
+#ifndef BOOST_SERIALIZATION_PFTO_HPP
+#define BOOST_SERIALIZATION_PFTO_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// pfto.hpp: workarounds for compilers which have problems supporting
+// Partial Function Template Ordering (PFTO).
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/serialization for updates, documentation, and revision history.
+// PFTO version is used to specify the last argument of certain functions
+// Function it is used to support  compilers that fail to support correct Partial 
+// Template Ordering
+#include <boost/config.hpp>
+
+// some compilers can use an exta argument and use function overloading
+// to choose desired function.  This extra argument is long in the default
+// function implementation and int for the rest.  The function is called
+// with an int argument.  This first attempts to match functions with an
+// int argument before the default one (with a long argument).  This is
+// known to function with VC 6.0. On other compilers this fails (Borland)
+// or causes other problems (GCC).  note: this 
+
+#if defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+    #define BOOST_PFTO long
+#else
+    #define BOOST_PFTO
+#endif
+
+// here's another approach.  Rather than use a default function - make sure
+// there is no default at all by requiring that all function invocations
+// have a "wrapped" argument type.  This solves a problem with VC 6.0
+// (and perhaps others) while implementing templated constructors.
+
+namespace boost {
+namespace serialization {
+
+template<class T>
+struct pfto_wrapper {
+    const T & t;
+    operator const T & (){
+        return t;
+    }
+    pfto_wrapper (const T & rhs) : t(rhs) {}
+};
+
+template<class T>
+pfto_wrapper< T > make_pfto_wrapper(const T & t, BOOST_PFTO int){
+    return pfto_wrapper< T >(t);
+}
+
+template<class T>
+pfto_wrapper< T > make_pfto_wrapper(const pfto_wrapper< T > & t, int){
+    return t;
+}
+
+} // namespace serialization
+} // namespace boost
+
+#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
+    #define BOOST_PFTO_WRAPPER(T) \
+        boost::serialization::pfto_wrapper< T >
+    #define BOOST_MAKE_PFTO_WRAPPER(t) \
+        boost::serialization::make_pfto_wrapper(t, 0)
+#else
+    #define BOOST_PFTO_WRAPPER(T) T
+    #define BOOST_MAKE_PFTO_WRAPPER(t) t
+#endif
+
+#endif // BOOST_SERIALIZATION_PFTO_HPP
diff --git a/SRC/Serialization/scoped_ptr.hpp b/SRC/Serialization/scoped_ptr.hpp
new file mode 100755
index 0000000..30cccfa
--- /dev/null
+++ b/SRC/Serialization/scoped_ptr.hpp
@@ -0,0 +1,58 @@
+#ifndef BOOST_SERIALIZATION_SCOPED_PTR_HPP_VP_2003_10_30
+#define BOOST_SERIALIZATION_SCOPED_PTR_HPP_VP_2003_10_30
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//  Copyright (c) 2003 Vladimir Prus.
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// Provides non-intrusive serialization for boost::scoped_ptr
+// Does not allow to serialize scoped_ptr's to builtin types.
+
+#include <boost/config.hpp>
+
+#include <boost/scoped_ptr.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+    
+    template<class Archive, class T>
+    void save(
+        Archive & ar, 
+        const boost::scoped_ptr< T > & t, 
+        const unsigned int /* version */
+    ){
+        T* r = t.get();
+        ar << boost::serialization::make_nvp("scoped_ptr", r);
+    }
+
+    template<class Archive, class T>
+    void load(
+        Archive & ar, 
+        boost::scoped_ptr< T > & t, 
+        const unsigned int /* version */
+    ){
+        T* r;
+        ar >> boost::serialization::make_nvp("scoped_ptr", r);
+        t.reset(r); 
+    }
+
+    template<class Archive, class T>
+    void serialize(
+        Archive& ar, 
+        boost::scoped_ptr< T >& t, 
+        const unsigned int version
+    ){
+        boost::serialization::split_free(ar, t, version);
+    }
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_SCOPED_PTR_HPP_VP_2003_10_30
diff --git a/SRC/Serialization/serialization.hpp b/SRC/Serialization/serialization.hpp
new file mode 100755
index 0000000..ec44003
--- /dev/null
+++ b/SRC/Serialization/serialization.hpp
@@ -0,0 +1,167 @@
+#ifndef BOOST_SERIALIZATION_SERIALIZATION_HPP
+#define BOOST_SERIALIZATION_SERIALIZATION_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1310)
+#  pragma warning (disable : 4675) // suppress ADL warning
+#endif
+
+#include <boost/config.hpp>
+#include <Serialization/strong_typedef.hpp>
+#include <Serialization/pfto.hpp>
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization.hpp: interface for serialization system.
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+//////////////////////////////////////////////////////////////////////
+// public interface to serialization. 
+
+/////////////////////////////////////////////////////////////////////////////
+// layer 0 - intrusive verison
+// declared and implemented for each user defined class to be serialized
+//
+//  template<Archive>
+//  serialize(Archive &ar, const unsigned int file_version){
+//      ar & base_object<base>(*this) & member1 & member2 ... ;
+//  }
+
+/////////////////////////////////////////////////////////////////////////////
+// layer 1 - layer that routes member access through the access class.
+// this is what permits us to grant access to private class member functions
+// by specifying friend class boost::serialization::access
+
+#include <Serialization/access.hpp>
+
+/////////////////////////////////////////////////////////////////////////////
+// layer 2 - default implementation of non-intrusive serialization.
+//
+// note the usage of function overloading to compensate that C++ does not
+// currently support Partial Template Specialization for function templates 
+// We have declared the version number as "const unsigned long".  
+// Overriding templates for specific data types should declare the version
+// number as "const unsigned int". Template matching will first be applied
+// to functions with the same version types - that is the overloads.  
+// If there is no declared function prototype that matches, the second argument
+// will be converted to "const unsigned long" and a match will be made with 
+// one of the default template functions below.
+
+namespace boost {
+namespace serialization {
+
+BOOST_STRONG_TYPEDEF(unsigned int, version_type)
+
+// default implementation - call the member function "serialize"
+template<class Archive, class T>
+inline void serialize(
+    Archive & ar, T & t, const BOOST_PFTO unsigned int file_version
+){
+    access::serialize(ar, t, static_cast<unsigned int>(file_version));
+}
+
+// save data required for construction
+template<class Archive, class T>
+inline void save_construct_data(
+    Archive & /*ar*/, 
+    const T * /*t*/, 
+    const BOOST_PFTO unsigned int /*file_version */
+){
+    // default is to save no data because default constructor
+    // requires no arguments.
+}
+
+// load data required for construction and invoke constructor in place
+template<class Archive, class T>
+inline void load_construct_data(
+    Archive & /*ar*/, 
+    T * t, 
+    const BOOST_PFTO unsigned int /*file_version*/
+){
+    // default just uses the default constructor.  going
+    // through access permits usage of otherwise private default
+    // constructor
+    access::construct(t);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// layer 3 - move call into serialization namespace so that ADL will function
+// in the manner we desire.
+//
+// on compilers which don't implement ADL. only the current namespace
+// i.e. boost::serialization will be searched.
+// 
+// on compilers which DO implement ADL
+// serialize overrides can be in any of the following
+// 
+// 1) same namepace as Archive
+// 2) same namespace as T
+// 3) boost::serialization
+//
+// Due to Martin Ecker
+
+template<class Archive, class T>
+inline void serialize_adl(
+    Archive & ar, 
+    T & t, 
+    const unsigned int file_version
+){
+    // note usage of function overloading to delay final resolution
+    // until the point of instantiation.  This works around the two-phase
+    // lookup "feature" which inhibits redefintion of a default function
+    // template implementation. Due to Robert Ramey
+    //
+    // Note that this trick generates problems for compiles which don't support
+    // PFTO, suppress it here.  As far as we know, there are no compilers
+    // which fail to support PFTO while supporting two-phase lookup.
+    #if ! defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+        const version_type v(file_version);
+        serialize(ar, t, v);
+    #else
+        serialize(ar, t, file_version);
+    #endif
+}
+
+template<class Archive, class T>
+inline void save_construct_data_adl(
+    Archive & ar, 
+    const T * t, 
+    const unsigned int file_version
+){
+    // see above
+    #if ! defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+        const version_type v(file_version);
+        save_construct_data(ar, t, v);
+    #else
+        save_construct_data(ar, t, file_version);
+    #endif
+}
+
+template<class Archive, class T>
+inline void load_construct_data_adl(
+    Archive & ar, 
+    T * t, 
+    const unsigned int file_version
+){
+    // see above comment
+    #if ! defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
+        const version_type v(file_version);
+        load_construct_data(ar, t, v);
+    #else
+        load_construct_data(ar, t, file_version);
+    #endif
+}
+
+} // namespace serialization
+} // namespace boost
+
+#endif //BOOST_SERIALIZATION_SERIALIZATION_HPP
diff --git a/SRC/Serialization/set.hpp b/SRC/Serialization/set.hpp
new file mode 100755
index 0000000..1b09b27
--- /dev/null
+++ b/SRC/Serialization/set.hpp
@@ -0,0 +1,120 @@
+#ifndef  BOOST_SERIALIZATION_SET_HPP
+#define BOOST_SERIALIZATION_SET_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// set.hpp: serialization for stl set templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <set>
+
+#include <boost/config.hpp>
+
+#include <Serialization/collections_save_imp.hpp>
+#include <Serialization/collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class Key, class Compare, class Allocator >
+inline void save(
+    Archive & ar,
+    const std::set<Key, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::save_collection<
+        Archive, std::set<Key, Compare, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class Key, class Compare, class Allocator >
+inline void load(
+    Archive & ar,
+    std::set<Key, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::set<Key, Compare, Allocator>,
+        boost::serialization::stl::archive_input_set<
+            Archive, std::set<Key, Compare, Allocator> 
+        >,
+        boost::serialization::stl::no_reserve_imp<std::set<
+            Key, Compare, Allocator> 
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class Key, class Compare, class Allocator >
+inline void serialize(
+    Archive & ar,
+    std::set<Key, Compare, Allocator> & t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+// multiset
+template<class Archive, class Key, class Compare, class Allocator >
+inline void save(
+    Archive & ar,
+    const std::multiset<Key, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::save_collection<
+        Archive, 
+        std::multiset<Key, Compare, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class Key, class Compare, class Allocator >
+inline void load(
+    Archive & ar,
+    std::multiset<Key, Compare, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::multiset<Key, Compare, Allocator>,
+        boost::serialization::stl::archive_input_set<
+            Archive, std::multiset<Key, Compare, Allocator> 
+        >,
+        boost::serialization::stl::no_reserve_imp<
+            std::multiset<Key, Compare, Allocator> 
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class Key, class Compare, class Allocator >
+inline void serialize(
+    Archive & ar,
+    std::multiset<Key, Compare, Allocator> & t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(std::set)
+BOOST_SERIALIZATION_COLLECTION_TRAITS(std::multiset)
+
+#endif // BOOST_SERIALIZATION_SET_HPP
diff --git a/SRC/Serialization/shared_ptr.hpp b/SRC/Serialization/shared_ptr.hpp
new file mode 100755
index 0000000..7dd8917
--- /dev/null
+++ b/SRC/Serialization/shared_ptr.hpp
@@ -0,0 +1,177 @@
+#ifndef BOOST_SERIALIZATION_SHARED_PTR_HPP
+#define BOOST_SERIALIZATION_SHARED_PTR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// shared_ptr.hpp: serialization for boost shared pointer
+
+// (C) Copyright 2004 Robert Ramey and Martin Ecker
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // NULL
+
+#include <boost/config.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+
+#include <boost/detail/workaround.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include <Serialization/split_free.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/version.hpp>
+#include <Serialization/tracking.hpp>
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// shared_ptr serialization traits
+// version 1 to distinguish from boost 1.32 version. Note: we can only do this
+// for a template when the compiler supports partial template specialization
+
+#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
+    namespace boost {
+    namespace serialization{
+        template<class T>
+        struct version< ::boost::shared_ptr< T > > {
+            typedef mpl::integral_c_tag tag;
+            #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
+            typedef BOOST_DEDUCED_TYPENAME mpl::int_<1> type;
+            #else
+            typedef mpl::int_<1> type;
+            #endif
+            #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
+            BOOST_STATIC_CONSTANT(int, value = 1);
+            #else
+            BOOST_STATIC_CONSTANT(int, value = type::value);
+            #endif
+        };
+        // don't track shared pointers
+        template<class T>
+        struct tracking_level< ::boost::shared_ptr< T > > { 
+            typedef mpl::integral_c_tag tag;
+            #if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
+            typedef BOOST_DEDUCED_TYPENAME mpl::int_< ::boost::serialization::track_never> type;
+            #else
+            typedef mpl::int_< ::boost::serialization::track_never> type;
+            #endif
+            #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x570))
+            BOOST_STATIC_CONSTANT(int, value = ::boost::serialization::track_never);
+            #else
+            BOOST_STATIC_CONSTANT(int, value = type::value);
+            #endif
+        };
+    }}
+    #define BOOST_SERIALIZATION_SHARED_PTR(T)
+#else
+    // define macro to let users of these compilers do this
+    #define BOOST_SERIALIZATION_SHARED_PTR(T)                         \
+    BOOST_CLASS_VERSION(                                              \
+        ::boost::shared_ptr< T >,                                     \
+        1                                                             \
+    )                                                                 \
+    BOOST_CLASS_TRACKING(                                             \
+        ::boost::shared_ptr< T >,                                     \
+        ::boost::serialization::track_never                           \
+    )                                                                 \
+    /**/
+#endif
+
+namespace boost {
+namespace serialization{
+
+struct null_deleter {
+    void operator()(void const *) const {}
+};
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization for shared_ptr
+
+template<class Archive, class T>
+inline void save(
+    Archive & ar,
+    const boost::shared_ptr< T > &t,
+    const unsigned int /* file_version */
+){
+    // The most common cause of trapping here would be serializing
+    // something like shared_ptr<int>.  This occurs because int
+    // is never tracked by default.  Wrap int in a trackable type
+    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
+    const T * t_ptr = t.get();
+    ar << boost::serialization::make_nvp("px", t_ptr);
+}
+
+#ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+template<class Archive, class T>
+inline void load(
+    Archive & ar,
+    boost::shared_ptr< T > &t,
+    const unsigned int file_version
+){
+    // The most common cause of trapping here would be serializing
+    // something like shared_ptr<int>.  This occurs because int
+    // is never tracked by default.  Wrap int in a trackable type
+    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
+    T* r;
+    if(file_version < 1){
+        //ar.register_type(static_cast<
+        //    boost_132::detail::sp_counted_base_impl<T *, boost::checked_deleter< T > > *
+        //>(NULL));
+        ar.register_type(static_cast<
+            boost_132::detail::sp_counted_base_impl<T *, null_deleter > *
+        >(NULL));
+        boost_132::shared_ptr< T > sp;
+        ar >> boost::serialization::make_nvp("px", sp.px);
+        ar >> boost::serialization::make_nvp("pn", sp.pn);
+        // got to keep the sps around so the sp.pns don't disappear
+        ar.append(sp);
+        r = sp.get();
+    }
+    else{
+        ar >> boost::serialization::make_nvp("px", r);
+    }
+    ar.reset(t,r);
+}
+
+#else
+template<class Archive, class T>
+inline void load(
+    Archive & ar,
+    boost::shared_ptr< T > &t,
+    const unsigned int /*file_version*/
+){
+    // The most common cause of trapping here would be serializing
+    // something like shared_ptr<int>.  This occurs because int
+    // is never tracked by default.  Wrap int in a trackable type
+    BOOST_STATIC_ASSERT((tracking_level< T >::value != track_never));
+    T* r;
+    ar >> boost::serialization::make_nvp("px", r);
+    ar.reset(t,r);
+}
+#endif
+
+template<class Archive, class T>
+inline void serialize(
+    Archive & ar,
+    boost::shared_ptr< T > &t,
+    const unsigned int file_version
+){
+    // correct shared_ptr serialization depends upon object tracking
+    // being used.
+    BOOST_STATIC_ASSERT(
+        boost::serialization::tracking_level< T >::value
+        != boost::serialization::track_never
+    );
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_SHARED_PTR_HPP
diff --git a/SRC/Serialization/shared_ptr_132.hpp b/SRC/Serialization/shared_ptr_132.hpp
new file mode 100755
index 0000000..693939e
--- /dev/null
+++ b/SRC/Serialization/shared_ptr_132.hpp
@@ -0,0 +1,222 @@
+#ifndef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+#define BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// shared_ptr.hpp: serialization for boost shared pointer
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// note: totally unadvised hack to gain access to private variables
+// in shared_ptr and shared_count. Unfortunately its the only way to
+// do this without changing shared_ptr and shared_count
+// the best we can do is to detect a conflict here
+#include <boost/config.hpp>
+
+#include <list>
+#include <cstddef> // NULL
+
+#include <Serialization/assume_abstract.hpp>
+#include <Serialization/split_free.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/tracking.hpp>
+#include <Serialization/void_cast.hpp>
+
+// mark base class as an (uncreatable) base class
+#include <Serialization/detail/shared_ptr_132.hpp>
+
+/////////////////////////////////////////////////////////////
+// Maintain a couple of lists of loaded shared pointers of the old previous
+// version (1.32)
+
+namespace boost_132 { 
+namespace serialization {
+namespace detail {
+
+struct null_deleter {
+    void operator()(void const *) const {}
+};
+
+} // namespace detail
+} // namespace serialization
+} // namespace boost_132
+
+/////////////////////////////////////////////////////////////
+// sp_counted_base_impl serialization
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class P, class D>
+inline void serialize(
+    Archive & /* ar */,
+    boost_132::detail::sp_counted_base_impl<P, D> & /* t */,
+    const unsigned int /*file_version*/
+){
+    // register the relationship between each derived class
+    // its polymorphic base
+    boost::serialization::void_cast_register<
+        boost_132::detail::sp_counted_base_impl<P, D>,
+        boost_132::detail::sp_counted_base 
+    >(
+        static_cast<boost_132::detail::sp_counted_base_impl<P, D> *>(NULL),
+        static_cast<boost_132::detail::sp_counted_base *>(NULL)
+    );
+}
+
+template<class Archive, class P, class D>
+inline void save_construct_data(
+    Archive & ar,
+    const 
+    boost_132::detail::sp_counted_base_impl<P, D> *t, 
+    const BOOST_PFTO unsigned int /* file_version */
+){
+    // variables used for construction
+    ar << boost::serialization::make_nvp("ptr", t->ptr);
+}
+
+template<class Archive, class P, class D>
+inline void load_construct_data(
+    Archive & ar,
+    boost_132::detail::sp_counted_base_impl<P, D> * t, 
+    const unsigned int /* file_version */
+){
+    P ptr_;
+    ar >> boost::serialization::make_nvp("ptr", ptr_);
+    // ::new(t)boost_132::detail::sp_counted_base_impl<P, D>(ptr_,  D()); 
+    // placement
+    // note: the original ::new... above is replaced by the one here.  This one
+    // creates all new objects with a null_deleter so that after the archive
+    // is finished loading and the shared_ptrs are destroyed - the underlying
+    // raw pointers are NOT deleted.  This is necessary as they are used by the 
+    // new system as well.
+    ::new(t)boost_132::detail::sp_counted_base_impl<
+        P, 
+        boost_132::serialization::detail::null_deleter
+    >(
+        ptr_,  boost_132::serialization::detail::null_deleter()
+    ); // placement new
+    // compensate for that fact that a new shared count always is 
+    // initialized with one. the add_ref_copy below will increment it
+    // every time its serialized so without this adjustment
+    // the use and weak counts will be off by one.
+    t->use_count_ = 0;
+}
+
+} // serialization
+} // namespace boost
+
+/////////////////////////////////////////////////////////////
+// shared_count serialization
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive>
+inline void save(
+    Archive & ar,
+    const boost_132::detail::shared_count &t,
+    const unsigned int /* file_version */
+){
+    ar << boost::serialization::make_nvp("pi", t.pi_);
+}
+
+template<class Archive>
+inline void load(
+    Archive & ar,
+    boost_132::detail::shared_count &t,
+    const unsigned int /* file_version */
+){
+    ar >> boost::serialization::make_nvp("pi", t.pi_);
+    if(NULL != t.pi_)
+        t.pi_->add_ref_copy();
+}
+
+} // serialization
+} // namespace boost
+
+BOOST_SERIALIZATION_SPLIT_FREE(boost_132::detail::shared_count)
+
+/////////////////////////////////////////////////////////////
+// implement serialization for shared_ptr< T >
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class T>
+inline void save(
+    Archive & ar,
+    const boost_132::shared_ptr< T > &t,
+    const unsigned int /* file_version */
+){
+    // only the raw pointer has to be saved
+    // the ref count is maintained automatically as shared pointers are loaded
+    ar.register_type(static_cast<
+        boost_132::detail::sp_counted_base_impl<T *, boost::checked_deleter< T > > *
+    >(NULL));
+    ar << boost::serialization::make_nvp("px", t.px);
+    ar << boost::serialization::make_nvp("pn", t.pn);
+}
+
+template<class Archive, class T>
+inline void load(
+    Archive & ar,
+    boost_132::shared_ptr< T > &t,
+    const unsigned int /* file_version */
+){
+    // only the raw pointer has to be saved
+    // the ref count is maintained automatically as shared pointers are loaded
+    ar.register_type(static_cast<
+        boost_132::detail::sp_counted_base_impl<T *, boost::checked_deleter< T > > *
+    >(NULL));
+    ar >> boost::serialization::make_nvp("px", t.px);
+    ar >> boost::serialization::make_nvp("pn", t.pn);
+}
+
+template<class Archive, class T>
+inline void serialize(
+    Archive & ar,
+    boost_132::shared_ptr< T > &t,
+    const unsigned int file_version
+){
+    // correct shared_ptr serialization depends upon object tracking
+    // being used.
+    BOOST_STATIC_ASSERT(
+        boost::serialization::tracking_level< T >::value
+        != boost::serialization::track_never
+    );
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // serialization
+} // namespace boost
+
+// note: change below uses null_deleter 
+// This macro is used to export GUIDS for shared pointers to allow
+// the serialization system to export them properly. David Tonge
+#define BOOST_SHARED_POINTER_EXPORT_GUID(T, K)                     \
+    typedef boost_132::detail::sp_counted_base_impl<               \
+        T *,                                                       \
+        boost::checked_deleter< T >                                \
+    > __shared_ptr_ ## T;                                          \
+    BOOST_CLASS_EXPORT_GUID(__shared_ptr_ ## T, "__shared_ptr_" K) \
+    BOOST_CLASS_EXPORT_GUID(T, K)                                  \
+    /**/
+
+#define BOOST_SHARED_POINTER_EXPORT(T)                             \
+    BOOST_SHARED_POINTER_EXPORT_GUID(                              \
+        T,                                                         \
+        BOOST_PP_STRINGIZE(T)                                      \
+    )                                                              \
+    /**/
+
+#endif // BOOST_SERIALIZATION_SHARED_PTR_132_HPP
diff --git a/SRC/Serialization/singleton.hpp b/SRC/Serialization/singleton.hpp
new file mode 100755
index 0000000..ca6ba9f
--- /dev/null
+++ b/SRC/Serialization/singleton.hpp
@@ -0,0 +1,158 @@
+#ifndef BOOST_SERIALIZATION_SINGLETON_HPP
+#define BOOST_SERIALIZATION_SINGLETON_HPP
+
+/////////1/////////2///////// 3/////////4/////////5/////////6/////////7/////////8
+//  singleton.hpp
+//
+// Copyright David Abrahams 2006. Original version
+//
+// Copyright Robert Ramey 2007.  Changes made to permit
+// application throughout the serialization library.
+//
+// Distributed under the Boost
+// Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// The intention here is to define a template which will convert
+// any class into a singleton with the following features:
+//
+// a) initialized before first use.
+// b) thread-safe for const access to the class
+// c) non-locking
+//
+// In order to do this,
+// a) Initialize dynamically when used.
+// b) Require that all singletons be initialized before main
+// is called or any entry point into the shared library is invoked.
+// This guarentees no race condition for initialization.
+// In debug mode, we assert that no non-const functions are called
+// after main is invoked.
+//
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif 
+
+#include <boost/assert.hpp>
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+#include <Serialization/force_include.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace serialization { 
+
+//////////////////////////////////////////////////////////////////////
+// Provides a dynamically-initialized (singleton) instance of T in a
+// way that avoids LNK1179 on vc6.  See http://tinyurl.com/ljdp8 or
+// http://lists.boost.org/Archives/boost/2006/05/105286.php for
+// details.
+//
+
+// singletons created by this code are guarenteed to be unique
+// within the executable or shared library which creates them.
+// This is sufficient and in fact ideal for the serialization library.
+// The singleton is created when the module is loaded and destroyed
+// when the module is unloaded.
+
+// This base class has two functions.
+
+// First it provides a module handle for each singleton indicating
+// the executable or shared library in which it was created. This
+// turns out to be necessary and sufficient to implement the tables
+// used by serialization library.
+
+// Second, it provides a mechanism to detect when a non-const function
+// is called after initialization.
+
+// make a singleton to lock/unlock all singletons for alteration.
+// The intent is that all singletons created/used by this code
+// are to be initialized before main is called. A test program
+// can lock all the singletons when main is entereed.  This any
+// attempt to retieve a mutable instances while locked will
+// generate a assertion if compiled for debug.
+
+class singleton_module : 
+    public boost::noncopyable
+{
+private:
+    static bool & get_lock(){
+        static bool lock = false;
+        return lock;
+    }
+public:
+//    static const void * get_module_handle(){
+//        return static_cast<const void *>(get_module_handle);
+//    }
+    static void lock(){
+        get_lock() = true;
+    }
+    static void unlock(){
+        get_lock() = false;
+    }
+    static bool is_locked() {
+        return get_lock();
+    }
+};
+
+namespace detail {
+
+template<class T>
+class singleton_wrapper : public T
+{
+public:
+    static bool m_is_destroyed;
+    ~singleton_wrapper(){
+        m_is_destroyed = true;
+    }
+};
+
+template<class T>
+bool detail::singleton_wrapper< T >::m_is_destroyed = false;
+
+} // detail
+
+template <class T>
+class singleton : public singleton_module
+{
+private:
+    BOOST_DLLEXPORT static T & instance;
+    // include this to provoke instantiation at pre-execution time
+    static void use(T const &) {}
+    BOOST_DLLEXPORT static T & get_instance() {
+        static detail::singleton_wrapper< T > t;
+        // refer to instance, causing it to be instantiated (and
+        // initialized at startup on working compilers)
+        BOOST_ASSERT(! detail::singleton_wrapper< T >::m_is_destroyed);
+        use(instance);
+        return static_cast<T &>(t);
+    }
+public:
+    BOOST_DLLEXPORT static T & get_mutable_instance(){
+        BOOST_ASSERT(! is_locked());
+        return get_instance();
+    }
+    BOOST_DLLEXPORT static const T & get_const_instance(){
+        return get_instance();
+    }
+    BOOST_DLLEXPORT static bool is_destroyed(){
+        return detail::singleton_wrapper< T >::m_is_destroyed;
+    }
+};
+
+template<class T>
+BOOST_DLLEXPORT T & singleton< T >::instance = singleton< T >::get_instance();
+
+} // namespace serialization
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+#endif // BOOST_SERIALIZATION_SINGLETON_HPP
diff --git a/SRC/Serialization/slist.hpp b/SRC/Serialization/slist.hpp
new file mode 100755
index 0000000..9fbdd67
--- /dev/null
+++ b/SRC/Serialization/slist.hpp
@@ -0,0 +1,103 @@
+#ifndef BOOST_SERIALIZATION_SLIST_HPP
+#define BOOST_SERIALIZATION_SLIST_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// slist.hpp
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // size_t
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#ifdef BOOST_HAS_SLIST
+#include BOOST_SLIST_HEADER
+
+#include <Serialization/collections_save_imp.hpp>
+#include <Serialization/collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+#include <Serialization/nvp.hpp>
+
+namespace boost { 
+namespace serialization {
+
+template<class Archive, class U, class Allocator>
+inline void save(
+    Archive & ar,
+    const BOOST_STD_EXTENSION_NAMESPACE::slist<U, Allocator> &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::save_collection<
+        Archive,
+        BOOST_STD_EXTENSION_NAMESPACE::slist<U, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class U, class Allocator>
+inline void load(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::slist<U, Allocator> &t,
+    const unsigned int file_version
+){
+    // retrieve number of elements
+    t.clear();
+    // retrieve number of elements
+    collection_size_type count;
+    ar >> BOOST_SERIALIZATION_NVP(count);
+    if(collection_size_type(0) == count)
+        return;
+    item_version_type item_version(0);
+    const boost::archive::library_version_type library_version(
+        ar.get_library_version()
+    );
+    if(boost::archive::library_version_type(3) < library_version){
+        ar >> BOOST_SERIALIZATION_NVP(item_version);
+    }
+    boost::serialization::detail::stack_construct<Archive, U> u(ar, item_version);
+    ar >> boost::serialization::make_nvp("item", u.reference());
+    t.push_front(u.reference());
+    BOOST_DEDUCED_TYPENAME BOOST_STD_EXTENSION_NAMESPACE::slist<U, Allocator>::iterator last;
+    last = t.begin();
+    while(--count > 0){
+        boost::serialization::detail::stack_construct<Archive, U> 
+            u(ar, file_version);
+        ar >> boost::serialization::make_nvp("item", u.reference());
+        last = t.insert_after(last, u.reference());
+        ar.reset_object_address(& (*last), & u.reference());
+    }
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class U, class Allocator>
+inline void serialize(
+    Archive & ar,
+    BOOST_STD_EXTENSION_NAMESPACE::slist<U, Allocator> &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // serialization
+} // namespace boost
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(BOOST_STD_EXTENSION_NAMESPACE::slist)
+
+#endif  // BOOST_HAS_SLIST
+#endif  // BOOST_SERIALIZATION_SLIST_HPP
diff --git a/SRC/Serialization/smart_cast.hpp b/SRC/Serialization/smart_cast.hpp
new file mode 100755
index 0000000..f184cb3
--- /dev/null
+++ b/SRC/Serialization/smart_cast.hpp
@@ -0,0 +1,301 @@
+#ifndef BOOST_SERIALIZATION_SMART_CAST_HPP
+#define BOOST_SERIALIZATION_SMART_CAST_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// smart_cast.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/serialization for updates, documentation, and revision history.
+
+// casting of pointers and references.  
+
+// In casting between different C++ classes, there are a number of
+// rules that have to be kept in mind in deciding whether to use
+// static_cast or dynamic_cast.  
+
+// a) dynamic casting can only be applied when one of the types is polymorphic
+// Otherwise static_cast must be used.
+// b) only dynamic casting can do runtime error checking
+// use of static_cast is generally un checked even when compiled for debug
+// c) static_cast would be considered faster than dynamic_cast.
+
+// If casting is applied to a template parameter, there is no apriori way
+// to know which of the two casting methods will be permitted or convenient.
+
+// smart_cast uses C++ type_traits, and program debug mode to select the
+// most convenient cast to use.
+
+#include <exception>
+#include <typeinfo>
+#include <cstddef> // NULL
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/type_traits/is_polymorphic.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/is_reference.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
+#include <boost/mpl/identity.hpp>
+
+namespace boost {
+namespace serialization {
+namespace smart_cast_impl {
+
+    template<class T>
+    struct reference {
+
+        struct polymorphic {
+
+            struct linear {
+                template<class U>
+                 static T cast(U & u){
+                    return static_cast< T >(u);
+                }
+            };
+
+            struct cross {
+                 template<class U>
+                static T cast(U & u){
+                    return dynamic_cast< T >(u);
+                }
+            };
+
+            template<class U>
+            static T cast(U & u){
+                // if we're in debug mode
+                #if ! defined(NDEBUG)                               \
+                || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560) \
+                || defined(__MWERKS__)
+                    // do a checked dynamic cast
+                    return cross::cast(u);
+                #else
+                    // borland 5.51 chokes here so we can't use it
+                    // note: if remove_reference isn't function for these types
+                    // cross casting will be selected this will work but will
+                    // not be the most efficient method. This will conflict with
+                    // the original smart_cast motivation.
+                    typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                            BOOST_DEDUCED_TYPENAME mpl::and_<
+                                mpl::not_<is_base_and_derived<
+                                    BOOST_DEDUCED_TYPENAME remove_reference< T >::type,
+                                    U
+                                > >,
+                                mpl::not_<is_base_and_derived<
+                                    U,
+                                    BOOST_DEDUCED_TYPENAME remove_reference< T >::type
+                                > >
+                            >,
+                            // borland chokes w/o full qualification here
+                            mpl::identity<cross>,
+                            mpl::identity<linear>
+                    >::type typex;
+                    // typex works around gcc 2.95 issue
+                    return typex::cast(u);
+                #endif
+            }
+        };
+
+        struct non_polymorphic {
+            template<class U>
+             static T cast(U & u){
+                return static_cast< T >(u);
+            }
+        };
+        template<class U>
+        static T cast(U & u){
+            #if defined(__BORLANDC__)
+                return mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type::cast(u);
+            #else
+                typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type typex;
+                return typex::cast(u);
+            #endif
+        }
+    };
+
+    template<class T>
+    struct pointer {
+
+        struct polymorphic {
+            // unfortunately, this below fails to work for virtual base 
+            // classes.  need has_virtual_base to do this.
+            // Subject for further study
+            #if 0
+            struct linear {
+                template<class U>
+                 static T cast(U * u){
+                    return static_cast< T >(u);
+                }
+            };
+
+            struct cross {
+                template<class U>
+                static T cast(U * u){
+                    T tmp = dynamic_cast< T >(u);
+                    #ifndef NDEBUG
+                        if ( tmp == 0 ) throw std::bad_cast();
+                    #endif
+                    return tmp;
+                }
+            };
+
+            template<class U>
+            static T cast(U * u){
+                // if we're in debug mode
+                #if ! defined(NDEBUG) || defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
+                    // do a checked dynamic cast
+                    return cross::cast(u);
+                #else
+                    // borland 5.51 chokes here so we can't use it
+                    // note: if remove_pointer isn't function for these types
+                    // cross casting will be selected this will work but will
+                    // not be the most efficient method. This will conflict with
+                    // the original smart_cast motivation.
+                    typedef
+                        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                            BOOST_DEDUCED_TYPENAME mpl::and_<
+                                mpl::not_<is_base_and_derived<
+                                    BOOST_DEDUCED_TYPENAME remove_pointer< T >::type,
+                                    U
+                                > >,
+                                mpl::not_<is_base_and_derived<
+                                    U,
+                                    BOOST_DEDUCED_TYPENAME remove_pointer< T >::type
+                                > >
+                            >,
+                            // borland chokes w/o full qualification here
+                            mpl::identity<cross>,
+                            mpl::identity<linear>
+                        >::type typex;
+                    return typex::cast(u);
+                #endif
+            }
+            #else
+            template<class U>
+            static T cast(U * u){
+                T tmp = dynamic_cast< T >(u);
+                #ifndef NDEBUG
+                    if ( tmp == 0 ) throw std::bad_cast();
+                #endif
+                return tmp;
+            }
+            #endif
+        };
+
+        struct non_polymorphic {
+            template<class U>
+             static T cast(U * u){
+                return static_cast< T >(u);
+            }
+        };
+
+        template<class U>
+        static T cast(U * u){
+            #if defined(__BORLANDC__)
+                return mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type::cast(u);
+            #else
+                typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                    boost::is_polymorphic<U>,
+                    mpl::identity<polymorphic>,
+                    mpl::identity<non_polymorphic>
+                >::type typex;
+                return typex::cast(u);
+            #endif
+        }
+
+    };
+
+    template<class TPtr>
+    struct void_pointer {
+        template<class UPtr>
+        static TPtr cast(UPtr uptr){
+            return static_cast<TPtr>(uptr);
+        }
+    };
+
+    template<class T>
+    struct error {
+        // if we get here, its because we are using one argument in the
+        // cast on a system which doesn't support partial template 
+        // specialization
+        template<class U>
+        static T cast(U u){
+            BOOST_STATIC_ASSERT(sizeof(T)==0);
+            return * static_cast<T *>(NULL);
+        }
+    };
+
+} // smart_cast_impl
+
+// this implements:
+// smart_cast<Target *, Source *>(Source * s)
+// smart_cast<Target &, Source &>(s)
+// note that it will fail with
+// smart_cast<Target &>(s)
+template<class T, class U>
+T smart_cast(U u) {
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            BOOST_DEDUCED_TYPENAME mpl::or_<
+                boost::is_same<void *, U>,
+                boost::is_same<void *, T>,
+                boost::is_same<const void *, U>,
+                boost::is_same<const void *, T>
+            >,
+            mpl::identity<smart_cast_impl::void_pointer< T > >,
+        // else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_pointer<U>,
+            mpl::identity<smart_cast_impl::pointer< T > >,
+        // else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_reference<U>,
+            mpl::identity<smart_cast_impl::reference< T > >,
+        // else
+            mpl::identity<smart_cast_impl::error< T >
+        >
+        >
+        >
+        >::type typex;
+    return typex::cast(u);
+}
+
+// this implements:
+// smart_cast_reference<Target &>(Source & s)
+template<class T, class U>
+T smart_cast_reference(U & u) {
+    return smart_cast_impl::reference< T >::cast(u);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_SMART_CAST_HPP
diff --git a/SRC/Serialization/split_free.hpp b/SRC/Serialization/split_free.hpp
new file mode 100755
index 0000000..ed317b1
--- /dev/null
+++ b/SRC/Serialization/split_free.hpp
@@ -0,0 +1,93 @@
+#ifndef BOOST_SERIALIZATION_SPLIT_FREE_HPP
+#define BOOST_SERIALIZATION_SPLIT_FREE_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// split_free.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <Serialization/serialization.hpp>
+
+namespace boost {
+namespace archive {
+    namespace detail {
+        template<class Archive> class interface_oarchive;
+        template<class Archive> class interface_iarchive;
+    } // namespace detail
+} // namespace archive
+
+namespace serialization {
+
+//namespace detail {
+template<class Archive, class T>
+struct free_saver {
+    static void invoke(
+        Archive & ar, 
+        const  T & t, 
+        const unsigned int file_version
+    ){
+        // use function overload (version_type) to workaround
+        // two-phase lookup issue
+        const version_type v(file_version);
+        save(ar, t, v);
+    }
+};
+template<class Archive, class T>
+struct free_loader {
+    static void invoke(
+        Archive & ar, 
+        T & t, 
+        const unsigned int file_version
+    ){
+        // use function overload (version_type) to workaround
+        // two-phase lookup issue
+        const version_type v(file_version);
+        load(ar, t, v);
+    }
+};
+//} // namespace detail
+
+template<class Archive, class T>
+inline void split_free(
+    Archive & ar, 
+    T & t, 
+    const unsigned int file_version
+){
+    typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+        BOOST_DEDUCED_TYPENAME Archive::is_saving,
+        mpl::identity</* detail:: */ free_saver<Archive, T> >, 
+        mpl::identity</* detail:: */ free_loader<Archive, T> >
+    >::type typex;
+    typex::invoke(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#define BOOST_SERIALIZATION_SPLIT_FREE(T)       \
+namespace boost { namespace serialization {     \
+template<class Archive>                         \
+inline void serialize(                          \
+        Archive & ar,                               \
+        T & t,                                      \
+        const unsigned int file_version             \
+){                                              \
+        split_free(ar, t, file_version);            \
+}                                               \
+}}
+/**/
+
+#endif // BOOST_SERIALIZATION_SPLIT_FREE_HPP
diff --git a/SRC/Serialization/split_member.hpp b/SRC/Serialization/split_member.hpp
new file mode 100755
index 0000000..1b4b565
--- /dev/null
+++ b/SRC/Serialization/split_member.hpp
@@ -0,0 +1,86 @@
+#ifndef BOOST_SERIALIZATION_SPLIT_MEMBER_HPP
+#define BOOST_SERIALIZATION_SPLIT_MEMBER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// split_member.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+
+#include <Serialization/access.hpp>
+
+namespace boost {
+namespace archive {
+    namespace detail {
+        template<class Archive> class interface_oarchive;
+        template<class Archive> class interface_iarchive;
+    } // namespace detail
+} // namespace archive
+
+namespace serialization {
+namespace detail {
+
+    template<class Archive, class T>
+    struct member_saver {
+        static void invoke(
+            Archive & ar, 
+            const T & t,
+            const unsigned int file_version
+        ){
+            access::member_save(ar, t, file_version);
+        }
+    };
+
+    template<class Archive, class T>
+    struct member_loader {
+        static void invoke(
+            Archive & ar, 
+            T & t,
+            const unsigned int file_version
+        ){
+            access::member_load(ar, t, file_version);
+        }
+    };
+
+} // detail
+
+template<class Archive, class T>
+inline void split_member(
+    Archive & ar, T & t, const unsigned int file_version
+){
+    typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+        BOOST_DEDUCED_TYPENAME Archive::is_saving,
+        mpl::identity<detail::member_saver<Archive, T> >, 
+        mpl::identity<detail::member_loader<Archive, T> >
+    >::type typex;
+    typex::invoke(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+// split member function serialize funcition into save/load
+#define BOOST_SERIALIZATION_SPLIT_MEMBER()                       \
+template<class Archive>                                          \
+void serialize(                                                  \
+    Archive &ar,                                                 \
+    const unsigned int file_version                              \
+){                                                               \
+    boost::serialization::split_member(ar, *this, file_version); \
+}                                                                \
+/**/
+
+#endif // BOOST_SERIALIZATION_SPLIT_MEMBER_HPP
diff --git a/SRC/Serialization/src/archive_exception.cpp b/SRC/Serialization/src/archive_exception.cpp
new file mode 100755
index 0000000..270a3f7
--- /dev/null
+++ b/SRC/Serialization/src/archive_exception.cpp
@@ -0,0 +1,114 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// archive_exception.cpp:
+
+// (C) Copyright 2009 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <exception>
+#include <boost/assert.hpp>
+#include <string>
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/archive_exception.hpp>
+
+namespace boost {
+namespace archive {
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+archive_exception::archive_exception(
+    exception_code c, 
+    const char * e1,
+    const char * e2
+) : 
+    code(c)
+{
+    m_msg = "programming error";
+    switch(code){
+    case no_exception:
+        m_msg = "uninitialized exception";
+        break;
+    case unregistered_class:
+        m_msg = "unregistered class";
+        if(NULL != e1){
+            m_msg += " - ";
+            m_msg += e1;
+        }    
+        break;
+    case invalid_signature:
+        m_msg = "invalid signature";
+        break;
+    case unsupported_version:
+        m_msg = "unsupported version";
+        break;
+    case pointer_conflict:
+        m_msg = "pointer conflict";
+        break;
+    case incompatible_native_format:
+        m_msg = "incompatible native format";
+        if(NULL != e1){
+            m_msg += " - ";
+            m_msg += e1;
+        }    
+        break;
+    case array_size_too_short:
+        m_msg = "array size too short";
+        break;
+    case input_stream_error:
+        m_msg = "input stream error";
+        break;
+    case invalid_class_name:
+        m_msg = "class name too long";
+        break;
+    case unregistered_cast:
+        m_msg = "unregistered void cast ";
+        m_msg += (NULL != e1) ? e1 : "?";
+        m_msg += "<-";
+        m_msg += (NULL != e2) ? e2 : "?";
+        break;
+    case unsupported_class_version:
+        m_msg = "class version ";
+        m_msg += (NULL != e1) ? e1 : "<unknown class>";
+        break;
+    case other_exception:
+        // if get here - it indicates a derived exception 
+        // was sliced by passing by value in catch
+        m_msg = "unknown derived exception";
+        break;
+    case multiple_code_instantiation:
+        m_msg = "code instantiated in more than one module";
+        if(NULL != e1){
+            m_msg += " - ";
+            m_msg += e1;
+        }    
+        break;
+    case output_stream_error:
+        m_msg = "output stream error";
+        break;
+    default:
+        BOOST_ASSERT(false);
+        break;
+    }
+}
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+archive_exception::~archive_exception() throw () {}
+
+BOOST_ARCHIVE_DECL(const char *)
+archive_exception::what( ) const throw()
+{
+    return m_msg.c_str();
+}
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+archive_exception::archive_exception() : 
+        code(no_exception)
+{}
+
+} // archive
+} // boost
diff --git a/SRC/Serialization/src/basic_archive.cpp b/SRC/Serialization/src/basic_archive.cpp
new file mode 100755
index 0000000..d67d985
--- /dev/null
+++ b/SRC/Serialization/src/basic_archive.cpp
@@ -0,0 +1,80 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_archive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+//////////////////////////////////////////////////////////////////////
+//
+//  objects are stored as
+//
+//      class_id*   // -1 for a null pointer
+//      if a new class id
+//      [
+//          exported key - class name*
+//          tracking level - always/never
+//          class version
+//      ]
+//
+//      if tracking
+//      [
+//          object_id
+//      ]
+//          
+//      [   // if a new object id
+//          data...
+//      ]
+//
+//  * required only for pointers - optional for objects
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/basic_archive.hpp>
+
+namespace boost {
+namespace archive {
+
+///////////////////////////////////////////////////////////////////////
+// constants used in archive signature
+//This should never ever change. note that is not an std::string
+// string.
+BOOST_ARCHIVE_DECL(const char *) 
+BOOST_ARCHIVE_SIGNATURE(){
+    return "serialization::archive";
+}
+
+// this should change if the capabilities are added to the library
+// such that archives can be created which can't be read by previous
+// versions of this library
+// 1 - initial version
+// 2 - made address tracking optional
+// 3 - numerous changes - can't guarentee compatibility with previous versions
+// 4 - Boost 1.34
+//     added item_version to properly support versioning for collections 
+// 5 - Boost 1.36
+//     changed serialization of collections: adding version even for primitive
+//     types caused backwards compatibility breaking change in 1.35
+// 6 - Boost 1.41 17 Nov 2009
+//     serializing collection sizes as std::size_t
+// 7   Boost 1.42 2 Feb 2010
+//     error - changed binary version to 16 bits w/o changing library version #
+//     That is - binary archives are recorded with #6 even though they are
+//     different from the previous versions.  This means that binary archives
+//     created with versions 1.42 and 1.43 will have to be fixed with a special
+//     program which fixes the library version # in the header
+//     Boost 1.43 6 May 2010
+//     no change
+// 8 - Boost 1.44
+//     separated version_type into library_version_type and class_version_type
+//     changed version_type to be stored as 8 bits.
+
+BOOST_ARCHIVE_DECL(library_version_type)
+BOOST_ARCHIVE_VERSION(){
+    return library_version_type(9);
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_iarchive.cpp b/SRC/Serialization/src/basic_iarchive.cpp
new file mode 100755
index 0000000..c62bde4
--- /dev/null
+++ b/SRC/Serialization/src/basic_iarchive.cpp
@@ -0,0 +1,576 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_archive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp> // msvc 6.0 needs this to suppress warnings
+
+#include <boost/assert.hpp>
+#include <set>
+#include <list>
+#include <vector>
+#include <cstddef> // size_t, NULL
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ 
+    using ::size_t; 
+} // namespace std
+#endif
+
+#include <boost/integer_traits.hpp>
+#include <Serialization/state_saver.hpp>
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/tracking.hpp>
+
+#define BOOST_ARCHIVE_SOURCE
+// include this to prevent linker errors when the
+// same modules are marked export and import.
+#define BOOST_SERIALIZATION_SOURCE
+
+#include <Serialization/archive/archive_exception.hpp>
+
+#include <Serialization/archive/detail/decl.hpp>
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/archive/detail/basic_iserializer.hpp>
+#include <Serialization/archive/detail/basic_pointer_iserializer.hpp>
+#include <Serialization/archive/detail/basic_iarchive.hpp>
+
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+
+using namespace boost::serialization;
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+class basic_iarchive_impl {
+    friend class basic_iarchive;
+    library_version_type m_archive_library_version;
+    unsigned int m_flags;
+
+    //////////////////////////////////////////////////////////////////////
+    // information about each serialized object loaded
+    // indexed on object_id
+    struct aobject
+    {
+        void * address;
+        bool loaded_as_pointer;
+        class_id_type class_id;
+        aobject(
+            void *a,
+            class_id_type class_id_
+        ) :
+            address(a),
+            loaded_as_pointer(false),
+            class_id(class_id_)
+        {}
+        aobject() : 
+            address(NULL),
+            loaded_as_pointer(false),
+            class_id(-2) 
+        {}
+    };
+    typedef std::vector<aobject> object_id_vector_type;
+    object_id_vector_type object_id_vector;
+
+    //////////////////////////////////////////////////////////////////////
+    // used to implement the reset_object_address operation.
+    object_id_type moveable_objects_start;
+    object_id_type moveable_objects_end;
+    object_id_type moveable_objects_recent;
+
+    void reset_object_address(
+        const void * new_address, 
+        const void *old_address
+    );
+
+    //////////////////////////////////////////////////////////////////////
+    // used by load object to look up class id given basic_serializer
+    struct cobject_type
+    {
+        const basic_iserializer * m_bis;
+        const class_id_type m_class_id;
+        cobject_type(
+            std::size_t class_id,
+            const basic_iserializer & bis
+        ) : 
+            m_bis(& bis),
+            m_class_id(class_id)
+        {}
+        cobject_type(const cobject_type & rhs) : 
+            m_bis(rhs.m_bis),
+            m_class_id(rhs.m_class_id)
+        {}
+        // the following cannot be defined because of the const
+        // member.  This will generate a link error if an attempt
+        // is made to assign.  This should never be necessary
+        cobject_type & operator=(const cobject_type & rhs);
+        bool operator<(const cobject_type &rhs) const
+        {
+            return *m_bis < *(rhs.m_bis);
+        }
+    };
+    typedef std::set<cobject_type> cobject_info_set_type;
+    cobject_info_set_type cobject_info_set;
+
+    //////////////////////////////////////////////////////////////////////
+    // information about each serialized class indexed on class_id
+    class cobject_id 
+    {
+    public:
+        cobject_id & operator=(const cobject_id & rhs){
+            bis_ptr = rhs.bis_ptr;
+            bpis_ptr = rhs.bpis_ptr;
+            file_version = rhs.file_version;
+            tracking_level = rhs.tracking_level;
+            initialized = rhs.initialized;
+            return *this;
+        }
+        const basic_iserializer * bis_ptr;
+        const basic_pointer_iserializer * bpis_ptr;
+        version_type file_version;
+        tracking_type tracking_level;
+        bool initialized;
+
+        cobject_id(const basic_iserializer & bis_) :
+            bis_ptr(& bis_),
+            bpis_ptr(NULL),
+            file_version(0),
+            tracking_level(track_never),
+            initialized(false)
+        {}
+        cobject_id(const cobject_id &rhs): 
+            bis_ptr(rhs.bis_ptr),
+            bpis_ptr(rhs.bpis_ptr),
+            file_version(rhs.file_version),
+            tracking_level(rhs.tracking_level),
+            initialized(rhs.initialized)
+        {}
+    };
+    typedef std::vector<cobject_id> cobject_id_vector_type;
+    cobject_id_vector_type cobject_id_vector;
+
+    //////////////////////////////////////////////////////////////////////
+    // address of the most recent object serialized as a poiner
+    // whose data itself is now pending serialization
+    void * pending_object;
+    const basic_iserializer * pending_bis;
+    version_type pending_version;
+
+    basic_iarchive_impl(unsigned int flags) :
+        m_archive_library_version(BOOST_ARCHIVE_VERSION()),
+        m_flags(flags),
+        moveable_objects_start(0),
+        moveable_objects_end(0),
+        moveable_objects_recent(0),
+        pending_object(NULL),
+        pending_bis(NULL),
+        pending_version(0)
+    {}
+    ~basic_iarchive_impl(){}
+    void set_library_version(library_version_type archive_library_version){
+        m_archive_library_version = archive_library_version;
+    }
+    bool
+    track(
+        basic_iarchive & ar,
+        void * & t
+    );
+    void
+    load_preamble(
+        basic_iarchive & ar,
+        cobject_id & co
+    );
+    class_id_type register_type(
+        const basic_iserializer & bis
+    );
+
+    // redirect through virtual functions to load functions for this archive
+    template<class T>
+    void load(basic_iarchive & ar, T & t){
+        ar.vload(t);
+    }
+
+//public:
+    void
+    next_object_pointer(void * t){
+        pending_object = t;
+    }
+    void delete_created_pointers();
+    class_id_type register_type(
+        const basic_pointer_iserializer & bpis
+    );
+    void load_object(
+        basic_iarchive & ar,
+        void * t,
+        const basic_iserializer & bis
+    );
+    const basic_pointer_iserializer * load_pointer(
+        basic_iarchive & ar,
+        void * & t, 
+        const basic_pointer_iserializer * bpis,
+        const basic_pointer_iserializer * (*finder)(
+            const boost::serialization::extended_type_info & type
+        )
+
+    );
+};
+
+inline void 
+basic_iarchive_impl::reset_object_address(
+    const void * new_address, 
+    const void *old_address
+){
+    // this code handles a couple of situations.
+    // a) where reset_object_address is applied to an untracked object.
+    //    In such a case the call is really superfluous and its really an
+    //    an error.  But we don't have access to the types here so we can't
+    //    know that.  However, this code will effectively turn this situation
+    //    into a no-op and every thing will work fine - albeat with a small
+    //    execution time penalty.
+    // b) where the call to reset_object_address doesn't immediatly follow
+    //    the << operator to which it corresponds.  This would be a bad idea
+    //    but the code may work anyway.  Naturally, a bad practice on the part
+    //    of the programmer but we can't detect it - as above.  So maybe we
+    //    can save a few more people from themselves as above.
+    object_id_type i;
+    for(i = moveable_objects_recent; i < moveable_objects_end; ++i){
+        if(old_address == object_id_vector[i].address)
+            break;
+    }
+    for(; i < moveable_objects_end; ++i){
+
+        // calculate displacement from this level
+        // warning - pointer arithmetic on void * is in herently non-portable
+        // but expected to work on all platforms in current usage
+        if(object_id_vector[i].address > old_address){
+            std::size_t member_displacement
+                = reinterpret_cast<std::size_t>(object_id_vector[i].address) 
+                - reinterpret_cast<std::size_t>(old_address);
+            object_id_vector[i].address = reinterpret_cast<void *>(
+                reinterpret_cast<std::size_t>(new_address) + member_displacement
+            );
+        }
+        else{
+            std::size_t member_displacement
+                = reinterpret_cast<std::size_t>(old_address)
+                - reinterpret_cast<std::size_t>(object_id_vector[i].address); 
+            object_id_vector[i].address = reinterpret_cast<void *>(
+                reinterpret_cast<std::size_t>(new_address) - member_displacement
+            );
+       }
+    }
+}
+
+inline void 
+basic_iarchive_impl::delete_created_pointers()
+{
+    object_id_vector_type::iterator i;
+    for(
+        i = object_id_vector.begin();
+        i != object_id_vector.end(); 
+        ++i
+    ){
+        if(i->loaded_as_pointer){
+            // borland complains without this minor hack
+            const int j = i->class_id;
+            const cobject_id & co = cobject_id_vector[j];
+            //const cobject_id & co = cobject_id_vector[i->class_id];
+            // with the appropriate input serializer, 
+            // delete the indicated object
+            co.bis_ptr->destroy(i->address);
+        }
+    }
+}
+
+inline class_id_type
+basic_iarchive_impl::register_type(
+    const basic_iserializer & bis
+){
+    class_id_type cid(cobject_info_set.size());
+    cobject_type co(cid, bis);
+    std::pair<cobject_info_set_type::const_iterator, bool>
+        result = cobject_info_set.insert(co);
+
+    if(result.second){
+        cobject_id_vector.push_back(cobject_id(bis));
+        BOOST_ASSERT(cobject_info_set.size() == cobject_id_vector.size());
+    }
+    cid = result.first->m_class_id;
+    // borland complains without this minor hack
+    const int tid = cid;
+    cobject_id & coid = cobject_id_vector[tid];
+    coid.bpis_ptr = bis.get_bpis_ptr();
+    return cid;
+}
+
+void
+basic_iarchive_impl::load_preamble(
+    basic_iarchive & ar,
+    cobject_id & co
+){
+    if(! co.initialized){
+        if(co.bis_ptr->class_info()){
+            class_id_optional_type cid(class_id_type(0));
+            load(ar, cid);    // to be thrown away
+            load(ar, co.tracking_level);
+            load(ar, co.file_version);
+        }
+        else{
+            // override tracking with indicator from class information
+            co.tracking_level = co.bis_ptr->tracking(m_flags);
+            co.file_version = version_type(
+                co.bis_ptr->version()
+            );
+        }
+        co.initialized = true;
+    }
+}
+
+bool
+basic_iarchive_impl::track(
+    basic_iarchive & ar,
+    void * & t
+){
+    object_id_type oid;
+    load(ar, oid);
+
+    // if its a reference to a old object
+    if(object_id_type(object_id_vector.size()) > oid){
+        // we're done
+        t = object_id_vector[oid].address;
+        return false;
+    }
+    return true;
+}
+
+inline void
+basic_iarchive_impl::load_object(
+    basic_iarchive & ar,
+    void * t,
+    const basic_iserializer & bis
+){
+    // if its been serialized through a pointer and the preamble's been done
+    if(t == pending_object && & bis == pending_bis){
+        // read data
+        (bis.load_object_data)(ar, t, pending_version);
+        return;
+    }
+
+    const class_id_type cid = register_type(bis);
+    const int i = cid;
+    cobject_id & co = cobject_id_vector[i];
+
+    load_preamble(ar, co);
+
+    // save the current move stack position in case we want to truncate it
+    boost::serialization::state_saver<object_id_type> w(moveable_objects_start);
+
+    // note: extra line used to evade borland issue
+    const bool tracking = co.tracking_level;
+
+    object_id_type this_id;
+    moveable_objects_start =
+    this_id = object_id_type(object_id_vector.size());
+
+    // if we tracked this object when the archive was saved
+    if(tracking){ 
+        // if it was already read
+        if(!track(ar, t))
+            // we're done
+            return;
+        // add a new enty into the tracking list
+        object_id_vector.push_back(aobject(t, cid));
+        // and add an entry for this object
+        moveable_objects_end = object_id_type(object_id_vector.size());
+    }
+    // read data
+    (bis.load_object_data)(ar, t, co.file_version);
+    moveable_objects_recent = this_id;
+}
+
+inline const basic_pointer_iserializer *
+basic_iarchive_impl::load_pointer(
+    basic_iarchive &ar,
+    void * & t,
+    const basic_pointer_iserializer * bpis_ptr,
+    const basic_pointer_iserializer * (*finder)(
+        const boost::serialization::extended_type_info & type_
+    )
+
+){
+    class_id_type cid;
+    load(ar, cid);
+
+    if(NULL_POINTER_TAG == cid){
+        t = NULL;
+        return bpis_ptr;
+    }
+
+    // if its a new class type - i.e. never been registered
+    if(class_id_type(cobject_info_set.size()) <= cid){
+        // if its either abstract
+        if(NULL == bpis_ptr
+        // or polymorphic
+        || bpis_ptr->get_basic_serializer().is_polymorphic()){
+            // is must have been exported
+            char key[BOOST_SERIALIZATION_MAX_KEY_SIZE];
+            class_name_type class_name(key);
+            load(ar, class_name);
+            // if it has a class name
+            const serialization::extended_type_info *eti = NULL;
+            if(0 != key[0])
+                eti = serialization::extended_type_info::find(key);
+            if(NULL == eti)
+                boost::serialization::throw_exception(
+                    archive_exception(archive_exception::unregistered_class)
+                );
+            bpis_ptr = (*finder)(*eti);
+        }
+        BOOST_ASSERT(NULL != bpis_ptr);
+        class_id_type new_cid = register_type(bpis_ptr->get_basic_serializer());
+        int i = cid;
+        cobject_id_vector[i].bpis_ptr = bpis_ptr;
+        BOOST_ASSERT(new_cid == cid);
+    }
+    int i = cid;
+    cobject_id & co = cobject_id_vector[i];
+    bpis_ptr = co.bpis_ptr;
+
+    load_preamble(ar, co);
+
+    // extra line to evade borland issue
+    const bool tracking = co.tracking_level;
+    // if we're tracking and the pointer has already been read
+    if(tracking && ! track(ar, t))
+        // we're done
+        return bpis_ptr;
+
+    // save state
+    serialization::state_saver<object_id_type> w_start(moveable_objects_start);
+
+    if(! tracking){
+        bpis_ptr->load_object_ptr(ar, t, co.file_version);
+    }
+    else{
+        serialization::state_saver<void *> x(pending_object);
+        serialization::state_saver<const basic_iserializer *> y(pending_bis);
+        serialization::state_saver<version_type> z(pending_version);
+
+        pending_bis = & bpis_ptr->get_basic_serializer();
+        pending_version = co.file_version;
+
+        // predict next object id to be created
+        const unsigned int ui = object_id_vector.size();
+
+        serialization::state_saver<object_id_type> w_end(moveable_objects_end);
+
+        // because the following operation could move the items
+        // don't use co after this
+        // add to list of serialized objects so that we can properly handle
+        // cyclic strucures
+        object_id_vector.push_back(aobject(t, cid));
+
+        bpis_ptr->load_object_ptr(
+            ar, 
+            object_id_vector[ui].address, 
+            co.file_version
+        );
+        t = object_id_vector[ui].address;
+        object_id_vector[ui].loaded_as_pointer = true;
+        BOOST_ASSERT(NULL != t);
+    }
+
+    return bpis_ptr;
+}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+//////////////////////////////////////////////////////////////////////
+// implementation of basic_iarchive functions
+namespace boost {
+namespace archive {
+namespace detail {
+
+BOOST_ARCHIVE_DECL(void)
+basic_iarchive::next_object_pointer(void *t){
+    pimpl->next_object_pointer(t);
+}
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_iarchive::basic_iarchive(unsigned int flags) : 
+    pimpl(new basic_iarchive_impl(flags))
+{}
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+basic_iarchive::~basic_iarchive()
+{
+    delete pimpl;
+}
+
+BOOST_ARCHIVE_DECL(void)
+basic_iarchive::set_library_version(library_version_type archive_library_version){
+    pimpl->set_library_version(archive_library_version);
+}
+
+BOOST_ARCHIVE_DECL(void)
+basic_iarchive::reset_object_address(
+    const void * new_address, 
+    const void * old_address
+){
+    pimpl->reset_object_address(new_address, old_address);
+}
+
+BOOST_ARCHIVE_DECL(void)
+basic_iarchive::load_object(
+    void *t, 
+    const basic_iserializer & bis
+){
+    pimpl->load_object(*this, t, bis);
+}
+
+// load a pointer object
+BOOST_ARCHIVE_DECL(const basic_pointer_iserializer *)
+basic_iarchive::load_pointer(
+    void * &t, 
+    const basic_pointer_iserializer * bpis_ptr,
+    const basic_pointer_iserializer * (*finder)(
+        const boost::serialization::extended_type_info & type_
+    )
+
+){
+    return pimpl->load_pointer(*this, t, bpis_ptr, finder);
+}
+
+BOOST_ARCHIVE_DECL(void)
+basic_iarchive::register_basic_serializer(const basic_iserializer & bis){
+    pimpl->register_type(bis);
+}
+
+BOOST_ARCHIVE_DECL(void)
+basic_iarchive::delete_created_pointers()
+{
+    pimpl->delete_created_pointers();
+}
+
+BOOST_ARCHIVE_DECL(boost::archive::library_version_type) 
+basic_iarchive::get_library_version() const{
+    return pimpl->m_archive_library_version;
+}
+
+BOOST_ARCHIVE_DECL(unsigned int) 
+basic_iarchive::get_flags() const{
+    return pimpl->m_flags;
+}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_iserializer.cpp b/SRC/Serialization/src/basic_iserializer.cpp
new file mode 100755
index 0000000..69b51fb
--- /dev/null
+++ b/SRC/Serialization/src/basic_iserializer.cpp
@@ -0,0 +1,33 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_iserializer.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // NULL
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/basic_iserializer.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_iserializer::basic_iserializer(
+    const boost::serialization::extended_type_info & eti
+) :
+    basic_serializer(eti), 
+    m_bpis(NULL)
+{}
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_iserializer::~basic_iserializer(){}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_oarchive.cpp b/SRC/Serialization/src/basic_oarchive.cpp
new file mode 100755
index 0000000..c1aec70
--- /dev/null
+++ b/SRC/Serialization/src/basic_oarchive.cpp
@@ -0,0 +1,459 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_oarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp> // msvc 6.0 needs this for warning suppression
+
+#include <boost/assert.hpp>
+#include <set>
+#include <cstddef> // NULL
+
+#include <boost/limits.hpp>
+#include <Serialization/state_saver.hpp>
+#include <Serialization/throw_exception.hpp>
+
+// including this here to work around an ICC in intel 7.0
+// normally this would be part of basic_oarchive.hpp below.
+#define BOOST_ARCHIVE_SOURCE
+// include this to prevent linker errors when the
+// same modules are marked export and import.
+#define BOOST_SERIALIZATION_SOURCE
+
+#include <Serialization/archive/detail/decl.hpp>
+#include <Serialization/archive/basic_archive.hpp>
+#include <Serialization/archive/detail/basic_oserializer.hpp>
+#include <Serialization/archive/detail/basic_pointer_oserializer.hpp>
+#include <Serialization/archive/detail/basic_oarchive.hpp>
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/extended_type_info.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4251 4231 4660 4275)
+#endif
+
+using namespace boost::serialization;
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+class basic_oarchive_impl {
+    friend class basic_oarchive;
+    unsigned int m_flags;
+
+    //////////////////////////////////////////////////////////////////////
+    // information about each serialized object saved
+    // keyed on address, class_id
+    struct aobject
+    {
+        const void * address;
+        class_id_type class_id;
+        object_id_type object_id;
+
+        bool operator<(const aobject &rhs) const
+        {
+            BOOST_ASSERT(NULL != address);
+            BOOST_ASSERT(NULL != rhs.address);
+            if( address < rhs.address )
+                return true;
+            if( address > rhs.address )
+                return false;
+            return class_id < rhs.class_id;
+        }
+        aobject & operator=(const aobject & rhs)
+        {
+            address = rhs.address;
+            class_id = rhs.class_id;
+            object_id = rhs.object_id;
+            return *this;
+        }
+        aobject(
+            const void *a,
+            class_id_type class_id_,
+            object_id_type object_id_
+        ) :
+            address(a),
+            class_id(class_id_),
+            object_id(object_id_)
+        {}
+        aobject() : address(NULL){}
+    };
+    // keyed on class_id, address
+    typedef std::set<aobject> object_set_type;
+    object_set_type object_set;
+
+    //////////////////////////////////////////////////////////////////////
+    // information about each serialized class saved
+    // keyed on type_info
+    struct cobject_type
+    {
+        const basic_oserializer * m_bos_ptr;
+        const class_id_type m_class_id;
+        bool m_initialized;
+        cobject_type(
+            std::size_t class_id,
+            const basic_oserializer & bos
+        ) :
+            m_bos_ptr(& bos),
+            m_class_id(class_id),
+            m_initialized(false)
+        {}
+        cobject_type(const basic_oserializer & bos)
+            : m_bos_ptr(& bos)
+        {}
+        cobject_type(
+            const cobject_type & rhs
+        ) :
+            m_bos_ptr(rhs.m_bos_ptr),
+            m_class_id(rhs.m_class_id),
+            m_initialized(rhs.m_initialized)
+        {}
+        // the following cannot be defined because of the const
+        // member.  This will generate a link error if an attempt
+        // is made to assign.  This should never be necessary
+        // use this only for lookup argument 
+        cobject_type & operator=(const cobject_type &rhs);
+        bool operator<(const cobject_type &rhs) const {
+            return *m_bos_ptr < *(rhs.m_bos_ptr);
+        }
+    };
+    // keyed on type_info
+    typedef std::set<cobject_type> cobject_info_set_type;
+    cobject_info_set_type cobject_info_set;
+
+    // list of objects initially stored as pointers - used to detect errors
+    // keyed on object id
+    std::set<object_id_type> stored_pointers;
+
+    // address of the most recent object serialized as a poiner
+    // whose data itself is now pending serialization
+    const void * pending_object;
+    const basic_oserializer * pending_bos;
+
+    basic_oarchive_impl(unsigned int flags) :
+        m_flags(flags),
+        pending_object(NULL),
+        pending_bos(NULL)
+    {}
+
+    const cobject_type &
+    find(const basic_oserializer & bos);
+    const basic_oserializer *  
+    find(const serialization::extended_type_info &ti) const;
+
+//public:
+    const cobject_type &
+    register_type(const basic_oserializer & bos);
+    void save_object(
+        basic_oarchive & ar,
+        const void *t,
+        const basic_oserializer & bos
+    );
+    void save_pointer(
+        basic_oarchive & ar,
+        const void * t, 
+        const basic_pointer_oserializer * bpos
+    );
+};
+
+//////////////////////////////////////////////////////////////////////
+// basic_oarchive implementation functions
+
+// given a type_info - find its bos
+// return NULL if not found
+inline const basic_oserializer *
+basic_oarchive_impl::find(const serialization::extended_type_info & ti) const {
+    #ifdef BOOST_MSVC
+    #  pragma warning(push)
+    #  pragma warning(disable : 4511 4512)
+    #endif
+    class bosarg : 
+        public basic_oserializer
+    {
+        bool class_info() const {
+            BOOST_ASSERT(false); 
+            return false;
+        }
+        // returns true if objects should be tracked
+        bool tracking(const unsigned int) const {
+            BOOST_ASSERT(false);
+            return false;
+        }
+        // returns class version
+        version_type version() const {
+            BOOST_ASSERT(false);
+            return version_type(0);
+        }
+        // returns true if this class is polymorphic
+        bool is_polymorphic() const{
+            BOOST_ASSERT(false);
+            return false;
+        }
+        void save_object_data(      
+            basic_oarchive & /*ar*/, const void * /*x*/
+        ) const {
+            BOOST_ASSERT(false);
+        }
+    public:
+        bosarg(const serialization::extended_type_info & eti) :
+          boost::archive::detail::basic_oserializer(eti)
+        {}
+    };
+    #ifdef BOOST_MSVC
+    #pragma warning(pop)
+    #endif
+    bosarg bos(ti);
+    cobject_info_set_type::const_iterator cit 
+        = cobject_info_set.find(cobject_type(bos));
+    // it should already have been "registered" - see below
+    if(cit == cobject_info_set.end()){
+        // if an entry is not found in the table it is because a pointer
+        // of a derived class has been serialized through its base class
+        // but the derived class hasn't been "registered" 
+        return NULL;
+    }
+    // return pointer to the real class
+    return cit->m_bos_ptr;
+}
+
+inline const basic_oarchive_impl::cobject_type &
+basic_oarchive_impl::find(const basic_oserializer & bos)
+{
+    std::pair<cobject_info_set_type::iterator, bool> cresult = 
+        cobject_info_set.insert(cobject_type(cobject_info_set.size(), bos));
+    return *(cresult.first);
+}
+
+inline const basic_oarchive_impl::cobject_type &
+basic_oarchive_impl::register_type(
+    const basic_oserializer & bos
+){
+    cobject_type co(cobject_info_set.size(), bos);
+    std::pair<cobject_info_set_type::const_iterator, bool>
+        result = cobject_info_set.insert(co);
+    return *(result.first);
+}
+
+inline void
+basic_oarchive_impl::save_object(
+    basic_oarchive & ar,
+    const void *t,
+    const basic_oserializer & bos
+){
+    // if its been serialized through a pointer and the preamble's been done
+    if(t == pending_object && pending_bos == & bos){
+        // just save the object data
+        ar.end_preamble();
+        (bos.save_object_data)(ar, t);
+        return;
+    }
+
+    // get class information for this object
+    const cobject_type & co = register_type(bos);
+    if(bos.class_info()){
+        if( ! co.m_initialized){
+            ar.vsave(class_id_optional_type(co.m_class_id));
+            ar.vsave(tracking_type(bos.tracking(m_flags)));
+            ar.vsave(version_type(bos.version()));
+            (const_cast<cobject_type &>(co)).m_initialized = true;
+        }
+    }
+
+    // we're not tracking this type of object
+    if(! bos.tracking(m_flags)){
+        // just windup the preamble - no object id to write
+        ar.end_preamble();
+        // and save the data
+        (bos.save_object_data)(ar, t);
+        return;
+    }
+
+    // look for an existing object id
+    object_id_type oid(object_set.size());
+    // lookup to see if this object has already been written to the archive
+    basic_oarchive_impl::aobject ao(t, co.m_class_id, oid);
+    std::pair<basic_oarchive_impl::object_set_type::const_iterator, bool>
+        aresult = object_set.insert(ao);
+    oid = aresult.first->object_id;
+
+    // if its a new object
+    if(aresult.second){
+        // write out the object id
+        ar.vsave(oid);
+        ar.end_preamble();
+        // and data
+        (bos.save_object_data)(ar, t);
+        return;
+    }
+
+    // check that it wasn't originally stored through a pointer
+    if(stored_pointers.end() != stored_pointers.find(oid)){
+        // this has to be a user error.  loading such an archive
+        // would create duplicate objects
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::pointer_conflict)
+        );
+    }
+    // just save the object id
+    ar.vsave(object_reference_type(oid));
+    ar.end_preamble();
+    return;
+}
+
+// save a pointer to an object instance
+inline void
+basic_oarchive_impl::save_pointer(
+    basic_oarchive & ar,
+    const void * t, 
+    const basic_pointer_oserializer * bpos_ptr
+){
+    const basic_oserializer & bos = bpos_ptr->get_basic_serializer();
+    std::size_t original_count = cobject_info_set.size();
+    const cobject_type & co = register_type(bos);
+    if(! co.m_initialized){
+        ar.vsave(co.m_class_id);
+        // if its a previously unregistered class 
+        if((cobject_info_set.size() > original_count)){
+            if(bos.is_polymorphic()){
+                const serialization::extended_type_info *eti = & bos.get_eti();
+                const char * key = NULL;
+                if(NULL != eti)
+                    key = eti->get_key();
+                if(NULL != key){
+                    // the following is required by IBM C++ compiler which
+                    // makes a copy when passing a non-const to a const.  This
+                    // is permitted by the standard but rarely seen in practice
+                    const class_name_type cn(key);
+                    // write out the external class identifier
+                    ar.vsave(cn);
+                }
+                else
+                    // without an external class name
+                    // we won't be able to de-serialize it so bail now
+                    boost::serialization::throw_exception(
+                        archive_exception(archive_exception::unregistered_class)
+                    );
+            }
+        }
+        if(bos.class_info()){
+            ar.vsave(tracking_type(bos.tracking(m_flags)));
+            ar.vsave(version_type(bos.version()));
+        }
+        (const_cast<cobject_type &>(co)).m_initialized = true;
+    }
+    else{
+        ar.vsave(class_id_reference_type(co.m_class_id));
+    }
+
+    // if we're not tracking
+    if(! bos.tracking(m_flags)){
+        // just save the data itself
+        ar.end_preamble();
+        serialization::state_saver<const void *> x(pending_object);
+        serialization::state_saver<const basic_oserializer *> y(pending_bos);
+        pending_object = t;
+        pending_bos = & bpos_ptr->get_basic_serializer();
+        bpos_ptr->save_object_ptr(ar, t);
+        return;
+    }
+
+    object_id_type oid(object_set.size());
+    // lookup to see if this object has already been written to the archive
+    basic_oarchive_impl::aobject ao(t, co.m_class_id, oid);
+    std::pair<basic_oarchive_impl::object_set_type::const_iterator, bool>
+        aresult = object_set.insert(ao);
+    oid = aresult.first->object_id;
+    // if the saved object already exists
+    if(! aresult.second){
+        // append the object id to he preamble
+        ar.vsave(object_reference_type(oid));
+        // and windup.
+        ar.end_preamble();
+        return;
+    }
+
+    // append id of this object to preamble
+    ar.vsave(oid);
+    ar.end_preamble();
+
+    // and save the object itself
+    serialization::state_saver<const void *> x(pending_object);
+    serialization::state_saver<const basic_oserializer *> y(pending_bos);
+    pending_object = t;
+    pending_bos = & bpos_ptr->get_basic_serializer();
+    bpos_ptr->save_object_ptr(ar, t);
+    // add to the set of object initially stored through pointers
+    stored_pointers.insert(oid);
+}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+//////////////////////////////////////////////////////////////////////
+// implementation of basic_oarchive functions
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_oarchive::basic_oarchive(unsigned int flags)
+    : pimpl(new basic_oarchive_impl(flags))
+{}
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_oarchive::~basic_oarchive()
+{
+    delete pimpl;
+}
+
+BOOST_ARCHIVE_DECL(void) 
+basic_oarchive::save_object(
+    const void *x, 
+    const basic_oserializer & bos
+){
+    pimpl->save_object(*this, x, bos);
+}
+
+BOOST_ARCHIVE_DECL(void) 
+basic_oarchive::save_pointer(
+    const void * t, 
+    const basic_pointer_oserializer * bpos_ptr
+){
+    pimpl->save_pointer(*this, t, bpos_ptr);
+}
+
+BOOST_ARCHIVE_DECL(void) 
+basic_oarchive::register_basic_serializer(const basic_oserializer & bos){
+    pimpl->register_type(bos);
+}
+
+BOOST_ARCHIVE_DECL(library_version_type)
+basic_oarchive::get_library_version() const{
+    return BOOST_ARCHIVE_VERSION();
+}
+
+BOOST_ARCHIVE_DECL(unsigned int)
+basic_oarchive::get_flags() const{
+    return pimpl->m_flags;
+}
+
+BOOST_ARCHIVE_DECL(void) 
+basic_oarchive::end_preamble(){
+}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
diff --git a/SRC/Serialization/src/basic_oserializer.cpp b/SRC/Serialization/src/basic_oserializer.cpp
new file mode 100755
index 0000000..f84cd84
--- /dev/null
+++ b/SRC/Serialization/src/basic_oserializer.cpp
@@ -0,0 +1,33 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_oserializer.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // NULL
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/basic_oserializer.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_oserializer::basic_oserializer(
+        const boost::serialization::extended_type_info & eti
+) :
+    basic_serializer(eti), 
+    m_bpos(NULL)
+{}
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_oserializer::~basic_oserializer(){}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_pointer_iserializer.cpp b/SRC/Serialization/src/basic_pointer_iserializer.cpp
new file mode 100755
index 0000000..b63d44f
--- /dev/null
+++ b/SRC/Serialization/src/basic_pointer_iserializer.cpp
@@ -0,0 +1,30 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_pointer_iserializer.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/basic_pointer_iserializer.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_pointer_iserializer::basic_pointer_iserializer(
+    const boost::serialization::extended_type_info & eti
+) :
+    basic_serializer(eti)
+{}
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_pointer_iserializer::~basic_pointer_iserializer() {}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_pointer_oserializer.cpp b/SRC/Serialization/src/basic_pointer_oserializer.cpp
new file mode 100755
index 0000000..0c5c13b
--- /dev/null
+++ b/SRC/Serialization/src/basic_pointer_oserializer.cpp
@@ -0,0 +1,30 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_pointer_oserializer.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/basic_pointer_oserializer.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_pointer_oserializer::basic_pointer_oserializer(
+    const boost::serialization::extended_type_info & eti
+) :
+    basic_serializer(eti)
+{}
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY()) 
+basic_pointer_oserializer::~basic_pointer_oserializer() {}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_serializer_map.cpp b/SRC/Serialization/src/basic_serializer_map.cpp
new file mode 100755
index 0000000..f5977c7
--- /dev/null
+++ b/SRC/Serialization/src/basic_serializer_map.cpp
@@ -0,0 +1,111 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serializer_map.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <set>
+#include <utility>
+
+#define BOOST_ARCHIVE_SOURCE
+// include this to prevent linker errors when the
+// same modules are marked export and import.
+#define BOOST_SERIALIZATION_SOURCE
+
+#include <Serialization/archive/archive_exception.hpp>
+#include <Serialization/throw_exception.hpp>
+
+#include <Serialization/archive/detail/basic_serializer.hpp>
+#include <Serialization/archive/detail/basic_serializer_map.hpp>
+
+namespace boost {
+    namespace serialization {
+        class extended_type_info;
+    }
+namespace archive {
+namespace detail {
+
+bool  
+basic_serializer_map::type_info_pointer_compare::operator()(
+    const basic_serializer * lhs, const basic_serializer * rhs
+) const {
+    return *lhs < *rhs;
+}
+
+BOOST_ARCHIVE_DECL(bool) 
+basic_serializer_map::insert(const basic_serializer * bs){
+    // attempt to insert serializer into it's map
+    const std::pair<map_type::iterator, bool> result =
+        m_map.insert(bs);
+    // the following is commented out - rather than being just
+    // deleted as a reminder not to try this.
+
+    // At first it seemed like a good idea.  It enforced the
+    // idea that a type be exported from at most one code module
+    // (DLL or mainline).  This would enforce a "one definition rule" 
+    // across code modules. This seems a good idea to me.  
+    // But it seems that it's just too hard for many users to implement.
+
+    // Ideally, I would like to make this exception a warning -
+    // but there isn't anyway to do that.
+
+    // if this fails, it's because it's been instantiated
+    // in multiple modules - DLLS - a recipe for problems.
+    // So trap this here
+    // if(!result.second){
+    //     boost::serialization::throw_exception(
+    //         archive_exception(
+    //             archive_exception::multiple_code_instantiation,
+    //             bs->get_debug_info()
+    //         )
+    //     );
+    // }
+    return true;
+}
+
+BOOST_ARCHIVE_DECL(void) 
+basic_serializer_map::erase(const basic_serializer * bs){
+    map_type::iterator it = m_map.begin();
+    map_type::iterator it_end = m_map.end();
+
+    while(it != it_end){
+        // note item 9 from Effective STL !!! it++
+        if(*it == bs)
+            m_map.erase(it++);
+        else
+            it++;
+    }
+    // note: we can't do this since some of the eti records
+    // we're pointing to might be expired and the comparison
+    // won't work.  Leave this as a reminder not to "optimize" this.
+    //it = m_map.find(bs);
+    //assert(it != m_map.end());
+    //if(*it == bs)
+    //    m_map.erase(it);
+}
+BOOST_ARCHIVE_DECL(const basic_serializer *)
+basic_serializer_map::find(
+    const boost::serialization::extended_type_info & eti
+) const {
+    const basic_serializer_arg bs(eti);
+    map_type::const_iterator it;
+    it = m_map.find(& bs);
+    if(it == m_map.end()){
+        BOOST_ASSERT(false);
+        return 0;
+    }
+    return *it;
+}
+
+} // namespace detail
+} // namespace archive
+} // namespace boost
+
diff --git a/SRC/Serialization/src/basic_text_iprimitive.cpp b/SRC/Serialization/src/basic_text_iprimitive.cpp
new file mode 100755
index 0000000..a34de24
--- /dev/null
+++ b/SRC/Serialization/src/basic_text_iprimitive.cpp
@@ -0,0 +1,28 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_iprimitive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <istream>
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/impl/basic_text_iprimitive.ipp>
+
+namespace boost {
+namespace archive {
+
+// explicitly instantiate for this type of text stream
+template class basic_text_iprimitive<std::istream> ;
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_text_oprimitive.cpp b/SRC/Serialization/src/basic_text_oprimitive.cpp
new file mode 100755
index 0000000..49f2dcc
--- /dev/null
+++ b/SRC/Serialization/src/basic_text_oprimitive.cpp
@@ -0,0 +1,28 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_oprimitive.cpp:
+
+// (C) Copyright 2004 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <ostream>
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/auto_link_archive.hpp>
+#include <Serialization/archive/impl/basic_text_oprimitive.ipp>
+
+namespace boost {
+namespace archive {
+
+// explicitly instantiate for this type of text stream
+template class basic_text_oprimitive<std::ostream> ;
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/basic_text_wiprimitive.cpp b/SRC/Serialization/src/basic_text_wiprimitive.cpp
new file mode 100755
index 0000000..1d17873
--- /dev/null
+++ b/SRC/Serialization/src/basic_text_wiprimitive.cpp
@@ -0,0 +1,35 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_wiprimitive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <istream>
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/detail/auto_link_warchive.hpp>
+#include <Serialization/archive/impl/basic_text_iprimitive.ipp>
+
+namespace boost {
+namespace archive {
+
+template class basic_text_iprimitive<std::wistream> ;
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/src/basic_text_woprimitive.cpp b/SRC/Serialization/src/basic_text_woprimitive.cpp
new file mode 100755
index 0000000..1ec44a0
--- /dev/null
+++ b/SRC/Serialization/src/basic_text_woprimitive.cpp
@@ -0,0 +1,35 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_text_woprimitive.cpp:
+
+// (C) Copyright 2004 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <ostream>
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/detail/auto_link_warchive.hpp>
+#include <Serialization/archive/impl/basic_text_oprimitive.ipp>
+
+namespace boost {
+namespace archive {
+
+template class basic_text_oprimitive<std::wostream> ;
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/src/basic_xml_archive.cpp b/SRC/Serialization/src/basic_xml_archive.cpp
new file mode 100755
index 0000000..8298b39
--- /dev/null
+++ b/SRC/Serialization/src/basic_xml_archive.cpp
@@ -0,0 +1,51 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_archive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/basic_xml_archive.hpp>
+
+namespace boost {
+namespace archive {
+
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_OBJECT_ID(){
+    return "object_id";
+}
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_OBJECT_REFERENCE(){
+    return "object_id_reference";
+}
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_CLASS_ID(){
+    return "class_id";
+}
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_CLASS_ID_REFERENCE(){
+    return "class_id_reference";
+}
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_CLASS_NAME(){
+    return "class_name";
+}
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_TRACKING(){
+    return "tracking_level";
+}
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_VERSION(){
+    return "version";
+}
+BOOST_ARCHIVE_DECL(const char *)
+BOOST_ARCHIVE_XML_SIGNATURE(){
+    return "signature";
+}
+
+}// namespace archive
+}// namespace boost
diff --git a/SRC/Serialization/src/basic_xml_grammar.ipp b/SRC/Serialization/src/basic_xml_grammar.ipp
new file mode 100755
index 0000000..b6c1be3
--- /dev/null
+++ b/SRC/Serialization/src/basic_xml_grammar.ipp
@@ -0,0 +1,468 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// basic_xml_grammar.ipp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <istream>
+#include <algorithm>
+#include <boost/config.hpp> // BOOST_DEDUCED_TYPENAME
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+// spirit stuff
+#include <boost/spirit/include/classic_operators.hpp>
+#include <boost/spirit/include/classic_actions.hpp>
+#include <boost/spirit/include/classic_numerics.hpp>
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+// for head_iterator test
+//#include <boost/bind.hpp> 
+#include <boost/function.hpp>
+#include <Serialization/pfto.hpp>
+
+#include <boost/io/ios_state.hpp>
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/archive/impl/basic_xml_grammar.hpp>
+#include <Serialization/archive/xml_archive_exception.hpp>
+#include <Serialization/archive/basic_xml_archive.hpp>
+#include <Serialization/archive/iterators/xml_unescape.hpp>
+
+using namespace boost::spirit::classic;
+
+namespace boost {
+namespace archive {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// template code for basic_xml_grammar of both wchar_t and char types
+
+namespace xml { // anonymous
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+template<class T>
+struct assign_impl {
+    T & t;
+    void operator()(const T t_) const {
+        t = t_;
+    }
+    assign_impl(T &  t_)
+        : t(t_)
+    {}
+};
+
+template<>
+struct assign_impl<std::string> {
+    std::string & t;
+    void operator()(
+        std::string::const_iterator b, 
+        std::string::const_iterator e
+    ) const {
+        t.resize(0);
+        while(b != e){
+            t += * b;
+            ++b;
+        }
+    }
+    assign_impl<std::string> & operator=(
+        assign_impl<std::string> & rhs
+    );
+    assign_impl(std::string & t_)
+        : t(t_)
+    {}
+};
+
+#ifndef BOOST_NO_STD_WSTRING
+template<>
+struct assign_impl<std::wstring> {
+    std::wstring & t;
+    void operator()(
+        std::wstring::const_iterator b, 
+        std::wstring::const_iterator e
+    ) const {
+        t.resize(0);
+        while(b != e){
+            t += * b;
+            ++b;
+        }
+    }
+    assign_impl(std::wstring & t_)
+        : t(t_)
+    {}
+};
+#endif
+
+template<class T>
+assign_impl<T> assign_object(T &t){
+    return assign_impl<T>(t);
+} 
+
+struct assign_level {
+    tracking_type & tracking_level;
+    void operator()(const unsigned int tracking_level_) const {
+        tracking_level = (0 == tracking_level_) ? false : true;
+    }
+    assign_level(tracking_type &  tracking_level_)
+        : tracking_level(tracking_level_)
+    {}
+};
+
+template<class String, class Iterator>
+struct append_string {
+    String & contents;
+    void operator()(Iterator start, Iterator end) const {
+    #if 0
+        typedef boost::archive::iterators::xml_unescape<Iterator> translator;
+        contents.append(
+            translator(BOOST_MAKE_PFTO_WRAPPER(start)), 
+            translator(BOOST_MAKE_PFTO_WRAPPER(end))
+        );
+    #endif
+        contents.append(start, end);
+    }
+    append_string(String & contents_)
+        : contents(contents_)
+    {}
+};
+
+template<class String>
+struct append_char {
+    String & contents;
+    void operator()(const unsigned int char_value) const {
+        const BOOST_DEDUCED_TYPENAME String::value_type z = char_value;
+        contents += z;
+    }
+    append_char(String & contents_)
+        : contents(contents_)
+    {}
+};
+
+template<class String, unsigned int c>
+struct append_lit {
+    String & contents;
+    template<class X, class Y>
+    void operator()(const X & /*x*/, const Y & /*y*/) const {
+        const BOOST_DEDUCED_TYPENAME String::value_type z = c;
+        contents += z;
+    }
+    append_lit(String & contents_)
+        : contents(contents_)
+    {}
+};
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+} // namespace anonymous
+
+template<class CharType>
+bool basic_xml_grammar<CharType>::my_parse(
+    BOOST_DEDUCED_TYPENAME basic_xml_grammar<CharType>::IStream & is,
+    const rule_t & rule_,
+    CharType delimiter
+) const {
+    if(is.fail()){
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::input_stream_error)
+        );
+    }
+    
+    boost::io::ios_flags_saver ifs(is);
+    is >> std::noskipws;
+
+    std::basic_string<CharType> arg;
+    
+    CharType val;
+    do{
+        BOOST_DEDUCED_TYPENAME basic_xml_grammar<CharType>::IStream::int_type
+            result = is.get();
+        if(is.fail())
+            return false;
+        val = static_cast<CharType>(result);
+        arg += val;
+    }
+    while(val != delimiter);
+    
+    // read just one more character.  This will be the newline after the tag
+    // this is so that the next operation will return fail if the archive
+    // is terminated.  This will permit the archive to be used for debug
+    // and transaction data logging in the standard way.
+    
+    parse_info<BOOST_DEDUCED_TYPENAME std::basic_string<CharType>::iterator> 
+        result = boost::spirit::classic::parse(arg.begin(), arg.end(), rule_);
+    return result.hit;
+}
+
+template<class CharType>
+bool basic_xml_grammar<CharType>::parse_start_tag(
+    BOOST_DEDUCED_TYPENAME basic_xml_grammar<CharType>::IStream & is
+){
+    rv.class_name.resize(0);
+    return my_parse(is, STag);
+}
+
+template<class CharType>
+bool basic_xml_grammar<CharType>::parse_end_tag(IStream & is) const {
+    return my_parse(is, ETag);
+}
+
+template<class CharType>
+bool basic_xml_grammar<CharType>::parse_string(IStream & is, StringType & s){
+    rv.contents.resize(0);
+    bool result = my_parse(is, content, '<');
+    // note: unget caused a problem with dinkumware.  replace with
+ // is.unget();
+    // putback another dilimiter instead
+    is.putback('<');
+    if(result)
+        s = rv.contents;
+    return result;
+}
+
+template<class CharType>
+basic_xml_grammar<CharType>::basic_xml_grammar(){
+    init_chset();
+
+    S =
+        +(Sch)
+    ;
+
+    // refactoring to workaround template depth on darwin
+    NameHead = (Letter | '_' | ':');
+    NameTail = *NameChar ;
+    Name =
+      NameHead >> NameTail
+    ;
+
+    Eq =
+        !S >> '=' >> !S
+    ;
+
+    AttributeList = 
+        *(S >> Attribute)
+    ;
+    
+    STag =
+        !S
+        >> '<'
+        >> Name  [xml::assign_object(rv.object_name)]
+        >> AttributeList
+        >> !S
+        >> '>'
+    ;
+
+    ETag =
+        !S
+        >> "</"
+        >> Name [xml::assign_object(rv.object_name)]
+        >> !S 
+        >> '>'
+    ;
+
+    // refactoring to workaround template depth on darwin
+    CharDataChars = +(anychar_p - chset_p(L"&<"));
+    CharData =  
+        CharDataChars [
+            xml::append_string<
+                StringType, 
+                BOOST_DEDUCED_TYPENAME std::basic_string<CharType>::const_iterator
+            >(rv.contents)
+        ]
+    ;
+
+    // slight factoring works around ICE in msvc 6.0
+    CharRef1 = 
+        str_p(L"&#") >> uint_p [xml::append_char<StringType>(rv.contents)] >> L';'
+    ;
+    CharRef2 =
+        str_p(L"&#x") >> hex_p [xml::append_char<StringType>(rv.contents)] >> L';'
+    ;
+    CharRef = CharRef1 | CharRef2 ;
+
+    AmpRef = str_p(L"&")[xml::append_lit<StringType, L'&'>(rv.contents)];
+    LTRef = str_p(L"<")[xml::append_lit<StringType, L'<'>(rv.contents)];
+    GTRef = str_p(L">")[xml::append_lit<StringType, L'>'>(rv.contents)];
+    AposRef = str_p(L"'")[xml::append_lit<StringType, L'\''>(rv.contents)];
+    QuoteRef = str_p(L""")[xml::append_lit<StringType, L'"'>(rv.contents)];
+
+    Reference =
+        AmpRef
+        | LTRef
+        | GTRef
+        | AposRef
+        | QuoteRef
+        | CharRef
+    ;
+
+    content = 
+        L"<" // should be end_p
+        | +(Reference | CharData) >> L"<"
+    ;
+
+    ClassIDAttribute = 
+        str_p(BOOST_ARCHIVE_XML_CLASS_ID()) >> NameTail
+        >> Eq 
+        >> L'"'
+        >> int_p [xml::assign_object(rv.class_id)]
+        >> L'"'
+      ;
+
+    ObjectIDAttribute = (
+        str_p(BOOST_ARCHIVE_XML_OBJECT_ID()) 
+        | 
+        str_p(BOOST_ARCHIVE_XML_OBJECT_REFERENCE()) 
+        )
+        >> NameTail
+        >> Eq 
+        >> L'"'
+        >> L'_'
+        >> uint_p [xml::assign_object(rv.object_id)]
+        >> L'"'
+    ;
+        
+    AmpName = str_p(L"&")[xml::append_lit<StringType, L'&'>(rv.class_name)];
+    LTName = str_p(L"<")[xml::append_lit<StringType, L'<'>(rv.class_name)];
+    GTName = str_p(L">")[xml::append_lit<StringType, L'>'>(rv.class_name)];
+    ClassNameChar = 
+        AmpName
+        | LTName
+        | GTName
+        | (anychar_p - chset_p(L"\"")) [xml::append_char<StringType>(rv.class_name)]
+    ;
+    
+    ClassName =
+        * ClassNameChar
+    ;
+    
+    ClassNameAttribute = 
+        str_p(BOOST_ARCHIVE_XML_CLASS_NAME()) 
+        >> Eq 
+        >> L'"'
+        >> ClassName
+        >> L'"'
+    ;
+
+    TrackingAttribute = 
+        str_p(BOOST_ARCHIVE_XML_TRACKING())
+        >> Eq
+        >> L'"'
+        >> uint_p [xml::assign_level(rv.tracking_level)]
+        >> L'"'
+    ;
+
+    VersionAttribute = 
+        str_p(BOOST_ARCHIVE_XML_VERSION())
+        >> Eq
+        >> L'"'
+        >> uint_p [xml::assign_object(rv.version)]
+        >> L'"'
+    ;
+
+    UnusedAttribute = 
+        Name
+        >> Eq
+        >> L'"'
+        >> !CharData
+        >> L'"'
+    ;
+
+    Attribute =
+        ClassIDAttribute
+        | ObjectIDAttribute
+        | ClassNameAttribute
+        | TrackingAttribute
+        | VersionAttribute
+        | UnusedAttribute
+    ;
+
+    XMLDeclChars = *(anychar_p - chset_p(L"?>"));
+    XMLDecl =
+        !S
+        >> str_p(L"<?xml")
+        >> S
+        >> str_p(L"version")
+        >> Eq
+        >> str_p(L"\"1.0\"")
+        >> XMLDeclChars
+        >> !S
+        >> str_p(L"?>")
+    ;
+
+    DocTypeDeclChars = *(anychar_p - chset_p(L">"));
+    DocTypeDecl =
+        !S
+        >> str_p(L"<!DOCTYPE")
+        >> DocTypeDeclChars
+        >> L'>'
+    ;
+
+    SignatureAttribute = 
+        str_p(L"signature") 
+        >> Eq 
+        >> L'"'
+        >> Name [xml::assign_object(rv.class_name)]
+        >> L'"'
+    ;
+    
+    SerializationWrapper =
+        !S
+        >> str_p(L"<boost_serialization")
+        >> S
+        >> ( (SignatureAttribute >> S >> VersionAttribute)
+           | (VersionAttribute >> S >> SignatureAttribute)
+           )
+        >> !S
+        >> L'>'
+    ;
+}
+
+template<class CharType>
+void basic_xml_grammar<CharType>::init(IStream & is){
+    init_chset();
+    if(! my_parse(is, XMLDecl))
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    if(! my_parse(is, DocTypeDecl))
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    if(! my_parse(is, SerializationWrapper))
+        boost::serialization::throw_exception(
+            xml_archive_exception(xml_archive_exception::xml_archive_parsing_error)
+        );
+    if(! std::equal(rv.class_name.begin(), rv.class_name.end(), BOOST_ARCHIVE_SIGNATURE()))
+        boost::serialization::throw_exception(
+            archive_exception(archive_exception::invalid_signature)
+        );
+}
+
+template<class CharType>
+void basic_xml_grammar<CharType>::windup(IStream & is){
+    if(is.fail())
+        return;
+    // uh-oh - don't throw exception from code called by a destructor !
+    // so just ignore any failure.
+    my_parse(is, ETag);
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/binary_iarchive.cpp b/SRC/Serialization/src/binary_iarchive.cpp
new file mode 100755
index 0000000..9095113
--- /dev/null
+++ b/SRC/Serialization/src/binary_iarchive.cpp
@@ -0,0 +1,53 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_iarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <istream>
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/binary_iarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_binary_iprimitive.ipp>
+#include <Serialization/archive/impl/basic_binary_iarchive.ipp>
+
+namespace boost {
+namespace archive {
+
+// explicitly instantiate for this type of stream
+template class detail::archive_serializer_map<naked_binary_iarchive>;
+template class basic_binary_iprimitive<
+    naked_binary_iarchive,
+    std::istream::char_type, 
+    std::istream::traits_type
+>;
+template class basic_binary_iarchive<naked_binary_iarchive> ;
+template class binary_iarchive_impl<
+    naked_binary_iarchive, 
+    std::istream::char_type, 
+    std::istream::traits_type
+>;
+
+// explicitly instantiate for this type of stream
+template class detail::archive_serializer_map<binary_iarchive>;
+template class basic_binary_iprimitive<
+    binary_iarchive,
+    std::istream::char_type, 
+    std::istream::traits_type
+>;
+template class basic_binary_iarchive<binary_iarchive> ;
+template class binary_iarchive_impl<
+    binary_iarchive, 
+    std::istream::char_type, 
+    std::istream::traits_type
+>;
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/binary_oarchive.cpp b/SRC/Serialization/src/binary_oarchive.cpp
new file mode 100755
index 0000000..53dcff4
--- /dev/null
+++ b/SRC/Serialization/src/binary_oarchive.cpp
@@ -0,0 +1,39 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_oarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <ostream>
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/binary_oarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of binary stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_binary_oprimitive.ipp>
+#include <Serialization/archive/impl/basic_binary_oarchive.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<binary_oarchive>;
+template class basic_binary_oprimitive<
+    binary_oarchive, 
+    std::ostream::char_type, 
+    std::ostream::traits_type
+>;
+template class basic_binary_oarchive<binary_oarchive> ;
+template class binary_oarchive_impl<
+    binary_oarchive, 
+    std::ostream::char_type, 
+    std::ostream::traits_type
+>;
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/binary_wiarchive.cpp b/SRC/Serialization/src/binary_wiarchive.cpp
new file mode 100755
index 0000000..795d27f
--- /dev/null
+++ b/SRC/Serialization/src/binary_wiarchive.cpp
@@ -0,0 +1,60 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_wiarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/binary_wiarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of text stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_binary_iprimitive.ipp>
+#include <Serialization/archive/impl/basic_binary_iarchive.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<naked_binary_wiarchive>;
+template class basic_binary_iprimitive<
+    naked_binary_wiarchive,
+    wchar_t, 
+    std::char_traits<wchar_t> 
+>;
+template class basic_binary_iarchive<naked_binary_wiarchive> ;
+template class binary_iarchive_impl<
+    naked_binary_wiarchive, 
+    wchar_t, 
+    std::char_traits<wchar_t> 
+>;
+
+// explicitly instantiate for this type of text stream
+template class detail::archive_serializer_map<binary_wiarchive>;
+template class basic_binary_iprimitive<
+    binary_wiarchive,
+    wchar_t, 
+    std::char_traits<wchar_t> 
+>;
+template class basic_binary_iarchive<binary_wiarchive> ;
+template class binary_iarchive_impl<
+    binary_wiarchive, 
+    wchar_t, 
+    std::char_traits<wchar_t> 
+>;
+
+} // namespace archive
+} // namespace boost
+
+#endif  // BOOST_NO_STD_WSTREAMBUF
+
diff --git a/SRC/Serialization/src/binary_woarchive.cpp b/SRC/Serialization/src/binary_woarchive.cpp
new file mode 100755
index 0000000..0963b7a
--- /dev/null
+++ b/SRC/Serialization/src/binary_woarchive.cpp
@@ -0,0 +1,44 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// binary_woarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/binary_woarchive.hpp>
+
+// explicitly instantiate for this type of text stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_binary_oprimitive.ipp>
+#include <Serialization/archive/impl/basic_binary_oarchive.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<binary_woarchive>;
+template class basic_binary_oprimitive<
+    binary_woarchive, 
+    wchar_t, 
+    std::char_traits<wchar_t> 
+>;
+template class basic_binary_oarchive<binary_woarchive> ;
+template class binary_oarchive_impl<
+    binary_woarchive, 
+    wchar_t, 
+    std::char_traits<wchar_t> 
+>;
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/src/codecvt_null.cpp b/SRC/Serialization/src/codecvt_null.cpp
new file mode 100755
index 0000000..6ca9ab3
--- /dev/null
+++ b/SRC/Serialization/src/codecvt_null.cpp
@@ -0,0 +1,83 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// codecvt_null.cpp
+
+// Copyright (c) 2004 Robert Ramey, Indiana University (garcia at osl.iu.edu)
+// Andrew Lumsdaine, Indiana University (lums at osl.iu.edu). 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/codecvt_null.hpp>
+
+// codecvt implementation for passing wchar_t objects to char output
+// without any translation whatever.  Used to implement binary output
+// of wchar_t objects.
+
+namespace boost {
+namespace archive {
+
+BOOST_WARCHIVE_DECL(std::codecvt_base::result)
+codecvt_null<wchar_t>::do_out(
+    std::mbstate_t & /*state*/,
+    const wchar_t * first1, 
+    const wchar_t * last1,
+    const wchar_t * & next1,
+    char * first2, 
+    char * last2, 
+    char * & next2
+) const {
+    while(first1 != last1){
+        // Per std::22.2.1.5.2/2, we can store no more that
+        // last2-first2 characters. If we need to more encode
+        // next internal char type, return 'partial'.
+        if(static_cast<int>(sizeof(wchar_t)) > (last2 - first2)){
+            next1 = first1;
+            next2 = first2;
+            return std::codecvt_base::partial;
+        }
+        * reinterpret_cast<wchar_t *>(first2) = * first1++;
+        first2 += sizeof(wchar_t);
+
+    }
+    next1 = first1;
+    next2 = first2;
+    return std::codecvt_base::ok;
+}
+
+BOOST_WARCHIVE_DECL(std::codecvt_base::result)
+codecvt_null<wchar_t>::do_in(
+    std::mbstate_t & state,
+    const char * first1, 
+    const char * last1, 
+    const char * & next1,
+    wchar_t * first2,
+    wchar_t * last2,
+    wchar_t * & next2
+) const {
+    // Process input characters until we've run of them,
+    // or the number of remaining characters is not
+    // enough to construct another output character,
+    // or we've run out of place for output characters.
+    while(first2 != last2){
+        // Have we converted all input characters? 
+        // Return with 'ok', if so.
+        if (first1 == last1)
+             break;
+        // Do we have less input characters than needed
+        // for a single output character?        
+        if(static_cast<int>(sizeof(wchar_t)) > (last1 - first1)){
+            next1 = first1;
+            next2 = first2;
+            return std::codecvt_base::partial; 
+        }
+        *first2++ = * reinterpret_cast<const wchar_t *>(first1);
+        first1 += sizeof(wchar_t);
+    }
+    next1 = first1;
+    next2 = first2;
+    return std::codecvt_base::ok;
+}
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/extended_type_info.cpp b/SRC/Serialization/src/extended_type_info.cpp
new file mode 100755
index 0000000..374107b
--- /dev/null
+++ b/SRC/Serialization/src/extended_type_info.cpp
@@ -0,0 +1,188 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// extended_type_info.cpp: implementation for portable version of type_info
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <algorithm>
+#include <set>
+#include <utility>
+#include <boost/assert.hpp>
+#include <cstddef> // NULL
+
+#include <boost/config.hpp> // msvc needs this to suppress warning
+
+#include <cstring>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ using ::strcmp; }
+#endif
+
+#include <boost/detail/no_exceptions_support.hpp>
+#include <Serialization/singleton.hpp>
+#include <Serialization/force_include.hpp>
+
+#define BOOST_SERIALIZATION_SOURCE
+#include <Serialization/extended_type_info.hpp>
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+namespace boost { 
+namespace serialization {
+namespace detail {
+
+struct key_compare
+{
+    bool
+    operator()(
+        const extended_type_info * lhs, 
+        const extended_type_info * rhs
+    ) const {
+        // performance shortcut
+        if(lhs == rhs)
+            return false;
+        const char * l = lhs->get_key();
+        BOOST_ASSERT(NULL != l);
+        const char * r = rhs->get_key();
+        BOOST_ASSERT(NULL != r);
+        // performance shortcut
+        // shortcut to exploit string pooling
+        if(l == r)
+            return false;
+        // for exported types, use the string key so that
+        // multiple instances in different translation units
+        // can be matched up
+        return std::strcmp(l, r) < 0;
+    }
+};
+
+typedef std::multiset<const extended_type_info *, key_compare> ktmap;
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+class extended_type_info_arg : public extended_type_info
+{
+    virtual bool
+    is_less_than(const extended_type_info & /*rhs*/) const {
+        BOOST_ASSERT(false);
+        return false;
+    };
+    virtual bool
+    is_equal(const extended_type_info & /*rhs*/) const {
+        BOOST_ASSERT(false);
+        return false;
+    };
+    virtual const char * get_debug_info() const {
+        return get_key();
+    }
+    virtual void * construct(unsigned int /*count*/, ...) const{
+        BOOST_ASSERT(false);
+        return NULL;
+    }
+    virtual void destroy(void const * const /*p*/) const {
+        BOOST_ASSERT(false);
+    }
+public:
+    extended_type_info_arg(const char * key) :
+        extended_type_info(0, key)
+    {}
+
+    ~extended_type_info_arg(){
+    }
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+} // namespace detail
+
+BOOST_SERIALIZATION_DECL(void)  
+extended_type_info::key_register() const{
+    if(NULL == get_key())
+        return;
+    singleton<detail::ktmap>::get_mutable_instance().insert(this);
+}
+
+BOOST_SERIALIZATION_DECL(void)  
+extended_type_info::key_unregister() const{
+    if(NULL == get_key())
+        return;
+    if(! singleton<detail::ktmap>::is_destroyed()){
+        detail::ktmap & x = singleton<detail::ktmap>::get_mutable_instance();
+        detail::ktmap::iterator start = x.lower_bound(this);
+        detail::ktmap::iterator end = x.upper_bound(this);
+        // remove entry in map which corresponds to this type
+        for(;start != end; ++start){
+            if(this == *start){
+                x.erase(start);
+                break;
+            }
+        }
+    }
+}
+
+BOOST_SERIALIZATION_DECL(const extended_type_info *) 
+extended_type_info::find(const char *key) {
+    BOOST_ASSERT(NULL != key);
+    const detail::ktmap & k = singleton<detail::ktmap>::get_const_instance();
+    const detail::extended_type_info_arg eti_key(key);
+    const detail::ktmap::const_iterator it = k.find(& eti_key);
+    if(k.end() == it)
+        return NULL;
+    return *(it);
+}
+
+BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
+extended_type_info::extended_type_info(
+    const unsigned int type_info_key,
+    const char * key
+) :
+    m_type_info_key(type_info_key),
+    m_key(key)
+{
+}
+
+BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) 
+extended_type_info::~extended_type_info(){
+}
+
+BOOST_SERIALIZATION_DECL(bool)  
+extended_type_info::operator<(const extended_type_info &rhs) const {
+    // short cut for a common cases
+    if(this == & rhs)
+        return false;
+    if(m_type_info_key == rhs.m_type_info_key){
+        return is_less_than(rhs);
+    }
+    if(m_type_info_key < rhs.m_type_info_key)
+        return true;
+    return false;
+}
+
+BOOST_SERIALIZATION_DECL(bool)
+extended_type_info::operator==(const extended_type_info &rhs) const {
+    // short cut for a common cases
+    if(this == & rhs)
+        return true;
+    if(m_type_info_key != rhs.m_type_info_key){
+        return false;
+    }
+    return is_equal(rhs);
+}
+
+} // namespace serialization
+} // namespace boost
diff --git a/SRC/Serialization/src/extended_type_info_no_rtti.cpp b/SRC/Serialization/src/extended_type_info_no_rtti.cpp
new file mode 100755
index 0000000..259be06
--- /dev/null
+++ b/SRC/Serialization/src/extended_type_info_no_rtti.cpp
@@ -0,0 +1,85 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// extended_type_info_no_rtti.cpp: specific implementation of type info
+// that is NOT based on typeid
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstring>
+#include <cstddef> // NULL
+#include <boost/assert.hpp>
+
+#include <boost/config.hpp>
+#if defined(BOOST_NO_STDC_NAMESPACE)
+namespace std{ using ::strcmp; }
+#endif
+
+#define BOOST_SERIALIZATION_SOURCE
+#include <Serialization/extended_type_info_no_rtti.hpp>
+
+#define EXTENDED_TYPE_INFO_NO_RTTI_KEY 2
+
+namespace boost { 
+namespace serialization { 
+namespace no_rtti_system { 
+
+BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())  
+extended_type_info_no_rtti_0::extended_type_info_no_rtti_0(
+    const char * key
+) :
+    extended_type_info(EXTENDED_TYPE_INFO_NO_RTTI_KEY, key)
+{}
+
+BOOST_SERIALIZATION_DECL(bool)
+extended_type_info_no_rtti_0::is_less_than(
+    const boost::serialization::extended_type_info &rhs) const 
+{
+    // shortcut for common case
+    if(this == & rhs)
+        return false;
+    const char * l = get_key();
+    const char * r = rhs.get_key();
+    // if this assertion is triggered, it could mean one of the following
+    // a) This class was never exported - make sure all calls which use
+    // this method of type id are in fact exported.
+    // b) This class was used (e.g. serialized through a pointer) before
+    // it was exported.  Make sure that classes which use this method
+    // of type id are NOT "automatically" registered by serializating 
+    // through a pointer to the to most derived class.  OR make sure
+    // that the BOOST_CLASS_EXPORT is included in every file
+    // which does this.
+    BOOST_ASSERT(NULL != l);
+    BOOST_ASSERT(NULL != r);
+    return std::strcmp(l, r) < 0;
+}
+
+BOOST_SERIALIZATION_DECL(bool)
+extended_type_info_no_rtti_0::is_equal(
+    const boost::serialization::extended_type_info &rhs) const 
+{
+    // shortcut for common case
+    if(this == & rhs)
+        return true;
+    // null keys don't match with anything
+    const char * l = get_key();
+    BOOST_ASSERT(NULL != l);
+    if(NULL == l)
+        return false;
+    const char * r = rhs.get_key();
+    BOOST_ASSERT(NULL != r);
+    if(NULL == r)
+        return false;
+    return 0 == std::strcmp(l, r);
+}
+
+BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())  
+extended_type_info_no_rtti_0::~extended_type_info_no_rtti_0()
+{}
+
+} // namespece detail
+} // namespace serialization
+} // namespace boost
diff --git a/SRC/Serialization/src/extended_type_info_typeid.cpp b/SRC/Serialization/src/extended_type_info_typeid.cpp
new file mode 100755
index 0000000..6cd311b
--- /dev/null
+++ b/SRC/Serialization/src/extended_type_info_typeid.cpp
@@ -0,0 +1,161 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// extended_type_info_typeid.cpp: specific implementation of type info
+// that is based on typeid
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <algorithm>
+#include <set>
+#include <boost/assert.hpp>
+#include <typeinfo>
+#include <cstddef> // NULL
+
+#include <boost/detail/no_exceptions_support.hpp>
+
+#include <Serialization/singleton.hpp>
+
+#define BOOST_SERIALIZATION_SOURCE
+#include <Serialization/extended_type_info_typeid.hpp>
+
+namespace boost { 
+namespace serialization { 
+namespace typeid_system {
+
+#define EXTENDED_TYPE_INFO_TYPE_KEY 1
+
+struct type_compare
+{
+    bool
+    operator()(
+        const extended_type_info_typeid_0 * lhs,
+        const extended_type_info_typeid_0 * rhs
+    ) const {
+        return lhs->is_less_than(*rhs);
+    }
+};
+
+typedef std::multiset<
+    const extended_type_info_typeid_0 *,
+    type_compare
+> tkmap;
+    
+BOOST_SERIALIZATION_DECL(bool) 
+extended_type_info_typeid_0::is_less_than(
+    const boost::serialization::extended_type_info & rhs
+) const {
+    // shortcut for common case
+    if(this == & rhs)
+        return false;
+    return 0 != m_ti->before(
+        *(static_cast<const extended_type_info_typeid_0 &>(rhs).m_ti)
+    );
+}
+
+BOOST_SERIALIZATION_DECL(bool) 
+extended_type_info_typeid_0::is_equal(
+    const boost::serialization::extended_type_info & rhs
+) const {
+    return 
+        // note: std::type_info == operator returns an int !!!
+        // the following permits conversion to bool without a warning.
+        ! (
+        * m_ti 
+        != *(static_cast<const extended_type_info_typeid_0 &>(rhs).m_ti)
+        )
+    ;
+}
+
+BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
+extended_type_info_typeid_0::extended_type_info_typeid_0(
+    const char * key
+) :
+    extended_type_info(EXTENDED_TYPE_INFO_TYPE_KEY, key),
+    m_ti(NULL)
+{}
+
+BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY())
+extended_type_info_typeid_0::~extended_type_info_typeid_0()
+{}
+
+BOOST_SERIALIZATION_DECL(void) 
+extended_type_info_typeid_0::type_register(const std::type_info & ti){
+    m_ti = & ti;
+    singleton<tkmap>::get_mutable_instance().insert(this);
+}
+
+BOOST_SERIALIZATION_DECL(void) 
+extended_type_info_typeid_0::type_unregister()
+{
+    if(NULL != m_ti){
+        if(! singleton<tkmap>::is_destroyed()){
+            tkmap & x = singleton<tkmap>::get_mutable_instance();
+            tkmap::iterator start = x.lower_bound(this);
+            tkmap::iterator end = x.upper_bound(this);
+            BOOST_ASSERT(start != end);
+
+            // remove entry in map which corresponds to this type
+            do{
+            if(this == *start)
+                x.erase(start++);
+            else
+                ++start;
+            }while(start != end);
+        }
+    }
+    m_ti = NULL;
+}
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+// this derivation is used for creating search arguments
+class extended_type_info_typeid_arg : 
+    public extended_type_info_typeid_0
+{
+    virtual void * construct(unsigned int /*count*/, ...) const{
+        BOOST_ASSERT(false);
+        return NULL;
+    }
+    virtual void destroy(void const * const /*p*/) const {
+        BOOST_ASSERT(false);
+    }
+public:
+    extended_type_info_typeid_arg(const std::type_info & ti) :
+        extended_type_info_typeid_0(NULL)
+    { 
+        // note absense of self register and key as this is used only as
+        // search argument given a type_info reference and is not to 
+        // be added to the map.
+        m_ti = & ti;
+    }
+    ~extended_type_info_typeid_arg(){
+        m_ti = NULL;
+    }
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+BOOST_SERIALIZATION_DECL(const extended_type_info *)
+extended_type_info_typeid_0::get_extended_type_info(
+    const std::type_info & ti
+) const {
+    typeid_system::extended_type_info_typeid_arg etia(ti);
+    const tkmap & t = singleton<tkmap>::get_const_instance();
+    const tkmap::const_iterator it = t.find(& etia);
+    if(t.end() == it)
+        return NULL;
+    return *(it);
+}
+
+} // namespace detail
+} // namespace serialization
+} // namespace boost
diff --git a/SRC/Serialization/src/polymorphic_iarchive.cpp b/SRC/Serialization/src/polymorphic_iarchive.cpp
new file mode 100755
index 0000000..1c150ec
--- /dev/null
+++ b/SRC/Serialization/src/polymorphic_iarchive.cpp
@@ -0,0 +1,29 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_iarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/polymorphic_iarchive.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+template class archive_serializer_map<polymorphic_iarchive>;
+
+} // detail
+} // archive
+} // boost
diff --git a/SRC/Serialization/src/polymorphic_oarchive.cpp b/SRC/Serialization/src/polymorphic_oarchive.cpp
new file mode 100755
index 0000000..e88a447
--- /dev/null
+++ b/SRC/Serialization/src/polymorphic_oarchive.cpp
@@ -0,0 +1,29 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// polymorphic_oarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/polymorphic_oarchive.hpp>
+
+namespace boost {
+namespace archive {
+namespace detail {
+
+template class archive_serializer_map<polymorphic_oarchive>;
+
+} // detail
+} // archive
+} // boost
diff --git a/SRC/Serialization/src/shared_ptr_helper.cpp b/SRC/Serialization/src/shared_ptr_helper.cpp
new file mode 100755
index 0000000..628b475
--- /dev/null
+++ b/SRC/Serialization/src/shared_ptr_helper.cpp
@@ -0,0 +1,138 @@
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// shared_ptr_helper.hpp: serialization for boost shared pointern
+
+// (C) Copyright 2004-2009 Robert Ramey, Martin Ecker and Takatoshi Kondo
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <map>
+#include <list>
+#include <utility>
+#include <cstddef> // NULL
+
+#define BOOST_ARCHIVE_SOURCE
+// include this to prevent linker errors when the
+// same modules are marked export and import.
+#define BOOST_SERIALIZATION_SOURCE
+
+#include <Serialization/throw_exception.hpp>
+#include <Serialization/void_cast.hpp>
+#include <Serialization/extended_type_info.hpp>
+#include <Serialization/archive/shared_ptr_helper.hpp>
+#include <Serialization/archive/archive_exception.hpp>
+
+namespace boost {
+namespace archive{
+namespace detail {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// a common class for holding various types of shared pointers
+
+// returns pointer to object and an indicator whether this is a
+// new entry (true) or a previous one (false)
+BOOST_ARCHIVE_DECL(shared_ptr<void>)
+shared_ptr_helper::get_od(
+        const void * t,
+        const boost::serialization::extended_type_info * true_type, 
+        const boost::serialization::extended_type_info * this_type
+){
+    // get void pointer to the most derived type
+    // this uniquely identifies the object referred to
+    const void * od = void_downcast(
+        *true_type, 
+        *this_type, 
+        t
+    );
+    if(NULL == od)
+        boost::serialization::throw_exception(
+            archive_exception(
+                archive_exception::unregistered_cast,
+                true_type->get_debug_info(),
+                this_type->get_debug_info()
+            )
+        );
+
+    // make tracking array if necessary
+    if(NULL == m_pointers)
+        m_pointers = new collection_type;
+
+    //shared_ptr<const void> sp(od, null_deleter()); 
+    shared_ptr<const void> sp(od, null_deleter());
+    collection_type::iterator i = m_pointers->find(sp);
+
+    if(i == m_pointers->end()){
+        shared_ptr<void> np;
+        return np;
+    }
+    od = void_upcast(
+        *true_type, 
+        *this_type,
+        i->get()
+    );
+    if(NULL == od)
+        boost::serialization::throw_exception(
+            archive_exception(
+                archive_exception::unregistered_cast,
+                true_type->get_debug_info(),
+                this_type->get_debug_info()
+            )
+        );
+
+    return shared_ptr<void>(
+        const_pointer_cast<void>(*i), 
+        const_cast<void *>(od)
+    );
+}
+
+BOOST_ARCHIVE_DECL(void)
+shared_ptr_helper::append(const boost::shared_ptr<const void> &sp){
+    // make tracking array if necessary
+    if(NULL == m_pointers)
+        m_pointers = new collection_type;
+
+    collection_type::iterator i = m_pointers->find(sp);
+
+    if(i == m_pointers->end()){
+        std::pair<collection_type::iterator, bool> result;
+        result = m_pointers->insert(sp);
+        BOOST_ASSERT(result.second);
+    }
+}
+
+//  #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+BOOST_ARCHIVE_DECL(void)
+shared_ptr_helper::append(const boost_132::shared_ptr<const void> & t){
+    if(NULL == m_pointers_132)
+        m_pointers_132 = new std::list<boost_132::shared_ptr<const void> >;
+    m_pointers_132->push_back(t);
+}
+//  #endif
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+shared_ptr_helper::shared_ptr_helper() : 
+    m_pointers(NULL)
+    #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+        , m_pointers_132(NULL)
+    #endif
+{}
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+shared_ptr_helper::~shared_ptr_helper(){
+    if(NULL != m_pointers)
+        delete m_pointers;
+    #ifdef BOOST_SERIALIZATION_SHARED_PTR_132_HPP
+    if(NULL != m_pointers_132)
+        delete m_pointers_132;
+    #endif
+}
+
+} // namespace detail
+} // namespace serialization
+} // namespace boost
+
diff --git a/SRC/Serialization/src/stl_port.cpp b/SRC/Serialization/src/stl_port.cpp
new file mode 100755
index 0000000..3fb098c
--- /dev/null
+++ b/SRC/Serialization/src/stl_port.cpp
@@ -0,0 +1,43 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// stl_port.cpp: implementation of run-time casting of void pointers
+
+// (C) Copyright 2005 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+# pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+// this befuddles the msvc 6 compiler so we can't use it
+#if ! ((defined _MSC_VER) && (_MSC_VER <= 1300)) \
+&&  ! defined(__BORLANDC__)
+
+#include <boost/config.hpp>
+
+#if defined(__SGI_STL_PORT) && (__SGI_STL_PORT < 0x500)
+
+#include <Serialization/archive/codecvt_null.hpp>
+
+// explicit instantiation
+
+namespace std {
+
+template
+locale::locale(
+    const locale& __loc, boost::archive::codecvt_null<char> * __f
+);
+
+template
+locale::locale(
+    const locale& __loc, boost::archive::codecvt_null<wchar_t> * __f
+);
+
+} // namespace std
+
+#endif
+
+#endif
diff --git a/SRC/Serialization/src/text_iarchive.cpp b/SRC/Serialization/src/text_iarchive.cpp
new file mode 100755
index 0000000..52811a3
--- /dev/null
+++ b/SRC/Serialization/src/text_iarchive.cpp
@@ -0,0 +1,36 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_iarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/text_iarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of text stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_text_iarchive.ipp>
+#include <Serialization/archive/impl/text_iarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<naked_text_iarchive>;
+template class basic_text_iarchive<naked_text_iarchive> ;
+template class text_iarchive_impl<naked_text_iarchive> ;
+
+template class detail::archive_serializer_map<text_iarchive>;
+template class basic_text_iarchive<text_iarchive> ;
+template class text_iarchive_impl<text_iarchive> ;
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/text_oarchive.cpp b/SRC/Serialization/src/text_oarchive.cpp
new file mode 100755
index 0000000..5b554fe
--- /dev/null
+++ b/SRC/Serialization/src/text_oarchive.cpp
@@ -0,0 +1,33 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_oarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/text_oarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of text stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_text_oarchive.ipp>
+#include <Serialization/archive/impl/text_oarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+//template class basic_text_oprimitive<std::ostream> ;
+template class detail::archive_serializer_map<text_oarchive>;
+template class basic_text_oarchive<text_oarchive> ;
+template class text_oarchive_impl<text_oarchive> ;
+
+} // namespace serialization
+} // namespace boost
diff --git a/SRC/Serialization/src/text_wiarchive.cpp b/SRC/Serialization/src/text_wiarchive.cpp
new file mode 100755
index 0000000..1e0e38a
--- /dev/null
+++ b/SRC/Serialization/src/text_wiarchive.cpp
@@ -0,0 +1,41 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_wiarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/text_wiarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of text stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_text_iarchive.ipp>
+#include <Serialization/archive/impl/text_wiarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<naked_text_wiarchive>;
+template class basic_text_iarchive<naked_text_wiarchive> ;
+template class text_wiarchive_impl<naked_text_wiarchive> ;
+
+template class detail::archive_serializer_map<text_wiarchive>;
+template class basic_text_iarchive<text_wiarchive> ;
+template class text_wiarchive_impl<text_wiarchive> ;
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
+
diff --git a/SRC/Serialization/src/text_woarchive.cpp b/SRC/Serialization/src/text_woarchive.cpp
new file mode 100755
index 0000000..31f7ff3
--- /dev/null
+++ b/SRC/Serialization/src/text_woarchive.cpp
@@ -0,0 +1,35 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// text_woarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/text_woarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of text stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_text_oarchive.ipp>
+#include <Serialization/archive/impl/text_woarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<text_woarchive>;
+template class basic_text_oarchive<text_woarchive> ;
+template class text_woarchive_impl<text_woarchive> ;
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/src/utf8_codecvt_facet.cpp b/SRC/Serialization/src/utf8_codecvt_facet.cpp
new file mode 100755
index 0000000..eb3e6b5
--- /dev/null
+++ b/SRC/Serialization/src/utf8_codecvt_facet.cpp
@@ -0,0 +1,21 @@
+// Copyright Vladimir Prus 2004.
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt
+// or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+//#include <boost/config.hpp>
+// #ifdef BOOST_NO_STD_WSTREAMBUF
+// #error "wide char i/o not supported on this platform"
+// #else
+
+// #define BOOST_UTF8_BEGIN_NAMESPACE \
+//      namespace boost { namespace archive { namespace detail {
+// #define BOOST_UTF8_DECL
+// #define BOOST_UTF8_END_NAMESPACE }}}
+// #include "../../detail/utf8_codecvt_facet.cpp"
+// #undef BOOST_UTF8_END_NAMESPACE
+// #undef BOOST_UTF8_DECL
+// #undef BOOST_UTF8_BEGIN_NAMESPACE
+
+//#endif // BOOST_NO_STD_WSTREAMBUF
+
diff --git a/SRC/Serialization/src/void_cast.cpp b/SRC/Serialization/src/void_cast.cpp
new file mode 100755
index 0000000..d3e0376
--- /dev/null
+++ b/SRC/Serialization/src/void_cast.cpp
@@ -0,0 +1,360 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// void_cast.cpp: implementation of run-time casting of void pointers
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// <gennadiy.rozental at tfn.com>
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+# pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#include <boost/assert.hpp>
+#include <cstddef> // NULL
+#ifdef BOOST_SERIALIZATION_LOG
+#include <iostream>
+#endif
+
+// STL
+#include <set>
+#include <functional>
+#include <algorithm>
+#include <boost/assert.hpp>
+
+// BOOST
+#define BOOST_SERIALIZATION_SOURCE
+#include <Serialization/singleton.hpp>
+#include <Serialization/extended_type_info.hpp>
+#include <Serialization/void_cast.hpp>
+
+namespace boost { 
+namespace serialization {
+namespace void_cast_detail {
+
+// note that void_casters are keyed on value of
+// member extended type info records - NOT their
+// addresses.  This is necessary in order for the
+// void cast operations to work across dll and exe
+// module boundries.
+bool void_caster::operator<(const void_caster & rhs) const {
+    // include short cut to save time and eliminate
+    // problems when when base class aren't virtual
+    if(m_derived != rhs.m_derived){
+        if(*m_derived < *rhs.m_derived)
+            return true;
+        if(*rhs.m_derived < *m_derived)
+            return false;
+    }
+    // m_derived == rhs.m_derived
+    if(m_base != rhs.m_base)
+        return *m_base < *rhs.m_base;
+    else
+        return false;
+}
+
+struct void_caster_compare {
+    bool operator()(const void_caster * lhs, const void_caster * rhs) const {
+        return *lhs < *rhs;
+    }
+};
+
+typedef std::set<const void_caster *, void_caster_compare> set_type;
+typedef boost::serialization::singleton<set_type> void_caster_registry;
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+// implementation of shortcut void caster
+class void_caster_shortcut : public void_caster
+{
+    bool m_includes_virtual_base;
+
+    void const * 
+    vbc_upcast(
+        void const * const t
+    ) const;
+    void const *
+    vbc_downcast(
+        void const * const t
+    ) const;
+    virtual void const *
+    upcast(void const * const t) const{
+        if(m_includes_virtual_base)
+            return vbc_upcast(t);
+        return static_cast<const char *> ( t ) - m_difference;
+    }
+    virtual void const *
+    downcast(void const * const t) const{
+        if(m_includes_virtual_base)
+            return vbc_downcast(t);
+        return static_cast<const char *> ( t ) + m_difference;
+    }
+    virtual bool is_shortcut() const {
+        return true;
+    }
+    virtual bool has_virtual_base() const {
+        return m_includes_virtual_base;
+    }
+public:
+    void_caster_shortcut(
+        extended_type_info const * derived,
+        extended_type_info const * base,
+        std::ptrdiff_t difference,
+        bool includes_virtual_base,
+        void_caster const * const parent
+    ) :
+        void_caster(derived, base, difference, parent),
+        m_includes_virtual_base(includes_virtual_base)
+    {
+        recursive_register(includes_virtual_base);
+    }
+    virtual ~void_caster_shortcut(){
+        recursive_unregister();
+    }
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+void const * 
+void_caster_shortcut::vbc_downcast(
+    void const * const t
+) const {
+    // try to find a chain that gives us what we want
+    const void_cast_detail::set_type & s
+        = void_cast_detail::void_caster_registry::get_const_instance();
+    void_cast_detail::set_type::const_iterator it;
+    for(it = s.begin(); it != s.end(); ++it){
+        // if the current candidate casts to the desired target type
+        if ((*it)->m_derived == m_derived){
+            // and if it's not us
+            if ((*it)->m_base != m_base){
+                // try to cast from the candidate base to our base
+                const void * t_new;
+                t_new = void_downcast(*(*it)->m_base, *m_base, t);
+                // if we were successful
+                if(NULL != t_new){
+                    // recast to our derived
+                    const void_caster * vc = *it;
+                    return vc->downcast(t_new);
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+void const * 
+void_caster_shortcut::vbc_upcast(
+    void const * const t
+) const {
+    // try to find a chain that gives us what we want
+    const void_cast_detail::set_type & s
+        = void_cast_detail::void_caster_registry::get_const_instance();
+    void_cast_detail::set_type::const_iterator it;
+    for(it = s.begin(); it != s.end(); ++it){
+        // if the current candidate casts from the desired base type
+        if((*it)->m_base == m_base){
+            // and if it's not us
+            if ((*it)->m_derived != m_derived){
+                // try to cast from the candidate derived to our our derived
+                const void * t_new;
+                t_new = void_upcast(*m_derived, *(*it)->m_derived, t);
+                if(NULL != t_new)
+                    return (*it)->upcast(t_new);
+            }
+        }
+    }
+    return NULL;
+}
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4511 4512)
+#endif
+
+// just used as a search key
+class void_caster_argument : public void_caster
+{
+    virtual void const *
+    upcast(void const * const /*t*/) const {
+        BOOST_ASSERT(false);
+        return NULL;
+    }
+    virtual void const *
+    downcast( void const * const /*t*/) const {
+        BOOST_ASSERT(false);
+        return NULL;
+    }
+    virtual bool has_virtual_base() const {
+        BOOST_ASSERT(false);
+        return false;
+    }
+public:
+    void_caster_argument(
+        extended_type_info const * derived,
+        extended_type_info const * base
+    ) :
+        void_caster(derived, base)
+    {}
+    virtual ~void_caster_argument(){};
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(pop)
+#endif
+
+// implementation of void caster base class
+BOOST_SERIALIZATION_DECL(void)
+void_caster::recursive_register(bool includes_virtual_base) const {
+    void_cast_detail::set_type & s
+        = void_cast_detail::void_caster_registry::get_mutable_instance();
+
+    #ifdef BOOST_SERIALIZATION_LOG
+    std::clog << "recursive_register\n";
+    std::clog << m_derived->get_debug_info();
+    std::clog << "<-";
+    std::clog << m_base->get_debug_info();
+    std::clog << "\n";
+    #endif
+
+    std::pair<void_cast_detail::set_type::const_iterator, bool> result;
+    // comment this out for now.  
+    result = s.insert(this);
+    //assert(result.second);
+
+    // generate all implied void_casts.
+    void_cast_detail::set_type::const_iterator it;
+    for(it = s.begin(); it != s.end(); ++it){
+        if(* m_derived == * (*it)->m_base){
+            const void_caster_argument vca(
+                (*it)->m_derived, 
+                m_base
+            );
+            void_cast_detail::set_type::const_iterator i;
+            i = s.find(& vca);
+            if(i == s.end()){
+                new void_caster_shortcut(
+                    (*it)->m_derived, 
+                    m_base,
+                    m_difference + (*it)->m_difference,
+                    (*it)->has_virtual_base() || includes_virtual_base,
+                    this
+                );
+            }
+        }
+        if(* (*it)->m_derived == * m_base){
+            const void_caster_argument vca(
+                m_derived, 
+                (*it)->m_base
+            );
+            void_cast_detail::set_type::const_iterator i;
+            i = s.find(& vca);
+            if(i == s.end()){
+                new void_caster_shortcut(
+                    m_derived, 
+                    (*it)->m_base, 
+                    m_difference + (*it)->m_difference,
+                    (*it)->has_virtual_base() || includes_virtual_base,
+                    this
+                );
+            }
+        }
+    }
+}
+
+BOOST_SERIALIZATION_DECL(void)
+void_caster::recursive_unregister() const {
+    if(void_caster_registry::is_destroyed())
+        return;
+
+    #ifdef BOOST_SERIALIZATION_LOG
+    std::clog << "recursive_unregister\n";
+    std::clog << m_derived->get_debug_info();
+    std::clog << "<-";
+    std::clog << m_base->get_debug_info();
+    std::clog << "\n";
+    #endif
+
+    void_cast_detail::set_type & s 
+        = void_caster_registry::get_mutable_instance();
+
+    // delete all shortcuts which use this primitive
+    void_cast_detail::set_type::iterator it;
+    for(it = s.begin(); it != s.end();){
+        const void_caster * vc = *it;
+        if(vc == this){
+            s.erase(it++);
+        }
+        else
+        if(vc->m_parent == this){
+            s.erase(it);
+            delete vc;
+            it = s.begin();
+        }
+        else
+            it++;
+    }
+}
+
+} // namespace void_cast_detail
+
+// Given a void *, assume that it really points to an instance of one type
+// and alter it so that it would point to an instance of a related type.
+// Return the altered pointer. If there exists no sequence of casts that
+// can transform from_type to to_type, return a NULL.  
+BOOST_SERIALIZATION_DECL(void const *)  
+void_upcast(
+    extended_type_info const & derived,
+    extended_type_info const & base,
+    void const * const t
+){
+    // same types - trivial case
+    if (derived == base)
+        return t;
+
+    // check to see if base/derived pair is found in the registry
+    const void_cast_detail::set_type & s
+        = void_cast_detail::void_caster_registry::get_const_instance();
+    const void_cast_detail::void_caster_argument ca(& derived, & base);
+
+    void_cast_detail::set_type::const_iterator it;
+    it = s.find(& ca);
+    if (s.end() != it)
+        return (*it)->upcast(t);
+
+    return NULL;
+}
+
+BOOST_SERIALIZATION_DECL(void const *)  
+void_downcast(
+    extended_type_info const & derived,
+    extended_type_info const & base,
+    void const * const t
+){
+    // same types - trivial case
+    if (derived == base)
+        return t;
+
+    // check to see if base/derived pair is found in the registry
+    const void_cast_detail::set_type & s
+        = void_cast_detail::void_caster_registry::get_const_instance();
+    const void_cast_detail::void_caster_argument ca(& derived, & base);
+
+    void_cast_detail::set_type::const_iterator it;
+    it = s.find(&ca);
+    if (s.end() != it)
+        return(*it)->downcast(t);
+
+    return NULL;
+}
+
+} // namespace serialization
+} // namespace boost
diff --git a/SRC/Serialization/src/xml_archive_exception.cpp b/SRC/Serialization/src/xml_archive_exception.cpp
new file mode 100755
index 0000000..d014a6b
--- /dev/null
+++ b/SRC/Serialization/src/xml_archive_exception.cpp
@@ -0,0 +1,56 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_archive_exception.cpp:
+
+// (C) Copyright 2009 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+
+#include <exception>
+#include <boost/assert.hpp>
+#include <string>
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/xml_archive_exception.hpp>
+
+namespace boost {
+namespace archive {
+
+BOOST_ARCHIVE_DECL(BOOST_PP_EMPTY())
+xml_archive_exception::xml_archive_exception(
+        exception_code c, 
+        const char * e1,
+        const char * e2
+    ) : 
+        archive_exception(other_exception, e1, e2)
+    {
+        m_msg = "programming error";
+        switch(c){
+        case xml_archive_parsing_error:
+            m_msg = "unrecognized XML syntax";
+            break;
+        case xml_archive_tag_mismatch:
+            m_msg = "XML start/end tag mismatch";
+            if(NULL != e1){
+                m_msg += " - ";
+                m_msg += e1;
+            }    
+            break;
+        case xml_archive_tag_name_error:
+            m_msg = "Invalid XML tag name";
+            break;
+        default:
+            BOOST_ASSERT(false);
+            break;
+        }
+    }
+
+} // archive
+} // boost
diff --git a/SRC/Serialization/src/xml_grammar.cpp b/SRC/Serialization/src/xml_grammar.cpp
new file mode 100755
index 0000000..046a44e
--- /dev/null
+++ b/SRC/Serialization/src/xml_grammar.cpp
@@ -0,0 +1,73 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_grammar.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/impl/basic_xml_grammar.hpp>
+
+using namespace boost::spirit::classic;
+
+#include <boost/config.hpp>
+
+// fixup for borland
+// The following code will be put into Boost.Config in a later revision
+#if ! defined(__SGI_STL_PORT) \
+&& defined(BOOST_RWSTD_VER) && BOOST_RWSTD_VER<=0x020101
+#include <string>
+namespace std {
+    template<>
+    inline string & 
+    string::replace (
+        char * first1, 
+        char * last1,
+        const char * first2,
+        const char * last2
+    ){
+        replace(first1-begin(),last1-first1,first2,last2-first2,0,last2-first2);
+        return *this;
+    }
+} // namespace std
+#endif
+
+namespace boost {
+namespace archive {
+
+typedef basic_xml_grammar<char> xml_grammar;
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// specific definitions for char based XML
+
+template<>
+void xml_grammar::init_chset(){
+    Char = chset_t("\x9\xA\xD\x20-\x7f\x80\x81-\xFF"); 
+    Letter = chset_t("\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF");
+    Digit = chset_t("0-9");
+    Extender = chset_t('\xB7');
+    Sch = chset_t("\x20\x9\xD\xA");
+    NameChar = Letter | Digit | chset_p("._:-") | Extender ;
+}
+
+} // namespace archive
+} // namespace boost
+
+#include "basic_xml_grammar.ipp"
+
+namespace boost {
+namespace archive {
+
+// explicit instantiation of xml for 8 bit characters
+template class basic_xml_grammar<char>;
+
+} // namespace archive
+} // namespace boost
+
diff --git a/SRC/Serialization/src/xml_iarchive.cpp b/SRC/Serialization/src/xml_iarchive.cpp
new file mode 100755
index 0000000..ce312cb
--- /dev/null
+++ b/SRC/Serialization/src/xml_iarchive.cpp
@@ -0,0 +1,46 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_iarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_ARCHIVE_SOURCE
+
+// the following works around an issue between spirit 1.61 and borland.
+// it turns out the the certain spirit stuff must be defined before
+// certain parts of mpl.  including this here makes sure that happens
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#if BOOST_WORKAROUND(__BORLANDC__, <= 0x560 )
+#include <Serialization/archive/impl/basic_xml_grammar.hpp>
+#endif
+
+#include <Serialization/archive/xml_iarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of xml stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_xml_iarchive.ipp>
+#include <Serialization/archive/impl/xml_iarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<naked_xml_iarchive>;
+template class basic_xml_iarchive<naked_xml_iarchive> ;
+template class xml_iarchive_impl<naked_xml_iarchive> ;
+
+template class detail::archive_serializer_map<xml_iarchive>;
+template class basic_xml_iarchive<xml_iarchive> ;
+template class xml_iarchive_impl<xml_iarchive> ;
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/xml_oarchive.cpp b/SRC/Serialization/src/xml_oarchive.cpp
new file mode 100755
index 0000000..8c9a3d4
--- /dev/null
+++ b/SRC/Serialization/src/xml_oarchive.cpp
@@ -0,0 +1,32 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_oarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_ARCHIVE_SOURCE
+#include <Serialization/archive/xml_oarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of xml stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_xml_oarchive.ipp>
+#include <Serialization/archive/impl/xml_oarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<xml_oarchive>;
+template class basic_xml_oarchive<xml_oarchive> ;
+template class xml_oarchive_impl<xml_oarchive> ;
+
+} // namespace archive
+} // namespace boost
diff --git a/SRC/Serialization/src/xml_wgrammar.cpp b/SRC/Serialization/src/xml_wgrammar.cpp
new file mode 100755
index 0000000..b2404a9
--- /dev/null
+++ b/SRC/Serialization/src/xml_wgrammar.cpp
@@ -0,0 +1,157 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_wgrammar.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/impl/basic_xml_grammar.hpp>
+
+using namespace boost::spirit::classic;
+
+// fixup for RogueWave
+#include <boost/config.hpp>
+#if ! defined(__SGI_STL_PORT) \
+&& defined(BOOST_RWSTD_VER) && BOOST_RWSTD_VER<=0x020101
+#include <string>
+namespace std {
+    template<>
+    inline wstring & 
+    wstring::replace (
+        wchar_t * first1, 
+        wchar_t * last1,
+        const wchar_t * first2,
+        const wchar_t * last2
+    ){
+        replace(first1-begin(),last1-first1,first2,last2-first2,0,last2-first2);
+        return *this;
+    }
+} // namespace std
+#endif
+
+namespace boost {
+namespace archive {
+
+typedef basic_xml_grammar<wchar_t> xml_wgrammar;
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// specific definitions for wchar_t based XML
+
+template<>
+void xml_wgrammar::init_chset(){
+    Char = chset_t(
+        #if defined(__GNUC__) && defined(linux)
+            L"\x9\xA\xD\x20-\xD7FF\xE000-\xFFFD\x10000-\x10FFFF"
+        #else
+            L"\x9\xA\xD\x20-\xD7FF\xE000-\xFFFD"
+        #endif
+    );
+
+    Sch = chset_t(L"\x20\x9\xD\xA");
+
+    BaseChar = chset_t(
+        L"\x41-\x5A\x61-\x7A\xC0-\xD6\xD8-\xF6\xF8-\xFF\x100-\x131\x134-\x13E"
+        L"\x141-\x148\x14A-\x17E\x180-\x1C3\x1CD-\x1F0\x1F4-\x1F5\x1FA-\x217"
+        L"\x250-\x2A8\x2BB-\x2C1\x386\x388-\x38A\x38C\x38E-\x3A1\x3A3-\x3CE"
+        L"\x3D0-\x3D6\x3DA\x3DC\x3DE\x3E0\x3E2-\x3F3\x401-\x40C\x40E-\x44F"
+        L"\x451-\x45C\x45E-\x481\x490-\x4C4\x4C7-\x4C8\x4CB-\x4CC\x4D0-\x4EB"
+        L"\x4EE-\x4F5\x4F8-\x4F9\x531-\x556\x559\x561-\x586\x5D0-\x5EA"
+        L"\x5F0-\x5F2\x621-\x63A\x641-\x64A\x671-\x6B7\x6BA-\x6BE\x6C0-\x6CE"
+        L"\x6D0-\x6D3\x6D5\x6E5-\x6E6\x905-\x939\x93D\x958-\x961\x985-\x98C"
+        L"\x98F-\x990\x993-\x9A8\x9AA-\x9B0\x9B2\x9B6-\x9B9\x9DC-\x9DD"
+        L"\x9DF-\x9E1\x9F0-\x9F1\xA05-\xA0A\xA0F-\xA10\xA13-\xA28\xA2A-\xA30"
+        L"\xA32-\xA33\xA35-\xA36\xA38-\xA39\xA59-\xA5C\xA5E\xA72-\xA74"
+        L"\xA85-\xA8B\xA8D\xA8F-\xA91\xA93-\xAA8\xAAA-\xAB0\xAB2-\xAB3"
+        L"\xAB5-\xAB9\xABD\xAE0\xB05-\xB0C\xB0F-\xB10\xB13-\xB28\xB2A-\xB30"
+        L"\xB32-\xB33\xB36-\xB39\xB3D\xB5C-\xB5D\xB5F-\xB61\xB85-\xB8A"
+        L"\xB8E-\xB90\xB92-\xB95\xB99-\xB9A\xB9C\xB9E-\xB9F\xBA3-\xBA4"
+        L"\xBA8-\xBAA\xBAE-\xBB5\xBB7-\xBB9\xC05-\xC0C\xC0E-\xC10\xC12-\xC28"
+        L"\xC2A-\xC33\xC35-\xC39\xC60-\xC61\xC85-\xC8C\xC8E-\xC90\xC92-\xCA8"
+        L"\xCAA-\xCB3\xCB5-\xCB9\xCDE\xCE0-\xCE1\xD05-\xD0C\xD0E-\xD10"
+        L"\xD12-\xD28\xD2A-\xD39\xD60-\xD61\xE01-\xE2E\xE30\xE32-\xE33"
+        L"\xE40-\xE45\xE81-\xE82\xE84\xE87-\xE88\xE8A\xE8D\xE94-\xE97"
+        L"\xE99-\xE9F\xEA1-\xEA3\xEA5\xEA7\xEAA-\xEAB\xEAD-\xEAE\xEB0"
+        L"\xEB2-\xEB3\xEBD\xEC0-\xEC4\xF40-\xF47\xF49-\xF69\x10A0-\x10C5"
+        L"\x10D0-\x10F6\x1100\x1102-\x1103\x1105-\x1107\x1109\x110B-\x110C"
+        L"\x110E-\x1112\x113C\x113E\x1140\x114C\x114E\x1150\x1154-\x1155"
+        L"\x1159\x115F-\x1161\x1163\x1165\x1167\x1169\x116D-\x116E"
+        L"\x1172-\x1173\x1175\x119E\x11A8\x11AB\x11AE-\x11AF\x11B7-\x11B8"
+        L"\x11BA\x11BC-\x11C2\x11EB\x11F0\x11F9\x1E00-\x1E9B\x1EA0-\x1EF9"
+        L"\x1F00-\x1F15\x1F18-\x1F1D\x1F20-\x1F45\x1F48-\x1F4D\x1F50-\x1F57"
+        L"\x1F59\x1F5B\x1F5D\x1F5F-\x1F7D\x1F80-\x1FB4\x1FB6-\x1FBC\x1FBE"
+        L"\x1FC2-\x1FC4\x1FC6-\x1FCC\x1FD0-\x1FD3\x1FD6-\x1FDB\x1FE0-\x1FEC"
+        L"\x1FF2-\x1FF4\x1FF6-\x1FFC\x2126\x212A-\x212B\x212E\x2180-\x2182"
+        L"\x3041-\x3094\x30A1-\x30FA\x3105-\x312C\xAC00-\xD7A3"
+    );
+
+    Ideographic = chset_t(L"\x4E00-\x9FA5\x3007\x3021-\x3029");
+
+    Letter = BaseChar | Ideographic;
+
+    CombiningChar = chset_t(
+        L"\x0300-\x0345\x0360-\x0361\x0483-\x0486\x0591-\x05A1\x05A3-\x05B9"
+        L"\x05BB-\x05BD\x05BF\x05C1-\x05C2\x05C4\x064B-\x0652\x0670"
+        L"\x06D6-\x06DC\x06DD-\x06DF\x06E0-\x06E4\x06E7-\x06E8\x06EA-\x06ED"
+        L"\x0901-\x0903\x093C\x093E-\x094C\x094D\x0951-\x0954\x0962-\x0963"
+        L"\x0981-\x0983\x09BC\x09BE\x09BF\x09C0-\x09C4\x09C7-\x09C8"
+        L"\x09CB-\x09CD\x09D7\x09E2-\x09E3\x0A02\x0A3C\x0A3E\x0A3F"
+        L"\x0A40-\x0A42\x0A47-\x0A48\x0A4B-\x0A4D\x0A70-\x0A71\x0A81-\x0A83"
+        L"\x0ABC\x0ABE-\x0AC5\x0AC7-\x0AC9\x0ACB-\x0ACD\x0B01-\x0B03\x0B3C"
+        L"\x0B3E-\x0B43\x0B47-\x0B48\x0B4B-\x0B4D\x0B56-\x0B57\x0B82-\x0B83"
+        L"\x0BBE-\x0BC2\x0BC6-\x0BC8\x0BCA-\x0BCD\x0BD7\x0C01-\x0C03"
+        L"\x0C3E-\x0C44\x0C46-\x0C48\x0C4A-\x0C4D\x0C55-\x0C56\x0C82-\x0C83"
+        L"\x0CBE-\x0CC4\x0CC6-\x0CC8\x0CCA-\x0CCD\x0CD5-\x0CD6\x0D02-\x0D03"
+        L"\x0D3E-\x0D43\x0D46-\x0D48\x0D4A-\x0D4D\x0D57\x0E31\x0E34-\x0E3A"
+        L"\x0E47-\x0E4E\x0EB1\x0EB4-\x0EB9\x0EBB-\x0EBC\x0EC8-\x0ECD"
+        L"\x0F18-\x0F19\x0F35\x0F37\x0F39\x0F3E\x0F3F\x0F71-\x0F84"
+        L"\x0F86-\x0F8B\x0F90-\x0F95\x0F97\x0F99-\x0FAD\x0FB1-\x0FB7\x0FB9"
+        L"\x20D0-\x20DC\x20E1\x302A-\x302F\x3099\x309A"
+    );
+
+    Digit = chset_t(
+        L"\x0030-\x0039\x0660-\x0669\x06F0-\x06F9\x0966-\x096F\x09E6-\x09EF"
+        L"\x0A66-\x0A6F\x0AE6-\x0AEF\x0B66-\x0B6F\x0BE7-\x0BEF\x0C66-\x0C6F"
+        L"\x0CE6-\x0CEF\x0D66-\x0D6F\x0E50-\x0E59\x0ED0-\x0ED9\x0F20-\x0F29"
+    );
+
+    Extender = chset_t(
+        L"\x00B7\x02D0\x02D1\x0387\x0640\x0E46\x0EC6\x3005\x3031-\x3035"
+        L"\x309D-\x309E\x30FC-\x30FE"
+    );
+
+    NameChar =
+        Letter 
+        | Digit 
+        | L'.'
+        | L'-'
+        | L'_'
+        | L':'
+        | CombiningChar 
+        | Extender
+    ;
+}
+} // namespace archive
+} // namespace boost
+
+#include "basic_xml_grammar.ipp"
+
+namespace boost {
+namespace archive {
+
+// explicit instantiation of xml for wide characters
+template class basic_xml_grammar<wchar_t>;
+
+} // namespace archive
+} // namespace boost
+
+#endif
diff --git a/SRC/Serialization/src/xml_wiarchive.cpp b/SRC/Serialization/src/xml_wiarchive.cpp
new file mode 100755
index 0000000..999a129
--- /dev/null
+++ b/SRC/Serialization/src/xml_wiarchive.cpp
@@ -0,0 +1,53 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_wiarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#include <boost/detail/workaround.hpp>
+
+#if (defined _MSC_VER) && (_MSC_VER == 1200)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+#define BOOST_WARCHIVE_SOURCE
+
+// the following works around an issue between spirit 1.61 and borland.
+// it turns out the the certain spirit stuff must be defined before
+// certain parts of mpl.  including this here makes sure that happens
+#if BOOST_WORKAROUND(__BORLANDC__, <= 0x560 )
+#include <Serialization/archive/impl/basic_xml_grammar.hpp>
+#endif
+
+#include <Serialization/archive/xml_wiarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of xml stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_xml_iarchive.ipp>
+#include <Serialization/archive/impl/xml_wiarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<naked_xml_wiarchive>;
+template class basic_xml_iarchive<naked_xml_wiarchive> ;
+template class xml_wiarchive_impl<naked_xml_wiarchive> ;
+
+template class detail::archive_serializer_map<xml_wiarchive>;
+template class basic_xml_iarchive<xml_wiarchive> ;
+template class xml_wiarchive_impl<xml_wiarchive> ;
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/src/xml_woarchive.cpp b/SRC/Serialization/src/xml_woarchive.cpp
new file mode 100755
index 0000000..9129931
--- /dev/null
+++ b/SRC/Serialization/src/xml_woarchive.cpp
@@ -0,0 +1,35 @@
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// xml_woarchive.cpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#ifdef BOOST_NO_STD_WSTREAMBUF
+#error "wide char i/o not supported on this platform"
+#else
+
+#define BOOST_WARCHIVE_SOURCE
+#include <Serialization/archive/xml_woarchive.hpp>
+#include <Serialization/archive/detail/archive_serializer_map.hpp>
+
+// explicitly instantiate for this type of text stream
+#include <Serialization/archive/impl/archive_serializer_map.ipp>
+#include <Serialization/archive/impl/basic_xml_oarchive.ipp>
+#include <Serialization/archive/impl/xml_woarchive_impl.ipp>
+
+namespace boost {
+namespace archive {
+
+template class detail::archive_serializer_map<xml_woarchive>;
+template class basic_xml_oarchive<xml_woarchive> ;
+template class xml_woarchive_impl<xml_woarchive> ;
+
+} // namespace archive
+} // namespace boost
+
+#endif // BOOST_NO_STD_WSTREAMBUF
diff --git a/SRC/Serialization/state_saver.hpp b/SRC/Serialization/state_saver.hpp
new file mode 100755
index 0000000..196b847
--- /dev/null
+++ b/SRC/Serialization/state_saver.hpp
@@ -0,0 +1,96 @@
+#ifndef BOOST_SERIALIZATION_STATE_SAVER_HPP
+#define BOOST_SERIALIZATION_STATE_SAVER_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// state_saver.hpp:
+
+// (C) Copyright 2003-4 Pavel Vozenilek and Robert Ramey - http://www.rrsd.com.
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/serialization for updates, documentation, and revision history.
+
+// Inspired by Daryle Walker's iostate_saver concept.  This saves the original
+// value of a variable when a state_saver is constructed and restores
+// upon destruction.  Useful for being sure that state is restored to
+// variables upon exit from scope.
+
+
+#include <boost/config.hpp>
+#ifndef BOOST_NO_EXCEPTIONS
+    #include <exception>
+#endif
+
+#include <boost/call_traits.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
+#include <boost/detail/no_exceptions_support.hpp>
+
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+
+namespace boost {
+namespace serialization {
+
+template<class T>
+// T requirements:
+//  - POD or object semantic (cannot be reference, function, ...)
+//  - copy constructor
+//  - operator = (no-throw one preferred)
+class state_saver : private boost::noncopyable
+{
+private:
+    const T previous_value;
+    T & previous_ref;
+
+    struct restore {
+        static void invoke(T & previous_ref, const T & previous_value){
+            previous_ref = previous_value; // won't throw
+        }
+    };
+
+    struct restore_with_exception {
+        static void invoke(T & previous_ref, const T & previous_value){
+            BOOST_TRY{
+                previous_ref = previous_value;
+            } 
+            BOOST_CATCH(::std::exception &) { 
+                // we must ignore it - we are in destructor
+            }
+            BOOST_CATCH_END
+        }
+    };
+
+public:
+    state_saver(
+        T & object
+    ) : 
+        previous_value(object),
+        previous_ref(object) 
+    {}
+    
+    ~state_saver() {
+        #ifndef BOOST_NO_EXCEPTIONS
+            typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<
+                has_nothrow_copy< T >,
+                mpl::identity<restore>,
+                mpl::identity<restore_with_exception>
+            >::type typex;
+            typex::invoke(previous_ref, previous_value);
+        #else
+            previous_ref = previous_value;
+        #endif
+    }
+
+}; // state_saver<>
+
+} // serialization
+} // boost
+
+#endif //BOOST_SERIALIZATION_STATE_SAVER_HPP
diff --git a/SRC/Serialization/static_warning.hpp b/SRC/Serialization/static_warning.hpp
new file mode 100755
index 0000000..83d0684
--- /dev/null
+++ b/SRC/Serialization/static_warning.hpp
@@ -0,0 +1,108 @@
+#ifndef BOOST_SERIALIZATION_STATIC_WARNING_HPP
+#define BOOST_SERIALIZATION_STATIC_WARNING_HPP
+
+//  (C) Copyright Robert Ramey 2003. Jonathan Turkanis 2004.
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/static_assert for documentation.
+
+/*
+ Revision history:
+   15 June  2003 - Initial version.
+   31 March 2004 - improved diagnostic messages and portability 
+                   (Jonathan Turkanis)
+   03 April 2004 - works on VC6 at class and namespace scope
+                 - ported to DigitalMars
+                 - static warnings disabled by default; when enabled,
+                   uses pragmas to enable required compiler warnings
+                   on MSVC, Intel, Metrowerks and Borland 5.x.
+                   (Jonathan Turkanis)
+   30 May 2004   - tweaked for msvc 7.1 and gcc 3.3
+                 - static warnings ENabled by default; when enabled,
+                   (Robert Ramey)
+*/
+
+#include <boost/config.hpp>
+
+//
+// Implementation
+// Makes use of the following warnings:
+//  1. GCC prior to 3.3: division by zero.
+//  2. BCC 6.0 preview: unreferenced local variable.
+//  3. DigitalMars: returning address of local automatic variable.
+//  4. VC6: class previously seen as struct (as in 'boost/mpl/print.hpp')
+//  5. All others: deletion of pointer to incomplete type.
+//
+// The trick is to find code which produces warnings containing the name of
+// a structure or variable. Details, with same numbering as above:
+// 1. static_warning_impl<B>::value is zero iff B is false, so diving an int
+//    by this value generates a warning iff B is false.
+// 2. static_warning_impl<B>::type has a constructor iff B is true, so an
+//    unreferenced variable of this type generates a warning iff B is false.
+// 3. static_warning_impl<B>::type overloads operator& to return a dynamically
+//    allocated int pointer only is B is true, so  returning the address of an
+//    automatic variable of this type generates a warning iff B is fasle.
+// 4. static_warning_impl<B>::STATIC_WARNING is decalred as a struct iff B is 
+//    false. 
+// 5. static_warning_impl<B>::type is incomplete iff B is false, so deleting a
+//    pointer to this type generates a warning iff B is false.
+//
+
+//------------------Enable selected warnings----------------------------------//
+
+// Enable the warnings relied on by BOOST_STATIC_WARNING, where possible. The 
+// only pragma which is absolutely necessary here is for Borland 5.x, since 
+// W8073 is disabled by default. If enabling selected warnings is considered 
+// unacceptable, this section can be replaced with:
+//   #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x600)
+//    pragma warn +st
+//   #endif
+
+// 6. replaced implementation with one which depends solely on
+//    mpl::print<>.  The previous one was found to fail for functions
+//    under recent versions of gcc and intel compilers - Robert Ramey
+
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/print.hpp>
+#include <boost/mpl/eval_if.hpp>
+
+namespace boost {
+namespace serialization {
+
+template<int L> 
+struct BOOST_SERIALIZATION_STATIC_WARNING_LINE{};
+
+template<bool B, int L>
+struct static_warning_test{
+    typename boost::mpl::eval_if_c<
+        B,
+        boost::mpl::true_,
+        typename boost::mpl::identity<
+            boost::mpl::print<
+                BOOST_SERIALIZATION_STATIC_WARNING_LINE<L>
+            >
+        >
+    >::type type;
+};
+
+template<int i>
+struct BOOST_SERIALIZATION_SS {};
+
+} // serialization
+} // boost
+
+#define BOOST_SERIALIZATION_BSW(B, L) \
+    typedef boost::serialization::BOOST_SERIALIZATION_SS< \
+        sizeof( boost::serialization::static_warning_test< B, L > ) \
+    > BOOST_JOIN(STATIC_WARNING_LINE, L);
+
+#define BOOST_STATIC_WARNING(B) BOOST_SERIALIZATION_BSW(B, __LINE__)
+
+#endif // BOOST_SERIALIZATION_STATIC_WARNING_HPP
diff --git a/SRC/Serialization/string.hpp b/SRC/Serialization/string.hpp
new file mode 100755
index 0000000..ecc9a00
--- /dev/null
+++ b/SRC/Serialization/string.hpp
@@ -0,0 +1,91 @@
+#ifndef  BOOST_SERIALIZATION_STRING_HPP
+#define BOOST_SERIALIZATION_STRING_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization/string.hpp:
+// serialization for stl string templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <string>
+
+#include <boost/config.hpp>
+#include <Serialization/level.hpp>
+
+BOOST_CLASS_IMPLEMENTATION(std::string, boost::serialization::primitive_type)
+#ifndef BOOST_NO_STD_WSTRING
+BOOST_CLASS_IMPLEMENTATION(std::wstring, boost::serialization::primitive_type)
+#endif
+
+// left over from a previous incarnation - strings are now always primitive types
+#if 0 
+#include <string>
+#include <Serialization/collections_save_imp.hpp>
+#include <Serialization/collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+
+namespace boost { 
+namespace serialization {
+
+// basic_string - general case
+template<class Archive, class U, class Allocator>
+inline void save(
+    Archive & ar,
+    const std::basic_string<U, Allocator> &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::save_collection<
+        Archive, std::basic_string<U, Allocator> 
+    >(ar, t);
+}
+
+template<class Archive, class U, class Allocator>
+inline void load(
+    Archive & ar,
+    std::basic_string<U, Allocator> &t,
+    const unsigned int file_version
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::basic_string<U, Allocator>,
+        boost::serialization::stl::archive_input_seq<
+            Archive, 
+            std::basic_string<U, Allocator> 
+        >,
+        boost::serialization::stl::reserve_imp<
+            std::basic_string<U, Allocator> 
+        >
+    >(ar, t);
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class U, class Allocator>
+inline void serialize(
+    Archive & ar,
+    std::basic_string<U, Allocator> & t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // serialization
+} // namespace boost
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(std::vector)
+
+#endif
+
+#endif // BOOST_SERIALIZATION_STRING_HPP
diff --git a/SRC/Serialization/strong_typedef.hpp b/SRC/Serialization/strong_typedef.hpp
new file mode 100755
index 0000000..1632bae
--- /dev/null
+++ b/SRC/Serialization/strong_typedef.hpp
@@ -0,0 +1,66 @@
+#ifndef BOOST_SERIALIZATION_STRONG_TYPEDEF_HPP
+#define BOOST_SERIALIZATION_STRONG_TYPEDEF_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// strong_typedef.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/serialization for updates, documentation, and revision history.
+
+// macro used to implement a strong typedef.  strong typedef
+// guarentees that two types are distinguised even though the
+// share the same underlying implementation.  typedef does not create
+// a new type.  BOOST_STRONG_TYPEDEF(T, D) creates a new type named D
+// that operates as a type T.
+
+#include <boost/config.hpp>
+#include <boost/operators.hpp>
+
+#if !defined(__BORLANDC__) || __BORLANDC__ >= 0x590
+    #define BOOST_STRONG_TYPEDEF(T, D)                              \
+    struct D                                                        \
+        : boost::totally_ordered1< D                                \
+        , boost::totally_ordered2< D, T                             \
+        > >                                                         \
+    {                                                               \
+        T t;                                                        \
+        explicit D(const T t_) : t(t_) {};                          \
+        D(): t() {};                                                \
+        D(const D & t_) : t(t_.t){}                                 \
+        D & operator=(const D & rhs) { t = rhs.t; return *this;}    \
+        D & operator=(const T & rhs) { t = rhs; return *this;}      \
+        operator const T & () const {return t; }                    \
+        operator T & () { return t; }                               \
+        bool operator==(const D & rhs) const { return t == rhs.t; } \
+        bool operator<(const D & rhs) const { return t < rhs.t; }   \
+    };
+#else
+    #define BOOST_STRONG_TYPEDEF(T, D)                              \
+    struct D                                                        \
+        : boost::totally_ordered1< D                                \
+        , boost::totally_ordered2< D, T                             \
+        > >                                                         \
+    {                                                               \
+        T t;                                                        \
+        explicit D(const T t_) : t(t_) {};                          \
+        D() : t(){};                                                \
+        D(const D & t_) : t(t_.t){}                                 \
+        D & operator=(const D & rhs) { t = rhs.t; return *this;}    \
+        D & operator=(const T & rhs) { t = rhs; return *this;}      \
+        /*operator const T & () const {return t; }*/                \
+        operator T & () { return t; }                               \
+        bool operator==(const D & rhs) const { return t == rhs.t; } \
+        bool operator<(const D & rhs) const { return t < rhs.t; }   \
+    };
+#endif // !defined(__BORLANDC) || __BORLANDC__ >= 0x590
+
+#endif // BOOST_SERIALIZATION_STRONG_TYPEDEF_HPP
diff --git a/SRC/Serialization/throw_exception.hpp b/SRC/Serialization/throw_exception.hpp
new file mode 100755
index 0000000..484ef09
--- /dev/null
+++ b/SRC/Serialization/throw_exception.hpp
@@ -0,0 +1,44 @@
+#ifndef BOOST_SERIALIZATION_THROW_EXCEPTION_HPP_INCLUDED
+#define BOOST_SERIALIZATION_THROW_EXCEPTION_HPP_INCLUDED
+
+// MS compatible compilers support #pragma once
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+//  boost/throw_exception.hpp
+//
+//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <boost/config.hpp>
+
+#ifndef BOOST_NO_EXCEPTIONS
+#include <exception>
+#endif
+
+namespace boost {
+namespace serialization {
+
+#ifdef BOOST_NO_EXCEPTIONS
+
+inline void throw_exception(std::exception const & e) {
+    ::boost::throw_exception(e);
+}
+
+#else
+
+template<class E> inline void throw_exception(E const & e){
+    throw e;
+}
+
+#endif
+
+} // namespace serialization
+} // namespace boost
+
+#endif // #ifndef BOOST_SERIALIZATION_THROW_EXCEPTION_HPP_INCLUDED
diff --git a/SRC/Serialization/tracking.hpp b/SRC/Serialization/tracking.hpp
new file mode 100755
index 0000000..0be47b0
--- /dev/null
+++ b/SRC/Serialization/tracking.hpp
@@ -0,0 +1,118 @@
+#ifndef BOOST_SERIALIZATION_TRACKING_HPP
+#define BOOST_SERIALIZATION_TRACKING_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// tracking.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/greater.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <Serialization/level.hpp>
+#include <Serialization/tracking_enum.hpp>
+#include <Serialization/type_info_implementation.hpp>
+
+namespace boost {
+namespace serialization {
+
+struct basic_traits;
+
+// default tracking level
+template<class T>
+struct tracking_level_impl {
+    template<class U>
+    struct traits_class_tracking {
+        typedef BOOST_DEDUCED_TYPENAME U::tracking type;
+    };
+    typedef mpl::integral_c_tag tag;
+    // note: at least one compiler complained w/o the full qualification
+    // on basic traits below
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_base_and_derived<boost::serialization::basic_traits, T>,
+            traits_class_tracking< T >,
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_pointer< T >,
+            // pointers are not tracked by default
+            mpl::int_<track_never>,
+        //else
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            // for primitives
+            BOOST_DEDUCED_TYPENAME mpl::equal_to<
+                implementation_level< T >,
+                mpl::int_<primitive_type> 
+            >,
+            // is never
+            mpl::int_<track_never>,
+            // otherwise its selective
+            mpl::int_<track_selectively>
+    >  > >::type type;
+    BOOST_STATIC_CONSTANT(int, value = type::value);
+};
+
+template<class T>
+struct tracking_level : 
+    public tracking_level_impl<const T>
+{
+};
+
+template<class T, enum tracking_type L>
+inline bool operator>=(tracking_level< T > t, enum tracking_type l)
+{
+    return t.value >= (int)l;
+}
+
+} // namespace serialization
+} // namespace boost
+
+
+// The STATIC_ASSERT is prevents one from setting tracking for a primitive type.  
+// This almost HAS to be an error.  Doing this will effect serialization of all 
+// char's in your program which is almost certainly what you don't want to do.  
+// If you want to track all instances of a given primitive type, You'll have to 
+// wrap it in your own type so its not a primitive anymore.  Then it will compile
+// without problem.
+#define BOOST_CLASS_TRACKING(T, E)           \
+namespace boost {                            \
+namespace serialization {                    \
+template<>                                   \
+struct tracking_level< T >                   \
+{                                            \
+    typedef mpl::integral_c_tag tag;         \
+    typedef mpl::int_< E> type;              \
+    BOOST_STATIC_CONSTANT(                   \
+        int,                                 \
+        value = tracking_level::type::value  \
+    );                                       \
+    /* tracking for a class  */              \
+    BOOST_STATIC_ASSERT((                    \
+        mpl::greater<                        \
+            /* that is a prmitive */         \
+            implementation_level< T >,       \
+            mpl::int_<primitive_type>        \
+        >::value                             \
+    ));                                      \
+};                                           \
+}}
+
+#endif // BOOST_SERIALIZATION_TRACKING_HPP
diff --git a/SRC/Serialization/tracking_enum.hpp b/SRC/Serialization/tracking_enum.hpp
new file mode 100755
index 0000000..a96db0d
--- /dev/null
+++ b/SRC/Serialization/tracking_enum.hpp
@@ -0,0 +1,41 @@
+#ifndef BOOST_SERIALIZATION_TRACKING_ENUM_HPP
+#define BOOST_SERIALIZATION_TRACKING_ENUM_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// tracking_enum.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+namespace boost {
+namespace serialization {
+
+// addresses of serialized objects may be tracked to avoid saving/loading
+// redundant copies.  This header defines a class trait that can be used
+// to specify when objects should be tracked
+
+// names for each tracking level
+enum tracking_type
+{
+    // never track this type
+    track_never = 0,
+    // track objects of this type if the object is serialized through a 
+    // pointer.
+    track_selectively = 1,
+    // always track this type
+    track_always = 2
+};
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_TRACKING_ENUM_HPP
diff --git a/SRC/Serialization/traits.hpp b/SRC/Serialization/traits.hpp
new file mode 100755
index 0000000..0310128
--- /dev/null
+++ b/SRC/Serialization/traits.hpp
@@ -0,0 +1,65 @@
+#ifndef BOOST_SERIALIZATION_TRAITS_HPP
+#define BOOST_SERIALIZATION_TRAITS_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// traits.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+// This header is used to apply serialization traits to templates.  The
+// standard system can't be used for platforms which don't support
+// Partial Templlate Specialization.  
+
+// The motivation for this is the Name-Value Pair (NVP) template.
+// it has to work the same on all platforms in order for archives
+// to be portable accross platforms.
+
+#include <boost/config.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/bool.hpp>
+#include <Serialization/level_enum.hpp>
+#include <Serialization/tracking_enum.hpp>
+
+namespace boost {
+namespace serialization {
+
+// common base class used to detect appended traits class
+struct basic_traits {};
+
+template <class T>
+struct extended_type_info_impl;
+
+template<
+    class T, 
+    int Level, 
+    int Tracking,
+    unsigned int Version = 0,
+    class ETII = extended_type_info_impl< T >,
+    class Wrapper = mpl::false_
+>
+struct traits : public basic_traits {
+    BOOST_STATIC_ASSERT(Version == 0 || Level >= object_class_info);
+    BOOST_STATIC_ASSERT(Tracking == track_never || Level >= object_serializable);
+    typedef BOOST_DEDUCED_TYPENAME mpl::int_<Level> level;
+    typedef BOOST_DEDUCED_TYPENAME mpl::int_<Tracking> tracking;
+    typedef BOOST_DEDUCED_TYPENAME mpl::int_<Version> version;
+    typedef ETII type_info_implementation;
+    typedef Wrapper is_wrapper;
+};
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_TRAITS_HPP
diff --git a/SRC/Serialization/type_info_implementation.hpp b/SRC/Serialization/type_info_implementation.hpp
new file mode 100755
index 0000000..f7d6f26
--- /dev/null
+++ b/SRC/Serialization/type_info_implementation.hpp
@@ -0,0 +1,86 @@
+#ifndef BOOST_SERIALIZATION_TYPE_INFO_IMPLEMENTATION_HPP
+#define BOOST_SERIALIZATION_TYPE_INFO_IMPLEMENTATION_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// type_info_implementation.hpp: interface for portable version of type_info
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+
+#include <boost/static_assert.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <Serialization/traits.hpp>
+
+namespace boost {
+namespace serialization {
+
+// note that T and const T are folded into const T so that
+// there is only one table entry per type
+template<class T>
+struct type_info_implementation {
+    template<class U>
+    struct traits_class_typeinfo_implementation {
+      typedef BOOST_DEDUCED_TYPENAME U::type_info_implementation::type type;
+    };
+    // note: at least one compiler complained w/o the full qualification
+    // on basic traits below
+    typedef 
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_base_and_derived<boost::serialization::basic_traits, T>,
+            traits_class_typeinfo_implementation< T >,
+        //else
+            mpl::identity<
+                BOOST_DEDUCED_TYPENAME extended_type_info_impl< T >::type
+            >
+        >::type type;
+};
+
+} // namespace serialization
+} // namespace boost
+
+// define a macro to assign a particular derivation of extended_type_info
+// to a specified a class. 
+#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x560))
+#define BOOST_CLASS_TYPE_INFO(T, ETI)              \
+namespace boost {                                  \
+namespace serialization {                          \
+template<>                                         \
+struct type_info_implementation< T > {             \
+    typedef const ETI type;                        \
+};                                                 \
+}                                                  \
+}                                                  \
+/**/
+#else
+#define BOOST_CLASS_TYPE_INFO(T, ETI)              \
+namespace boost {                                  \
+namespace serialization {                          \
+template<>                                         \
+struct type_info_implementation< T > {             \
+    typedef ETI type;                              \
+};                                                 \
+template<>                                         \
+struct type_info_implementation< const T > {       \
+    typedef ETI type;                              \
+};                                                 \
+}                                                  \
+}                                                  \
+/**/
+#endif
+
+#endif /// BOOST_SERIALIZATION_TYPE_INFO_IMPLEMENTATION_HPP
diff --git a/SRC/Serialization/utility.hpp b/SRC/Serialization/utility.hpp
new file mode 100755
index 0000000..7b9ae94
--- /dev/null
+++ b/SRC/Serialization/utility.hpp
@@ -0,0 +1,56 @@
+#ifndef  BOOST_SERIALIZATION_UTILITY_HPP
+#define BOOST_SERIALIZATION_UTILITY_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// serialization/utility.hpp:
+// serialization for stl utility templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <utility>
+#include <boost/config.hpp>
+
+#include <boost/type_traits/remove_const.hpp>
+#include <Serialization/nvp.hpp>
+#include <Serialization/is_bitwise_serializable.hpp>
+#include <boost/mpl/and.hpp>
+
+namespace boost { 
+namespace serialization {
+
+// pair
+template<class Archive, class F, class S>
+inline void serialize(
+    Archive & ar,
+    std::pair<F, S> & p,
+    const unsigned int /* file_version */
+){
+    // note: we remove any const-ness on the first argument.  The reason is that 
+    // for stl maps, the type saved is pair<const key, T).  We remove
+    // the const-ness in order to be able to load it.
+    typedef BOOST_DEDUCED_TYPENAME boost::remove_const<F>::type typef;
+    ar & boost::serialization::make_nvp("first", const_cast<typef &>(p.first));
+    ar & boost::serialization::make_nvp("second", p.second);
+}
+
+/// specialization of is_bitwise_serializable for pairs
+template <class T, class U>
+struct is_bitwise_serializable<std::pair<T,U> >
+ : public mpl::and_<is_bitwise_serializable< T >,is_bitwise_serializable<U> >
+{
+};
+
+} // serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_UTILITY_HPP
diff --git a/SRC/Serialization/valarray.hpp b/SRC/Serialization/valarray.hpp
new file mode 100755
index 0000000..ef86ee5
--- /dev/null
+++ b/SRC/Serialization/valarray.hpp
@@ -0,0 +1,74 @@
+#ifndef BOOST_SERIALIZATION_VALARAY_HPP
+#define BOOST_SERIALIZATION_VALARAY_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// valarray.hpp: serialization for stl vector templates
+
+// (C) Copyright 2005 Matthias Troyer . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <valarray>
+#include <boost/config.hpp>
+#include <Serialization/split_free.hpp>
+#include <Serialization/array.hpp>
+#include <Serialization/collection_size_type.hpp>
+#include <Serialization/detail/get_data.hpp>
+
+// function specializations must be defined in the appropriate
+// namespace - boost::serialization
+#if defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)
+#define STD _STLP_STD
+#else
+#define STD std
+#endif
+
+namespace boost { namespace serialization {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// valarray< T >
+
+template<class Archive, class U>
+void save( Archive & ar, const STD::valarray<U> &t, const unsigned int /*file_version*/ )
+{
+  const collection_size_type count(t.size());
+  ar << BOOST_SERIALIZATION_NVP(count);
+  if (t.size())
+    ar << make_array(detail::get_data(t), t.size());
+}
+
+
+template<class Archive, class U>
+void load( Archive & ar, STD::valarray<U> &t,  const unsigned int /*file_version*/ )
+{
+  collection_size_type count;
+  ar >> BOOST_SERIALIZATION_NVP(count);
+  t.resize(count);
+  if (t.size())
+    ar >> make_array(detail::get_data(t), t.size());
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class U>
+inline void serialize( Archive & ar, STD::valarray<U> & t, const unsigned int file_version)
+{
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} } // end namespace boost::serialization
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(STD::valarray)
+#undef STD
+
+#endif // BOOST_SERIALIZATION_VALARAY_HPP
diff --git a/SRC/Serialization/variant.hpp b/SRC/Serialization/variant.hpp
new file mode 100755
index 0000000..49d0f4f
--- /dev/null
+++ b/SRC/Serialization/variant.hpp
@@ -0,0 +1,163 @@
+#ifndef BOOST_SERIALIZATION_VARIANT_HPP
+#define BOOST_SERIALIZATION_VARIANT_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+#if defined(_MSC_VER) && (_MSC_VER <= 1020)
+#  pragma warning (disable : 4786) // too long name, harmless warning
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// variant.hpp - non-intrusive serialization of variant types
+//
+// copyright (c) 2005   
+// troy d. straszheim <troy at resophonic.com>
+// http://www.resophonic.com
+//
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// See http://www.boost.org for updates, documentation, and revision history.
+//
+// thanks to Robert Ramey, Peter Dimov, and Richard Crossley.
+//
+
+#include <boost/mpl/front.hpp>
+#include <boost/mpl/pop_front.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/size.hpp>
+#include <boost/mpl/empty.hpp>
+
+#include <Serialization/throw_exception.hpp>
+
+#include <boost/variant.hpp>
+
+#include <Serialization/archive/archive_exception.hpp>
+
+#include <Serialization/split_free.hpp>
+#include <Serialization/serialization.hpp>
+#include <Serialization/nvp.hpp>
+
+namespace boost {
+namespace serialization {
+
+template<class Archive>
+struct variant_save_visitor : 
+    boost::static_visitor<> 
+{
+    variant_save_visitor(Archive& ar) :
+        m_ar(ar)
+    {}
+    template<class T>
+    void operator()(T const & value) const
+    {
+        m_ar << BOOST_SERIALIZATION_NVP(value);
+    }
+private:
+    Archive & m_ar;
+};
+
+template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
+void save(
+    Archive & ar,
+    boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const & v,
+    unsigned int /*version*/
+){
+    int which = v.which();
+    ar << BOOST_SERIALIZATION_NVP(which);
+    typedef BOOST_DEDUCED_TYPENAME  boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
+    variant_save_visitor<Archive> visitor(ar);
+    v.apply_visitor(visitor);
+}
+
+template<class S>
+struct variant_impl {
+
+    struct load_null {
+        template<class Archive, class V>
+        static void invoke(
+            Archive & /*ar*/,
+            int /*which*/,
+            V & /*v*/,
+            const unsigned int /*version*/
+        ){}
+    };
+
+    struct load_impl {
+        template<class Archive, class V>
+        static void invoke(
+            Archive & ar,
+            int which,
+            V & v,
+            const unsigned int version
+        ){
+            if(which == 0){
+                // note: A non-intrusive implementation (such as this one)
+                // necessary has to copy the value.  This wouldn't be necessary
+                // with an implementation that de-serialized to the address of the
+                // aligned storage included in the variant.
+                typedef BOOST_DEDUCED_TYPENAME mpl::front<S>::type head_type;
+                head_type value;
+                ar >> BOOST_SERIALIZATION_NVP(value);
+                v = value;
+                ar.reset_object_address(& boost::get<head_type>(v), & value);
+                return;
+            }
+            typedef BOOST_DEDUCED_TYPENAME mpl::pop_front<S>::type type;
+            variant_impl<type>::load(ar, which - 1, v, version);
+        }
+    };
+
+    template<class Archive, class V>
+    static void load(
+        Archive & ar,
+        int which,
+        V & v,
+        const unsigned int version
+    ){
+        typedef BOOST_DEDUCED_TYPENAME mpl::eval_if<mpl::empty<S>,
+            mpl::identity<load_null>,
+            mpl::identity<load_impl>
+        >::type typex;
+        typex::invoke(ar, which, v, version);
+    }
+
+};
+
+template<class Archive, BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
+void load(
+    Archive & ar, 
+    boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& v,
+    const unsigned int version
+){
+    int which;
+    typedef BOOST_DEDUCED_TYPENAME boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types types;
+    ar >> BOOST_SERIALIZATION_NVP(which);
+    if(which >=  mpl::size<types>::value)
+        // this might happen if a type was removed from the list of variant types
+        boost::serialization::throw_exception(
+            boost::archive::archive_exception(
+                boost::archive::archive_exception::unsupported_version
+            )
+        );
+    variant_impl<types>::load(ar, which, v, version);
+}
+
+template<class Archive,BOOST_VARIANT_ENUM_PARAMS(/* typename */ class T)>
+inline void serialize(
+    Archive & ar,
+    boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & v,
+    const unsigned int file_version
+){
+    split_free(ar,v,file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#endif //BOOST_SERIALIZATION_VARIANT_HPP
diff --git a/SRC/Serialization/vector.hpp b/SRC/Serialization/vector.hpp
new file mode 100755
index 0000000..5cbdcd0
--- /dev/null
+++ b/SRC/Serialization/vector.hpp
@@ -0,0 +1,211 @@
+#ifndef  BOOST_SERIALIZATION_VECTOR_HPP
+#define BOOST_SERIALIZATION_VECTOR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// vector.hpp: serialization for stl vector templates
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// fast array serialization (C) Copyright 2005 Matthias Troyer 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <vector>
+
+#include <boost/config.hpp>
+#include <boost/detail/workaround.hpp>
+#include <boost/type_traits/is_arithmetic.hpp> 
+
+#include <Serialization/collections_save_imp.hpp>
+#include <Serialization/collections_load_imp.hpp>
+#include <Serialization/split_free.hpp>
+#include <Serialization/array.hpp>
+#include <Serialization/detail/get_data.hpp>
+#include <boost/mpl/bool.hpp>
+
+// default is being compatible with version 1.34.1 files, not 1.35 files
+#ifndef BOOST_SERIALIZATION_VECTOR_VERSIONED
+#define BOOST_SERIALIZATION_VECTOR_VERSIONED(V) (V==4 || V==5)
+#endif
+
+namespace boost { 
+namespace serialization {
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// vector< T >
+
+// the default versions
+
+template<class Archive, class U, class Allocator>
+inline void save(
+    Archive & ar,
+    const std::vector<U, Allocator> &t,
+    const unsigned int /* file_version */,
+    mpl::false_
+){
+    boost::serialization::stl::save_collection<Archive, STD::vector<U, Allocator> >(
+        ar, t
+    );
+}
+
+template<class Archive, class U, class Allocator>
+inline void load(
+    Archive & ar,
+    std::vector<U, Allocator> &t,
+    const unsigned int /* file_version */,
+    mpl::false_
+){
+    boost::serialization::stl::load_collection<
+        Archive,
+        std::vector<U, Allocator>,
+        boost::serialization::stl::archive_input_seq<
+            Archive, STD::vector<U, Allocator> 
+        >,
+        boost::serialization::stl::reserve_imp<STD::vector<U, Allocator> >
+    >(ar, t);
+}
+
+// the optimized versions
+
+template<class Archive, class U, class Allocator>
+inline void save(
+    Archive & ar,
+    const std::vector<U, Allocator> &t,
+    const unsigned int /* file_version */,
+    mpl::true_
+){
+    const collection_size_type count(t.size());
+    ar << BOOST_SERIALIZATION_NVP(count);
+    if (!t.empty())
+        ar << make_array(detail::get_data(t),t.size());
+}
+
+template<class Archive, class U, class Allocator>
+inline void load(
+    Archive & ar,
+    std::vector<U, Allocator> &t,
+    const unsigned int /* file_version */,
+    mpl::true_
+){
+    collection_size_type count(t.size());
+    ar >> BOOST_SERIALIZATION_NVP(count);
+    t.resize(count);
+    unsigned int item_version=0;
+    if(BOOST_SERIALIZATION_VECTOR_VERSIONED(ar.get_library_version())) {
+        ar >> BOOST_SERIALIZATION_NVP(item_version);
+    }
+    if (!t.empty())
+        ar >> make_array(detail::get_data(t),t.size());
+  }
+
+// dispatch to either default or optimized versions
+
+template<class Archive, class U, class Allocator>
+inline void save(
+    Archive & ar,
+    const std::vector<U, Allocator> &t,
+    const unsigned int file_version
+){
+    typedef BOOST_DEDUCED_TYPENAME 
+    boost::serialization::use_array_optimization<Archive>::template apply<
+        BOOST_DEDUCED_TYPENAME remove_const<U>::type 
+    >::type use_optimized;
+    save(ar,t,file_version, use_optimized());
+}
+
+template<class Archive, class U, class Allocator>
+inline void load(
+    Archive & ar,
+    std::vector<U, Allocator> &t,
+    const unsigned int file_version
+){
+#ifdef BOOST_SERIALIZATION_VECTOR_135_HPP
+    if (ar.get_library_version()==boost::archive::library_version_type(5))
+    {
+      load(ar,t,file_version, boost::is_arithmetic<U>());
+      return;
+    }
+#endif
+    typedef BOOST_DEDUCED_TYPENAME 
+    boost::serialization::use_array_optimization<Archive>::template apply<
+        BOOST_DEDUCED_TYPENAME remove_const<U>::type 
+    >::type use_optimized;
+    load(ar,t,file_version, use_optimized());
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class U, class Allocator>
+inline void serialize(
+    Archive & ar,
+    std::vector<U, Allocator> & t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+#if ! BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// vector<bool>
+template<class Archive, class Allocator>
+inline void save(
+    Archive & ar,
+    const std::vector<bool, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    // record number of elements
+    collection_size_type count (t.size());
+    ar << BOOST_SERIALIZATION_NVP(count);
+    std::vector<bool>::const_iterator it = t.begin();
+    while(count-- > 0){
+        bool tb = *it++;
+        ar << boost::serialization::make_nvp("item", tb);
+    }
+}
+
+template<class Archive, class Allocator>
+inline void load(
+    Archive & ar,
+    std::vector<bool, Allocator> &t,
+    const unsigned int /* file_version */
+){
+    // retrieve number of elements
+    collection_size_type count;
+    ar >> BOOST_SERIALIZATION_NVP(count);
+    t.clear();
+    while(count-- > 0){
+        bool i;
+        ar >> boost::serialization::make_nvp("item", i);
+        t.push_back(i);
+    }
+}
+
+// split non-intrusive serialization function member into separate
+// non intrusive save/load member functions
+template<class Archive, class Allocator>
+inline void serialize(
+    Archive & ar,
+    std::vector<bool, Allocator> & t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+#endif // BOOST_WORKAROUND
+
+} // serialization
+} // namespace boost
+
+#include <Serialization/collection_traits.hpp>
+
+BOOST_SERIALIZATION_COLLECTION_TRAITS(std::vector)
+
+#endif // BOOST_SERIALIZATION_VECTOR_HPP
diff --git a/SRC/Serialization/vector_135.hpp b/SRC/Serialization/vector_135.hpp
new file mode 100755
index 0000000..88f6928
--- /dev/null
+++ b/SRC/Serialization/vector_135.hpp
@@ -0,0 +1,26 @@
+////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// vector_135.hpp: serialization for stl vector templates for compatibility
+//                 with release 1.35, which had a bug
+
+// (C) Copyright 2008 Matthias Troyer
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+
+#ifndef  BOOST_SERIALIZATION_VECTOR_135_HPP
+#define BOOST_SERIALIZATION_VECTOR_135_HPP
+
+#ifdef BOOST_SERIALIZATION_VECTOR_VERSIONED
+#if BOOST_SERIALIZATION_VECTOR_VERSION != 4
+#error Boost.Serialization cannot be compatible with both 1.35 and 1.36-1.40 files
+#endif
+#else
+#define BOOST_SERIALIZATION_VECTOR_VERSIONED(V) (V==4)
+#endif
+
+#include <Serialization/vector.hpp>
+
+#endif // BOOST_SERIALIZATION_VECTOR_135_HPP
diff --git a/SRC/Serialization/version.hpp b/SRC/Serialization/version.hpp
new file mode 100755
index 0000000..7387290
--- /dev/null
+++ b/SRC/Serialization/version.hpp
@@ -0,0 +1,107 @@
+#ifndef BOOST_SERIALIZATION_VERSION_HPP
+#define BOOST_SERIALIZATION_VERSION_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// version.hpp:
+
+// (C) Copyright 2002 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/config.hpp>
+#include <boost/mpl/assert.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
+#include <boost/mpl/integral_c_tag.hpp>
+
+#include <boost/type_traits/is_base_and_derived.hpp>
+
+namespace boost { 
+namespace serialization {
+
+struct basic_traits;
+
+// default version number is 0. Override with higher version
+// when class definition changes.
+template<class T>
+struct version
+{
+    template<class U>
+    struct traits_class_version {
+        typedef BOOST_DEDUCED_TYPENAME U::version type;
+    };
+
+    typedef mpl::integral_c_tag tag;
+    // note: at least one compiler complained w/o the full qualification
+    // on basic traits below
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<
+            is_base_and_derived<boost::serialization::basic_traits,T>,
+            traits_class_version< T >,
+            mpl::int_<0>
+        >::type type;
+    BOOST_STATIC_CONSTANT(int, value = version::type::value);
+};
+
+#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
+template<class T>
+const int version<T>::value;
+#endif
+
+} // namespace serialization
+} // namespace boost
+
+/* note: at first it seemed that this would be a good place to trap
+ * as an error an attempt to set a version # for a class which doesn't
+ * save its class information (including version #) in the archive.
+ * However, this imposes a requirement that the version be set after
+ * the implemention level which would be pretty confusing.  If this
+ * is to be done, do this check in the input or output operators when
+ * ALL the serialization traits are available.  Included the implementation
+ * here with this comment as a reminder not to do this!
+ */
+//#include <Serialization/level.hpp>
+//#include <boost/mpl/equal_to.hpp>
+
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/comparison.hpp>
+
+// specify the current version number for the class
+// version numbers limited to 8 bits !!!
+#define BOOST_CLASS_VERSION(T, N)                                      \
+namespace boost {                                                      \
+namespace serialization {                                              \
+template<>                                                             \
+struct version<T >                                                     \
+{                                                                      \
+    typedef mpl::int_<N> type;                                         \
+    typedef mpl::integral_c_tag tag;                                   \
+    BOOST_STATIC_CONSTANT(int, value = version::type::value);          \
+    BOOST_MPL_ASSERT((                                                 \
+        boost::mpl::less<                                              \
+            boost::mpl::int_<N>,                                       \
+            boost::mpl::int_<256>                                      \
+        >                                                              \
+    ));                                                                \
+    /*                                                                 \
+    BOOST_MPL_ASSERT((                                                 \
+        mpl::equal_to<                                                 \
+            :implementation_level<T >,                                 \
+            mpl::int_<object_class_info>                               \
+        >::value                                                       \
+    ));                                                                \
+    */                                                                 \
+};                                                                     \
+}                                                                      \
+}
+
+#endif // BOOST_SERIALIZATION_VERSION_HPP
diff --git a/SRC/Serialization/void_cast.hpp b/SRC/Serialization/void_cast.hpp
new file mode 100755
index 0000000..5e94ffa
--- /dev/null
+++ b/SRC/Serialization/void_cast.hpp
@@ -0,0 +1,298 @@
+#ifndef  BOOST_SERIALIZATION_VOID_CAST_HPP
+#define BOOST_SERIALIZATION_VOID_CAST_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// void_cast.hpp:   interface for run-time casting of void pointers.
+
+// (C) Copyright 2002-2009 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// gennadiy.rozental at tfn.com
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // for ptrdiff_t
+#include <boost/config.hpp>
+#include <boost/noncopyable.hpp>
+
+#include <Serialization/smart_cast.hpp>
+#include <Serialization/singleton.hpp>
+#include <Serialization/force_include.hpp>
+#include <Serialization/type_info_implementation.hpp>
+#include <Serialization/extended_type_info.hpp>
+#include <boost/type_traits/is_virtual_base_of.hpp>
+#include <Serialization/void_cast_fwd.hpp>
+
+#include <Serialization/config.hpp>
+#include <boost/config/abi_prefix.hpp> // must be the last header
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4251 4231 4660 4275)
+#endif
+
+namespace boost { 
+namespace serialization { 
+
+class extended_type_info;
+
+// Given a void *, assume that it really points to an instance of one type
+// and alter it so that it would point to an instance of a related type.
+// Return the altered pointer. If there exists no sequence of casts that
+// can transform from_type to to_type, return a NULL.  
+
+BOOST_SERIALIZATION_DECL(void const *)
+void_upcast(
+    extended_type_info const & derived,  
+    extended_type_info const & base, 
+    void const * const t
+);
+
+inline void *
+void_upcast(
+    extended_type_info const & derived,
+    extended_type_info const & base,
+    void * const t 
+){
+    return const_cast<void*>(void_upcast(
+        derived, 
+        base, 
+        const_cast<void const *>(t)
+    ));
+}
+
+BOOST_SERIALIZATION_DECL(void const *)
+void_downcast(
+    extended_type_info const & derived,  
+    extended_type_info const & base, 
+    void const * const t
+);
+
+inline void *
+void_downcast(
+    extended_type_info const & derived,
+    extended_type_info const & base,
+    void * const t 
+){
+    return const_cast<void*>(void_downcast(
+        derived, 
+        base, 
+        const_cast<void const *>(t)
+    ));
+}
+
+namespace void_cast_detail {
+
+class BOOST_SERIALIZATION_DECL(BOOST_PP_EMPTY()) void_caster :
+    private boost::noncopyable
+{
+    friend 
+    BOOST_SERIALIZATION_DECL(void const *)
+    boost::serialization::void_upcast(
+        extended_type_info const & derived,
+        extended_type_info const & base,
+        void const * const
+    );
+    friend 
+    BOOST_SERIALIZATION_DECL(void const *)  
+    boost::serialization::void_downcast(
+        extended_type_info const & derived,
+        extended_type_info const & base,
+        void const * const
+    );
+protected:
+    void recursive_register(bool includes_virtual_base = false) const;
+    void recursive_unregister() const;
+    virtual bool has_virtual_base() const = 0;
+public:
+    // Data members
+    const extended_type_info * m_derived;
+    const extended_type_info * m_base;
+    /*const*/ std::ptrdiff_t m_difference;
+    void_caster const * const m_parent;
+
+    // note that void_casters are keyed on value of
+    // member extended type info records - NOT their
+    // addresses.  This is necessary in order for the
+    // void cast operations to work across dll and exe
+    // module boundries.
+    bool operator<(const void_caster & rhs) const;
+
+    const void_caster & operator*(){
+        return *this;
+    }
+    // each derived class must re-implement these;
+    virtual void const * upcast(void const * const t) const = 0;
+    virtual void const * downcast(void const * const t) const = 0;
+    // Constructor
+    void_caster(
+        extended_type_info const * derived,
+        extended_type_info const * base,
+        std::ptrdiff_t difference = 0,
+        void_caster const * const parent = 0
+    ) :
+        m_derived(derived),
+        m_base(base),
+        m_difference(difference),
+        m_parent(parent)
+    {}
+    virtual ~void_caster(){}
+};
+
+#ifdef BOOST_MSVC
+#  pragma warning(push)
+#  pragma warning(disable : 4251 4231 4660 4275 4511 4512)
+#endif
+
+template <class Derived, class Base>
+class void_caster_primitive : 
+    public void_caster
+{
+    virtual void const * downcast(void const * const t) const {
+        const Derived * d = 
+            boost::serialization::smart_cast<const Derived *, const Base *>(
+                static_cast<const Base *>(t)
+            );
+        return d;
+    }
+    virtual void const * upcast(void const * const t) const {
+        const Base * b = 
+            boost::serialization::smart_cast<const Base *, const Derived *>(
+                static_cast<const Derived *>(t)
+            );
+        return b;
+    }
+    virtual bool has_virtual_base() const {
+        return false;
+    }
+public:
+    void_caster_primitive();
+    virtual ~void_caster_primitive();
+};
+
+template <class Derived, class Base>
+void_caster_primitive<Derived, Base>::void_caster_primitive() :
+    void_caster( 
+        & type_info_implementation<Derived>::type::get_const_instance(), 
+        & type_info_implementation<Base>::type::get_const_instance(),
+        // note:I wanted to display from 0 here, but at least one compiler
+        // treated 0 by not shifting it at all.
+        reinterpret_cast<std::ptrdiff_t>(
+            static_cast<Derived *>(
+                reinterpret_cast<Base *>(1)
+            )
+        ) - 1
+    )
+{
+    recursive_register();
+}
+
+template <class Derived, class Base>
+void_caster_primitive<Derived, Base>::~void_caster_primitive(){
+    recursive_unregister();
+}
+
+template <class Derived, class Base>
+class void_caster_virtual_base : 
+    public void_caster
+{
+    virtual bool has_virtual_base() const {
+        return true;
+    }
+public:
+    virtual void const * downcast(void const * const t) const {
+        const Derived * d = 
+            dynamic_cast<const Derived *>(
+                static_cast<const Base *>(t)
+            );
+        return d;
+    }
+    virtual void const * upcast(void const * const t) const {
+        const Base * b = 
+            dynamic_cast<const Base *>(
+                static_cast<const Derived *>(t)
+            );
+        return b;
+    }
+    void_caster_virtual_base();
+    virtual ~void_caster_virtual_base();
+};
+
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
+template <class Derived, class Base>
+void_caster_virtual_base<Derived,Base>::void_caster_virtual_base() :
+    void_caster( 
+        & (type_info_implementation<Derived>::type::get_const_instance()), 
+        & (type_info_implementation<Base>::type::get_const_instance())
+    )
+{
+    recursive_register(true);
+}
+
+template <class Derived, class Base>
+void_caster_virtual_base<Derived,Base>::~void_caster_virtual_base(){
+    recursive_unregister();
+}
+
+template <class Derived, class Base>
+struct void_caster_base :
+    public void_caster
+{
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
+            mpl::identity<
+                void_cast_detail::void_caster_virtual_base<Derived, Base>
+            >
+        ,// else
+            mpl::identity<
+                void_cast_detail::void_caster_primitive<Derived, Base>
+            >
+        >::type type;
+};
+
+} // void_cast_detail 
+
+template<class Derived, class Base>
+BOOST_DLLEXPORT 
+inline const void_cast_detail::void_caster & void_cast_register(
+    Derived const * /* dnull = NULL */, 
+    Base const * /* bnull = NULL */
+){
+    typedef
+        BOOST_DEDUCED_TYPENAME mpl::eval_if<boost::is_virtual_base_of<Base,Derived>,
+            mpl::identity<
+                void_cast_detail::void_caster_virtual_base<Derived, Base>
+            >
+        ,// else
+            mpl::identity<
+                void_cast_detail::void_caster_primitive<Derived, Base>
+            >
+        >::type typex;
+    return singleton<typex>::get_const_instance();
+}
+
+template<class Derived, class Base>
+class void_caster :
+    public void_cast_detail::void_caster_base<Derived, Base>::type
+{
+};
+
+} // namespace serialization
+} // namespace boost
+
+#ifdef BOOST_MSVC  
+#  pragma warning(pop)  
+#endif
+
+#include <boost/config/abi_suffix.hpp> // pops abi_suffix.hpp pragmas
+
+#endif // BOOST_SERIALIZATION_VOID_CAST_HPP
diff --git a/SRC/Serialization/void_cast_fwd.hpp b/SRC/Serialization/void_cast_fwd.hpp
new file mode 100755
index 0000000..14260cf
--- /dev/null
+++ b/SRC/Serialization/void_cast_fwd.hpp
@@ -0,0 +1,37 @@
+#ifndef  BOOST_SERIALIZATION_VOID_CAST_FWD_HPP
+#define BOOST_SERIALIZATION_VOID_CAST_FWD_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// void_cast_fwd.hpp:   interface for run-time casting of void pointers.
+
+// (C) Copyright 2005 Robert Ramey - http://www.rrsd.com . 
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+// gennadiy.rozental at tfn.com
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <cstddef> // NULL
+#include <Serialization/force_include.hpp>
+
+namespace boost {
+namespace serialization {
+namespace void_cast_detail{
+class void_caster;
+} // namespace void_cast_detail
+template<class Derived, class Base>
+BOOST_DLLEXPORT 
+inline const void_cast_detail::void_caster & void_cast_register(
+    const Derived * dnull = NULL, 
+    const Base * bnull = NULL
+) BOOST_USED;
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_VOID_CAST_HPP
diff --git a/SRC/Serialization/weak_ptr.hpp b/SRC/Serialization/weak_ptr.hpp
new file mode 100755
index 0000000..ebaca62
--- /dev/null
+++ b/SRC/Serialization/weak_ptr.hpp
@@ -0,0 +1,58 @@
+#ifndef BOOST_SERIALIZATION_WEAK_PTR_HPP
+#define BOOST_SERIALIZATION_WEAK_PTR_HPP
+
+// MS compatible compilers support #pragma once
+#if defined(_MSC_VER) && (_MSC_VER >= 1020)
+# pragma once
+#endif
+
+/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
+// shared_ptr.hpp: serialization for boost shared pointer
+
+// (C) Copyright 2004 Robert Ramey and Martin Ecker
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org for updates, documentation, and revision history.
+
+#include <boost/weak_ptr.hpp>
+#include <Serialization/shared_ptr.hpp>
+
+namespace boost {
+namespace serialization{
+
+template<class Archive, class T>
+inline void save(
+    Archive & ar,
+    const boost::weak_ptr< T > &t,
+    const unsigned int /* file_version */
+){
+    const boost::shared_ptr< T > sp = t.lock();
+    ar << boost::serialization::make_nvp("weak_ptr", sp);
+}
+
+template<class Archive, class T>
+inline void load(
+    Archive & ar,
+    boost::weak_ptr< T > &t,
+    const unsigned int /* file_version */
+){
+    boost::shared_ptr< T > sp;
+    ar >> boost::serialization::make_nvp("weak_ptr", sp);
+    t = sp;
+}
+
+template<class Archive, class T>
+inline void serialize(
+    Archive & ar,
+    boost::weak_ptr< T > &t,
+    const unsigned int file_version
+){
+    boost::serialization::split_free(ar, t, file_version);
+}
+
+} // namespace serialization
+} // namespace boost
+
+#endif // BOOST_SERIALIZATION_WEAK_PTR_HPP
diff --git a/SRC/Serialization/wrapper.hpp b/SRC/Serialization/wrapper.hpp
new file mode 100755
index 0000000..33ce2e9
--- /dev/null
+++ b/SRC/Serialization/wrapper.hpp
@@ -0,0 +1,60 @@
+#ifndef BOOST_SERIALIZATION_WRAPPER_HPP
+#define BOOST_SERIALIZATION_WRAPPER_HPP
+
+// (C) Copyright 2005-2006 Matthias Troyer
+// Use, modification and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <Serialization/traits.hpp>
+#include <boost/type_traits/is_base_and_derived.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/bool.hpp>
+
+namespace boost { namespace serialization {
+
+/// the base class for serialization wrappers
+///
+/// wrappers need to be treated differently at various places in the serialization library,
+/// e.g. saving of non-const wrappers has to be possible. Since partial specialization
+// is not supported by all compilers, we derive all wrappers from wrapper_traits. 
+
+template<
+    class T, 
+    int Level = object_serializable, 
+    int Tracking = track_never,
+    unsigned int Version = 0,
+    class ETII = extended_type_info_impl< T >
+>
+struct wrapper_traits : 
+    public traits<T,Level,Tracking,Version,ETII,mpl::true_> 
+{};
+
+template<class T>
+struct is_wrapper_impl :
+    boost::mpl::eval_if<
+      boost::is_base_and_derived<basic_traits,T>,
+      boost::mpl::true_,
+      boost::mpl::false_
+    >::type
+{};
+
+template<class T>
+struct is_wrapper {
+    typedef BOOST_DEDUCED_TYPENAME is_wrapper_impl<const T>::type type;
+};
+
+} // serialization
+} // boost
+
+// A macro to define that a class is a wrapper
+#define BOOST_CLASS_IS_WRAPPER(T)                       \
+namespace boost {                                       \
+namespace serialization {                               \
+template<>                                              \
+struct is_wrapper_impl<const T> : boost::mpl::true_ {}; \
+}                                                       \
+}                                                       \
+/**/
+
+#endif //BOOST_SERIALIZATION_WRAPPER_HPP

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/openmeca.git



More information about the debian-science-commits mailing list